RSCG – Dusharp
RSCG – Dusharp
name | Dusharp |
nuget | https://www.nuget.org/packages/Dusharp/ |
link | https://github.com/kolebynov/Dusharp |
author | Vitali |
Generate tagged union
This is how you can use Dusharp .
The code that you start with is
<Project Sdk="Microsoft.NET.Sdk"> <PropertyGroup> <OutputType>Exe</OutputType> <TargetFramework>net8.0</TargetFramework> <ImplicitUsings>enable</ImplicitUsings> <Nullable>enable</Nullable> </PropertyGroup> <PropertyGroup> <EmitCompilerGeneratedFiles>true</EmitCompilerGeneratedFiles> <CompilerGeneratedFilesOutputPath>$(BaseIntermediateOutputPath)\GX</CompilerGeneratedFilesOutputPath> </PropertyGroup> <ItemGroup> <PackageReference Include="Dusharp" Version="0.4.0"> <PrivateAssets>all</PrivateAssets> <IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets> </PackageReference> </ItemGroup> </Project>
The code that you will use is
using UnionTypesDemo; Console.WriteLine("Save or not"); var data = SaveToDatabase.Save(0); data.Match( ok => Console.WriteLine(ok), ()=> Console.WriteLine("Not found") ); data = SaveToDatabase.Save(1); data.Match( ok => Console.WriteLine(ok), () => Console.WriteLine("Not found") );
using Dusharp; namespace UnionTypesDemo; [Union] public partial class ResultSave { [UnionCase] public static partial ResultSave Ok(int i); [UnionCase] public static partial ResultSave NotFound(); }
namespace UnionTypesDemo; public class SaveToDatabase { public static ResultSave Save(int i) { if (i == 0) { return ResultSave.NotFound(); } return ResultSave.Ok(i); ; } }
The code that is generated is
// <auto-generated> This file has been auto generated. </auto-generated> #nullable enable using System; using System.Runtime.CompilerServices; namespace Dusharp { public static class ExceptionUtils { [MethodImpl(MethodImplOptions.AggressiveInlining)] public static void ThrowIfNull<T>(this T value, string paramName) where T : class { if (value == null) { ThrowArgumentNull(paramName); } } [MethodImpl(MethodImplOptions.NoInlining)] public static void ThrowUnionInInvalidState() => throw new InvalidOperationException("Union in invalid state."); [MethodImpl(MethodImplOptions.NoInlining)] private static void ThrowArgumentNull(string paramName) => throw new ArgumentNullException(paramName); } }
// <auto-generated> This file has been auto generated. </auto-generated> #nullable enable using System; namespace Dusharp { [AttributeUsage(AttributeTargets.Class)] public sealed class UnionAttribute : Attribute { } }
// <auto-generated> This file has been auto generated. </auto-generated> #nullable enable using System; namespace Dusharp { [AttributeUsage(AttributeTargets.Method)] public sealed class UnionCaseAttribute : Attribute { } }
// <auto-generated> This file has been auto generated. </auto-generated> #nullable enable namespace UnionTypesDemo { [System.Diagnostics.CodeAnalysis.SuppressMessage("", "CA1000", Justification = "For generic unions.")] abstract partial class ResultSave : System.IEquatable<ResultSave> { private ResultSave() {} public void Match(System.Action<int> okCase, System.Action notFoundCase) { Dusharp.ExceptionUtils.ThrowIfNull(okCase, "okCase"); Dusharp.ExceptionUtils.ThrowIfNull(notFoundCase, "notFoundCase"); { var unionCase = this as OkCase; if (!object.ReferenceEquals(unionCase, null)) { okCase(unionCase.i); return; } } { var unionCase = this as NotFoundCase; if (!object.ReferenceEquals(unionCase, null)) { notFoundCase(); return; } } Dusharp.ExceptionUtils.ThrowUnionInInvalidState(); } public TRet Match<TRet>(System.Func<int, TRet> okCase, System.Func<TRet> notFoundCase) { Dusharp.ExceptionUtils.ThrowIfNull(okCase, "okCase"); Dusharp.ExceptionUtils.ThrowIfNull(notFoundCase, "notFoundCase"); { var unionCase = this as OkCase; if (!object.ReferenceEquals(unionCase, null)) { return okCase(unionCase.i); } } { var unionCase = this as NotFoundCase; if (!object.ReferenceEquals(unionCase, null)) { return notFoundCase(); } } Dusharp.ExceptionUtils.ThrowUnionInInvalidState(); return default!; } public void Match<TState>(TState state, System.Action<TState, int> okCase, System.Action<TState> notFoundCase) { Dusharp.ExceptionUtils.ThrowIfNull(okCase, "okCase"); Dusharp.ExceptionUtils.ThrowIfNull(notFoundCase, "notFoundCase"); { var unionCase = this as OkCase; if (!object.ReferenceEquals(unionCase, null)) { okCase(state, unionCase.i); return; } } { var unionCase = this as NotFoundCase; if (!object.ReferenceEquals(unionCase, null)) { notFoundCase(state); return; } } Dusharp.ExceptionUtils.ThrowUnionInInvalidState(); } public TRet Match<TState, TRet>(TState state, System.Func<TState, int, TRet> okCase, System.Func<TState, TRet> notFoundCase) { Dusharp.ExceptionUtils.ThrowIfNull(okCase, "okCase"); Dusharp.ExceptionUtils.ThrowIfNull(notFoundCase, "notFoundCase"); { var unionCase = this as OkCase; if (!object.ReferenceEquals(unionCase, null)) { return okCase(state, unionCase.i); } } { var unionCase = this as NotFoundCase; if (!object.ReferenceEquals(unionCase, null)) { return notFoundCase(state); } } Dusharp.ExceptionUtils.ThrowUnionInInvalidState(); return default!; } public virtual bool Equals(ResultSave? other) { return object.ReferenceEquals(this, other); } public override bool Equals(object? other) { return object.ReferenceEquals(this, other); } public override int GetHashCode() { return System.Runtime.CompilerServices.RuntimeHelpers.GetHashCode(this); } public static bool operator ==(ResultSave? left, ResultSave? right) { return !object.ReferenceEquals(left, null) ? left.Equals(right) : object.ReferenceEquals(left, right); } public static bool operator !=(ResultSave? left, ResultSave? right) { return !object.ReferenceEquals(left, null) ? !left.Equals(right) : !object.ReferenceEquals(left, right); } private sealed class OkCase : ResultSave { public readonly int i; public OkCase(int i) { this.i = i; } public override string ToString() { return $"Ok {{ i = {i} }}"; } public override bool Equals(ResultSave? other) { if (object.ReferenceEquals(this, other)) return true; var otherCasted = other as OkCase; if (object.ReferenceEquals(otherCasted, null)) return false; return StructuralEquals(otherCasted); } public override bool Equals(object? other) { if (object.ReferenceEquals(this, other)) return true; var otherCasted = other as OkCase; if (object.ReferenceEquals(otherCasted, null)) return false; return StructuralEquals(otherCasted); } public override int GetHashCode() { unchecked { return System.Collections.Generic.EqualityComparer<int>.Default.GetHashCode(i!) * -1521134295 + "Ok".GetHashCode(); } } private bool StructuralEquals(OkCase other) { return System.Collections.Generic.EqualityComparer<int>.Default.Equals(i, other.i); } } public static partial ResultSave Ok(int i) { return new OkCase(i); } private sealed class NotFoundCase : ResultSave { public static readonly NotFoundCase Instance = new NotFoundCase(); public NotFoundCase() { } public override string ToString() { return "NotFound"; } } public static partial ResultSave NotFound() { return NotFoundCase.Instance; } } }
// <auto-generated/> #nullable enable using Sera.TaggedUnion; namespace UnionTypesDemo { public partial struct ResultSave : global::Sera.TaggedUnion.ITaggedUnion , global::System.IEquatable<ResultSave> , global::System.IComparable<ResultSave> #if NET7_0_OR_GREATER , global::System.Numerics.IEqualityOperators<ResultSave, ResultSave, bool> , global::System.Numerics.IComparisonOperators<ResultSave, ResultSave, bool> #endif { private __impl_ _impl; private ResultSave(__impl_ _impl) { this._impl = _impl; } public readonly Tags Tag { [global::System.Runtime.CompilerServices.MethodImpl(global::System.Runtime.CompilerServices.MethodImplOptions.AggressiveInlining)] get => this._impl._tag; } public enum Tags : byte { Ok = 1, NotFound = 2, } [global::System.Runtime.CompilerServices.CompilerGenerated] private struct __impl_ { public __unmanaged_ _unmanaged_; public readonly Tags _tag; [global::System.Runtime.CompilerServices.CompilerGenerated] [global::System.Runtime.InteropServices.StructLayout(global::System.Runtime.InteropServices.LayoutKind.Explicit)] internal struct __unmanaged_ { [global::System.Runtime.InteropServices.FieldOffset(0)] public int _0; } public __impl_(Tags _tag) { global::System.Runtime.CompilerServices.Unsafe.SkipInit(out this._unmanaged_); this._tag = _tag; } } [global::System.Runtime.CompilerServices.MethodImpl(global::System.Runtime.CompilerServices.MethodImplOptions.AggressiveInlining)] public static ResultSave MakeOk(int value) { var _impl = new __impl_(Tags.Ok); _impl._unmanaged_._0 = value; return new ResultSave(_impl); } [global::System.Runtime.CompilerServices.MethodImpl(global::System.Runtime.CompilerServices.MethodImplOptions.AggressiveInlining)] public static ResultSave MakeNotFound() { var _impl = new __impl_(Tags.NotFound); return new ResultSave(_impl); } public readonly bool IsOk { [global::System.Runtime.CompilerServices.MethodImpl(global::System.Runtime.CompilerServices.MethodImplOptions.AggressiveInlining)] get => this._impl._tag == Tags.Ok; } public readonly bool IsNotFound { [global::System.Runtime.CompilerServices.MethodImpl(global::System.Runtime.CompilerServices.MethodImplOptions.AggressiveInlining)] get => this._impl._tag == Tags.NotFound; } public int Ok { [global::System.Runtime.CompilerServices.MethodImpl(global::System.Runtime.CompilerServices.MethodImplOptions.AggressiveInlining)] readonly get => !this.IsOk ? default! : this._impl._unmanaged_._0!; [global::System.Runtime.CompilerServices.MethodImpl(global::System.Runtime.CompilerServices.MethodImplOptions.AggressiveInlining)] set { if (this.IsOk) { this._impl._unmanaged_._0 = value; } } } [global::System.Runtime.CompilerServices.MethodImpl(global::System.Runtime.CompilerServices.MethodImplOptions.AggressiveInlining)] public readonly bool Equals(ResultSave other) => this.Tag != other.Tag ? false : this.Tag switch { Tags.Ok => global::System.Collections.Generic.EqualityComparer<int>.Default.Equals(this.Ok, other.Ok), _ => true, }; [global::System.Runtime.CompilerServices.MethodImpl(global::System.Runtime.CompilerServices.MethodImplOptions.AggressiveInlining)] public readonly override int GetHashCode() => this.Tag switch { Tags.Ok => global::System.HashCode.Combine(this.Tag, this.Ok), _ => global::System.HashCode.Combine(this.Tag), }; [global::System.Runtime.CompilerServices.MethodImpl(global::System.Runtime.CompilerServices.MethodImplOptions.AggressiveInlining)] public readonly override bool Equals(object? obj) => obj is ResultSave other && Equals(other); [global::System.Runtime.CompilerServices.MethodImpl(global::System.Runtime.CompilerServices.MethodImplOptions.AggressiveInlining)] public static bool operator ==(ResultSave left, ResultSave right) => Equals(left, right); [global::System.Runtime.CompilerServices.MethodImpl(global::System.Runtime.CompilerServices.MethodImplOptions.AggressiveInlining)] public static bool operator !=(ResultSave left, ResultSave right) => !Equals(left, right); [global::System.Runtime.CompilerServices.MethodImpl(global::System.Runtime.CompilerServices.MethodImplOptions.AggressiveInlining)] public readonly int CompareTo(ResultSave other) => this.Tag != other.Tag ? global::System.Collections.Generic.Comparer<Tags>.Default.Compare(this.Tag, other.Tag) : this.Tag switch { Tags.Ok => global::System.Collections.Generic.Comparer<int>.Default.Compare(this.Ok, other.Ok), _ => 0, }; [global::System.Runtime.CompilerServices.MethodImpl(global::System.Runtime.CompilerServices.MethodImplOptions.AggressiveInlining)] public static bool operator <(ResultSave left, ResultSave right) => left.CompareTo(right) < 0; [global::System.Runtime.CompilerServices.MethodImpl(global::System.Runtime.CompilerServices.MethodImplOptions.AggressiveInlining)] public static bool operator >(ResultSave left, ResultSave right) => left.CompareTo(right) > 0; [global::System.Runtime.CompilerServices.MethodImpl(global::System.Runtime.CompilerServices.MethodImplOptions.AggressiveInlining)] public static bool operator <=(ResultSave left, ResultSave right) => left.CompareTo(right) <= 0; [global::System.Runtime.CompilerServices.MethodImpl(global::System.Runtime.CompilerServices.MethodImplOptions.AggressiveInlining)] public static bool operator >=(ResultSave left, ResultSave right) => left.CompareTo(right) >= 0; [global::System.Runtime.CompilerServices.MethodImpl(global::System.Runtime.CompilerServices.MethodImplOptions.AggressiveInlining)] public readonly override string ToString() => this.Tag switch { Tags.Ok => $"{nameof(ResultSave)}.{nameof(Tags.Ok)} {{ {this.Ok} }}", Tags.NotFound => $"{nameof(ResultSave)}.{nameof(Tags.NotFound)}", _ => nameof(ResultSave), }; } } // namespace UnionTypesDemo
Code and pdf at
https://ignatandrei.github.io/RSCG_Examples/v2/docs/Dusharp
Leave a Reply