diff --git a/src/FlatSharp.Compiler/CompilerOptions.cs b/src/FlatSharp.Compiler/CompilerOptions.cs
index e5f8840d..93fe52ef 100644
--- a/src/FlatSharp.Compiler/CompilerOptions.cs
+++ b/src/FlatSharp.Compiler/CompilerOptions.cs
@@ -28,5 +28,14 @@ public record CompilerOptions
[Option("nullable-warnings", Default = false)]
public bool? NullableWarnings { get; set; }
+
+ [Option('s', "offset-size")]
+ public int? OffsetSize { get; set; }
+
+ [Option( "file-identifier-size")]
+ public int? FileIdentifierSize { get; set; }
+
+ [Option("strict-file-identifier-size")]
+ public bool? StrictFileIdentifierSize { get; set; }
}
}
diff --git a/src/FlatSharp.Compiler/FlatSharp.Compiler.targets b/src/FlatSharp.Compiler/FlatSharp.Compiler.targets
index 0c2bd3a2..25446c39 100644
--- a/src/FlatSharp.Compiler/FlatSharp.Compiler.targets
+++ b/src/FlatSharp.Compiler/FlatSharp.Compiler.targets
@@ -33,7 +33,7 @@
diff --git a/src/FlatSharp.Compiler/FlatSharpCompiler.cs b/src/FlatSharp.Compiler/FlatSharpCompiler.cs
index a1d0ca09..f8a22a1f 100644
--- a/src/FlatSharp.Compiler/FlatSharpCompiler.cs
+++ b/src/FlatSharp.Compiler/FlatSharpCompiler.cs
@@ -371,15 +371,32 @@ private static void CreateCSharp(
writer = new CodeWriter();
+ TypeModelContainer container;
+
+ if (localOptions.OffsetSize == null
+ && localOptions.FileIdentifierSize == null
+ && localOptions.StrictFileIdentifierSize == null)
+ {
+ container = TypeModelContainer.CreateDefault();
+ }
+ else
+ {
+ container = TypeModelContainer.CreateDefault(new(
+ localOptions.OffsetSize,
+ localOptions.FileIdentifierSize,
+ localOptions.StrictFileIdentifierSize
+ ));
+ }
+
rootNode.WriteCode(
writer,
new CompileContext
{
CompilePass = step,
Options = localOptions,
- RootFile = rootNode.DeclaringFile,
+ RootFile = rootNode.DeclaringFile ?? string.Empty,
PreviousAssembly = assembly,
- TypeModelContainer = TypeModelContainer.CreateDefault(),
+ TypeModelContainer = container,
});
ErrorContext.Current.ThrowIfHasErrors();
diff --git a/src/FlatSharp.Compiler/TypeDefinitions/TableOrStructDefinition.cs b/src/FlatSharp.Compiler/TypeDefinitions/TableOrStructDefinition.cs
index 50491dae..1d41cc21 100755
--- a/src/FlatSharp.Compiler/TypeDefinitions/TableOrStructDefinition.cs
+++ b/src/FlatSharp.Compiler/TypeDefinitions/TableOrStructDefinition.cs
@@ -50,7 +50,7 @@ public TableOrStructDefinition(
public DefaultConstructorKind? DefaultConstructorKind { get; set; }
- public string? FileIdentifier { get; set; }
+ public string? FileIdentifier;
public FlatBufferDeserializationOption? RequestedSerializer { get; set; }
@@ -158,6 +158,7 @@ protected override void OnWriteCode(CodeWriter writer, CompileContext context)
if (this.IsTable && !string.IsNullOrEmpty(this.FileIdentifier))
{
+ context.TypeModelContainer.OffsetModel.ValidateFileIdentifier(ref this.FileIdentifier);
attributeParts.Add($"{nameof(FlatBufferTableAttribute.FileIdentifier)} = \"{this.FileIdentifier}\"");
}
diff --git a/src/FlatSharp.Runtime/Attributes/FlatBufferTableAttribute.cs b/src/FlatSharp.Runtime/Attributes/FlatBufferTableAttribute.cs
index c9940c30..12e1bf4b 100644
--- a/src/FlatSharp.Runtime/Attributes/FlatBufferTableAttribute.cs
+++ b/src/FlatSharp.Runtime/Attributes/FlatBufferTableAttribute.cs
@@ -27,6 +27,6 @@ public class FlatBufferTableAttribute : Attribute
///
/// Specifies the file identifier for serialized tables. Must be precisely 4 ASCII characters.
///
- public string? FileIdentifier { get; set; }
+ public string? FileIdentifier;
}
}
diff --git a/src/FlatSharp/FlatBufferSerializer.cs b/src/FlatSharp/FlatBufferSerializer.cs
index dbf5116c..f5c84af4 100644
--- a/src/FlatSharp/FlatBufferSerializer.cs
+++ b/src/FlatSharp/FlatBufferSerializer.cs
@@ -48,7 +48,7 @@ public FlatBufferSerializer()
/// Creates a new FlatBufferSerializer using the given options.
///
public FlatBufferSerializer(FlatBufferSerializerOptions options)
- : this(options, TypeModelContainer.CreateDefault())
+ : this(options, TypeModelContainer.CreateDefault(new(options.OffsetSize, options.FileIdentifierSize, options.StrictFileIdentifierSize)))
{
}
diff --git a/src/FlatSharp/FlatBufferSerializerOptions.cs b/src/FlatSharp/FlatBufferSerializerOptions.cs
index f0cf118d..10d2eccf 100644
--- a/src/FlatSharp/FlatBufferSerializerOptions.cs
+++ b/src/FlatSharp/FlatBufferSerializerOptions.cs
@@ -118,5 +118,20 @@ public FlatBufferSerializerOptions(
/// Indicates if "protected internal" modifiers should be converted to protected.
///
internal bool ConvertProtectedInternalToProtected { get; set; } = true;
+
+ ///
+ /// Specify the offset size
+ ///
+ public int? OffsetSize { get; set; } = null;
+
+ ///
+ /// Specify the size of the file identifier.
+ ///
+ public int? FileIdentifierSize { get; set; } = null;
+
+ ///
+ /// Specify if the size of the file identifier is strict.
+ ///
+ public bool? StrictFileIdentifierSize { get; set; } = null;
}
}
diff --git a/src/FlatSharp/FlatSharp.csproj b/src/FlatSharp/FlatSharp.csproj
index c37c9cd4..e7614301 100644
--- a/src/FlatSharp/FlatSharp.csproj
+++ b/src/FlatSharp/FlatSharp.csproj
@@ -21,8 +21,8 @@
-
-
+
+
all
runtime
diff --git a/src/FlatSharp/OffsetModel.cs b/src/FlatSharp/OffsetModel.cs
new file mode 100644
index 00000000..28580c58
--- /dev/null
+++ b/src/FlatSharp/OffsetModel.cs
@@ -0,0 +1,83 @@
+/*
+ * Copyright 2020 James Courtney
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+namespace FlatSharp.TypeModel
+{
+ using System;
+ using System.Collections.Generic;
+ using System.Collections.Immutable;
+ using System.Diagnostics.CodeAnalysis;
+ using System.Reflection;
+
+ ///
+ /// Common or shared type model properties.
+ ///
+ public class OffsetModel
+ {
+ public static readonly OffsetModel Default = new(4);
+
+ public int OffsetSize;
+ public int FileIdentifierSize;
+ public bool StrictFileIdentifierSize;
+
+ public OffsetModel(int offsetSize, int fileIdentifierSize, bool strictFileIdentifierSize)
+ {
+ OffsetSize = offsetSize;
+ FileIdentifierSize = fileIdentifierSize;
+ StrictFileIdentifierSize = strictFileIdentifierSize;
+ }
+
+ public OffsetModel(int offsetSize, int fileIdentifierSize) : this(offsetSize, fileIdentifierSize, fileIdentifierSize == 4)
+ {
+ }
+
+ public OffsetModel(int offsetSize) : this(offsetSize, offsetSize, offsetSize == 4)
+ {
+ }
+
+ public OffsetModel(int? offsetSize, int? fileIdentifierSize, bool? strictFileIdentifierSize)
+ {
+ OffsetSize = offsetSize ?? 4;
+ FileIdentifierSize = fileIdentifierSize ?? OffsetSize;
+ StrictFileIdentifierSize = strictFileIdentifierSize ?? FileIdentifierSize == 4;
+ }
+
+ public void ValidateFileIdentifier(ref string? fileIdentifier)
+ {
+ if (string.IsNullOrEmpty(fileIdentifier)) return;
+
+ if (fileIdentifier.Length != FileIdentifierSize)
+ {
+ if (StrictFileIdentifierSize)
+ {
+ throw new InvalidFlatBufferDefinitionException(
+ $"File identifier '{fileIdentifier}' is invalid. FileIdentifiers must be exactly {FileIdentifierSize} ASCII characters.");
+ }
+
+ fileIdentifier = fileIdentifier.Length > FileIdentifierSize
+ ? fileIdentifier.Substring(0, FileIdentifierSize)
+ : fileIdentifier.PadRight(FileIdentifierSize, '\0');
+ }
+
+ foreach (var c in fileIdentifier)
+ {
+ if (c < 128) continue;
+
+ throw new InvalidFlatBufferDefinitionException($"File identifier '{fileIdentifier}' contains non-ASCII characters. Character '{c}' is invalid.");
+ }
+ }
+ }
+}
diff --git a/src/FlatSharp/TypeModel/EnumTypeModel.cs b/src/FlatSharp/TypeModel/EnumTypeModel.cs
index d071d342..23ea7ab3 100644
--- a/src/FlatSharp/TypeModel/EnumTypeModel.cs
+++ b/src/FlatSharp/TypeModel/EnumTypeModel.cs
@@ -30,7 +30,7 @@ public class EnumTypeModel : RuntimeTypeModel
{
private ITypeModel underlyingTypeModel;
- internal EnumTypeModel(Type type, TypeModelContainer typeModelContainer) : base(type, typeModelContainer)
+ internal EnumTypeModel(Type type, TypeModelContainer typeModelContainer) : base(type, typeModelContainer, typeModelContainer.OffsetModel)
{
this.underlyingTypeModel = null!;
}
diff --git a/src/FlatSharp/TypeModel/ITypeModel.cs b/src/FlatSharp/TypeModel/ITypeModel.cs
index 5c06287c..2061ee78 100644
--- a/src/FlatSharp/TypeModel/ITypeModel.cs
+++ b/src/FlatSharp/TypeModel/ITypeModel.cs
@@ -27,6 +27,8 @@ namespace FlatSharp.TypeModel
///
public interface ITypeModel
{
+ OffsetModel OffsetModel { get; }
+
///
/// Gets the schema element type that this type model represents. Note that this is not a 1:1 relationship with the type of class. There can
/// be multiple implementations of ITypeModel that satisfy a particular schema type.
diff --git a/src/FlatSharp/TypeModel/ItemMemberModel.cs b/src/FlatSharp/TypeModel/ItemMemberModel.cs
index 55c4ad37..9f8c4379 100644
--- a/src/FlatSharp/TypeModel/ItemMemberModel.cs
+++ b/src/FlatSharp/TypeModel/ItemMemberModel.cs
@@ -43,6 +43,7 @@ protected ItemMemberModel(
var setMethod = propertyInfo.SetMethod;
this.ItemTypeModel = propertyModel;
+ this.OffsetModel = propertyModel.OffsetModel;
this.PropertyInfo = propertyInfo;
this.Index = attribute.Index;
this.CustomAccessor = propertyInfo.GetFlatBufferMetadataOrNull(FlatBufferMetadataKind.Accessor);
@@ -102,6 +103,8 @@ protected ItemMemberModel(
}
}
}
+
+ public OffsetModel OffsetModel { get; }
private static bool CanBeOverridden(MethodInfo method)
{
diff --git a/src/FlatSharp/TypeModel/NullableTypeModel.cs b/src/FlatSharp/TypeModel/NullableTypeModel.cs
index 7d14a5ce..5295d0df 100644
--- a/src/FlatSharp/TypeModel/NullableTypeModel.cs
+++ b/src/FlatSharp/TypeModel/NullableTypeModel.cs
@@ -29,7 +29,7 @@ public class NullableTypeModel : RuntimeTypeModel
private Type underlyingType;
private ITypeModel underlyingTypeModel;
- internal NullableTypeModel(TypeModelContainer container, Type type) : base(type, container)
+ internal NullableTypeModel(TypeModelContainer container, Type type) : base(type, container, container.OffsetModel)
{
this.underlyingType = null!;
this.underlyingTypeModel = null!;
diff --git a/src/FlatSharp/TypeModel/RuntimeTypeModel.cs b/src/FlatSharp/TypeModel/RuntimeTypeModel.cs
index eaf9489a..9ed7af46 100644
--- a/src/FlatSharp/TypeModel/RuntimeTypeModel.cs
+++ b/src/FlatSharp/TypeModel/RuntimeTypeModel.cs
@@ -31,12 +31,18 @@ public abstract class RuntimeTypeModel : ITypeModel
{
protected readonly TypeModelContainer typeModelContainer;
- internal RuntimeTypeModel(Type clrType, TypeModelContainer typeModelContainer)
+ internal RuntimeTypeModel(Type clrType, TypeModelContainer typeModelContainer, OffsetModel offsetModel)
{
this.ClrType = clrType;
this.typeModelContainer = typeModelContainer;
+ OffsetModel = offsetModel;
}
+ ///
+ /// The offset model for serialization.
+ ///
+ public OffsetModel OffsetModel { get; }
+
///
/// Initializes this runtime type model instance.
///
@@ -122,7 +128,15 @@ public virtual bool ValidateDefaultValue(object defaultValue)
///
internal static ITypeModel CreateFrom(Type type)
{
- return TypeModelContainer.CreateDefault().CreateTypeModel(type);
+ return CreateFrom(TypeModelContainer.CreateDefault(), type);
+ }
+
+ ///
+ /// Gets or creates a runtime type model from the given type. This is only used in test cases any more.
+ ///
+ internal static ITypeModel CreateFrom(TypeModelContainer container, Type type)
+ {
+ return container.CreateTypeModel(type);
}
public abstract CodeGeneratedMethod CreateSerializeMethodBody(SerializationCodeGenContext context);
diff --git a/src/FlatSharp/TypeModel/ScalarTypeModel.cs b/src/FlatSharp/TypeModel/ScalarTypeModel.cs
index 05344a79..ae890269 100644
--- a/src/FlatSharp/TypeModel/ScalarTypeModel.cs
+++ b/src/FlatSharp/TypeModel/ScalarTypeModel.cs
@@ -31,7 +31,7 @@ public abstract class ScalarTypeModel : RuntimeTypeModel
internal ScalarTypeModel(
TypeModelContainer container,
Type type,
- int size) : base(type, container)
+ int size) : base(type, container, container.OffsetModel)
{
this.size = size;
}
diff --git a/src/FlatSharp/TypeModel/SharedStringTypeModel.cs b/src/FlatSharp/TypeModel/SharedStringTypeModel.cs
index 9aa0199b..8ed56857 100644
--- a/src/FlatSharp/TypeModel/SharedStringTypeModel.cs
+++ b/src/FlatSharp/TypeModel/SharedStringTypeModel.cs
@@ -25,7 +25,7 @@ namespace FlatSharp.TypeModel
///
public class SharedStringTypeModel : RuntimeTypeModel, ITypeModel
{
- internal SharedStringTypeModel(TypeModelContainer container) : base(typeof(SharedString), container)
+ internal SharedStringTypeModel(TypeModelContainer container) : base(typeof(SharedString), container, container.OffsetModel)
{
}
diff --git a/src/FlatSharp/TypeModel/StringTypeModel.cs b/src/FlatSharp/TypeModel/StringTypeModel.cs
index a4cba266..d76d3f5c 100644
--- a/src/FlatSharp/TypeModel/StringTypeModel.cs
+++ b/src/FlatSharp/TypeModel/StringTypeModel.cs
@@ -25,8 +25,7 @@ namespace FlatSharp.TypeModel
///
public class StringTypeModel : RuntimeTypeModel
{
- internal StringTypeModel(TypeModelContainer container) : base(typeof(string), container)
- {
+ internal StringTypeModel(TypeModelContainer container) : base(typeof(string), container, container.OffsetModel) {
}
///
diff --git a/src/FlatSharp/TypeModel/StructTypeModel.cs b/src/FlatSharp/TypeModel/StructTypeModel.cs
index 376a841b..86333053 100644
--- a/src/FlatSharp/TypeModel/StructTypeModel.cs
+++ b/src/FlatSharp/TypeModel/StructTypeModel.cs
@@ -37,7 +37,7 @@ public class StructTypeModel : RuntimeTypeModel
private MethodInfo? onDeserializeMethod;
private FlatBufferStructAttribute attribute = null!;
- internal StructTypeModel(Type clrType, TypeModelContainer container) : base(clrType, container)
+ internal StructTypeModel(Type clrType, TypeModelContainer container) : base(clrType, container, container.OffsetModel)
{
}
diff --git a/src/FlatSharp/TypeModel/TableMemberModel.cs b/src/FlatSharp/TypeModel/TableMemberModel.cs
index dd5d3952..97b25e75 100644
--- a/src/FlatSharp/TypeModel/TableMemberModel.cs
+++ b/src/FlatSharp/TypeModel/TableMemberModel.cs
@@ -118,7 +118,7 @@ private string CreateSingleWidthReadItemBody(string parseItemMethodName, string
{this.GetNotPresentStatement()}
}}
- ushort relativeOffset = buffer.ReadUShort({vtableLocationVariableName} + {4 + (2 * this.Index)});
+ ushort relativeOffset = buffer.ReadUShort({vtableLocationVariableName} + {OffsetModel.OffsetSize + (2 * this.Index)});
if (relativeOffset == 0)
{{
{this.GetNotPresentStatement()}
@@ -140,7 +140,7 @@ private string CreateWideReadItemBody(string parseItemMethodName, string bufferV
int idx = this.Index + i;
relativeOffsets.Add($@"
- ushort relativeOffset{i} = buffer.ReadUShort({vtableLocationVariableName} + {4 + (2 * idx)});
+ ushort relativeOffset{i} = buffer.ReadUShort({vtableLocationVariableName} + {OffsetModel.OffsetSize + (2 * idx)});
if (relativeOffset{i} == 0)
{{
{this.GetNotPresentStatement()}
diff --git a/src/FlatSharp/TypeModel/TableTypeModel.cs b/src/FlatSharp/TypeModel/TableTypeModel.cs
index 4aa8ffb0..43a072ea 100644
--- a/src/FlatSharp/TypeModel/TableTypeModel.cs
+++ b/src/FlatSharp/TypeModel/TableTypeModel.cs
@@ -31,7 +31,6 @@ namespace FlatSharp.TypeModel
public class TableTypeModel : RuntimeTypeModel
{
internal const string OnDeserializedMethodName = "OnFlatSharpDeserialized";
- private const int FileIdentifierSize = 4;
private readonly string ParseClassName = "tableReader_" + Guid.NewGuid().ToString("n");
@@ -49,7 +48,7 @@ public class TableTypeModel : RuntimeTypeModel
private FlatBufferTableAttribute attribute = null!;
private readonly string tableReaderClassName = "tableReader_" + Guid.NewGuid().ToString("n");
- internal TableTypeModel(Type clrType, TypeModelContainer typeModelProvider) : base(clrType, typeModelProvider)
+ internal TableTypeModel(Type clrType, TypeModelContainer typeModelProvider) : base(clrType, typeModelProvider, typeModelProvider.OffsetModel)
{
}
@@ -119,8 +118,8 @@ internal TableTypeModel(Type clrType, TypeModelContainer typeModelProvider) : ba
///
internal int NonPaddedMaxTableInlineSize
{
- // add sizeof(int) for soffset_t to vtable.
- get => this.IndexToMemberMap.Values.Sum(x => x.ItemTypeModel.MaxInlineSize) + sizeof(int);
+ // add TypeModel.OffsetSize for soffset_t to vtable.
+ get => this.IndexToMemberMap.Values.Sum(x => x.ItemTypeModel.MaxInlineSize) + OffsetModel.OffsetSize;
}
public override ConstructorInfo? PreferredSubclassConstructor => this.preferredConstructor;
@@ -135,7 +134,7 @@ public override void Initialize()
this.attribute = attr;
}
- ValidateFileIdentifier(this.attribute.FileIdentifier);
+ OffsetModel.ValidateFileIdentifier(ref this.attribute.FileIdentifier);
EnsureClassCanBeInheritedByOutsideAssembly(this.ClrType, out this.preferredConstructor);
this.onDeserializeMethod = ValidateOnDeserializedMethod(this);
@@ -363,26 +362,6 @@ internal static void EnsureClassCanBeInheritedByOutsideAssembly(Type type, out C
}
}
- private static void ValidateFileIdentifier(string? fileIdentifier)
- {
- if (!string.IsNullOrEmpty(fileIdentifier))
- {
- if (fileIdentifier.Length != FileIdentifierSize)
- {
- throw new InvalidFlatBufferDefinitionException($"File identifier '{fileIdentifier}' is invalid. FileIdentifiers must be exactly {FileIdentifierSize} ASCII characters.");
- }
-
- for (int i = 0; i < fileIdentifier.Length; ++i)
- {
- char c = fileIdentifier[i];
- if (c >= 128)
- {
- throw new InvalidFlatBufferDefinitionException($"File identifier '{fileIdentifier}' contains non-ASCII characters. Character '{c}' is invalid.");
- }
- }
- }
- }
-
public override CodeGeneratedMethod CreateSerializeMethodBody(SerializationCodeGenContext context)
{
var type = this.ClrType;
@@ -483,12 +462,12 @@ public override CodeGeneratedMethod CreateSerializeMethodBody(SerializationCodeG
// Start by asking for the worst-case number of bytes from the serializationcontext.
string methodStart =
$@"
- int tableStart = {context.SerializationContextVariableName}.{nameof(SerializationContext.AllocateSpace)}({maxInlineSize}, sizeof(int));
+ int tableStart = {context.SerializationContextVariableName}.{nameof(SerializationContext.AllocateSpace)}({maxInlineSize}, {OffsetModel.OffsetSize});
{context.SpanWriterVariableName}.{nameof(SpanWriterExtensions.WriteUOffset)}({context.SpanVariableName}, {context.OffsetVariableName}, tableStart);
- int currentOffset = tableStart + sizeof(int); // skip past vtable soffset_t.
+ int currentOffset = tableStart + {OffsetModel.OffsetSize}; // skip past vtable soffset_t.
int vtableLength = {minVtableLength};
- Span vtable = stackalloc byte[{4 + 2 * (maxIndex + 1)}];
+ Span vtable = stackalloc byte[{OffsetModel.OffsetSize + 2 * (maxIndex + 1)}];
";
List body = new();
@@ -745,8 +724,8 @@ public override bool TryGetTableKeyMember([NotNullWhen(true)] out TableMemberMod
return tableMember != null;
}
- private int GetVTableLength(int index) => 4 + (2 * (index + 1));
+ private int GetVTableLength(int index) => OffsetModel.OffsetSize + (2 * (index + 1));
- private int GetVTablePosition(int index) => 4 + (2 * index);
+ private int GetVTablePosition(int index) => OffsetModel.OffsetSize + (2 * index);
}
}
diff --git a/src/FlatSharp/TypeModel/TypeFacadeTypeModelProvider.cs b/src/FlatSharp/TypeModel/TypeFacadeTypeModelProvider.cs
index db07426c..958acd11 100644
--- a/src/FlatSharp/TypeModel/TypeFacadeTypeModelProvider.cs
+++ b/src/FlatSharp/TypeModel/TypeFacadeTypeModelProvider.cs
@@ -32,9 +32,9 @@ internal class TypeFacadeTypeModelProvider : ITy
private readonly ITypeModel model;
public TypeFacadeTypeModelProvider(
- ITypeModel underlyingModel)
+ ITypeModel underlyingModel, OffsetModel offsetModel)
{
- this.model = new TypeFacadeTypeModel(underlyingModel);
+ this.model = new TypeFacadeTypeModel(underlyingModel, offsetModel);
}
public bool TryCreateTypeModel(TypeModelContainer container, Type type, [NotNullWhen(true)] out ITypeModel? typeModel)
@@ -60,12 +60,16 @@ private class TypeFacadeTypeModel : ITypeModel
private readonly ITypeModel underlyingModel;
public TypeFacadeTypeModel(
- ITypeModel underlyingModel)
+ ITypeModel underlyingModel,
+ OffsetModel offsetModel)
{
this.underlyingModel = underlyingModel;
+ this.OffsetModel = offsetModel;
}
public FlatBufferSchemaType SchemaType => this.underlyingModel.SchemaType;
+
+ public OffsetModel OffsetModel { get; }
public Type ClrType => typeof(TType);
diff --git a/src/FlatSharp/TypeModel/TypeModelContainer.cs b/src/FlatSharp/TypeModel/TypeModelContainer.cs
index 5f7e742f..faeb880f 100644
--- a/src/FlatSharp/TypeModel/TypeModelContainer.cs
+++ b/src/FlatSharp/TypeModel/TypeModelContainer.cs
@@ -36,8 +36,9 @@ public sealed class TypeModelContainer
private readonly ConcurrentDictionary cache = new ConcurrentDictionary();
private readonly List providers = new List();
- private TypeModelContainer()
+ private TypeModelContainer(OffsetModel offsetModel)
{
+ OffsetModel = offsetModel;
}
///
@@ -45,7 +46,7 @@ private TypeModelContainer()
///
public static TypeModelContainer CreateEmpty()
{
- return new TypeModelContainer();
+ return new TypeModelContainer(OffsetModel.Default);
}
///
@@ -53,12 +54,25 @@ public static TypeModelContainer CreateEmpty()
///
public static TypeModelContainer CreateDefault()
{
- var container = new TypeModelContainer();
+ var container = new TypeModelContainer(OffsetModel.Default);
container.RegisterProvider(new ScalarTypeModelProvider());
container.RegisterProvider(new FlatSharpTypeModelProvider());
return container;
}
+ ///
+ /// Creates a FlatSharp type model container with default support but with a custom offset model.
+ ///
+ public static TypeModelContainer CreateDefault(OffsetModel offsetModel)
+ {
+ var container = new TypeModelContainer(offsetModel);
+ container.RegisterProvider(new ScalarTypeModelProvider());
+ container.RegisterProvider(new FlatSharpTypeModelProvider());
+ return container;
+ }
+
+ public OffsetModel OffsetModel { get; }
+
///
/// Registers a type facade for the given type. Facades are a convenience mechanism to
/// expose types to FlatSharp that are based on some well-known underlying type.
@@ -94,12 +108,12 @@ public void RegisterTypeFacade(bool th
if (typeof(TUnderlyingType).IsValueType && Nullable.GetUnderlyingType(typeof(TUnderlyingType)) == null)
{
// non-nullable value type: omit the null check
- provider = new TypeFacadeTypeModelProvider(model);
+ provider = new TypeFacadeTypeModelProvider(model, OffsetModel);
}
else
{
// reference type or nullable value type.
- provider = new TypeFacadeTypeModelProvider, TUnderlyingType, TFacadeType>(model);
+ provider = new TypeFacadeTypeModelProvider, TUnderlyingType, TFacadeType>(model, OffsetModel);
}
// add first.
diff --git a/src/FlatSharp/TypeModel/UnionTypeModel.cs b/src/FlatSharp/TypeModel/UnionTypeModel.cs
index 19a28de9..21204070 100644
--- a/src/FlatSharp/TypeModel/UnionTypeModel.cs
+++ b/src/FlatSharp/TypeModel/UnionTypeModel.cs
@@ -29,7 +29,7 @@ public class UnionTypeModel : RuntimeTypeModel
{
private ITypeModel[] memberTypeModels;
- internal UnionTypeModel(Type unionType, TypeModelContainer provider) : base(unionType, provider)
+ internal UnionTypeModel(Type unionType, TypeModelContainer provider) : base(unionType, provider, provider.OffsetModel)
{
this.memberTypeModels = null!;
}
diff --git a/src/FlatSharp/TypeModel/ValueStructTypeModel.cs b/src/FlatSharp/TypeModel/ValueStructTypeModel.cs
index c5d393c6..c40e5489 100644
--- a/src/FlatSharp/TypeModel/ValueStructTypeModel.cs
+++ b/src/FlatSharp/TypeModel/ValueStructTypeModel.cs
@@ -36,7 +36,7 @@ public class ValueStructTypeModel : RuntimeTypeModel
private int inlineSize;
private int maxAlignment = 1;
- internal ValueStructTypeModel(Type clrType, TypeModelContainer container) : base(clrType, container)
+ internal ValueStructTypeModel(Type clrType, TypeModelContainer container) : base(clrType, container, container.OffsetModel)
{
}
diff --git a/src/FlatSharp/TypeModel/Vectors/BaseVectorTypeModel.cs b/src/FlatSharp/TypeModel/Vectors/BaseVectorTypeModel.cs
index 48d460dd..8b48c98a 100644
--- a/src/FlatSharp/TypeModel/Vectors/BaseVectorTypeModel.cs
+++ b/src/FlatSharp/TypeModel/Vectors/BaseVectorTypeModel.cs
@@ -29,7 +29,7 @@ public abstract class BaseVectorTypeModel : RuntimeTypeModel
// count of items + padding(uoffset_t);
protected static readonly int VectorMinSize = sizeof(uint) + SerializationHelpers.GetMaxPadding(sizeof(uint));
- internal BaseVectorTypeModel(Type vectorType, TypeModelContainer provider) : base(vectorType, provider)
+ internal BaseVectorTypeModel(Type vectorType, TypeModelContainer provider) : base(vectorType, provider, provider.OffsetModel)
{
this.ItemTypeModel = null!;
}
@@ -160,7 +160,7 @@ public override CodeGeneratedMethod CreateSerializeMethodBody(SerializationCodeG
int vectorOffset = {context.SerializationContextVariableName}.{nameof(SerializationContext.AllocateVector)}({itemTypeModel.PhysicalLayout[0].Alignment}, count, {this.PaddedMemberInlineSize});
{context.SpanWriterVariableName}.{nameof(SpanWriterExtensions.WriteUOffset)}({context.SpanVariableName}, {context.OffsetVariableName}, vectorOffset);
{context.SpanWriterVariableName}.{nameof(SpanWriter.WriteInt)}({context.SpanVariableName}, count, vectorOffset);
- vectorOffset += sizeof(int);
+ vectorOffset += {OffsetModel.OffsetSize};
{this.CreateLoop(context.Options, context.ValueVariableName, "count", "current", loopBody)}";
diff --git a/src/FlatSharp/TypeModel/VectorsOfUnion/BaseVectorOfUnionTypeModel.cs b/src/FlatSharp/TypeModel/VectorsOfUnion/BaseVectorOfUnionTypeModel.cs
index 6942e56d..1aaac8a4 100644
--- a/src/FlatSharp/TypeModel/VectorsOfUnion/BaseVectorOfUnionTypeModel.cs
+++ b/src/FlatSharp/TypeModel/VectorsOfUnion/BaseVectorOfUnionTypeModel.cs
@@ -26,7 +26,7 @@ namespace FlatSharp.TypeModel
///
public abstract class BaseVectorOfUnionTypeModel : RuntimeTypeModel
{
- internal BaseVectorOfUnionTypeModel(Type vectorType, TypeModelContainer provider) : base(vectorType, provider)
+ internal BaseVectorOfUnionTypeModel(Type vectorType, TypeModelContainer provider) : base(vectorType, provider, provider.OffsetModel)
{
this.ItemTypeModel = null!;
}
@@ -104,12 +104,12 @@ public override bool TryGetUnderlyingVectorType([NotNullWhen(true)] out ITypeMod
public override CodeGeneratedMethod CreateGetMaxSizeMethodBody(GetMaxSizeCodeGenContext context)
{
// 2 vectors.
- int baseSize = 2 * (sizeof(int) + SerializationHelpers.GetMaxPadding(sizeof(int)));
+ int baseSize = 2 * (OffsetModel.OffsetSize + SerializationHelpers.GetMaxPadding(OffsetModel.OffsetSize));
string body =
$@"
int count = {context.ValueVariableName}.{this.LengthPropertyName};
- int length = {baseSize} + (count * (sizeof(byte) + sizeof(int)));
+ int length = {baseSize} + (count * (sizeof(byte) + {OffsetModel.OffsetSize}));
for (int i = 0; i < count; ++i)
{{
@@ -139,12 +139,12 @@ public override CodeGeneratedMethod CreateSerializeMethodBody(SerializationCodeG
int discriminatorVectorOffset = {context.SerializationContextVariableName}.{nameof(SerializationContext.AllocateVector)}(sizeof(byte), count, sizeof(byte));
{context.SpanWriterVariableName}.{nameof(SpanWriterExtensions.WriteUOffset)}({context.SpanVariableName}, {context.OffsetVariableName}.offset0, discriminatorVectorOffset);
{context.SpanWriterVariableName}.{nameof(SpanWriter.WriteInt)}({context.SpanVariableName}, count, discriminatorVectorOffset);
- discriminatorVectorOffset += sizeof(int);
+ discriminatorVectorOffset += {OffsetModel.OffsetSize};
- int offsetVectorOffset = {context.SerializationContextVariableName}.{nameof(SerializationContext.AllocateVector)}(sizeof(int), count, sizeof(int));
+ int offsetVectorOffset = {context.SerializationContextVariableName}.{nameof(SerializationContext.AllocateVector)}({OffsetModel.OffsetSize}, count, {OffsetModel.OffsetSize});
{context.SpanWriterVariableName}.{nameof(SpanWriterExtensions.WriteUOffset)}({context.SpanVariableName}, {context.OffsetVariableName}.offset1, offsetVectorOffset);
{context.SpanWriterVariableName}.{nameof(SpanWriter.WriteInt)}({context.SpanVariableName}, count, offsetVectorOffset);
- offsetVectorOffset += sizeof(int);
+ offsetVectorOffset += {OffsetModel.OffsetSize};
for (int i = 0; i < count; ++i)
{{
@@ -155,7 +155,7 @@ public override CodeGeneratedMethod CreateSerializeMethodBody(SerializationCodeG
{innerContext.GetSerializeInvocation(itemTypeModel.ClrType)};
discriminatorVectorOffset++;
- offsetVectorOffset += sizeof(int);
+ offsetVectorOffset += {OffsetModel.OffsetSize};
}}";
return new CodeGeneratedMethod(body);
diff --git a/src/Tests/FlatSharpCompilerTests/FileIdentifierTests.cs b/src/Tests/FlatSharpCompilerTests/FileIdentifierTests.cs
index b36b24b6..ee48307e 100644
--- a/src/Tests/FlatSharpCompilerTests/FileIdentifierTests.cs
+++ b/src/Tests/FlatSharpCompilerTests/FileIdentifierTests.cs
@@ -14,6 +14,9 @@
* limitations under the License.
*/
+using System.Collections.Generic;
+using FlatSharp.TypeModel;
+
namespace FlatSharpTests.Compiler
{
using System;
@@ -27,8 +30,17 @@ namespace FlatSharpTests.Compiler
public class FileIdentifierTests
{
- [Fact]
- public void Multiple_Root_Types_Different_Namespaces()
+ public static readonly IEnumerable