Exemple #1
0
 private static void ReadArrayLengths(DeserializationState state, ArrayRecord record)
 {
     record.Lengths.Capacity = record.Rank;
     for (var i = 0; i < record.Rank; ++i)
     {
         record.Lengths.Add(state.array.ReadInt32LEFromBytes(ref state.idx));
     }
 }
Exemple #2
0
        private static void ReadArrayValues(DeserializationState state, ArrayRecord record)
        {
            var maxLen = record.Lengths.Aggregate(1, (cur, length) => cur * length);

            record.ValuesAsVector.Capacity = maxLen;
            for (var i = 0; i < maxLen; ++i)
            {
                record.ValuesAsVector.Add(ReadMemberValue(state, record));
            }
        }
Exemple #3
0
        private static void ReadArrayInformation(DeserializationState state, ArrayRecord record)
        {
            var arType = (BinaryArrayTypeEnumeration)state.array.ReadByteFromBytes(ref state.idx);

            record.ArrayKind = arType;
            record.Rank      = state.array.ReadInt32LEFromBytes(ref state.idx);

            ReadArrayLengths(state, record);

            switch (arType)
            {
            case BinaryArrayTypeEnumeration.SingleOffset:
            case BinaryArrayTypeEnumeration.JaggedOffset:
            case BinaryArrayTypeEnumeration.RectangularOffset:
                record.LowerBounds.Capacity = record.Rank;
                for (var i = 0; i < record.Rank; ++i)
                {
                    record.LowerBounds.Add(state.array.ReadInt32LEFromBytes(ref state.idx));
                }
                break;
            }
            ReadBasicTypeInfo(state, record);
            ReadAdditionalTypeInfo(state, record);
        }
