internal int WriteLengthPrefixed <TValue>(TValue value, uint underEstimatedLength, ILengthProperty <TValue> property) { Flush(); // commit to the stream before monkeying with the buffers... MemoryStream ms = stream as MemoryStream; if (ms != null) { // we'll write to out current stream, optimising // for the case when the length-prefix is 1-byte; // if not we'll have to BlockCopy int startIndex = (int)ms.Position; uint guessLength = underEstimatedLength, guessPrefixLength = (uint)this.EncodeUInt32(guessLength), actualLength = (uint)property.Serialize(value, this); if (guessLength == actualLength) { // good guess! nothing to do... return((int)(guessPrefixLength + actualLength)); } uint actualPrefixLength = (uint)SerializationContext.GetLength(actualLength); Flush(); // commit to the stream before we start messing with it... if (actualPrefixLength < guessPrefixLength) { throw new ProtoException("Internal error; the serializer over-estimated the length. Sorry, but this shouldn't have happened."); } else if (actualPrefixLength > guessPrefixLength) { // our guess of the length turned out to be bad; we need to // fix things... // extend the buffer to ensure we have space for (uint i = actualPrefixLength - guessPrefixLength; i > 0; i--) { ms.WriteByte(0); position++; } // move the data // (note; we MUST call GetBuffer *after* extending it, // otherwise there the buffer might change if we extend // over a boundary) byte[] buffer = ms.GetBuffer(); Buffer.BlockCopy(buffer, (int)(startIndex + guessPrefixLength), buffer, (int)(startIndex + actualPrefixLength), (int)actualLength); } // back-fill the actual length into the buffer SerializationContext.EncodeUInt32(actualLength, ms.GetBuffer(), startIndex); return((int)(actualPrefixLength + actualLength)); } else { // create a temporary stream and write the final result using (ms = new MemoryStream()) { SerializationContext ctx = new SerializationContext(ms, this); int len = property.Serialize(value, ctx); ctx.Flush(); this.ReadFrom(ctx); int preambleLen = this.EncodeInt32(len); byte[] buffer = ms.GetBuffer(); this.WriteBlock(buffer, 0, len); return(preambleLen + len); } } }