Skip to content

Commit

Permalink
Merge pull request #113 from Nexus-Mods/feat/more-attributes
Browse files Browse the repository at this point in the history
More attributes and misc improvements
  • Loading branch information
halgari authored Nov 13, 2024
2 parents f4a11ce + 8d4321f commit ea97d53
Show file tree
Hide file tree
Showing 38 changed files with 434 additions and 110 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
using JetBrains.Annotations;
using Microsoft.Extensions.DependencyInjection;
using NexusMods.MnemonicDB.Abstractions.ValueSerializers;
using NexusMods.Paths;

namespace NexusMods.MnemonicDB.Abstractions.Attributes;

/// <summary>
/// An attribute that holds an <see cref="AbsolutePath"/>.
/// </summary>
[PublicAPI]
public sealed class AbsolutePathAttribute(string ns, string name) : ScalarAttribute<AbsolutePath, string, Utf8InsensitiveSerializer>(ns, name)
{
/// <inheritdoc/>
protected override string ToLowLevel(AbsolutePath value) => value.ToString();

/// <inheritdoc/>
protected override AbsolutePath FromLowLevel(string value, AttributeResolver resolver)
{
return resolver.ServiceProvider.GetRequiredService<IFileSystem>().FromUnsanitizedFullPath(value);
}
}
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
using NexusMods.MnemonicDB.Abstractions.Models;
using JetBrains.Annotations;
using NexusMods.MnemonicDB.Abstractions.Models;
// ReSharper disable UnusedTypeParameter
#pragma warning disable CS9113 // Parameter is unread.

Expand All @@ -8,7 +9,5 @@ namespace NexusMods.MnemonicDB.Abstractions.Attributes;
/// A meta attribute the expresses a backwards reference some other
/// model has
/// </summary>
public class BackReferenceAttribute<TOtherModel>(ReferenceAttribute referenceAttribute)
where TOtherModel : IModelDefinition
{
}
[PublicAPI]
public sealed class BackReferenceAttribute<TOtherModel>(ReferenceAttribute referenceAttribute) where TOtherModel : IModelDefinition { }
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
using JetBrains.Annotations;
using NexusMods.MnemonicDB.Abstractions.ValueSerializers;

namespace NexusMods.MnemonicDB.Abstractions.Attributes;

/// <summary>
/// An attribute that holds a boolean value.
/// </summary>
[PublicAPI]
public sealed class BooleanAttribute(string ns, string name) : ScalarAttribute<bool, byte, UInt8Serializer>(ns, name)
{
/// <inheritdoc/>
protected override byte ToLowLevel(bool value) => value ? (byte)1 : (byte)0;

/// <inheritdoc/>
protected override bool FromLowLevel(byte value, AttributeResolver resolver) => value == 1;
}
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
using NexusMods.MnemonicDB.Abstractions.ElementComparers;
using JetBrains.Annotations;
using NexusMods.MnemonicDB.Abstractions.ValueSerializers;

namespace NexusMods.MnemonicDB.Abstractions.Attributes;

