private static void EndSubItem(SubItemToken token, ProtoWriter writer, PrefixStyle style) { if (writer == null) { throw new ArgumentNullException("writer"); } if (writer.wireType != WireType.None) { throw CreateException(writer); } int value = token.value; if (writer.depth <= 0) { throw CreateException(writer); } if (writer.depth-- > RecursionCheckDepth) { writer.PopRecursionStack(); } writer.packedFieldNumber = 0; // ending the sub-item always wipes packed encoding if (value < 0) { // group - very simple append WriteHeaderCore(-value, WireType.EndGroup, writer); writer.wireType = WireType.None; return; } // so we're backfilling the length into an existing sequence int len; switch (style) { case PrefixStyle.Fixed32: len = (int)((writer.ioIndex - value) - 4); ProtoWriter.WriteInt32ToBuffer(len, writer.ioBuffer, value); break; case PrefixStyle.Fixed32BigEndian: len = (int)((writer.ioIndex - value) - 4); byte[] buffer = writer.ioBuffer; ProtoWriter.WriteInt32ToBuffer(len, buffer, value); // and swap the byte order byte b = buffer[value]; buffer[value] = buffer[value + 3]; buffer[value + 3] = b; b = buffer[value + 1]; buffer[value + 1] = buffer[value + 2]; buffer[value + 2] = b; break; case PrefixStyle.Base128: // string - complicated because we only reserved one byte; // if the prefix turns out to need more than this then // we need to shuffle the existing data len = (int)((writer.ioIndex - value) - 1); int offset = 0; uint tmp = (uint)len; while ((tmp >>= 7) != 0) { offset++; } if (offset == 0) { writer.ioBuffer[value] = (byte)(len & 0x7F); } else { DemandSpace(offset, writer); byte[] blob = writer.ioBuffer; Helpers.BlockCopy(blob, value + 1, blob, value + 1 + offset, len); tmp = (uint)len; do { blob[value++] = (byte)((tmp & 0x7F) | 0x80); } while ((tmp >>= 7) != 0); blob[value - 1] = (byte)(blob[value - 1] & ~0x80); writer.position += offset; writer.ioIndex += offset; } break; default: throw new ArgumentOutOfRangeException("style"); } // and this object is no longer a blockage - also flush if sensible const int ADVISORY_FLUSH_SIZE = 1024; if (--writer.flushLock == 0 && writer.ioIndex >= ADVISORY_FLUSH_SIZE) { ProtoWriter.Flush(writer); } }