Skip to content

Commit 5f4d6c0

Browse files
committed
add initial vdf code
1 parent 8495201 commit 5f4d6c0

File tree

10 files changed

+1645
-10
lines changed

10 files changed

+1645
-10
lines changed

src/AET.SteamAbstraction/AET.SteamAbstraction.Test/AET.SteamAbstraction.Test.csproj

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,6 @@
1212
</PropertyGroup>
1313

1414
<ItemGroup>
15-
<PackageReference Include="Gameloop.Vdf" Version="0.6.2" />
1615
<PackageReference Include="GitHubActionsTestLogger" Version="2.4.1">
1716
<PrivateAssets>all</PrivateAssets>
1817
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>

src/AET.SteamAbstraction/AET.SteamAbstraction.Test/SteamVdfReaderTest.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,11 +2,11 @@
22
using System.Linq;
33
using AET.SteamAbstraction.Games;
44
using AET.SteamAbstraction.Library;
5-
using Gameloop.Vdf;
65
using Microsoft.Extensions.DependencyInjection;
76
using Moq;
87
using Testably.Abstractions.Testing;
98
using Xunit;
9+
using VdfException = AET.SteamAbstraction.Vdf.VdfException;
1010

1111
namespace AET.SteamAbstraction.Test;
1212

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
using AET.SteamAbstraction.Vdf.Linq;
2+
using Xunit;
3+
4+
namespace AET.SteamAbstraction.Test.Vdf;
5+
6+
public class VObjectFacts
7+
{
8+
[Fact]
9+
public void DeepCloneWorksCorrectly()
10+
{
11+
var original = new VObject
12+
{
13+
new VProperty("key1", new VValue("value1")),
14+
};
15+
16+
var clone = original.DeepClone() as VObject;
17+
clone["key1"] = new VValue("value2");
18+
19+
Assert.True(((VValue)original["key1"]).Value.Equals("value1"));
20+
}
21+
22+
[Fact]
23+
public void DeepEqualsSucceedsCorrectly()
24+
{
25+
var obj1 = new VObject
26+
{
27+
new VProperty("key1", new VValue("value1")),
28+
new VProperty("key2", new VValue("value2")),
29+
};
30+
31+
var obj2 = new VObject
32+
{
33+
new VProperty("key1", new VValue("value1")),
34+
new VProperty("key2", new VValue("value2")),
35+
};
36+
37+
Assert.True(VToken.DeepEquals(obj1, obj2));
38+
}
39+
40+
[Fact]
41+
public void DeepEqualsFailsCorrectly()
42+
{
43+
var obj1 = new VObject
44+
{
45+
new VProperty("key1", new VValue("value1")),
46+
new VProperty("key2", new VValue("value2")),
47+
};
48+
49+
var obj2 = new VObject
50+
{
51+
new VProperty("key1", new VValue("value1")),
52+
new VProperty("key2", new VValue("value3")),
53+
};
54+
55+
Assert.False(VToken.DeepEquals(obj1, obj2));
56+
}
57+
}
Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
using AET.SteamAbstraction.Vdf.Linq;
2+
using Xunit;
3+
4+
namespace AET.SteamAbstraction.Test.Vdf;
5+
6+
public class VPropertyFacts
7+
{
8+
[Fact]
9+
public void DeepCloneWorksCorrectly()
10+
{
11+
var original = new VProperty("key1", new VObject
12+
{
13+
new VProperty("key2", new VValue("value2")),
14+
});
15+
16+
var clone = original.DeepClone() as VProperty;
17+
clone.Value = new VValue("value3");
18+
19+
Assert.True(original.Value is VObject);
20+
}
21+
22+
[Fact]
23+
public void DeepEqualsSucceedsCorrectly()
24+
{
25+
var prop1 = new VProperty("key1", new VValue("value1"));
26+
var prop2 = new VProperty("key1", new VValue("value1"));
27+
28+
Assert.True(VToken.DeepEquals(prop1, prop2));
29+
}
30+
31+
[Fact]
32+
public void DeepEqualsFailsCorrectly()
33+
{
34+
var prop1 = new VProperty("key1", new VValue("value1"));
35+
var prop2 = new VProperty("key2", new VValue("value1"));
36+
var prop3 = new VProperty("key1", new VValue("value2"));
37+
38+
Assert.False(VToken.DeepEquals(prop1, prop2));
39+
Assert.False(VToken.DeepEquals(prop1, prop3));
40+
}
41+
}
Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
using AET.SteamAbstraction.Vdf.Linq;
2+
using Xunit;
3+
4+
namespace AET.SteamAbstraction.Test.Vdf;
5+
6+
public class VValueFacts
7+
{
8+
[Fact]
9+
public void DeepCloneWorksCorrectly()
10+
{
11+
var original = new VValue("value1");
12+
13+
var clone = original.DeepClone() as VValue;
14+
clone.Value = "value2";
15+
16+
Assert.True(original.Value.Equals("value1"));
17+
}
18+
19+
[Fact]
20+
public void DeepEqualsSucceedsCorrectly()
21+
{
22+
var val1 = new VValue("value1");
23+
var val2 = new VValue("value1");
24+
25+
Assert.True(VToken.DeepEquals(val1, val2));
26+
}
27+
28+
[Fact]
29+
public void DeepEqualsFailsCorrectly()
30+
{
31+
var val1 = new VValue("value1");
32+
var val2 = new VValue("value2");
33+
34+
Assert.False(VToken.DeepEquals(val1, val2));
35+
}
36+
}
Lines changed: 209 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,209 @@
1+
using System.IO;
2+
using AET.SteamAbstraction.Vdf;
3+
using AET.SteamAbstraction.Vdf.Linq;
4+
using Xunit;
5+
6+
namespace AET.SteamAbstraction.Test.Vdf;
7+
8+
public class VdfConvertFacts
9+
{
10+
[Fact]
11+
public void EmptyStringThrowsException()
12+
{
13+
Assert.Throws<VdfException>(() => VdfConvert.Deserialize(TextReader.Null));
14+
}
15+
16+
[Fact]
17+
public void CommentsDeserializeCorrectly()
18+
{
19+
const string vdf =
20+
"""
21+
// Comment type A (at the start of the file)
22+
"root"
23+
{
24+
// Comment type B (as a child to an object)
25+
key1 "value1"
26+
"key2" // Comment type C (to the right of a property name)
27+
{
28+
"key3" "value3" // Comment type D (to the right of a property value)
29+
}
30+
}
31+
// Comment type E (at the end of the file)
32+
""";
33+
34+
using TextReader sr = new StringReader(vdf);
35+
36+
var result = VdfConvert.Deserialize(sr);
37+
38+
var expected = new VProperty("root", new VObject
39+
{
40+
VValue.CreateComment(" Comment type B (as a child to an object)"),
41+
new VProperty("key1", new VValue("value1")),
42+
new VProperty("key2", new VObject
43+
{
44+
new VProperty("key3", new VValue("value3")),
45+
VValue.CreateComment(" Comment type D (to the right of a property value)"),
46+
}),
47+
});
48+
49+
Assert.True(VToken.DeepEquals(result, expected));
50+
}
51+
52+
[Fact]
53+
public void DoubleSlashInValueDeserializesCorrectly()
54+
{
55+
const string vdf =
56+
"""
57+
"root"
58+
{
59+
"key1" "//"
60+
}
61+
""";
62+
63+
using TextReader sr = new StringReader(vdf);
64+
65+
var result = VdfConvert.Deserialize(sr);
66+
67+
var expected = new VProperty("root", new VObject
68+
{
69+
new VProperty("key1", new VValue("//")),
70+
});
71+
72+
Assert.True(VToken.DeepEquals(result, expected));
73+
}
74+
75+
[Fact]
76+
public void ObjectWithManyPropertiesDeserializesCorrectly()
77+
{
78+
const string vdf =
79+
"""
80+
"result"
81+
{
82+
"status" "1"
83+
"items_game_url" "http://media.steampowered.com/apps/440/scripts/items/items_game.140f75a4dad99e92cd86e7092b1516fff18786a6.txt"
84+
"qualities"
85+
{
86+
"Normal" "0"
87+
"rarity1" "1"
88+
"rarity2" "2"
89+
}
90+
"originNames"
91+
{
92+
"vintage" "3"
93+
"rarity3" "4"
94+
"rarity4" "5"
95+
}
96+
}
97+
""";
98+
99+
using TextReader sr = new StringReader(vdf);
100+
101+
var result = VdfConvert.Deserialize(sr);
102+
103+
var expected = new VProperty("result", new VObject
104+
{
105+
new VProperty("status", new VValue("1")),
106+
new VProperty("items_game_url", new VValue("http://media.steampowered.com/apps/440/scripts/items/items_game.140f75a4dad99e92cd86e7092b1516fff18786a6.txt")),
107+
new VProperty("qualities", new VObject
108+
{
109+
new VProperty("Normal", new VValue("0")),
110+
new VProperty("rarity1", new VValue("1")),
111+
new VProperty("rarity2", new VValue("2")),
112+
}),
113+
new VProperty("originNames", new VObject
114+
{
115+
new VProperty("vintage", new VValue("3")),
116+
new VProperty("rarity3", new VValue("4")),
117+
new VProperty("rarity4", new VValue("5")),
118+
})
119+
});
120+
121+
Assert.True(VToken.DeepEquals(result, expected));
122+
}
123+
124+
[Fact]
125+
public void ConditionalsDeserializeCorrectly()
126+
{
127+
const string vdf =
128+
"""
129+
"root"
130+
{
131+
"key1" "//" [!$WIN32&&!$OSX&&!$PS3]
132+
"key2" "some value containing [!$WIN32&&!$OSX&&!$PS3]" [$WIN32||$OSX||$PS3]
133+
"key3" "//"
134+
}
135+
""";
136+
137+
using TextReader sr = new StringReader(vdf);
138+
139+
var result = VdfConvert.Deserialize(sr);
140+
141+
var expected = new VProperty("root", new VObject
142+
{
143+
new VProperty("key1", new VValue("//"), new VConditional
144+
{
145+
new VConditional.Token(VConditional.TokenType.Not),
146+
new VConditional.Token(VConditional.TokenType.Constant, "WIN32"),
147+
new VConditional.Token(VConditional.TokenType.And),
148+
new VConditional.Token(VConditional.TokenType.Not),
149+
new VConditional.Token(VConditional.TokenType.Constant, "OSX"),
150+
new VConditional.Token(VConditional.TokenType.And),
151+
new VConditional.Token(VConditional.TokenType.Not),
152+
new VConditional.Token(VConditional.TokenType.Constant, "PS3"),
153+
}),
154+
new VProperty("key2", new VValue("some value containing [!$WIN32&&!$OSX&&!$PS3]"), new VConditional
155+
{
156+
new VConditional.Token(VConditional.TokenType.Constant, "WIN32"),
157+
new VConditional.Token(VConditional.TokenType.Or),
158+
new VConditional.Token(VConditional.TokenType.Constant, "OSX"),
159+
new VConditional.Token(VConditional.TokenType.Or),
160+
new VConditional.Token(VConditional.TokenType.Constant, "PS3"),
161+
}),
162+
new VProperty("key3", new VValue("//")),
163+
});
164+
165+
Assert.True(VToken.DeepEquals(result, expected));
166+
}
167+
168+
[Fact]
169+
public void ConditionalsEvaluateCorrectly()
170+
{
171+
const string vdf =
172+
"""
173+
"root"
174+
{
175+
"key1" "//" [!$WIN32&&!$OSX&&!$PS3]
176+
"key2" "//" [$WIN32||$OSX||$PS3]
177+
"key3" "//"
178+
"key4" "//" [$X360]
179+
}
180+
""";
181+
var settings = new VdfSerializerSettings { UsesConditionals = true, DefinedConditionals = ["X360"] };
182+
183+
using TextReader sr = new StringReader(vdf);
184+
185+
var result = VdfConvert.Deserialize(sr, settings);
186+
187+
var expected = new VProperty("root", new VObject
188+
{
189+
new VProperty("key1", new VValue("//"), new VConditional
190+
{
191+
new VConditional.Token(VConditional.TokenType.Not),
192+
new VConditional.Token(VConditional.TokenType.Constant, "WIN32"),
193+
new VConditional.Token(VConditional.TokenType.And),
194+
new VConditional.Token(VConditional.TokenType.Not),
195+
new VConditional.Token(VConditional.TokenType.Constant, "OSX"),
196+
new VConditional.Token(VConditional.TokenType.And),
197+
new VConditional.Token(VConditional.TokenType.Not),
198+
new VConditional.Token(VConditional.TokenType.Constant, "PS3"),
199+
}),
200+
new VProperty("key3", new VValue("//")),
201+
new VProperty("key4", new VValue("//"), new VConditional
202+
{
203+
new VConditional.Token(VConditional.TokenType.Constant, "X360"),
204+
}),
205+
});
206+
207+
Assert.True(VToken.DeepEquals(result, expected));
208+
}
209+
}

src/AET.SteamAbstraction/AET.SteamAbstraction/AET.SteamAbstraction.csproj

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,6 @@
3030
<PrivateAssets>all</PrivateAssets>
3131
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
3232
</PackageReference>
33-
<PackageReference Include="Gameloop.Vdf" Version="0.6.2" PrivateAssets="compile" />
3433
<PackageReference Include="System.Text.Json" Version="9.0.0" />
3534
</ItemGroup>
3635
</Project>

0 commit comments

Comments
 (0)