GameCult.Thing.Contract: the gamecult.thing.* wire types for .NET, every door through a validating constructor

One C# type per Rust type, keys in the crate's slot order. Unions are abstract classes with an
internal constructor and sealed arms; unit arms are shared instances. ThingDomain owns the four
domains and ThingKeys the key grammar. CommandResult is built by four factories only; its
constructor is private. Builds against CultLib b3bd8dd5 through CultLibRoot. Tests follow in the
next commit; this one builds.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
This commit is contained in:
Meta Vens 2026-10-12 08:37:04 +02:00
commit 33eed442c7
10 changed files with 2084 additions and 0 deletions

2
.gitignore vendored
View file

@ -14,6 +14,8 @@ packages/org.gamecult.eve.surface/bin~/
packages/org.gamecult.eve.surface/obj~/
!packages/org.gamecult.eve.unity-uitoolkit/
!packages/org.gamecult.eve.unity-uitoolkit/**
!packages/GameCult.Thing.Contract/
!packages/GameCult.Thing.Contract/**
obj/
artifacts/
tools/deps/

View file

@ -0,0 +1,44 @@
using System.Collections.Generic;
using GameCult.Caching;
using MessagePack;
namespace GameCult.Thing.Contract;
[MessagePackObject]
public sealed class AssetEntry
{
[Key(0)] public string Id { get; }
[Key(1)] public string MediaType { get; }
[Key(2)] public string Uri { get; }
[Key(3)] public int Width { get; }
[Key(4)] public int Height { get; }
public AssetEntry(string id, string mediaType, string uri, int width, int height)
{
Id = id;
MediaType = mediaType;
Uri = uri;
Width = ThingDomain.Count(width);
Height = ThingDomain.Count(height);
}
}
[CultDocument("gamecult.thing.asset_catalog", "gamecult.thing.asset_catalog.v1")]
[MessagePackObject]
public sealed class AssetCatalog
{
[Key(0)] public string ProviderId { get; }
[Key(1)] public string CatalogId { get; }
[Key(2)] public long Version { get; }
[Key(3)] public List<AssetEntry> Assets { get; }
public AssetCatalog(string providerId, string catalogId, long version, List<AssetEntry> assets)
{
ProviderId = providerId;
CatalogId = ThingDomain.Segment(catalogId);
Version = ThingDomain.Version(version);
Assets = assets;
}
[IgnoreMember] public string RecordKey => ThingKeys.AssetCatalogKey(ProviderId, CatalogId);
}

View file

@ -0,0 +1,160 @@
using System.Collections.Generic;
using GameCult.Caching;
using MessagePack;
namespace GameCult.Thing.Contract;
[Union(0, typeof(CommandIdRef))]
[Union(1, typeof(CommandRefParam))]
public abstract class CommandRef
{
internal CommandRef() { }
}
[MessagePackObject]
public sealed class CommandIdRef : CommandRef
{
[Key(0)] public string Id { get; }
public CommandIdRef(string id)
{
Id = id;
}
}
[MessagePackObject]
public sealed class CommandRefParam : CommandRef
{
[Key(0)] public string Name { get; }
public CommandRefParam(string name)
{
Name = name;
}
}
[Union(0, typeof(TextValue))]
[Union(1, typeof(NumberValue))]
[Union(2, typeof(BoolValue))]
[Union(3, typeof(ChoiceValue))]
public abstract class InputValue
{
internal InputValue() { }
}
[MessagePackObject]
public sealed class TextValue : InputValue
{
[Key(0)] public string Value { get; }
public TextValue(string value)
{
Value = value;
}
}
[MessagePackObject]
public sealed class NumberValue : InputValue
{
[Key(0)] public double Value { get; }
public NumberValue(double value)
{
Value = value;
}
}
[MessagePackObject]
public sealed class BoolValue : InputValue
{
[Key(0)] public bool Value { get; }
public BoolValue(bool value)
{
Value = value;
}
}
[MessagePackObject]
public sealed class ChoiceValue : InputValue
{
[Key(0)] public string Value { get; }
public ChoiceValue(string value)
{
Value = value;
}
}
[MessagePackObject]
public sealed class CommandDecl
{
[Key(0)] public string Id { get; }
[Key(1)] public string PayloadSchema { get; }
[Key(2)] public List<string> Captures { get; }
[Key(3)] public string? Confirm { get; }
public CommandDecl(string id, string payloadSchema, List<string> captures, string? confirm)
{
Id = id;
PayloadSchema = payloadSchema;
Captures = captures;
Confirm = confirm;
}
}
[MessagePackObject]
public sealed class RecordPayload
{
[Key(0)] public string Schema { get; }
[Key(1)] public byte[] Bytes { get; }
public RecordPayload(string schema, byte[] bytes)
{
Schema = schema;
Bytes = bytes;
}
}
[MessagePackObject]
public sealed class CapturedInput
{
[Key(0)] public string Node { get; }
[Key(1)] public InputValue Value { get; }
public CapturedInput(string node, InputValue value)
{
Node = node;
Value = value;
}
}
[CultDocument("gamecult.thing.command_invocation", "gamecult.thing.command_invocation.v1")]
[MessagePackObject]
public sealed class CommandInvocation
{
[Key(0)] public string InvocationId { get; }
[Key(1)] public string SurfaceKey { get; }
[Key(2)] public long SurfaceVersion { get; }
[Key(3)] public string Command { get; }
[Key(4)] public RecordPayload Payload { get; }
[Key(5)] public List<CapturedInput> Captured { get; }
[Key(6)] public string Client { get; }
[Key(7)] public string IssuedAt { get; }
[Key(8)] public string? Delegation { get; }
public CommandInvocation(string invocationId, string surfaceKey, long surfaceVersion, string command, RecordPayload payload, List<CapturedInput> captured, string client, string issuedAt, string? delegation)
{
InvocationId = invocationId;
SurfaceKey = surfaceKey;
SurfaceVersion = ThingDomain.Version(surfaceVersion);
Command = command;
Payload = payload;
Captured = captured;
Client = client;
IssuedAt = issuedAt;
Delegation = delegation;
}
[IgnoreMember] public string RecordKey => ThingKeys.InvocationKey(InvocationId);
}

View file

@ -0,0 +1,45 @@
using System;
namespace GameCult.Thing.Contract;
/// <summary>A value was outside its domain. Names the domain and its bound, never the value.</summary>
public sealed class ThingDomainException : Exception
{
public ThingDomainException(string domain, string bound) : base($"{domain} must be {bound}")
{
Domain = domain;
Bound = bound;
}
/// <summary>The domain that refused.</summary>
public string Domain { get; }
/// <summary>The bound that was not met.</summary>
public string Bound { get; }
}
/// <summary>
/// The value domains of the contract's numbers and local names. Every constructor whose field carries a domain calls the
/// matching check, and every deserializer reaches a value through that constructor, so no door skips a check.
/// </summary>
public static class ThingDomain
{
/// <summary>A result's position in its invocation's answers, counting from 1.</summary>
public static int Seq(int value) => value >= 1 ? value : throw new ThingDomainException("Seq", "at least 1");
/// <summary>A document or source version, never negative.</summary>
public static long Version(long value) => value >= 0 ? value : throw new ThingDomainException("Version", "at least 0");
public static long? Version(long? value) => value.HasValue ? Version(value.Value) : null;
/// <summary>A count, an extent or an index, never negative.</summary>
public static int Count(int value) => value >= 0 ? value : throw new ThingDomainException("Count", "at least 0");
public static int? Count(int? value) => value.HasValue ? Count(value.Value) : null;
/// <summary>A name the contract joins into a record key: non-empty, no '.'.</summary>
public static string Segment(string value) =>
string.IsNullOrEmpty(value) ? throw new ThingDomainException("Segment", "non-empty")
: value.IndexOf('.') >= 0 ? throw new ThingDomainException("Segment", "free of '.'")
: value;
}

View file

@ -0,0 +1,22 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>netstandard2.1</TargetFramework>
<Nullable>enable</Nullable>
<LangVersion>latest</LangVersion>
<Description>The gamecult.thing.* wire types, held to the Rust crate's goldens.</Description>
<PackageId>GameCult.Thing.Contract</PackageId>
<Version>0.1.0</Version>
<Authors>GameCult</Authors>
<PackageLicenseExpression>MPL-2.0</PackageLicenseExpression>
<PackageProjectUrl>https://github.com/GameCult/Eve</PackageProjectUrl>
<RepositoryUrl>https://github.com/GameCult/Eve</RepositoryUrl>
<BaseOutputPath>obj\bin\</BaseOutputPath>
<TreatWarningsAsErrors>true</TreatWarningsAsErrors>
<NoWarn>$(NoWarn);CS1591</NoWarn>
<CultLibRoot Condition="'$(CultLibRoot)' == ''">$(MSBuildThisFileDirectory)..\..\..\CultLib</CultLibRoot>
</PropertyGroup>
<ItemGroup>
<ProjectReference Include="$(CultLibRoot)\src\GameCult.Caching\GameCult.Caching.csproj" />
</ItemGroup>
</Project>

View file

@ -0,0 +1,25 @@
using System.Globalization;
namespace GameCult.Thing.Contract;
/// <summary>
/// The record key of each kind. Each key joins free-string provider or publisher ids (dotted, as the Verse names them)
/// with typed trailing parts: a segment holds no dot and a seq or version is digits, so a key splits at its last dot
/// (surface, asset catalog, result) or last two (composition), and two different field sets never build one key.
/// </summary>
public static class ThingKeys
{
public static string SurfaceKey(string providerId, string label) =>
$"thing:surface:{providerId}.{ThingDomain.Segment(label)}";
public static string CompositionKey(string publisher, string name, long version) =>
$"thing:composition:{publisher}.{ThingDomain.Segment(name)}.v{ThingDomain.Version(version).ToString(CultureInfo.InvariantCulture)}";
public static string InvocationKey(string invocationId) => $"thing:invocation:{invocationId}";
public static string ResultKey(string invocationId, int seq) =>
$"thing:result:{invocationId}.{ThingDomain.Seq(seq).ToString(CultureInfo.InvariantCulture)}";
public static string AssetCatalogKey(string providerId, string catalogId) =>
$"thing:asset_catalog:{providerId}.{ThingDomain.Segment(catalogId)}";
}

View file

@ -0,0 +1,714 @@
using System.Collections.Generic;
using GameCult.Caching;
using MessagePack;
namespace GameCult.Thing.Contract;
[Union(0, typeof(BoxNode))]
[Union(1, typeof(TextNode))]
[Union(2, typeof(ImageNode))]
[Union(3, typeof(ButtonNode))]
[Union(4, typeof(ToggleNode))]
[Union(5, typeof(SliderNode))]
[Union(6, typeof(TextInputNode))]
[Union(7, typeof(SelectNode))]
[Union(8, typeof(RepeatNode))]
[Union(9, typeof(OverlayNode))]
[Union(10, typeof(PlotNode))]
[Union(11, typeof(EmbedNode))]
[Union(12, typeof(UseNode))]
public abstract class Node
{
internal Node() { }
}
[MessagePackObject]
public sealed class BoxNode : Node
{
[Key(0)] public NodeCommon Common { get; }
[Key(1)] public BoxStyle Style { get; }
[Key(2)] public Paint Paint { get; }
[Key(3)] public Role Role { get; }
[Key(4)] public List<Node> Children { get; }
public BoxNode(NodeCommon common, BoxStyle style, Paint paint, Role role, List<Node> children)
{
Common = common;
Style = style;
Paint = paint;
Role = role;
Children = children;
}
}
[MessagePackObject]
public sealed class TextNode : Node
{
[Key(0)] public NodeCommon Common { get; }
[Key(1)] public TextSource Content { get; }
[Key(2)] public string StyleToken { get; }
[Key(3)] public bool Wrap { get; }
[Key(4)] public int? MaxLines { get; }
[Key(5)] public bool Selectable { get; }
public TextNode(NodeCommon common, TextSource content, string styleToken, bool wrap, int? maxLines, bool selectable)
{
Common = common;
Content = content;
StyleToken = styleToken;
Wrap = wrap;
MaxLines = ThingDomain.Count(maxLines);
Selectable = selectable;
}
}
[MessagePackObject]
public sealed class ImageNode : Node
{
[Key(0)] public NodeCommon Common { get; }
[Key(1)] public string Catalog { get; }
[Key(2)] public string Asset { get; }
[Key(3)] public ImageFit Fit { get; }
[Key(4)] public TextSource Alt { get; }
public ImageNode(NodeCommon common, string catalog, string asset, ImageFit fit, TextSource alt)
{
Common = common;
Catalog = catalog;
Asset = asset;
Fit = fit;
Alt = alt;
}
}
[MessagePackObject]
public sealed class ButtonNode : Node
{
[Key(0)] public NodeCommon Common { get; }
[Key(1)] public List<Node> Content { get; }
[Key(2)] public CommandRef OnActivate { get; }
[Key(3)] public BoolSource Enabled { get; }
public ButtonNode(NodeCommon common, List<Node> content, CommandRef onActivate, BoolSource enabled)
{
Common = common;
Content = content;
OnActivate = onActivate;
Enabled = enabled;
}
}
[MessagePackObject]
public sealed class ToggleNode : Node
{
[Key(0)] public NodeCommon Common { get; }
[Key(1)] public BoolSource Checked { get; }
[Key(2)] public CommandRef OnChange { get; }
public ToggleNode(NodeCommon common, BoolSource @checked, CommandRef onChange)
{
Common = common;
Checked = @checked;
OnChange = onChange;
}
}
[MessagePackObject]
public sealed class SliderNode : Node
{
[Key(0)] public NodeCommon Common { get; }
[Key(1)] public double Min { get; }
[Key(2)] public double Max { get; }
[Key(3)] public double Step { get; }
[Key(4)] public NumberSource Value { get; }
[Key(5)] public CommandRef Commit { get; }
public SliderNode(NodeCommon common, double min, double max, double step, NumberSource value, CommandRef commit)
{
Common = common;
Min = min;
Max = max;
Step = step;
Value = value;
Commit = commit;
}
}
[MessagePackObject]
public sealed class TextInputNode : Node
{
[Key(0)] public NodeCommon Common { get; }
[Key(1)] public bool Multiline { get; }
[Key(2)] public InputKind Kind { get; }
[Key(3)] public TextSource Placeholder { get; }
[Key(4)] public TextSource Initial { get; }
[Key(5)] public CommandRef Submit { get; }
public TextInputNode(NodeCommon common, bool multiline, InputKind kind, TextSource placeholder, TextSource initial, CommandRef submit)
{
Common = common;
Multiline = multiline;
Kind = kind;
Placeholder = placeholder;
Initial = initial;
Submit = submit;
}
}
[MessagePackObject]
public sealed class SelectNode : Node
{
[Key(0)] public NodeCommon Common { get; }
[Key(1)] public OptionList Options { get; }
[Key(2)] public Bind Value { get; }
[Key(3)] public CommandRef OnChange { get; }
public SelectNode(NodeCommon common, OptionList options, Bind value, CommandRef onChange)
{
Common = common;
Options = options;
Value = value;
OnChange = onChange;
}
}
[MessagePackObject]
public sealed class RepeatNode : Node
{
[Key(0)] public NodeCommon Common { get; }
[Key(1)] public CollectionSource Collection { get; }
[Key(2)] public MemberPath KeyMember { get; }
[Key(3)] public Node Template { get; }
public RepeatNode(NodeCommon common, CollectionSource collection, MemberPath keyMember, Node template)
{
Common = common;
Collection = collection;
KeyMember = keyMember;
Template = template;
}
}
[MessagePackObject]
public sealed class OverlayNode : Node
{
[Key(0)] public NodeCommon Common { get; }
[Key(1)] public Anchor Anchor { get; }
[Key(2)] public bool Modal { get; }
[Key(3)] public CommandRef Dismiss { get; }
[Key(4)] public List<Node> Children { get; }
public OverlayNode(NodeCommon common, Anchor anchor, bool modal, CommandRef dismiss, List<Node> children)
{
Common = common;
Anchor = anchor;
Modal = modal;
Dismiss = dismiss;
Children = children;
}
}
[MessagePackObject]
public sealed class PlotNode : Node
{
[Key(0)] public NodeCommon Common { get; }
[Key(1)] public Bind Series { get; }
[Key(2)] public PlotMark Mark { get; }
[Key(3)] public double? XMin { get; }
[Key(4)] public double? XMax { get; }
[Key(5)] public double? YMin { get; }
[Key(6)] public double? YMax { get; }
public PlotNode(NodeCommon common, Bind series, PlotMark mark, double? xMin, double? xMax, double? yMin, double? yMax)
{
Common = common;
Series = series;
Mark = mark;
XMin = xMin;
XMax = xMax;
YMin = yMin;
YMax = yMax;
}
}
[MessagePackObject]
public sealed class EmbedNode : Node
{
[Key(0)] public NodeCommon Common { get; }
[Key(1)] public string SlotKind { get; }
[Key(2)] public string SlotId { get; }
[Key(3)] public double Width { get; }
[Key(4)] public double Height { get; }
public EmbedNode(NodeCommon common, string slotKind, string slotId, double width, double height)
{
Common = common;
SlotKind = slotKind;
SlotId = slotId;
Width = width;
Height = height;
}
}
[MessagePackObject]
public sealed class UseNode : Node
{
[Key(0)] public NodeCommon Common { get; }
[Key(1)] public CompositionRef Composition { get; }
[Key(2)] public List<Arg> Args { get; }
public UseNode(NodeCommon common, CompositionRef composition, List<Arg> args)
{
Common = common;
Composition = composition;
Args = args;
}
}
[Union(0, typeof(ImageFitContain))]
[Union(1, typeof(ImageFitCover))]
[Union(2, typeof(ImageFitFill))]
[Union(3, typeof(ImageFitUnscaled))]
public abstract class ImageFit
{
internal ImageFit() { }
public static ImageFit Contain => ImageFitContain.Instance;
public static ImageFit Cover => ImageFitCover.Instance;
public static ImageFit Fill => ImageFitFill.Instance;
public static ImageFit Unscaled => ImageFitUnscaled.Instance;
}
[MessagePackObject(AllowPrivate = true)]
public sealed class ImageFitContain : ImageFit
{
internal static readonly ImageFitContain Instance = new ImageFitContain();
[SerializationConstructor] private ImageFitContain() { }
}
[MessagePackObject(AllowPrivate = true)]
public sealed class ImageFitCover : ImageFit
{
internal static readonly ImageFitCover Instance = new ImageFitCover();
[SerializationConstructor] private ImageFitCover() { }
}
[MessagePackObject(AllowPrivate = true)]
public sealed class ImageFitFill : ImageFit
{
internal static readonly ImageFitFill Instance = new ImageFitFill();
[SerializationConstructor] private ImageFitFill() { }
}
[MessagePackObject(AllowPrivate = true)]
public sealed class ImageFitUnscaled : ImageFit
{
internal static readonly ImageFitUnscaled Instance = new ImageFitUnscaled();
[SerializationConstructor] private ImageFitUnscaled() { }
}
[Union(0, typeof(InputKindText))]
[Union(1, typeof(InputKindNumber))]
public abstract class InputKind
{
internal InputKind() { }
public static InputKind Text => InputKindText.Instance;
public static InputKind Number => InputKindNumber.Instance;
}
[MessagePackObject(AllowPrivate = true)]
public sealed class InputKindText : InputKind
{
internal static readonly InputKindText Instance = new InputKindText();
[SerializationConstructor] private InputKindText() { }
}
[MessagePackObject(AllowPrivate = true)]
public sealed class InputKindNumber : InputKind
{
internal static readonly InputKindNumber Instance = new InputKindNumber();
[SerializationConstructor] private InputKindNumber() { }
}
[Union(0, typeof(LiteralOptions))]
[Union(1, typeof(BoundOptions))]
public abstract class OptionList
{
internal OptionList() { }
}
[MessagePackObject]
public sealed class LiteralOptions : OptionList
{
[Key(0)] public List<SelectOption> Options { get; }
public LiteralOptions(List<SelectOption> options)
{
Options = options;
}
}
[MessagePackObject]
public sealed class BoundOptions : OptionList
{
[Key(0)] public CollectionSource Collection { get; }
[Key(1)] public MemberPath ValueMember { get; }
[Key(2)] public MemberPath LabelMember { get; }
public BoundOptions(CollectionSource collection, MemberPath valueMember, MemberPath labelMember)
{
Collection = collection;
ValueMember = valueMember;
LabelMember = labelMember;
}
}
[Union(0, typeof(AnchorViewport))]
[Union(1, typeof(AnchorNode))]
public abstract class Anchor
{
internal Anchor() { }
public static Anchor Viewport => AnchorViewport.Instance;
}
[MessagePackObject(AllowPrivate = true)]
public sealed class AnchorViewport : Anchor
{
internal static readonly AnchorViewport Instance = new AnchorViewport();
[SerializationConstructor] private AnchorViewport() { }
}
[MessagePackObject]
public sealed class AnchorNode : Anchor
{
[Key(0)] public string Node { get; }
public AnchorNode(string node)
{
Node = node;
}
}
[Union(0, typeof(PlotMarkLine))]
[Union(1, typeof(PlotMarkBar))]
[Union(2, typeof(PlotMarkArea))]
public abstract class PlotMark
{
internal PlotMark() { }
public static PlotMark Line => PlotMarkLine.Instance;
public static PlotMark Bar => PlotMarkBar.Instance;
public static PlotMark Area => PlotMarkArea.Instance;
}
[MessagePackObject(AllowPrivate = true)]
public sealed class PlotMarkLine : PlotMark
{
internal static readonly PlotMarkLine Instance = new PlotMarkLine();
[SerializationConstructor] private PlotMarkLine() { }
}
[MessagePackObject(AllowPrivate = true)]
public sealed class PlotMarkBar : PlotMark
{
internal static readonly PlotMarkBar Instance = new PlotMarkBar();
[SerializationConstructor] private PlotMarkBar() { }
}
[MessagePackObject(AllowPrivate = true)]
public sealed class PlotMarkArea : PlotMark
{
internal static readonly PlotMarkArea Instance = new PlotMarkArea();
[SerializationConstructor] private PlotMarkArea() { }
}
[Union(0, typeof(TextArg))]
[Union(1, typeof(NumberArg))]
[Union(2, typeof(BoolArg))]
[Union(3, typeof(ArgValueBind))]
[Union(4, typeof(CollectionArg))]
[Union(5, typeof(CommandArg))]
[Union(6, typeof(SlotArg))]
public abstract class ArgValue
{
internal ArgValue() { }
}
[MessagePackObject]
public sealed class TextArg : ArgValue
{
[Key(0)] public string Value { get; }
public TextArg(string value)
{
Value = value;
}
}
[MessagePackObject]
public sealed class NumberArg : ArgValue
{
[Key(0)] public double Value { get; }
public NumberArg(double value)
{
Value = value;
}
}
[MessagePackObject]
public sealed class BoolArg : ArgValue
{
[Key(0)] public bool Value { get; }
public BoolArg(bool value)
{
Value = value;
}
}
[MessagePackObject]
public sealed class ArgValueBind : ArgValue
{
[Key(0)] public StateSource Source { get; }
[Key(1)] public MemberPath Member { get; }
[Key(2)] public Format? Format { get; }
public ArgValueBind(StateSource source, MemberPath member, Format? format)
{
Source = source;
Member = member;
Format = format;
}
}
[MessagePackObject]
public sealed class CollectionArg : ArgValue
{
[Key(0)] public CollectionSource Source { get; }
public CollectionArg(CollectionSource source)
{
Source = source;
}
}
[MessagePackObject]
public sealed class CommandArg : ArgValue
{
[Key(0)] public CommandRef Command { get; }
public CommandArg(CommandRef command)
{
Command = command;
}
}
[MessagePackObject]
public sealed class SlotArg : ArgValue
{
[Key(0)] public List<Node> Nodes { get; }
public SlotArg(List<Node> nodes)
{
Nodes = nodes;
}
}
[Union(0, typeof(ParamKindText))]
[Union(1, typeof(ParamKindNumber))]
[Union(2, typeof(ParamKindBool))]
[Union(3, typeof(ParamKindBind))]
[Union(4, typeof(ParamKindCollection))]
[Union(5, typeof(ParamKindCommand))]
[Union(6, typeof(ParamKindSlot))]
public abstract class ParamKind
{
internal ParamKind() { }
public static ParamKind Text => ParamKindText.Instance;
public static ParamKind Number => ParamKindNumber.Instance;
public static ParamKind Bool => ParamKindBool.Instance;
public static ParamKind Bind => ParamKindBind.Instance;
public static ParamKind Collection => ParamKindCollection.Instance;
public static ParamKind Command => ParamKindCommand.Instance;
public static ParamKind Slot => ParamKindSlot.Instance;
}
[MessagePackObject(AllowPrivate = true)]
public sealed class ParamKindText : ParamKind
{
internal static readonly ParamKindText Instance = new ParamKindText();
[SerializationConstructor] private ParamKindText() { }
}
[MessagePackObject(AllowPrivate = true)]
public sealed class ParamKindNumber : ParamKind
{
internal static readonly ParamKindNumber Instance = new ParamKindNumber();
[SerializationConstructor] private ParamKindNumber() { }
}
[MessagePackObject(AllowPrivate = true)]
public sealed class ParamKindBool : ParamKind
{
internal static readonly ParamKindBool Instance = new ParamKindBool();
[SerializationConstructor] private ParamKindBool() { }
}
[MessagePackObject(AllowPrivate = true)]
public sealed class ParamKindBind : ParamKind
{
internal static readonly ParamKindBind Instance = new ParamKindBind();
[SerializationConstructor] private ParamKindBind() { }
}
[MessagePackObject(AllowPrivate = true)]
public sealed class ParamKindCollection : ParamKind
{
internal static readonly ParamKindCollection Instance = new ParamKindCollection();
[SerializationConstructor] private ParamKindCollection() { }
}
[MessagePackObject(AllowPrivate = true)]
public sealed class ParamKindCommand : ParamKind
{
internal static readonly ParamKindCommand Instance = new ParamKindCommand();
[SerializationConstructor] private ParamKindCommand() { }
}
[MessagePackObject(AllowPrivate = true)]
public sealed class ParamKindSlot : ParamKind
{
internal static readonly ParamKindSlot Instance = new ParamKindSlot();
[SerializationConstructor] private ParamKindSlot() { }
}
[MessagePackObject]
public sealed class NodeCommon
{
[Key(0)] public string Id { get; }
[Key(1)] public BoolSource Visible { get; }
[Key(2)] public TextSource? A11yLabel { get; }
public NodeCommon(string id, BoolSource visible, TextSource? a11yLabel)
{
Id = id;
Visible = visible;
A11yLabel = a11yLabel;
}
}
[MessagePackObject]
public sealed class SelectOption
{
[Key(0)] public string Value { get; }
[Key(1)] public string Label { get; }
public SelectOption(string value, string label)
{
Value = value;
Label = label;
}
}
[MessagePackObject]
public sealed class CompositionRef
{
[Key(0)] public string Publisher { get; }
[Key(1)] public string Name { get; }
[Key(2)] public long Version { get; }
public CompositionRef(string publisher, string name, long version)
{
Publisher = publisher;
Name = ThingDomain.Segment(name);
Version = ThingDomain.Version(version);
}
}
[MessagePackObject]
public sealed class Arg
{
[Key(0)] public string Name { get; }
[Key(1)] public ArgValue Value { get; }
public Arg(string name, ArgValue value)
{
Name = name;
Value = value;
}
}
[MessagePackObject]
public sealed class ParamDecl
{
[Key(0)] public string Name { get; }
[Key(1)] public ParamKind Kind { get; }
public ParamDecl(string name, ParamKind kind)
{
Name = name;
Kind = kind;
}
}
[CultDocument("gamecult.thing.surface", "gamecult.thing.surface.v1")]
[MessagePackObject]
public sealed class SurfaceDocument
{
[Key(0)] public string ProviderId { get; }
[Key(1)] public string Label { get; }
[Key(2)] public long Version { get; }
[Key(3)] public string Title { get; }
[Key(4)] public Node Root { get; }
[Key(5)] public List<CommandDecl> Commands { get; }
public SurfaceDocument(string providerId, string label, long version, string title, Node root, List<CommandDecl> commands)
{
ProviderId = providerId;
Label = ThingDomain.Segment(label);
Version = ThingDomain.Version(version);
Title = title;
Root = root;
Commands = commands;
}
[IgnoreMember] public string RecordKey => ThingKeys.SurfaceKey(ProviderId, Label);
}
[CultDocument("gamecult.thing.composition", "gamecult.thing.composition.v1")]
[MessagePackObject]
public sealed class CompositionDocument
{
[Key(0)] public string Publisher { get; }
[Key(1)] public string Name { get; }
[Key(2)] public long Version { get; }
[Key(3)] public List<ParamDecl> Params { get; }
[Key(4)] public Node Body { get; }
public CompositionDocument(string publisher, string name, long version, List<ParamDecl> @params, Node body)
{
Publisher = publisher;
Name = ThingDomain.Segment(name);
Version = ThingDomain.Version(version);
Params = @params;
Body = body;
}
[IgnoreMember] public string RecordKey => ThingKeys.CompositionKey(Publisher, Name, Version);
}

View file

@ -0,0 +1,132 @@
using System.Collections.Generic;
using GameCult.Caching;
using MessagePack;
namespace GameCult.Thing.Contract;
[Union(0, typeof(PendingOutcome))]
[Union(1, typeof(CompletedOutcome))]
[Union(2, typeof(DeniedOutcome))]
[Union(3, typeof(FailedOutcome))]
public abstract class Outcome
{
internal Outcome() { }
}
[MessagePackObject]
public sealed class PendingOutcome : Outcome
{
[Key(0)] public string Message { get; }
public PendingOutcome(string message)
{
Message = message;
}
}
[MessagePackObject]
public sealed class CompletedOutcome : Outcome
{
[Key(0)] public long? SourceVersion { get; }
[Key(1)] public bool ClearDrafts { get; }
[Key(2)] public Effect? Effect { get; }
public CompletedOutcome(long? sourceVersion, bool clearDrafts, Effect? effect)
{
SourceVersion = ThingDomain.Version(sourceVersion);
ClearDrafts = clearDrafts;
Effect = effect;
}
}
[MessagePackObject]
public sealed class DeniedOutcome : Outcome
{
[Key(0)] public string Reason { get; }
[Key(1)] public string? Node { get; }
public DeniedOutcome(string reason, string? node)
{
Reason = reason;
Node = node;
}
}
[MessagePackObject]
public sealed class FailedOutcome : Outcome
{
[Key(0)] public string Reason { get; }
public FailedOutcome(string reason)
{
Reason = reason;
}
}
[Union(0, typeof(OpenSurfaceEffect))]
[Union(1, typeof(OpenExternalEffect))]
public abstract class Effect
{
internal Effect() { }
}
[MessagePackObject]
public sealed class OpenSurfaceEffect : Effect
{
[Key(0)] public string Key { get; }
public OpenSurfaceEffect(string key)
{
Key = key;
}
}
[MessagePackObject]
public sealed class OpenExternalEffect : Effect
{
[Key(0)] public string Url { get; }
[Key(1)] public CommandRef Resume { get; }
public OpenExternalEffect(string url, CommandRef resume)
{
Url = url;
Resume = resume;
}
}
/// <summary>
/// A provider's answer to one invocation. Results are built by the four factories and nothing else: the constructor is
/// private (MessagePack calls it on decode, and it holds the same <see cref="ThingDomain.Seq"/> bound), and no API takes a
/// state as a string or an object payload. <c>Seq</c> counts from 1 per invocation. The copied invocation id is a
/// convenience: core binds a result to an invocation it issued, so the copy is not provenance.
/// </summary>
[CultDocument("gamecult.thing.command_result", "gamecult.thing.command_result.v1")]
[MessagePackObject(AllowPrivate = true)]
public sealed class CommandResult
{
[Key(0)] public string InvocationId { get; }
[Key(1)] public int Seq { get; }
[Key(2)] public Outcome Outcome { get; }
[SerializationConstructor]
private CommandResult(string invocationId, int seq, Outcome outcome)
{
InvocationId = invocationId;
Seq = ThingDomain.Seq(seq);
Outcome = outcome;
}
[IgnoreMember] public string RecordKey => ThingKeys.ResultKey(InvocationId, Seq);
public static CommandResult Pending(CommandInvocation invocation, int seq, string message) =>
new(invocation.InvocationId, seq, new PendingOutcome(message));
public static CommandResult Completed(CommandInvocation invocation, int seq, long? sourceVersion, bool clearDrafts, Effect? effect) =>
new(invocation.InvocationId, seq, new CompletedOutcome(sourceVersion, clearDrafts, effect));
public static CommandResult Denied(CommandInvocation invocation, int seq, string reason, string? node) =>
new(invocation.InvocationId, seq, new DeniedOutcome(reason, node));
public static CommandResult Failed(CommandInvocation invocation, int seq, string reason) =>
new(invocation.InvocationId, seq, new FailedOutcome(reason));
}

View file

@ -0,0 +1,330 @@
using System.Collections.Generic;
using GameCult.Caching;
using MessagePack;
namespace GameCult.Thing.Contract;
[Union(0, typeof(TextLiteral))]
[Union(1, typeof(TextSourceBound))]
[Union(2, typeof(TextSourceParam))]
public abstract class TextSource
{
internal TextSource() { }
}
[MessagePackObject]
public sealed class TextLiteral : TextSource
{
[Key(0)] public string Value { get; }
public TextLiteral(string value)
{
Value = value;
}
}
[MessagePackObject]
public sealed class TextSourceBound : TextSource
{
[Key(0)] public StateSource Source { get; }
[Key(1)] public MemberPath Member { get; }
[Key(2)] public Format? Format { get; }
public TextSourceBound(StateSource source, MemberPath member, Format? format)
{
Source = source;
Member = member;
Format = format;
}
}
[MessagePackObject]
public sealed class TextSourceParam : TextSource
{
[Key(0)] public string Name { get; }
public TextSourceParam(string name)
{
Name = name;
}
}
[Union(0, typeof(NumberLiteral))]
[Union(1, typeof(NumberSourceBound))]
[Union(2, typeof(NumberSourceParam))]
public abstract class NumberSource
{
internal NumberSource() { }
}
[MessagePackObject]
public sealed class NumberLiteral : NumberSource
{
[Key(0)] public double Value { get; }
public NumberLiteral(double value)
{
Value = value;
}
}
[MessagePackObject]
public sealed class NumberSourceBound : NumberSource
{
[Key(0)] public StateSource Source { get; }
[Key(1)] public MemberPath Member { get; }
[Key(2)] public Format? Format { get; }
public NumberSourceBound(StateSource source, MemberPath member, Format? format)
{
Source = source;
Member = member;
Format = format;
}
}
[MessagePackObject]
public sealed class NumberSourceParam : NumberSource
{
[Key(0)] public string Name { get; }
public NumberSourceParam(string name)
{
Name = name;
}
}
[Union(0, typeof(BoolLiteral))]
[Union(1, typeof(BoolSourceBound))]
[Union(2, typeof(BoolSourceParam))]
public abstract class BoolSource
{
internal BoolSource() { }
}
[MessagePackObject]
public sealed class BoolLiteral : BoolSource
{
[Key(0)] public bool Value { get; }
public BoolLiteral(bool value)
{
Value = value;
}
}
[MessagePackObject]
public sealed class BoolSourceBound : BoolSource
{
[Key(0)] public StateSource Source { get; }
[Key(1)] public MemberPath Member { get; }
[Key(2)] public Format? Format { get; }
public BoolSourceBound(StateSource source, MemberPath member, Format? format)
{
Source = source;
Member = member;
Format = format;
}
}
[MessagePackObject]
public sealed class BoolSourceParam : BoolSource
{
[Key(0)] public string Name { get; }
public BoolSourceParam(string name)
{
Name = name;
}
}
[Union(0, typeof(StateRef))]
[Union(1, typeof(StateSourceItem))]
public abstract class StateSource
{
internal StateSource() { }
public static StateSource Item => StateSourceItem.Instance;
}
[MessagePackObject]
public sealed class StateRef : StateSource
{
[Key(0)] public string? Provider { get; }
[Key(1)] public string Schema { get; }
[Key(2)] public string Key { get; }
public StateRef(string? provider, string schema, string key)
{
Provider = provider;
Schema = schema;
Key = key;
}
}
[MessagePackObject(AllowPrivate = true)]
public sealed class StateSourceItem : StateSource
{
internal static readonly StateSourceItem Instance = new StateSourceItem();
[SerializationConstructor] private StateSourceItem() { }
}
[Union(0, typeof(MemberName))]
[Union(1, typeof(MemberIndex))]
public abstract class MemberStep
{
internal MemberStep() { }
}
[MessagePackObject]
public sealed class MemberName : MemberStep
{
[Key(0)] public string Name { get; }
public MemberName(string name)
{
Name = name;
}
}
[MessagePackObject]
public sealed class MemberIndex : MemberStep
{
[Key(0)] public int Index { get; }
public MemberIndex(int index)
{
Index = ThingDomain.Count(index);
}
}
[Union(0, typeof(NumberFormat))]
[Union(1, typeof(FormatDuration))]
[Union(2, typeof(FormatTimestamp))]
[Union(3, typeof(AffixFormat))]
public abstract class Format
{
internal Format() { }
public static Format Duration => FormatDuration.Instance;
public static Format Timestamp => FormatTimestamp.Instance;
}
[MessagePackObject]
public sealed class NumberFormat : Format
{
[Key(0)] public int Precision { get; }
[Key(1)] public bool Percent { get; }
[Key(2)] public string? Unit { get; }
public NumberFormat(int precision, bool percent, string? unit)
{
Precision = ThingDomain.Count(precision);
Percent = percent;
Unit = unit;
}
}
[MessagePackObject(AllowPrivate = true)]
public sealed class FormatDuration : Format
{
internal static readonly FormatDuration Instance = new FormatDuration();
[SerializationConstructor] private FormatDuration() { }
}
[MessagePackObject(AllowPrivate = true)]
public sealed class FormatTimestamp : Format
{
internal static readonly FormatTimestamp Instance = new FormatTimestamp();
[SerializationConstructor] private FormatTimestamp() { }
}
[MessagePackObject]
public sealed class AffixFormat : Format
{
[Key(0)] public string Prefix { get; }
[Key(1)] public string Suffix { get; }
public AffixFormat(string prefix, string suffix)
{
Prefix = prefix;
Suffix = suffix;
}
}
[Union(0, typeof(RecordsSource))]
[Union(1, typeof(CollectionSourceMember))]
[Union(2, typeof(CollectionSourceParam))]
public abstract class CollectionSource
{
internal CollectionSource() { }
}
[MessagePackObject]
public sealed class RecordsSource : CollectionSource
{
[Key(0)] public string? Provider { get; }
[Key(1)] public string Schema { get; }
[Key(2)] public string KeyPrefix { get; }
public RecordsSource(string? provider, string schema, string keyPrefix)
{
Provider = provider;
Schema = schema;
KeyPrefix = keyPrefix;
}
}
[MessagePackObject]
public sealed class CollectionSourceMember : CollectionSource
{
[Key(0)] public StateSource Source { get; }
[Key(1)] public MemberPath Member { get; }
[Key(2)] public Format? Format { get; }
public CollectionSourceMember(StateSource source, MemberPath member, Format? format)
{
Source = source;
Member = member;
Format = format;
}
}
[MessagePackObject]
public sealed class CollectionSourceParam : CollectionSource
{
[Key(0)] public string Name { get; }
public CollectionSourceParam(string name)
{
Name = name;
}
}
[MessagePackObject]
public sealed class Bind
{
[Key(0)] public StateSource Source { get; }
[Key(1)] public MemberPath Member { get; }
[Key(2)] public Format? Format { get; }
public Bind(StateSource source, MemberPath member, Format? format)
{
Source = source;
Member = member;
Format = format;
}
}
[MessagePackObject]
public sealed class MemberPath
{
[Key(0)] public List<MemberStep> Steps { get; }
public MemberPath(List<MemberStep> steps)
{
Steps = steps;
}
}

View file

@ -0,0 +1,610 @@
using System.Collections.Generic;
using GameCult.Caching;
using MessagePack;
namespace GameCult.Thing.Contract;
[Union(0, typeof(DimensionPx))]
[Union(1, typeof(DimensionPercent))]
[Union(2, typeof(DimensionFr))]
[Union(3, typeof(DimensionAuto))]
[Union(4, typeof(DimensionContent))]
public abstract class Dimension
{
internal Dimension() { }
public static Dimension Auto => DimensionAuto.Instance;
public static Dimension Content => DimensionContent.Instance;
}
[MessagePackObject]
public sealed class DimensionPx : Dimension
{
[Key(0)] public double Value { get; }
public DimensionPx(double value)
{
Value = value;
}
}
[MessagePackObject]
public sealed class DimensionPercent : Dimension
{
[Key(0)] public double Value { get; }
public DimensionPercent(double value)
{
Value = value;
}
}
[MessagePackObject]
public sealed class DimensionFr : Dimension
{
[Key(0)] public double Value { get; }
public DimensionFr(double value)
{
Value = value;
}
}
[MessagePackObject(AllowPrivate = true)]
public sealed class DimensionAuto : Dimension
{
internal static readonly DimensionAuto Instance = new DimensionAuto();
[SerializationConstructor] private DimensionAuto() { }
}
[MessagePackObject(AllowPrivate = true)]
public sealed class DimensionContent : Dimension
{
internal static readonly DimensionContent Instance = new DimensionContent();
[SerializationConstructor] private DimensionContent() { }
}
[Union(0, typeof(DisplayFlex))]
[Union(1, typeof(DisplayGrid))]
[Union(2, typeof(DisplayBlock))]
public abstract class Display
{
internal Display() { }
public static Display Flex => DisplayFlex.Instance;
public static Display Grid => DisplayGrid.Instance;
public static Display Block => DisplayBlock.Instance;
}
[MessagePackObject(AllowPrivate = true)]
public sealed class DisplayFlex : Display
{
internal static readonly DisplayFlex Instance = new DisplayFlex();
[SerializationConstructor] private DisplayFlex() { }
}
[MessagePackObject(AllowPrivate = true)]
public sealed class DisplayGrid : Display
{
internal static readonly DisplayGrid Instance = new DisplayGrid();
[SerializationConstructor] private DisplayGrid() { }
}
[MessagePackObject(AllowPrivate = true)]
public sealed class DisplayBlock : Display
{
internal static readonly DisplayBlock Instance = new DisplayBlock();
[SerializationConstructor] private DisplayBlock() { }
}
[Union(0, typeof(DirectionRow))]
[Union(1, typeof(DirectionColumn))]
[Union(2, typeof(DirectionRowReverse))]
[Union(3, typeof(DirectionColumnReverse))]
public abstract class Direction
{
internal Direction() { }
public static Direction Row => DirectionRow.Instance;
public static Direction Column => DirectionColumn.Instance;
public static Direction RowReverse => DirectionRowReverse.Instance;
public static Direction ColumnReverse => DirectionColumnReverse.Instance;
}
[MessagePackObject(AllowPrivate = true)]
public sealed class DirectionRow : Direction
{
internal static readonly DirectionRow Instance = new DirectionRow();
[SerializationConstructor] private DirectionRow() { }
}
[MessagePackObject(AllowPrivate = true)]
public sealed class DirectionColumn : Direction
{
internal static readonly DirectionColumn Instance = new DirectionColumn();
[SerializationConstructor] private DirectionColumn() { }
}
[MessagePackObject(AllowPrivate = true)]
public sealed class DirectionRowReverse : Direction
{
internal static readonly DirectionRowReverse Instance = new DirectionRowReverse();
[SerializationConstructor] private DirectionRowReverse() { }
}
[MessagePackObject(AllowPrivate = true)]
public sealed class DirectionColumnReverse : Direction
{
internal static readonly DirectionColumnReverse Instance = new DirectionColumnReverse();
[SerializationConstructor] private DirectionColumnReverse() { }
}
[Union(0, typeof(WrapNoWrap))]
[Union(1, typeof(WrapWrap))]
[Union(2, typeof(WrapWrapReverse))]
public abstract class Wrap
{
internal Wrap() { }
public static Wrap NoWrap => WrapNoWrap.Instance;
public static Wrap Wrapped => WrapWrap.Instance;
public static Wrap WrapReverse => WrapWrapReverse.Instance;
}
[MessagePackObject(AllowPrivate = true)]
public sealed class WrapNoWrap : Wrap
{
internal static readonly WrapNoWrap Instance = new WrapNoWrap();
[SerializationConstructor] private WrapNoWrap() { }
}
[MessagePackObject(AllowPrivate = true)]
public sealed class WrapWrap : Wrap
{
internal static readonly WrapWrap Instance = new WrapWrap();
[SerializationConstructor] private WrapWrap() { }
}
[MessagePackObject(AllowPrivate = true)]
public sealed class WrapWrapReverse : Wrap
{
internal static readonly WrapWrapReverse Instance = new WrapWrapReverse();
[SerializationConstructor] private WrapWrapReverse() { }
}
[Union(0, typeof(PositionRelative))]
[Union(1, typeof(PositionAbsolute))]
public abstract class Position
{
internal Position() { }
public static Position Relative => PositionRelative.Instance;
public static Position Absolute => PositionAbsolute.Instance;
}
[MessagePackObject(AllowPrivate = true)]
public sealed class PositionRelative : Position
{
internal static readonly PositionRelative Instance = new PositionRelative();
[SerializationConstructor] private PositionRelative() { }
}
[MessagePackObject(AllowPrivate = true)]
public sealed class PositionAbsolute : Position
{
internal static readonly PositionAbsolute Instance = new PositionAbsolute();
[SerializationConstructor] private PositionAbsolute() { }
}
[Union(0, typeof(OverflowVisible))]
[Union(1, typeof(OverflowClip))]
[Union(2, typeof(OverflowScroll))]
public abstract class Overflow
{
internal Overflow() { }
public static Overflow Visible => OverflowVisible.Instance;
public static Overflow Clip => OverflowClip.Instance;
public static Overflow Scroll => OverflowScroll.Instance;
}
[MessagePackObject(AllowPrivate = true)]
public sealed class OverflowVisible : Overflow
{
internal static readonly OverflowVisible Instance = new OverflowVisible();
[SerializationConstructor] private OverflowVisible() { }
}
[MessagePackObject(AllowPrivate = true)]
public sealed class OverflowClip : Overflow
{
internal static readonly OverflowClip Instance = new OverflowClip();
[SerializationConstructor] private OverflowClip() { }
}
[MessagePackObject(AllowPrivate = true)]
public sealed class OverflowScroll : Overflow
{
internal static readonly OverflowScroll Instance = new OverflowScroll();
[SerializationConstructor] private OverflowScroll() { }
}
[Union(0, typeof(ItemAlignAuto))]
[Union(1, typeof(ItemAlignStart))]
[Union(2, typeof(ItemAlignEnd))]
[Union(3, typeof(ItemAlignCenter))]
[Union(4, typeof(ItemAlignStretch))]
[Union(5, typeof(ItemAlignBaseline))]
public abstract class ItemAlign
{
internal ItemAlign() { }
public static ItemAlign Auto => ItemAlignAuto.Instance;
public static ItemAlign Start => ItemAlignStart.Instance;
public static ItemAlign End => ItemAlignEnd.Instance;
public static ItemAlign Center => ItemAlignCenter.Instance;
public static ItemAlign Stretch => ItemAlignStretch.Instance;
public static ItemAlign Baseline => ItemAlignBaseline.Instance;
}
[MessagePackObject(AllowPrivate = true)]
public sealed class ItemAlignAuto : ItemAlign
{
internal static readonly ItemAlignAuto Instance = new ItemAlignAuto();
[SerializationConstructor] private ItemAlignAuto() { }
}
[MessagePackObject(AllowPrivate = true)]
public sealed class ItemAlignStart : ItemAlign
{
internal static readonly ItemAlignStart Instance = new ItemAlignStart();
[SerializationConstructor] private ItemAlignStart() { }
}
[MessagePackObject(AllowPrivate = true)]
public sealed class ItemAlignEnd : ItemAlign
{
internal static readonly ItemAlignEnd Instance = new ItemAlignEnd();
[SerializationConstructor] private ItemAlignEnd() { }
}
[MessagePackObject(AllowPrivate = true)]
public sealed class ItemAlignCenter : ItemAlign
{
internal static readonly ItemAlignCenter Instance = new ItemAlignCenter();
[SerializationConstructor] private ItemAlignCenter() { }
}
[MessagePackObject(AllowPrivate = true)]
public sealed class ItemAlignStretch : ItemAlign
{
internal static readonly ItemAlignStretch Instance = new ItemAlignStretch();
[SerializationConstructor] private ItemAlignStretch() { }
}
[MessagePackObject(AllowPrivate = true)]
public sealed class ItemAlignBaseline : ItemAlign
{
internal static readonly ItemAlignBaseline Instance = new ItemAlignBaseline();
[SerializationConstructor] private ItemAlignBaseline() { }
}
[Union(0, typeof(ContentAlignAuto))]
[Union(1, typeof(ContentAlignStart))]
[Union(2, typeof(ContentAlignEnd))]
[Union(3, typeof(ContentAlignCenter))]
[Union(4, typeof(ContentAlignStretch))]
[Union(5, typeof(ContentAlignSpaceBetween))]
[Union(6, typeof(ContentAlignSpaceAround))]
[Union(7, typeof(ContentAlignSpaceEvenly))]
public abstract class ContentAlign
{
internal ContentAlign() { }
public static ContentAlign Auto => ContentAlignAuto.Instance;
public static ContentAlign Start => ContentAlignStart.Instance;
public static ContentAlign End => ContentAlignEnd.Instance;
public static ContentAlign Center => ContentAlignCenter.Instance;
public static ContentAlign Stretch => ContentAlignStretch.Instance;
public static ContentAlign SpaceBetween => ContentAlignSpaceBetween.Instance;
public static ContentAlign SpaceAround => ContentAlignSpaceAround.Instance;
public static ContentAlign SpaceEvenly => ContentAlignSpaceEvenly.Instance;
}
[MessagePackObject(AllowPrivate = true)]
public sealed class ContentAlignAuto : ContentAlign
{
internal static readonly ContentAlignAuto Instance = new ContentAlignAuto();
[SerializationConstructor] private ContentAlignAuto() { }
}
[MessagePackObject(AllowPrivate = true)]
public sealed class ContentAlignStart : ContentAlign
{
internal static readonly ContentAlignStart Instance = new ContentAlignStart();
[SerializationConstructor] private ContentAlignStart() { }
}
[MessagePackObject(AllowPrivate = true)]
public sealed class ContentAlignEnd : ContentAlign
{
internal static readonly ContentAlignEnd Instance = new ContentAlignEnd();
[SerializationConstructor] private ContentAlignEnd() { }
}
[MessagePackObject(AllowPrivate = true)]
public sealed class ContentAlignCenter : ContentAlign
{
internal static readonly ContentAlignCenter Instance = new ContentAlignCenter();
[SerializationConstructor] private ContentAlignCenter() { }
}
[MessagePackObject(AllowPrivate = true)]
public sealed class ContentAlignStretch : ContentAlign
{
internal static readonly ContentAlignStretch Instance = new ContentAlignStretch();
[SerializationConstructor] private ContentAlignStretch() { }
}
[MessagePackObject(AllowPrivate = true)]
public sealed class ContentAlignSpaceBetween : ContentAlign
{
internal static readonly ContentAlignSpaceBetween Instance = new ContentAlignSpaceBetween();
[SerializationConstructor] private ContentAlignSpaceBetween() { }
}
[MessagePackObject(AllowPrivate = true)]
public sealed class ContentAlignSpaceAround : ContentAlign
{
internal static readonly ContentAlignSpaceAround Instance = new ContentAlignSpaceAround();
[SerializationConstructor] private ContentAlignSpaceAround() { }
}
[MessagePackObject(AllowPrivate = true)]
public sealed class ContentAlignSpaceEvenly : ContentAlign
{
internal static readonly ContentAlignSpaceEvenly Instance = new ContentAlignSpaceEvenly();
[SerializationConstructor] private ContentAlignSpaceEvenly() { }
}
[Union(0, typeof(ThemeToken))]
[Union(1, typeof(Rgba))]
public abstract class ColorRef
{
internal ColorRef() { }
}
[MessagePackObject]
public sealed class ThemeToken : ColorRef
{
[Key(0)] public string Name { get; }
public ThemeToken(string name)
{
Name = name;
}
}
[MessagePackObject]
public sealed class Rgba : ColorRef
{
[Key(0)] public byte R { get; }
[Key(1)] public byte G { get; }
[Key(2)] public byte B { get; }
[Key(3)] public byte A { get; }
public Rgba(byte r, byte g, byte b, byte a)
{
R = r;
G = g;
B = b;
A = a;
}
}
[Union(0, typeof(RoleGroup))]
[Union(1, typeof(RoleRegion))]
[Union(2, typeof(RoleList))]
[Union(3, typeof(RoleListItem))]
[Union(4, typeof(RoleHeading))]
[Union(5, typeof(RoleDialog))]
[Union(6, typeof(RoleToolbar))]
public abstract class Role
{
internal Role() { }
public static Role Group => RoleGroup.Instance;
public static Role Region => RoleRegion.Instance;
public static Role List => RoleList.Instance;
public static Role ListItem => RoleListItem.Instance;
public static Role Heading => RoleHeading.Instance;
public static Role Dialog => RoleDialog.Instance;
public static Role Toolbar => RoleToolbar.Instance;
}
[MessagePackObject(AllowPrivate = true)]
public sealed class RoleGroup : Role
{
internal static readonly RoleGroup Instance = new RoleGroup();
[SerializationConstructor] private RoleGroup() { }
}
[MessagePackObject(AllowPrivate = true)]
public sealed class RoleRegion : Role
{
internal static readonly RoleRegion Instance = new RoleRegion();
[SerializationConstructor] private RoleRegion() { }
}
[MessagePackObject(AllowPrivate = true)]
public sealed class RoleList : Role
{
internal static readonly RoleList Instance = new RoleList();
[SerializationConstructor] private RoleList() { }
}
[MessagePackObject(AllowPrivate = true)]
public sealed class RoleListItem : Role
{
internal static readonly RoleListItem Instance = new RoleListItem();
[SerializationConstructor] private RoleListItem() { }
}
[MessagePackObject(AllowPrivate = true)]
public sealed class RoleHeading : Role
{
internal static readonly RoleHeading Instance = new RoleHeading();
[SerializationConstructor] private RoleHeading() { }
}
[MessagePackObject(AllowPrivate = true)]
public sealed class RoleDialog : Role
{
internal static readonly RoleDialog Instance = new RoleDialog();
[SerializationConstructor] private RoleDialog() { }
}
[MessagePackObject(AllowPrivate = true)]
public sealed class RoleToolbar : Role
{
internal static readonly RoleToolbar Instance = new RoleToolbar();
[SerializationConstructor] private RoleToolbar() { }
}
[MessagePackObject]
public sealed class Size2
{
[Key(0)] public Dimension Width { get; }
[Key(1)] public Dimension Height { get; }
public Size2(Dimension width, Dimension height)
{
Width = width;
Height = height;
}
}
[MessagePackObject]
public sealed class Edges
{
[Key(0)] public Dimension Top { get; }
[Key(1)] public Dimension Right { get; }
[Key(2)] public Dimension Bottom { get; }
[Key(3)] public Dimension Left { get; }
public Edges(Dimension top, Dimension right, Dimension bottom, Dimension left)
{
Top = top;
Right = right;
Bottom = bottom;
Left = left;
}
}
[MessagePackObject]
public sealed class BoxStyle
{
[Key(0)] public Display Display { get; }
[Key(1)] public Direction Direction { get; }
[Key(2)] public Wrap Wrap { get; }
[Key(3)] public Size2 Gap { get; }
[Key(4)] public Edges Padding { get; }
[Key(5)] public Edges Margin { get; }
[Key(6)] public Size2 Size { get; }
[Key(7)] public Size2 MinSize { get; }
[Key(8)] public Size2 MaxSize { get; }
[Key(9)] public Position Position { get; }
[Key(10)] public Edges Inset { get; }
[Key(11)] public Overflow Overflow { get; }
[Key(12)] public ItemAlign AlignItems { get; }
[Key(13)] public ItemAlign AlignSelf { get; }
[Key(14)] public ContentAlign AlignContent { get; }
[Key(15)] public ContentAlign JustifyContent { get; }
[Key(16)] public double Grow { get; }
[Key(17)] public double Shrink { get; }
[Key(18)] public Dimension Basis { get; }
[Key(19)] public List<Dimension> GridColumns { get; }
[Key(20)] public List<Dimension> GridRows { get; }
public BoxStyle(Display display, Direction direction, Wrap wrap, Size2 gap, Edges padding, Edges margin, Size2 size, Size2 minSize, Size2 maxSize, Position position, Edges inset, Overflow overflow, ItemAlign alignItems, ItemAlign alignSelf, ContentAlign alignContent, ContentAlign justifyContent, double grow, double shrink, Dimension basis, List<Dimension> gridColumns, List<Dimension> gridRows)
{
Display = display;
Direction = direction;
Wrap = wrap;
Gap = gap;
Padding = padding;
Margin = margin;
Size = size;
MinSize = minSize;
MaxSize = maxSize;
Position = position;
Inset = inset;
Overflow = overflow;
AlignItems = alignItems;
AlignSelf = alignSelf;
AlignContent = alignContent;
JustifyContent = justifyContent;
Grow = grow;
Shrink = shrink;
Basis = basis;
GridColumns = gridColumns;
GridRows = gridRows;
}
}
[MessagePackObject]
public sealed class Border
{
[Key(0)] public ColorRef Color { get; }
[Key(1)] public double Width { get; }
public Border(ColorRef color, double width)
{
Color = color;
Width = width;
}
}
[MessagePackObject]
public sealed class Paint
{
[Key(0)] public ColorRef? Background { get; }
[Key(1)] public Border? Border { get; }
[Key(2)] public double Radius { get; }
public Paint(ColorRef? background, Border? border, double radius)
{
Background = background;
Border = border;
Radius = radius;
}
}