public static int GetScalarSize(this BaseType type) { FlatSharpInternal.Assert(type.IsScalar(), "Type " + type + " was not a scalar"); switch (type) { case BaseType.Bool: case BaseType.Byte: case BaseType.UByte: return(1); case BaseType.Short: case BaseType.UShort: return(2); case BaseType.Int: case BaseType.UInt: case BaseType.Float: return(4); case BaseType.Long: case BaseType.ULong: case BaseType.Double: return(8); default: throw new InvalidOperationException("impossible"); } }
internal static string GetCompilableTypeName(this Type t) { FlatSharpInternal.Assert(!string.IsNullOrEmpty(t.FullName), $"{t} has null/empty full name."); string name; if (t.IsGenericType) { List <string> parameters = new List <string>(); foreach (var generic in t.GetGenericArguments()) { parameters.Add(GetCompilableTypeName(generic)); } name = $"{t.FullName.Split('`')[0]}<{string.Join(", ", parameters)}>"; } else if (t.IsArray) { name = $"{GetCompilableTypeName(t.GetElementType()!)}[]"; } else { name = t.FullName; } name = name.Replace('+', '.'); return(name); }
public override CodeGeneratedMethod CreateParseMethodBody(ParserCodeGenContext context) { if (!context.Options.GreedyDeserialize) { throw new InvalidFlatBufferDefinitionException("Array vectors may only be used with Greedy serializers."); } var(classDef, className) = FlatBufferVectorHelpers.CreateFlatBufferVectorOfUnionSubclass( this.ItemTypeModel, context); FlatSharpInternal.Assert(!string.IsNullOrEmpty(context.TableFieldContextVariableName), "expecting table field context"); string createFlatBufferVector = $@"new {className}<{context.InputBufferTypeName}>( {context.InputBufferVariableName}, {context.OffsetVariableName}.offset0 + {context.InputBufferVariableName}.{nameof(InputBufferExtensions.ReadUOffset)}({context.OffsetVariableName}.offset0), {context.OffsetVariableName}.offset1 + {context.InputBufferVariableName}.{nameof(InputBufferExtensions.ReadUOffset)}({context.OffsetVariableName}.offset1), {context.TableFieldContextVariableName})"; string body = $"return ({createFlatBufferVector}).ToArray();"; return(new CodeGeneratedMethod(body) { ClassDefinition = classDef }); }
public override Type OnInitialize() { FlatSharpInternal.Assert(this.ClrType.IsArray, $"Array vectors must be arrays. Type = {this.ClrType.FullName}."); FlatSharpInternal.Assert(this.ClrType.GetArrayRank() == 1, "Array vectors may only be single-dimension."); return(this.ClrType.GetElementType() !); }
internal static string CreateParseBody( ITypeModel itemTypeModel, string createFlatBufferVector, ParserCodeGenContext context) { FlatSharpInternal.Assert(!string.IsNullOrEmpty(context.TableFieldContextVariableName), "expecting table field context"); if (context.Options.GreedyDeserialize) { string body = $"({createFlatBufferVector}).FlatBufferVectorToList()"; if (!context.Options.GenerateMutableObjects) { body += ".AsReadOnly()"; } return($"return {body};"); } else if (context.Options.Lazy) { return($"return {createFlatBufferVector};"); } else { FlatSharpInternal.Assert(context.Options.Progressive, "expecting progressive"); return($"return new FlatBufferProgressiveVector<{itemTypeModel.GetGlobalCompilableTypeName()}, {context.InputBufferTypeName}>({createFlatBufferVector});"); } }
public sealed override void Initialize() { base.Initialize(); this.ItemTypeModel = this.typeModelContainer.CreateTypeModel(this.OnInitialize()); FlatSharpInternal.Assert(this.ItemTypeModel.SchemaType == FlatBufferSchemaType.Union, "Union vectors can't contain non-union elements."); }
private TableSchemaModel(Schema.Schema schema, FlatBufferObject table) : base(schema, table) { FlatSharpInternal.Assert(table.IsStruct == false, "Not expecting struct"); this.AttributeValidator.DeserializationOptionValidator = _ => AttributeValidationResult.Valid; this.AttributeValidator.DefaultConstructorValidator = _ => AttributeValidationResult.Valid; this.AttributeValidator.ForceWriteValidator = _ => AttributeValidationResult.Valid; }
private void ValidateHasSerializer(FlatBufferObject obj) { FlatSharpInternal.Assert(!obj.IsStruct, "expecting only tables"); FlatSharpAttributes attrs = new FlatSharpAttributes(obj.Attributes); if (attrs.DeserializationOption is null) { ErrorContext.Current.RegisterError($"RPC call '{this.fullName}' uses table '{obj.Name}', which does not specify the '{MetadataKeys.SerializerKind}' attribute."); } }
public Memory <byte> GetByteMemory(int start, int length) { checked { FlatSharpInternal.Assert(start >= 0, "GetByteMemory.Start was negative."); var seg = this.pointer.segment; return(new Memory <byte>(seg.Array, seg.Offset + start, length)); } }
public override Type OnInitialize() { var genericDef = this.ClrType.GetGenericTypeDefinition(); FlatSharpInternal.Assert( genericDef == typeof(IList <>) || genericDef == typeof(IReadOnlyList <>), "List vector of union must be IList or IReadOnlyList."); return(this.ClrType.GetGenericArguments()[0]); }
private EnumSchemaModel(Schema.Schema schema, FlatBufferEnum @enum) : base(schema, @enum.Name, new FlatSharpAttributes(@enum.Attributes)) { FlatSharpInternal.Assert([email protected], "Not expecting union"); FlatSharpInternal.Assert(@enum.UnderlyingType.BaseType.IsInteger(), "Expected scalar base type"); FlatSharpInternal.Assert(@enum.UnderlyingType.BaseType.TryGetBuiltInTypeName(out this.underlyingType !), "Couldn't get type name string"); this.isFlags = @enum.Attributes?.ContainsKey(MetadataKeys.BitFlags) == true; this.nameValueMap = @enum.Values.ToDictionary(x => x.Value.Key, x => x.Value); this.DeclaringFile = @enum.DeclarationFile; this.documentation = @enum.Documentation; }
public override Type OnInitialize() { var genericDef = this.ClrType.GetGenericTypeDefinition(); FlatSharpInternal.Assert( genericDef == typeof(IList <>) || genericDef == typeof(IReadOnlyList <>), $"Cannot build a vector from type: {this.ClrType}. Only List, ReadOnlyList, Memory, ReadOnlyMemory, and Arrays are supported."); this.isReadOnly = genericDef == typeof(IReadOnlyList <>); return(this.ClrType.GetGenericArguments()[0]); }
private ReferenceStructSchemaModel(Schema.Schema schema, FlatBufferObject @struct) : base(schema, @struct) { FlatSharpInternal.Assert(@struct.IsStruct, "Expecting struct"); this.AttributeValidator.DefaultConstructorValidator = kind => kind switch { DefaultConstructorKind.Public or DefaultConstructorKind.PublicObsolete => AttributeValidationResult.Valid, _ => AttributeValidationResult.ValueInvalid, }; this.AttributeValidator.WriteThroughValidator = _ => AttributeValidationResult.Valid; }
public override CodeGeneratedMethod CreateParseMethodBody(ParserCodeGenContext context) { string body; FlatSharpInternal.Assert(this.ItemTypeModel is not null, "Flatsharp internal error: ItemTypeModel null"); if (!context.Options.GreedyDeserialize) { throw new InvalidFlatBufferDefinitionException("Array vectors may only be used with Greedy serializers."); } ValidateWriteThrough( writeThroughSupported: false, this, context.AllFieldContexts, context.Options); (string vectorClassDef, string vectorClassName) = (string.Empty, string.Empty); if (this.ItemTypeModel.ClrType == typeof(byte)) { // can handle this as memory. string method = nameof(InputBufferExtensions.ReadByteReadOnlyMemoryBlock); string memoryVectorRead = $"{context.InputBufferVariableName}.{method}({context.OffsetVariableName})"; body = $"return {memoryVectorRead}.ToArray();"; } else { (vectorClassDef, vectorClassName) = FlatBufferVectorHelpers.CreateFlatBufferVectorSubclass( this.ItemTypeModel, context); FlatSharpInternal.Assert(!string.IsNullOrEmpty(context.TableFieldContextVariableName), "expecting table field context"); string createFlatBufferVector = $@"new {vectorClassName}<{context.InputBufferTypeName}>( {context.InputBufferVariableName}, {context.OffsetVariableName} + {context.InputBufferVariableName}.{nameof(InputBufferExtensions.ReadUOffset)}({context.OffsetVariableName}), {this.PaddedMemberInlineSize}, {context.TableFieldContextVariableName})"; body = $"return ({createFlatBufferVector}).ToArray();"; } return(new CodeGeneratedMethod(body) { ClassDefinition = vectorClassDef }); }
internal static (AccessModifier propertyModifier, AccessModifier?getModifer, AccessModifier?setModifier) GetPropertyAccessModifiers( AccessModifier getModifier, AccessModifier?setModifier) { if (setModifier is null || getModifier == setModifier.Value) { return(getModifier, null, null); } FlatSharpInternal.Assert( getModifier < setModifier.Value, "Getter expected to be more visible than setter"); return(getModifier, null, setModifier); }
public override CodeGeneratedMethod CreateParseMethodBody(ParserCodeGenContext context) { ValidateWriteThrough( writeThroughSupported: false, this, context.AllFieldContexts, context.Options); string body; string keyTypeName = CSharpHelpers.GetGlobalCompilableTypeName(this.keyTypeModel.ClrType); string valueTypeName = CSharpHelpers.GetGlobalCompilableTypeName(this.valueTypeModel.ClrType); (string vectorClassDef, string vectorClassName) = FlatBufferVectorHelpers.CreateFlatBufferVectorSubclass( this.valueTypeModel, context); FlatSharpInternal.Assert(!string.IsNullOrEmpty(context.TableFieldContextVariableName), "field context was null/empty"); string createFlatBufferVector = $@"new {vectorClassName}<{context.InputBufferTypeName}>( {context.InputBufferVariableName}, {context.OffsetVariableName} + {context.InputBufferVariableName}.{nameof(InputBufferExtensions.ReadUOffset)}({context.OffsetVariableName}), {this.PaddedMemberInlineSize}, {context.TableFieldContextVariableName})"; string mutable = context.Options.GenerateMutableObjects.ToString().ToLowerInvariant(); if (context.Options.GreedyDeserialize) { // Eager indexed vector. body = $@"return new {nameof(IndexedVector<string, string>)}<{keyTypeName}, {valueTypeName}>({createFlatBufferVector}, {mutable});"; } else if (context.Options.Lazy) { // Lazy indexed vector. body = $@"return new {nameof(FlatBufferIndexedVector<string, string, IInputBuffer>)}<{keyTypeName}, {valueTypeName}, {context.InputBufferTypeName}>({createFlatBufferVector});"; } else { FlatSharpInternal.Assert(context.Options.Progressive, "expecting progressive"); body = $@"return new {nameof(FlatBufferProgressiveIndexedVector<string, string, IInputBuffer>)}<{keyTypeName}, {valueTypeName}, {context.InputBufferTypeName}>({createFlatBufferVector});"; } return(new CodeGeneratedMethod(body) { IsMethodInline = true, ClassDefinition = vectorClassDef }); }
public override void Initialize() { { FlatBufferStructAttribute?attribute = this.ClrType.GetCustomAttribute <FlatBufferStructAttribute>(); FlatSharpInternal.Assert(attribute != null, "Missing attribute."); this.attribute = attribute !; } TableTypeModel.EnsureClassCanBeInheritedByOutsideAssembly(this.ClrType, out this.preferredConstructor); this.onDeserializeMethod = TableTypeModel.ValidateOnDeserializedMethod(this); var properties = this.ClrType .GetProperties(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance) .Select(x => new { Property = x, Attribute = x.GetCustomAttribute <FlatBufferItemAttribute>() ! // suppress check here; we filter on the next line. })
private ValueStructSchemaModel(Schema.Schema schema, FlatBufferObject @struct) : base(schema, @struct.Name, new FlatSharpAttributes(@struct.Attributes)) { FlatSharpInternal.Assert(@struct.IsStruct, "Expecting struct"); FlatSharpInternal.Assert(this.Attributes.ValueStruct == true, "Expecting value struct"); this.@struct = @struct; this.fields = new(); this.structVectors = new(); foreach (Field field in [email protected](x => x.Id)) { IFlatSharpAttributes attrs = new FlatSharpAttributes(field.Attributes); string fieldType = field.Type.ResolveTypeOrElementTypeName(schema, this.Attributes); if (field.Type.BaseType == BaseType.Array) { // struct vector int size = field.Type.ElementType.GetScalarSize(); List <string> vectorFields = new(); for (int i = 0; i < field.Type.FixedLength; ++i) { string name = $"__flatsharp__{field.Name}_{i}"; MutableFlatSharpAttributes tempAttrs = new MutableFlatSharpAttributes(attrs) { UnsafeStructVector = null, }; vectorFields.Add(name); this.fields.Add(new(field.Offset + (i * size), name, "private", fieldType, $"{field.Name}({i})", null, this, tempAttrs)); } this.structVectors.Add(new(fieldType, field.Name, vectorFields, this, field.Documentation, attrs)); } else { this.fields.Add(new(field.Offset, field.Name, "public", fieldType, field.Name, field.Documentation, this, attrs)); } } this.AttributeValidator.MemoryMarshalValidator = _ => AttributeValidationResult.Valid; }
public override Type OnInitialize() { FlatSharpInternal.Assert( this.ClrType.IsGenericType && this.ClrType.GetGenericTypeDefinition() == typeof(IIndexedVector <,>), $"Indexed vectors must be of type IIndexedVector. Type = {this.GetCompilableTypeName()}."); Type keyType = this.ClrType.GetGenericArguments()[0]; Type valueType = this.ClrType.GetGenericArguments()[1]; this.keyTypeModel = this.typeModelContainer.CreateTypeModel(keyType); this.valueTypeModel = this.typeModelContainer.CreateTypeModel(valueType); if (this.valueTypeModel.SchemaType != FlatBufferSchemaType.Table) { throw new InvalidFlatBufferDefinitionException( $"Indexed vector values must be flatbuffer tables. Type = '{this.valueTypeModel.GetCompilableTypeName()}'"); } if (!this.valueTypeModel.TryGetTableKeyMember(out TableMemberModel? tempKeyMemberModel)) { throw new InvalidFlatBufferDefinitionException( $"Indexed vector values must have a property with the key attribute defined. Table = '{this.valueTypeModel.GetCompilableTypeName()}'"); } else { this.keyMemberModel = tempKeyMemberModel; } if (!this.keyMemberModel.ItemTypeModel.TryGetSpanComparerType(out _)) { throw new InvalidFlatBufferDefinitionException( $"FlatSharp indexed vector keys must supply a span comparer. KeyType = '{this.keyMemberModel.ItemTypeModel.GetCompilableTypeName()}'."); } if (keyMemberModel.ItemTypeModel.ClrType != this.keyTypeModel.ClrType) { throw new InvalidFlatBufferDefinitionException( $"FlatSharp indexed vector keys must have the same type as the key of the value. KeyType = {this.keyTypeModel.GetCompilableTypeName()}, Value Key Type = '{this.valueTypeModel.GetCompilableTypeName()}'."); } return(valueType); }
public override CodeGeneratedMethod CreateSerializeMethodBody(SerializationCodeGenContext context) { List <string> body = new List <string>(); body.Add($"Span<byte> scopedSpan = {context.SpanVariableName}.Slice({context.OffsetVariableName}, {this.PhysicalLayout[0].InlineSize});"); FlatSharpInternal.Assert(!this.ClrType.IsValueType, "Value-type struct is unexpected"); body.Add( $@" if ({context.ValueVariableName} is null) {{ scopedSpan.Clear(); return; }} "); for (int i = 0; i < this.Members.Count; ++i) { var memberInfo = this.Members[i]; string propertyAccessor = $"{context.ValueVariableName}.{memberInfo.PropertyInfo.Name}"; if (memberInfo.CustomAccessor is not null) { propertyAccessor = $"{context.ValueVariableName}.{memberInfo.CustomAccessor}"; } var propContext = context with { SpanVariableName = "scopedSpan", OffsetVariableName = $"{memberInfo.Offset}", ValueVariableName = $"{propertyAccessor}" }; string invocation = propContext.GetSerializeInvocation(memberInfo.ItemTypeModel.ClrType) + ";"; body.Add(invocation); } return(new CodeGeneratedMethod(string.Join("\r\n", body))); }
private UnionSchemaModel(Schema.Schema schema, FlatBufferEnum union) : base(schema, union.Name, new FlatSharpAttributes(union.Attributes)) { FlatSharpInternal.Assert(union.UnderlyingType.BaseType == BaseType.UType, "Expecting utype"); this.union = union; }
protected override void OnWriteCode(CodeWriter writer, CompileContext context) { List <(string resolvedType, EnumVal value)> innerTypes = new List <(string, EnumVal)>(); foreach (var inner in this.union.Values.Select(x => x.Value)) { // Skip "none". if (inner.Value == 0) { FlatSharpInternal.Assert(inner.Key == "NONE", "Expecting discriminator 0 to be 'None'"); continue; } FlatSharpInternal.Assert(inner.UnionType is not null, "Union type was null"); long discriminator = inner.Value; string typeName = inner.UnionType.ResolveTypeOrElementTypeName(this.Schema, this.Attributes); innerTypes.Add((typeName, inner)); } string interfaceName = $"IFlatBufferUnion<{string.Join(", ", innerTypes.Select(x => x.resolvedType))}>"; writer.AppendSummaryComment(this.union.Documentation); writer.AppendLine("[System.Runtime.CompilerServices.CompilerGenerated]"); writer.AppendLine($"public partial struct {this.Name} : {interfaceName}"); using (writer.WithBlock()) { // Generate an internal type enum. writer.AppendLine("public enum ItemKind : byte"); using (writer.WithBlock()) { foreach (var item in this.union.Values) { writer.AppendLine($"{item.Value.Key} = {item.Value.Value},"); } } writer.AppendLine(); writer.AppendLine("private readonly object value;"); writer.AppendLine(); writer.AppendLine("public ItemKind Kind => (ItemKind)this.Discriminator;"); writer.AppendLine(); writer.AppendLine("public byte Discriminator { get; }"); foreach (var item in innerTypes) { Type?propertyClrType = null; if (context.CompilePass > CodeWritingPass.Initialization) { Type?previousType = context.PreviousAssembly?.GetType(this.FullName); FlatSharpInternal.Assert(previousType is not null, "PreviousType was null"); propertyClrType = previousType .GetProperty($"Item{item.value.Value}", System.Reflection.BindingFlags.Public | System.Reflection.BindingFlags.Instance)? .PropertyType; FlatSharpInternal.Assert(propertyClrType is not null, "Couldn't find property"); } writer.AppendLine(); writer.AppendLine($"public {this.Name}({item.resolvedType} value)"); using (writer.WithBlock()) { if (propertyClrType?.IsValueType == false) { writer.AppendLine("if (value is null)"); using (writer.WithBlock()) { writer.AppendLine("throw new ArgumentNullException(nameof(value));"); } } writer.AppendLine($"this.value = value;"); writer.AppendLine($"this.Discriminator = {item.value.Value};"); } writer.AppendLine(); writer.AppendLine($"public {item.resolvedType} {item.value.Key} => this.Item{item.value.Value};"); writer.AppendLine(); writer.AppendLine($"public {item.resolvedType} Item{item.value.Value}"); using (writer.WithBlock()) { writer.AppendLine("get"); using (writer.WithBlock()) { writer.AppendLine($"if (this.Discriminator != {item.value.Value})"); using (writer.WithBlock()) { writer.AppendLine("throw new InvalidOperationException();"); } writer.AppendLine($"return ({item.resolvedType})this.value;"); } } string notNullWhen = string.Empty; string nullableReference = string.Empty; if (propertyClrType is not null) { if (!propertyClrType.IsValueType) { nullableReference = "?"; if (context.Options.NullableWarnings == true) { notNullWhen = $"[global::System.Diagnostics.CodeAnalysis.NotNullWhen(true)] "; } } } writer.AppendLine(); writer.AppendLine($"public bool TryGet({notNullWhen}out {item.resolvedType}{nullableReference} value)"); using (writer.WithBlock()) { writer.AppendLine($"if (this.Discriminator != {item.value.Value})"); using (writer.WithBlock()) { writer.AppendLine("value = default;"); writer.AppendLine("return false;"); } writer.AppendLine($"value = ({item.resolvedType})this.value;"); writer.AppendLine("return true;"); } } // Switch methods. this.WriteSwitchMethod(writer, true, true, innerTypes); this.WriteSwitchMethod(writer, true, false, innerTypes); this.WriteSwitchMethod(writer, false, true, innerTypes); this.WriteSwitchMethod(writer, false, false, innerTypes); } }
protected override string CreateLoop(FlatBufferSerializerOptions options, string vectorVariableName, string numberOfItemsVariableName, string expectedVariableName, string body) { FlatSharpInternal.Assert(false, "Not expecting to do loop get max size for memory vector"); throw new Exception(); }
protected override void OnWriteCode(CodeWriter writer, CompileContext context) { writer.AppendSummaryComment([email protected]); string memMarshalBehavior = string.Empty; if (this.Attributes.MemoryMarshalBehavior is not null) { memMarshalBehavior = $"{nameof(FlatBufferStructAttribute.MemoryMarshalBehavior)} = {nameof(MemoryMarshalBehavior)}.{this.Attributes.MemoryMarshalBehavior}"; } writer.AppendLine($"[FlatBufferStruct({memMarshalBehavior})]"); string size = string.Empty; if (context.CompilePass > CodeWritingPass.Initialization) { // load size from type. Type?previousType = context.PreviousAssembly?.GetType(this.FullName); FlatSharpInternal.Assert(previousType is not null, "Previous type was null"); ITypeModel model = context.TypeModelContainer.CreateTypeModel(previousType); FlatSharpInternal.Assert(model.PhysicalLayout.Length == 1, "Expected physical layout length of 1."); size = $", Size = {model.PhysicalLayout[0].InlineSize}"; } writer.AppendLine($"[System.Runtime.InteropServices.StructLayout(System.Runtime.InteropServices.LayoutKind.Explicit{size})]"); writer.AppendLine($"public partial struct {this.Name}"); using (writer.WithBlock()) { foreach (var field in this.fields) { writer.AppendSummaryComment(field.Documentation); writer.AppendLine($"[System.Runtime.InteropServices.FieldOffset({field.Offset})]"); writer.AppendLine($"[FlatBufferMetadataAttribute(FlatBufferMetadataKind.Accessor, \"{field.Accessor}\")]"); writer.AppendLine($"{field.Visibility} {field.TypeName} {field.Name};"); writer.AppendLine(); } foreach (var sv in this.structVectors) { writer.AppendSummaryComment($"Gets the number of items in the {sv.Name} vector."); writer.AppendLine($"public int {sv.Name}_Length => {sv.Properties.Count};"); writer.AppendLine(); writer.AppendSummaryComment(sv.Documentation); writer.AppendLine($"public static ref {sv.TypeName} {sv.Name}_Item(ref {this.Name} item, int index)"); using (writer.WithBlock()) { if (sv.Attributes.UnsafeStructVector == true) { writer.AppendLine($"if (unchecked((uint)index) >= {sv.Properties.Count})"); using (writer.WithBlock()) { writer.AppendLine("throw new IndexOutOfRangeException();"); } writer.AppendLine($"return ref System.Runtime.CompilerServices.Unsafe.Add(ref item.{sv.Properties[0]}, index);"); } else { writer.AppendLine("switch (index)"); using (writer.WithBlock()) { for (int i = 0; i < sv.Properties.Count; ++i) { var item = sv.Properties[i]; writer.AppendLine($"case {i}: return ref item.{item};"); } writer.AppendLine("default: throw new IndexOutOfRangeException();"); } } } } } // extensions class. if (this.structVectors.Any()) { writer.AppendLine($"public static class {this.Name}__FlatSharpExtensions"); using (writer.WithBlock()) { foreach (var sv in this.structVectors) { writer.AppendSummaryComment(sv.Documentation); writer.AppendLine($"public static ref {sv.TypeName} {sv.Name}(this ref {this.Name} item, int index)"); using (writer.WithBlock()) { writer.AppendLine($"return ref {this.Name}.{sv.Name}_Item(ref item, index);"); } } } } }