public static void Run() { TypeModelContainer container = TypeModelContainer.CreateDefault(); container.RegisterTypeFacade <long, DateTimeOffset, DateTimeOffsetTypeFacadeConverter>(); container.RegisterTypeFacade <byte[], Guid, GuidByteArrayConverter>(); var example = new FacadeExampleTable { Guid = Guid.NewGuid(), Timestamp = DateTimeOffset.UtcNow, }; FlatBufferSerializer serializer = new FlatBufferSerializer( new FlatBufferSerializerOptions(FlatBufferDeserializationOption.PropertyCache), container); byte[] destination = new byte[1024]; serializer.Serialize(example, destination); var parsed = serializer.Parse <FacadeExampleTable>(destination); Debug.Assert(parsed.Guid == example.Guid); Debug.Assert(parsed.Timestamp == example.Timestamp); }
// TODO: consider moving to TableOrStructDefinition. private static string GenerateSerializerForType(Assembly assembly, TableOrStructDefinition tableOrStruct) { CSharpHelpers.ConvertProtectedInternalToProtected = false; try { Type type = assembly.GetType(tableOrStruct.FullName); var options = new FlatBufferSerializerOptions(tableOrStruct.RequestedSerializer.Value); var generator = new RoslynSerializerGenerator(options, TypeModelContainer.CreateDefault()); var method = generator .GetType() .GetMethod(nameof(RoslynSerializerGenerator.GenerateCSharp), BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.Public) .MakeGenericMethod(type); try { string code = (string)method.Invoke(generator, new[] { "private" }); return(code); } catch (TargetInvocationException ex) { ExceptionDispatchInfo.Capture(ex.InnerException).Throw(); throw; } } finally { CSharpHelpers.ConvertProtectedInternalToProtected = true; } }
public void Facade_NullReturnedFromConverter() { TypeModelContainer container = TypeModelContainer.CreateDefault(); container.RegisterTypeFacade <string, DateTimeOffset, InvalidDateTimeStringConverter>(); FlatBufferSerializer serializer = new FlatBufferSerializer( new FlatBufferSerializerOptions(FlatBufferDeserializationOption.Greedy), container); byte[] destination = new byte[200]; var compiled = serializer.Compile <ExtensionTable <DateTimeOffset> >(); try { serializer.Serialize( new ExtensionTable <DateTimeOffset> { Item = DateTimeOffset.UtcNow }, destination); Assert.False(true, "expected exception"); } catch (InvalidOperationException ex) { Assert.Contains("ITypeFacadeConverter", ex.Message); } }
public void Facade_NullReturnedFromConverter2() { TypeModelContainer container = TypeModelContainer.CreateDefault(); container.RegisterTypeFacade <long?, DateTimeOffset?, InvalidNullableDateTimeNullableLongConverter>(); FlatBufferSerializer serializer = new FlatBufferSerializer( new FlatBufferSerializerOptions(FlatBufferDeserializationOption.Greedy), container); byte[] destination = new byte[200]; var compiled = serializer.Compile <ExtensionTable <DateTimeOffset?> >(); try { serializer.Serialize( new ExtensionTable <DateTimeOffset?> { Item = DateTimeOffset.UtcNow }, destination); Assert.Fail(); } catch (InvalidOperationException ex) { Assert.IsTrue(ex.Message.Contains("ITypeFacadeConverter")); } }
private static string CreateCSharp(BaseSchemaMember rootNode, CompilerOptions options) { ErrorContext.Current.ThrowIfHasErrors(); if (string.IsNullOrEmpty(rootNode.DeclaringFile)) { throw new InvalidFbsFileException("FlatSharp.Internal: RootNode missing declaring file"); } Assembly? assembly = null; CodeWriter writer = new CodeWriter(); var steps = new[] { CodeWritingPass.Initialization, CodeWritingPass.PropertyModeling, CodeWritingPass.SerializerGeneration, CodeWritingPass.RpcGeneration, }; foreach (var step in steps) { var localOptions = options; if (step <= CodeWritingPass.PropertyModeling) { localOptions = localOptions with { NullableWarnings = false }; } if (step > CodeWritingPass.Initialization) { string code = writer.ToString(); (assembly, _, _) = RoslynSerializerGenerator.CompileAssembly(code, true); } writer = new CodeWriter(); rootNode.WriteCode( writer, new CompileContext { CompilePass = step, Options = localOptions, RootFile = rootNode.DeclaringFile, PreviousAssembly = assembly, TypeModelContainer = TypeModelContainer.CreateDefault(), }); ErrorContext.Current.ThrowIfHasErrors(); } string rawCode = writer.ToString(); string formattedCode = RoslynSerializerGenerator.GetFormattedText(rawCode); return(formattedCode); } }
public void Facade_SortedVector() { TypeModelContainer container = TypeModelContainer.CreateDefault(); container.RegisterTypeFacade <long, DateTimeOffset, DateTimeTicksConverter>(); var ex = Assert.Throws <InvalidFlatBufferDefinitionException>( () => container.CreateTypeModel(typeof(ExtensionTable <IIndexedVector <DateTimeOffset, KeyTable> >))); Assert.Equal( "Table FlatSharpTests.TypeFacadeTests.KeyTable declares a key property on a type that that does not support being a key in a sorted vector.", ex.Message); }
public void Facade_Chained() { TypeModelContainer container = TypeModelContainer.CreateDefault(); container.RegisterTypeFacade <long, TimeSpan, TimeSpanTicksConverter>(); container.RegisterTypeFacade <TimeSpan, DateTimeOffset, DateTimeTimeSpanConverter>(); DateTimeOffset ts = DateTimeOffset.UtcNow; TimeSpan span = ts - DateTimeOffset.MinValue; long expectedValue = span.Ticks; this.FacadeTest <long, TimeSpan, TimeSpanTicksConverter>(expectedValue, span, container); this.FacadeTest <TimeSpan, DateTimeOffset, DateTimeTimeSpanConverter>(span, ts, container); }
public static ParserCodeGenContext CreateParserContext(FlatBufferSerializerOptions?options = null) { return(new ParserCodeGenContext( "a", "b", "c", false, "d", new ReturnsRandomDictionary(), new ReturnsRandomDictionary(), options ?? new FlatBufferSerializerOptions(), TypeModelContainer.CreateDefault(), new Dictionary <ITypeModel, List <TableFieldContext> >())); }
private void FacadeTest <TUnderlyingType, TType, TConverter>( TUnderlyingType underlyingValue, TType value, TypeModelContainer container = null) where TConverter : struct, ITypeFacadeConverter <TUnderlyingType, TType> { if (container == null) { container = TypeModelContainer.CreateDefault(); container.RegisterTypeFacade <TUnderlyingType, TType, TConverter>(); } FlatBufferSerializer serializer = new FlatBufferSerializer( new FlatBufferSerializerOptions(FlatBufferDeserializationOption.Greedy), container); byte[] destination = new byte[1024]; byte[] destination2 = new byte[1024]; var compiled = serializer.Compile <ExtensionTable <TType> >(); var underlyingItem = new ExtensionTable <TUnderlyingType> { Item = underlyingValue }; var facadeItem = new ExtensionTable <TType> { Item = value }; serializer.Serialize(facadeItem, destination); serializer.Serialize(underlyingItem, destination2); Assert.True(destination.AsSpan().SequenceEqual(destination2)); var parsed = serializer.Parse <ExtensionTable <TType> >(destination); Assert.Equal(parsed.Item, value); Assert.Equal(serializer.GetMaxSize(facadeItem), serializer.GetMaxSize(underlyingItem)); }
/// <summary> /// Creates a new FlatBufferSerializer using the given options. /// </summary> public FlatBufferSerializer(FlatBufferSerializerOptions options) : this(options, TypeModelContainer.CreateDefault()) { }
public static bool TryResolve(string type, out ITypeModel builtInType) { return(TryResolve(type, TypeModelContainer.CreateDefault(), out builtInType)); }
private void RunTest <T>(string fbsType, int length, FlatBufferDeserializationOption option) where T : struct { string schema = $@" {MetadataHelpers.AllAttributes} namespace StructVectorTests; table Table ({MetadataKeys.SerializerKind}) {{ foo:Foo; }} struct Foo {{ V:[{fbsType}:{length}]; }}"; (Assembly asm, string code) = FlatSharpCompiler.CompileAndLoadAssemblyWithCode( schema, new()); Type tableType = asm.GetType("StructVectorTests.Table"); Type fooType = asm.GetType("StructVectorTests.Foo"); var typeModel = TypeModelContainer.CreateDefault().CreateTypeModel(fooType); Assert.Equal(FlatBufferSchemaType.Struct, typeModel.SchemaType); for (int i = 0; i < length; ++i) { PropertyInfo p = fooType.GetProperty($"__flatsharp__V_{i}", BindingFlags.Instance | BindingFlags.NonPublic); Assert.True(p.GetMethod.IsFamily); Assert.True(p.SetMethod.IsFamily); Assert.True(p.GetMethod.IsVirtual); Assert.True(p.SetMethod.IsVirtual); var metaAttr = p.GetCustomAttribute <FlatBufferMetadataAttribute>(); var attr = p.GetCustomAttribute <FlatBufferItemAttribute>(); Assert.NotNull(attr); Assert.NotNull(metaAttr); Assert.Equal(i, attr.Index); Assert.Equal(FlatBufferMetadataKind.Accessor, metaAttr.Kind); Assert.Equal($"V[{attr.Index}]", metaAttr.Value); } var vectorProperty = fooType.GetProperty("V"); Assert.Null(vectorProperty.GetCustomAttribute <FlatBufferItemAttribute>()); // pseudo-item, not actual. Assert.True(vectorProperty.GetMethod.IsPublic); Assert.False(vectorProperty.GetMethod.IsVirtual); Assert.Null(vectorProperty.SetMethod); dynamic table = Activator.CreateInstance(tableType); dynamic foo = Activator.CreateInstance(fooType); table.foo = foo; Assert.Equal(length, foo.V.Count); // Test copyFrom with full array. List <T> items = new List <T>(); for (int i = 0; i < length; ++i) { items.Add(GetRandom <T>()); } table.foo.V.CopyFrom((IReadOnlyList <T>)items); for (int i = 0; i < length; ++i) { CheckRandom <T>(items[i], table.foo.V[i]); } for (int i = 0; i < length; ++i) { foo.V[i] = GetRandom <T>(); } byte[] data = new byte[1024]; var fbs = new FlatBufferSerializer( new FlatBufferSerializerOptions(option) { EnableAppDomainInterceptOnAssemblyLoad = true }); var serializer = fbs.Compile((object)table); serializer.Write(data, (object)table); dynamic parsed = serializer.Parse(data); dynamic copy = Activator.CreateInstance(tableType, (object)parsed); Assert.Equal(length, parsed.foo.V.Count); for (int i = 0; i < length; ++i) { CheckRandom <T>(foo.V[i], parsed.foo.V[i]); CheckRandom <T>(foo.V[i], copy.foo.V[i]); } bool isMutable = option is FlatBufferDeserializationOption.GreedyMutable; if (length == 0) { return; } try { for (int i = 0; i < length; ++i) { parsed.foo.V[i] = GetRandom <T>(); } Assert.True(isMutable); } catch (NotMutableException) { Assert.False(isMutable); } }
private void RunTest <T>(string fbsType, int length, FlatBufferDeserializationOption option) where T : struct { string schema = $@" namespace StructVectorTests; table Table ({MetadataKeys.SerializerKind}) {{ foo:Foo; }} struct Foo {{ V:[{fbsType}:{length}]; }}"; Assembly asm = FlatSharpCompiler.CompileAndLoadAssembly( schema, new()); Type tableType = asm.GetType("StructVectorTests.Table"); Type fooType = asm.GetType("StructVectorTests.Foo"); var typeModel = TypeModelContainer.CreateDefault().CreateTypeModel(fooType); Assert.AreEqual(FlatBufferSchemaType.Struct, typeModel.SchemaType); for (int i = 0; i < length; ++i) { PropertyInfo p = fooType.GetProperty($"__flatsharp__V_{i}"); Assert.IsTrue(p.GetMethod.IsPublic); Assert.IsTrue(p.SetMethod.IsPublic); Assert.IsTrue(p.GetMethod.IsVirtual); Assert.IsTrue(p.SetMethod.IsVirtual); var attr = p.GetCustomAttribute <FlatBufferItemAttribute>(); Assert.IsNotNull(attr); Assert.AreEqual(i, attr.Index); var browsableAttr = p.GetCustomAttribute <EditorBrowsableAttribute>(); Assert.IsNotNull(browsableAttr); Assert.AreEqual(EditorBrowsableState.Advanced, browsableAttr.State); } var vectorProperty = fooType.GetProperty("V"); Assert.IsNull(vectorProperty.GetCustomAttribute <FlatBufferItemAttribute>()); // pseudo-item, not actual. Assert.IsNull(vectorProperty.GetCustomAttribute <EditorBrowsableAttribute>()); Assert.IsTrue(vectorProperty.GetMethod.IsPublic); Assert.IsFalse(vectorProperty.GetMethod.IsVirtual); Assert.IsNull(vectorProperty.SetMethod); dynamic table = Activator.CreateInstance(tableType); dynamic foo = Activator.CreateInstance(fooType); table.foo = foo; Assert.AreEqual(length, foo.V.Count); for (int i = 0; i < length; ++i) { foo.V[i] = GetRandom <T>(); } byte[] data = new byte[1024]; var fbs = new FlatBufferSerializer( new FlatBufferSerializerOptions(option) { EnableAppDomainInterceptOnAssemblyLoad = true }); var serializer = fbs.Compile((object)table); serializer.Write(data, (object)table); dynamic parsed = serializer.Parse(data); dynamic copy = Activator.CreateInstance(tableType, (object)parsed); Assert.AreEqual(length, parsed.foo.V.Count); for (int i = 0; i < length; ++i) { CheckRandom <T>(foo.V[i], parsed.foo.V[i]); CheckRandom <T>(foo.V[i], copy.foo.V[i]); } bool isMutable = option is FlatBufferDeserializationOption.VectorCacheMutable or FlatBufferDeserializationOption.GreedyMutable; if (length == 0) { return; } try { for (int i = 0; i < length; ++i) { parsed.foo.V[i] = GetRandom <T>(); } Assert.IsTrue(isMutable); } catch (NotMutableException) { Assert.IsFalse(isMutable); } }
/// <summary> /// Gets or creates a runtime type model from the given type. This is only used in test cases any more. /// </summary> internal static ITypeModel CreateFrom(Type type) { return(TypeModelContainer.CreateDefault().CreateTypeModel(type)); }