Some checks failed
CultMesh QUIC native / Build win32-x64 (push) Has been skipped
CultMesh QUIC native / Build linux-x64 (push) Has been skipped
CultMesh QUIC native / Release native binaries (push) Has been skipped
CultMesh portability and performance / ubuntu-latest reactive semantics and leases (push) Failing after 20m15s
CultMesh QUIC native / Verify committed binaries match SHA256SUMS (push) Successful in 48s
136 lines
4.5 KiB
C#
136 lines
4.5 KiB
C#
using System;
|
|
|
|
namespace GameCult.Caching
|
|
{
|
|
[AttributeUsage(AttributeTargets.Class, Inherited = false)]
|
|
public sealed class CultDocumentAttribute : Attribute
|
|
{
|
|
public CultDocumentAttribute(string schemaName, string schemaVersion)
|
|
{
|
|
SchemaName = string.IsNullOrWhiteSpace(schemaName)
|
|
? throw new ArgumentException("SchemaName must be non-empty.", nameof(schemaName))
|
|
: schemaName;
|
|
SchemaVersion = string.IsNullOrWhiteSpace(schemaVersion)
|
|
? throw new ArgumentException("SchemaVersion must be non-empty.", nameof(schemaVersion))
|
|
: schemaVersion;
|
|
}
|
|
|
|
public string SchemaName { get; }
|
|
|
|
public string SchemaVersion { get; }
|
|
|
|
/// <summary>
|
|
/// Schema ids other than this type's own that a store may hold its records under, typically the ids an earlier
|
|
/// version of the schema had. The registered catalog entry lists them, and a cache resolves a record stored under
|
|
/// one of them to this type (its own id is tried first) and restamps it to the type's own id on load. TypeScript
|
|
/// and Python name the same declaration <c>compatibleSchemaIds</c>.
|
|
/// </summary>
|
|
public string[] CompatibleSchemaIds { get; set; } = Array.Empty<string>();
|
|
}
|
|
|
|
[AttributeUsage(AttributeTargets.Class, Inherited = false)]
|
|
public sealed class CultGlobalAttribute : Attribute
|
|
{
|
|
}
|
|
|
|
[AttributeUsage(AttributeTargets.Field | AttributeTargets.Property, Inherited = true)]
|
|
public sealed class CultNameAttribute : Attribute
|
|
{
|
|
}
|
|
|
|
// A unique lookup: within one document type, a non-blank value names one record. Also filterable by CultNet selection.
|
|
[AttributeUsage(AttributeTargets.Field | AttributeTargets.Property, Inherited = true, AllowMultiple = false)]
|
|
public sealed class CultIndexAttribute : Attribute
|
|
{
|
|
public CultIndexAttribute(string? alias = null)
|
|
{
|
|
Alias = alias;
|
|
}
|
|
|
|
public string? Alias { get; }
|
|
}
|
|
|
|
// Names the member's selection and reference role (the alias, or the member name). Implies nothing about uniqueness:
|
|
// many records may hold one value, and a role member is never indexed for lookup.
|
|
[AttributeUsage(AttributeTargets.Field | AttributeTargets.Property, Inherited = true, AllowMultiple = false)]
|
|
public sealed class CultRoleAttribute : Attribute
|
|
{
|
|
public CultRoleAttribute(string? alias = null)
|
|
{
|
|
Alias = alias;
|
|
}
|
|
|
|
public string? Alias { get; }
|
|
}
|
|
|
|
[AttributeUsage(AttributeTargets.Field | AttributeTargets.Property, Inherited = true)]
|
|
public sealed class CultReferenceAttribute : Attribute
|
|
{
|
|
public CultReferenceAttribute(Type? targetType = null, bool many = false)
|
|
{
|
|
TargetType = targetType;
|
|
Many = many;
|
|
}
|
|
|
|
public Type? TargetType { get; }
|
|
|
|
public bool Many { get; }
|
|
}
|
|
|
|
public readonly struct CultRecordKey : IEquatable<CultRecordKey>
|
|
{
|
|
private readonly string? _value;
|
|
|
|
public CultRecordKey(string value)
|
|
{
|
|
_value = value;
|
|
}
|
|
|
|
// Never null: default(CultRecordKey) and new CultRecordKey("") are one empty key.
|
|
public string Value => _value ?? string.Empty;
|
|
|
|
public override string ToString() => Value;
|
|
|
|
public bool Equals(CultRecordKey other) => string.Equals(Value, other.Value, StringComparison.Ordinal);
|
|
|
|
public override bool Equals(object? obj) => obj is CultRecordKey other && Equals(other);
|
|
|
|
public override int GetHashCode() => StringComparer.Ordinal.GetHashCode(Value);
|
|
}
|
|
|
|
public readonly struct CultRecordHandle<T>
|
|
{
|
|
public CultRecordHandle(CultRecordKey key)
|
|
{
|
|
Key = key;
|
|
}
|
|
|
|
public CultRecordKey Key { get; }
|
|
|
|
public override string ToString() => Key.ToString();
|
|
}
|
|
|
|
// The key of any CultRecordRef<T>, for code that holds one without knowing T.
|
|
public interface ICultRecordRef
|
|
{
|
|
CultRecordKey Key { get; }
|
|
}
|
|
|
|
public readonly struct CultRecordRef<T> : ICultRecordRef
|
|
{
|
|
public CultRecordRef(CultRecordKey key)
|
|
{
|
|
Key = key;
|
|
}
|
|
|
|
public CultRecordKey Key { get; }
|
|
|
|
public T? Resolve(CultCache cache)
|
|
{
|
|
if (cache == null) throw new ArgumentNullException(nameof(cache));
|
|
return cache.Get(Key) is T typed ? typed : default;
|
|
}
|
|
|
|
public override string ToString() => Key.ToString();
|
|
}
|
|
}
|