1 #region Copyright notice and license 2 // Protocol Buffers - Google's data interchange format 3 // Copyright 2008 Google Inc. All rights reserved. 4 // 5 // Use of this source code is governed by a BSD-style 6 // license that can be found in the LICENSE file or at 7 // https://developers.google.com/open-source/licenses/bsd 8 #endregion 9 10 using System; 11 12 namespace Google.Protobuf 13 { 14 // This part of CodedOutputStream provides all the static entry points that are used 15 // by generated code and internally to compute the size of messages prior to being 16 // written to an instance of CodedOutputStream. 17 public sealed partial class CodedOutputStream 18 { 19 private const int LittleEndian64Size = 8; 20 private const int LittleEndian32Size = 4; 21 22 internal const int DoubleSize = LittleEndian64Size; 23 internal const int FloatSize = LittleEndian32Size; 24 internal const int BoolSize = 1; 25 26 /// <summary> 27 /// Computes the number of bytes that would be needed to encode a 28 /// double field, including the tag. 29 /// </summary> ComputeDoubleSize(double value)30 public static int ComputeDoubleSize(double value) 31 { 32 return DoubleSize; 33 } 34 35 /// <summary> 36 /// Computes the number of bytes that would be needed to encode a 37 /// float field, including the tag. 38 /// </summary> ComputeFloatSize(float value)39 public static int ComputeFloatSize(float value) 40 { 41 return FloatSize; 42 } 43 44 /// <summary> 45 /// Computes the number of bytes that would be needed to encode a 46 /// uint64 field, including the tag. 47 /// </summary> ComputeUInt64Size(ulong value)48 public static int ComputeUInt64Size(ulong value) 49 { 50 return ComputeRawVarint64Size(value); 51 } 52 53 /// <summary> 54 /// Computes the number of bytes that would be needed to encode an 55 /// int64 field, including the tag. 56 /// </summary> ComputeInt64Size(long value)57 public static int ComputeInt64Size(long value) 58 { 59 return ComputeRawVarint64Size((ulong) value); 60 } 61 62 /// <summary> 63 /// Computes the number of bytes that would be needed to encode an 64 /// int32 field, including the tag. 65 /// </summary> ComputeInt32Size(int value)66 public static int ComputeInt32Size(int value) 67 { 68 if (value >= 0) 69 { 70 return ComputeRawVarint32Size((uint) value); 71 } 72 else 73 { 74 // Must sign-extend. 75 return 10; 76 } 77 } 78 79 /// <summary> 80 /// Computes the number of bytes that would be needed to encode a 81 /// fixed64 field, including the tag. 82 /// </summary> ComputeFixed64Size(ulong value)83 public static int ComputeFixed64Size(ulong value) 84 { 85 return LittleEndian64Size; 86 } 87 88 /// <summary> 89 /// Computes the number of bytes that would be needed to encode a 90 /// fixed32 field, including the tag. 91 /// </summary> ComputeFixed32Size(uint value)92 public static int ComputeFixed32Size(uint value) 93 { 94 return LittleEndian32Size; 95 } 96 97 /// <summary> 98 /// Computes the number of bytes that would be needed to encode a 99 /// bool field, including the tag. 100 /// </summary> ComputeBoolSize(bool value)101 public static int ComputeBoolSize(bool value) 102 { 103 return BoolSize; 104 } 105 106 /// <summary> 107 /// Computes the number of bytes that would be needed to encode a 108 /// string field, including the tag. 109 /// </summary> ComputeStringSize(String value)110 public static int ComputeStringSize(String value) 111 { 112 int byteArraySize = WritingPrimitives.Utf8Encoding.GetByteCount(value); 113 return ComputeLengthSize(byteArraySize) + byteArraySize; 114 } 115 116 /// <summary> 117 /// Computes the number of bytes that would be needed to encode a 118 /// group field, including the tag. 119 /// </summary> ComputeGroupSize(IMessage value)120 public static int ComputeGroupSize(IMessage value) 121 { 122 return value.CalculateSize(); 123 } 124 125 /// <summary> 126 /// Computes the number of bytes that would be needed to encode an 127 /// embedded message field, including the tag. 128 /// </summary> ComputeMessageSize(IMessage value)129 public static int ComputeMessageSize(IMessage value) 130 { 131 int size = value.CalculateSize(); 132 return ComputeLengthSize(size) + size; 133 } 134 135 /// <summary> 136 /// Computes the number of bytes that would be needed to encode a 137 /// bytes field, including the tag. 138 /// </summary> ComputeBytesSize(ByteString value)139 public static int ComputeBytesSize(ByteString value) 140 { 141 return ComputeLengthSize(value.Length) + value.Length; 142 } 143 144 /// <summary> 145 /// Computes the number of bytes that would be needed to encode a 146 /// uint32 field, including the tag. 147 /// </summary> ComputeUInt32Size(uint value)148 public static int ComputeUInt32Size(uint value) 149 { 150 return ComputeRawVarint32Size(value); 151 } 152 153 /// <summary> 154 /// Computes the number of bytes that would be needed to encode a 155 /// enum field, including the tag. The caller is responsible for 156 /// converting the enum value to its numeric value. 157 /// </summary> ComputeEnumSize(int value)158 public static int ComputeEnumSize(int value) 159 { 160 // Currently just a pass-through, but it's nice to separate it logically. 161 return ComputeInt32Size(value); 162 } 163 164 /// <summary> 165 /// Computes the number of bytes that would be needed to encode an 166 /// sfixed32 field, including the tag. 167 /// </summary> ComputeSFixed32Size(int value)168 public static int ComputeSFixed32Size(int value) 169 { 170 return LittleEndian32Size; 171 } 172 173 /// <summary> 174 /// Computes the number of bytes that would be needed to encode an 175 /// sfixed64 field, including the tag. 176 /// </summary> ComputeSFixed64Size(long value)177 public static int ComputeSFixed64Size(long value) 178 { 179 return LittleEndian64Size; 180 } 181 182 /// <summary> 183 /// Computes the number of bytes that would be needed to encode an 184 /// sint32 field, including the tag. 185 /// </summary> ComputeSInt32Size(int value)186 public static int ComputeSInt32Size(int value) 187 { 188 return ComputeRawVarint32Size(WritingPrimitives.EncodeZigZag32(value)); 189 } 190 191 /// <summary> 192 /// Computes the number of bytes that would be needed to encode an 193 /// sint64 field, including the tag. 194 /// </summary> ComputeSInt64Size(long value)195 public static int ComputeSInt64Size(long value) 196 { 197 return ComputeRawVarint64Size(WritingPrimitives.EncodeZigZag64(value)); 198 } 199 200 /// <summary> 201 /// Computes the number of bytes that would be needed to encode a length, 202 /// as written by <see cref="WriteLength"/>. 203 /// </summary> ComputeLengthSize(int length)204 public static int ComputeLengthSize(int length) 205 { 206 return ComputeRawVarint32Size((uint) length); 207 } 208 209 /// <summary> 210 /// Computes the number of bytes that would be needed to encode a varint. 211 /// </summary> ComputeRawVarint32Size(uint value)212 public static int ComputeRawVarint32Size(uint value) 213 { 214 if ((value & (0xffffffff << 7)) == 0) 215 { 216 return 1; 217 } 218 if ((value & (0xffffffff << 14)) == 0) 219 { 220 return 2; 221 } 222 if ((value & (0xffffffff << 21)) == 0) 223 { 224 return 3; 225 } 226 if ((value & (0xffffffff << 28)) == 0) 227 { 228 return 4; 229 } 230 return 5; 231 } 232 233 /// <summary> 234 /// Computes the number of bytes that would be needed to encode a varint. 235 /// </summary> ComputeRawVarint64Size(ulong value)236 public static int ComputeRawVarint64Size(ulong value) 237 { 238 if ((value & (0xffffffffffffffffL << 7)) == 0) 239 { 240 return 1; 241 } 242 if ((value & (0xffffffffffffffffL << 14)) == 0) 243 { 244 return 2; 245 } 246 if ((value & (0xffffffffffffffffL << 21)) == 0) 247 { 248 return 3; 249 } 250 if ((value & (0xffffffffffffffffL << 28)) == 0) 251 { 252 return 4; 253 } 254 if ((value & (0xffffffffffffffffL << 35)) == 0) 255 { 256 return 5; 257 } 258 if ((value & (0xffffffffffffffffL << 42)) == 0) 259 { 260 return 6; 261 } 262 if ((value & (0xffffffffffffffffL << 49)) == 0) 263 { 264 return 7; 265 } 266 if ((value & (0xffffffffffffffffL << 56)) == 0) 267 { 268 return 8; 269 } 270 if ((value & (0xffffffffffffffffL << 63)) == 0) 271 { 272 return 9; 273 } 274 return 10; 275 } 276 277 /// <summary> 278 /// Computes the number of bytes that would be needed to encode a tag. 279 /// </summary> ComputeTagSize(int fieldNumber)280 public static int ComputeTagSize(int fieldNumber) 281 { 282 return ComputeRawVarint32Size(WireFormat.MakeTag(fieldNumber, 0)); 283 } 284 } 285 }