private void ApplyTableAttributeFlags(StructTypeDefinition structTypeDef, FlatBuffersTableAttribute attribute)
 {
     structTypeDef.UseOriginalOrdering = attribute.OriginalOrdering;
     if (attribute.HasIdentitifer)
     {
         structTypeDef.Identifier = attribute.Identifier;
     }
 }
 private void SerializeFieldValue(object obj, StructTypeDefinition structDef, FieldTypeDefinition field)
 {
     if (structDef.IsFixed)
     {
         SerializeInlineValue(obj, field.TypeModel);
     }
     else
     {
         SerializePropertyValue(obj, field);
     }
 }
        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 void ApplyStructAttributeFlags(StructTypeDefinition structTypeDef, FlatBuffersStructAttribute attribute)
 {
     // check force align makes sense
     if (attribute.IsForceAlignSet)
     {
         var align = attribute.ForceAlign;
         if (align < structTypeDef.MinAlign ||
             align > 16 ||
             (align & (align - 1)) != 0)
         {
             throw new FlatBuffersTypeReflectionException(
                       "ForceAlign must be a power of two integer ranging from the struct's natural alignment to 16");
         }
         structTypeDef.MinAlign       = align;
         structTypeDef.ForceAlignSize = align;
     }
 }
        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 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);
        }
        private StructTypeDefinition ReflectStructDef(Type type)
        {
            var members =
                type.GetMembers(BindingFlags.Public | BindingFlags.Instance)
                .Where(i => i.MemberType == MemberTypes.Field || i.MemberType == MemberTypes.Property)
                .Where(i => !i.Defined <FlatBuffersIgnoreAttribute>())
                .ToArray();

            var isFixed = !type.IsClass;

            if (type.IsClass && type.Defined <FlatBuffersStructAttribute>())
            {
                isFixed = true;
            }

            if (!type.IsClass && type.Defined <FlatBuffersTableAttribute>())
            {
                isFixed = false;
            }

            if (type.Defined <FlatBuffersTableAttribute>() && type.Defined <FlatBuffersStructAttribute>())
            {
                throw new FlatBuffersTypeReflectionException("Cannot use FlatBuffersStructAttribute and FlatBuffersTableAttribute on same type");
            }

            var structTypeDef = new StructTypeDefinition(isFixed);

            ReflectUserMetadata(type, structTypeDef);

            if (members.Any(i =>
            {
                var attr = i.Attribute <FlatBuffersFieldAttribute>();
                if (attr == null)
                {
                    return(false);
                }

                return(attr.IsIdSetExplicitly);
            }))
            {
                structTypeDef.HasCustomOrdering = true;
            }

            if (structTypeDef.IsFixed)
            {
                var structAttr = type.Attribute <FlatBuffersStructAttribute>();
                if (structAttr != null)
                {
                    ApplyStructAttributeFlags(structTypeDef, structAttr);
                }
            }
            else
            {
                var tableAttr = type.Attribute <FlatBuffersTableAttribute>();
                if (tableAttr != null)
                {
                    ApplyTableAttributeFlags(structTypeDef, tableAttr);
                }
            }

            foreach (var member in members)
            {
                try
                {
                    ReflectStructFieldDef(structTypeDef, member);
                }
                catch (FlatBuffersStructFieldReflectionException fieldEx)
                {
                    fieldEx.ClrType = type;
                    fieldEx.Member  = member;
                    throw;
                }
            }

            // Pad the last field in the struct so it aligns correctly
            structTypeDef.PadLastField(structTypeDef.MinAlign);
            structTypeDef.FinalizeFieldDefinition();
            return(structTypeDef);
        }