CodedInputStream.cs 61 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684
  1. #region Copyright notice and license
  2. // Protocol Buffers - Google's data interchange format
  3. // Copyright 2008 Google Inc. All rights reserved.
  4. // https://developers.google.com/protocol-buffers/
  5. //
  6. // Redistribution and use in source and binary forms, with or without
  7. // modification, are permitted provided that the following conditions are
  8. // met:
  9. //
  10. // * Redistributions of source code must retain the above copyright
  11. // notice, this list of conditions and the following disclaimer.
  12. // * Redistributions in binary form must reproduce the above
  13. // copyright notice, this list of conditions and the following disclaimer
  14. // in the documentation and/or other materials provided with the
  15. // distribution.
  16. // * Neither the name of Google Inc. nor the names of its
  17. // contributors may be used to endorse or promote products derived from
  18. // this software without specific prior written permission.
  19. //
  20. // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
  21. // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
  22. // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
  23. // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
  24. // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
  25. // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
  26. // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
  27. // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
  28. // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  29. // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
  30. // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  31. #endregion
  32. using Google.Protobuf.Collections;
  33. using System;
  34. using System.Collections.Generic;
  35. using System.IO;
  36. namespace Google.Protobuf
  37. {
  38. /// <summary>
  39. /// Reads and decodes protocol message fields.
  40. /// </summary>
  41. /// <remarks>
  42. /// <para>
  43. /// This class is generally used by generated code to read appropriate
  44. /// primitives from the stream. It effectively encapsulates the lowest
  45. /// levels of protocol buffer format.
  46. /// </para>
  47. /// <para>
  48. /// Repeated fields and map fields are not handled by this class; use <see cref="RepeatedField{T}"/>
  49. /// and <see cref="MapField{TKey, TValue}"/> to serialize such fields.
  50. /// </para>
  51. /// </remarks>
  52. public sealed class CodedInputStream : IDisposable
  53. {
  54. /// <summary>
  55. /// Whether to leave the underlying stream open when disposing of this stream.
  56. /// This is always true when there's no stream.
  57. /// </summary>
  58. private readonly bool leaveOpen;
  59. /// <summary>
  60. /// Buffer of data read from the stream or provided at construction time.
  61. /// </summary>
  62. private readonly byte[] buffer;
  63. /// <summary>
  64. /// The index of the buffer at which we need to refill from the stream (if there is one).
  65. /// </summary>
  66. private int bufferSize;
  67. private int bufferSizeAfterLimit = 0;
  68. /// <summary>
  69. /// The position within the current buffer (i.e. the next byte to read)
  70. /// </summary>
  71. private int bufferPos = 0;
  72. /// <summary>
  73. /// The stream to read further input from, or null if the byte array buffer was provided
  74. /// directly on construction, with no further data available.
  75. /// </summary>
  76. private readonly Stream input;
  77. /// <summary>
  78. /// The last tag we read. 0 indicates we've read to the end of the stream
  79. /// (or haven't read anything yet).
  80. /// </summary>
  81. private uint lastTag = 0;
  82. /// <summary>
  83. /// The next tag, used to store the value read by PeekTag.
  84. /// </summary>
  85. private uint nextTag = 0;
  86. private bool hasNextTag = false;
  87. internal const int DefaultRecursionLimit = 100;
  88. internal const int DefaultSizeLimit = Int32.MaxValue;
  89. internal const int BufferSize = 4096;
  90. /// <summary>
  91. /// The total number of bytes read before the current buffer. The
  92. /// total bytes read up to the current position can be computed as
  93. /// totalBytesRetired + bufferPos.
  94. /// </summary>
  95. private int totalBytesRetired = 0;
  96. /// <summary>
  97. /// The absolute position of the end of the current message.
  98. /// </summary>
  99. private int currentLimit = int.MaxValue;
  100. private int recursionDepth = 0;
  101. private readonly int recursionLimit;
  102. private readonly int sizeLimit;
  103. #region Construction
  104. // Note that the checks are performed such that we don't end up checking obviously-valid things
  105. // like non-null references for arrays we've just created.
  106. /// <summary>
  107. /// Creates a new CodedInputStream reading data from the given byte array.
  108. /// </summary>
  109. public CodedInputStream(byte[] buffer) : this(null, ProtoPreconditions.CheckNotNull(buffer, "buffer"), 0, buffer.Length, true)
  110. {
  111. }
  112. /// <summary>
  113. /// Creates a new <see cref="CodedInputStream"/> that reads from the given byte array slice.
  114. /// </summary>
  115. public CodedInputStream(byte[] buffer, int offset, int length)
  116. : this(null, ProtoPreconditions.CheckNotNull(buffer, "buffer"), offset, offset + length, true)
  117. {
  118. if (offset < 0 || offset > buffer.Length)
  119. {
  120. throw new ArgumentOutOfRangeException("offset", "Offset must be within the buffer");
  121. }
  122. if (length < 0 || offset + length > buffer.Length)
  123. {
  124. throw new ArgumentOutOfRangeException("length", "Length must be non-negative and within the buffer");
  125. }
  126. }
  127. /// <summary>
  128. /// Creates a new <see cref="CodedInputStream"/> reading data from the given stream, which will be disposed
  129. /// when the returned object is disposed.
  130. /// </summary>
  131. /// <param name="input">The stream to read from.</param>
  132. public CodedInputStream(Stream input) : this(input, false)
  133. {
  134. }
  135. /// <summary>
  136. /// Creates a new <see cref="CodedInputStream"/> reading data from the given stream.
  137. /// </summary>
  138. /// <param name="input">The stream to read from.</param>
  139. /// <param name="leaveOpen"><c>true</c> to leave <paramref name="input"/> open when the returned
  140. /// <c cref="CodedInputStream"/> is disposed; <c>false</c> to dispose of the given stream when the
  141. /// returned object is disposed.</param>
  142. public CodedInputStream(Stream input, bool leaveOpen)
  143. : this(ProtoPreconditions.CheckNotNull(input, "input"), new byte[BufferSize], 0, 0, leaveOpen)
  144. {
  145. }
  146. /// <summary>
  147. /// Creates a new CodedInputStream reading data from the given
  148. /// stream and buffer, using the default limits.
  149. /// </summary>
  150. internal CodedInputStream(Stream input, byte[] buffer, int bufferPos, int bufferSize, bool leaveOpen)
  151. {
  152. this.input = input;
  153. this.buffer = buffer;
  154. this.bufferPos = bufferPos;
  155. this.bufferSize = bufferSize;
  156. this.sizeLimit = DefaultSizeLimit;
  157. this.recursionLimit = DefaultRecursionLimit;
  158. this.leaveOpen = leaveOpen;
  159. }
  160. /// <summary>
  161. /// Creates a new CodedInputStream reading data from the given
  162. /// stream and buffer, using the specified limits.
  163. /// </summary>
  164. /// <remarks>
  165. /// This chains to the version with the default limits instead of vice versa to avoid
  166. /// having to check that the default values are valid every time.
  167. /// </remarks>
  168. internal CodedInputStream(Stream input, byte[] buffer, int bufferPos, int bufferSize, int sizeLimit, int recursionLimit, bool leaveOpen)
  169. : this(input, buffer, bufferPos, bufferSize, leaveOpen)
  170. {
  171. if (sizeLimit <= 0)
  172. {
  173. throw new ArgumentOutOfRangeException("sizeLimit", "Size limit must be positive");
  174. }
  175. if (recursionLimit <= 0)
  176. {
  177. throw new ArgumentOutOfRangeException("recursionLimit!", "Recursion limit must be positive");
  178. }
  179. this.sizeLimit = sizeLimit;
  180. this.recursionLimit = recursionLimit;
  181. }
  182. #endregion
  183. /// <summary>
  184. /// Creates a <see cref="CodedInputStream"/> with the specified size and recursion limits, reading
  185. /// from an input stream.
  186. /// </summary>
  187. /// <remarks>
  188. /// This method exists separately from the constructor to reduce the number of constructor overloads.
  189. /// It is likely to be used considerably less frequently than the constructors, as the default limits
  190. /// are suitable for most use cases.
  191. /// </remarks>
  192. /// <param name="input">The input stream to read from</param>
  193. /// <param name="sizeLimit">The total limit of data to read from the stream.</param>
  194. /// <param name="recursionLimit">The maximum recursion depth to allow while reading.</param>
  195. /// <returns>A <c>CodedInputStream</c> reading from <paramref name="input"/> with the specified size
  196. /// and recursion limits.</returns>
  197. public static CodedInputStream CreateWithLimits(Stream input, int sizeLimit, int recursionLimit)
  198. {
  199. // Note: we may want an overload accepting leaveOpen
  200. return new CodedInputStream(input, new byte[BufferSize], 0, 0, sizeLimit, recursionLimit, false);
  201. }
  202. /// <summary>
  203. /// Returns the current position in the input stream, or the position in the input buffer
  204. /// </summary>
  205. public long Position
  206. {
  207. get
  208. {
  209. if (input != null)
  210. {
  211. return input.Position - ((bufferSize + bufferSizeAfterLimit) - bufferPos);
  212. }
  213. return bufferPos;
  214. }
  215. }
  216. /// <summary>
  217. /// Returns the last tag read, or 0 if no tags have been read or we've read beyond
  218. /// the end of the stream.
  219. /// </summary>
  220. internal uint LastTag { get { return lastTag; } }
  221. /// <summary>
  222. /// Returns the size limit for this stream.
  223. /// </summary>
  224. /// <remarks>
  225. /// This limit is applied when reading from the underlying stream, as a sanity check. It is
  226. /// not applied when reading from a byte array data source without an underlying stream.
  227. /// The default value is Int32.MaxValue.
  228. /// </remarks>
  229. /// <value>
  230. /// The size limit.
  231. /// </value>
  232. public int SizeLimit { get { return sizeLimit; } }
  233. /// <summary>
  234. /// Returns the recursion limit for this stream. This limit is applied whilst reading messages,
  235. /// to avoid maliciously-recursive data.
  236. /// </summary>
  237. /// <remarks>
  238. /// The default limit is 100.
  239. /// </remarks>
  240. /// <value>
  241. /// The recursion limit for this stream.
  242. /// </value>
  243. public int RecursionLimit { get { return recursionLimit; } }
  244. /// <summary>
  245. /// Internal-only property; when set to true, unknown fields will be discarded while parsing.
  246. /// </summary>
  247. internal bool DiscardUnknownFields { get; set; }
  248. /// <summary>
  249. /// Internal-only property; provides extension identifiers to compatible messages while parsing.
  250. /// </summary>
  251. internal ExtensionRegistry ExtensionRegistry { get; set; }
  252. /// <summary>
  253. /// Disposes of this instance, potentially closing any underlying stream.
  254. /// </summary>
  255. /// <remarks>
  256. /// As there is no flushing to perform here, disposing of a <see cref="CodedInputStream"/> which
  257. /// was constructed with the <c>leaveOpen</c> option parameter set to <c>true</c> (or one which
  258. /// was constructed to read from a byte array) has no effect.
  259. /// </remarks>
  260. public void Dispose()
  261. {
  262. if (!leaveOpen)
  263. {
  264. input.Dispose();
  265. }
  266. }
  267. #region Validation
  268. /// <summary>
  269. /// Verifies that the last call to ReadTag() returned tag 0 - in other words,
  270. /// we've reached the end of the stream when we expected to.
  271. /// </summary>
  272. /// <exception cref="InvalidProtocolBufferException">The
  273. /// tag read was not the one specified</exception>
  274. internal void CheckReadEndOfStreamTag()
  275. {
  276. if (lastTag != 0)
  277. {
  278. throw InvalidProtocolBufferException.MoreDataAvailable();
  279. }
  280. }
  281. internal void CheckLastTagWas(uint expectedTag)
  282. {
  283. if (lastTag != expectedTag) {
  284. throw InvalidProtocolBufferException.InvalidEndTag();
  285. }
  286. }
  287. #endregion
  288. #region Reading of tags etc
  289. /// <summary>
  290. /// Peeks at the next field tag. This is like calling <see cref="ReadTag"/>, but the
  291. /// tag is not consumed. (So a subsequent call to <see cref="ReadTag"/> will return the
  292. /// same value.)
  293. /// </summary>
  294. public uint PeekTag()
  295. {
  296. if (hasNextTag)
  297. {
  298. return nextTag;
  299. }
  300. uint savedLast = lastTag;
  301. nextTag = ReadTag();
  302. hasNextTag = true;
  303. lastTag = savedLast; // Undo the side effect of ReadTag
  304. return nextTag;
  305. }
  306. /// <summary>
  307. /// Reads a field tag, returning the tag of 0 for "end of stream".
  308. /// </summary>
  309. /// <remarks>
  310. /// If this method returns 0, it doesn't necessarily mean the end of all
  311. /// the data in this CodedInputStream; it may be the end of the logical stream
  312. /// for an embedded message, for example.
  313. /// </remarks>
  314. /// <returns>The next field tag, or 0 for end of stream. (0 is never a valid tag.)</returns>
  315. public uint ReadTag()
  316. {
  317. if (hasNextTag)
  318. {
  319. lastTag = nextTag;
  320. hasNextTag = false;
  321. return lastTag;
  322. }
  323. // Optimize for the incredibly common case of having at least two bytes left in the buffer,
  324. // and those two bytes being enough to get the tag. This will be true for fields up to 4095.
  325. if (bufferPos + 2 <= bufferSize)
  326. {
  327. int tmp = buffer[bufferPos++];
  328. if (tmp < 128)
  329. {
  330. lastTag = (uint)tmp;
  331. }
  332. else
  333. {
  334. int result = tmp & 0x7f;
  335. if ((tmp = buffer[bufferPos++]) < 128)
  336. {
  337. result |= tmp << 7;
  338. lastTag = (uint) result;
  339. }
  340. else
  341. {
  342. // Nope, rewind and go the potentially slow route.
  343. bufferPos -= 2;
  344. lastTag = ReadRawVarint32();
  345. }
  346. }
  347. }
  348. else
  349. {
  350. if (IsAtEnd)
  351. {
  352. lastTag = 0;
  353. return 0;
  354. }
  355. lastTag = ReadRawVarint32();
  356. }
  357. if (WireFormat.GetTagFieldNumber(lastTag) == 0)
  358. {
  359. // If we actually read a tag with a field of 0, that's not a valid tag.
  360. throw InvalidProtocolBufferException.InvalidTag();
  361. }
  362. if (ReachedLimit)
  363. {
  364. return 0;
  365. }
  366. return lastTag;
  367. }
  368. /// <summary>
  369. /// Skips the data for the field with the tag we've just read.
  370. /// This should be called directly after <see cref="ReadTag"/>, when
  371. /// the caller wishes to skip an unknown field.
  372. /// </summary>
  373. /// <remarks>
  374. /// This method throws <see cref="InvalidProtocolBufferException"/> if the last-read tag was an end-group tag.
  375. /// If a caller wishes to skip a group, they should skip the whole group, by calling this method after reading the
  376. /// start-group tag. This behavior allows callers to call this method on any field they don't understand, correctly
  377. /// resulting in an error if an end-group tag has not been paired with an earlier start-group tag.
  378. /// </remarks>
  379. /// <exception cref="InvalidProtocolBufferException">The last tag was an end-group tag</exception>
  380. /// <exception cref="InvalidOperationException">The last read operation read to the end of the logical stream</exception>
  381. public void SkipLastField()
  382. {
  383. if (lastTag == 0)
  384. {
  385. throw new InvalidOperationException("SkipLastField cannot be called at the end of a stream");
  386. }
  387. switch (WireFormat.GetTagWireType(lastTag))
  388. {
  389. case WireFormat.WireType.StartGroup:
  390. SkipGroup(lastTag);
  391. break;
  392. case WireFormat.WireType.EndGroup:
  393. throw new InvalidProtocolBufferException(
  394. "SkipLastField called on an end-group tag, indicating that the corresponding start-group was missing");
  395. case WireFormat.WireType.Fixed32:
  396. ReadFixed32();
  397. break;
  398. case WireFormat.WireType.Fixed64:
  399. ReadFixed64();
  400. break;
  401. case WireFormat.WireType.LengthDelimited:
  402. var length = ReadLength();
  403. SkipRawBytes(length);
  404. break;
  405. case WireFormat.WireType.Varint:
  406. ReadRawVarint32();
  407. break;
  408. }
  409. }
  410. /// <summary>
  411. /// Skip a group.
  412. /// </summary>
  413. internal void SkipGroup(uint startGroupTag)
  414. {
  415. // Note: Currently we expect this to be the way that groups are read. We could put the recursion
  416. // depth changes into the ReadTag method instead, potentially...
  417. recursionDepth++;
  418. if (recursionDepth >= recursionLimit)
  419. {
  420. throw InvalidProtocolBufferException.RecursionLimitExceeded();
  421. }
  422. uint tag;
  423. while (true)
  424. {
  425. tag = ReadTag();
  426. if (tag == 0)
  427. {
  428. throw InvalidProtocolBufferException.TruncatedMessage();
  429. }
  430. // Can't call SkipLastField for this case- that would throw.
  431. if (WireFormat.GetTagWireType(tag) == WireFormat.WireType.EndGroup)
  432. {
  433. break;
  434. }
  435. // This recursion will allow us to handle nested groups.
  436. SkipLastField();
  437. }
  438. int startField = WireFormat.GetTagFieldNumber(startGroupTag);
  439. int endField = WireFormat.GetTagFieldNumber(tag);
  440. if (startField != endField)
  441. {
  442. throw new InvalidProtocolBufferException(
  443. $"Mismatched end-group tag. Started with field {startField}; ended with field {endField}");
  444. }
  445. recursionDepth--;
  446. }
  447. /// <summary>
  448. /// Reads a double field from the stream.
  449. /// </summary>
  450. public double ReadDouble()
  451. {
  452. if (bufferPos + 8 <= bufferSize)
  453. {
  454. if (BitConverter.IsLittleEndian)
  455. {
  456. var result = BitConverter.ToDouble(buffer, bufferPos);
  457. bufferPos += 8;
  458. return result;
  459. }
  460. else
  461. {
  462. var bytes = new byte[8];
  463. bytes[0] = buffer[bufferPos + 7];
  464. bytes[1] = buffer[bufferPos + 6];
  465. bytes[2] = buffer[bufferPos + 5];
  466. bytes[3] = buffer[bufferPos + 4];
  467. bytes[4] = buffer[bufferPos + 3];
  468. bytes[5] = buffer[bufferPos + 2];
  469. bytes[6] = buffer[bufferPos + 1];
  470. bytes[7] = buffer[bufferPos];
  471. bufferPos += 8;
  472. return BitConverter.ToDouble(bytes, 0);
  473. }
  474. }
  475. else
  476. {
  477. return BitConverter.Int64BitsToDouble((long)ReadRawLittleEndian64());
  478. }
  479. }
  480. /// <summary>
  481. /// Reads a float field from the stream.
  482. /// </summary>
  483. public float ReadFloat()
  484. {
  485. if (BitConverter.IsLittleEndian && 4 <= bufferSize - bufferPos)
  486. {
  487. float ret = BitConverter.ToSingle(buffer, bufferPos);
  488. bufferPos += 4;
  489. return ret;
  490. }
  491. else
  492. {
  493. byte[] rawBytes = ReadRawBytes(4);
  494. if (!BitConverter.IsLittleEndian)
  495. {
  496. ByteArray.Reverse(rawBytes);
  497. }
  498. return BitConverter.ToSingle(rawBytes, 0);
  499. }
  500. }
  501. /// <summary>
  502. /// Reads a uint64 field from the stream.
  503. /// </summary>
  504. public ulong ReadUInt64()
  505. {
  506. return ReadRawVarint64();
  507. }
  508. /// <summary>
  509. /// Reads an int64 field from the stream.
  510. /// </summary>
  511. public long ReadInt64()
  512. {
  513. return (long) ReadRawVarint64();
  514. }
  515. /// <summary>
  516. /// Reads an int32 field from the stream.
  517. /// </summary>
  518. public int ReadInt32()
  519. {
  520. return (int) ReadRawVarint32();
  521. }
  522. /// <summary>
  523. /// Reads a fixed64 field from the stream.
  524. /// </summary>
  525. public ulong ReadFixed64()
  526. {
  527. return ReadRawLittleEndian64();
  528. }
  529. /// <summary>
  530. /// Reads a fixed32 field from the stream.
  531. /// </summary>
  532. public uint ReadFixed32()
  533. {
  534. return ReadRawLittleEndian32();
  535. }
  536. /// <summary>
  537. /// Reads a bool field from the stream.
  538. /// </summary>
  539. public bool ReadBool()
  540. {
  541. return ReadRawVarint64() != 0;
  542. }
  543. /// <summary>
  544. /// Reads a string field from the stream.
  545. /// </summary>
  546. public string ReadString()
  547. {
  548. int length = ReadLength();
  549. // No need to read any data for an empty string.
  550. if (length == 0)
  551. {
  552. return "";
  553. }
  554. if (length <= bufferSize - bufferPos && length > 0)
  555. {
  556. // Fast path: We already have the bytes in a contiguous buffer, so
  557. // just copy directly from it.
  558. String result = CodedOutputStream.Utf8Encoding.GetString(buffer, bufferPos, length);
  559. bufferPos += length;
  560. return result;
  561. }
  562. // Slow path: Build a byte array first then copy it.
  563. return CodedOutputStream.Utf8Encoding.GetString(ReadRawBytes(length), 0, length);
  564. }
  565. /// <summary>
  566. /// Reads an embedded message field value from the stream.
  567. /// </summary>
  568. public void ReadMessage(IMessage builder)
  569. {
  570. int length = ReadLength();
  571. if (recursionDepth >= recursionLimit)
  572. {
  573. throw InvalidProtocolBufferException.RecursionLimitExceeded();
  574. }
  575. int oldLimit = PushLimit(length);
  576. ++recursionDepth;
  577. builder.MergeFrom(this);
  578. CheckReadEndOfStreamTag();
  579. // Check that we've read exactly as much data as expected.
  580. if (!ReachedLimit)
  581. {
  582. throw InvalidProtocolBufferException.TruncatedMessage();
  583. }
  584. --recursionDepth;
  585. PopLimit(oldLimit);
  586. }
  587. /// <summary>
  588. /// Reads an embedded group field from the stream.
  589. /// </summary>
  590. public void ReadGroup(IMessage builder)
  591. {
  592. if (recursionDepth >= recursionLimit)
  593. {
  594. throw InvalidProtocolBufferException.RecursionLimitExceeded();
  595. }
  596. ++recursionDepth;
  597. uint tag = lastTag;
  598. int fieldNumber = WireFormat.GetTagFieldNumber(tag);
  599. builder.MergeFrom(this);
  600. CheckLastTagWas(WireFormat.MakeTag(fieldNumber, WireFormat.WireType.EndGroup));
  601. --recursionDepth;
  602. }
  603. /// <summary>
  604. /// Reads an embedded group unknown field from the stream.
  605. /// </summary>
  606. internal void ReadGroup(int fieldNumber, UnknownFieldSet set)
  607. {
  608. if (recursionDepth >= recursionLimit)
  609. {
  610. throw InvalidProtocolBufferException.RecursionLimitExceeded();
  611. }
  612. ++recursionDepth;
  613. set.MergeGroupFrom(this);
  614. CheckLastTagWas(WireFormat.MakeTag(fieldNumber, WireFormat.WireType.EndGroup));
  615. --recursionDepth;
  616. }
  617. /// <summary>
  618. /// Reads a bytes field value from the stream.
  619. /// </summary>
  620. public ByteString ReadBytes()
  621. {
  622. int length = ReadLength();
  623. if (length <= bufferSize - bufferPos && length > 0)
  624. {
  625. // Fast path: We already have the bytes in a contiguous buffer, so
  626. // just copy directly from it.
  627. ByteString result = ByteString.CopyFrom(buffer, bufferPos, length);
  628. bufferPos += length;
  629. return result;
  630. }
  631. else
  632. {
  633. // Slow path: Build a byte array and attach it to a new ByteString.
  634. return ByteString.AttachBytes(ReadRawBytes(length));
  635. }
  636. }
  637. /// <summary>
  638. /// Reads a uint32 field value from the stream.
  639. /// </summary>
  640. public uint ReadUInt32()
  641. {
  642. return ReadRawVarint32();
  643. }
  644. /// <summary>
  645. /// Reads an enum field value from the stream.
  646. /// </summary>
  647. public int ReadEnum()
  648. {
  649. // Currently just a pass-through, but it's nice to separate it logically from WriteInt32.
  650. return (int) ReadRawVarint32();
  651. }
  652. /// <summary>
  653. /// Reads an sfixed32 field value from the stream.
  654. /// </summary>
  655. public int ReadSFixed32()
  656. {
  657. return (int) ReadRawLittleEndian32();
  658. }
  659. /// <summary>
  660. /// Reads an sfixed64 field value from the stream.
  661. /// </summary>
  662. public long ReadSFixed64()
  663. {
  664. return (long) ReadRawLittleEndian64();
  665. }
  666. /// <summary>
  667. /// Reads an sint32 field value from the stream.
  668. /// </summary>
  669. public int ReadSInt32()
  670. {
  671. return DecodeZigZag32(ReadRawVarint32());
  672. }
  673. /// <summary>
  674. /// Reads an sint64 field value from the stream.
  675. /// </summary>
  676. public long ReadSInt64()
  677. {
  678. return DecodeZigZag64(ReadRawVarint64());
  679. }
  680. /// <summary>
  681. /// Reads a length for length-delimited data.
  682. /// </summary>
  683. /// <remarks>
  684. /// This is internally just reading a varint, but this method exists
  685. /// to make the calling code clearer.
  686. /// </remarks>
  687. public int ReadLength()
  688. {
  689. return (int) ReadRawVarint32();
  690. }
  691. /// <summary>
  692. /// Peeks at the next tag in the stream. If it matches <paramref name="tag"/>,
  693. /// the tag is consumed and the method returns <c>true</c>; otherwise, the
  694. /// stream is left in the original position and the method returns <c>false</c>.
  695. /// </summary>
  696. public bool MaybeConsumeTag(uint tag)
  697. {
  698. if (PeekTag() == tag)
  699. {
  700. hasNextTag = false;
  701. return true;
  702. }
  703. return false;
  704. }
  705. internal static float? ReadFloatWrapperLittleEndian(CodedInputStream input)
  706. {
  707. // length:1 + tag:1 + value:4 = 6 bytes
  708. if (input.bufferPos + 6 <= input.bufferSize)
  709. {
  710. // The entire wrapper message is already contained in `buffer`.
  711. int length = input.buffer[input.bufferPos];
  712. if (length == 0)
  713. {
  714. input.bufferPos++;
  715. return 0F;
  716. }
  717. // tag:1 + value:4 = length of 5 bytes
  718. // field=1, type=32-bit = tag of 13
  719. if (length != 5 || input.buffer[input.bufferPos + 1] != 13)
  720. {
  721. return ReadFloatWrapperSlow(input);
  722. }
  723. var result = BitConverter.ToSingle(input.buffer, input.bufferPos + 2);
  724. input.bufferPos += 6;
  725. return result;
  726. }
  727. else
  728. {
  729. return ReadFloatWrapperSlow(input);
  730. }
  731. }
  732. internal static float? ReadFloatWrapperSlow(CodedInputStream input)
  733. {
  734. int length = input.ReadLength();
  735. if (length == 0)
  736. {
  737. return 0F;
  738. }
  739. int finalBufferPos = input.totalBytesRetired + input.bufferPos + length;
  740. float result = 0F;
  741. do
  742. {
  743. // field=1, type=32-bit = tag of 13
  744. if (input.ReadTag() == 13)
  745. {
  746. result = input.ReadFloat();
  747. }
  748. else
  749. {
  750. input.SkipLastField();
  751. }
  752. }
  753. while (input.totalBytesRetired + input.bufferPos < finalBufferPos);
  754. return result;
  755. }
  756. internal static double? ReadDoubleWrapperLittleEndian(CodedInputStream input)
  757. {
  758. // length:1 + tag:1 + value:8 = 10 bytes
  759. if (input.bufferPos + 10 <= input.bufferSize)
  760. {
  761. // The entire wrapper message is already contained in `buffer`.
  762. int length = input.buffer[input.bufferPos];
  763. if (length == 0)
  764. {
  765. input.bufferPos++;
  766. return 0D;
  767. }
  768. // tag:1 + value:8 = length of 9 bytes
  769. // field=1, type=64-bit = tag of 9
  770. if (length != 9 || input.buffer[input.bufferPos + 1] != 9)
  771. {
  772. return ReadDoubleWrapperSlow(input);
  773. }
  774. var result = BitConverter.ToDouble(input.buffer, input.bufferPos + 2);
  775. input.bufferPos += 10;
  776. return result;
  777. }
  778. else
  779. {
  780. return ReadDoubleWrapperSlow(input);
  781. }
  782. }
  783. internal static double? ReadDoubleWrapperSlow(CodedInputStream input)
  784. {
  785. int length = input.ReadLength();
  786. if (length == 0)
  787. {
  788. return 0D;
  789. }
  790. int finalBufferPos = input.totalBytesRetired + input.bufferPos + length;
  791. double result = 0D;
  792. do
  793. {
  794. // field=1, type=64-bit = tag of 9
  795. if (input.ReadTag() == 9)
  796. {
  797. result = input.ReadDouble();
  798. }
  799. else
  800. {
  801. input.SkipLastField();
  802. }
  803. }
  804. while (input.totalBytesRetired + input.bufferPos < finalBufferPos);
  805. return result;
  806. }
  807. internal static bool? ReadBoolWrapper(CodedInputStream input)
  808. {
  809. return ReadUInt64Wrapper(input) != 0;
  810. }
  811. internal static uint? ReadUInt32Wrapper(CodedInputStream input)
  812. {
  813. // length:1 + tag:1 + value:5(varint32-max) = 7 bytes
  814. if (input.bufferPos + 7 <= input.bufferSize)
  815. {
  816. // The entire wrapper message is already contained in `buffer`.
  817. int pos0 = input.bufferPos;
  818. int length = input.buffer[input.bufferPos++];
  819. if (length == 0)
  820. {
  821. return 0;
  822. }
  823. // Length will always fit in a single byte.
  824. if (length >= 128)
  825. {
  826. input.bufferPos = pos0;
  827. return ReadUInt32WrapperSlow(input);
  828. }
  829. int finalBufferPos = input.bufferPos + length;
  830. // field=1, type=varint = tag of 8
  831. if (input.buffer[input.bufferPos++] != 8)
  832. {
  833. input.bufferPos = pos0;
  834. return ReadUInt32WrapperSlow(input);
  835. }
  836. var result = input.ReadUInt32();
  837. // Verify this message only contained a single field.
  838. if (input.bufferPos != finalBufferPos)
  839. {
  840. input.bufferPos = pos0;
  841. return ReadUInt32WrapperSlow(input);
  842. }
  843. return result;
  844. }
  845. else
  846. {
  847. return ReadUInt32WrapperSlow(input);
  848. }
  849. }
  850. private static uint? ReadUInt32WrapperSlow(CodedInputStream input)
  851. {
  852. int length = input.ReadLength();
  853. if (length == 0)
  854. {
  855. return 0;
  856. }
  857. int finalBufferPos = input.totalBytesRetired + input.bufferPos + length;
  858. uint result = 0;
  859. do
  860. {
  861. // field=1, type=varint = tag of 8
  862. if (input.ReadTag() == 8)
  863. {
  864. result = input.ReadUInt32();
  865. }
  866. else
  867. {
  868. input.SkipLastField();
  869. }
  870. }
  871. while (input.totalBytesRetired + input.bufferPos < finalBufferPos);
  872. return result;
  873. }
  874. internal static int? ReadInt32Wrapper(CodedInputStream input)
  875. {
  876. return (int?)ReadUInt32Wrapper(input);
  877. }
  878. internal static ulong? ReadUInt64Wrapper(CodedInputStream input)
  879. {
  880. // field=1, type=varint = tag of 8
  881. const int expectedTag = 8;
  882. // length:1 + tag:1 + value:10(varint64-max) = 12 bytes
  883. if (input.bufferPos + 12 <= input.bufferSize)
  884. {
  885. // The entire wrapper message is already contained in `buffer`.
  886. int pos0 = input.bufferPos;
  887. int length = input.buffer[input.bufferPos++];
  888. if (length == 0)
  889. {
  890. return 0L;
  891. }
  892. // Length will always fit in a single byte.
  893. if (length >= 128)
  894. {
  895. input.bufferPos = pos0;
  896. return ReadUInt64WrapperSlow(input);
  897. }
  898. int finalBufferPos = input.bufferPos + length;
  899. if (input.buffer[input.bufferPos++] != expectedTag)
  900. {
  901. input.bufferPos = pos0;
  902. return ReadUInt64WrapperSlow(input);
  903. }
  904. var result = input.ReadUInt64();
  905. // Verify this message only contained a single field.
  906. if (input.bufferPos != finalBufferPos)
  907. {
  908. input.bufferPos = pos0;
  909. return ReadUInt64WrapperSlow(input);
  910. }
  911. return result;
  912. }
  913. else
  914. {
  915. return ReadUInt64WrapperSlow(input);
  916. }
  917. }
  918. internal static ulong? ReadUInt64WrapperSlow(CodedInputStream input)
  919. {
  920. // field=1, type=varint = tag of 8
  921. const int expectedTag = 8;
  922. int length = input.ReadLength();
  923. if (length == 0)
  924. {
  925. return 0L;
  926. }
  927. int finalBufferPos = input.totalBytesRetired + input.bufferPos + length;
  928. ulong result = 0L;
  929. do
  930. {
  931. if (input.ReadTag() == expectedTag)
  932. {
  933. result = input.ReadUInt64();
  934. }
  935. else
  936. {
  937. input.SkipLastField();
  938. }
  939. }
  940. while (input.totalBytesRetired + input.bufferPos < finalBufferPos);
  941. return result;
  942. }
  943. internal static long? ReadInt64Wrapper(CodedInputStream input)
  944. {
  945. return (long?)ReadUInt64Wrapper(input);
  946. }
  947. #endregion
  948. #region Underlying reading primitives
  949. /// <summary>
  950. /// Same code as ReadRawVarint32, but read each byte individually, checking for
  951. /// buffer overflow.
  952. /// </summary>
  953. private uint SlowReadRawVarint32()
  954. {
  955. int tmp = ReadRawByte();
  956. if (tmp < 128)
  957. {
  958. return (uint) tmp;
  959. }
  960. int result = tmp & 0x7f;
  961. if ((tmp = ReadRawByte()) < 128)
  962. {
  963. result |= tmp << 7;
  964. }
  965. else
  966. {
  967. result |= (tmp & 0x7f) << 7;
  968. if ((tmp = ReadRawByte()) < 128)
  969. {
  970. result |= tmp << 14;
  971. }
  972. else
  973. {
  974. result |= (tmp & 0x7f) << 14;
  975. if ((tmp = ReadRawByte()) < 128)
  976. {
  977. result |= tmp << 21;
  978. }
  979. else
  980. {
  981. result |= (tmp & 0x7f) << 21;
  982. result |= (tmp = ReadRawByte()) << 28;
  983. if (tmp >= 128)
  984. {
  985. // Discard upper 32 bits.
  986. for (int i = 0; i < 5; i++)
  987. {
  988. if (ReadRawByte() < 128)
  989. {
  990. return (uint) result;
  991. }
  992. }
  993. throw InvalidProtocolBufferException.MalformedVarint();
  994. }
  995. }
  996. }
  997. }
  998. return (uint) result;
  999. }
  1000. /// <summary>
  1001. /// Reads a raw Varint from the stream. If larger than 32 bits, discard the upper bits.
  1002. /// This method is optimised for the case where we've got lots of data in the buffer.
  1003. /// That means we can check the size just once, then just read directly from the buffer
  1004. /// without constant rechecking of the buffer length.
  1005. /// </summary>
  1006. internal uint ReadRawVarint32()
  1007. {
  1008. if (bufferPos + 5 > bufferSize)
  1009. {
  1010. return SlowReadRawVarint32();
  1011. }
  1012. int tmp = buffer[bufferPos++];
  1013. if (tmp < 128)
  1014. {
  1015. return (uint) tmp;
  1016. }
  1017. int result = tmp & 0x7f;
  1018. if ((tmp = buffer[bufferPos++]) < 128)
  1019. {
  1020. result |= tmp << 7;
  1021. }
  1022. else
  1023. {
  1024. result |= (tmp & 0x7f) << 7;
  1025. if ((tmp = buffer[bufferPos++]) < 128)
  1026. {
  1027. result |= tmp << 14;
  1028. }
  1029. else
  1030. {
  1031. result |= (tmp & 0x7f) << 14;
  1032. if ((tmp = buffer[bufferPos++]) < 128)
  1033. {
  1034. result |= tmp << 21;
  1035. }
  1036. else
  1037. {
  1038. result |= (tmp & 0x7f) << 21;
  1039. result |= (tmp = buffer[bufferPos++]) << 28;
  1040. if (tmp >= 128)
  1041. {
  1042. // Discard upper 32 bits.
  1043. // Note that this has to use ReadRawByte() as we only ensure we've
  1044. // got at least 5 bytes at the start of the method. This lets us
  1045. // use the fast path in more cases, and we rarely hit this section of code.
  1046. for (int i = 0; i < 5; i++)
  1047. {
  1048. if (ReadRawByte() < 128)
  1049. {
  1050. return (uint) result;
  1051. }
  1052. }
  1053. throw InvalidProtocolBufferException.MalformedVarint();
  1054. }
  1055. }
  1056. }
  1057. }
  1058. return (uint) result;
  1059. }
  1060. /// <summary>
  1061. /// Reads a varint from the input one byte at a time, so that it does not
  1062. /// read any bytes after the end of the varint. If you simply wrapped the
  1063. /// stream in a CodedInputStream and used ReadRawVarint32(Stream)
  1064. /// then you would probably end up reading past the end of the varint since
  1065. /// CodedInputStream buffers its input.
  1066. /// </summary>
  1067. /// <param name="input"></param>
  1068. /// <returns></returns>
  1069. internal static uint ReadRawVarint32(Stream input)
  1070. {
  1071. int result = 0;
  1072. int offset = 0;
  1073. for (; offset < 32; offset += 7)
  1074. {
  1075. int b = input.ReadByte();
  1076. if (b == -1)
  1077. {
  1078. throw InvalidProtocolBufferException.TruncatedMessage();
  1079. }
  1080. result |= (b & 0x7f) << offset;
  1081. if ((b & 0x80) == 0)
  1082. {
  1083. return (uint) result;
  1084. }
  1085. }
  1086. // Keep reading up to 64 bits.
  1087. for (; offset < 64; offset += 7)
  1088. {
  1089. int b = input.ReadByte();
  1090. if (b == -1)
  1091. {
  1092. throw InvalidProtocolBufferException.TruncatedMessage();
  1093. }
  1094. if ((b & 0x80) == 0)
  1095. {
  1096. return (uint) result;
  1097. }
  1098. }
  1099. throw InvalidProtocolBufferException.MalformedVarint();
  1100. }
  1101. /// <summary>
  1102. /// Reads a raw varint from the stream.
  1103. /// </summary>
  1104. internal ulong ReadRawVarint64()
  1105. {
  1106. if (bufferPos + 10 <= bufferSize)
  1107. {
  1108. ulong result = buffer[bufferPos++];
  1109. if (result < 128)
  1110. {
  1111. return result;
  1112. }
  1113. result &= 0x7f;
  1114. int shift = 7;
  1115. do
  1116. {
  1117. byte b = buffer[bufferPos++];
  1118. result |= (ulong)(b & 0x7F) << shift;
  1119. if (b < 0x80)
  1120. {
  1121. return result;
  1122. }
  1123. shift += 7;
  1124. }
  1125. while (shift < 64);
  1126. }
  1127. else
  1128. {
  1129. int shift = 0;
  1130. ulong result = 0;
  1131. do
  1132. {
  1133. byte b = ReadRawByte();
  1134. result |= (ulong)(b & 0x7F) << shift;
  1135. if (b < 0x80)
  1136. {
  1137. return result;
  1138. }
  1139. shift += 7;
  1140. }
  1141. while (shift < 64);
  1142. }
  1143. throw InvalidProtocolBufferException.MalformedVarint();
  1144. }
  1145. /// <summary>
  1146. /// Reads a 32-bit little-endian integer from the stream.
  1147. /// </summary>
  1148. internal uint ReadRawLittleEndian32()
  1149. {
  1150. if (bufferPos + 4 <= bufferSize)
  1151. {
  1152. if (BitConverter.IsLittleEndian)
  1153. {
  1154. var result = BitConverter.ToUInt32(buffer, bufferPos);
  1155. bufferPos += 4;
  1156. return result;
  1157. }
  1158. else
  1159. {
  1160. uint b1 = buffer[bufferPos];
  1161. uint b2 = buffer[bufferPos + 1];
  1162. uint b3 = buffer[bufferPos + 2];
  1163. uint b4 = buffer[bufferPos + 3];
  1164. bufferPos += 4;
  1165. return b1 | (b2 << 8) | (b3 << 16) | (b4 << 24);
  1166. }
  1167. }
  1168. else
  1169. {
  1170. uint b1 = ReadRawByte();
  1171. uint b2 = ReadRawByte();
  1172. uint b3 = ReadRawByte();
  1173. uint b4 = ReadRawByte();
  1174. return b1 | (b2 << 8) | (b3 << 16) | (b4 << 24);
  1175. }
  1176. }
  1177. /// <summary>
  1178. /// Reads a 64-bit little-endian integer from the stream.
  1179. /// </summary>
  1180. internal ulong ReadRawLittleEndian64()
  1181. {
  1182. if (bufferPos + 8 <= bufferSize)
  1183. {
  1184. if (BitConverter.IsLittleEndian)
  1185. {
  1186. var result = BitConverter.ToUInt64(buffer, bufferPos);
  1187. bufferPos += 8;
  1188. return result;
  1189. }
  1190. else
  1191. {
  1192. ulong b1 = buffer[bufferPos];
  1193. ulong b2 = buffer[bufferPos + 1];
  1194. ulong b3 = buffer[bufferPos + 2];
  1195. ulong b4 = buffer[bufferPos + 3];
  1196. ulong b5 = buffer[bufferPos + 4];
  1197. ulong b6 = buffer[bufferPos + 5];
  1198. ulong b7 = buffer[bufferPos + 6];
  1199. ulong b8 = buffer[bufferPos + 7];
  1200. bufferPos += 8;
  1201. return b1 | (b2 << 8) | (b3 << 16) | (b4 << 24)
  1202. | (b5 << 32) | (b6 << 40) | (b7 << 48) | (b8 << 56);
  1203. }
  1204. }
  1205. else
  1206. {
  1207. ulong b1 = ReadRawByte();
  1208. ulong b2 = ReadRawByte();
  1209. ulong b3 = ReadRawByte();
  1210. ulong b4 = ReadRawByte();
  1211. ulong b5 = ReadRawByte();
  1212. ulong b6 = ReadRawByte();
  1213. ulong b7 = ReadRawByte();
  1214. ulong b8 = ReadRawByte();
  1215. return b1 | (b2 << 8) | (b3 << 16) | (b4 << 24)
  1216. | (b5 << 32) | (b6 << 40) | (b7 << 48) | (b8 << 56);
  1217. }
  1218. }
  1219. /// <summary>
  1220. /// Decode a 32-bit value with ZigZag encoding.
  1221. /// </summary>
  1222. /// <remarks>
  1223. /// ZigZag encodes signed integers into values that can be efficiently
  1224. /// encoded with varint. (Otherwise, negative values must be
  1225. /// sign-extended to 64 bits to be varint encoded, thus always taking
  1226. /// 10 bytes on the wire.)
  1227. /// </remarks>
  1228. internal static int DecodeZigZag32(uint n)
  1229. {
  1230. return (int)(n >> 1) ^ -(int)(n & 1);
  1231. }
  1232. /// <summary>
  1233. /// Decode a 32-bit value with ZigZag encoding.
  1234. /// </summary>
  1235. /// <remarks>
  1236. /// ZigZag encodes signed integers into values that can be efficiently
  1237. /// encoded with varint. (Otherwise, negative values must be
  1238. /// sign-extended to 64 bits to be varint encoded, thus always taking
  1239. /// 10 bytes on the wire.)
  1240. /// </remarks>
  1241. internal static long DecodeZigZag64(ulong n)
  1242. {
  1243. return (long)(n >> 1) ^ -(long)(n & 1);
  1244. }
  1245. #endregion
  1246. #region Internal reading and buffer management
  1247. /// <summary>
  1248. /// Sets currentLimit to (current position) + byteLimit. This is called
  1249. /// when descending into a length-delimited embedded message. The previous
  1250. /// limit is returned.
  1251. /// </summary>
  1252. /// <returns>The old limit.</returns>
  1253. internal int PushLimit(int byteLimit)
  1254. {
  1255. if (byteLimit < 0)
  1256. {
  1257. throw InvalidProtocolBufferException.NegativeSize();
  1258. }
  1259. byteLimit += totalBytesRetired + bufferPos;
  1260. int oldLimit = currentLimit;
  1261. if (byteLimit > oldLimit)
  1262. {
  1263. throw InvalidProtocolBufferException.TruncatedMessage();
  1264. }
  1265. currentLimit = byteLimit;
  1266. RecomputeBufferSizeAfterLimit();
  1267. return oldLimit;
  1268. }
  1269. private void RecomputeBufferSizeAfterLimit()
  1270. {
  1271. bufferSize += bufferSizeAfterLimit;
  1272. int bufferEnd = totalBytesRetired + bufferSize;
  1273. if (bufferEnd > currentLimit)
  1274. {
  1275. // Limit is in current buffer.
  1276. bufferSizeAfterLimit = bufferEnd - currentLimit;
  1277. bufferSize -= bufferSizeAfterLimit;
  1278. }
  1279. else
  1280. {
  1281. bufferSizeAfterLimit = 0;
  1282. }
  1283. }
  1284. /// <summary>
  1285. /// Discards the current limit, returning the previous limit.
  1286. /// </summary>
  1287. internal void PopLimit(int oldLimit)
  1288. {
  1289. currentLimit = oldLimit;
  1290. RecomputeBufferSizeAfterLimit();
  1291. }
  1292. /// <summary>
  1293. /// Returns whether or not all the data before the limit has been read.
  1294. /// </summary>
  1295. /// <returns></returns>
  1296. internal bool ReachedLimit
  1297. {
  1298. get
  1299. {
  1300. if (currentLimit == int.MaxValue)
  1301. {
  1302. return false;
  1303. }
  1304. int currentAbsolutePosition = totalBytesRetired + bufferPos;
  1305. return currentAbsolutePosition >= currentLimit;
  1306. }
  1307. }
  1308. /// <summary>
  1309. /// Returns true if the stream has reached the end of the input. This is the
  1310. /// case if either the end of the underlying input source has been reached or
  1311. /// the stream has reached a limit created using PushLimit.
  1312. /// </summary>
  1313. public bool IsAtEnd
  1314. {
  1315. get { return bufferPos == bufferSize && !RefillBuffer(false); }
  1316. }
  1317. /// <summary>
  1318. /// Called when buffer is empty to read more bytes from the
  1319. /// input. If <paramref name="mustSucceed"/> is true, RefillBuffer() gurantees that
  1320. /// either there will be at least one byte in the buffer when it returns
  1321. /// or it will throw an exception. If <paramref name="mustSucceed"/> is false,
  1322. /// RefillBuffer() returns false if no more bytes were available.
  1323. /// </summary>
  1324. /// <param name="mustSucceed"></param>
  1325. /// <returns></returns>
  1326. private bool RefillBuffer(bool mustSucceed)
  1327. {
  1328. if (bufferPos < bufferSize)
  1329. {
  1330. throw new InvalidOperationException("RefillBuffer() called when buffer wasn't empty.");
  1331. }
  1332. if (totalBytesRetired + bufferSize == currentLimit)
  1333. {
  1334. // Oops, we hit a limit.
  1335. if (mustSucceed)
  1336. {
  1337. throw InvalidProtocolBufferException.TruncatedMessage();
  1338. }
  1339. else
  1340. {
  1341. return false;
  1342. }
  1343. }
  1344. totalBytesRetired += bufferSize;
  1345. bufferPos = 0;
  1346. bufferSize = (input == null) ? 0 : input.Read(buffer, 0, buffer.Length);
  1347. if (bufferSize < 0)
  1348. {
  1349. throw new InvalidOperationException("Stream.Read returned a negative count");
  1350. }
  1351. if (bufferSize == 0)
  1352. {
  1353. if (mustSucceed)
  1354. {
  1355. throw InvalidProtocolBufferException.TruncatedMessage();
  1356. }
  1357. else
  1358. {
  1359. return false;
  1360. }
  1361. }
  1362. else
  1363. {
  1364. RecomputeBufferSizeAfterLimit();
  1365. int totalBytesRead =
  1366. totalBytesRetired + bufferSize + bufferSizeAfterLimit;
  1367. if (totalBytesRead < 0 || totalBytesRead > sizeLimit)
  1368. {
  1369. throw InvalidProtocolBufferException.SizeLimitExceeded();
  1370. }
  1371. return true;
  1372. }
  1373. }
  1374. /// <summary>
  1375. /// Read one byte from the input.
  1376. /// </summary>
  1377. /// <exception cref="InvalidProtocolBufferException">
  1378. /// the end of the stream or the current limit was reached
  1379. /// </exception>
  1380. internal byte ReadRawByte()
  1381. {
  1382. if (bufferPos == bufferSize)
  1383. {
  1384. RefillBuffer(true);
  1385. }
  1386. return buffer[bufferPos++];
  1387. }
  1388. /// <summary>
  1389. /// Reads a fixed size of bytes from the input.
  1390. /// </summary>
  1391. /// <exception cref="InvalidProtocolBufferException">
  1392. /// the end of the stream or the current limit was reached
  1393. /// </exception>
  1394. internal byte[] ReadRawBytes(int size)
  1395. {
  1396. if (size < 0)
  1397. {
  1398. throw InvalidProtocolBufferException.NegativeSize();
  1399. }
  1400. if (totalBytesRetired + bufferPos + size > currentLimit)
  1401. {
  1402. // Read to the end of the stream (up to the current limit) anyway.
  1403. SkipRawBytes(currentLimit - totalBytesRetired - bufferPos);
  1404. // Then fail.
  1405. throw InvalidProtocolBufferException.TruncatedMessage();
  1406. }
  1407. if (size <= bufferSize - bufferPos)
  1408. {
  1409. // We have all the bytes we need already.
  1410. byte[] bytes = new byte[size];
  1411. ByteArray.Copy(buffer, bufferPos, bytes, 0, size);
  1412. bufferPos += size;
  1413. return bytes;
  1414. }
  1415. else if (size < buffer.Length)
  1416. {
  1417. // Reading more bytes than are in the buffer, but not an excessive number
  1418. // of bytes. We can safely allocate the resulting array ahead of time.
  1419. // First copy what we have.
  1420. byte[] bytes = new byte[size];
  1421. int pos = bufferSize - bufferPos;
  1422. ByteArray.Copy(buffer, bufferPos, bytes, 0, pos);
  1423. bufferPos = bufferSize;
  1424. // We want to use RefillBuffer() and then copy from the buffer into our
  1425. // byte array rather than reading directly into our byte array because
  1426. // the input may be unbuffered.
  1427. RefillBuffer(true);
  1428. while (size - pos > bufferSize)
  1429. {
  1430. Buffer.BlockCopy(buffer, 0, bytes, pos, bufferSize);
  1431. pos += bufferSize;
  1432. bufferPos = bufferSize;
  1433. RefillBuffer(true);
  1434. }
  1435. ByteArray.Copy(buffer, 0, bytes, pos, size - pos);
  1436. bufferPos = size - pos;
  1437. return bytes;
  1438. }
  1439. else
  1440. {
  1441. // The size is very large. For security reasons, we can't allocate the
  1442. // entire byte array yet. The size comes directly from the input, so a
  1443. // maliciously-crafted message could provide a bogus very large size in
  1444. // order to trick the app into allocating a lot of memory. We avoid this
  1445. // by allocating and reading only a small chunk at a time, so that the
  1446. // malicious message must actually *be* extremely large to cause
  1447. // problems. Meanwhile, we limit the allowed size of a message elsewhere.
  1448. // Remember the buffer markers since we'll have to copy the bytes out of
  1449. // it later.
  1450. int originalBufferPos = bufferPos;
  1451. int originalBufferSize = bufferSize;
  1452. // Mark the current buffer consumed.
  1453. totalBytesRetired += bufferSize;
  1454. bufferPos = 0;
  1455. bufferSize = 0;
  1456. // Read all the rest of the bytes we need.
  1457. int sizeLeft = size - (originalBufferSize - originalBufferPos);
  1458. List<byte[]> chunks = new List<byte[]>();
  1459. while (sizeLeft > 0)
  1460. {
  1461. byte[] chunk = new byte[Math.Min(sizeLeft, buffer.Length)];
  1462. int pos = 0;
  1463. while (pos < chunk.Length)
  1464. {
  1465. int n = (input == null) ? -1 : input.Read(chunk, pos, chunk.Length - pos);
  1466. if (n <= 0)
  1467. {
  1468. throw InvalidProtocolBufferException.TruncatedMessage();
  1469. }
  1470. totalBytesRetired += n;
  1471. pos += n;
  1472. }
  1473. sizeLeft -= chunk.Length;
  1474. chunks.Add(chunk);
  1475. }
  1476. // OK, got everything. Now concatenate it all into one buffer.
  1477. byte[] bytes = new byte[size];
  1478. // Start by copying the leftover bytes from this.buffer.
  1479. int newPos = originalBufferSize - originalBufferPos;
  1480. ByteArray.Copy(buffer, originalBufferPos, bytes, 0, newPos);
  1481. // And now all the chunks.
  1482. foreach (byte[] chunk in chunks)
  1483. {
  1484. Buffer.BlockCopy(chunk, 0, bytes, newPos, chunk.Length);
  1485. newPos += chunk.Length;
  1486. }
  1487. // Done.
  1488. return bytes;
  1489. }
  1490. }
  1491. /// <summary>
  1492. /// Reads and discards <paramref name="size"/> bytes.
  1493. /// </summary>
  1494. /// <exception cref="InvalidProtocolBufferException">the end of the stream
  1495. /// or the current limit was reached</exception>
  1496. private void SkipRawBytes(int size)
  1497. {
  1498. if (size < 0)
  1499. {
  1500. throw InvalidProtocolBufferException.NegativeSize();
  1501. }
  1502. if (totalBytesRetired + bufferPos + size > currentLimit)
  1503. {
  1504. // Read to the end of the stream anyway.
  1505. SkipRawBytes(currentLimit - totalBytesRetired - bufferPos);
  1506. // Then fail.
  1507. throw InvalidProtocolBufferException.TruncatedMessage();
  1508. }
  1509. if (size <= bufferSize - bufferPos)
  1510. {
  1511. // We have all the bytes we need already.
  1512. bufferPos += size;
  1513. }
  1514. else
  1515. {
  1516. // Skipping more bytes than are in the buffer. First skip what we have.
  1517. int pos = bufferSize - bufferPos;
  1518. // ROK 5/7/2013 Issue #54: should retire all bytes in buffer (bufferSize)
  1519. // totalBytesRetired += pos;
  1520. totalBytesRetired += bufferSize;
  1521. bufferPos = 0;
  1522. bufferSize = 0;
  1523. // Then skip directly from the InputStream for the rest.
  1524. if (pos < size)
  1525. {
  1526. if (input == null)
  1527. {
  1528. throw InvalidProtocolBufferException.TruncatedMessage();
  1529. }
  1530. SkipImpl(size - pos);
  1531. totalBytesRetired += size - pos;
  1532. }
  1533. }
  1534. }
  1535. /// <summary>
  1536. /// Abstraction of skipping to cope with streams which can't really skip.
  1537. /// </summary>
  1538. private void SkipImpl(int amountToSkip)
  1539. {
  1540. if (input.CanSeek)
  1541. {
  1542. long previousPosition = input.Position;
  1543. input.Position += amountToSkip;
  1544. if (input.Position != previousPosition + amountToSkip)
  1545. {
  1546. throw InvalidProtocolBufferException.TruncatedMessage();
  1547. }
  1548. }
  1549. else
  1550. {
  1551. byte[] skipBuffer = new byte[Math.Min(1024, amountToSkip)];
  1552. while (amountToSkip > 0)
  1553. {
  1554. int bytesRead = input.Read(skipBuffer, 0, Math.Min(skipBuffer.Length, amountToSkip));
  1555. if (bytesRead <= 0)
  1556. {
  1557. throw InvalidProtocolBufferException.TruncatedMessage();
  1558. }
  1559. amountToSkip -= bytesRead;
  1560. }
  1561. }
  1562. }
  1563. #endregion
  1564. }
  1565. }