Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions Directory.Packages.props
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
<PackageVersion Include="SHA3.Net" Version="2.0.0" />
<PackageVersion Include="SQLitePCLRaw.bundle_e_sqlite3" Version="3.0.2" />
<PackageVersion Include="System.Management" Version="10.0.7" />
<PackageVersion Include="ValveKeyValue" Version="0.13.1.398" />
<PackageVersion Include="ValveKeyValue" Version="0.70.0.499" />
<PackageVersion Include="TransparentValueObjects" Version="1.1.0" />
<PackageVersion Include="TransparentValueObjects.Abstractions" Version="1.1.0" />
</ItemGroup>
Expand Down Expand Up @@ -64,4 +64,4 @@
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageVersion>
</ItemGroup>
</Project>
</Project>
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ public static Result<AppManifest> 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!")
Expand Down Expand Up @@ -242,21 +242,21 @@ private static Result<IReadOnlyDictionary<DepotId, InstalledDepot>> ParseInstall
);
}

private static Result<InstalledDepot> ParseInstalledDepot(KVObject depotObject)
private static Result<InstalledDepot> ParseInstalledDepot(KeyValuePair<string, KVObject> 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,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ public static Result<LibraryFoldersManifest> 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!")
Expand Down Expand Up @@ -80,7 +80,7 @@ public static Result<LibraryFoldersManifest> ParseManifestFile(AbsolutePath mani
private static Result<IReadOnlyList<LibraryFolder>> 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<LibraryFolder>)e.ToList()));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ public static Result<LocalUserConfig> 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!")
Expand Down Expand Up @@ -125,21 +125,21 @@ private static Result<IReadOnlyDictionary<AppId, LocalAppData>> ParseLocalAppDat
);
}

private static Result<LocalAppData> ParseSingleLocalAppData(KVObject appObject)
private static Result<LocalAppData> ParseSingleLocalAppData(KeyValuePair<string, KVObject> 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,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ internal static Result<IReadOnlyDictionary<TKey, TValue>> ParseBasicDictionary<T
KVObject parentObject,
string dictionaryObjectName,
Func<string, TKey> keyParser,
Func<KVValue, TValue> valueParser,
Func<KVObject, TValue> valueParser,
IEqualityComparer<TKey>? equalityComparer = null)
where TKey : notnull
{
Expand All @@ -35,9 +35,9 @@ internal static Result<IReadOnlyDictionary<TKey, TValue>> ParseBasicDictionary<T
}

var dictionaryValueResults = dictionaryObject.Children
.Select<KVObject, Result<KeyValuePair<TKey, TValue>>>(childObject =>
.Select<KeyValuePair<string, KVObject>, Result<KeyValuePair<TKey, TValue>>>(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(
Expand All @@ -56,7 +56,7 @@ internal static Result<IReadOnlyDictionary<TKey, TValue>> ParseBasicDictionary<T
);
}

private static Result<T> ParseValue<T>(KVValue value, Func<KVValue, T> parser)
private static Result<T> ParseValue<T>(KVObject value, Func<KVObject, T> parser)
{
return Result.Try(
() => parser(value),
Expand All @@ -67,13 +67,12 @@ private static Result<T> ParseValue<T>(KVValue value, Func<KVValue, T> parser)
internal static Result<T> ParseChildObjectValue<T>(
KVObject childObject,
KVObject parentObject,
Func<KVValue, T> parser)
Func<KVObject, T> 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())
);
}

Expand All @@ -83,20 +82,20 @@ internal static Result<T> ParseChildObjectValue<T>(

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<T> ParseOptionalChildObject<T>(
KVObject parentObject,
string childObjectName,
Func<KVValue, T> parser,
Func<KVObject, T> parser,
T defaultValue)
{
var childObject = FindOptionalChildObject(parentObject, childObjectName);
Expand All @@ -114,7 +113,7 @@ internal static Result<KVObject> 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())
);
}

Expand All @@ -124,7 +123,7 @@ internal static Result<KVObject> FindRequiredChildObject(KVObject parentObject,
internal static Result<T> ParseRequiredChildObject<T>(
KVObject parentObject,
string childObjectName,
Func<KVValue, T> parser)
Func<KVObject, T> parser)
{
var childObjectResult = FindRequiredChildObject(parentObject, childObjectName);
return childObjectResult.Bind(childObject => ParseChildObjectValue(childObject, parentObject, parser));
Expand All @@ -135,9 +134,9 @@ internal static Result<T> ParseRequiredChildObject<T>(
#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;
Expand All @@ -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
}
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ public static Result<WorkshopManifest> 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!")
Expand Down Expand Up @@ -139,21 +139,21 @@ private static Result<IReadOnlyDictionary<WorkshopItemId, WorkshopItemDetails>>
);
}

private static Result<WorkshopItemDetails> ParseInstalledWorkshopItem(KVObject installedWorkshopItemObject)
private static Result<WorkshopItemDetails> ParseInstalledWorkshopItem(KeyValuePair<string, KVObject> 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,
Expand All @@ -175,23 +175,23 @@ private static Result<WorkshopItemDetails> ParseInstalledWorkshopItem(KVObject i
}

private static Result<WorkshopItemDetails> ParseWorkshopItemDetails(
KVObject workshopItemDetailObject,
KeyValuePair<string, KVObject> workshopItemDetailObject,
IEnumerable<WorkshopItemDetails> 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,
Expand Down
Loading