private void WriteArrayOrObjectEnd(bool isArray) { this.JsonObjectState.RegisterToken(isArray ? JsonTokenType.EndArray : JsonTokenType.EndObject); BeginOffsetAndCount nestedContext = this.bufferedContexts.Pop(); // Do some math int typeMarkerIndex = (int)nestedContext.Offset; int payloadIndex = typeMarkerIndex + this.reservationSize; int originalCursor = (int)this.CurrentLength; int payloadLength = originalCursor - payloadIndex; int count = (int)nestedContext.Count; // Figure out what the typemarker and length should be and do any corrections needed if (count == 0) { // Empty object // Move the cursor back this.binaryWriter.BaseStream.Seek(typeMarkerIndex, SeekOrigin.Begin); // Write the type marker this.binaryWriter.Write( isArray ? JsonBinaryEncoding.TypeMarker.EmptyArray : JsonBinaryEncoding.TypeMarker.EmptyObject); } else if (count == 1) { // Single-property object // Move the buffer back 2 or 4 bytes since we don't need to encode a length byte[] buffer = ((MemoryStream)this.binaryWriter.BaseStream).GetBuffer(); Array.Copy(buffer, payloadIndex, buffer, payloadIndex - (TwoByteLength + (this.serializeCount ? TwoByteCount : 0)), payloadLength); // Move the cursor back this.binaryWriter.BaseStream.Seek(typeMarkerIndex, SeekOrigin.Begin); // Write the type marker this.binaryWriter.Write( isArray ? JsonBinaryEncoding.TypeMarker.SingleItemArray : JsonBinaryEncoding.TypeMarker.SinglePropertyObject); // Move the cursor forward this.binaryWriter.BaseStream.Seek(typeMarkerIndex + TypeMarker + payloadLength, SeekOrigin.Begin); } else { // Need to figure out how many bytes to encode the length and the count if (payloadLength <= byte.MaxValue) { // 1 byte length - move the buffer back byte[] buffer = ((MemoryStream)this.binaryWriter.BaseStream).GetBuffer(); Array.Copy(buffer, payloadIndex, buffer, payloadIndex - (OneByteLength + (this.serializeCount ? OneByteCount : 0)), payloadLength); // Move the cursor back this.binaryWriter.BaseStream.Seek(typeMarkerIndex, SeekOrigin.Begin); // Write the type marker if (this.serializeCount) { this.binaryWriter.Write( isArray ? JsonBinaryEncoding.TypeMarker.Array1ByteLengthAndCount : JsonBinaryEncoding.TypeMarker.Object1ByteLengthAndCount); this.binaryWriter.Write((byte)payloadLength); this.binaryWriter.Write((byte)count); } else { this.binaryWriter.Write( isArray ? JsonBinaryEncoding.TypeMarker.Array1ByteLength : JsonBinaryEncoding.TypeMarker.Object1ByteLength); this.binaryWriter.Write((byte)payloadLength); } // Move the cursor forward this.binaryWriter.BaseStream.Seek(typeMarkerIndex + TypeMarker + OneByteLength + (this.serializeCount ? OneByteCount : 0) + payloadLength, SeekOrigin.Begin); } else if (payloadLength <= ushort.MaxValue) { // 2 byte length - don't need to move the buffer // Move the cursor back this.binaryWriter.BaseStream.Seek(typeMarkerIndex, SeekOrigin.Begin); // Write the type marker if (this.serializeCount) { this.binaryWriter.Write( isArray ? JsonBinaryEncoding.TypeMarker.Array2ByteLengthAndCount : JsonBinaryEncoding.TypeMarker.Object2ByteLengthAndCount); this.binaryWriter.Write((ushort)payloadLength); this.binaryWriter.Write((ushort)count); } else { this.binaryWriter.Write( isArray ? JsonBinaryEncoding.TypeMarker.Array2ByteLength : JsonBinaryEncoding.TypeMarker.Object2ByteLength); this.binaryWriter.Write((ushort)payloadLength); } // Move the cursor forward this.binaryWriter.BaseStream.Seek(typeMarkerIndex + TypeMarker + TwoByteLength + (this.serializeCount ? TwoByteCount : 0) + payloadLength, SeekOrigin.Begin); } else { // (payloadLength <= uint.MaxValue) // 4 byte length - make space for an extra 2 byte length (and 2 byte count) this.binaryWriter.Write((ushort)0); if (this.serializeCount) { this.binaryWriter.Write((ushort)0); } // Move the buffer forward byte[] buffer = ((MemoryStream)this.binaryWriter.BaseStream).GetBuffer(); Array.Copy(buffer, payloadIndex, buffer, payloadIndex + TwoByteLength + (this.serializeCount ? TwoByteCount : 0), payloadLength); // Move the cursor back this.binaryWriter.BaseStream.Seek(typeMarkerIndex, SeekOrigin.Begin); // Write the type marker if (this.serializeCount) { this.binaryWriter.Write( isArray ? JsonBinaryEncoding.TypeMarker.Array4ByteLengthAndCount : JsonBinaryEncoding.TypeMarker.Object4ByteLengthAndCount); this.binaryWriter.Write((uint)payloadLength); this.binaryWriter.Write((uint)count); } else { this.binaryWriter.Write( isArray ? JsonBinaryEncoding.TypeMarker.Array4ByteLength : JsonBinaryEncoding.TypeMarker.Object4ByteLength); this.binaryWriter.Write((uint)payloadLength); } // Move the cursor forward this.binaryWriter.BaseStream.Seek(typeMarkerIndex + TypeMarker + FourByteLength + (this.serializeCount ? FourByteCount : 0) + payloadLength, SeekOrigin.Begin); } } this.bufferedContexts.Peek().Count++; }
private void WriteArrayOrObjectEnd(bool isArray) { this.JsonObjectState.RegisterToken(isArray ? JsonTokenType.EndArray : JsonTokenType.EndObject); BeginOffsetAndCount nestedContext = this.bufferedContexts.Pop(); // Do some math int typeMarkerIndex = (int)nestedContext.Offset; int payloadIndex = typeMarkerIndex + this.reservationSize; int originalCursor = (int)this.CurrentLength; int payloadLength = originalCursor - payloadIndex; int count = (int)nestedContext.Count; // Figure out what the typemarker and length should be and do any corrections needed if (count == 0) { // Empty object // Move the cursor back this.binaryWriter.Position = typeMarkerIndex; // Write the type marker this.binaryWriter.Write( isArray ? JsonBinaryEncoding.TypeMarker.EmptyArray : JsonBinaryEncoding.TypeMarker.EmptyObject); } else if (count == 1) { // Single-property object // Move the buffer back but leave one byte for the typemarker Memory <byte> buffer = this.binaryWriter.Buffer; buffer.Slice(payloadIndex).CopyTo(buffer.Slice(typeMarkerIndex + JsonBinaryEncoding.TypeMarkerLength)); // Move the cursor back this.binaryWriter.Position = typeMarkerIndex; // Write the type marker this.binaryWriter.Write( isArray ? JsonBinaryEncoding.TypeMarker.SingleItemArray : JsonBinaryEncoding.TypeMarker.SinglePropertyObject); // Move the cursor forward this.binaryWriter.Position = typeMarkerIndex + JsonBinaryEncoding.TypeMarkerLength + payloadLength; } else { // Need to figure out how many bytes to encode the length and the count if (payloadLength <= byte.MaxValue) { // 1 byte length - don't need to move the buffer int bytesToWrite = JsonBinaryEncoding.TypeMarkerLength + JsonBinaryEncoding.OneByteLength + (this.serializeCount ? JsonBinaryEncoding.OneByteCount : 0); // Move the cursor back this.binaryWriter.Position = typeMarkerIndex; // Write the type marker if (this.serializeCount) { this.binaryWriter.Write( isArray ? JsonBinaryEncoding.TypeMarker.Array1ByteLengthAndCount : JsonBinaryEncoding.TypeMarker.Object1ByteLengthAndCount); this.binaryWriter.Write((byte)payloadLength); this.binaryWriter.Write((byte)count); } else { this.binaryWriter.Write( isArray ? JsonBinaryEncoding.TypeMarker.Array1ByteLength : JsonBinaryEncoding.TypeMarker.Object1ByteLength); this.binaryWriter.Write((byte)payloadLength); } // Move the cursor forward this.binaryWriter.Position = typeMarkerIndex + bytesToWrite + payloadLength; } else if (payloadLength <= ushort.MaxValue) { // 2 byte length - make space for the extra byte length (and extra byte count) this.binaryWriter.Write((byte)0); if (this.serializeCount) { this.binaryWriter.Write((byte)0); } // Move the buffer forward Memory <byte> buffer = this.binaryWriter.Buffer; int bytesToWrite = JsonBinaryEncoding.TypeMarkerLength + JsonBinaryEncoding.TwoByteLength + (this.serializeCount ? JsonBinaryEncoding.TwoByteCount : 0); Memory <byte> payload = buffer.Slice(payloadIndex, payloadLength); Memory <byte> newPayloadStart = buffer.Slice(typeMarkerIndex + bytesToWrite); payload.CopyTo(newPayloadStart); // Move the cursor back this.binaryWriter.Position = typeMarkerIndex; // Write the type marker if (this.serializeCount) { this.binaryWriter.Write( isArray ? JsonBinaryEncoding.TypeMarker.Array2ByteLengthAndCount : JsonBinaryEncoding.TypeMarker.Object2ByteLengthAndCount); this.binaryWriter.Write((ushort)payloadLength); this.binaryWriter.Write((ushort)count); } else { this.binaryWriter.Write( isArray ? JsonBinaryEncoding.TypeMarker.Array2ByteLength : JsonBinaryEncoding.TypeMarker.Object2ByteLength); this.binaryWriter.Write((ushort)payloadLength); } // Move the cursor forward this.binaryWriter.Position = typeMarkerIndex + bytesToWrite + payloadLength; } else { // (payloadLength <= uint.MaxValue) // 4 byte length - make space for an extra 2 byte length (and 2 byte count) this.binaryWriter.Write((ushort)0); if (this.serializeCount) { this.binaryWriter.Write((ushort)0); } // Move the buffer forward Memory <byte> buffer = this.binaryWriter.Buffer; int bytesToWrite = JsonBinaryEncoding.TypeMarkerLength + JsonBinaryEncoding.FourByteLength + (this.serializeCount ? JsonBinaryEncoding.FourByteCount : 0); Memory <byte> payload = buffer.Slice(payloadIndex, payloadLength); Memory <byte> newPayloadStart = buffer.Slice(typeMarkerIndex + bytesToWrite); payload.CopyTo(newPayloadStart); // Move the cursor back this.binaryWriter.Position = typeMarkerIndex; // Write the type marker if (this.serializeCount) { this.binaryWriter.Write( isArray ? JsonBinaryEncoding.TypeMarker.Array4ByteLengthAndCount : JsonBinaryEncoding.TypeMarker.Object4ByteLengthAndCount); this.binaryWriter.Write((uint)payloadLength); this.binaryWriter.Write((uint)count); } else { this.binaryWriter.Write( isArray ? JsonBinaryEncoding.TypeMarker.Array4ByteLength : JsonBinaryEncoding.TypeMarker.Object4ByteLength); this.binaryWriter.Write((uint)payloadLength); } // Move the cursor forward this.binaryWriter.Position = typeMarkerIndex + bytesToWrite + payloadLength; } } this.bufferedContexts.Peek().Count++; }