Exemple #4
0
        private static void WriteArrayRecord(SerializationState state, ArrayRecord array, Int32 id)
        {
            var  rank  = Math.Max(1, array.Rank);
            Type pType = null;
            // Default for empty arrays and arrays with just nulls is ArraySinglePrimitive
            var recType            = RecordTypeEnumeration.ArraySinglePrimitive;
            var nonNullEncountered = false;

            foreach (var val in array.ValuesAsVector)
            {
                if (val != null || (val is PrimitiveWrapperRecord && ((PrimitiveWrapperRecord)val).Value != null))
                {
                    var valType = (val is PrimitiveWrapperRecord ? ((PrimitiveWrapperRecord)val).Value : val).GetType();
                    if (nonNullEncountered)
                    {
                        if (
                            (recType == RecordTypeEnumeration.ArraySingleString && !(val is String || val is StringRecord)) ||
                            (recType == RecordTypeEnumeration.ArraySinglePrimitive && !Object.Equals(pType, valType))
                            )
                        {
                            recType = RecordTypeEnumeration.ArraySingleObject;
                        }
                    }
                    else
                    {
                        recType = (val is String || val is StringRecord) ?
                                  RecordTypeEnumeration.ArraySingleString :
                                  ((!(val is AbstractRecord) || val is PrimitiveWrapperRecord) ?
                                   RecordTypeEnumeration.ArraySinglePrimitive :
                                   RecordTypeEnumeration.ArraySingleObject);
                        if (recType == RecordTypeEnumeration.ArraySinglePrimitive)
                        {
                            pType = valType;
                        }
                        nonNullEncountered = true;
                    }
                }
                if (recType == RecordTypeEnumeration.ArraySingleObject)
                {
                    break;
                }
            }
            var recTypeToUse = BinaryArrayTypeEnumeration.Single == array.ArrayKind ? recType : RecordTypeEnumeration.BinaryArray;

            // Write information common for all arrays
            state.EnsureCapacity(9);
            state.array
            .WriteByteToBytes(ref state.idx, (Byte)recTypeToUse)
            .WriteInt32LEToBytes(ref state.idx, id);
            if (RecordTypeEnumeration.BinaryArray != recTypeToUse)
            {
                state.array.WriteInt32LEToBytes(ref state.idx, array.ValuesAsVector.Count);
            }
            state.WriteArrayToStream();
            PrimitiveTypeEnumeration pEnum;

            switch (recTypeToUse)
            {
            case RecordTypeEnumeration.BinaryArray:
                var ak        = array.ArrayKind;
                var cap       = 7 + 4 * rank; // array type (1), rank (4), rank lengths (4 each) + type info (1) + possible primitive info
                var hasOffset = false;
                switch (array.ArrayKind)
                {
                case BinaryArrayTypeEnumeration.SingleOffset:
                case BinaryArrayTypeEnumeration.JaggedOffset:
                case BinaryArrayTypeEnumeration.RectangularOffset:
                    hasOffset = true;
                    cap      += 4 * rank; // rank offsets (4 each);
                    break;
                }
                state.EnsureCapacity(cap);
                state.array
                .WriteByteToBytes(ref state.idx, (Byte)RecordTypeEnumeration.BinaryArray)
                .WriteInt32LEToBytes(ref state.idx, rank);
                for (var i = 0; i < rank; ++i)
                {
                    state.array.WriteInt32LEToBytes(ref state.idx, array.Lengths[i]);
                }
                if (hasOffset)
                {
                    for (var i = 0; i < rank; ++i)
                    {
                        state.array.WriteInt32LEToBytes(ref state.idx, array.LowerBounds[i]);
                    }
                }
                BinaryTypeEnumeration typeEnum;
                switch (recType)
                {
                case RecordTypeEnumeration.ArraySinglePrimitive:
                    typeEnum = BinaryTypeEnumeration.Primitive;
                    break;

                case RecordTypeEnumeration.ArraySingleObject:
                    typeEnum = BinaryTypeEnumeration.Object;
                    break;

                case RecordTypeEnumeration.ArraySingleString:
                    typeEnum = BinaryTypeEnumeration.String;
                    break;

                default:
                    throw new InvalidOperationException("The code to detect array type has changed and this switch clause wasn't adjusted appropriately.");
                }
                state.array.WriteByteToBytes(ref state.idx, (Byte)typeEnum);
                pEnum = GetPrimitiveTypeFromType(pType);
                if (BinaryTypeEnumeration.Primitive == typeEnum)
                {
                    state.array.WriteByteToBytes(ref state.idx, (Byte)pEnum);
                }
                state.WriteArrayToStream();
                WriteArrayValues(state, array.ValuesAsVector, obj =>
                {
                    if (BinaryTypeEnumeration.Primitive == typeEnum)
                    {
                        WritePrimitive(state, obj, pEnum);
                    }
                    else
                    {
                        var rec = obj as AbstractRecord;
                        if (rec == null)
                        {
                            if (obj is String)
                            {
                                rec = new StringRecord();
                                ((StringRecord)rec).StringValue = (String)obj;
                            }
                            else
                            {
                                rec = new PrimitiveWrapperRecord();
                                ((PrimitiveWrapperRecord)rec).Value = obj;
                            }
                        }
                        WriteSingleRecord(state, rec, false);
                    }
                });
                break;

            // Serialize all information about array
            case RecordTypeEnumeration.ArraySinglePrimitive:
                state.EnsureCapacity(1);
                pEnum = GetPrimitiveTypeFromType(pType);
                state.array.WriteByteToBytes(ref state.idx, (Byte)pEnum);
                state.WriteArrayToStream();
                WriteArrayValues(state, array.ValuesAsVector, obj => WritePrimitive(state, obj is PrimitiveWrapperRecord ? ((PrimitiveWrapperRecord)obj).Value : obj, pEnum));
                break;

            case RecordTypeEnumeration.ArraySingleObject:
                WriteArrayValues(state, array.ValuesAsVector, obj =>
                {
                    var objRec = obj as AbstractRecord;
                    if (objRec == null)
                    {
                        objRec = new PrimitiveWrapperRecord();
                        ((PrimitiveWrapperRecord)objRec).Value = obj;
                    }
                    WriteSingleRecord(state, objRec, false);
                });
                break;

            case RecordTypeEnumeration.ArraySingleString:
                WriteArrayValues(state, array.ValuesAsVector, obj =>
                {
                    var str = obj as StringRecord;
                    if (str == null)
                    {
                        str             = new StringRecord();
                        str.StringValue = (String)obj;
                    }
                    WriteSingleRecord(state, str, false);
                });
                break;
            }
        }