Commit e305e56c authored by Chris Bacon's avatar Chris Bacon

C#: Optimize parsing of some primitive and wrapper types

parent 4668a332
...@@ -507,7 +507,7 @@ namespace Google.Protobuf ...@@ -507,7 +507,7 @@ namespace Google.Protobuf
{ {
var nestedCodec = WrapperCodecs.GetCodec<T>(); var nestedCodec = WrapperCodecs.GetCodec<T>();
return new FieldCodec<T?>( return new FieldCodec<T?>(
input => WrapperCodecs.Read<T>(input, nestedCodec), WrapperCodecs.GetReader<T>(),
(output, value) => WrapperCodecs.Write<T>(output, value.Value, nestedCodec), (output, value) => WrapperCodecs.Write<T>(output, value.Value, nestedCodec),
(CodedInputStream i, ref T? v) => v = WrapperCodecs.Read<T>(i, nestedCodec), (CodedInputStream i, ref T? v) => v = WrapperCodecs.Read<T>(i, nestedCodec),
(ref T? v, T? v2) => { if (v2.HasValue) { v = v2; } return v.HasValue; }, (ref T? v, T? v2) => { if (v2.HasValue) { v = v2; } return v.HasValue; },
...@@ -539,6 +539,22 @@ namespace Google.Protobuf ...@@ -539,6 +539,22 @@ namespace Google.Protobuf
{ typeof(ByteString), ForBytes(WireFormat.MakeTag(WrappersReflection.WrapperValueFieldNumber, WireFormat.WireType.LengthDelimited)) } { typeof(ByteString), ForBytes(WireFormat.MakeTag(WrappersReflection.WrapperValueFieldNumber, WireFormat.WireType.LengthDelimited)) }
}; };
private static readonly Dictionary<System.Type, Func<object>> Readers = new Dictionary<System.Type, Func<object>>
{
// TODO: Provide more optimized readers.
{ typeof(bool), null },
{ typeof(int), null },
{ typeof(long), () => (Func<CodedInputStream, long?>)CodedInputStream.ReadInt64Wrapper },
{ typeof(uint), null },
{ typeof(ulong), null },
{ typeof(float), null },
{ typeof(double), () => BitConverter.IsLittleEndian ?
(Func<CodedInputStream, double?>)CodedInputStream.ReadDoubleWrapperLittleEndian :
(Func<CodedInputStream, double?>)CodedInputStream.ReadDoubleWrapperBigEndian },
{ typeof(string), null },
{ typeof(ByteString), null },
};
/// <summary> /// <summary>
/// Returns a field codec which effectively wraps a value of type T in a message. /// Returns a field codec which effectively wraps a value of type T in a message.
/// ///
...@@ -553,6 +569,23 @@ namespace Google.Protobuf ...@@ -553,6 +569,23 @@ namespace Google.Protobuf
return (FieldCodec<T>) value; return (FieldCodec<T>) value;
} }
internal static Func<CodedInputStream, T?> GetReader<T>() where T : struct
{
Func<object> value;
if (!Readers.TryGetValue(typeof(T), out value))
{
throw new InvalidOperationException("Invalid type argument requested for wrapper reader: " + typeof(T));
}
if (value == null)
{
// Return default unoptimized reader for the wrapper type.
var nestedCoded = GetCodec<T>();
return input => Read<T>(input, nestedCoded);
}
// Return optimized read for the wrapper type.
return (Func<CodedInputStream, T?>)value();
}
internal static T Read<T>(CodedInputStream input, FieldCodec<T> codec) internal static T Read<T>(CodedInputStream input, FieldCodec<T> codec)
{ {
int length = input.ReadLength(); int length = input.ReadLength();
......
...@@ -136,5 +136,20 @@ namespace Google.Protobuf ...@@ -136,5 +136,20 @@ namespace Google.Protobuf
{ {
return new InvalidProtocolBufferException("Message was missing required fields"); return new InvalidProtocolBufferException("Message was missing required fields");
} }
}
internal static InvalidProtocolBufferException InvalidWrapperMessageLength()
{
return new InvalidProtocolBufferException("Wrapper type message length is incorrect.");
}
internal static InvalidProtocolBufferException InvalidWrapperMessageTag()
{
return new InvalidProtocolBufferException("Wrapper type message tag is incorrect.");
}
internal static InvalidProtocolBufferException InvalidWrapperMessageExtraFields()
{
return new InvalidProtocolBufferException("Wrapper type message contains invalid extra field(s).");
}
}
} }
\ No newline at end of file
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment