private object DeserializeVector(int structBase, int offset, FieldTypeDefinition field)
        {
            var    typeModel   = field.TypeModel;
            object result      = null;
            var    vectorStart = GetVectorStart(structBase, offset);

            if (_offsetToObject.TryGetValue(vectorStart, out result))
            {
                return(result);
            }

            var vectorLength = GetVectorLength(structBase, offset);

            if (typeModel.Type.BaseType == typeof(Array))
            {
                result = DeserializeArray(typeModel, vectorLength, vectorStart);
            }
            else if (typeModel.Type.IsGenericType && typeof(IList).IsAssignableFrom(typeModel.Type))
            {
                result = DeserializeList(typeModel, vectorLength, vectorStart);
            }

            _offsetToObject.Add(vectorStart, result);
            return(result);
        }
 private void SerializeFieldValue(object obj, StructTypeDefinition structDef, FieldTypeDefinition field)
 {
     if (structDef.IsFixed)
     {
         SerializeInlineValue(obj, field.TypeModel);
     }
     else
     {
         SerializePropertyValue(obj, field);
     }
 }
        private string BuildMetadata(FieldTypeDefinition field)
        {
            var sb = new StringBuilder();

            if (field.DefaultValueProvider.IsDefaultValueSetExplicity)
            {
                sb.AppendFormat(" = {0}", field.DefaultValueProvider.GetDefaultValue(field.TypeModel.Type));
            }

            BuildMetadata(sb, field);
            return(sb.ToString());
        }
        private void AddReferenceFieldOffset(object obj, FieldTypeDefinition field)
        {
            var fieldBufferOffset = 0;

            var dict = field.HasNestedFlatBufferType ? _nestedOffsets : _objectOffsets;

            if (!dict.TryGetValue(obj, out fieldBufferOffset))
            {
                throw new FlatBuffersSerializationException("Offset for object not found in map");
            }

            _builder.AddOffset(field.Index, fieldBufferOffset, 0);
        }
        private object DeserializeInlineValue(int structBase, FieldTypeDefinition field)
        {
            var typeModel = field.TypeModel;
            var offset    = structBase + field.Offset;

            if (typeModel.BaseType.IsScalar())
            {
                return(DeserializeScalarValue(typeModel.BaseType, offset));
            }
            if (typeModel.BaseType == BaseType.Struct)
            {
                return(DeserializeStruct(offset, 0, typeModel));
            }
            throw new NotImplementedException();
        }
        private void WriteField(FieldTypeDefinition field)
        {
            var fieldTypeName = GetFlatBufferTypeName(field.TypeModel);

            if (field.HasNestedFlatBufferType)
            {
                fieldTypeName = "[ubyte]";
            }

            var meta = BuildMetadata(field);

            WriteAllComments(field, false);

            var fieldName = ApplyNameStyle(_options.FieldNamingStyle, field.Name);

            _writer.WriteLine("{0}{1}:{2}{3};", _indent, fieldName, fieldTypeName, meta);
        }
        private object DeserializeUnion(int structBase, int offset, FieldTypeDefinition field)
        {
            var unionDef        = field.TypeModel.UnionDef;
            var unionTypeOffset = GetFieldOffset(structBase, field.UnionTypeField.Offset);

            if (unionTypeOffset == 0)
            {
                return(null);
            }

            // Get the value of the union type
            var unionType         = _buffer.Get(unionTypeOffset + structBase);
            var typeToDeserialize = unionDef.Fields.FirstOrDefault(i => i.Index == unionType);

            if (typeToDeserialize == null || typeToDeserialize.MemberType == null)
            {
                return(null);
            }
            return(DeserializeStruct(structBase, offset, typeToDeserialize.MemberType));
        }
Beispiel #8
0
        /// <summary>
        /// Adds a field to the struct, recalculating the valious sizing, alignment and padding values.
        /// </summary>
        /// <param name="field"></param>
        /// <exception cref="FlatBuffersStructFieldReflectionException"></exception>
        public void AddField(FieldTypeDefinition field)
        {
            field.OriginalIndex = _fields.Count;
            var typeModel = field.TypeModel;

            if (IsFixed)
            {
                var size      = typeModel.InlineSize;
                var alignment = typeModel.InlineAlignment;

                if (typeModel.IsStruct)
                {
                    // We're adding an inline struct
                    var structDef = typeModel.StructDef;
                    size = structDef.ByteSize;
                }

                // align
                MinAlign = Math.Max(MinAlign, alignment);
                PadLastField(alignment);
                field.Offset = ByteSize;
                ByteSize    += size;
            }
            else
            {
                field.Offset = FieldIndexToOffset(field.Index);
            }

            if (field.Key && HasKey)
            {
                throw new FlatBuffersStructFieldReflectionException("Cannot add '{0}' as a key field, key already exists", field.Name);
            }
            if (field.Key)
            {
                HasKey = true;
            }

            _fields.Add(field);
        }
        private object DeserializeReferenceType(int structBase, int offset, FieldTypeDefinition field)
        {
            var typeModel = field.TypeModel;

            if (field.HasNestedFlatBufferType)
            {
                var nestedStart = GetVectorStart(structBase, offset);
                return(DeserializeStruct(nestedStart, 0, field.NestedFlatBufferType));
            }

            switch (typeModel.BaseType)
            {
            case BaseType.Vector:
            {
                return(DeserializeVector(structBase, offset, field));
            }

            case BaseType.Struct:
            {
                return(DeserializeStruct(structBase, offset, typeModel));
            }

            case BaseType.String:
            {
                return(DeserializeString(structBase, offset));
            }

            case BaseType.Union:
            {
                return(DeserializeUnion(structBase, offset, field));
            }

            default:
            {
                throw new ArgumentException("Field is not a reference type");
            }
            }
        }
        private void DeserializeStructField(object obj, StructTypeDefinition structDef, FieldTypeDefinition field, int structBase)
        {
            if (field.Deprecated)
            {
                return;
            }

            object value = null;

            if (structDef.IsFixed)
            {
                value = DeserializeInlineValue(structBase, field);
            }
            else
            {
                value = DeserializePropertyValue(structBase, field);
            }

            field.ValueProvider.SetValue(obj, value);
        }
        private object DeserializePropertyValue(int structBase, FieldTypeDefinition field)
        {
            var typeModel = field.TypeModel;
            var offset    = GetFieldOffset(structBase, field.Offset);

            if (offset == 0)
            {
                // Nothing in buffer, use default value
                return(field.DefaultValueProvider.GetDefaultValue(field.TypeModel.Type));
            }

            switch (typeModel.BaseType)
            {
            case BaseType.Bool:
            {
                return(_buffer.Get(offset + structBase) == 1);
            }

            case BaseType.Char:
            {
                return(_buffer.GetSbyte(offset + structBase));
            }

            case BaseType.UType:
            case BaseType.UChar:
            {
                return(_buffer.Get(offset + structBase));
            }

            case BaseType.Short:
            {
                return(_buffer.GetShort(offset + structBase));
            }

            case BaseType.UShort:
            {
                return(_buffer.GetUshort(offset + structBase));
            }

            case BaseType.Int:
            {
                return(_buffer.GetInt(offset + structBase));
            }

            case BaseType.UInt:
            {
                return(_buffer.GetUint(offset + structBase));
            }

            case BaseType.Long:
            {
                return(_buffer.GetLong(offset + structBase));
            }

            case BaseType.ULong:
            {
                return(_buffer.GetUlong(offset + structBase));
            }

            case BaseType.Float:
            {
                return(_buffer.GetFloat(offset + structBase));
            }

            case BaseType.Double:
            {
                return(_buffer.GetDouble(offset + structBase));
            }

            case BaseType.String:
            case BaseType.Struct:
            case BaseType.Vector:
            case BaseType.Union:
            {
                return(DeserializeReferenceType(structBase, offset, field));
            }

            default:
            {
                throw new InvalidOperationException();
            }
            }
        }
        private void SerializeStructField(object obj, StructTypeDefinition structDef, FieldTypeDefinition field)
        {
            if (field.Deprecated)
            {
                return;
            }

            if (field.Padding > 0)
            {
                _builder.Pad(field.Padding);
            }
            var val = field.ValueProvider.GetValue(obj);

            SerializeFieldValue(val, structDef, field);
        }
        private int SerializePropertyValue(object obj, FieldTypeDefinition field)
        {
            var typeModel = field.TypeModel;

            if (typeModel.IsReferenceType && obj == null)
            {
                if (field.Required)
                {
                    throw new FlatBuffersSerializationException("Required field '{0}' is not set", field.Name);
                }
            }

            if (field.DefaultValueProvider.IsDefaultValue(obj))
            {
                return(_builder.Offset);
            }

            switch (typeModel.BaseType)
            {
            case BaseType.Bool:
            {
                _builder.AddBool(field.Index, (bool)obj, false);
                break;
            }

            case BaseType.Char:
            {
                _builder.AddSbyte(field.Index, (sbyte)obj, 0);
                break;
            }

            case BaseType.UType:
            case BaseType.UChar:
            {
                _builder.AddByte(field.Index, (byte)obj, 0);
                break;
            }

            case BaseType.Short:
            {
                _builder.AddShort(field.Index, (short)obj, 0);
                break;
            }

            case BaseType.UShort:
            {
                _builder.AddUshort(field.Index, (ushort)obj, 0);
                break;
            }

            case BaseType.Int:
            {
                _builder.AddInt(field.Index, (int)obj, 0);
                break;
            }

            case BaseType.UInt:
            {
                _builder.AddUint(field.Index, (uint)obj, 0);
                break;
            }

            case BaseType.Long:
            {
                _builder.AddLong(field.Index, (long)obj, 0);
                break;
            }

            case BaseType.ULong:
            {
                _builder.AddUlong(field.Index, (ulong)obj, 0);
                break;
            }

            case BaseType.Float:
            {
                _builder.AddFloat(field.Index, (float)obj, 0);
                break;
            }

            case BaseType.Double:
            {
                _builder.AddDouble(field.Index, (double)obj, 0);
                break;
            }

            case BaseType.Struct:
            {
                if (typeModel.IsStruct)
                {
                    // Structs are serialized inline
                    var structOffset = SerializeStruct(obj, typeModel);
                    _builder.AddStruct(field.Index, structOffset, 0);
                }
                else
                {
                    // Is a table, so grab the offset
                    AddReferenceFieldOffset(obj, field);
                }

                break;
            }

            case BaseType.String:
            case BaseType.Vector:
            case BaseType.Union:
            {
                AddReferenceFieldOffset(obj, field);
                break;
            }

            default:
            {
                throw new InvalidOperationException();
            }
            }
            return(_builder.Offset);
        }
        private void ReflectStructFieldDef(StructTypeDefinition structDef, MemberInfo member)
        {
            var valueProvider        = CreateValueProvider(member);
            var defaultValueProvider = CreateDefaultValueProvider(member);
            var attr = member.Attribute <FlatBuffersFieldAttribute>();

            var valueType = valueProvider.ValueType;

            TypeModel memberTypeModel = null;
            TypeModel nestedTypeModel = null;

            if (valueType == typeof(object))
            {
                if (attr == null || (!attr.IsUnionField && !attr.HasNestedFlatBufferType))
                {
                    throw new FlatBuffersStructFieldReflectionException("Field with 'object' member must have a UnionType or NestedFlatBufferType declared");
                }

                if (attr.HasNestedFlatBufferType)
                {
                    memberTypeModel = nestedTypeModel = GetTypeModel(attr.NestedFlatBufferType);
                }

                if (attr.IsUnionField)
                {
                    memberTypeModel = GetTypeModel(attr.UnionType);
                }
            }
            else
            {
                if (attr != null && attr.HasNestedFlatBufferType)
                {
                    throw new FlatBuffersStructFieldReflectionException("HasNestedFlatBufferType can only be used on fields with 'object' member");
                }

                memberTypeModel = GetTypeModel(valueType);
            }

            FieldTypeDefinition unionTypeField = null;

            if (memberTypeModel.IsUnion)
            {
                var unionTypeFieldValueProvider        = new UnionTypeValueProvider(valueProvider, memberTypeModel);
                var unionTypeFieldDefaultValueProvider = TypeDefaultValueProvider.Instance;
                unionTypeField = new FieldTypeDefinition(unionTypeFieldValueProvider,
                                                         unionTypeFieldDefaultValueProvider)
                {
                    Name      = string.Format("{0}_type", member.Name),
                    TypeModel = GetTypeModel <UnionFieldType>()
                };
            }

            var field = new FieldTypeDefinition(valueProvider, defaultValueProvider)
            {
                Name      = member.Name, // TODO: allow attribute override
                TypeModel = memberTypeModel,
            };

            if (nestedTypeModel != null)
            {
                field.NestedFlatBufferType = nestedTypeModel;
            }

            ReflectUserMetadata(member, field);

            if (attr != null)
            {
                if (!string.IsNullOrEmpty(attr.Name))
                {
                    field.Name = attr.Name;
                }

                if (attr.IsIdSetExplicitly)
                {
                    field.UserIndex = attr.Id;
                    if (unionTypeField != null)
                    {
                        unionTypeField.UserIndex = attr.Id - 1;
                    }
                }
                field.Required   = attr.Required;
                field.Deprecated = attr.Deprecated;

                if (attr.Key)
                {
                    if (!ValidKeyType(valueType))
                    {
                        throw new FlatBuffersStructFieldReflectionException("Cannot add '{0}' as a key field. Type must be string or scalar", member.Name);
                    }
                    field.Key = attr.Key;
                }

                if (attr.Hash != FlatBuffersHash.None)
                {
                    if (!ValidHashType(valueType))
                    {
                        throw new FlatBuffersStructFieldReflectionException("Cannot use Hash setting on '{0}'. Type must be int/uint/long/ulong", member.Name);
                    }
                    field.Hash = attr.Hash;
                }
            }

            if (unionTypeField != null)
            {
                structDef.AddField(unionTypeField);
                field.UnionTypeField = unionTypeField;
            }

            structDef.AddField(field);
        }