Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Tuple3 #85

Merged
merged 2 commits into from
Aug 5, 2024
Merged
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
79 changes: 79 additions & 0 deletions src/NexusMods.MnemonicDB.Abstractions/Attributes/TupleAttribute.cs
Original file line number Diff line number Diff line change
Expand Up @@ -77,3 +77,82 @@ protected override (T1LowLevel, T2LowLevel) ToLowLevel((T1HighLevel, T2HighLevel
throw new NotSupportedException("This attribute uses custom serialization, and does not support low-level conversion.");
}
}


public class TupleAttribute<T1HighLevel, T1LowLevel, T2HighLevel, T2LowLevel, T3HighLevel, T3LowLevel> :
ScalarAttribute<(T1HighLevel, T2HighLevel, T3HighLevel), (T1LowLevel, T2LowLevel, T3LowLevel)>
{
private readonly ValueTags _tag1;
private readonly ValueTags _tag2;
private readonly ValueTags _tag3;

/// <summary>
/// Creates a new tuple attribute, the value tags are used to determine the type of each elelement in the tuple.
/// </summary>
public TupleAttribute(ValueTags tag1, ValueTags tag2, ValueTags tag3, string ns, string name) : base(ValueTags.Tuple3, ns, name)
{
_tag1 = tag1;
_tag2 = tag2;
_tag3 = tag3;
}

/// <inheritdoc />
public override (T1HighLevel, T2HighLevel, T3HighLevel) ReadValue(ReadOnlySpan<byte> span, ValueTags tag, RegistryId registryId)
{
if (tag != ValueTags.Tuple3)
throw new ArgumentException($"Expected tag {ValueTags.Tuple3}, but got {tag}");

var type1 = span[0];
var type2 = span[1];
var type3 = span[2];

if (type1 != (byte)_tag1 || type2 != (byte)_tag2 || type3 != (byte)_tag3)
throw new ArgumentException($"Expected tag ({_tag1}, {_tag2}, {_tag3}), but got ({type1}, {type2}, {type3})");

var valA = ReadValue<T1LowLevel>(span.SliceFast(3), _tag1, registryId, out var sizeA);
var valB = ReadValue<T2LowLevel>(span.SliceFast(3 + sizeA), _tag2, registryId, out var sizeB);
var valC = ReadValue<T3LowLevel>(span.SliceFast(3 + sizeA + sizeB), _tag3, registryId, out _);

return FromLowLevel((valA, valB, valC));
}

/// <inheritdoc />
protected virtual (T1HighLevel, T2HighLevel, T3HighLevel) FromLowLevel((T1LowLevel, T2LowLevel, T3LowLevel) value)
{
throw new NotSupportedException("You must override this method to support low-level conversion.");
}

public override void Remap(Func<EntityId, EntityId> remapper, Span<byte> valueSpan)
{
if (_tag1 == ValueTags.Reference)
{
var entityId = MemoryMarshal.Read<EntityId>(valueSpan.SliceFast(2));
var newEntityId = remapper(entityId);
MemoryMarshal.Write(valueSpan.SliceFast(2), newEntityId);
}
else if (_tag2 == ValueTags.Reference)
{
throw new NotImplementedException();
}
}

/// <inheritdoc />
public override void WriteValue<TWriter>((T1HighLevel, T2HighLevel, T3HighLevel) value, TWriter writer)
{
var span = writer.GetSpan(3);
span[0] = (byte)_tag1;
span[1] = (byte)_tag2;
span[2] = (byte)_tag3;
writer.Advance(3);

WriteValueLowLevel(value.Item1, _tag1, writer);
WriteValueLowLevel(value.Item2, _tag2, writer);
WriteValueLowLevel(value.Item3, _tag3, writer);
}

/// <inheritdoc />
protected override (T1LowLevel, T2LowLevel, T3LowLevel) ToLowLevel((T1HighLevel, T2HighLevel, T3HighLevel) value)
{
throw new NotSupportedException("This attribute uses custom serialization, and does not support low-level conversion.");
}
}
18 changes: 18 additions & 0 deletions tests/NexusMods.MnemonicDB.TestModel/Attributes/Int3Attribute.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
using NexusMods.MnemonicDB.Abstractions;
using NexusMods.MnemonicDB.Abstractions.Attributes;
using NexusMods.MnemonicDB.Abstractions.ElementComparers;

