Exemplo n.º 1
0
 private static void WriteNullFillers(SerializationState state, UInt32 nullCount)
 {
     if (nullCount > 0)
     {
         if (nullCount > 1)
         {
             var useByte = nullCount <= Byte.MaxValue;
             state.EnsureCapacity(useByte ? 2 : 5);
             state.array.WriteByteToBytes(ref state.idx, (Byte)(useByte ? RecordTypeEnumeration.ObjectNullMultiple256 : RecordTypeEnumeration.ObjectNullMultiple));
             if (useByte)
             {
                 state.array.WriteByteToBytes(ref state.idx, (Byte)nullCount);
             }
             else
             {
                 state.array.WriteUInt32LEToBytes(ref state.idx, nullCount);
             }
         }
         else
         {
             // Just write one null
             state.EnsureCapacity(1);
             state.array.WriteByteToBytes(ref state.idx, (Byte)RecordTypeEnumeration.ObjectNull);
         }
         state.WriteArrayToStream();
     }
 }
Exemplo n.º 2
0
        public static void WriteNRBFRecords(this IList <AbstractRecord> records, Stream stream)
        {
            var state = new SerializationState(stream);

            // Write header
            state.EnsureCapacity(17); // Header + header value
            state.array
            .WriteByteToBytes(ref state.idx, (Byte)RecordTypeEnumeration.SerializedStreamHeader)
            .WriteInt32LEToBytes(ref state.idx, 1)
            .WriteInt32LEToBytes(ref state.idx, -1)
            .WriteInt32LEToBytes(ref state.idx, 1)
            .WriteInt32LEToBytes(ref state.idx, 0);
            stream.Write(state.array);

            // Collect all assembly names
            foreach (var rec in records)
            {
                // Write used assembly names first
                WriteAssemblyNames(state, rec);

                // Write record structure
                WriteSingleRecord(state, rec, false);

                // Empty queue of reference objects
                while (state.recordQueue.Count > 0)
                {
                    WriteSingleRecord(state, state.recordQueue.Dequeue(), true);
                }
            }

            // Write end
            state.EnsureCapacity(1);
            state.array.WriteByteToBytes(ref state.idx, (Byte)RecordTypeEnumeration.MessageEnd);
            stream.Write(state.array);
        }
Exemplo n.º 3
0
        private static void WriteSingleRecord(SerializationState state, AbstractRecord record, Boolean forceWrite)
        {
            Int32 id;

            if (state.TryAddRecord(record, out id) || forceWrite)
            {
                // If record hasn't been previously processed, or if we are told to write contents no matter what
                switch (record.Kind)
                {
                case RecordKind.String:
                    var s   = ((StringRecord)record).StringValue;
                    var len = UTF8.GetByteCount(s);
                    state.EnsureCapacity(10 + len);
                    state.array
                    .WriteByteToBytes(ref state.idx, (Byte)RecordTypeEnumeration.BinaryObjectString)
                    .WriteInt32LEToBytes(ref state.idx, id)
                    .WriteInt32Encoded7Bit(ref state.idx, len)
                    .WriteStringToBytes(ref state.idx, UTF8, s);
                    state.WriteArrayToStream();
                    break;

                case RecordKind.Class:
                    WriteClassRecord(state, (ClassRecord)record, id);
                    break;

                case RecordKind.Array:
                    WriteArrayRecord(state, (ArrayRecord)record, id);
                    break;

                case RecordKind.PrimitiveWrapper:
                    // Write header
                    state.EnsureCapacity(2);
                    var p     = ((PrimitiveWrapperRecord)record).Value;
                    var pType = GetPrimitiveType(p);
                    state.array
                    .WriteByteToBytes(ref state.idx, (Byte)RecordTypeEnumeration.MemberPrimitiveTyped)
                    .WriteByteToBytes(ref state.idx, (Byte)pType);
                    state.WriteArrayToStream();
                    // Write primitive
                    WritePrimitive(state, p, pType);
                    break;
                }
            }
            else
            {
                // Record was already serialized, write member reference to it
                state.EnsureCapacity(5);
                state.array
                .WriteByteToBytes(ref state.idx, (Byte)RecordTypeEnumeration.MemberReference)
                .WriteInt32LEToBytes(ref state.idx, id);
                state.WriteArrayToStream();
            }
        }
Exemplo n.º 4
0
 private static void WriteAssemblyName(SerializationState state, ElementWithTypeInfo element)
 {
     if (element != null)
     {
         var   assName = element.AssemblyName;
         Int32 id;
         if (state.TryAddAssemblyName(assName, out id))
         {
             var strByteCount = UTF8.GetByteCount(assName);
             state.EnsureCapacity(10 + strByteCount);
             state.array
             .WriteByteToBytes(ref state.idx, (Byte)RecordTypeEnumeration.BinaryLibrary)
             .WriteInt32LEToBytes(ref state.idx, id)
             .WriteInt32Encoded7Bit(ref state.idx, strByteCount)
             .WriteStringToBytes(ref state.idx, UTF8, assName);
             state.WriteArrayToStream();
         }
     }
 }
