in Microsoft.Azure.Cosmos/src/Json/JsonWriter.JsonBinaryWriter.cs [831:1017]
private void WriteArrayOrObjectEnd(bool isArray)
{
this.JsonObjectState.RegisterToken(isArray ? JsonTokenType.EndArray : JsonTokenType.EndObject);
ArrayAndObjectInfo 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;
int stringStartIndex = (int)nestedContext.StringStartIndex;
int stringReferenceStartIndex = (int)nestedContext.StringReferenceStartIndex;
// 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 ? TypeMarker.Arr0 : TypeMarker.Obj0);
}
else if (count == 1)
{
// Single-property object
// Move the buffer back but leave one byte for the typemarker
Span<byte> buffer = this.binaryWriter.BufferAsSpan;
int bytesToWrite = TypeMarkerLength;
this.MoveBuffer(buffer, payloadIndex, payloadLength, typeMarkerIndex, bytesToWrite, stringStartIndex, stringReferenceStartIndex);
// Move the cursor back
this.binaryWriter.Position = typeMarkerIndex;
// Write the type marker
this.binaryWriter.Write(isArray ? TypeMarker.Arr1 : TypeMarker.Obj1);
// Move the cursor forward
this.binaryWriter.Position = typeMarkerIndex + TypeMarkerLength + payloadLength;
}
else
{
// Need to figure out how many bytes to encode the length and the count
int bytesToWrite;
if (payloadLength <= byte.MaxValue)
{
bool serializeCount = isArray && (count > 16);
// 1 byte length - move the buffer forward
Span<byte> buffer = this.binaryWriter.BufferAsSpan;
bytesToWrite = TypeMarkerLength
+ JsonBinaryEncoding.OneByteLength
+ (serializeCount ? JsonBinaryEncoding.OneByteCount : 0);
this.MoveBuffer(buffer, payloadIndex, payloadLength, typeMarkerIndex, bytesToWrite, stringStartIndex, stringReferenceStartIndex);
// Move the cursor back
this.binaryWriter.Position = typeMarkerIndex;
// Write the type marker
if (serializeCount)
{
this.binaryWriter.Write(isArray ? TypeMarker.ArrLC1 : TypeMarker.ObjLC1);
this.binaryWriter.Write((byte)payloadLength);
this.binaryWriter.Write((byte)count);
}
else
{
this.binaryWriter.Write(isArray ? TypeMarker.ArrL1 : TypeMarker.ObjL1);
this.binaryWriter.Write((byte)payloadLength);
}
}
else if (payloadLength <= ushort.MaxValue)
{
bool serializeCount = isArray && ((count > 16) || (payloadLength > 0x1000));
// 2 byte length - make space for the extra byte length (and extra byte count)
this.binaryWriter.Write((byte)0);
if (serializeCount)
{
this.binaryWriter.Write((byte)0);
}
// Move the buffer forward
Span<byte> buffer = this.binaryWriter.BufferAsSpan;
bytesToWrite = TypeMarkerLength
+ JsonBinaryEncoding.TwoByteLength
+ (serializeCount ? JsonBinaryEncoding.TwoByteCount : 0);
this.MoveBuffer(buffer, payloadIndex, payloadLength, typeMarkerIndex, bytesToWrite, stringStartIndex, stringReferenceStartIndex);
// Move the cursor back
this.binaryWriter.Position = typeMarkerIndex;
// Write the type marker
if (serializeCount)
{
this.binaryWriter.Write(isArray ? TypeMarker.ArrLC2 : TypeMarker.ObjLC2);
this.binaryWriter.Write((ushort)payloadLength);
this.binaryWriter.Write((ushort)count);
}
else
{
this.binaryWriter.Write(isArray ? TypeMarker.ArrL2 : TypeMarker.ObjL2);
this.binaryWriter.Write((ushort)payloadLength);
}
}
else
{
// (payloadLength <= uint.MaxValue)
bool serializeCount = isArray;
// 4 byte length - make space for an extra 3 byte length (and 3 byte count)
this.binaryWriter.Write((byte)0);
this.binaryWriter.Write((ushort)0);
if (serializeCount)
{
this.binaryWriter.Write((byte)0);
this.binaryWriter.Write((ushort)0);
}
// Move the buffer forward
Span<byte> buffer = this.binaryWriter.BufferAsSpan;
bytesToWrite = TypeMarkerLength
+ JsonBinaryEncoding.FourByteLength
+ (serializeCount ? JsonBinaryEncoding.FourByteCount : 0);
this.MoveBuffer(buffer, payloadIndex, payloadLength, typeMarkerIndex, bytesToWrite, stringStartIndex, stringReferenceStartIndex);
// Move the cursor back
this.binaryWriter.Position = typeMarkerIndex;
// Write the type marker
if (serializeCount)
{
this.binaryWriter.Write(isArray ? TypeMarker.ArrLC4 : TypeMarker.ObjLC4);
this.binaryWriter.Write((uint)payloadLength);
this.binaryWriter.Write((uint)count);
}
else
{
this.binaryWriter.Write(isArray ? TypeMarker.ArrL4 : TypeMarker.ObjL4);
this.binaryWriter.Write((uint)payloadLength);
}
}
// For an array, attempt to convert it to a uniform number array
bool isUniformArray;
if (isArray && (payloadLength > 4) && this.enableNumberArrays)
{
this.binaryWriter.Position = typeMarkerIndex;
isUniformArray = TryWriteUniformNumberArray(
this.binaryWriter,
bytesToWrite,
payloadLength,
count);
if (!isUniformArray)
{
this.binaryWriter.Position = typeMarkerIndex;
isUniformArray = TryWriteUniformArrayOfNumberArrays(
this.binaryWriter,
bytesToWrite,
payloadLength,
count);
}
}
else
{
isUniformArray = false;
}
// Move the cursor forward if this is not a uniform array
if (!isUniformArray)
{
this.binaryWriter.Position = typeMarkerIndex + bytesToWrite + payloadLength;
}
}
this.bufferedContexts.Peek().Count++;
// If we are closing the outermost array / object, we need to fix up reference string offsets
if (typeMarkerIndex == 1 && this.sharedStrings.Count > 0)
{
this.FixReferenceStringOffsets(this.binaryWriter.BufferAsSpan);
}
}