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

More attributes and misc improvements #113

Merged
merged 5 commits into from
Nov 13, 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
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
Loading