/// <summary> /// Compress /// </summary> /// <param name="dataXf">can be null</param> /// <param name="input">input array to compress</param> /// <param name="compressedData"></param> internal void Compress(DataXform dataXf, int[] input, List<byte> compressedData) { // // use the writer to write to the list<byte> // BitStreamWriter writer = new BitStreamWriter(compressedData); if (null != dataXf) { dataXf.ResetState(); int xfData = 0; int xfExtra = 0; for (uint i = 0; i < input.Length; i++) { dataXf.Transform(input[i], ref xfData, ref xfExtra); Encode(xfData, xfExtra, writer); } } else { for (uint i = 0; i < input.Length; i++) { Encode(input[i], 0, writer); } } }
public static void WriteUInt64(this BitStreamWriter writer, UInt64 value) { BitConverterX.UInt64ToUInt32(value, out UInt32 left, out UInt32 right); writer.WriteUInt32(left); writer.WriteUInt32(right); }
public static void WriteUInt16(this BitStreamWriter writer, UInt16 value) { writer.WriteBits(value, 16); }
public static void WriteChar(this BitStreamWriter writer, Char value) { writer.WriteBits(value, 16); }
internal override void WriteToStreamWriter(BitStreamWriter bsw) { throw new NotImplementedException(); }
internal override void WriteToStreamWriter(BitStreamWriter bsw) { bsw.WriteByte((byte)Channel); MsgInfo?.WriteToStreamWriter(bsw); }
public void Serialize(BitStreamWriter aWriter) { aWriter.WriteBit(0); left.Serialize(aWriter); right.Serialize(aWriter); }
void WriteDynamicArraySize(BitStreamWriter writer, int count, ArrayDsdlType arrayDsdlType) { var bitLen = BitSerializer.IntBitLength(arrayDsdlType.MaxSize + 1); BitSerializer.Write(writer, count, bitLen); }
public static void Serialize(Single value, BitStreamWriter writer) => writer.WriteFloat32(value);
public static void Serialize(Byte value, BitStreamWriter writer) => writer.WriteByte(value);
public static void Serialize(object obj, BitStreamWriter writer) => impl.Serialize(obj, writer);
/// <summary> /// Creates a 32x32 fingerprint for the specified bitmap. /// </summary> /// <param name="bitmap">The bitmap.</param> /// <returns>Returns a fingerprint with 6 bits per pixel (32 px = 6144 bit = 768 byte = 1024 base32 chars).</returns> public static FingerPrint Create(IBitmap32 bitmap) { using var thumb = bitmap.Resize(32, 32, ResizeMode.TouchFromInside); var data = thumb.Data; using var ms = new MemoryStream(); // calculate fingerprint and distance matrix var writer = new BitStreamWriter(ms); var distanceMatrix = new float[16]; { int x = 0, y = 0; ARGB last = 0; foreach (ARGB pixel in data.Data) { if (++x > 15) { x = 0; ++y; } var r = pixel.Red >> 6; var g = pixel.Green >> 6; var b = pixel.Blue >> 6; writer.WriteBits(r, 2); writer.WriteBits(g, 2); writer.WriteBits(b, 2); unchecked { var i = ((y << 1) & 0xC) + (x >> 2); var distance = Math.Abs(pixel.GetDistance(last)); distanceMatrix[i] += distance; last = pixel; } } } // normalize matrix var maxDistance = distanceMatrix.Max(); for (var i = 0; i < distanceMatrix.Length; i++) { distanceMatrix[i] /= maxDistance; } // calculate blocks var blocks = new uint[4]; var index = new int[] { 0, 2, 8, 10 }; for (var i = 0; i < 4; i++) { var idx = index[i]; var blockValue = (uint)(255 * distanceMatrix[idx]) << 24; blockValue |= (uint)(255 * distanceMatrix[idx + 1]) << 16; blockValue |= (uint)(255 * distanceMatrix[idx + 4]) << 8; blockValue |= (uint)(255 * distanceMatrix[idx + 5]); blocks[i] = blockValue; } /* * uint b1 = (uint)(uint.MaxValue * (distanceMatrix[0] + distanceMatrix[1] + distanceMatrix[4] + distanceMatrix[5]) /4); * uint b2 = (uint)(uint.MaxValue * (distanceMatrix[3] + distanceMatrix[2] + distanceMatrix[7] + distanceMatrix[6]) / 4); * uint b3 = (uint)(uint.MaxValue * (distanceMatrix[12] + distanceMatrix[13] + distanceMatrix[8] + distanceMatrix[9]) / 4); * uint b4 = (uint)(uint.MaxValue * (distanceMatrix[15] + distanceMatrix[14] + distanceMatrix[11] + distanceMatrix[10]) / 4); */ return(new FingerPrint(32, blocks, ms.ToArray())); }
void WriteUnionFieldIndex(BitStreamWriter writer, int index, CompositeDsdlTypeBase t) { var bitLen = BitSerializer.IntBitLength(t.Fields.Count); BitSerializer.Write(writer, index, bitLen); }
void SerializeObjectCore( BitStreamWriter writer, Func <string, ResolvedProperty?> propertyResolver, ContainerContract containerContract, DsdlType derivedDsdlType, bool tailArrayOptimization) { var dsdlScheme = GetScheme <CompositeDsdlTypeBase>(containerContract, derivedDsdlType); //WriteObjectStart(writer, value, contract, member, collectionContract, containerProperty); VoidDsdlType voidDsdlType = null; int voidDsdlTypeIndex = -1; var isUnion = dsdlScheme.IsUnion; var unionMemberFound = false; for (int i = 0; i < dsdlScheme.Fields.Count; i++) { var dsdlMember = dsdlScheme.Fields[i]; var isLastMember = i == dsdlScheme.Fields.Count - 1; if ((voidDsdlType = (dsdlMember.Type as VoidDsdlType)) != null) { voidDsdlTypeIndex = i; if (!isUnion) { WriteAlignment(writer, voidDsdlType); } continue; } var resolvedProp = propertyResolver(dsdlMember.Name); if (isUnion) { if (resolvedProp == null) { continue; } if (unionMemberFound) { throw new InvalidOperationException($"Cannot find single union value for type '{containerContract.UnderlyingType.FullName}'."); } unionMemberFound = true; WriteUnionFieldIndex(writer, i, dsdlScheme); var rp = resolvedProp.Value; SerializeValue(writer, rp.MemberValue, rp.MemberContact, dsdlMember.Type); } else { if (resolvedProp == null) { throw new InvalidOperationException($"Cannot resove member '{containerContract.UnderlyingType.FullName}.{dsdlMember.Name}'."); } var rp = resolvedProp.Value; var tao = tailArrayOptimization && isLastMember && dsdlMember.Type is ArrayDsdlType adt; SerializeValue(writer, rp.MemberValue, rp.MemberContact, dsdlMember.Type, tao); } } if (isUnion && !unionMemberFound) { if (voidDsdlType != null) { WriteUnionFieldIndex(writer, voidDsdlTypeIndex, dsdlScheme); WriteAlignment(writer, voidDsdlType); } else { throw new InvalidOperationException($"Cannot find union value for '{containerContract.UnderlyingType.FullName}' type."); } } }
public static void Serialize(Boolean value, BitStreamWriter writer) => writer.WriteBool(value);
/// <summary> /// Compress - compresses the byte[] being read by the BitStreamReader into compressed data /// </summary> /// <param name="bitCount">the number of bits to use for each element</param> /// <param name="reader">a reader over the byte[] to compress</param> /// <param name="encodingType">int, short or byte?</param> /// <param name="unitsToEncode">number of logical units to encoded</param> /// <param name="compressedData">output write buffer</param> internal void Compress(int bitCount, BitStreamReader reader, GorillaEncodingType encodingType, int unitsToEncode, List<byte> compressedData) { if (null == reader || null == compressedData) { throw new ArgumentNullException(StrokeCollectionSerializer.ISFDebugMessage("reader or compressedData was null in compress")); } if (bitCount < 0) { throw new ArgumentOutOfRangeException("bitCount"); } if (unitsToEncode < 0) { throw new ArgumentOutOfRangeException("unitsToEncode"); } if (bitCount == 0) { //adjust if the bitcount is 0 //(this makes bitCount 32) switch (encodingType) { case GorillaEncodingType.Int: { bitCount = Native.BitsPerInt; break; } case GorillaEncodingType.Short: { bitCount = Native.BitsPerShort; break; } case GorillaEncodingType.Byte: { bitCount = Native.BitsPerByte; break; } default: { throw new ArgumentException(StrokeCollectionSerializer.ISFDebugMessage("bogus GorillaEncodingType passed to compress")); } } } //have the writer adapt to the List<byte> passed in and write to it BitStreamWriter writer = new BitStreamWriter(compressedData); while (!reader.EndOfStream && unitsToEncode > 0) { int data = GetDataFromReader(reader, encodingType); writer.Write((uint)data, bitCount); unitsToEncode--; } }
public static void Serialize(ref Char value, BitStreamWriter writer) => writer.WriteChar(value);
/// <summary> /// Decodes a single pixel row. /// </summary> public byte[] DecodeRow(byte[] data) { Reset(CCITT4DecoderState.White); var reader = new BitStreamReaderReverse(new MemoryStream(data)); var writer = new BitStreamWriter(new MemoryStream()); while (reader.Position < reader.Length) { // read a bit currentValue = (currentValue << 1) | reader.ReadBit(); currentBitLength++; if (currentBitLength > 13) { throw new FormatException(); } // did we get a EndOfLine code ? if ((currentBitLength == EOL[1]) && (currentValue == EOL[0])) { Reset(0); continue; } if (state == 0) { // white makeup search for (var i = 0; i < WhiteMakeUpCodes.GetLength(0); i++) { if ((WhiteMakeUpCodes[i, 1] == currentBitLength) && (WhiteMakeUpCodes[i, 0] == currentValue)) { writer.WriteBits(WhiteMakeUpCodes[i, 2], true); Reset(CCITT4DecoderState.WhiteTerminationRequired); break; } } if (state != 0) { continue; } } if ((int)state <= 1) { // white termination search for (var i = 0; i < WhiteTerminatingCodes.GetLength(0); i++) { if ((WhiteTerminatingCodes[i, 1] == currentBitLength) && (WhiteTerminatingCodes[i, 0] == currentValue)) { writer.WriteBits(i, true); Reset(CCITT4DecoderState.Black); break; } } if ((int)state != 1) { continue; } } if ((int)state == 2) { // black makeup search for (var i = 0; i < BlackMakeUpCodes.GetLength(0); i++) { if ((BlackMakeUpCodes[i, 1] == currentBitLength) && (BlackMakeUpCodes[i, 0] == currentValue)) { writer.WriteBits(BlackMakeUpCodes[i, 2], false); Reset(CCITT4DecoderState.BlackTerminationRequired); break; } } if ((int)state != 2) { continue; } } if ((int)state >= 2) { // black termination search for (var i = 0; i < BlackTerminatingCodes.GetLength(0); i++) { if ((BlackTerminatingCodes[i, 1] == currentBitLength) && (BlackTerminatingCodes[i, 0] == currentValue)) { writer.WriteBits(i, false); Reset(CCITT4DecoderState.White); break; } } if ((int)state != 3) { continue; } } } return(((MemoryStream)writer.BaseStream).ToArray()); }
public static void Serialize(ref Vector3Int value, BitStreamWriter writer) => writer.WriteVector3Int(value);
public void Serialize(BitStreamWriter aWriter) { aWriter.WriteBit(1); aWriter.WriteBits(data, 8); }
public static void Serialize(ref DateTime value, BitStreamWriter writer) { Log.Assert(value.Kind == DateTimeKind.Utc, "DateTime must be UTC"); writer.WriteInt64(value.Ticks); }
public static void Write(BitStreamWriter destination, double value, int bitLength) => Write(destination, b => LittleEndianBitConverter.FillBytes(value, b), bitLength);
public static void Serialize(ref UInt64 value, BitStreamWriter writer) => writer.WriteUInt64(value);
public static void Serialize(ref Entity value, BitStreamWriter writer) { writer.WriteInt32(value.Index); writer.WriteInt32(value.Version); }
public static void Serialize(UInt32 value, BitStreamWriter writer) => writer.WriteUInt32(value);
public static void WriteInt32(this BitStreamWriter writer, Int32 value) { writer.WriteBits(BitConverterX.Int32ToUInt32(value), 32); }
public static void Serialize(Int16 value, BitStreamWriter writer) => writer.WriteInt16(value);
public static void WriteUInt32(this BitStreamWriter writer, UInt32 value) { writer.WriteBits(value, 32); }
internal override void WriteToStreamWriter(BitStreamWriter bsw) { }
/// <summary> /// Encode /// </summary> /// <param name="data"></param> /// <param name="extra"></param> /// <param name="writer"></param> /// <returns>number of bits encoded, 0 for failure</returns> internal byte Encode(int data, int extra, BitStreamWriter writer) { if (writer == null) { throw new ArgumentNullException("writer"); } if (data == 0) { writer.Write((byte)0, 1); //more efficent return (byte)1; } // First, encode extra if non-ZERO uint bitSize = _huffBits.GetSize(); if (0 != extra) { // Prefix lenght is 1 more than table size byte extraPrefixLength = (byte)(bitSize + 1); int extraPrefix = ((1 << extraPrefixLength) - 2); writer.Write((uint)extraPrefix, (int)extraPrefixLength); // Encode the extra data first byte extraCodeLength = Encode(extra, 0, writer); // Encode the actual data next byte dataCodeLength = Encode(data, 0, writer); // Return the total code lenght return (byte)((int)extraPrefixLength + (int)extraCodeLength + (int)dataCodeLength); } // Find the absolute value of the data // IMPORTANT : It is extremely important that nData is uint, and NOT int // If it is int, the LONG_MIN will be encoded erroneaouly uint nData = (uint)MathHelper.AbsNoThrow(data); // Find the prefix lenght byte nPrefLen = 1; for (; (nPrefLen < bitSize) && (nData >= _mins[nPrefLen]); ++nPrefLen) ; // Get the data length uint nDataLen = _huffBits.GetBitsAtIndex((uint)nPrefLen - 1); // Find the prefix int nPrefix = ((1 << nPrefLen) - 2); // Append the prefix to the bit stream writer.Write((uint)nPrefix, (int)nPrefLen); // Find the data offset by lower bound // and append sign bit at LSB Debug.Assert(nDataLen > 0 && nDataLen - 1 <= Int32.MaxValue); int dataLenMinusOne = (int)(nDataLen - 1); //can't left shift by a uint, we need to thunk to an int nData = ((((nData - _mins[nPrefLen - 1]) & (uint)((1 << dataLenMinusOne) - 1)) << 1) | (uint)((data < 0) ? 1 : 0)); // Append data into the bit streamdataLenMinusOne Debug.Assert(nDataLen <= Int32.MaxValue); writer.Write(nData, (int)nDataLen); return (byte)((uint)nPrefLen + nDataLen); }
/// <summary> /// Encode /// </summary> /// <param name="data"></param> /// <param name="extra"></param> /// <param name="writer"></param> /// <returns>number of bits encoded, 0 for failure</returns> internal byte Encode(int data, int extra, BitStreamWriter writer) { if (writer == null) { throw new ArgumentNullException("writer"); } if (data == 0) { writer.Write((byte)0, 1); //more efficent return((byte)1); } // First, encode extra if non-ZERO uint bitSize = _huffBits.GetSize(); if (0 != extra) { // Prefix lenght is 1 more than table size byte extraPrefixLength = (byte)(bitSize + 1); int extraPrefix = ((1 << extraPrefixLength) - 2); writer.Write((uint)extraPrefix, (int)extraPrefixLength); // Encode the extra data first byte extraCodeLength = Encode(extra, 0, writer); // Encode the actual data next byte dataCodeLength = Encode(data, 0, writer); // Return the total code lenght return((byte)((int)extraPrefixLength + (int)extraCodeLength + (int)dataCodeLength)); } // Find the absolute value of the data // IMPORTANT : It is extremely important that nData is uint, and NOT int // If it is int, the LONG_MIN will be encoded erroneaouly uint nData = (uint)MathHelper.AbsNoThrow(data); // Find the prefix lenght byte nPrefLen = 1; for (; (nPrefLen < bitSize) && (nData >= _mins[nPrefLen]); ++nPrefLen) { ; } // Get the data length uint nDataLen = _huffBits.GetBitsAtIndex((uint)nPrefLen - 1); // Find the prefix int nPrefix = ((1 << nPrefLen) - 2); // Append the prefix to the bit stream writer.Write((uint)nPrefix, (int)nPrefLen); // Find the data offset by lower bound // and append sign bit at LSB Debug.Assert(nDataLen > 0 && nDataLen - 1 <= Int32.MaxValue); int dataLenMinusOne = (int)(nDataLen - 1); //can't left shift by a uint, we need to thunk to an int nData = ((((nData - _mins[nPrefLen - 1]) & (uint)((1 << dataLenMinusOne) - 1)) << 1) | (uint)((data < 0) ? 1 : 0)); // Append data into the bit streamdataLenMinusOne Debug.Assert(nDataLen <= Int32.MaxValue); writer.Write(nData, (int)nDataLen); return((byte)((uint)nPrefLen + nDataLen)); }
/// <summary> /// Compress - compress the input[] into compressedData /// </summary> /// <param name="bitCount">The count of bits needed for all elements</param> /// <param name="input">input buffer</param> /// <param name="startInputIndex">offset into the input buffer</param> /// <param name="dtxf">data transform. can be null</param> /// <param name="compressedData">The list of bytes to write the compressed input to</param> internal void Compress(int bitCount, int[] input, int startInputIndex, DeltaDelta dtxf, List<byte> compressedData) { if (null == input || null == compressedData) { throw new ArgumentNullException(StrokeCollectionSerializer.ISFDebugMessage("input or compressed data was null in Compress")); } if (bitCount < 0) { throw new ArgumentOutOfRangeException("bitCount"); } if (bitCount == 0) { //adjust if the bitcount is 0 //(this makes bitCount 32) bitCount = (int)(Native.SizeOfInt << 3); } //have the writer adapt to the List<byte> passed in and write to it BitStreamWriter writer = new BitStreamWriter(compressedData); if (null != dtxf) { int xfData = 0; int xfExtra = 0; for (int i = startInputIndex; i < input.Length; i++) { dtxf.Transform(input[i], ref xfData, ref xfExtra); if (xfExtra != 0) { throw new InvalidOperationException(StrokeCollectionSerializer.ISFDebugMessage("Transform returned unexpected results")); } writer.Write((uint)xfData, bitCount); } } else { for (int i = startInputIndex; i < input.Length; i++) { writer.Write((uint)input[i], bitCount); } } }
/// <summary> /// Uncompress - uncompress the byte[] in the reader to a byte[] to return /// </summary> /// <param name="bitCount">number of bits each element is compressed to</param> /// <param name="reader">a reader over the compressed byte[]</param> /// <param name="encodingType">int, short or byte?</param> /// <param name="unitsToDecode">number of logical units to decode</param> /// <returns>Uncompressed byte[]</returns> internal byte[] Uncompress(int bitCount, BitStreamReader reader, GorillaEncodingType encodingType, int unitsToDecode) { if (null == reader) { throw new ArgumentNullException("reader"); } if (bitCount < 0) { throw new ArgumentOutOfRangeException("bitCount"); } if (unitsToDecode < 0) { throw new ArgumentOutOfRangeException("unitsToDecode"); } int bitsToWrite = 0; // Test whether the items are signed. For unsigned number, we don't need mask // If we are trying to compress signed long values with bit count = 5 // The mask will be 1111 1111 1111 0000. The way it is done is, if the 5th // bit is 1, the number is negative numbe, othrwise it's positive. Testing // will be non-zero, ONLY if the 5th bit is 1, in which case we OR with the mask // otherwise we leave the number as it is. uint bitMask = 0; //adjust if the bitcount is 0 //(this makes bitCount 32) switch (encodingType) { case GorillaEncodingType.Int: { if (bitCount == 0) { bitCount = Native.BitsPerInt; } bitsToWrite = Native.BitsPerInt; //we decode int's as unsigned, so we need to create a mask bitMask = (unchecked ((uint)~0) << (bitCount - 1)); break; } case GorillaEncodingType.Short: { if (bitCount == 0) { bitCount = Native.BitsPerShort; } bitsToWrite = Native.BitsPerShort; //shorts are decoded as unsigned values, no mask required bitMask = 0; break; } case GorillaEncodingType.Byte: { if (bitCount == 0) { bitCount = Native.BitsPerByte; } bitsToWrite = Native.BitsPerByte; //bytes are decoded as unsigned values, no mask required bitMask = 0; break; } default: { throw new ArgumentException(StrokeCollectionSerializer.ISFDebugMessage("bogus GorillaEncodingType passed to Uncompress")); } } List <byte> output = new List <byte>((bitsToWrite / 8) * unitsToDecode); BitStreamWriter writer = new BitStreamWriter(output); uint bitData = 0; while (!reader.EndOfStream && unitsToDecode > 0) { //we're going to cast to an uint anyway, just read as one bitData = reader.ReadUInt32(bitCount); // Construct the item bitData = ((bitData & bitMask) != 0) ? bitMask | bitData : bitData; writer.WriteReverse(bitData, bitsToWrite); unitsToDecode--; } return(output.ToArray()); }
/// <summary> /// Uncompress - uncompress the byte[] in the reader to a byte[] to return /// </summary> /// <param name="bitCount">number of bits each element is compressed to</param> /// <param name="reader">a reader over the compressed byte[]</param> /// <param name="encodingType">int, short or byte?</param> /// <param name="unitsToDecode">number of logical units to decode</param> /// <returns>Uncompressed byte[]</returns> internal byte[] Uncompress(int bitCount, BitStreamReader reader, GorillaEncodingType encodingType, int unitsToDecode) { if (null == reader) { throw new ArgumentNullException("reader"); } if (bitCount < 0) { throw new ArgumentOutOfRangeException("bitCount"); } if (unitsToDecode < 0) { throw new ArgumentOutOfRangeException("unitsToDecode"); } int bitsToWrite = 0; // Test whether the items are signed. For unsigned number, we don't need mask // If we are trying to compress signed long values with bit count = 5 // The mask will be 1111 1111 1111 0000. The way it is done is, if the 5th // bit is 1, the number is negative numbe, othrwise it's positive. Testing // will be non-zero, ONLY if the 5th bit is 1, in which case we OR with the mask // otherwise we leave the number as it is. uint bitMask = 0; //adjust if the bitcount is 0 //(this makes bitCount 32) switch (encodingType) { case GorillaEncodingType.Int: { if (bitCount == 0) { bitCount = Native.BitsPerInt; } bitsToWrite = Native.BitsPerInt; //we decode int's as unsigned, so we need to create a mask bitMask = (unchecked((uint)~0) << (bitCount - 1)); break; } case GorillaEncodingType.Short: { if (bitCount == 0) { bitCount = Native.BitsPerShort; } bitsToWrite = Native.BitsPerShort; //shorts are decoded as unsigned values, no mask required bitMask = 0; break; } case GorillaEncodingType.Byte: { if (bitCount == 0) { bitCount = Native.BitsPerByte; } bitsToWrite = Native.BitsPerByte; //bytes are decoded as unsigned values, no mask required bitMask = 0; break; } default: { throw new ArgumentException(StrokeCollectionSerializer.ISFDebugMessage("bogus GorillaEncodingType passed to Uncompress")); } } List<byte> output = new List<byte>((bitsToWrite / 8) * unitsToDecode); BitStreamWriter writer = new BitStreamWriter(output); uint bitData = 0; while (!reader.EndOfStream && unitsToDecode > 0) { //we're going to cast to an uint anyway, just read as one bitData = reader.ReadUInt32(bitCount); // Construct the item bitData = ((bitData & bitMask) != 0) ? bitMask | bitData : bitData; writer.WriteReverse(bitData, bitsToWrite); unitsToDecode--; } return output.ToArray(); }
void SerializeList( BitStreamWriter writer, IEnumerable values, IContract contract, IContract finalItemContract, DsdlType derivedDsdlType, bool tailArrayOptimization) { if (!(derivedDsdlType is ArrayDsdlType arrayDsdlType)) { throw new InvalidOperationException($"Array DSDL type expected for type '{contract.UnderlyingType.FullName}'."); } object underlyingList = values is IWrappedCollection wrappedCollection ? wrappedCollection.UnderlyingCollection : values; _serializeStack.Push(underlyingList); var arrayCount = values.Count(); switch (arrayDsdlType.Mode) { case ArrayDsdlTypeMode.Dynamic: { if (arrayCount > arrayDsdlType.MaxSize) { throw new SerializationException($"'{contract.UnderlyingType.FullName}' is too big. MaxSize is {arrayDsdlType.MaxSize}."); } if (!tailArrayOptimization || arrayDsdlType.ElementType.MinBitlen < 8) { WriteDynamicArraySize(writer, arrayCount, arrayDsdlType); } else { tailArrayOptimization = false; } break; } case ArrayDsdlTypeMode.Static: { if (arrayCount != arrayDsdlType.MaxSize) { throw new SerializationException($"'{contract.UnderlyingType.FullName}' expected size is {arrayDsdlType.MaxSize}."); } break; } } // Note: an exception from the IEnumerable won't be caught. int i = 0; foreach (object value in values) { i++; var valueContract = finalItemContract ?? (value == null ? null : _serializer.ContractResolver.ResolveContract(value.GetType())); if (!CheckForCircularReference(value, null, valueContract)) { continue; } if (!CheckDsdlTypeCompatibility(arrayDsdlType.ElementType, valueContract)) { throw new InvalidOperationException( $"DSDL type mismatch for enumerated item '{contract.UnderlyingType.FullName}.{valueContract.UnderlyingType}'."); } var tao = i == arrayCount ? tailArrayOptimization : false; SerializeValue(writer, value, valueContract, arrayDsdlType.ElementType, tao); } //writer.WriteEndArray(); _serializeStack.Pop(); }