Exemplo n.º 5
0
        private static void WritePrimitive(SerializationState state, Object primitive, PrimitiveTypeEnumeration pType)
        {
            String s;
            Int32  len;

            switch (pType)
            {
            case PrimitiveTypeEnumeration.Boolean:
                state.EnsureCapacity(1);
                state.array.WriteByteToBytes(ref state.idx, ((Boolean)primitive) == true ? (Byte)1 : (Byte)0);
                break;

            case PrimitiveTypeEnumeration.Byte:
                state.EnsureCapacity(1);
                state.array.WriteByteToBytes(ref state.idx, (Byte)primitive);
                break;

            case PrimitiveTypeEnumeration.Char:
                state.EnsureCapacity(4);
                state.idx = UTF8.GetBytes(new[] { (Char)primitive }, 0, 1, state.array, 0);
                break;

            case PrimitiveTypeEnumeration.Decimal:
                var d = (Decimal)primitive;
                s   = d.ToString();
                len = UTF8.GetByteCount(s);
                var ints = Decimal.GetBits(d);
                state.EnsureCapacity(5 + len + 16);
                state.array
                .WriteInt32Encoded7Bit(ref state.idx, len)
                .WriteStringToBytes(ref state.idx, UTF8, s)
                .WriteInt32LEToBytes(ref state.idx, ints[0])
                .WriteInt32LEToBytes(ref state.idx, ints[1])
                .WriteInt32LEToBytes(ref state.idx, ints[2])
                .WriteInt32LEToBytes(ref state.idx, ints[3]);
                break;

            case PrimitiveTypeEnumeration.Double:
                state.EnsureCapacity(8);
                state.array.WriteDoubleLEToBytes(ref state.idx, (Double)primitive);
                break;

            case PrimitiveTypeEnumeration.Int16:
                state.EnsureCapacity(2);
                state.array.WriteInt16LEToBytes(ref state.idx, (Int16)primitive);
                break;

            case PrimitiveTypeEnumeration.Int32:
                state.EnsureCapacity(4);
                state.array.WriteInt32LEToBytes(ref state.idx, (Int32)primitive);
                break;

            case PrimitiveTypeEnumeration.Int64:
                state.EnsureCapacity(8);
                state.array.WriteInt64LEToBytes(ref state.idx, (Int64)primitive);
                break;

            case PrimitiveTypeEnumeration.SByte:
                state.EnsureCapacity(1);
                state.array.WriteSByteToBytes(ref state.idx, (SByte)primitive);
                break;

            case PrimitiveTypeEnumeration.Single:
                state.EnsureCapacity(4);
                state.array.WriteSingleLEToBytes(ref state.idx, (Single)primitive);
                break;

            case PrimitiveTypeEnumeration.TimeSpan:
                state.EnsureCapacity(8);
                state.array.WriteInt64LEToBytes(ref state.idx, ((TimeSpan)primitive).Ticks);
                break;

            case PrimitiveTypeEnumeration.DateTime:
                state.EnsureCapacity(8);
                state.array.WriteInt64LEToBytes(ref state.idx, ((DateTime)primitive).Ticks);
                break;

            case PrimitiveTypeEnumeration.UInt16:
                state.EnsureCapacity(2);
                state.array.WriteUInt16LEToBytes(ref state.idx, (UInt16)primitive);
                break;

            case PrimitiveTypeEnumeration.UInt32:
                state.EnsureCapacity(4);
                state.array.WriteUInt32LEToBytes(ref state.idx, (UInt32)primitive);
                break;

            case PrimitiveTypeEnumeration.UInt64:
                state.EnsureCapacity(8);
                state.array.WriteUInt64LEToBytes(ref state.idx, (UInt64)primitive);
                break;

            case PrimitiveTypeEnumeration.Null:
                state.EnsureCapacity(0);
                break;

            case PrimitiveTypeEnumeration.String:
                s   = (String)primitive;
                len = UTF8.GetByteCount(s);
                state.EnsureCapacity(5 + len);
                state.array
                .WriteInt32Encoded7Bit(ref state.idx, len)
                .WriteStringToBytes(ref state.idx, UTF8, s);
                break;

            default:
                state.EnsureCapacity(0);
                break;
            }
            state.WriteArrayToStream();
        }
Exemplo n.º 6
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;
            }
        }
