Skip to content

Commit

Permalink
Open up InvalidDeserializeValueException (#196)
Browse files Browse the repository at this point in the history
Renames InvalidDeserializeValueException to DeserializeException and
unseals it. This will allow formats to define their own custom subtypes
of the exception.
  • Loading branch information
agocke authored Aug 29, 2024
1 parent 93c794a commit c41c144
Show file tree
Hide file tree
Showing 65 changed files with 112 additions and 103 deletions.
2 changes: 1 addition & 1 deletion perf/bench/SampleTypes.cs
Original file line number Diff line number Diff line change
Expand Up @@ -133,7 +133,7 @@ public partial record LocationWrap : IDeserialize<Location>

if (_r_assignedValid != 0b111111111)
{
throw new Serde.InvalidDeserializeValueException("Not all members were assigned");
throw Serde.DeserializeException.UnassignedMember();
}

var newType = new Benchmarks.Location()
Expand Down
8 changes: 4 additions & 4 deletions src/generator/Generator.Deserialize.cs
Original file line number Diff line number Diff line change
Expand Up @@ -92,12 +92,12 @@ private static MethodDeclarationSyntax GenerateEnumDeserializeMethod(
int index;
if ((index = de.TryReadIndex(serdeInfo, out var errorName)) == IDeserializeType.IndexNotFound)
{
throw new InvalidDeserializeValueException($"Unexpected value: {errorName}");
throw Serde.DeserializeException.UnknownMember(errorName!, serdeInfo);
}
return index switch {
{{string.Join("," + Utilities.NewLine, members
.Select((m, i) => $"{i} => {typeSyntax}.{m.Name}")) }},
_ => throw new InvalidDeserializeValueException($"Unexpected index: {index}")
_ => throw new InvalidOperationException($"Unexpected index: {index}")
};
}
""";
Expand Down Expand Up @@ -229,7 +229,7 @@ private static MethodDeclarationSyntax GenerateCustomDeserializeMethod(
}
var unknownMemberBehavior = SymbolUtilities.GetTypeOptions(type).DenyUnknownMembers
? $"""
throw new InvalidDeserializeValueException("Unexpected field or property name in type {type.Name}: '" + _l_errorName + "'");
throw Serde.DeserializeException.UnknownMember(_l_errorName!, {typeInfoLocalName});
"""
: "break;";
foreach (var i in skippedIndices)
Expand Down Expand Up @@ -340,7 +340,7 @@ private static string GenerateTypeCreation(
return $$"""
if (({{AssignedVarName}} & {{assignedMask}}) != {{assignedMask}})
{
throw new Serde.InvalidDeserializeValueException("Not all members were assigned");
throw Serde.DeserializeException.UnassignedMember();
}
var newType = new {{typeName}}({{parameters}}) {
{{assignments}}
Expand Down
30 changes: 19 additions & 11 deletions src/serde/IDeserialize.cs
Original file line number Diff line number Diff line change
Expand Up @@ -24,35 +24,43 @@ public interface IDeserialize<T> : ISerdeInfoProvider
/// Thrown from implementations of <see cref="IDeserializer" />. Indicates that an unexpected
/// value was seen in the input which cannot be converted to the target type.
/// </summary>
public sealed class InvalidDeserializeValueException : Exception
public class DeserializeException : Exception
{
public InvalidDeserializeValueException(string msg)
internal DeserializeException(string msg)
: base(msg)
{ }

public static DeserializeException UnassignedMember() => throw new DeserializeException("Not all members were assigned.");

public static DeserializeException UnknownMember(string name, ISerdeInfo info)
=> new DeserializeException($"Could not find member named '{name ?? "<null>"}' in type '{info.Name}'.");

public static DeserializeException WrongItemCount(int expected, int actual)
=> new DeserializeException($"Expected {expected} items, got {actual}.");
}

public interface IDeserializeVisitor<T>
{
string ExpectedTypeName { get; }
T VisitBool(bool b) => throw new InvalidDeserializeValueException("Expected type " + ExpectedTypeName);
T VisitBool(bool b) => throw new DeserializeException("Expected type " + ExpectedTypeName);
T VisitChar(char c) => VisitString(c.ToString());
T VisitByte(byte b) => VisitU64(b);
T VisitU16(ushort u16) => VisitU64(u16);
T VisitU32(uint u32) => VisitU64(u32);
T VisitU64(ulong u64) => throw new InvalidDeserializeValueException("Expected type " + ExpectedTypeName);
T VisitU64(ulong u64) => throw new DeserializeException("Expected type " + ExpectedTypeName);
T VisitSByte(sbyte b) => VisitI64(b);
T VisitI16(short i16) => VisitI64(i16);
T VisitI32(int i32) => VisitI64(i32);
T VisitI64(long i64) => throw new InvalidDeserializeValueException("Expected type " + ExpectedTypeName);
T VisitI64(long i64) => throw new DeserializeException("Expected type " + ExpectedTypeName);
T VisitFloat(float f) => VisitDouble(f);
T VisitDouble(double d) => throw new InvalidDeserializeValueException("Expected type " + ExpectedTypeName);
T VisitDecimal(decimal d) => throw new InvalidDeserializeValueException("Expected type " + ExpectedTypeName);
T VisitString(string s) => throw new InvalidDeserializeValueException("Expected type " + ExpectedTypeName);
T VisitUtf8Span(ReadOnlySpan<byte> s) => throw new InvalidDeserializeValueException("Expected type " + ExpectedTypeName);
T VisitDouble(double d) => throw new DeserializeException("Expected type " + ExpectedTypeName);
T VisitDecimal(decimal d) => throw new DeserializeException("Expected type " + ExpectedTypeName);
T VisitString(string s) => throw new DeserializeException("Expected type " + ExpectedTypeName);
T VisitUtf8Span(ReadOnlySpan<byte> s) => throw new DeserializeException("Expected type " + ExpectedTypeName);
T VisitEnumerable<D>(ref D d) where D : IDeserializeEnumerable
=> throw new InvalidDeserializeValueException("Expected type " + ExpectedTypeName);
=> throw new DeserializeException("Expected type " + ExpectedTypeName);
T VisitDictionary<D>(ref D d) where D : IDeserializeDictionary
=> throw new InvalidDeserializeValueException("Expected type " + ExpectedTypeName);
=> throw new DeserializeException("Expected type " + ExpectedTypeName);
T VisitNull() => throw new InvalidOperationException("Expected type " + ExpectedTypeName);
T VisitNotNull(IDeserializer d) => throw new InvalidOperationException("Expected type " + ExpectedTypeName);
}
Expand Down
4 changes: 2 additions & 2 deletions src/serde/Wrappers.Dictionary.cs
Original file line number Diff line number Diff line change
Expand Up @@ -52,13 +52,13 @@ public static Dictionary<TKey, TValue> Deserialize(IDeserializer deserializer)
{
if (!deCollection.TryReadValue<TValue, TValueWrap>(typeInfo, out var value))
{
throw new InvalidDeserializeValueException("Expected value, but reached end of collection.");
throw new DeserializeException("Expected value, but reached end of collection.");
}
dict.Add(key, value);
}
if (size >= 0 && size != dict.Count)
{
throw new InvalidDeserializeValueException($"Expected {size} items, found {dict.Count}");
throw new DeserializeException($"Expected {size} items, found {dict.Count}");
}
return dict;
}
Expand Down
6 changes: 3 additions & 3 deletions src/serde/Wrappers.List.cs
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ public static T[] Deserialize(IDeserializer deserializer)
{
if (!deCollection.TryReadValue<T, TWrap>(typeInfo, out var value))
{
throw new InvalidDeserializeValueException($"Expected array of size {size}, but only received {i} items");
throw new DeserializeException($"Expected array of size {size}, but only received {i} items");
}
array[i] = value;
}
Expand Down Expand Up @@ -116,7 +116,7 @@ public static List<T> Deserialize(IDeserializer deserializer)
}
if (size >= 0 && list.Count != size)
{
throw new InvalidDeserializeValueException($"Expected enumerable of size {size}, but only received {list.Count} items");
throw new DeserializeException($"Expected enumerable of size {size}, but only received {list.Count} items");
}
return list;
}
Expand Down Expand Up @@ -163,7 +163,7 @@ public static ImmutableArray<T> Deserialize(IDeserializer deserializer)
}
if (size >= 0 && builder.Count != size)
{
throw new InvalidDeserializeValueException($"Expected {size} items, found {builder.Count}");
throw new DeserializeException($"Expected {size} items, found {builder.Count}");
}
return builder.ToImmutable();
}
Expand Down
2 changes: 1 addition & 1 deletion src/serde/Wrappers.cs
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@ private char GetChar(string s)
{
return s[0];
}
throw new InvalidDeserializeValueException("Expected type " + ExpectedTypeName);
throw new DeserializeException("Expected type " + ExpectedTypeName);
}
char IDeserializeVisitor<char>.VisitUtf8Span(Utf8Span s)
{
Expand Down
16 changes: 8 additions & 8 deletions src/serde/json/JsonDeserializer.cs
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ public T DeserializeAny<T>(IDeserializeVisitor<T> v)
break;

default:
throw new InvalidDeserializeValueException($"Could not deserialize '{reader.TokenType}");
throw new DeserializeException($"Could not deserialize '{reader.TokenType}");
}
return result;
}
Expand All @@ -80,7 +80,7 @@ public T DeserializeDictionary<T>(IDeserializeVisitor<T> v)

