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

v0.3.0 #1

Merged
merged 8 commits into from
May 19, 2022
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
20 changes: 17 additions & 3 deletions .github/workflows/build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,17 @@ name: Build

on:
push:
branches: [ master, develop ]
pull_request:
branches: [ master ]
workflow_dispatch:
inputs:
publish_github:
type: boolean
description: Publish to GitHub Packages
default: false
publish_nuget:
type: boolean
description: Publish to nuget.org
default: false

env:
T4_MAX_TYPE_PARAM: 16
Expand Down Expand Up @@ -36,6 +44,12 @@ jobs:
name: nupkg
path: artifacts/*.nupkg
- name: NuGet add souce
id: nuget_add_source
if: ${{ github.event.inputs.publish_github }}
run: dotnet nuget add source -u hikarin522 -p ${{ secrets.GITHUB_TOKEN }} --store-password-in-clear-text -n "github" "https://nuget.pkg.github.com/hikarin522/index.json"
- name: Publish
- name: Publish GitHub Packages
if: ${{ steps.nuget_add_source.conclusion == 'success' }}
run: dotnet nuget push "artifacts/*.nupkg" -k ${{ secrets.GITHUB_TOKEN }} -s "github" --skip-duplicate
- name: Publish NuGet
if: ${{ github.event.inputs.publish_nuget }}
run: dotnet nuget push "artifacts/*.nupkg" -k ${{ secrets.NUGET_OLG_API_KEY }} -s "nuget" --skip-duplicate
3 changes: 2 additions & 1 deletion Directory.Build.props
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
<LangVersion>latest</LangVersion>
<Nullable>enable</Nullable>

<Version>0.2.0</Version>
<Version>0.3.0</Version>
<Authors>hikarin522</Authors>
<Copyright>(c) 2022 hikarin522.</Copyright>
<PackageLicenseExpression>MIT</PackageLicenseExpression>
Expand All @@ -12,5 +12,6 @@
<PackageProjectUrl>$(RepositoryUrl)</PackageProjectUrl>
<PackageReadmeFile>README.md</PackageReadmeFile>
<PackageTags>variant;union</PackageTags>
<Description>C# source generator to generate efficient and type-safe variant types for unmanaged types.</Description>
</PropertyGroup>
</Project>
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ readonly partial struct SampleVariant: IEquatable<SampleVariant>

private readonly Union Value;

public TypeIndex Index { get; }
public readonly TypeIndex Index;

public int Item1 => Index == TypeIndex.Type1 ? Value.Item1 : throw new InvalidCastException();
public long Item2 => Index == TypeIndex.Type2 ? Value.Item2 : throw new InvalidCastException();
Expand Down
9 changes: 6 additions & 3 deletions ValueVariant.Generator/ValueVariant.Generator.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -37,15 +37,18 @@
<Compile Update="@(T4->'%(RelativeDir)%(Filename).cs')">
<DesignTime>True</DesignTime>
<AutoGen>True</AutoGen>
<DependentUpon>%(RelativeDir)%(Filename).tt</DependentUpon>
<DependentUpon>%(Filename).tt</DependentUpon>
</Compile>
</ItemGroup>

<Target Name="T4Generate" BeforeTargets="BeforeBuild" Condition="'$(MSBuildRuntimeType)' != 'Full'">
<Exec Command="dotnet t4 &quot;%(T4.Filename).tt&quot; -c &quot;$(RootNamespace).%(T4.Filename)&quot; -o &quot;%(T4.Filename).cs&quot;" WorkingDirectory="$(MSBuildProjectDirectory)\%(T4.RelativeDir)" />
<ItemGroup>
<Compile Remove="@(T4->'%(RelativeDir)%(Filename).cs')" />
<Compile Include="@(T4->'%(RelativeDir)%(Filename).cs')" />
<Compile Include="@(T4->'%(RelativeDir)%(Filename).cs')" Exclude="@(Compile)">
<DesignTime>True</DesignTime>
<AutoGen>True</AutoGen>
<DependentUpon>%(Filename).tt</DependentUpon>
</Compile>
</ItemGroup>
</Target>

Expand Down
57 changes: 14 additions & 43 deletions ValueVariant.Generator/ValueVariantTemplate.tt
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,6 @@ namespace <#= Namespace #>
using T<#= i #> = global::<#= Types[i - 1] #>;
<# } #>

[StructLayout(LayoutKind.Sequential, Pack = 1)]
<# if (Options.HasFlag(ValueVariantGenerateOptions.MessagePackFormatter)) { #>
[MessagePackFormatter(typeof(<#= TypeName #>.MessagePackFormatter))]
<# } #>
Expand All @@ -60,7 +59,7 @@ namespace <#= Namespace #>

public readonly TypeIndex Index;

byte V2.Details.IValueVariant.TypeIndexByte { [MethodImpl(MethodImplOptions.AggressiveInlining)] get => (byte)this.Index; }
byte V2.Details.IValueVariant.TypeIndex { [MethodImpl(MethodImplOptions.AggressiveInlining)] get => (byte)this.Index; }

private <#= TypeName #>(in Union value, TypeIndex index)
=> (this.Value, this.Index) = (value, index);
Expand Down Expand Up @@ -116,75 +115,47 @@ namespace <#= Namespace #>

public interface IFuncVisitor<in TA1, out TR> : <#= Join(1, Count, e => $"V2.IValueVariantFuncVisitor<T{e}, TA1, TR>") #> { }

public void Accept(IActionVisitor visitor)
=> this.AcceptActionVisitor(visitor);

public void Accept<TA1>(IActionVisitor<TA1> visitor, TA1 arg1)
=> this.AcceptActionVisitor(visitor, arg1);

public TR Accept<TR>(IFuncVisitor<TR> visitor)
{
this.AcceptFuncVisitor(visitor, out TR result);
this.Accept(visitor, out TR result);
return result;
}

public TR Accept<TA1, TR>(IFuncVisitor<TA1, TR> visitor, TA1 arg1)
{
this.AcceptFuncVisitor(visitor, arg1, out TR result);
return result;
}

public void Accept(V2.IValueVariantGenericActionVisitor visitor)
=> this.AcceptGenericActionVisitor(visitor);

public void Accept<TA1>(V2.IValueVariantGenericActionVisitor<TA1> visitor, TA1 arg1)
=> this.AcceptGenericActionVisitor(visitor, arg1);

public TR Accept<TA1, TR>(V2.IValueVariantGenericFuncVisitor<TA1, TR> visitor, TA1 arg1)
{
this.AcceptGenericFuncVisitor(visitor, arg1, out TR result);
return result;
}

public TR Accept<TR>(V2.IValueVariantGenericFuncVisitor<TR> visitor)
{
this.AcceptGenericFuncVisitor(visitor, out TR result);
this.Accept(visitor, arg1, out TR result);
return result;
}

public void AcceptActionVisitor<TV>(in TV visitor)
public void Accept<TV>(in TV visitor)
where TV : <#= Join(1, Count, e => $"V2.IValueVariantActionVisitor<T{e}>") #>
=> V2.Details.ValueVariant<<#= Join(1, Count, e => $"T{e}") #>>.AcceptActionVisitor(this, visitor);

public void AcceptActionVisitor<TV, TA1>(in TV visitor, TA1 arg1)
public void Accept<TV, TA1>(in TV visitor, TA1 arg1)
where TV : <#= Join(1, Count, e => $"V2.IValueVariantActionVisitor<T{e}, TA1>") #>
=> V2.Details.ValueVariant<<#= Join(1, Count, e => $"T{e}") #>>.AcceptActionVisitor(this, visitor, arg1);

public void AcceptFuncVisitor<TV, TR>(in TV visitor, out TR result)
public void Accept<TV, TR>(in TV visitor, out TR result)
where TV : <#= Join(1, Count, e => $"V2.IValueVariantFuncVisitor<T{e}, TR>") #>
=> result = V2.Details.ValueVariant<<#= Join(1, Count, e => $"T{e}") #>>.AcceptFuncVisitor<T, TV, TR>(this, visitor);

public void AcceptFuncVisitor<TV, TA1, TR>(in TV visitor, TA1 arg1, out TR result)
public void Accept<TV, TA1, TR>(in TV visitor, TA1 arg1, out TR result)
where TV : <#= Join(1, Count, e => $"V2.IValueVariantFuncVisitor<T{e}, TA1, TR>") #>
=> result = V2.Details.ValueVariant<<#= Join(1, Count, e => $"T{e}") #>>.AcceptFuncVisitor<T, TV, TA1, TR>(this, visitor, arg1);

public void AcceptGenericActionVisitor<TV>(in TV visitor)
where TV : V2.IValueVariantGenericActionVisitor
public void Accept(V2.IValueVariantGenericActionVisitor visitor)
=> V2.Details.ValueVariant<<#= Join(1, Count, e => $"T{e}") #>>.AcceptGenericActionVisitor(this, visitor);

public void AcceptGenericActionVisitor<TV, TA1>(in TV visitor, TA1 arg1)
where TV : V2.IValueVariantGenericActionVisitor<TA1>
public void Accept<TA1>(V2.IValueVariantGenericActionVisitor<TA1> visitor, TA1 arg1)
=> V2.Details.ValueVariant<<#= Join(1, Count, e => $"T{e}") #>>.AcceptGenericActionVisitor(this, visitor, arg1);

public void AcceptGenericFuncVisitor<TV, TR>(in TV visitor, out TR result)
where TV : V2.IValueVariantGenericFuncVisitor<TR>
=> result = V2.Details.ValueVariant<<#= Join(1, Count, e => $"T{e}") #>>.AcceptGenericFuncVisitor<T, TV, TR>(this, visitor);
public TR Accept<TR>(V2.IValueVariantGenericFuncVisitor<TR> visitor)
=> V2.Details.ValueVariant<<#= Join(1, Count, e => $"T{e}") #>>.AcceptGenericFuncVisitor<T, V2.IValueVariantGenericFuncVisitor<TR>, TR>(this, visitor);

public void AcceptGenericFuncVisitor<TV, TA1, TR>(in TV visitor, TA1 arg1, out TR result)
where TV : V2.IValueVariantGenericFuncVisitor<TA1, TR>
=> result = V2.Details.ValueVariant<<#= Join(1, Count, e => $"T{e}") #>>.AcceptGenericFuncVisitor<T, TV, TA1, TR>(this, visitor, arg1);
public TR Accept<TA1, TR>(V2.IValueVariantGenericFuncVisitor<TA1, TR> visitor, TA1 arg1)
=> V2.Details.ValueVariant<<#= Join(1, Count, e => $"T{e}") #>>.AcceptGenericFuncVisitor<T, V2.IValueVariantGenericFuncVisitor<TA1, TR>, TA1, TR>(this, visitor, arg1);

public struct DefaultConverter : IFuncVisitor<T>
public readonly struct DefaultConverter : IFuncVisitor<T>
{
<# for (var i = 1; i <= Count; ++i ) { #>
public T Visit(in T<#= i #> value) => value;
Expand Down
16 changes: 8 additions & 8 deletions ValueVariant.Test/TestVariant.cs
Original file line number Diff line number Diff line change
Expand Up @@ -9,17 +9,17 @@ namespace ValueVariant.Test;
[ValueVariant(ValueVariantGenerateOptions.MessagePackFormatter)]
public readonly partial struct TestVariant : IValueVariant<TestVariant, int, TestStruct<Guid>, DateTime> { }

public readonly struct TestVariantVisitor : TestVariant.IFuncVisitor<int>
public readonly struct TestVariantVisitor : TestVariant.IFuncVisitor<Type>
{
public int Visit(in int value)
=> 1;
public Type Visit(in int value)
=> typeof(int);

public int Visit(in TestStruct<Guid> value)
=> 2;
public Type Visit(in TestStruct<Guid> value)
=> typeof(TestStruct<Guid>);

public int Visit(in DateTime value)
=> 3;
public Type Visit(in DateTime value)
=> typeof(DateTime);
}

[ValueVariant]
public readonly partial struct TestVariant2 : IValueVariant<TestVariant2, TestStruct<int>, DateTime, int> { }
public readonly partial struct TestVariant2 : IValueVariant<TestVariant2, TestStruct<Guid>, DateTime, int> { }
21 changes: 17 additions & 4 deletions ValueVariant.Test/UnitTest1.cs
Original file line number Diff line number Diff line change
Expand Up @@ -14,14 +14,27 @@ public class UnitTest1
[Fact]
public void Test1()
{
TestVariant v = default(int);
Assert.Equal(v.Accept(new TestVariantVisitor()), (int)v.Index);
TestVariant v;
TestVariant2 v2;
Type type;

v = default(int);
Assert.Equal(typeof(int), v.Accept(new TestVariantVisitor()));
v.Accept(new TestVariant2.DefaultConverter(), out v2);
v2.Accept(new TestVariantVisitor(), out type);
Assert.Equal(typeof(int), type);

v = default(TestStruct<Guid>);
Assert.Equal(v.Accept(new TestVariantVisitor()), (int)v.Index);
Assert.Equal(typeof(TestStruct<Guid>), v.Accept(new TestVariantVisitor()));
v.Accept(new TestVariant2.DefaultConverter(), out v2);
v2.Accept(new TestVariantVisitor(), out type);
Assert.Equal(typeof(TestStruct<Guid>), type);

v = default(DateTime);
Assert.Equal(v.Accept(new TestVariantVisitor()), (int)v.Index);
Assert.Equal(typeof(DateTime), v.Accept(new TestVariantVisitor()));
v.Accept(new TestVariant2.DefaultConverter(), out v2);
v2.Accept(new TestVariantVisitor(), out type);
Assert.Equal(typeof(DateTime), type);
}

[Fact]
Expand Down
10 changes: 5 additions & 5 deletions ValueVariant/Details/IValueVariant.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,15 +5,15 @@ namespace System.ValueVariant.Details;

public interface IValueVariant
{
byte TypeIndexByte { [MethodImpl(MethodImplOptions.AggressiveInlining)] get; }
byte TypeIndex { [MethodImpl(MethodImplOptions.AggressiveInlining)] get; }

void AcceptGenericActionVisitor<TV>(in TV visitor) where TV : IValueVariantGenericActionVisitor;
void Accept(IValueVariantGenericActionVisitor visitor);

void AcceptGenericActionVisitor<TV, TA1>(in TV visitor, TA1 arg1) where TV : IValueVariantGenericActionVisitor<TA1>;
void Accept<TA1>(IValueVariantGenericActionVisitor<TA1> visitor, TA1 arg1);

void AcceptGenericFuncVisitor<TV, TR>(in TV visitor, out TR result) where TV : IValueVariantGenericFuncVisitor<TR>;
TR Accept<TR>(IValueVariantGenericFuncVisitor<TR> visitor);

void AcceptGenericFuncVisitor<TV, TA1, TR>(in TV visitor, TA1 arg1, out TR result) where TV : IValueVariantGenericFuncVisitor<TA1, TR>;
TR Accept<TA1, TR>(IValueVariantGenericFuncVisitor<TA1, TR> visitor, TA1 arg1);
}

public interface IValueVariantElement<T>: IValueVariant where T: unmanaged { }
8 changes: 4 additions & 4 deletions ValueVariant/Details/IValueVariantT.tt
Original file line number Diff line number Diff line change
Expand Up @@ -17,12 +17,12 @@ public interface IValueVariant<<#= Join(1, i, e => $"T{e}") #>>:
<#= Join(1, i, e => $"IValueVariantIndex{e}<T{e}>") #>
<#= string.Join(" ", Range(1, i, e => $"where T{e}: unmanaged")) #>
{
void AcceptActionVisitor<TV>(in TV visitor) where TV: <#= Join(1, i, e => $"IValueVariantActionVisitor<T{e}>") #>;
void Accept<TV>(in TV visitor) where TV: <#= Join(1, i, e => $"IValueVariantActionVisitor<T{e}>") #>;

void AcceptActionVisitor<TV, TA1>(in TV visitor, TA1 arg1) where TV: <#= Join(1, i, e => $"IValueVariantActionVisitor<T{e}, TA1>") #>;
void Accept<TV, TA1>(in TV visitor, TA1 arg1) where TV: <#= Join(1, i, e => $"IValueVariantActionVisitor<T{e}, TA1>") #>;

void AcceptFuncVisitor<TV, TR>(in TV visitor, out TR result) where TV: <#= Join(1, i, e => $"IValueVariantFuncVisitor<T{e}, TR>") #>;
void Accept<TV, TR>(in TV visitor, out TR result) where TV: <#= Join(1, i, e => $"IValueVariantFuncVisitor<T{e}, TR>") #>;

void AcceptFuncVisitor<TV, TA1, TR>(in TV visitor, TA1 arg1, out TR result) where TV: <#= Join(1, i, e => $"IValueVariantFuncVisitor<T{e}, TA1, TR>") #>;
void Accept<TV, TA1, TR>(in TV visitor, TA1 arg1, out TR result) where TV: <#= Join(1, i, e => $"IValueVariantFuncVisitor<T{e}, TA1, TR>") #>;
}
<# } #>
4 changes: 2 additions & 2 deletions ValueVariant/Details/ValueVariantT.ActionVisitor.tt
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ partial class ValueVariant<<#= Join(1, i, e => $"T{e}") #>>
where T: unmanaged, V2.IValueVariant<T, <#= Join(1, i, e => $"T{e}") #>>
where V: <#= Join(1, i, e => $"IValueVariantActionVisitor<T{e}>") #>
{
switch (@this.TypeIndexByte) {
switch (@this.TypeIndex) {
<# for (var j = 1; j <= i; ++j) { #>
case <#= j #>: visitor.Visit(@this.Item<#= j #>); return;
<# } #>
Expand All @@ -37,7 +37,7 @@ partial class ValueVariant<<#= Join(1, i, e => $"T{e}") #>>
where T: unmanaged, V2.IValueVariant<T, <#= Join(1, i, e => $"T{e}") #>>
where V: <#= Join(1, i, e => $"IValueVariantActionVisitor<T{e}, TA1>") #>
{
switch (@this.TypeIndexByte) {
switch (@this.TypeIndex) {
<# for (var j = 1; j <= i; ++j) { #>
case <#= j #>: visitor.Visit(@this.Item<#= j #>, arg1); return;
<# } #>
Expand Down
4 changes: 2 additions & 2 deletions ValueVariant/Details/ValueVariantT.FuncVisitor.tt
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ partial class ValueVariant<<#= Join(1, i, e => $"T{e}") #>>
where T: unmanaged, V2.IValueVariant<T, <#= Join(1, i, e => $"T{e}") #>>
where V: <#= Join(1, i, e => $"IValueVariantFuncVisitor<T{e}, TR>") #>
{
return @this.TypeIndexByte switch {
return @this.TypeIndex switch {
<# for (var j = 1; j <= i; ++j) { #>
<#= j #> => visitor.Visit(@this.Item<#= j #>),
<# } #>
Expand All @@ -37,7 +37,7 @@ partial class ValueVariant<<#= Join(1, i, e => $"T{e}") #>>
where T: unmanaged, V2.IValueVariant<T, <#= Join(1, i, e => $"T{e}") #>>
where V: <#= Join(1, i, e => $"IValueVariantFuncVisitor<T{e}, TA1, TR>") #>
{
return @this.TypeIndexByte switch {
return @this.TypeIndex switch {
<# for (var j = 1; j <= i; ++j) { #>
<#= j #> => visitor.Visit(@this.Item<#= j #>, arg1),
<# } #>
Expand Down
4 changes: 2 additions & 2 deletions ValueVariant/Details/ValueVariantT.GenericActionVisitor.tt
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ partial class ValueVariant<<#= Join(1, i, e => $"T{e}") #>>
where T: unmanaged, V2.IValueVariant<T, <#= Join(1, i, e => $"T{e}") #>>
where V: IValueVariantGenericActionVisitor
{
switch (@this.TypeIndexByte) {
switch (@this.TypeIndex) {
<# for (var j = 1; j <= i; ++j) { #>
case <#= j #>: visitor.Visit(@this.Item<#= j #>); return;
<# } #>
Expand All @@ -37,7 +37,7 @@ partial class ValueVariant<<#= Join(1, i, e => $"T{e}") #>>
where T: unmanaged, V2.IValueVariant<T, <#= Join(1, i, e => $"T{e}") #>>
where V: IValueVariantGenericActionVisitor<TA1>
{
switch (@this.TypeIndexByte) {
switch (@this.TypeIndex) {
<# for (var j = 1; j <= i; ++j) { #>
case <#= j #>: visitor.Visit(@this.Item<#= j #>, arg1); return;
<# } #>
Expand Down
4 changes: 2 additions & 2 deletions ValueVariant/Details/ValueVariantT.GenericFuncVisitor.tt
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ partial class ValueVariant<<#= Join(1, i, e => $"T{e}") #>>
where T: unmanaged, V2.IValueVariant<T, <#= Join(1, i, e => $"T{e}") #>>
where V: IValueVariantGenericFuncVisitor<TR>
{
return @this.TypeIndexByte switch {
return @this.TypeIndex switch {
<# for (var j = 1; j <= i; ++j) { #>
<#= j #> => visitor.Visit(@this.Item<#= j #>),
<# } #>
Expand All @@ -37,7 +37,7 @@ partial class ValueVariant<<#= Join(1, i, e => $"T{e}") #>>
where T: unmanaged, V2.IValueVariant<T, <#= Join(1, i, e => $"T{e}") #>>
where V: IValueVariantGenericFuncVisitor<TA1, TR>
{
return @this.TypeIndexByte switch {
return @this.TypeIndex switch {
<# for (var j = 1; j <= i; ++j) { #>
<#= j #> => visitor.Visit(@this.Item<#= j #>, arg1),
<# } #>
Expand Down
10 changes: 5 additions & 5 deletions ValueVariant/Details/ValueVariantT.IEquatable.tt
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ partial class ValueVariant<<#= Join(1, i, e => $"T{e}") #>>
{
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static bool Equals<T>(in T lhs, in T rhs) where T: unmanaged, V2.IValueVariant<T, <#= Join(1, i, e => $"T{e}") #>>
=> lhs.TypeIndexByte == rhs.TypeIndexByte && lhs.TypeIndexByte switch {
=> lhs.TypeIndex == rhs.TypeIndex && lhs.TypeIndex switch {
<# for (var j = 1; j <= i; ++j) { #>
<#= j #> => EqualityComparer<T<#= j #>>.Default.Equals(lhs.Item<#= j #>, rhs.Item<#= j #>),
<# } #>
Expand All @@ -31,16 +31,16 @@ partial class ValueVariant<<#= Join(1, i, e => $"T{e}") #>>

[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static int GetHashCode<T>(in T @this) where T: unmanaged, V2.IValueVariant<T, <#= Join(1, i, e => $"T{e}") #>>
=> @this.TypeIndexByte switch {
=> @this.TypeIndex switch {
<# for (var j = 1; j <= i; ++j) { #>
<#= j #> => HashCode.Combine(@this.TypeIndexByte, @this.Item<#= j #>),
<#= j #> => HashCode.Combine(@this.TypeIndex, @this.Item<#= j #>),
<# } #>
_ => HashCode.Combine(@this.TypeIndexByte)
_ => HashCode.Combine(@this.TypeIndex)
};

[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static string ToString<T>(in T @this) where T: unmanaged, V2.IValueVariant<T, <#= Join(1, i, e => $"T{e}") #>>
=> @this.TypeIndexByte switch {
=> @this.TypeIndex switch {
<# for (var j = 1; j <= i; ++j) { #>
<#= j #> => @this.Item<#= j #>.ToString(),
<# } #>
Expand Down
Loading