diff --git a/Directory.Packages.props b/Directory.Packages.props
index 5e1d7238..b7c4445f 100644
--- a/Directory.Packages.props
+++ b/Directory.Packages.props
@@ -13,7 +13,7 @@
-
+
@@ -64,4 +64,4 @@
runtime; build; native; contentfiles; analyzers; buildtransitive
-
\ No newline at end of file
+
diff --git a/src/GameFinder.StoreHandlers.Steam/Services/Parsers/AppManifestParser.cs b/src/GameFinder.StoreHandlers.Steam/Services/Parsers/AppManifestParser.cs
index ee4e630c..56fff7ce 100644
--- a/src/GameFinder.StoreHandlers.Steam/Services/Parsers/AppManifestParser.cs
+++ b/src/GameFinder.StoreHandlers.Steam/Services/Parsers/AppManifestParser.cs
@@ -56,7 +56,7 @@ public static Result ParseManifestFile(AbsolutePath manifestPath)
);
}
- if (!appState.Name.Equals("AppState", StringComparison.Ordinal))
+ if (!string.Equals(appState.Name, "AppState", StringComparison.Ordinal))
{
return Result.Fail(
new Error("Manifest file is potentially broken because the name doesn't match!")
@@ -242,21 +242,21 @@ private static Result> ParseInstall
);
}
- private static Result ParseInstalledDepot(KVObject depotObject)
+ private static Result ParseInstalledDepot(KeyValuePair depotObject)
{
- if (!uint.TryParse(depotObject.Name, NumberFormatInfo.InvariantInfo, out var rawDepotId))
+ if (!uint.TryParse(depotObject.Key, NumberFormatInfo.InvariantInfo, out var rawDepotId))
{
return Result.Fail(
new Error("Unable to parse Depot name as a 32-bit unsigned integer!")
- .WithMetadata("OriginalName", depotObject.Name)
+ .WithMetadata("OriginalName", depotObject.Key)
);
}
var depotId = DepotId.From(rawDepotId);
- var manifestIdResult = ParseRequiredChildObject(depotObject, "manifest", ParseManifestId);
- var sizeOnDiskResult = ParseRequiredChildObject(depotObject, "size", ParseSize);
- var dlcAppIdResult = ParseOptionalChildObject(depotObject, "dlcappid", ParseAppId, AppId.DefaultValue);
+ var manifestIdResult = ParseRequiredChildObject(depotObject.Value, "manifest", ParseManifestId);
+ var sizeOnDiskResult = ParseRequiredChildObject(depotObject.Value, "size", ParseSize);
+ var dlcAppIdResult = ParseOptionalChildObject(depotObject.Value, "dlcappid", ParseAppId, AppId.DefaultValue);
var mergedResults = Result.Merge(
manifestIdResult,
diff --git a/src/GameFinder.StoreHandlers.Steam/Services/Parsers/LibraryFoldersManifestParser.cs b/src/GameFinder.StoreHandlers.Steam/Services/Parsers/LibraryFoldersManifestParser.cs
index 356ce241..4a102fef 100644
--- a/src/GameFinder.StoreHandlers.Steam/Services/Parsers/LibraryFoldersManifestParser.cs
+++ b/src/GameFinder.StoreHandlers.Steam/Services/Parsers/LibraryFoldersManifestParser.cs
@@ -47,7 +47,7 @@ public static Result ParseManifestFile(AbsolutePath mani
);
}
- if (!data.Name.Equals("libraryfolders", StringComparison.Ordinal))
+ if (!string.Equals(data.Name, "libraryfolders", StringComparison.Ordinal))
{
return Result.Fail(
new Error("Manifest file is potentially broken because the name doesn't match!")
@@ -80,7 +80,7 @@ public static Result ParseManifestFile(AbsolutePath mani
private static Result> ParseLibraryFolders(KVObject data, IFileSystem fileSystem)
{
var libraryFolderResults = data.Children
- .Select(c => ParseLibraryFolder(c, fileSystem))
+ .Select(c => ParseLibraryFolder(c.Value, fileSystem))
.ToArray();
return Result.Merge(libraryFolderResults).Bind(e => Result.Ok((IReadOnlyList)e.ToList()));
diff --git a/src/GameFinder.StoreHandlers.Steam/Services/Parsers/LocalUserConfigParser.cs b/src/GameFinder.StoreHandlers.Steam/Services/Parsers/LocalUserConfigParser.cs
index 23c52375..1c19f200 100644
--- a/src/GameFinder.StoreHandlers.Steam/Services/Parsers/LocalUserConfigParser.cs
+++ b/src/GameFinder.StoreHandlers.Steam/Services/Parsers/LocalUserConfigParser.cs
@@ -49,7 +49,7 @@ public static Result ParseConfigFile(SteamId steamId, AbsoluteP
);
}
- if (!localConfigStore.Name.Equals("UserLocalConfigStore", StringComparison.Ordinal))
+ if (!string.Equals(localConfigStore.Name, "UserLocalConfigStore", StringComparison.Ordinal))
{
return Result.Fail(
new Error("Config file is potentially broken because the name doesn't match!")
@@ -125,21 +125,21 @@ private static Result> ParseLocalAppDat
);
}
- private static Result ParseSingleLocalAppData(KVObject appObject)
+ private static Result ParseSingleLocalAppData(KeyValuePair appObject)
{
- if (!uint.TryParse(appObject.Name, NumberFormatInfo.InvariantInfo, out var rawAppId))
+ if (!uint.TryParse(appObject.Key, NumberFormatInfo.InvariantInfo, out var rawAppId))
{
return Result.Fail(
new Error("Unable to parse AppId as a 32-bit unsigned integer!")
- .WithMetadata("OriginalName", appObject.Name)
+ .WithMetadata("OriginalName", appObject.Key)
);
}
var appId = AppId.From(rawAppId);
- var lastPlayedResult = ParseOptionalChildObject(appObject, "LastPlayed", ParseDateTimeOffset, DateTimeOffset.UnixEpoch);
- var playtimeResult = ParseOptionalChildObject(appObject, "Playtime", ParseUInt32, default).Map(x => TimeSpan.FromMinutes(x));
- var launchOptionsResult = ParseOptionalChildObject(appObject, "LaunchOptions", ParseString, string.Empty);
+ var lastPlayedResult = ParseOptionalChildObject(appObject.Value, "LastPlayed", ParseDateTimeOffset, DateTimeOffset.UnixEpoch);
+ var playtimeResult = ParseOptionalChildObject(appObject.Value, "Playtime", ParseUInt32, default).Map(x => TimeSpan.FromMinutes(x));
+ var launchOptionsResult = ParseOptionalChildObject(appObject.Value, "LaunchOptions", ParseString, string.Empty);
var mergedResults = Result.Merge(
lastPlayedResult,
diff --git a/src/GameFinder.StoreHandlers.Steam/Services/Parsers/ParserHelpers.cs b/src/GameFinder.StoreHandlers.Steam/Services/Parsers/ParserHelpers.cs
index a13ffe04..43216a2a 100644
--- a/src/GameFinder.StoreHandlers.Steam/Services/Parsers/ParserHelpers.cs
+++ b/src/GameFinder.StoreHandlers.Steam/Services/Parsers/ParserHelpers.cs
@@ -22,7 +22,7 @@ internal static Result> ParseBasicDictionary keyParser,
- Func valueParser,
+ Func valueParser,
IEqualityComparer? equalityComparer = null)
where TKey : notnull
{
@@ -35,9 +35,9 @@ internal static Result> ParseBasicDictionary>>(childObject =>
+ .Select, Result>>(childObject =>
{
- var keyResult = Result.Try(() => keyParser(childObject.Name));
+ var keyResult = Result.Try(() => keyParser(childObject.Key));
var valueResult = ParseValue(childObject.Value, valueParser);
var mergedResult = Result.Merge(
@@ -56,7 +56,7 @@ internal static Result> ParseBasicDictionary ParseValue(KVValue value, Func parser)
+ private static Result ParseValue(KVObject value, Func parser)
{
return Result.Try(
() => parser(value),
@@ -67,13 +67,12 @@ private static Result ParseValue(KVValue value, Func parser)
internal static Result ParseChildObjectValue(
KVObject childObject,
KVObject parentObject,
- Func parser)
+ Func parser)
{
return Result.Try(
- () => parser(childObject.Value),
+ () => parser(childObject),
ex => new ExceptionalError("Unable to parse value of child object!", ex)
- .WithMetadata("ChildObjectName", childObject.Name)
- .WithMetadata("ParentObjectName", parentObject.Name)
+ .WithMetadata("ParentObject", parentObject.ToString())
);
}
@@ -83,20 +82,20 @@ internal static Result ParseChildObjectValue(
var childObject = parentObject
.Children
- .FirstOrDefault(child => child.Name.Equals(childObjectName, StringComparison.OrdinalIgnoreCase));
+ .FirstOrDefault(child => child.Key.Equals(childObjectName, StringComparison.OrdinalIgnoreCase));
- if (childObject is null && Debugger.IsLogging())
+ if (childObject.Key is null && Debugger.IsLogging())
{
- Debugger.Log(0, Debugger.DefaultCategory, $"Optional child object {childObjectName} was not found in {parentObject.Name}");
+ Debugger.Log(0, Debugger.DefaultCategory, $"Optional child object {childObjectName} was not found.");
}
- return childObject;
+ return childObject.Key is null ? null : childObject.Value;
}
internal static Result ParseOptionalChildObject(
KVObject parentObject,
string childObjectName,
- Func parser,
+ Func parser,
T defaultValue)
{
var childObject = FindOptionalChildObject(parentObject, childObjectName);
@@ -114,7 +113,7 @@ internal static Result FindRequiredChildObject(KVObject parentObject,
return Result.Fail(
new Error("Unable to find required child object by name in parent!")
.WithMetadata("ChildObjectName", childObjectName)
- .WithMetadata("ParentObjectName", parentObject.Name)
+ .WithMetadata("ParentObject", parentObject.ToString())
);
}
@@ -124,7 +123,7 @@ internal static Result FindRequiredChildObject(KVObject parentObject,
internal static Result ParseRequiredChildObject(
KVObject parentObject,
string childObjectName,
- Func parser)
+ Func parser)
{
var childObjectResult = FindRequiredChildObject(parentObject, childObjectName);
return childObjectResult.Bind(childObject => ParseChildObjectValue(childObject, parentObject, parser));
@@ -135,9 +134,9 @@ internal static Result ParseRequiredChildObject(
#region Type Parser
[MethodImpl(MethodImplOptions.AggressiveInlining)]
- internal static byte ParseByte(KVValue value) => byte.Parse(ParseString(value), CultureInfo.InvariantCulture);
+ internal static byte ParseByte(KVObject value) => byte.Parse(ParseString(value), CultureInfo.InvariantCulture);
- internal static bool ParseBool(KVValue value)
+ internal static bool ParseBool(KVObject value)
{
var s = ParseString(value);
if (string.Equals(s, "0", StringComparison.Ordinal)) return false;
@@ -146,43 +145,43 @@ internal static bool ParseBool(KVValue value)
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
- internal static uint ParseUInt32(KVValue value) => uint.Parse(ParseString(value), CultureInfo.InvariantCulture);
+ internal static uint ParseUInt32(KVObject value) => uint.Parse(ParseString(value), CultureInfo.InvariantCulture);
[MethodImpl(MethodImplOptions.AggressiveInlining)]
- internal static ulong ParseUInt64(KVValue value) => ulong.Parse(ParseString(value), CultureInfo.InvariantCulture);
+ internal static ulong ParseUInt64(KVObject value) => ulong.Parse(ParseString(value), CultureInfo.InvariantCulture);
[MethodImpl(MethodImplOptions.AggressiveInlining)]
- internal static string ParseString(KVValue value) => value.ToString(CultureInfo.InvariantCulture);
+ internal static string ParseString(KVObject value) => value.ToString(CultureInfo.InvariantCulture);
[MethodImpl(MethodImplOptions.AggressiveInlining)]
- internal static DateTimeOffset ParseDateTimeOffset(KVValue value) => DateTimeOffset.FromUnixTimeSeconds(ParseUInt32(value));
+ internal static DateTimeOffset ParseDateTimeOffset(KVObject value) => DateTimeOffset.FromUnixTimeSeconds(ParseUInt32(value));
[MethodImpl(MethodImplOptions.AggressiveInlining)]
- internal static SteamId ParseSteamId(KVValue value) => SteamId.From(ParseUInt64(value));
+ internal static SteamId ParseSteamId(KVObject value) => SteamId.From(ParseUInt64(value));
[MethodImpl(MethodImplOptions.AggressiveInlining)]
- internal static AppId ParseAppId(KVValue value) => AppId.From(ParseUInt32(value));
+ internal static AppId ParseAppId(KVObject value) => AppId.From(ParseUInt32(value));
[MethodImpl(MethodImplOptions.AggressiveInlining)]
- internal static BuildId ParseBuildId(KVValue value) => BuildId.From(ParseUInt32(value));
+ internal static BuildId ParseBuildId(KVObject value) => BuildId.From(ParseUInt32(value));
// [MethodImpl(MethodImplOptions.AggressiveInlining)]
// internal static DepotId ParseDepotId(KVValue value) => DepotId.From(ParseUInt32(value));
[MethodImpl(MethodImplOptions.AggressiveInlining)]
- internal static ManifestId ParseManifestId(KVValue value) => ManifestId.From(ParseUInt64(value));
+ internal static ManifestId ParseManifestId(KVObject value) => ManifestId.From(ParseUInt64(value));
[MethodImpl(MethodImplOptions.AggressiveInlining)]
- internal static WorkshopManifestId ParseWorkshopManifestId(KVValue value) => WorkshopManifestId.From(ParseUInt64(value));
+ internal static WorkshopManifestId ParseWorkshopManifestId(KVObject value) => WorkshopManifestId.From(ParseUInt64(value));
[MethodImpl(MethodImplOptions.AggressiveInlining)]
- internal static Size ParseSize(KVValue value) => Size.From(ParseUInt64(value));
+ internal static Size ParseSize(KVObject value) => Size.From(ParseUInt64(value));
[MethodImpl(MethodImplOptions.AggressiveInlining)]
- internal static RelativePath ParseRelativePath(KVValue value) => ParseString(value);
+ internal static RelativePath ParseRelativePath(KVObject value) => ParseString(value);
[MethodImpl(MethodImplOptions.AggressiveInlining)]
- internal static AbsolutePath ParseAbsolutePath(KVValue value, IFileSystem fileSystem) => fileSystem.FromUnsanitizedFullPath(ParseString(value));
+ internal static AbsolutePath ParseAbsolutePath(KVObject value, IFileSystem fileSystem) => fileSystem.FromUnsanitizedFullPath(ParseString(value));
#endregion
}
diff --git a/src/GameFinder.StoreHandlers.Steam/Services/Parsers/WorkshopManifestParser.cs b/src/GameFinder.StoreHandlers.Steam/Services/Parsers/WorkshopManifestParser.cs
index 6d6bc4dc..bf849c61 100644
--- a/src/GameFinder.StoreHandlers.Steam/Services/Parsers/WorkshopManifestParser.cs
+++ b/src/GameFinder.StoreHandlers.Steam/Services/Parsers/WorkshopManifestParser.cs
@@ -47,7 +47,7 @@ public static Result ParseManifestFile(AbsolutePath manifestPa
);
}
- if (!appWorkshop.Name.Equals("AppWorkshop", StringComparison.Ordinal))
+ if (!string.Equals(appWorkshop.Name, "AppWorkshop", StringComparison.Ordinal))
{
return Result.Fail(
new Error("Manifest file is potentially broken because the name doesn't match!")
@@ -139,21 +139,21 @@ private static Result>
);
}
- private static Result ParseInstalledWorkshopItem(KVObject installedWorkshopItemObject)
+ private static Result ParseInstalledWorkshopItem(KeyValuePair installedWorkshopItemObject)
{
- if (!ulong.TryParse(installedWorkshopItemObject.Name, NumberFormatInfo.InvariantInfo, out var rawWorkshopItemId))
+ if (!ulong.TryParse(installedWorkshopItemObject.Key, NumberFormatInfo.InvariantInfo, out var rawWorkshopItemId))
{
return Result.Fail(
new Error("Unable to parse WorkshopItem name as a 64-bit unsigned integer!")
- .WithMetadata("OriginalName", installedWorkshopItemObject.Name)
+ .WithMetadata("OriginalName", installedWorkshopItemObject.Key)
);
}
var workshopItemId = WorkshopItemId.From(rawWorkshopItemId);
- var sizeOnDiskResult = ParseRequiredChildObject(installedWorkshopItemObject, "size", ParseSize);
- var lastUpdatedResult = ParseOptionalChildObject(installedWorkshopItemObject, "timeupdated", ParseDateTimeOffset, DateTimeOffset.UnixEpoch);
- var manifestResult = ParseRequiredChildObject(installedWorkshopItemObject, "manifest", ParseWorkshopManifestId);
+ var sizeOnDiskResult = ParseRequiredChildObject(installedWorkshopItemObject.Value, "size", ParseSize);
+ var lastUpdatedResult = ParseOptionalChildObject(installedWorkshopItemObject.Value, "timeupdated", ParseDateTimeOffset, DateTimeOffset.UnixEpoch);
+ var manifestResult = ParseRequiredChildObject(installedWorkshopItemObject.Value, "manifest", ParseWorkshopManifestId);
var mergedResults = Result.Merge(
sizeOnDiskResult,
@@ -175,23 +175,23 @@ private static Result ParseInstalledWorkshopItem(KVObject i
}
private static Result ParseWorkshopItemDetails(
- KVObject workshopItemDetailObject,
+ KeyValuePair workshopItemDetailObject,
IEnumerable installedWorkshopItems)
{
- if (!ulong.TryParse(workshopItemDetailObject.Name, NumberFormatInfo.InvariantInfo, out var rawWorkshopItemId))
+ if (!ulong.TryParse(workshopItemDetailObject.Key, NumberFormatInfo.InvariantInfo, out var rawWorkshopItemId))
{
return Result.Fail(
new Error("Unable to parse WorkshopItem name as a 64-bit unsigned integer!")
- .WithMetadata("OriginalName", workshopItemDetailObject.Name)
+ .WithMetadata("OriginalName", workshopItemDetailObject.Key)
);
}
var workshopItemId = WorkshopItemId.From(rawWorkshopItemId);
- var manifestResult = ParseRequiredChildObject(workshopItemDetailObject, "manifest", ParseWorkshopManifestId);
- var lastUpdatedResult = ParseOptionalChildObject(workshopItemDetailObject, "timeupdated", ParseDateTimeOffset, DateTimeOffset.UnixEpoch);
- var lastTouchedResult = ParseOptionalChildObject(workshopItemDetailObject, "timetouched", ParseDateTimeOffset, DateTimeOffset.UnixEpoch);
- var subscribedByResult = ParseOptionalChildObject(workshopItemDetailObject, "subscribedby", ParseUInt32, default).Map(x => SteamId.FromAccountId(x));
+ var manifestResult = ParseRequiredChildObject(workshopItemDetailObject.Value, "manifest", ParseWorkshopManifestId);
+ var lastUpdatedResult = ParseOptionalChildObject(workshopItemDetailObject.Value, "timeupdated", ParseDateTimeOffset, DateTimeOffset.UnixEpoch);
+ var lastTouchedResult = ParseOptionalChildObject(workshopItemDetailObject.Value, "timetouched", ParseDateTimeOffset, DateTimeOffset.UnixEpoch);
+ var subscribedByResult = ParseOptionalChildObject(workshopItemDetailObject.Value, "subscribedby", ParseUInt32, default).Map(x => SteamId.FromAccountId(x));
var mergedResults = Result.Merge(
manifestResult,
diff --git a/src/GameFinder.StoreHandlers.Steam/Services/Writers/AppManifestWriter.cs b/src/GameFinder.StoreHandlers.Steam/Services/Writers/AppManifestWriter.cs
index 18b6dcdb..23ca8e0d 100644
--- a/src/GameFinder.StoreHandlers.Steam/Services/Writers/AppManifestWriter.cs
+++ b/src/GameFinder.StoreHandlers.Steam/Services/Writers/AppManifestWriter.cs
@@ -22,7 +22,7 @@ public static class AppManifestWriter
///
public static Result Write(AppManifest manifest, AbsolutePath outputPath)
{
- var values = new List();
+ var values = KVObject.ListCollection();
values.AddValue("appid", manifest.AppId, AppId.DefaultValue);
values.AddValue("Universe", (byte)manifest.Universe, -1);
values.AddValue("name", manifest.Name, string.Empty);
@@ -46,21 +46,20 @@ public static Result Write(AppManifest manifest, AbsolutePath outputPath)
if (manifest.InstalledDepots.Count != 0)
{
- var children = new List();
+ var children = KVObject.ListCollection();
foreach (var kv in manifest.InstalledDepots)
{
var (depotId, installedDepot) = kv;
- var objValues = new List();
+ var objValues = KVObject.ListCollection();
objValues.AddValue("manifest", installedDepot.ManifestId, ManifestId.DefaultValue);
objValues.AddValue("size", installedDepot.SizeOnDisk.Value, default);
objValues.AddValue("dlcappid", installedDepot.DLCAppId, AppId.DefaultValue);
- var obj = new KVObject(depotId.ToString(), objValues);
- children.Add(obj);
+ children.Add(depotId.ToString(), objValues);
}
- values.Add(new KVObject("InstalledDepots", children));
+ values.Add("InstalledDepots", children);
}
values.AddDictionary("InstallScripts", manifest.InstallScripts, RelativePath.Empty);
@@ -68,13 +67,11 @@ public static Result Write(AppManifest manifest, AbsolutePath outputPath)
values.AddDictionary("UserConfig", manifest.UserConfig, string.Empty);
values.AddDictionary("MountedConfig", manifest.MountedConfig, string.Empty);
- var data = new KVObject("AppState", values);
-
try
{
var serializer = KVSerializer.Create(KVSerializationFormat.KeyValues1Text);
using var stream = outputPath.Open(FileMode.Create, FileAccess.ReadWrite, FileShare.None);
- serializer.Serialize(stream, data);
+ serializer.Serialize(stream, values, "AppState", KVSerializerOptions.DefaultOptions);
}
catch (Exception e)
{
diff --git a/src/GameFinder.StoreHandlers.Steam/Services/Writers/LibraryFoldersManifestWriter.cs b/src/GameFinder.StoreHandlers.Steam/Services/Writers/LibraryFoldersManifestWriter.cs
index 4c05ca37..0babf399 100644
--- a/src/GameFinder.StoreHandlers.Steam/Services/Writers/LibraryFoldersManifestWriter.cs
+++ b/src/GameFinder.StoreHandlers.Steam/Services/Writers/LibraryFoldersManifestWriter.cs
@@ -24,12 +24,12 @@ public static class LibraryFoldersManifestWriter
///
public static Result Write(LibraryFoldersManifest manifest, AbsolutePath outputPath)
{
- var values = new List();
+ var values = KVObject.ListCollection();
for (var i = 0; i < manifest.Count; i++)
{
var libraryFolder = manifest[i];
- var children = new List();
+ var children = KVObject.ListCollection();
children.AddValue("path", libraryFolder.Path.ToString(), string.Empty);
children.AddValue("label", libraryFolder.Label, string.Empty);
children.AddValue("totalsize", libraryFolder.TotalDiskSize.Value, default);
@@ -39,16 +39,14 @@ public static Result Write(LibraryFoldersManifest manifest, AbsolutePath outputP
default
);
- values.Add(new KVObject($"{i.ToString(CultureInfo.InvariantCulture)}", children));
+ values.Add(i.ToString(CultureInfo.InvariantCulture), children);
}
- var data = new KVObject("libraryfolders", values);
-
try
{
var serializer = KVSerializer.Create(KVSerializationFormat.KeyValues1Text);
using var stream = outputPath.Open(FileMode.Create, FileAccess.ReadWrite, FileShare.None);
- serializer.Serialize(stream, data);
+ serializer.Serialize(stream, values, "libraryfolders", KVSerializerOptions.DefaultOptions);
}
catch (Exception e)
{
diff --git a/src/GameFinder.StoreHandlers.Steam/Services/Writers/LocalUserConfigWriter.cs b/src/GameFinder.StoreHandlers.Steam/Services/Writers/LocalUserConfigWriter.cs
index ffa3e3ff..d598f0c0 100644
--- a/src/GameFinder.StoreHandlers.Steam/Services/Writers/LocalUserConfigWriter.cs
+++ b/src/GameFinder.StoreHandlers.Steam/Services/Writers/LocalUserConfigWriter.cs
@@ -23,46 +23,43 @@ public static class LocalUserConfigWriter
///
public static Result Write(LocalUserConfig config, AbsolutePath outputPath)
{
- var values = new List();
+ var values = KVObject.ListCollection();
var appDataObjects = config.LocalAppData.Select(x =>
{
var (appId, data) = x;
- var innerValues = new List();
+ var innerValues = KVObject.ListCollection();
innerValues.AddValue("LastPlayed", data.LastPlayed.ToUnixTimeSeconds(), default);
innerValues.AddValue("Playtime", (int)data.Playtime.TotalMinutes, default);
innerValues.AddValue("LaunchOptions", data.LaunchOptions, string.Empty);
- return new KVObject(appId.Value.ToString(CultureInfo.InvariantCulture), innerValues);
+ return new KeyValuePair(appId.Value.ToString(CultureInfo.InvariantCulture), innerValues);
});
- values.Add(new KVObject("Software", new[]
- {
- new KVObject("Valve", new []
- {
- new KVObject("Steam", new []
- {
- new KVObject("apps", appDataObjects),
- }),
- }),
- }));
+ var apps = KVObject.ListCollection(appDataObjects);
+ var steam = KVObject.ListCollection();
+ steam.Add("apps", apps);
- var systemObjects = new List();
- systemObjects.AddValue("InGameOverlayScreenshotSaveUncompressedPath", config.InGameOverlayScreenshotSaveUncompressedPath?.ToString() ?? string.Empty, string.Empty);
+ var valve = KVObject.ListCollection();
+ valve.Add("Steam", steam);
- values.Add(new KVObject("WebStorage", new[]
- {
- new KVObject("system", systemObjects),
- }));
+ var software = KVObject.ListCollection();
+ software.Add("Valve", valve);
+ values.Add("Software", software);
+
+ var systemObjects = KVObject.ListCollection();
+ systemObjects.AddValue("InGameOverlayScreenshotSaveUncompressedPath", config.InGameOverlayScreenshotSaveUncompressedPath?.ToString() ?? string.Empty, string.Empty);
- var data = new KVObject("UserLocalConfigStore", values);
+ var webStorage = KVObject.ListCollection();
+ webStorage.Add("system", systemObjects);
+ values.Add("WebStorage", webStorage);
try
{
var serializer = KVSerializer.Create(KVSerializationFormat.KeyValues1Text);
using var stream = outputPath.Open(FileMode.Create, FileAccess.ReadWrite, FileShare.None);
- serializer.Serialize(stream, data);
+ serializer.Serialize(stream, values, "UserLocalConfigStore", KVSerializerOptions.DefaultOptions);
}
catch (Exception e)
{
diff --git a/src/GameFinder.StoreHandlers.Steam/Services/Writers/WorkshopManifestWriter.cs b/src/GameFinder.StoreHandlers.Steam/Services/Writers/WorkshopManifestWriter.cs
index b3a801e8..ab5bde81 100644
--- a/src/GameFinder.StoreHandlers.Steam/Services/Writers/WorkshopManifestWriter.cs
+++ b/src/GameFinder.StoreHandlers.Steam/Services/Writers/WorkshopManifestWriter.cs
@@ -22,7 +22,7 @@ public class WorkshopManifestWriter
///
public static Result Write(WorkshopManifest manifest, AbsolutePath outputPath)
{
- var values = new List();
+ var values = KVObject.ListCollection();
values.AddValue("appid", manifest.AppId, AppId.DefaultValue);
values.AddValue("SizeOnDisk", manifest.SizeOnDisk.Value, default);
values.AddValue("NeedsUpdate", manifest.NeedsUpdate ? "1" : "0", string.Empty);
@@ -32,39 +32,37 @@ public static Result Write(WorkshopManifest manifest, AbsolutePath outputPath)
if (manifest.InstalledWorkshopItems.Count != 0)
{
- var workshopItemsInstalledChildren = new List();
- var workshopItemDetailsChildren = new List();
+ var workshopItemsInstalledChildren = KVObject.ListCollection();
+ var workshopItemDetailsChildren = KVObject.ListCollection();
foreach (var kv in manifest.InstalledWorkshopItems)
{
var (workshopItemId, workshopItemDetails) = kv;
- var workshopItemInstalledValues = new List();
+ var workshopItemInstalledValues = KVObject.ListCollection();
workshopItemInstalledValues.AddValue("size", workshopItemDetails.SizeOnDisk.Value, default);
workshopItemInstalledValues.AddValue("timeupdated", workshopItemDetails.LastUpdated.ToUnixTimeSeconds(), default);
workshopItemInstalledValues.AddValue("manifest", workshopItemDetails.ManifestId, WorkshopManifestId.DefaultValue);
- var workshopItemDetailsValues = new List();
+ var workshopItemDetailsValues = KVObject.ListCollection();
workshopItemDetailsValues.AddValue("manifest", workshopItemDetails.ManifestId, WorkshopManifestId.DefaultValue);
workshopItemDetailsValues.AddValue("timeupdated", workshopItemDetails.LastUpdated.ToUnixTimeSeconds(), default);
workshopItemDetailsValues.AddValue("timetouched", workshopItemDetails.LastTouched.ToUnixTimeSeconds(), default);
workshopItemDetailsValues.AddValue("subscribedby", workshopItemDetails.SubscribedBy.AccountId, default);
- workshopItemsInstalledChildren.Add(new KVObject(workshopItemId.ToString(), workshopItemInstalledValues));
- workshopItemDetailsChildren.Add(new KVObject(workshopItemId.ToString(), workshopItemDetailsValues));
+ workshopItemsInstalledChildren.Add(workshopItemId.ToString(), workshopItemInstalledValues);
+ workshopItemDetailsChildren.Add(workshopItemId.ToString(), workshopItemDetailsValues);
}
- values.Add(new KVObject("WorkshopItemsInstalled", workshopItemsInstalledChildren));
- values.Add(new KVObject("WorkshopItemDetails", workshopItemDetailsChildren));
+ values.Add("WorkshopItemsInstalled", workshopItemsInstalledChildren);
+ values.Add("WorkshopItemDetails", workshopItemDetailsChildren);
}
- var data = new KVObject("AppWorkshop", values);
-
try
{
var serializer = KVSerializer.Create(KVSerializationFormat.KeyValues1Text);
using var stream = outputPath.Open(FileMode.Create, FileAccess.ReadWrite, FileShare.None);
- serializer.Serialize(stream, data);
+ serializer.Serialize(stream, values, "AppWorkshop", KVSerializerOptions.DefaultOptions);
}
catch (Exception e)
{
diff --git a/src/GameFinder.StoreHandlers.Steam/Services/Writers/WriterHelpers.cs b/src/GameFinder.StoreHandlers.Steam/Services/Writers/WriterHelpers.cs
index 3ec55fd0..3d7dc974 100644
--- a/src/GameFinder.StoreHandlers.Steam/Services/Writers/WriterHelpers.cs
+++ b/src/GameFinder.StoreHandlers.Steam/Services/Writers/WriterHelpers.cs
@@ -1,70 +1,41 @@
using System;
using System.Collections.Generic;
-using System.Diagnostics.CodeAnalysis;
+using System.Globalization;
using ValveKeyValue;
namespace GameCollector.StoreHandlers.Steam.Services;
internal static class WriterHelpers
{
- internal static void AddValue(this List list, string name, TValue value, TValue defaultValue)
+ internal static void AddValue(this KVObject collection, string name, TValue value, TValue defaultValue)
where TValue : notnull
{
if (value.Equals(defaultValue)) return;
- list.Add(new KVObject(name, new StringValue(value)));
+ collection.Add(name, ConvertToString(value));
}
- internal static void AddDictionary(this List list, string name, IReadOnlyDictionary dictionary, TValue defaultValue)
+ internal static void AddDictionary(this KVObject collection, string name, IReadOnlyDictionary dictionary, TValue defaultValue)
where TKey : notnull
where TValue : notnull
{
if (dictionary.Count == 0) return;
- var children = new List();
+ var children = KVObject.ListCollection();
foreach (var kv in dictionary)
{
children.AddValue(kv.Key.ToString()!, kv.Value, defaultValue);
}
- list.Add(new KVObject(name, children));
+ collection.Add(name, children);
}
- [ExcludeFromCodeCoverage]
- private class StringValue : KVValue
+ private static string ConvertToString(TValue value)
{
- private readonly string _value;
+ if (value is null) throw new ArgumentNullException(nameof(value));
- public StringValue(string value)
- {
- _value = value;
- }
-
- public StringValue(object obj)
- {
- _value = obj.ToString() ?? throw new ArgumentException($"Doesn't have a ToString: {obj.GetType()}", nameof(obj));
- }
-
- public override string ToString() => _value;
-
- public override KVValueType ValueType => KVValueType.String;
- public override TypeCode GetTypeCode() => TypeCode.String;
-
- public override bool ToBoolean(IFormatProvider? provider) => Convert.ToBoolean(_value, provider);
- public override byte ToByte(IFormatProvider? provider) => Convert.ToByte(_value, provider);
- public override char ToChar(IFormatProvider? provider) => Convert.ToChar(_value, provider);
- public override DateTime ToDateTime(IFormatProvider? provider) => Convert.ToDateTime(_value, provider);
- public override decimal ToDecimal(IFormatProvider? provider) => Convert.ToDecimal(_value, provider);
- public override double ToDouble(IFormatProvider? provider) => Convert.ToDouble(_value, provider);
- public override short ToInt16(IFormatProvider? provider) => Convert.ToInt16(_value, provider);
- public override int ToInt32(IFormatProvider? provider) => Convert.ToInt32(_value, provider);
- public override long ToInt64(IFormatProvider? provider) => Convert.ToInt64(_value, provider);
- public override sbyte ToSByte(IFormatProvider? provider) => Convert.ToSByte(_value, provider);
- public override float ToSingle(IFormatProvider? provider) => Convert.ToSingle(_value, provider);
- public override string ToString(IFormatProvider? provider) => Convert.ToString(_value, provider);
- public override object ToType(Type conversionType, IFormatProvider? provider) => throw new NotSupportedException();
- public override ushort ToUInt16(IFormatProvider? provider) => Convert.ToUInt16(_value, provider);
- public override uint ToUInt32(IFormatProvider? provider) => Convert.ToUInt32(_value, provider);
- public override ulong ToUInt64(IFormatProvider? provider) => Convert.ToUInt64(_value, provider);
+ return value is IFormattable formattable
+ ? formattable.ToString(null, CultureInfo.InvariantCulture)
+ : value.ToString() ?? throw new ArgumentException($"Doesn't have a ToString: {typeof(TValue)}", nameof(value));
}
}
diff --git a/src/GameFinder.StoreHandlers.Steam/SteamAPI.cs b/src/GameFinder.StoreHandlers.Steam/SteamAPI.cs
index af155f33..763b41eb 100644
--- a/src/GameFinder.StoreHandlers.Steam/SteamAPI.cs
+++ b/src/GameFinder.StoreHandlers.Steam/SteamAPI.cs
@@ -148,7 +148,7 @@ private static AbsolutePath GetLoginUsersFile(AbsolutePath steamDirectory)
List<(ulong, uint, bool)> userList = new();
try
{
- KVValue autoUser = "";
+ KVObject autoUser = "";
if (!SteamLocationFinder.TryFindSteam(_fileSystem, _registry, _logger, out var steamPathResult))
{
@@ -188,7 +188,7 @@ private static AbsolutePath GetLoginUsersFile(AbsolutePath steamDirectory)
var data = kv.Deserialize(stream, KvSerializerOptions);
if (data is null) return null;
- if (!data.Name.Equals("SteamAppData", StringComparison.OrdinalIgnoreCase)) return null;
+ if (!string.Equals(data.Name, "SteamAppData", StringComparison.OrdinalIgnoreCase)) return null;
autoUser = data["AutoLoginUser"];
}
@@ -199,12 +199,12 @@ private static AbsolutePath GetLoginUsersFile(AbsolutePath steamDirectory)
var data = kv.Deserialize(stream, KvSerializerOptions);
if (data is null) return null;
- if (!data.Name.Equals("users", StringComparison.OrdinalIgnoreCase)) return null;
+ if (!string.Equals(data.Name, "users", StringComparison.OrdinalIgnoreCase)) return null;
- var users = data.Children.ToList();
+ var users = data.Root.Children.ToList();
foreach (var user in users)
{
- if (!ulong.TryParse(user.Name, out var id))
+ if (!ulong.TryParse(user.Key, out var id))
continue;
var auto = false;