if (reader.TokenType != JsonTokenType.StartObject)
{
throw new InvalidDeserializeValueException("Expected object start");
throw new DeserializeException("Expected object start");
}

var map = new DeDictionary(this);
Expand All @@ -100,7 +100,7 @@ public IDeserializeCollection DeserializeCollection(ISerdeInfo typeInfo)
if (typeInfo.Kind == InfoKind.Dictionary && reader.TokenType != JsonTokenType.StartObject
|| typeInfo.Kind == InfoKind.Enumerable && reader.TokenType != JsonTokenType.StartArray)
{
throw new InvalidDeserializeValueException("Expected object start");
throw new DeserializeException("Expected object start");
}

return new DeCollection(this);
Expand All @@ -125,13 +125,13 @@ public bool TryReadValue<T, D>(ISerdeInfo typeInfo, [MaybeNullWhen(false)] out T
case JsonTokenType.EndArray:
if (typeInfo.Kind != InfoKind.Enumerable)
{
throw new InvalidDeserializeValueException($"Unexpected end of array in type kind: {typeInfo.Kind}");
throw new DeserializeException($"Unexpected end of array in type kind: {typeInfo.Kind}");
}
break;
case JsonTokenType.EndObject:
if (typeInfo.Kind != InfoKind.Dictionary)
{
throw new InvalidDeserializeValueException($"Unexpected end of object in type kind: {typeInfo.Kind}");
throw new DeserializeException($"Unexpected end of object in type kind: {typeInfo.Kind}");
}
break;
default:
Expand Down Expand Up @@ -171,7 +171,7 @@ public T DeserializeEnumerable<T>(IDeserializeVisitor<T> v)

if (reader.TokenType != JsonTokenType.StartArray)
{
throw new InvalidDeserializeValueException("Expected array start");
throw new DeserializeException("Expected array start");
}

var enumerable = new DeEnumerable(this);
Expand Down Expand Up @@ -311,7 +311,7 @@ public IDeserializeType DeserializeType(ISerdeInfo fieldMap)

if (reader.TokenType != JsonTokenType.StartObject)
{
throw new InvalidDeserializeValueException("Expected object start");
throw new DeserializeException("Expected object start");
}
}
else if (fieldMap.Kind != InfoKind.Enum)
Expand Down Expand Up @@ -422,7 +422,7 @@ public static void ReadOrThrow(ref this Utf8JsonReader reader)
{
if (!reader.Read())
{
throw new InvalidDeserializeValueException("Unexpected end of stream");
throw new DeserializeException("Unexpected end of stream");
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,15 +17,15 @@ partial struct ColorEnumWrap : Serde.IDeserialize<Serde.Test.AllInOne.ColorEnum>
int index;
if ((index = de.TryReadIndex(serdeInfo, out var errorName)) == IDeserializeType.IndexNotFound)
{
throw new InvalidDeserializeValueException($"Unexpected value: {errorName}");
throw Serde.DeserializeException.UnknownMember(errorName!, serdeInfo);
}

return index switch
{
0 => Serde.Test.AllInOne.ColorEnum.Red,
1 => Serde.Test.AllInOne.ColorEnum.Blue,
2 => Serde.Test.AllInOne.ColorEnum.Green,
_ => throw new InvalidDeserializeValueException($"Unexpected index: {index}")};
_ => throw new InvalidOperationException($"Unexpected index: {index}")};
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -107,7 +107,7 @@ partial record AllInOne : Serde.IDeserialize<Serde.Test.AllInOne>

if ((_r_assignedValid & 0b1111011111111111) != 0b1111011111111111)
{
throw new Serde.InvalidDeserializeValueException("Not all members were assigned");
throw Serde.DeserializeException.UnassignedMember();
}

var newType = new Serde.Test.AllInOne()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ static C Serde.IDeserialize<C>.Deserialize(IDeserializer deserializer)

if ((_r_assignedValid & 0b1111) != 0b1111)
{
throw new Serde.InvalidDeserializeValueException("Not all members were assigned");
throw Serde.DeserializeException.UnassignedMember();
}

var newType = new C()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,14 +13,14 @@ static ColorByte IDeserialize<ColorByte>.Deserialize(IDeserializer deserializer)
int index;
if ((index = de.TryReadIndex(serdeInfo, out var errorName)) == IDeserializeType.IndexNotFound)
{
throw new InvalidDeserializeValueException($"Unexpected value: {errorName}");
throw Serde.DeserializeException.UnknownMember(errorName!, serdeInfo);
}

return index switch
{
0 => ColorByte.Red,
1 => ColorByte.Green,
2 => ColorByte.Blue,
_ => throw new InvalidDeserializeValueException($"Unexpected index: {index}")};
_ => throw new InvalidOperationException($"Unexpected index: {index}")};
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -13,14 +13,14 @@ static ColorInt IDeserialize<ColorInt>.Deserialize(IDeserializer deserializer)
int index;
if ((index = de.TryReadIndex(serdeInfo, out var errorName)) == IDeserializeType.IndexNotFound)
{
throw new InvalidDeserializeValueException($"Unexpected value: {errorName}");
throw Serde.DeserializeException.UnknownMember(errorName!, serdeInfo);
}