namespace NexusMods.MnemonicDB.TestModel.Attributes;

public class Int3Attribute(string ns, string name) : TupleAttribute<int, int, int, int, int, int>(ValueTags.Int32, ValueTags.Int32, ValueTags.Int32, ns, name)
{
protected override (int, int, int) FromLowLevel((int, int, int) value)
{
return value;
}

protected override (int, int, int) ToLowLevel((int, int, int) value)
{
return value;
}
}
6 changes: 6 additions & 0 deletions tests/NexusMods.MnemonicDB.TestModel/File.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
using NexusMods.Hashing.xxHash64;
using NexusMods.MnemonicDB.Abstractions.Attributes;
using NexusMods.MnemonicDB.Abstractions.ElementComparers;
using NexusMods.MnemonicDB.Abstractions.Models;
using NexusMods.MnemonicDB.TestModel.Attributes;

Expand All @@ -17,4 +18,9 @@ public partial class File : IModelDefinition
/// A combination of the loadout
/// </summary>
public static readonly TuplePath TuplePath = new(Namespace, nameof(TuplePath)) {IsIndexed = true, IsOptional = true};

/// <summary>
/// Tuple3 test
/// </summary>
public static readonly Int3Attribute TupleTest = new(Namespace, nameof(TupleTest)) { IsIndexed = true, IsOptional = true};
}
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
+ | 0200000000000002 | (0010) Name | Mod1 - Updated | 0100000000000004
+ | 0200000000000002 | (0011) Source | http://somesite.com/Mod1 | 0100000000000003
+ | 0200000000000002 | (0012) Loadout | 0200000000000001 | 0100000000000003
+ | 0200000000000002 | (0011) Name | Mod1 - Updated | 0100000000000004
+ | 0200000000000002 | (0012) Source | http://somesite.com/Mod1 | 0100000000000003
+ | 0200000000000002 | (0013) Loadout | 0200000000000001 | 0100000000000003
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
+ | 0100000000000003 | (0008) Timestamp | DateTime : 0 | 0100000000000003
+ | 0200000000000001 | (001D) Name | Parent A | 0100000000000003
+ | 0200000000000001 | (001E) Name | Parent B | 0100000000000003
+ | 0200000000000001 | (001F) Name | Test Child | 0100000000000003
+ | 0200000000000001 | (001E) Name | Parent A | 0100000000000003
+ | 0200000000000001 | (001F) Name | Parent B | 0100000000000003
+ | 0200000000000001 | (0020) Name | Test Child | 0100000000000003
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
+ | 0100000000000003 | (0008) Timestamp | DateTime : 0 | 0100000000000003
+ | 0200000000000001 | (001D) Name | Parent A | 0100000000000003
+ | 0200000000000001 | (001E) Name | Parent B | 0100000000000003
+ | 0200000000000001 | (001F) Name | Test Child | 0100000000000003
+ | 0200000000000001 | (001E) Name | Parent A | 0100000000000003
+ | 0200000000000001 | (001F) Name | Parent B | 0100000000000003
+ | 0200000000000001 | (0020) Name | Test Child | 0100000000000003
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
+ | 0200000000000001 | (0010) Name | Test Mod | 0100000000000003
+ | 0200000000000001 | (0011) Source | http://test.com/ | 0100000000000003
+ | 0200000000000001 | (0012) Loadout | 0200000000000002 | 0100000000000003
+ | 0200000000000001 | (0011) Name | Test Mod | 0100000000000003
+ | 0200000000000001 | (0012) Source | http://test.com/ | 0100000000000003
+ | 0200000000000001 | (0013) Loadout | 0200000000000002 | 0100000000000003
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
+ | 0200000000000001 | (0010) Name | Test Mod 0 | 0100000000000004
+ | 0200000000000001 | (0011) Source | http://test.com/ | 0100000000000003
+ | 0200000000000001 | (0012) Loadout | 0200000000000002 | 0100000000000003
+ | 0200000000000001 | (0011) Name | Test Mod 0 | 0100000000000004
+ | 0200000000000001 | (0012) Source | http://test.com/ | 0100000000000003
+ | 0200000000000001 | (0013) Loadout | 0200000000000002 | 0100000000000003
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
+ | 0200000000000001 | (0010) Name | Test Mod 1 | 0100000000000005
+ | 0200000000000001 | (0011) Source | http://test.com/ | 0100000000000003
+ | 0200000000000001 | (0012) Loadout | 0200000000000002 | 0100000000000003
+ | 0200000000000001 | (0011) Name | Test Mod 1 | 0100000000000005
+ | 0200000000000001 | (0012) Source | http://test.com/ | 0100000000000003
+ | 0200000000000001 | (0013) Loadout | 0200000000000002 | 0100000000000003
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
+ | 0200000000000001 | (0010) Name | Test Mod 2 | 0100000000000006
+ | 0200000000000001 | (0011) Source | http://test.com/ | 0100000000000003
+ | 0200000000000001 | (0012) Loadout | 0200000000000002 | 0100000000000003
+ | 0200000000000001 | (0011) Name | Test Mod 2 | 0100000000000006
+ | 0200000000000001 | (0012) Source | http://test.com/ | 0100000000000003
+ | 0200000000000001 | (0013) Loadout | 0200000000000002 | 0100000000000003
Original file line number Diff line number Diff line change
Expand Up @@ -2,5 +2,5 @@
+ | 0200000000000001 | (000A) Hash | 0x00000000DEADBEF0 | 0100000000000003
+ | 0200000000000001 | (000B) Size | 1 B | 0100000000000003
+ | 0200000000000001 | (000C) Mod | 0000000000000001 | 0100000000000003
+ | 0200000000000001 | (000E) Path | C:\test.zip | 0100000000000003
+ | 0200000000000001 | (000F) Hash | 0x00000000FEEDBEEF | 0100000000000003
+ | 0200000000000001 | (000F) Path | C:\test.zip | 0100000000000003
+ | 0200000000000001 | (0010) Hash | 0x00000000FEEDBEEF | 0100000000000003
Original file line number Diff line number Diff line change
Expand Up @@ -2,5 +2,5 @@
+ | 0200000000000001 | (000A) Hash | 0x00000000DEADBEF0 | 0100000000000003
+ | 0200000000000001 | (000B) Size | 1 B | 0100000000000003
+ | 0200000000000001 | (000C) Mod | 0000000000000001 | 0100000000000003
+ | 0200000000000001 | (000E) Path | C:\test.zip | 0100000000000003
+ | 0200000000000001 | (000F) Hash | 0x00000000FEEDBEEF | 0100000000000003
+ | 0200000000000001 | (000F) Path | C:\test.zip | 0100000000000003
+ | 0200000000000001 | (0010) Hash | 0x00000000FEEDBEEF | 0100000000000003
20 changes: 20 additions & 0 deletions tests/NexusMods.MnemonicDB.Tests/DbTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -818,6 +818,26 @@ public async Task CanWriteTupleAttributes()
var avet = Connection.Db.Datoms(SliceDescriptor.Create(File.TuplePath, (EntityId.From(0), ""), (EntityId.MaxValueNoPartition, ""), Connection.Db.Registry));
await VerifyTable(avet.Resolved());
}

[Fact]
public async Task CanUseTuple3Attributes()
{
using var tx = Connection.BeginTransaction();
var fileA = new File.New(tx)
{
Path = "C:\\test.txt",
Hash = Hash.From(0xDEADBEEF),
Size = Size.From(1),
ModId = EntityId.From(0),
TupleTest = (1, 2, 3)
};

var results = await tx.Commit();

var file = results.Remap(fileA);

file.TupleTest.Should().Be((1, 2, 3));
}

[Fact]
public async Task CanGetAnalyzerData()
Expand Down
Loading