/// <summary>
/// Used to mark the cardinality of an attribute in the database
/// </summary>
[PublicAPI]
public sealed class CardinalityAttribute(string ns, string name) : ScalarAttribute<Cardinality, byte, UInt8Serializer>(ns, name)
{
/// <inheritdoc />
Expand Down
Original file line number Diff line number Diff line change
@@ -1,11 +1,13 @@
using NexusMods.MnemonicDB.Abstractions.IndexSegments;
using JetBrains.Annotations;
using NexusMods.MnemonicDB.Abstractions.IndexSegments;
using NexusMods.MnemonicDB.Abstractions.Models;

namespace NexusMods.MnemonicDB.Abstractions.Attributes;

/// <summary>
/// An attribute that represents a collection of values
/// </summary>
[PublicAPI]
public abstract class CollectionAttribute<TValue, TLowLevel, TSerializer>(string ns, string name)
: Attribute<TValue, TLowLevel, TSerializer>(ns, name, cardinality: Cardinality.Many)
where TSerializer : IValueSerializer<TLowLevel>
Expand Down
53 changes: 53 additions & 0 deletions src/NexusMods.MnemonicDB.Abstractions/Attributes/EnumAttribute.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
using System;
using JetBrains.Annotations;
using NexusMods.MnemonicDB.Abstractions.ValueSerializers;

namespace NexusMods.MnemonicDB.Abstractions.Attributes;

/// <summary>
/// An attribute that holds an enum value backed by an int32 value.
/// </summary>
[PublicAPI]
public sealed class EnumAttribute<T>(string ns, string name) : ScalarAttribute<T, int, Int32Serializer>(ns, name)
where T : Enum
{
/// <inheritdoc />
protected override int ToLowLevel(T value)
{
// NOTE(halgari): Looks like an allocation, but the cast to object is removed by the JIT since the type of
// T is a compile-time constant. Verified via sharpLab.io:
// https://sharplab.io/#v2:EYLgtghglgdgNAFxBAzmAPgAQEwEYCwAUJgAwAEAygBYQBOADgDITAB0ASgK4wJRgCmAbiJEA2gCkoCAOL8Y/WlADGACgQBPevwD2AMxUBZdQFEYnMAEoLAXTKYAzHexkAwgB4AKgD4yAdyoK/GQeZCBkpuZkAN5EZHHxDmSwCGQGKiEAbhAANpz8FtGx8cWYAOxkKskWKtrAAFb8SggWWblCRXEAvkTdhESJcpFGEWDRZABi2tpkALxkJHBkAEJ0s2S4ZJ2CQA=
return (int)(object)value;
}

/// <inheritdoc />
protected override T FromLowLevel(int value, AttributeResolver resolver)
{
// Same as ToLowLevel, the cast to object is removed by the JIT
return (T)(object)value;
}
}

/// <summary>
/// An attribute that holds an enum value backed by a byte value.
/// </summary>
[PublicAPI]
public sealed class EnumByteAttribute<T>(string ns, string name) : ScalarAttribute<T, byte, UInt8Serializer>(ns, name)
where T : Enum
{
/// <inheritdoc />
protected override byte ToLowLevel(T value)
{
// NOTE(halgari): Looks like an allocation, but the cast to object is removed by the JIT since the type of
// T is a compile-time constant. Verified via sharpLab.io:
// https://sharplab.io/#v2:EYLgtghglgdgNAFxBAzmAPgAQEwEYCwAUJgAwAEAygBYQBOADgDITAB0ASgK4wJRgCmAbiJEA2gCkoCAOL8Y/WlADGACgQBPevwD2AMxUBZdQFEYnMAEoLAXTKYAzHexkAwgB4AKgD4yAdyoK/GQeZCBkpuZkAN5EZHHxDmSwCGQGKiEAbhAANpz8FtGx8cWYAOxkKskWKtrAAFb8SggWWblCRXEAvkTdhESJcpFGEWDRZABi2tpkALxkJHBkAEJ0s2S4ZJ2CQA=
return (byte)(object)value;
}

/// <inheritdoc />
protected override T FromLowLevel(byte value, AttributeResolver resolver)
{
// Same as ToLowLevel, the cast to object is removed by the JIT
return (T)(object)value;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
using JetBrains.Annotations;
using NexusMods.MnemonicDB.Abstractions.ValueSerializers;

namespace NexusMods.MnemonicDB.Abstractions.Attributes;

/// <summary>
/// An attribute that holds a float32 value.
/// </summary>
[PublicAPI]
public sealed class Float32Attribute(string ns, string name) : ScalarAttribute<float, float, Float32Serializer>(ns, name)
{
/// <inheritdoc />
protected override float ToLowLevel(float value) => value;

/// <inheritdoc />
protected override float FromLowLevel(float value, AttributeResolver resolver) => value;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
using JetBrains.Annotations;
using NexusMods.MnemonicDB.Abstractions.ValueSerializers;

namespace NexusMods.MnemonicDB.Abstractions.Attributes;

/// <summary>
/// An attribute that holds a float64 value.
/// </summary>
[PublicAPI]
public sealed class Float64Attribute(string ns, string name) : ScalarAttribute<double, double, Float64Serializer>(ns, name)
{
/// <inheritdoc />
protected override double ToLowLevel(double value) => value;

/// <inheritdoc />
protected override double FromLowLevel(double value, AttributeResolver resolver) => value;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
using System;
using JetBrains.Annotations;
using NexusMods.MnemonicDB.Abstractions.ValueSerializers;

namespace NexusMods.MnemonicDB.Abstractions.Attributes;

/// <summary>
/// An attribute that holds an int128 value.
/// </summary>
[PublicAPI]
public sealed class Int128Attribute(string ns, string name) : ScalarAttribute<Int128, Int128, Int128Serializer>(ns, name)
{
/// <inheritdoc />
protected override Int128 ToLowLevel(Int128 value) => value;

/// <inheritdoc />
protected override Int128 FromLowLevel(Int128 value, AttributeResolver resolver) => value;
}
17 changes: 17 additions & 0 deletions src/NexusMods.MnemonicDB.Abstractions/Attributes/Int16Attribute.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
using JetBrains.Annotations;
using NexusMods.MnemonicDB.Abstractions.ValueSerializers;

namespace NexusMods.MnemonicDB.Abstractions.Attributes;

/// <summary>
/// An attribute that holds an int16 value.
/// </summary>
[PublicAPI]
public sealed class Int16Attribute(string ns, string name) : ScalarAttribute<short, short, Int16Serializer>(ns, name)
{
/// <inheritdoc />
protected override short ToLowLevel(short value) => value;

/// <inheritdoc />
protected override short FromLowLevel(short value, AttributeResolver resolver) => value;
}
17 changes: 17 additions & 0 deletions src/NexusMods.MnemonicDB.Abstractions/Attributes/Int32Attribute.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
using JetBrains.Annotations;
using NexusMods.MnemonicDB.Abstractions.ValueSerializers;

namespace NexusMods.MnemonicDB.Abstractions.Attributes;

/// <summary>
/// An attribute that holds an int32 value.
/// </summary>
[PublicAPI]
public sealed class Int32Attribute(string ns, string name) : ScalarAttribute<int, int, Int32Serializer>(ns, name)
{
/// <inheritdoc />
protected override int ToLowLevel(int value) => value;

/// <inheritdoc />
protected override int FromLowLevel(int value, AttributeResolver resolver) => value;
}
17 changes: 17 additions & 0 deletions src/NexusMods.MnemonicDB.Abstractions/Attributes/Int64Attribute.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
using JetBrains.Annotations;
using NexusMods.MnemonicDB.Abstractions.ValueSerializers;

namespace NexusMods.MnemonicDB.Abstractions.Attributes;

/// <summary>
/// An attribute that holds an uint64 value.
/// </summary>
[PublicAPI]
public sealed class Int64Attribute(string ns, string name) : ScalarAttribute<long, long, Int64Serializer>(ns, name)
{
/// <inheritdoc />
protected override long ToLowLevel(long value) => value;

/// <inheritdoc />
protected override long FromLowLevel(long value, AttributeResolver resolver) => value;
}
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
using NexusMods.MnemonicDB.Abstractions.ElementComparers;
using NexusMods.MnemonicDB.Abstractions.Models;
using JetBrains.Annotations;
using NexusMods.MnemonicDB.Abstractions.ElementComparers;
using NexusMods.MnemonicDB.Abstractions.ValueSerializers;

namespace NexusMods.MnemonicDB.Abstractions.Attributes;
Expand All @@ -8,29 +8,12 @@ namespace NexusMods.MnemonicDB.Abstractions.Attributes;
/// An attribute that doesn't have a value, but is used to dispatch logic or to mark an entity
/// as being of a certain type.
/// </summary>
/// <param name="ns"></param>
/// <param name="name"></param>
public class MarkerAttribute(string ns, string name) : Attribute<Null, Null, NullSerializer>(ns, name)
[PublicAPI]
public sealed class MarkerAttribute(string ns, string name) : ScalarAttribute<Null, Null, NullSerializer>(ns, name)
{
/// <inheritdoc />
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.
/// </summary>
public bool Contains(IHasIdAndIndexSegment entity)
{
var segment = entity.IndexSegment;
var dbId = entity.Db.Connection.AttributeCache.GetAttributeId(Id);
for (var i = 0; i < segment.Count; i++)
{
var datom = segment[i];
if (datom.A != dbId) continue;
return true;
}
return false;
}
}
Original file line number Diff line number Diff line change
@@ -1,11 +1,13 @@
using NexusMods.MnemonicDB.Abstractions.Models;
using JetBrains.Annotations;
using NexusMods.MnemonicDB.Abstractions.Models;
using NexusMods.MnemonicDB.Abstractions.ValueSerializers;

namespace NexusMods.MnemonicDB.Abstractions.Attributes;

/// <summary>
/// An attribute that references another entity.
/// </summary>
[PublicAPI]
public class ReferenceAttribute(string ns, string name) : ScalarAttribute<EntityId, EntityId, EntityIdSerializer>(ns, name)
{
/// <inheritdoc />
Expand All @@ -18,5 +20,6 @@ public class ReferenceAttribute(string ns, string name) : ScalarAttribute<Entity
/// <summary>
/// A typesafe reference attribute, that references entities of type T.
/// </summary>
[PublicAPI]
public sealed class ReferenceAttribute<T>(string ns, string name) : ReferenceAttribute(ns, name)
where T : IModelDefinition;
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
using NexusMods.MnemonicDB.Abstractions.ElementComparers;
using JetBrains.Annotations;
using NexusMods.MnemonicDB.Abstractions.Models;
using NexusMods.MnemonicDB.Abstractions.ValueSerializers;

Expand All @@ -7,6 +7,7 @@ namespace NexusMods.MnemonicDB.Abstractions.Attributes;
/// <summary>
/// Represents a collection of references to other entities.
/// </summary>
[PublicAPI]
public class ReferencesAttribute(string ns, string name) : CollectionAttribute<EntityId, EntityId, EntityIdSerializer>(ns, name)
{
/// <inheritdoc />
Expand All @@ -19,5 +20,6 @@ public class ReferencesAttribute(string ns, string name) : CollectionAttribute<E
/// <summary>
/// A typesafe reference attribute, that references entities of type T.
/// </summary>
[PublicAPI]
public sealed class ReferencesAttribute<T>(string ns, string name) : ReferencesAttribute(ns, name)
where T : IModelDefinition;
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
using JetBrains.Annotations;
using Microsoft.Extensions.DependencyInjection;
using NexusMods.MnemonicDB.Abstractions.ValueSerializers;
using NexusMods.Paths;

namespace NexusMods.MnemonicDB.Abstractions.Attributes;

/// <summary>
/// An attribute that holds an <see cref="RelativePath"/>.
/// </summary>
[PublicAPI]
public sealed class RelativePathAttribute(string ns, string name) : ScalarAttribute<RelativePath, string, Utf8InsensitiveSerializer>(ns, name)
{
/// <inheritdoc/>
protected override string ToLowLevel(RelativePath value) => value.ToString();

/// <inheritdoc/>
protected override RelativePath FromLowLevel(string value, AttributeResolver resolver)
{
return new RelativePath(value);
}
}
Original file line number Diff line number Diff line change
@@ -1,13 +1,14 @@
using System.Collections.Generic;
using DynamicData.Kernel;
using NexusMods.MnemonicDB.Abstractions.ElementComparers;
using JetBrains.Annotations;
using NexusMods.MnemonicDB.Abstractions.Models;

namespace NexusMods.MnemonicDB.Abstractions.Attributes;

/// <summary>
/// An attribute that represents a scalar value, where there is a 1:1 ratio between the attribute and the value.
/// </summary>
[PublicAPI]
public abstract class ScalarAttribute<TValue, TLowLevel, TSerializer>(string ns, string name) :
Attribute<TValue, TLowLevel, TSerializer>(ns, name)
where TSerializer : IValueSerializer<TLowLevel>
Expand All @@ -22,6 +23,14 @@ public bool IsOptional
init => DeclaredOptional = value;
}

/// <summary>
/// True whether the index segment contains this attribute.
/// </summary>
public bool Contains<T>(T entity) where T : IHasIdAndIndexSegment
{
return entity.IndexSegment.Contains(this);
}

/// <summary>
/// Gets the value of the attribute from the entity.
/// </summary>
Expand Down
Loading

0 comments on commit ea97d53

Please sign in to comment.