return index switch
{
0 => ColorInt.Red,
1 => ColorInt.Green,
2 => ColorInt.Blue,
_ => throw new InvalidDeserializeValueException($"Unexpected index: {index}")};
_ => throw new InvalidOperationException($"Unexpected index: {index}")};
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -13,14 +13,14 @@ static ColorLong IDeserialize<ColorLong>.Deserialize(IDeserializer deserializer)
int index;
if ((index = de.TryReadIndex(serdeInfo, out var errorName)) == IDeserializeType.IndexNotFound)
{
throw new InvalidDeserializeValueException($"Unexpected value: {errorName}");
throw Serde.DeserializeException.UnknownMember(errorName!, serdeInfo);
}

return index switch
{
0 => ColorLong.Red,
1 => ColorLong.Green,
2 => ColorLong.Blue,
_ => throw new InvalidDeserializeValueException($"Unexpected index: {index}")};
_ => throw new InvalidOperationException($"Unexpected index: {index}")};
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -13,14 +13,14 @@ static ColorULong IDeserialize<ColorULong>.Deserialize(IDeserializer deserialize
int index;
if ((index = de.TryReadIndex(serdeInfo, out var errorName)) == IDeserializeType.IndexNotFound)
{
throw new InvalidDeserializeValueException($"Unexpected value: {errorName}");
throw Serde.DeserializeException.UnknownMember(errorName!, serdeInfo);
}

return index switch
{
0 => ColorULong.Red,
1 => ColorULong.Green,
2 => ColorULong.Blue,
_ => throw new InvalidDeserializeValueException($"Unexpected index: {index}")};
_ => throw new InvalidOperationException($"Unexpected index: {index}")};
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ partial record struct OptsWrap : Serde.IDeserialize<System.Runtime.InteropServic

