From e847497c9e8ec27a8635c937e5d171041151768d Mon Sep 17 00:00:00 2001 From: erri120 Date: Wed, 13 Nov 2024 12:34:20 +0100 Subject: [PATCH] Add extension methods --- .../Attributes/Float32Attribute.cs | 17 ++++++++++++ .../Attributes/Float64Attribute.cs | 17 ++++++++++++ .../Attributes/Int128Attribute.cs | 18 +++++++++++++ .../Attributes/UInt128Attribute.cs | 18 +++++++++++++ .../EntityExtensions.cs | 27 +++++++++++++++++++ .../EntityId.cs | 26 +++++++++++++++++- 6 files changed, 122 insertions(+), 1 deletion(-) create mode 100644 src/NexusMods.MnemonicDB.Abstractions/Attributes/Float32Attribute.cs create mode 100644 src/NexusMods.MnemonicDB.Abstractions/Attributes/Float64Attribute.cs create mode 100644 src/NexusMods.MnemonicDB.Abstractions/Attributes/Int128Attribute.cs create mode 100644 src/NexusMods.MnemonicDB.Abstractions/Attributes/UInt128Attribute.cs create mode 100644 src/NexusMods.MnemonicDB.Abstractions/EntityExtensions.cs diff --git a/src/NexusMods.MnemonicDB.Abstractions/Attributes/Float32Attribute.cs b/src/NexusMods.MnemonicDB.Abstractions/Attributes/Float32Attribute.cs new file mode 100644 index 00000000..ca5798e9 --- /dev/null +++ b/src/NexusMods.MnemonicDB.Abstractions/Attributes/Float32Attribute.cs @@ -0,0 +1,17 @@ +using JetBrains.Annotations; +using NexusMods.MnemonicDB.Abstractions.ValueSerializers; + +namespace NexusMods.MnemonicDB.Abstractions.Attributes; + +/// +/// An attribute that holds a float32 value. +/// +[PublicAPI] +public sealed class Float32Attribute(string ns, string name) : ScalarAttribute(ns, name) +{ + /// + protected override float ToLowLevel(float value) => value; + + /// + protected override float FromLowLevel(float value, AttributeResolver resolver) => value; +} diff --git a/src/NexusMods.MnemonicDB.Abstractions/Attributes/Float64Attribute.cs b/src/NexusMods.MnemonicDB.Abstractions/Attributes/Float64Attribute.cs new file mode 100644 index 00000000..2c5b55ab --- /dev/null +++ b/src/NexusMods.MnemonicDB.Abstractions/Attributes/Float64Attribute.cs @@ -0,0 +1,17 @@ +using JetBrains.Annotations; +using NexusMods.MnemonicDB.Abstractions.ValueSerializers; + +namespace NexusMods.MnemonicDB.Abstractions.Attributes; + +/// +/// An attribute that holds a float64 value. +/// +[PublicAPI] +public sealed class Float64Attribute(string ns, string name) : ScalarAttribute(ns, name) +{ + /// + protected override double ToLowLevel(double value) => value; + + /// + protected override double FromLowLevel(double value, AttributeResolver resolver) => value; +} diff --git a/src/NexusMods.MnemonicDB.Abstractions/Attributes/Int128Attribute.cs b/src/NexusMods.MnemonicDB.Abstractions/Attributes/Int128Attribute.cs new file mode 100644 index 00000000..d658ed1b --- /dev/null +++ b/src/NexusMods.MnemonicDB.Abstractions/Attributes/Int128Attribute.cs @@ -0,0 +1,18 @@ +using System; +using JetBrains.Annotations; +using NexusMods.MnemonicDB.Abstractions.ValueSerializers; + +namespace NexusMods.MnemonicDB.Abstractions.Attributes; + +/// +/// An attribute that holds an int128 value. +/// +[PublicAPI] +public sealed class Int128Attribute(string ns, string name) : ScalarAttribute(ns, name) +{ + /// + protected override Int128 ToLowLevel(Int128 value) => value; + + /// + protected override Int128 FromLowLevel(Int128 value, AttributeResolver resolver) => value; +} diff --git a/src/NexusMods.MnemonicDB.Abstractions/Attributes/UInt128Attribute.cs b/src/NexusMods.MnemonicDB.Abstractions/Attributes/UInt128Attribute.cs new file mode 100644 index 00000000..510a76cb --- /dev/null +++ b/src/NexusMods.MnemonicDB.Abstractions/Attributes/UInt128Attribute.cs @@ -0,0 +1,18 @@ +using System; +using JetBrains.Annotations; +using NexusMods.MnemonicDB.Abstractions.ValueSerializers; + +namespace NexusMods.MnemonicDB.Abstractions.Attributes; + +/// +/// An attribute that holds an uint128 value. +/// +[PublicAPI] +public sealed class UInt128Attribute(string ns, string name) : ScalarAttribute(ns, name) +{ + /// + protected override UInt128 ToLowLevel(UInt128 value) => value; + + /// + protected override UInt128 FromLowLevel(UInt128 value, AttributeResolver resolver) => value; +} diff --git a/src/NexusMods.MnemonicDB.Abstractions/EntityExtensions.cs b/src/NexusMods.MnemonicDB.Abstractions/EntityExtensions.cs new file mode 100644 index 00000000..d33207e2 --- /dev/null +++ b/src/NexusMods.MnemonicDB.Abstractions/EntityExtensions.cs @@ -0,0 +1,27 @@ +using System; +using System.Linq; +using JetBrains.Annotations; +using NexusMods.MnemonicDB.Abstractions.BuiltInEntities; +using NexusMods.MnemonicDB.Abstractions.Models; + +namespace NexusMods.MnemonicDB.Abstractions; + +/// +/// Extension methods for entities. +/// +[PublicAPI] +public static class EntityExtensions +{ + /// + /// Gets the timestamp of the transaction that created the model. + /// + public static DateTimeOffset GetCreatedAt(this T model, DateTimeOffset defaultValue = default) + where T : IReadOnlyModel + { + if (model.Count == 0) return defaultValue; + var minTx = model.Min(m => m.T); + + var tx = new Transaction.ReadOnly(model.Db, EntityId.From(minTx.Value)); + return Transaction.Timestamp.Get(tx); + } +} diff --git a/src/NexusMods.MnemonicDB.Abstractions/EntityId.cs b/src/NexusMods.MnemonicDB.Abstractions/EntityId.cs index 895a37a9..4ab2d6c7 100644 --- a/src/NexusMods.MnemonicDB.Abstractions/EntityId.cs +++ b/src/NexusMods.MnemonicDB.Abstractions/EntityId.cs @@ -1,4 +1,7 @@ -using TransparentValueObjects; +using System; +using System.Globalization; +using JetBrains.Annotations; +using TransparentValueObjects; namespace NexusMods.MnemonicDB.Abstractions; @@ -6,6 +9,7 @@ namespace NexusMods.MnemonicDB.Abstractions; /// A unique identifier for an entity. /// [ValueObject] +[PublicAPI] public readonly partial struct EntityId : IAugmentWith { /// @@ -38,4 +42,24 @@ public override string ToString() { return "EId:" + Value.ToString("X"); } + + /// + /// Tries to parse a hex string as an entity ID. + /// + public static bool TryParseFromHex(ReadOnlySpan input, out EntityId id) + { + const string prefix = "EId:"; + + if (input.StartsWith(prefix)) + input = input[prefix.Length..]; + + if (ulong.TryParse(input, NumberStyles.HexNumber, CultureInfo.InvariantCulture, out var result)) + { + id = EntityId.From(result); + return true; + } + + id = default; + return false; + } }