Exemplo n.º 7
0
        private static void WriteClassRecord(SerializationState state, ClassRecord claas, Int32 id)
        {
            var   metaDataKey = Tuple.Create(claas.AssemblyName, claas.TypeName);
            Int32 otherID;

            if (state.serializedObjects.TryGetValue(metaDataKey, out otherID))
            {
                // Another record of the same type was serialized earlier, can use previous info
                state.EnsureCapacity(9);
                state.array
                .WriteByteToBytes(ref state.idx, (Byte)RecordTypeEnumeration.ClassWithID)
                .WriteInt32LEToBytes(ref state.idx, id)
                .WriteInt32LEToBytes(ref state.idx, otherID);
                state.WriteArrayToStream();
            }
            else
            {
                var isSystem      = claas.AssemblyName == null;
                var nameByteCount = SafeByteCount(claas.TypeName);
                state.EnsureCapacity(14 + nameByteCount); // class type (1), id (4), space for class name length (max 5), member count (4)
                state.array
                .WriteByteToBytes(ref state.idx, (Byte)(isSystem ? RecordTypeEnumeration.SystemClassWithMembersAndTypes : RecordTypeEnumeration.ClassWithMembersAndTypes))
                .WriteInt32LEToBytes(ref state.idx, id)
                .WriteInt32Encoded7Bit(ref state.idx, nameByteCount)
                .WriteStringToBytes(ref state.idx, UTF8, claas.TypeName)
                .WriteInt32LEToBytes(ref state.idx, claas.Members.Count);
                state.WriteArrayToStream();

                // Write member names
                foreach (var member in claas.Members)
                {
                    nameByteCount = SafeByteCount(member.Name);
                    state.EnsureCapacity(5 + nameByteCount);
                    state.array
                    .WriteInt32Encoded7Bit(ref state.idx, nameByteCount)
                    .WriteStringToBytes(ref state.idx, UTF8, member.Name);
                    state.WriteArrayToStream();
                }
                // Write member type infos
                state.EnsureCapacity(claas.Members.Count);
                var mTypeCodes = new List <Tuple <BinaryTypeEnumeration, PrimitiveTypeEnumeration> >(claas.Members.Count);
                foreach (var member in claas.Members)
                {
                    PrimitiveTypeEnumeration pType;
                    var bt = GetTypeInfo(member.Value, out pType);
                    mTypeCodes.Add(Tuple.Create(bt, pType));
                    state.array.WriteByteToBytes(ref state.idx, (Byte)bt);
                }
                state.WriteArrayToStream();
                // Write additional type info where applicable
                for (var i = 0; i < mTypeCodes.Count; ++i)
                {
                    var member = claas.Members[i];
                    var tuple  = mTypeCodes[i];
                    switch (tuple.Item1)
                    {
                    case BinaryTypeEnumeration.Primitive:
                        state.EnsureCapacity(1);
                        state.array.WriteByteToBytes(ref state.idx, (Byte)tuple.Item2);
                        break;

                    case BinaryTypeEnumeration.SystemClass:
                        nameByteCount = SafeByteCount(member.TypeName);
                        state.EnsureCapacity(5 + nameByteCount);
                        state.array
                        .WriteInt32Encoded7Bit(ref state.idx, nameByteCount)
                        .WriteStringToBytes(ref state.idx, UTF8, member.TypeName);
                        break;

                    case BinaryTypeEnumeration.Class:
                        nameByteCount = SafeByteCount(member.TypeName);
                        state.EnsureCapacity(9 + nameByteCount);
                        state.array
                        .WriteInt32Encoded7Bit(ref state.idx, nameByteCount)
                        .WriteStringToBytes(ref state.idx, UTF8, member.TypeName)
                        .WriteInt32LEToBytes(ref state.idx, state.assemblies[member.AssemblyName]);
                        break;

                    case BinaryTypeEnumeration.PrimitiveArray:
                        state.EnsureCapacity(1);
                        state.array
                        .WriteByteToBytes(ref state.idx, (Byte)tuple.Item2);
                        break;
                    }
                    state.WriteArrayToStream();
                }


                // Write this class assembly name if needed
                if (!isSystem)
                {
                    state.EnsureCapacity(4);
                    state.array.WriteInt32LEToBytes(ref state.idx, state.assemblies[claas.AssemblyName]);
                    state.WriteArrayToStream();
                }

                // Write member values
                for (var i = 0; i < mTypeCodes.Count; ++i)
                {
                    var member = claas.Members[i];
                    var val    = member.Value;

                    // Change raw string values to StringRecords to enable caching strings by id
                    if (val is String)
                    {
                        var sRec = new StringRecord();
                        sRec.StringValue = (String)val;
                        val = sRec;
                    }
                    var rec = val as AbstractRecord;
                    if (rec != null)
                    {
                        // All arrays and non-structs are serialized afterwards.
                        if (rec is ArrayRecord || (rec is ClassRecord && !((ClassRecord)rec).IsSerializedInPlace))
                        {
                            // Add to mapping before calling recursively in order to create MemberReference
                            if (state.TryAddRecord(rec, out id))
                            {
                                // The record hasn't been serialized, add to queue
                                state.recordQueue.Enqueue(rec);
                            }
                        }

                        // Write the record
                        WriteSingleRecord(state, rec, false);
                    }
                    else
                    {
                        // Write value as primitive
                        WritePrimitive(state, val, mTypeCodes[i].Item2);
                    }
                }
            }
            if (!state.serializedObjects.ContainsKey(metaDataKey))
            {
                state.serializedObjects.Add(metaDataKey, id);
            }
        }