Skip to content

Commit

Permalink
Merge pull request #8 from hikarin522/develop
Browse files Browse the repository at this point in the history
v0.4.0
  • Loading branch information
hikarin522 authored Nov 30, 2022
2 parents 92bb428 + 2c18c19 commit e2113be
Show file tree
Hide file tree
Showing 24 changed files with 126 additions and 48 deletions.
2 changes: 1 addition & 1 deletion .config/dotnet-tools.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
"isRoot": true,
"tools": {
"dotnet-t4": {
"version": "2.2.1",
"version": "2.3.1",
"commands": [
"t4"
]
Expand Down
2 changes: 1 addition & 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.3.4</Version>
<Version>0.4.0</Version>
<Authors>hikarin522</Authors>
<Copyright>(c) 2022 hikarin522.</Copyright>
<PackageLicenseExpression>MIT</PackageLicenseExpression>
Expand Down
34 changes: 33 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ C# source generator to generate efficient and type-safe variant types for unmana
## Usage

```cs
using System.ValueVariant;
using ValueVariant;

[ValueVariant]
public readonly partial struct SampleVariant: IValueVariant<SampleVariant, int, long, float> { }
Expand Down Expand Up @@ -60,3 +60,35 @@ readonly partial struct SampleVariant: IEquatable<SampleVariant>
...
}
```

## Type conversion between variant types

```cs
[ValueVariant]
public readonly partial struct SampleVariant1 : IValueVariant<SampleVariant1, int, Guid, DateTime>
{
public static explicit operator SampleVariant1(SampleVariant2 value)
=> value.TryCast(out var result) ? result : throw new InvalidCastException();

public readonly bool TryCast(out SampleVariant2 result)
{
if (this == default) { result = default; return true; }
this.Accept(SampleVariant2.DefaultConverter.Instance, out result);
return result != default;
}
}

[ValueVariant]
public readonly partial struct SampleVariant2 : IValueVariant<SampleVariant2, Guid, DateTime, int, long, bool>
{
public static explicit operator SampleVariant2(SampleVariant1 value)
=> value.TryCast(out var result) ? result : throw new InvalidCastException();

public readonly bool TryCast(out SampleVariant1 result)
{
if (this == default) { result = default; return true; }
this.Accept(SampleVariant1.DefaultConverter<long, bool>.Instance, out result);
return result != default;
}
}
```
3 changes: 1 addition & 2 deletions ValueVariant.Generator/ValueVariantGenerator.cs
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.ValueVariant;

using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.CSharp.Syntax;
Expand Down Expand Up @@ -44,7 +43,7 @@ public void Execute(GeneratorExecutionContext context)
if (attr is null) return (symbol, attr, itf: default(INamedTypeSymbol?));

var itf = symbol.Interfaces
.SingleOrDefault(e => e.ToString().StartsWith("System.ValueVariant.IValueVariant<") && e.TypeArguments.Length >= 2);
.SingleOrDefault(e => e.ToString().StartsWith("ValueVariant.IValueVariant<") && e.TypeArguments.Length >= 2);

return (symbol, attr, itf);
}).Where(e => e.attr is not null && e.itf is not null).Select(e => (e.symbol, e.attr!, e.itf!));
Expand Down
1 change: 0 additions & 1 deletion ValueVariant.Generator/ValueVariantTemplate.partial.cs
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@

using System.Linq;
using System.ValueVariant;

namespace ValueVariant.Generator;

Expand Down
26 changes: 23 additions & 3 deletions ValueVariant.Generator/ValueVariantTemplate.tt
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
<#@ import namespace="System.Linq" #>
<#@ import namespace="System.Text" #>
<#@ import namespace="System.Collections.Generic" #>
<#@ import namespace="System.ValueVariant" #>
<#@ import namespace="ValueVariant" #>
<#@ include file="../Const.t4" #>
// <auto-generated>
// THIS (.cs) FILE IS GENERATED BY ValueVariant.Generator. DO NOT CHANGE IT.
Expand All @@ -27,7 +27,7 @@ using System.Diagnostics.CodeAnalysis;

