Exemple #1
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();
            }
        }
Exemple #2
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);
            }
        }