1b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer#region Copyright notice and license 2b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer// Protocol Buffers - Google's data interchange format 3b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer// Copyright 2015 Google Inc. All rights reserved. 4b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer// https://developers.google.com/protocol-buffers/ 5b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer// 6b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer// Redistribution and use in source and binary forms, with or without 7b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer// modification, are permitted provided that the following conditions are 8b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer// met: 9b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer// 10b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer// * Redistributions of source code must retain the above copyright 11b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer// notice, this list of conditions and the following disclaimer. 12b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer// * Redistributions in binary form must reproduce the above 13b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer// copyright notice, this list of conditions and the following disclaimer 14b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer// in the documentation and/or other materials provided with the 15b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer// distribution. 16b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer// * Neither the name of Google Inc. nor the names of its 17b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer// contributors may be used to endorse or promote products derived from 18b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer// this software without specific prior written permission. 19b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer// 20b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 21b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 22b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 23b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 24b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 25b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 26b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 27b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 28b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 29b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 30b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 31b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer#endregion 32b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer 33b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerusing Google.Protobuf.Compatibility; 34b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerusing Google.Protobuf.WellKnownTypes; 35b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerusing System; 36b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerusing System.Collections.Generic; 37b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer 38b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammernamespace Google.Protobuf 39b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer{ 40b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer /// <summary> 41b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer /// Factory methods for <see cref="FieldCodec{T}"/>. 42b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer /// </summary> 43b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer public static class FieldCodec 44b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer { 45b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer // TODO: Avoid the "dual hit" of lambda expressions: create open delegates instead. (At least test...) 46b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer 47b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer /// <summary> 48b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer /// Retrieves a codec suitable for a string field with the given tag. 49b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer /// </summary> 50b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer /// <param name="tag">The tag.</param> 51b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer /// <returns>A codec for the given tag.</returns> 52b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer public static FieldCodec<string> ForString(uint tag) 53b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer { 54b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer return new FieldCodec<string>(input => input.ReadString(), (output, value) => output.WriteString(value), CodedOutputStream.ComputeStringSize, tag); 55b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer } 56b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer 57b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer /// <summary> 58b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer /// Retrieves a codec suitable for a bytes field with the given tag. 59b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer /// </summary> 60b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer /// <param name="tag">The tag.</param> 61b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer /// <returns>A codec for the given tag.</returns> 62b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer public static FieldCodec<ByteString> ForBytes(uint tag) 63b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer { 64b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer return new FieldCodec<ByteString>(input => input.ReadBytes(), (output, value) => output.WriteBytes(value), CodedOutputStream.ComputeBytesSize, tag); 65b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer } 66b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer 67b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer /// <summary> 68b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer /// Retrieves a codec suitable for a bool field with the given tag. 69b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer /// </summary> 70b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer /// <param name="tag">The tag.</param> 71b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer /// <returns>A codec for the given tag.</returns> 72b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer public static FieldCodec<bool> ForBool(uint tag) 73b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer { 74b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer return new FieldCodec<bool>(input => input.ReadBool(), (output, value) => output.WriteBool(value), CodedOutputStream.ComputeBoolSize, tag); 75b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer } 76b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer 77b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer /// <summary> 78b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer /// Retrieves a codec suitable for an int32 field with the given tag. 79b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer /// </summary> 80b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer /// <param name="tag">The tag.</param> 81b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer /// <returns>A codec for the given tag.</returns> 82b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer public static FieldCodec<int> ForInt32(uint tag) 83b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer { 84b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer return new FieldCodec<int>(input => input.ReadInt32(), (output, value) => output.WriteInt32(value), CodedOutputStream.ComputeInt32Size, tag); 85b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer } 86b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer 87b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer /// <summary> 88b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer /// Retrieves a codec suitable for an sint32 field with the given tag. 89b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer /// </summary> 90b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer /// <param name="tag">The tag.</param> 91b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer /// <returns>A codec for the given tag.</returns> 92b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer public static FieldCodec<int> ForSInt32(uint tag) 93b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer { 94b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer return new FieldCodec<int>(input => input.ReadSInt32(), (output, value) => output.WriteSInt32(value), CodedOutputStream.ComputeSInt32Size, tag); 95b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer } 96b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer 97b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer /// <summary> 98b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer /// Retrieves a codec suitable for a fixed32 field with the given tag. 99b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer /// </summary> 100b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer /// <param name="tag">The tag.</param> 101b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer /// <returns>A codec for the given tag.</returns> 102b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer public static FieldCodec<uint> ForFixed32(uint tag) 103b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer { 104b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer return new FieldCodec<uint>(input => input.ReadFixed32(), (output, value) => output.WriteFixed32(value), 4, tag); 105b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer } 106b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer 107b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer /// <summary> 108b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer /// Retrieves a codec suitable for an sfixed32 field with the given tag. 109b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer /// </summary> 110b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer /// <param name="tag">The tag.</param> 111b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer /// <returns>A codec for the given tag.</returns> 112b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer public static FieldCodec<int> ForSFixed32(uint tag) 113b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer { 114b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer return new FieldCodec<int>(input => input.ReadSFixed32(), (output, value) => output.WriteSFixed32(value), 4, tag); 115b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer } 116b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer 117b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer /// <summary> 118b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer /// Retrieves a codec suitable for a uint32 field with the given tag. 119b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer /// </summary> 120b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer /// <param name="tag">The tag.</param> 121b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer /// <returns>A codec for the given tag.</returns> 122b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer public static FieldCodec<uint> ForUInt32(uint tag) 123b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer { 124b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer return new FieldCodec<uint>(input => input.ReadUInt32(), (output, value) => output.WriteUInt32(value), CodedOutputStream.ComputeUInt32Size, tag); 125b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer } 126b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer 127b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer /// <summary> 128b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer /// Retrieves a codec suitable for an int64 field with the given tag. 129b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer /// </summary> 130b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer /// <param name="tag">The tag.</param> 131b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer /// <returns>A codec for the given tag.</returns> 132b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer public static FieldCodec<long> ForInt64(uint tag) 133b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer { 134b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer return new FieldCodec<long>(input => input.ReadInt64(), (output, value) => output.WriteInt64(value), CodedOutputStream.ComputeInt64Size, tag); 135b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer } 136b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer 137b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer /// <summary> 138b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer /// Retrieves a codec suitable for an sint64 field with the given tag. 139b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer /// </summary> 140b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer /// <param name="tag">The tag.</param> 141b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer /// <returns>A codec for the given tag.</returns> 142b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer public static FieldCodec<long> ForSInt64(uint tag) 143b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer { 144b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer return new FieldCodec<long>(input => input.ReadSInt64(), (output, value) => output.WriteSInt64(value), CodedOutputStream.ComputeSInt64Size, tag); 145b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer } 146b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer 147b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer /// <summary> 148b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer /// Retrieves a codec suitable for a fixed64 field with the given tag. 149b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer /// </summary> 150b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer /// <param name="tag">The tag.</param> 151b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer /// <returns>A codec for the given tag.</returns> 152b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer public static FieldCodec<ulong> ForFixed64(uint tag) 153b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer { 154b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer return new FieldCodec<ulong>(input => input.ReadFixed64(), (output, value) => output.WriteFixed64(value), 8, tag); 155b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer } 156b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer 157b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer /// <summary> 158b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer /// Retrieves a codec suitable for an sfixed64 field with the given tag. 159b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer /// </summary> 160b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer /// <param name="tag">The tag.</param> 161b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer /// <returns>A codec for the given tag.</returns> 162b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer public static FieldCodec<long> ForSFixed64(uint tag) 163b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer { 164b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer return new FieldCodec<long>(input => input.ReadSFixed64(), (output, value) => output.WriteSFixed64(value), 8, tag); 165b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer } 166b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer 167b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer /// <summary> 168b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer /// Retrieves a codec suitable for a uint64 field with the given tag. 169b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer /// </summary> 170b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer /// <param name="tag">The tag.</param> 171b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer /// <returns>A codec for the given tag.</returns> 172b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer public static FieldCodec<ulong> ForUInt64(uint tag) 173b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer { 174b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer return new FieldCodec<ulong>(input => input.ReadUInt64(), (output, value) => output.WriteUInt64(value), CodedOutputStream.ComputeUInt64Size, tag); 175b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer } 176b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer 177b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer /// <summary> 178b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer /// Retrieves a codec suitable for a float field with the given tag. 179b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer /// </summary> 180b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer /// <param name="tag">The tag.</param> 181b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer /// <returns>A codec for the given tag.</returns> 182b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer public static FieldCodec<float> ForFloat(uint tag) 183b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer { 184b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer return new FieldCodec<float>(input => input.ReadFloat(), (output, value) => output.WriteFloat(value), CodedOutputStream.ComputeFloatSize, tag); 185b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer } 186b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer 187b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer /// <summary> 188b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer /// Retrieves a codec suitable for a double field with the given tag. 189b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer /// </summary> 190b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer /// <param name="tag">The tag.</param> 191b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer /// <returns>A codec for the given tag.</returns> 192b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer public static FieldCodec<double> ForDouble(uint tag) 193b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer { 194b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer return new FieldCodec<double>(input => input.ReadDouble(), (output, value) => output.WriteDouble(value), CodedOutputStream.ComputeDoubleSize, tag); 195b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer } 196b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer 197b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer // Enums are tricky. We can probably use expression trees to build these delegates automatically, 198b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer // but it's easy to generate the code for it. 199b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer 200b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer /// <summary> 201b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer /// Retrieves a codec suitable for an enum field with the given tag. 202b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer /// </summary> 203b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer /// <param name="tag">The tag.</param> 204b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer /// <param name="toInt32">A conversion function from <see cref="Int32"/> to the enum type.</param> 205b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer /// <param name="fromInt32">A conversion function from the enum type to <see cref="Int32"/>.</param> 206b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer /// <returns>A codec for the given tag.</returns> 207b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer public static FieldCodec<T> ForEnum<T>(uint tag, Func<T, int> toInt32, Func<int, T> fromInt32) 208b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer { 209b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer return new FieldCodec<T>(input => fromInt32( 210b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer input.ReadEnum()), 211b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer (output, value) => output.WriteEnum(toInt32(value)), 212b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer value => CodedOutputStream.ComputeEnumSize(toInt32(value)), tag); 213b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer } 214b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer 215b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer /// <summary> 216b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer /// Retrieves a codec suitable for a message field with the given tag. 217b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer /// </summary> 218b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer /// <param name="tag">The tag.</param> 219b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer /// <param name="parser">A parser to use for the message type.</param> 220b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer /// <returns>A codec for the given tag.</returns> 221b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer public static FieldCodec<T> ForMessage<T>(uint tag, MessageParser<T> parser) where T : IMessage<T> 222b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer { 223b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer return new FieldCodec<T>(input => { T message = parser.CreateTemplate(); input.ReadMessage(message); return message; }, 224b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer (output, value) => output.WriteMessage(value), message => CodedOutputStream.ComputeMessageSize(message), tag); 225b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer } 226b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer 227b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer /// <summary> 228b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer /// Creates a codec for a wrapper type of a class - which must be string or ByteString. 229b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer /// </summary> 230b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer public static FieldCodec<T> ForClassWrapper<T>(uint tag) where T : class 231b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer { 232b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer var nestedCodec = WrapperCodecs.GetCodec<T>(); 233b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer return new FieldCodec<T>( 234b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer input => WrapperCodecs.Read<T>(input, nestedCodec), 235b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer (output, value) => WrapperCodecs.Write<T>(output, value, nestedCodec), 236b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer value => WrapperCodecs.CalculateSize<T>(value, nestedCodec), 237b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer tag, 238b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer null); // Default value for the wrapper 239b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer } 240b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer 241b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer /// <summary> 242b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer /// Creates a codec for a wrapper type of a struct - which must be Int32, Int64, UInt32, UInt64, 243b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer /// Bool, Single or Double. 244b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer /// </summary> 245b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer public static FieldCodec<T?> ForStructWrapper<T>(uint tag) where T : struct 246b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer { 247b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer var nestedCodec = WrapperCodecs.GetCodec<T>(); 248b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer return new FieldCodec<T?>( 249b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer input => WrapperCodecs.Read<T>(input, nestedCodec), 250b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer (output, value) => WrapperCodecs.Write<T>(output, value.Value, nestedCodec), 251b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer value => value == null ? 0 : WrapperCodecs.CalculateSize<T>(value.Value, nestedCodec), 252b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer tag, 253b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer null); // Default value for the wrapper 254b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer } 255b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer 256b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer /// <summary> 257b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer /// Helper code to create codecs for wrapper types. 258b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer /// </summary> 259b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer /// <remarks> 260b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer /// Somewhat ugly with all the static methods, but the conversions involved to/from nullable types make it 261b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer /// slightly tricky to improve. So long as we keep the public API (ForClassWrapper, ForStructWrapper) in place, 262b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer /// we can refactor later if we come up with something cleaner. 263b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer /// </remarks> 264b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer private static class WrapperCodecs 265b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer { 266b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer private static readonly Dictionary<System.Type, object> Codecs = new Dictionary<System.Type, object> 267b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer { 268b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer { typeof(bool), ForBool(WireFormat.MakeTag(WrappersReflection.WrapperValueFieldNumber, WireFormat.WireType.Varint)) }, 269b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer { typeof(int), ForInt32(WireFormat.MakeTag(WrappersReflection.WrapperValueFieldNumber, WireFormat.WireType.Varint)) }, 270b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer { typeof(long), ForInt64(WireFormat.MakeTag(WrappersReflection.WrapperValueFieldNumber, WireFormat.WireType.Varint)) }, 271b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer { typeof(uint), ForUInt32(WireFormat.MakeTag(WrappersReflection.WrapperValueFieldNumber, WireFormat.WireType.Varint)) }, 272b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer { typeof(ulong), ForUInt64(WireFormat.MakeTag(WrappersReflection.WrapperValueFieldNumber, WireFormat.WireType.Varint)) }, 273b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer { typeof(float), ForFloat(WireFormat.MakeTag(WrappersReflection.WrapperValueFieldNumber, WireFormat.WireType.Fixed32)) }, 274b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer { typeof(double), ForDouble(WireFormat.MakeTag(WrappersReflection.WrapperValueFieldNumber, WireFormat.WireType.Fixed64)) }, 275b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer { typeof(string), ForString(WireFormat.MakeTag(WrappersReflection.WrapperValueFieldNumber, WireFormat.WireType.LengthDelimited)) }, 276b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer { typeof(ByteString), ForBytes(WireFormat.MakeTag(WrappersReflection.WrapperValueFieldNumber, WireFormat.WireType.LengthDelimited)) } 277b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer }; 278b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer 279b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer /// <summary> 280b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer /// Returns a field codec which effectively wraps a value of type T in a message. 281b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer /// 282b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer /// </summary> 283b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer internal static FieldCodec<T> GetCodec<T>() 284b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer { 285b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer object value; 286b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer if (!Codecs.TryGetValue(typeof(T), out value)) 287b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer { 288b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer throw new InvalidOperationException("Invalid type argument requested for wrapper codec: " + typeof(T)); 289b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer } 290b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer return (FieldCodec<T>) value; 291b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer } 292b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer 293b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer internal static T Read<T>(CodedInputStream input, FieldCodec<T> codec) 294b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer { 295b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer int length = input.ReadLength(); 296b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer int oldLimit = input.PushLimit(length); 297b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer 298b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer uint tag; 299b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer T value = codec.DefaultValue; 300b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer while ((tag = input.ReadTag()) != 0) 301b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer { 302b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer if (tag == codec.Tag) 303b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer { 304b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer value = codec.Read(input); 305b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer } 306b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer else 307b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer { 308b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer input.SkipLastField(); 309b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer } 310b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer 311b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer } 312b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer input.CheckReadEndOfStreamTag(); 313b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer input.PopLimit(oldLimit); 314b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer 315b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer return value; 316b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer } 317b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer 318b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer internal static void Write<T>(CodedOutputStream output, T value, FieldCodec<T> codec) 319b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer { 320b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer output.WriteLength(codec.CalculateSizeWithTag(value)); 321b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer codec.WriteTagAndValue(output, value); 322b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer } 323b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer 324b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer internal static int CalculateSize<T>(T value, FieldCodec<T> codec) 325b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer { 326b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer int fieldLength = codec.CalculateSizeWithTag(value); 327b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer return CodedOutputStream.ComputeLengthSize(fieldLength) + fieldLength; 328b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer } 329b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer } 330b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer } 331b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer 332b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer /// <summary> 333b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer /// <para> 334b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer /// An encode/decode pair for a single field. This effectively encapsulates 335b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer /// all the information needed to read or write the field value from/to a coded 336b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer /// stream. 337b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer /// </para> 338b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer /// <para> 339b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer /// This class is public and has to be as it is used by generated code, but its public 340b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer /// API is very limited - just what the generated code needs to call directly. 341b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer /// </para> 342b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer /// </summary> 343b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer /// <remarks> 344b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer /// This never writes default values to the stream, and does not address "packedness" 345b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer /// in repeated fields itself, other than to know whether or not the field *should* be packed. 346b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer /// </remarks> 347b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer public sealed class FieldCodec<T> 348b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer { 349b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer private static readonly T DefaultDefault; 350b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer private static readonly bool TypeSupportsPacking = typeof(T).IsValueType() && Nullable.GetUnderlyingType(typeof(T)) == null; 351b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer 352b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer static FieldCodec() 353b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer { 354b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer if (typeof(T) == typeof(string)) 355b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer { 356b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer DefaultDefault = (T)(object)""; 357b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer } 358b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer else if (typeof(T) == typeof(ByteString)) 359b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer { 360b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer DefaultDefault = (T)(object)ByteString.Empty; 361b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer } 362b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer // Otherwise it's the default value of the CLR type 363b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer } 364b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer 365b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer internal static bool IsPackedRepeatedField(uint tag) => 366b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer TypeSupportsPacking && WireFormat.GetTagWireType(tag) == WireFormat.WireType.LengthDelimited; 367b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer 368b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer internal bool PackedRepeatedField { get; } 369b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer 370b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer /// <summary> 371b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer /// Returns a delegate to write a value (unconditionally) to a coded output stream. 372b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer /// </summary> 373b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer internal Action<CodedOutputStream, T> ValueWriter { get; } 374b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer 375b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer /// <summary> 376b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer /// Returns the size calculator for just a value. 377b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer /// </summary> 378b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer internal Func<T, int> ValueSizeCalculator { get; } 379b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer 380b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer /// <summary> 381b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer /// Returns a delegate to read a value from a coded input stream. It is assumed that 382b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer /// the stream is already positioned on the appropriate tag. 383b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer /// </summary> 384b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer internal Func<CodedInputStream, T> ValueReader { get; } 385b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer 386b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer /// <summary> 387b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer /// Returns the fixed size for an entry, or 0 if sizes vary. 388b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer /// </summary> 389b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer internal int FixedSize { get; } 390b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer 391b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer /// <summary> 392b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer /// Gets the tag of the codec. 393b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer /// </summary> 394b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer /// <value> 395b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer /// The tag of the codec. 396b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer /// </value> 397b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer internal uint Tag { get; } 398b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer 399b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer /// <summary> 400b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer /// Default value for this codec. Usually the same for every instance of the same type, but 401b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer /// for string/ByteString wrapper fields the codec's default value is null, whereas for 402b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer /// other string/ByteString fields it's "" or ByteString.Empty. 403b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer /// </summary> 404b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer /// <value> 405b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer /// The default value of the codec's type. 406b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer /// </value> 407b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer internal T DefaultValue { get; } 408b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer 409b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer private readonly int tagSize; 410b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer 411b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer internal FieldCodec( 412b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer Func<CodedInputStream, T> reader, 413b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer Action<CodedOutputStream, T> writer, 414b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer int fixedSize, 415b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer uint tag) : this(reader, writer, _ => fixedSize, tag) 416b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer { 417b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer FixedSize = fixedSize; 418b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer } 419b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer 420b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer internal FieldCodec( 421b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer Func<CodedInputStream, T> reader, 422b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer Action<CodedOutputStream, T> writer, 423b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer Func<T, int> sizeCalculator, 424b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer uint tag) : this(reader, writer, sizeCalculator, tag, DefaultDefault) 425b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer { 426b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer } 427b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer 428b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer internal FieldCodec( 429b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer Func<CodedInputStream, T> reader, 430b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer Action<CodedOutputStream, T> writer, 431b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer Func<T, int> sizeCalculator, 432b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer uint tag, 433b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer T defaultValue) 434b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer { 435b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer ValueReader = reader; 436b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer ValueWriter = writer; 437b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer ValueSizeCalculator = sizeCalculator; 438b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer FixedSize = 0; 439b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer Tag = tag; 440b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer DefaultValue = defaultValue; 441b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer tagSize = CodedOutputStream.ComputeRawVarint32Size(tag); 442b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer // Detect packed-ness once, so we can check for it within RepeatedField<T>. 443b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer PackedRepeatedField = IsPackedRepeatedField(tag); 444b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer } 445b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer 446b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer /// <summary> 447b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer /// Write a tag and the given value, *if* the value is not the default. 448b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer /// </summary> 449b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer public void WriteTagAndValue(CodedOutputStream output, T value) 450b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer { 451b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer if (!IsDefault(value)) 452b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer { 453b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer output.WriteTag(Tag); 454b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer ValueWriter(output, value); 455b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer } 456b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer } 457b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer 458b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer /// <summary> 459b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer /// Reads a value of the codec type from the given <see cref="CodedInputStream"/>. 460b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer /// </summary> 461b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer /// <param name="input">The input stream to read from.</param> 462b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer /// <returns>The value read from the stream.</returns> 463b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer public T Read(CodedInputStream input) => ValueReader(input); 464b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer 465b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer /// <summary> 466b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer /// Calculates the size required to write the given value, with a tag, 467b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer /// if the value is not the default. 468b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer /// </summary> 469b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer public int CalculateSizeWithTag(T value) => IsDefault(value) ? 0 : ValueSizeCalculator(value) + tagSize; 470b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer 471b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer private bool IsDefault(T value) => EqualityComparer<T>.Default.Equals(value, DefaultValue); 472b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer } 473b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer} 474