Skip to content

Commit

Permalink
Merge pull request #103 from Nexus-Mods/serializer-cleanup
Browse files Browse the repository at this point in the history
Serializer cleanup
  • Loading branch information
halgari authored Oct 14, 2024
2 parents 9d7ca56 + 57e2731 commit ae13439
Show file tree
Hide file tree
Showing 68 changed files with 736 additions and 1,275 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ public IndexSegmentABenchmarks()
for (int a = 1; a < 100; a++)
{
var prefix = new KeyPrefix(EntityId.From(42), AttributeId.From((ushort)a), TxId.From(42), false,
ValueTags.Null);
ValueTag.Null);
builder.Add(new Datom(prefix, ReadOnlyMemory<byte>.Empty));
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ public IndexSegmentEBenchmarks()
for (var a = 0; a < 20; a++)
{
builder.Add(new Datom(new KeyPrefix(EntityId.From((ulong)e), AttributeId.From((ushort)a), TxId.From((ulong)(e + a)), false,
ValueTags.Null), ReadOnlyMemory<byte>.Empty));
ValueTag.Null), ReadOnlyMemory<byte>.Empty));
}
}

Expand Down
165 changes: 33 additions & 132 deletions src/NexusMods.MnemonicDB.Abstractions/Attribute.cs
Original file line number Diff line number Diff line change
Expand Up @@ -18,15 +18,10 @@ namespace NexusMods.MnemonicDB.Abstractions;
/// Interface for a specific attribute
/// </summary>
/// <typeparam name="TValueType"></typeparam>
public abstract partial class Attribute<TValueType, TLowLevelType> : IAttribute<TValueType>
public abstract class Attribute<TValueType, TLowLevelType> : IAttribute<TValueType>
{
private const int MaxStackAlloc = 128;
private static Encoding AsciiEncoding = Encoding.ASCII;

private static Encoding Utf8Encoding = Encoding.UTF8;

protected Attribute(
ValueTags lowLevelType,
ValueTag lowLevelType,
string ns,
string name,
bool isIndexed = false,
Expand All @@ -44,116 +39,14 @@ protected Attribute(
/// Converts a high-level value to a low-level value
/// </summary>
protected abstract TLowLevelType ToLowLevel(TValueType value);

/// <summary>
/// Converts a low-level value to a high-level value
/// </summary>
protected virtual TValueType FromLowLevel(byte value, ValueTags tags, AttributeResolver resolver)
{
throw new NotSupportedException("Unsupported low-level type " + value + " on attribute " + Id);
}

/// <summary>
/// Converts a low-level value to a high-level value
/// </summary>
protected virtual TValueType FromLowLevel(ushort value, ValueTags tags, AttributeResolver resolver)
{
throw new NotSupportedException("Unsupported low-level type " + value + " on attribute " + Id);
}

/// <summary>
/// Converts a low-level value to a high-level value
/// </summary>
protected virtual TValueType FromLowLevel(uint value, ValueTags tags, AttributeResolver resolver)
{
throw new NotSupportedException("Unsupported low-level type " + value + " on attribute " + Id);
}


/// <summary>
/// Converts a low-level value to a high-level value
/// </summary>
protected virtual TValueType FromLowLevel(string value, ValueTags tag, AttributeResolver resolver)
{
throw new NotSupportedException("Unsupported low-level type " + value + " on attribute " + Id);
}

/// <summary>
/// Converts a low-level value to a high-level value
/// </summary>
protected virtual TValueType FromLowLevel(ReadOnlySpan<byte> value, ValueTags tag, AttributeResolver resolver)
{
throw new NotSupportedException("Unsupported low-level type " + tag + " on attribute " + Id);
}


/// <summary>
/// Converts a low-level value to a high-level value
/// </summary>
protected virtual TValueType FromLowLevel(ulong value, ValueTags tags, AttributeResolver resolver)
{
throw new NotSupportedException("Unsupported low-level type " + value + " on attribute " + Id);
}


/// <summary>
/// Converts a low-level value to a high-level value
/// </summary>
protected virtual TValueType FromLowLevel(UInt128 value, ValueTags tags, AttributeResolver resolver)
{
throw new NotSupportedException("Unsupported low-level type " + value + " on attribute " + Id);
}

/// <summary>
/// Converts a low-level value to a high-level value
/// </summary>
protected virtual TValueType FromLowLevel(short value, ValueTags tags, AttributeResolver resolver)
{
throw new NotSupportedException("Unsupported low-level type " + value + " on attribute " + Id);
}

/// <summary>
/// Converts a low-level value to a high-level value
/// </summary>
protected virtual TValueType FromLowLevel(int value, ValueTags tags, AttributeResolver resolver)
{
throw new NotSupportedException("Unsupported low-level type " + value + " on attribute " + Id);
}

/// <summary>
/// Converts a low-level value to a high-level value
/// </summary>
protected virtual TValueType FromLowLevel(long value, ValueTags tags, AttributeResolver resolver)
{
throw new NotSupportedException("Unsupported low-level type " + value + " on attribute " + Id);
}

/// <summary>
/// Converts a low-level value to a high-level value
/// </summary>
protected virtual TValueType FromLowLevel(Int128 value, ValueTags tags, AttributeResolver resolver)
{
throw new NotSupportedException("Unsupported low-level type " + value + " on attribute " + Id);
}

/// <summary>
/// Converts a low-level value to a high-level value
/// </summary>
protected virtual TValueType FromLowLevel(float value, ValueTags tags, AttributeResolver resolver)
{
throw new NotSupportedException("Unsupported low-level type " + value + " on attribute " + Id);
}


/// <summary>
/// Converts a low-level value to a high-level value
/// Converts a high-level value to a low-level value
/// </summary>
protected virtual TValueType FromLowLevel(double value, ValueTags tags, AttributeResolver resolver)
{
throw new NotSupportedException("Unsupported low-level type " + value + " on attribute " + Id);
}

protected abstract TValueType FromLowLevel(TLowLevelType value, AttributeResolver resolver);

/// <inheritdoc />
public ValueTags LowLevelType { get; }
public ValueTag LowLevelType { get; }

/// <inheritdoc />
public Symbol Id { get; }
Expand All @@ -174,7 +67,7 @@ protected virtual TValueType FromLowLevel(double value, ValueTags tags, Attribut
public Type ValueType => typeof(TValueType);

/// <inheritdoc />
public bool IsReference => LowLevelType == ValueTags.Reference;
public bool IsReference => LowLevelType == ValueTag.Reference;

/// <inheritdoc />
IReadDatom IAttribute.Resolve(in KeyPrefix prefix, ReadOnlySpan<byte> valueSpan, AttributeResolver resolver)
Expand All @@ -198,6 +91,27 @@ public ReadDatom Resolve(in Datom datom, AttributeResolver resolver)
var prefix = datom.Prefix;
return new ReadDatom(in prefix, ReadValue(datom.ValueSpan, datom.Prefix.ValueTag, resolver), this);
}

/// <summary>
/// Reads the high level value from the given span
/// </summary>
public TValueType ReadValue(ReadOnlySpan<byte> span, ValueTag tag, AttributeResolver resolver)
{
return FromLowLevel(tag.Read<TLowLevelType>(span), resolver);
}

/// <summary>
/// Write a datom for this attribute to the given writer
/// </summary>
public void Write<TWriter>(EntityId entityId, AttributeCache cache, TValueType value, TxId txId, bool isRetract, TWriter writer)
where TWriter : IBufferWriter<byte>
{
var prefix = new KeyPrefix(entityId, cache.GetAttributeId(Id), txId, isRetract, LowLevelType);
var span = writer.GetSpan(KeyPrefix.Size);
MemoryMarshal.Write(span, prefix);
writer.Advance(KeyPrefix.Size);
LowLevelType.Write(ToLowLevel(value), writer);
}

/// <summary>
/// Returns true if the attribute is present on the entity
Expand All @@ -216,23 +130,7 @@ public bool IsIn<T>(T entity)
{
return entity.IndexSegment.Contains(this);
}

/// <inheritdoc />
public virtual void Remap(Func<EntityId, EntityId> remapper, Span<byte> valueSpan)
{
if (LowLevelType == ValueTags.Reference)
{
var id = MemoryMarshal.Read<EntityId>(valueSpan);
var newId = remapper(id);
MemoryMarshal.Write(valueSpan, newId);
}
}

private void ThrowKeyNotFoundException(EntityId id)
{
throw new KeyNotFoundException($"Attribute {Id} not found on entity {id}");
}


/// <summary>
/// Adds a datom to the active transaction for this entity that adds the given value to this attribute
/// </summary>
Expand Down Expand Up @@ -274,6 +172,9 @@ public override string ToString()
/// </summary>
public readonly record struct ReadDatom : IReadDatom
{
/// <summary>
/// The key prefix for this datom, contains the E, A, T, IsRetract and ValueTag values for this datom
/// </summary>
public readonly KeyPrefix Prefix;

/// <summary>
Expand Down
4 changes: 2 additions & 2 deletions src/NexusMods.MnemonicDB.Abstractions/AttributeCache.cs
Original file line number Diff line number Diff line change
Expand Up @@ -64,14 +64,14 @@ public void Reset(IDb db)
_symbols = newSymbols;

var types = db.Datoms(AttributeDefinition.ValueType);
var newTypes = new ValueTags[maxIndex];
var newTypes = new ValueTag[maxIndex];
var newIsReference = new BitArray(maxIndex);
foreach (var datom in types)
{
var id = datom.E.Value;
var type = AttributeDefinition.ValueType.ReadValue(datom.ValueSpan, datom.Prefix.ValueTag, null!);
newTypes[id] = type;
newIsReference[(int)id] = type == ValueTags.Reference;
newIsReference[(int)id] = type == ValueTag.Reference;
}
_isReference = newIsReference;

Expand Down
37 changes: 0 additions & 37 deletions src/NexusMods.MnemonicDB.Abstractions/Attributes/BlobAttribute.cs

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -5,17 +5,11 @@ namespace NexusMods.MnemonicDB.Abstractions.Attributes;
/// <summary>
/// Used to mark the cardinality of an attribute in the database
/// </summary>
public class CardinalityAttribute(string ns, string name) : ScalarAttribute<Cardinality, byte>(ValueTags.UInt8, ns, name)
public sealed class CardinalityAttribute(string ns, string name) : ScalarAttribute<Cardinality, byte>(ValueTag.UInt8, ns, name)
{
/// <inheritdoc />
protected override byte ToLowLevel(Cardinality value)
{
return (byte)value;
}
protected override byte ToLowLevel(Cardinality value) => (byte)value;

/// <inheritdoc />
protected override Cardinality FromLowLevel(byte value, ValueTags tags, AttributeResolver resolver)
{
return (Cardinality)value;
}
protected override Cardinality FromLowLevel(byte value, AttributeResolver resolver) => (Cardinality)value;
}
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ namespace NexusMods.MnemonicDB.Abstractions.Attributes;
/// <summary>
/// An attribute that represents a collection of values
/// </summary>
public abstract class CollectionAttribute<TValue, TLowLevel>(ValueTags tag, string ns, string name)
public abstract class CollectionAttribute<TValue, TLowLevel>(ValueTag tag, string ns, string name)
: Attribute<TValue, TLowLevel>(tag, ns, name, cardinality: Cardinality.Many)
{

Expand Down

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -9,13 +9,13 @@ namespace NexusMods.MnemonicDB.Abstractions.Attributes;
/// </summary>
/// <param name="ns"></param>
/// <param name="name"></param>
public class MarkerAttribute(string ns, string name) : Attribute<Null, Null>(ValueTags.Null, ns, name)
public class MarkerAttribute(string ns, string name) : Attribute<Null, Null>(ValueTag.Null, ns, name)
{
/// <inheritdoc />
protected override Null ToLowLevel(Null value)
{
return value;
}
protected override Null ToLowLevel(Null value) => value;

/// <inheritdoc />
protected override Null FromLowLevel(Null value, AttributeResolver resolver) => value;

/// <summary>
/// Returns true if the entity contains the attribute.
Expand Down
Loading

0 comments on commit ae13439

Please sign in to comment.