private void ImplementTableGetMaxSizeMethod(TableTypeModel tableModel) { int vtableEntryCount = tableModel.MaxIndex + 1; // vtable length + table length + 2 * entryCount + padding to 2-byte alignment. int maxVtableSize = sizeof(ushort) * (2 + vtableEntryCount) + SerializationHelpers.GetMaxPadding(sizeof(ushort)); int maxTableSize = tableModel.NonPaddedMaxTableInlineSize + SerializationHelpers.GetMaxPadding(tableModel.Alignment); List <string> statements = new List <string>(); foreach (var kvp in tableModel.IndexToMemberMap) { int index = kvp.Key; var member = kvp.Value; if (member.ItemTypeModel.IsFixedSize) { // This should already be accounted for in table.NonPaddedMax size above. continue; } string variableName = $"index{index}Value"; statements.Add($"var {variableName} = item.{member.PropertyInfo.Name};"); string statement = $"runningSum += {this.InvokeGetMaxSizeMethod(member.ItemTypeModel, variableName)};"; string condition = $"if ({variableName} != null)"; if (member.ItemTypeModel is VectorTypeModel vectorModel && vectorModel.IsMemoryVector) { condition = string.Empty; } statement = $@" {condition} {{ {statement} }}"; statements.Add(statement); } string body = $@" int runningSum = {maxTableSize} + {maxVtableSize}; {string.Join("\r\n", statements)}; return runningSum; "; this.GenerateGetMaxSizeMethod(tableModel.ClrType, body); }
private void ImplementTableInlineWriteMethod(TableTypeModel tableModel) { var type = tableModel.ClrType; int maxIndex = tableModel.MaxIndex; int maxInlineSize = tableModel.NonPaddedMaxTableInlineSize; // Start by asking for the worst-case number of bytes from the serializationcontext. string methodStart = $@" int tableStart = context.{nameof(SerializationContext.AllocateSpace)}({maxInlineSize}, sizeof(int)); writer.{nameof(SpanWriter.WriteUOffset)}(span, originalOffset, tableStart, context); int currentOffset = tableStart + sizeof(int); // skip past vtable soffset_t. var vtable = context.{nameof(SerializationContext.VTableBuilder)}; vtable.StartObject({maxIndex}); "; List <string> body = new List <string>(); List <string> writers = new List <string>(); // load the properties of the object into locals. foreach (var kvp in tableModel.IndexToMemberMap) { string prepare, write; if (kvp.Value.ItemTypeModel.SchemaType == FlatBufferSchemaType.Union) { (prepare, write) = this.GetUnionSerializeBlocks(kvp.Key, kvp.Value); } else { (prepare, write) = this.GetStandardSerializeBlocks(kvp.Key, kvp.Value); } body.Add(prepare); writers.Add(write); } // We probably over-allocated. Figure out by how much and back up the cursor. // Then we can write the vtable. body.Add("int tableLength = currentOffset - tableStart;"); body.Add($"context.{nameof(SerializationContext.Offset)} -= {maxInlineSize} - tableLength;"); body.Add($"int vtablePosition = vtable.{nameof(VTableBuilder.EndObject)}(span, writer, tableLength);"); body.Add($"writer.{nameof(SpanWriter.WriteInt)}(span, tableStart - vtablePosition, tableStart, context);"); body.AddRange(writers); // These methods are often enormous, and inlining can have a detrimental effect on perf. this.GenerateSerializeMethod(type, $"{methodStart} \r\n {string.Join("\r\n", body)}", inline: false); }
public void TypeModel_Vector_Indexed() { var model = RuntimeTypeModel.CreateFrom(typeof(GenericTable <IIndexedVector <string, SortedVectorKeyTable <string> > >)); Assert.AreEqual(FlatBufferSchemaType.Table, model.SchemaType); TableTypeModel tableModel = (TableTypeModel)model; var firstMember = tableModel.IndexToMemberMap[0]; Assert.IsTrue(firstMember.IsSortedVector); // sorted vector is set even though it's not explicitly declared. Indexed Vectors force it to be set. var vectorModel = firstMember.ItemTypeModel; Assert.AreEqual(FlatBufferSchemaType.Vector, vectorModel.SchemaType); }
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 void ImplementTableReadMethod(TableTypeModel typeModel) { // We have to implement two items: The table class and the overall "read" method. // Let's start with the read method. string className = "tableReader_" + Guid.NewGuid().ToString("n"); this.GenerateMethodDefinition(typeModel.ClrType, $"return new {className}(memory, offset + memory.{nameof(InputBuffer.ReadUOffset)}(offset));"); // Build up a list of property overrides. var propertyOverrides = new List <GeneratedProperty>(); foreach (var item in typeModel.IndexToMemberMap) { int index = item.Key; var value = item.Value; GeneratedProperty propertyStuff; if (value.ItemTypeModel is UnionTypeModel) { propertyStuff = this.CreateUnionTableGetter(value, index); } else { propertyStuff = this.CreateStandardTableProperty(value, index); } propertyOverrides.Add(propertyStuff); } string classDefinition = this.CreateClass( className, typeModel.ClrType, typeModel.IndexToMemberMap.Values.Select(x => x.PropertyInfo.Name), propertyOverrides); var node = CSharpSyntaxTree.ParseText(classDefinition, ParseOptions); this.methodDeclarations.Add(node.GetRoot()); }
public static TableType ForTableType(TableTypeModel tableType, Schema schema) { return(new TableType(tableType, schema)); }
public TableType(TableTypeModel tableType, Schema schema) { _tableType = tableType; _schema = schema; }
private (string prepareBlock, string serializeBlock) GetStandardSerializeBlocks(int index, TableMemberModel memberModel) { string valueVariableName = $"index{index}Value"; string offsetVariableName = $"index{index}Offset"; string condition = $"if ({valueVariableName} != {CSharpHelpers.GetDefaultValueToken(memberModel)})"; if ((memberModel.ItemTypeModel is VectorTypeModel vector && vector.IsMemoryVector) || memberModel.IsKey) { // 1) Memory is a struct and can't be null, and 0-length vectors are valid. // Therefore, we just need to omit the conditional check entirely. // 2) For sorted vector keys, we must include the value since some other // libraries cannot do binary search with omitted keys. condition = string.Empty; } string keyCheckMethodCall = string.Empty; if (memberModel.IsKey) { keyCheckMethodCall = $"{nameof(SortedVectorHelpers)}.{nameof(SortedVectorHelpers.EnsureKeyNonNull)}({valueVariableName});"; } string prepareBlock = $@" var {valueVariableName} = item.{memberModel.PropertyInfo.Name}; int {offsetVariableName} = 0; {keyCheckMethodCall} {condition} {{ currentOffset += {CSharpHelpers.GetFullMethodName(ReflectedMethods.SerializationHelpers_GetAlignmentErrorMethod)}(currentOffset, {memberModel.ItemTypeModel.Alignment}); {offsetVariableName} = currentOffset; vtable.{nameof(VTableBuilder.SetOffset)}({index}, currentOffset - tableStart); currentOffset += {memberModel.ItemTypeModel.InlineSize}; }}"; string sortInvocation = string.Empty; if (memberModel.IsSortedVector) { VectorTypeModel vectorModel = (VectorTypeModel)memberModel.ItemTypeModel; TableTypeModel tableModel = (TableTypeModel)vectorModel.ItemTypeModel; TableMemberModel keyMember = tableModel.IndexToMemberMap.Single(x => x.Value.PropertyInfo == tableModel.KeyProperty).Value; var builtInType = BuiltInType.BuiltInTypes[keyMember.ItemTypeModel.ClrType]; string inlineSize = builtInType.TypeModel.SchemaType == FlatBufferSchemaType.Scalar ? builtInType.TypeModel.InlineSize.ToString() : "null"; sortInvocation = $"{nameof(SortedVectorHelpers)}.{nameof(SortedVectorHelpers.SortVector)}(" + $"span, {offsetVariableName}, {keyMember.Index}, {inlineSize}, {CSharpHelpers.GetCompilableTypeName(builtInType.SpanComparerType)}.Instance);"; } string serializeBlock = $@" if ({offsetVariableName} != 0) {{ {this.GetSerializeInvocation(memberModel.ItemTypeModel.ClrType, valueVariableName, offsetVariableName)} {sortInvocation} }}"; return(prepareBlock, serializeBlock); }
public async Task <List <SchemaModel> > ListAsync(ConfigurationModel config, CancellationToken cancellationToken = default) { var dbSchemas = await DbContext.SchemaListAsync(cancellationToken); if (dbSchemas == null) { return(null); } var schemas = dbSchemas?.Select(i => new SchemaModel(i)).ToList(); // overwrite with current config if (config?.Schema != null) { foreach (var schema in schemas) { // ! Do not compare with Id. The Id is different for each SQL-Server Instance var currentSchema = config.Schema.SingleOrDefault(i => i.Name == schema.Name); // TODO define a global and local Property "onNewSchemaFound" (IGNORE, BUILD, WARN, PROMPT) to set the default Status schema.Status = (currentSchema != null) ? currentSchema.Status : config.Project.DefaultSchemaStatus; } } // reorder schemas, ignored at top schemas = schemas.OrderByDescending(schema => schema.Status).ToList(); var schemaListString = string.Join(',', schemas.Where(i => i.Status != SchemaStatusEnum.Ignore).Select(i => $"'{i.Name}'")); if (string.IsNullOrEmpty(schemaListString)) { _reportService.Warn("No schemas found or all schemas ignored!"); return(schemas); } var storedProcedures = await DbContext.StoredProcedureListAsync(schemaListString, cancellationToken); var tableTypes = await DbContext.TableTypeListAsync(schemaListString, cancellationToken); foreach (var schema in schemas) { schema.StoredProcedures = storedProcedures.Where(i => i.SchemaName.Equals(schema.Name))?.Select(i => new StoredProcedureModel(i))?.ToList(); if (schema.StoredProcedures == null) { continue; } foreach (var storedProcedure in schema.StoredProcedures) { var inputs = await DbContext.StoredProcedureInputListAsync(storedProcedure.SchemaName, storedProcedure.Name, cancellationToken); storedProcedure.Input = inputs.Select(i => new StoredProcedureInputModel(i)).ToList(); var output = await DbContext.StoredProcedureOutputListAsync(storedProcedure.SchemaName, storedProcedure.Name, cancellationToken); storedProcedure.Output = output.Select(i => new StoredProcedureOutputModel(i)).ToList(); } var tableTypeModels = new List <TableTypeModel>(); foreach (var tableType in tableTypes.Where(i => i.SchemaName.Equals(schema.Name))) { var columns = await DbContext.TableTypeColumnListAsync(tableType.UserTypeId ?? -1, cancellationToken); var tableTypeModel = new TableTypeModel(tableType, columns); tableTypeModels.Add(tableTypeModel); } schema.TableTypes = tableTypeModels; } return(schemas); }