namespace <#= Namespace #>
{
using V2 = global::System.ValueVariant;
using V2 = global::ValueVariant;

using T = global::<#= FullName #>;

Expand Down Expand Up @@ -155,12 +155,32 @@ namespace <#= Namespace #>
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 readonly struct DefaultConverter : IFuncVisitor<T>
public class DefaultConverter : IFuncVisitor<T>
{
public static DefaultConverter Instance { get; } = new DefaultConverter();

<# for (var i = 1; i <= Count; ++i ) { #>
public T Visit(in T<#= i #> value) => value;
<# } #>
}

public class DefaultConverter<TEx1> : DefaultConverter, V2.IValueVariantFuncVisitor<TEx1, T>
where TEx1 : unmanaged
{
public static new DefaultConverter<TEx1> Instance { get; } = new DefaultConverter<TEx1>();

public T Visit(in TEx1 value) => default;
}
<# for (var i = 2; i <= 4; ++i ) { #>

public class DefaultConverter<<#= Join(1, i, e => $"TEx{e}") #>> : DefaultConverter<<#= Join(1, i - 1, e => $"TEx{e}") #>>, V2.IValueVariantFuncVisitor<TEx<#= i #>, T>
<#= string.Join(" ", Range(1, i, e => $"where TEx{e}: unmanaged")) #>
{
public static new DefaultConverter<<#= Join(1, i, e => $"TEx{e}") #>> Instance { get; } = new DefaultConverter<<#= Join(1, i, e => $"TEx{e}") #>>();

public T Visit(in TEx<#= i #> value) => default;
}
<# } #>
<# if (Options.HasFlag(ValueVariantGenerateOptions.MessagePackFormatter)) { #>

private sealed class MessagePackFormatter : IMessagePackFormatter<T>
Expand Down
43 changes: 32 additions & 11 deletions ValueVariant.Test/TestVariant.cs
Original file line number Diff line number Diff line change
@@ -1,25 +1,46 @@
using System;

using System.ValueVariant;

using Variant.Test;

namespace ValueVariant.Test;

[ValueVariant(ValueVariantGenerateOptions.MessagePackFormatter)]
public readonly partial struct TestVariant : IValueVariant<TestVariant, int, TestStruct<Guid>, DateTime> { }
public readonly partial struct TestVariant : IValueVariant<TestVariant, int, TestStruct<Guid>, DateTime>
{
public static explicit operator TestVariant(TestVariant2 value)
=> value.TryCast(out var result) ? result : throw new InvalidCastException();

public readonly bool TryCast(out TestVariant2 result)
{
if (this == default) { result = default; return true; }
this.Accept(TestVariant2.DefaultConverter.Instance, out result);
return result != default;
}
}

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

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

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

public Type Visit(in DateTime value)
=> typeof(DateTime);
public Type Visit(in long value) => typeof(long);

public Type Visit(in bool value) => typeof(bool);
}

[ValueVariant]
public readonly partial struct TestVariant2 : IValueVariant<TestVariant2, TestStruct<Guid>, DateTime, int> { }
public readonly partial struct TestVariant2 : IValueVariant<TestVariant2, TestStruct<Guid>, DateTime, int, long, bool>
{
public static explicit operator TestVariant2(TestVariant value)
=> value.TryCast(out var result) ? result : throw new InvalidCastException();

public readonly bool TryCast(out TestVariant result)
{
if (this == default) { result = default; return true; }
this.Accept(TestVariant.DefaultConverter<long, bool>.Instance, out result);
return result != default;
}
}
11 changes: 7 additions & 4 deletions ValueVariant.Test/UnitTest1.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
using System;
using System.ValueVariant;

using MessagePack;

Expand All @@ -20,21 +19,25 @@ public void Test1()

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

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

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

v2 = default(long);
Assert.Equal(typeof(long), v2.Accept(new TestVariantVisitor()));
Assert.Throws<InvalidCastException>(() => (TestVariant)v2);
}

[Fact]
Expand Down
6 changes: 3 additions & 3 deletions ValueVariant.Test/ValueVariant.Test.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -7,13 +7,13 @@

<ItemGroup>
<PackageReference Include="MessagePack" Version="2.3.85" />
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.2.0" />
<PackageReference Include="xunit" Version="2.4.1" />
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.4.0" />
<PackageReference Include="xunit" Version="2.4.2" />
<PackageReference Include="xunit.runner.visualstudio" Version="2.4.5">
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
<PrivateAssets>all</PrivateAssets>
</PackageReference>
<PackageReference Include="coverlet.collector" Version="3.1.2">
<PackageReference Include="coverlet.collector" Version="3.2.0">
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
<PrivateAssets>all</PrivateAssets>
</PackageReference>
Expand Down
2 changes: 1 addition & 1 deletion ValueVariant/Details/IValueVariant.cs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@

using System.Runtime.CompilerServices;

namespace System.ValueVariant.Details;
namespace ValueVariant.Details;

public interface IValueVariant
{
Expand Down
2 changes: 1 addition & 1 deletion ValueVariant/Details/IValueVariantIndex.tt
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@

using System.Runtime.CompilerServices;

namespace System.ValueVariant.Details;
namespace ValueVariant.Details;
<# for (var i = 1; i <= MaxTypeParam; ++i) { #>

public interface IValueVariantIndex<#= i #><T>: IValueVariant where T: unmanaged
Expand Down
2 changes: 1 addition & 1 deletion ValueVariant/Details/IValueVariantT.tt
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
// </auto-generated>
#nullable enable

namespace System.ValueVariant.Details;
namespace ValueVariant.Details;
<# for (var i = 1; i <= MaxTypeParam; ++i) { #>

public interface IValueVariant<<#= Join(1, i, e => $"T{e}") #>>:
Expand Down
3 changes: 2 additions & 1 deletion ValueVariant/Details/Throw.cs
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
using System;

#if NETSTANDARD2_1_OR_GREATER
using System.Diagnostics.CodeAnalysis;
#endif

namespace System.ValueVariant.Details;
namespace ValueVariant.Details;

internal static class Throw
{
Expand Down
4 changes: 2 additions & 2 deletions ValueVariant/Details/ValueVariantT.ActionVisitor.tt
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,9 @@

using System.Runtime.CompilerServices;

using V2 = System.ValueVariant;
using V2 = ValueVariant;

namespace System.ValueVariant.Details;
namespace ValueVariant.Details;
<# for (var i = 1; i <= MaxTypeParam; ++i) { #>

partial class ValueVariant<<#= Join(1, i, e => $"T{e}") #>>
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 @@ -12,9 +12,9 @@

using System.Runtime.CompilerServices;

using V2 = System.ValueVariant;
using V2 = ValueVariant;

namespace System.ValueVariant.Details;
namespace ValueVariant.Details;
<# for (var i = 1; i <= MaxTypeParam; ++i) { #>

partial class ValueVariant<<#= Join(1, i, e => $"T{e}") #>>
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 @@ -12,9 +12,9 @@

using System.Runtime.CompilerServices;

using V2 = System.ValueVariant;
using V2 = ValueVariant;

namespace System.ValueVariant.Details;
namespace ValueVariant.Details;
<# for (var i = 1; i <= MaxTypeParam; ++i) { #>

partial class ValueVariant<<#= Join(1, i, e => $"T{e}") #>>
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 @@ -12,9 +12,9 @@

using System.Runtime.CompilerServices;

using V2 = System.ValueVariant;
using V2 = ValueVariant;

namespace System.ValueVariant.Details;
namespace ValueVariant.Details;
<# for (var i = 1; i <= MaxTypeParam; ++i) { #>

partial class ValueVariant<<#= Join(1, i, e => $"T{e}") #>>
Expand Down
5 changes: 3 additions & 2 deletions ValueVariant/Details/ValueVariantT.IEquatable.tt
Original file line number Diff line number Diff line change
Expand Up @@ -10,12 +10,13 @@
// </auto-generated>
#nullable enable

using System;
using System.Collections.Generic;
using System.Runtime.CompilerServices;

using V2 = System.ValueVariant;
using V2 = ValueVariant;

namespace System.ValueVariant.Details;
namespace ValueVariant.Details;
<# for (var i = 1; i <= MaxTypeParam; ++i) { #>

partial class ValueVariant<<#= Join(1, i, e => $"T{e}") #>>
Expand Down
2 changes: 1 addition & 1 deletion ValueVariant/Details/ValueVariantT.tt
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
// </auto-generated>
#nullable enable

namespace System.ValueVariant.Details;
namespace ValueVariant.Details;
<# for (var i = 1; i <= MaxTypeParam; ++i) { #>

public static partial class ValueVariant<<#= Join(1, i, e => $"T{e}") #>> <#= string.Join(" ", Range(1, i, e => $"where T{e}: unmanaged")) #> { }
Expand Down
2 changes: 1 addition & 1 deletion ValueVariant/IValueVariantT.tt
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
// </auto-generated>
#nullable enable

namespace System.ValueVariant;
namespace ValueVariant;
<# for (var i = 1; i <= MaxTypeParam; ++i) { #>

public interface IValueVariant<T, <#= Join(1, i, e => $"T{e}") #>>:
Expand Down
2 changes: 1 addition & 1 deletion ValueVariant/IValueVariantVisitor.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@

namespace System.ValueVariant;
namespace ValueVariant;

public interface IValueVariantActionVisitor<T> where T: unmanaged
{
Expand Down
2 changes: 1 addition & 1 deletion ValueVariant/ValueVariant.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

<PropertyGroup>
<TargetFrameworks>netstandard2.0;netstandard2.1</TargetFrameworks>
<RootNamespace>System.ValueVariant</RootNamespace>
<RootNamespace>ValueVariant</RootNamespace>
<IsPackable>true</IsPackable>
</PropertyGroup>

Expand Down
3 changes: 2 additions & 1 deletion ValueVariant/ValueVariantAttribute.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
using System;

namespace System.ValueVariant
namespace ValueVariant
{
[Flags]
public enum ValueVariantGenerateOptions
Expand Down
Loading

0 comments on commit e2113be

Please sign in to comment.