if ((_r_assignedValid & 0b1111) != 0b1111)
{
throw new Serde.InvalidDeserializeValueException("Not all members were assigned");
throw Serde.DeserializeException.UnassignedMember();
}

var newType = new System.Runtime.InteropServices.ComTypes.BIND_OPTS()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ static S Serde.IDeserialize<S>.Deserialize(IDeserializer deserializer)

if ((_r_assignedValid & 0b1) != 0b1)
{
throw new Serde.InvalidDeserializeValueException("Not all members were assigned");
throw Serde.DeserializeException.UnassignedMember();
}

var newType = new S()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ static ArrayField Serde.IDeserialize<ArrayField>.Deserialize(IDeserializer deser

if ((_r_assignedValid & 0b1) != 0b1)
{
throw new Serde.InvalidDeserializeValueException("Not all members were assigned");
throw Serde.DeserializeException.UnassignedMember();
}

var newType = new ArrayField()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ static SetToNull Serde.IDeserialize<SetToNull>.Deserialize(IDeserializer deseria

if ((_r_assignedValid & 0b101) != 0b101)
{
throw new Serde.InvalidDeserializeValueException("Not all members were assigned");
throw Serde.DeserializeException.UnassignedMember();
}

var newType = new SetToNull()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ partial record struct Wrap : Serde.IDeserialize<System.Runtime.InteropServices.C

if ((_r_assignedValid & 0b1111) != 0b1111)
{
throw new Serde.InvalidDeserializeValueException("Not all members were assigned");
throw Serde.DeserializeException.UnassignedMember();
}

var newType = new System.Runtime.InteropServices.ComTypes.BIND_OPTS()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ static Rgb Serde.IDeserialize<Rgb>.Deserialize(IDeserializer deserializer)

if ((_r_assignedValid & 0b11) != 0b11)
{
throw new Serde.InvalidDeserializeValueException("Not all members were assigned");
throw Serde.DeserializeException.UnassignedMember();
}

var newType = new Rgb()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ static Rgb Serde.IDeserialize<Rgb>.Deserialize(IDeserializer deserializer)

if ((_r_assignedValid & 0b101) != 0b101)
{
throw new Serde.InvalidDeserializeValueException("Not all members were assigned");
throw Serde.DeserializeException.UnassignedMember();
}

var newType = new Rgb()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ static Rgb Serde.IDeserialize<Rgb>.Deserialize(IDeserializer deserializer)

if ((_r_assignedValid & 0b111) != 0b111)
{
throw new Serde.InvalidDeserializeValueException("Not all members were assigned");
throw Serde.DeserializeException.UnassignedMember();
}

var newType = new Rgb()
Expand Down
Loading

0 comments on commit c41c144

Please sign in to comment.