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
{
var nestedCodec = WrapperCodecs.GetCodec<T>();
return new FieldCodec<T?>(
input => WrapperCodecs.Read<T>(input, nestedCodec),
WrapperCodecs.GetReader<T>(),
(output, value) => WrapperCodecs.Write<T>(output, value.Value, 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; },
......@@ -539,6 +539,22 @@ namespace Google.Protobuf
{ 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>
/// Returns a field codec which effectively wraps a value of type T in a message.
///
......@@ -553,6 +569,23 @@ namespace Google.Protobuf
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)
{
int length = input.ReadLength();
......
......@@ -136,5 +136,20 @@ namespace Google.Protobuf
{
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