Skip to content

Commit

Permalink
Fix exception expressions
Browse files Browse the repository at this point in the history
  • Loading branch information
afxres committed Jul 3, 2024
1 parent ecf4e78 commit 4c11c43
Show file tree
Hide file tree
Showing 9 changed files with 52 additions and 35 deletions.
4 changes: 2 additions & 2 deletions code/Binary.Tests.FSharp/Contexts/ConverterModuleTests.fs
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ type ConverterModuleTests() =
[<MemberData("Data Invalid Converter")>]
member __.``Get Generic Argument (invalid converter instance)`` (converter : IConverter) =
let error = Assert.Throws<ArgumentException>(fun () -> Converter.GetGenericArgument converter |> ignore)
let message = sprintf "Can not get generic argument, '%O' is not a subclass of '%O'" (converter.GetType()) typedefof<Converter<_>>
let message = sprintf "Invalid converter instance, '%O' is not a subclass of '%O'" (converter.GetType()) typedefof<Converter<_>>
Assert.Null(error.ParamName)
Assert.Equal(message, error.Message)
()
Expand Down Expand Up @@ -113,7 +113,7 @@ type ConverterModuleTests() =
[<MemberData("Data Invalid Converter")>]
member __.``Get Method (invalid converter instance)`` (converter : IConverter) =
let error = Assert.Throws<ArgumentException>(fun () -> Converter.GetMethod(converter, String.Empty) |> ignore)
let message = sprintf "Can not get generic argument, '%O' is not a subclass of '%O'" (converter.GetType()) typedefof<Converter<_>>
let message = sprintf "Invalid converter instance, '%O' is not a subclass of '%O'" (converter.GetType()) typedefof<Converter<_>>
Assert.Null(error.ParamName)
Assert.Equal(message, error.Message)
()
Expand Down
2 changes: 1 addition & 1 deletion code/Binary.Tests.FSharp/Contexts/GeneratorTests.fs
Original file line number Diff line number Diff line change
Expand Up @@ -236,7 +236,7 @@ let ``Bad Creator (item type mismatch)`` () =
let ``Bad Creator (not a subclass)`` () =
let generator = Generator.CreateDefaultBuilder().AddConverterCreator(BadConverterCreatorInterfaceImplementation()).Build()
let error = Assert.Throws<ArgumentException>(fun () -> generator.GetConverter typeof<BadType> |> ignore)
let message = $"Can not get generic argument, '{typeof<BadConverterInterfaceImplementation>}' is not a subclass of '{typedefof<Converter<_>>}'"
let message = $"Invalid converter instance, '{typeof<BadConverterInterfaceImplementation>}' is not a subclass of '{typedefof<Converter<_>>}'"
Assert.Equal(message, error.Message)
()

Expand Down
7 changes: 1 addition & 6 deletions code/Binary.Tests.FSharp/Sequence/EnumerableDecodeTests.fs
Original file line number Diff line number Diff line change
Expand Up @@ -160,12 +160,7 @@ let Test (enumerable : 'a) (expected : 'b) (encoderName : string) =
let encoderActualName = encoder.Method.DeclaringType.Name
Assert.Equal(encoderName, encoderActualName)
let decoder = converterType.GetField("decode", BindingFlags.Instance ||| BindingFlags.NonPublic).GetValue converter |> unbox<Delegate>
let decoderMethod = decoder.Method
// anonymous type
Assert.Contains("<", decoderMethod.DeclaringType.Name)
Assert.Contains(">", decoderMethod.DeclaringType.Name)
Assert.Contains("<", decoderMethod.Name)
Assert.Contains(">", decoderMethod.Name)
Assert.Null decoder

let buffer = converter.Encode enumerable
let target = generator.Encode expected
Expand Down
14 changes: 8 additions & 6 deletions code/Binary/Converter.Static.cs
Original file line number Diff line number Diff line change
Expand Up @@ -12,18 +12,20 @@ public static partial class Converter
public static Type GetGenericArgument(IConverter converter)
{
ArgumentNullException.ThrowIfNull(converter);
if (converter is IConverterMetadata metadata)
return metadata.GetGenericArgument();
return ThrowHelper.ThrowNotConverter<Type>(converter.GetType());
var metadata = converter as IConverterMetadata;
if (metadata is null)
ThrowHelper.ThrowNotConverter(converter.GetType());
return metadata.GetGenericArgument();
}

public static MethodInfo GetMethod(IConverter converter, string name)
{
ArgumentNullException.ThrowIfNull(name);
ArgumentNullException.ThrowIfNull(converter);
if (converter is IConverterMetadata metadata)
return metadata.GetMethod(name);
return ThrowHelper.ThrowNotConverter<MethodInfo>(converter.GetType());
var metadata = converter as IConverterMetadata;
if (metadata is null)
ThrowHelper.ThrowNotConverter(converter.GetType());
return metadata.GetMethod(name);
}

public static void Encode(scoped Span<byte> span, int number, out int bytesWritten)
Expand Down
8 changes: 6 additions & 2 deletions code/Binary/Creators/NullableConverter.cs
Original file line number Diff line number Diff line change
Expand Up @@ -35,14 +35,18 @@ public override void EncodeAuto(ref Allocator allocator, T? item)
var head = Converter.Decode(ref body);
if (head is Some)
return this.converter.Decode(in body);
return head is None ? null : ThrowHelper.ThrowNullableTagInvalid<T>(head);
if (head is not None)
ThrowHelper.ThrowNullableTagInvalid<T>(head);
return null;
}

public override T? DecodeAuto(ref ReadOnlySpan<byte> span)
{
var head = Converter.Decode(ref span);
if (head is Some)
return this.converter.DecodeAuto(ref span);
return head is None ? null : ThrowHelper.ThrowNullableTagInvalid<T>(head);
if (head is not None)
ThrowHelper.ThrowNullableTagInvalid<T>(head);
return null;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -9,17 +9,20 @@ internal sealed class NamedObjectDelegateConverter<T>(Converter<string> converte
{
private readonly AllocatorAction<T> encode = encode;

private readonly NamedObjectDecodeDelegate<T> decode = decode ?? (_ => ThrowHelper.ThrowNoSuitableConstructor<T>());

public override T Decode(NamedObjectParameter parameter)
{
return this.decode.Invoke(parameter);
}
private readonly NamedObjectDecodeDelegate<T>? decode = decode;

public override void Encode(ref Allocator allocator, T? item)
{
if (item is null)
return;
this.encode.Invoke(ref allocator, item);
}

public override T Decode(NamedObjectParameter parameter)
{
var decode = this.decode;
if (decode is null)
ThrowHelper.ThrowNoSuitableConstructor<T>();
return decode.Invoke(parameter);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,17 +2,16 @@

using Mikodev.Binary.Internal.Metadata;
using System;
using System.Diagnostics;

internal sealed class TupleObjectDelegateConverter<T>(AllocatorAction<T> encode, AllocatorAction<T> encodeAuto, DecodeDelegate<T>? decode, DecodeDelegate<T>? decodeAuto, int length) : Converter<T>(length)
{
private readonly AllocatorAction<T> encode = encode;

private readonly AllocatorAction<T> encodeAuto = encodeAuto;

private readonly DecodeDelegate<T> decode = decode ?? ((ref ReadOnlySpan<byte> _) => ThrowHelper.ThrowNoSuitableConstructor<T>());
private readonly DecodeDelegate<T>? decode = decode;

private readonly DecodeDelegate<T> decodeAuto = decodeAuto ?? ((ref ReadOnlySpan<byte> _) => ThrowHelper.ThrowNoSuitableConstructor<T>());
private readonly DecodeDelegate<T>? decodeAuto = decodeAuto;

public override void Encode(ref Allocator allocator, T? item)
{
Expand All @@ -30,13 +29,18 @@ public override void EncodeAuto(ref Allocator allocator, T? item)

public override T Decode(in ReadOnlySpan<byte> span)
{
Debug.Assert(this.decode is not null);
var body = span;
return this.decode.Invoke(ref body);
var decode = this.decode;
if (decode is null)
ThrowHelper.ThrowNoSuitableConstructor<T>();
return decode.Invoke(ref body);
}

public override T DecodeAuto(ref ReadOnlySpan<byte> span)
{
return this.decodeAuto.Invoke(ref span);
var decodeAuto = this.decodeAuto;
if (decodeAuto is null)
ThrowHelper.ThrowNoSuitableConstructor<T>();
return decodeAuto.Invoke(ref span);
}
}
15 changes: 12 additions & 3 deletions code/Binary/Internal.Sequence/SequenceConverter.cs
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,18 @@ internal sealed class SequenceConverter<T>(AllocatorAction<T?> encode, DecodePas
{
private readonly AllocatorAction<T?> encode = encode;

private readonly DecodePassSpanDelegate<T> decode = decode ?? (_ => ThrowHelper.ThrowNoSuitableConstructor<T>());
private readonly DecodePassSpanDelegate<T>? decode = decode;

public override void Encode(ref Allocator allocator, T? item) => this.encode.Invoke(ref allocator, item);
public override void Encode(ref Allocator allocator, T? item)
{
this.encode.Invoke(ref allocator, item);
}

public override T Decode(in ReadOnlySpan<byte> span) => this.decode.Invoke(span);
public override T Decode(in ReadOnlySpan<byte> span)
{
var decode = this.decode;
if (decode is null)
ThrowHelper.ThrowNoSuitableConstructor<T>();
return decode.Invoke(span);
}
}
6 changes: 3 additions & 3 deletions code/Binary/Internal/ThrowHelper.cs
Original file line number Diff line number Diff line change
Expand Up @@ -38,11 +38,11 @@ internal static class ThrowHelper
internal static void ThrowAmbiguousMembers(string memberName, Type type) => throw new ArgumentException($"Get members error, ambiguous members detected, member name: {memberName}, type: {type}");

[DoesNotReturn]
internal static T ThrowNotConverter<T>(Type type) => throw new ArgumentException($"Can not get generic argument, '{type}' is not a subclass of '{typeof(Converter<>)}'");
internal static void ThrowNotConverter(Type type) => throw new ArgumentException($"Invalid converter instance, '{type}' is not a subclass of '{typeof(Converter<>)}'");

[DoesNotReturn]
internal static T ThrowNoSuitableConstructor<T>() => throw new NotSupportedException($"No suitable constructor found, type: {typeof(T)}");
internal static void ThrowNoSuitableConstructor<T>() => throw new NotSupportedException($"No suitable constructor found, type: {typeof(T)}");

[DoesNotReturn]
internal static T? ThrowNullableTagInvalid<T>(int tag) where T : struct => throw new ArgumentException($"Invalid nullable tag '{tag}', type: {typeof(T?)}");
internal static void ThrowNullableTagInvalid<T>(int tag) where T : struct => throw new ArgumentException($"Invalid nullable tag '{tag}', type: {typeof(T?)}");
}

0 comments on commit 4c11c43

Please sign in to comment.