Skip to content

Releases: jamescourtney/FlatSharp

Version 5.2.0

12 Apr 02:57
2e8ab94
Compare
Choose a tag to compare

FlatSharp 5.2.0 brings a few new features and a couple of bugfixes

Feature: Vectors of Unions

FlatSharp now supports vectors of unions for arrays, IList, and IReadOnlyList. Declaring a vector of unions is just like any other vector:

[FlatBufferItem(3)] public virtual IList<FlatBufferUnion<string, MyTable, MyStruct>> VectorOfUnion { get; set; }
table MyTable
{
   VectorOfUnion : [Union] (fs_vector:"IList");
}

Feature: IList Devirtualization

When serializing IList<T> vectors, FlatSharp now attempts to devirtualize the interface into a couple of well-known concrete types: T[] and List<T>. Doing so allows the JIT to generate much more compact code.

Feature: OnFlatSharpDeserialized

When a method with the correct signature is defined, FlatSharp will invoke it upon deserializing an object:

protected void OnFlatSharpDeserialized(FlatBufferDeserializationContext context)
{
 ...
}

Feature-ish: Support for Empty Tables

FlatSharp no longer raises an error when defining a table with no properties. Empty structs are not allowed.

5.1.0

18 Mar 21:38
40e36e7
Compare
Choose a tag to compare

5.1.0 is a minor release for FlatSharp that contains an important fix and a couple of new features:

Fix: Mono AOT and Unity AOT compilation now work. FlatSharp relies heavily on generics, and these AOT compilers need "hints" as to what types of values the generics might be so that they can precompile them.

Feature: All tables defined in fbs files now implement IFlatBufferSerializable<T>, which provides access to the ISerializer<T> instance. This makes it possible to test for serializable objects and write reusable code to interact with them.

Feature: Struct serialization code has been optimized to elide unnecessary bounds checks. This can significantly increase the speed of struct serialization (especially with struct vectors).

5.0.0

10 Mar 21:45
c95f29e
Compare
Choose a tag to compare

Version 5 is a major release for FlatSharp, with support for lots of new features:

  • ~5-15% performance uplift for both Serialize and Parse workflows, depending on scenario.
  • file_identifier and root_type support
  • Updated Flatsharp FBS annotations to start with fs_
  • Deserialized FlatSharp objects now implement IFlatBufferDeserializedObject so objects can be queried to see if they are deserialized.
  • Non-Generic Serialize/Parse methods exposed via FlatBufferSerializer.Default.Compile(Type t) or FlatBufferSerializer.Default.Compile(object o)
  • Types are no longer required to expose parameterless constructors (can use a constructor accepting FlatBufferDeserializationContext instead).
  • Support for fixed-size vectors in structs: field:[int:8]
  • Support for C# 8 and 9 features
    • Nullable annotations in FlatSharp core libraries and generated C#
    • Init-only properties

Breaking changes:

  • Compiler no longer supports the NoCustomType metadata on unions.
  • Compiler no longer suports the ObsoleteDefaultConstructor metadata. It has been replaced with fs_defaultCtor, which provides more options.
  • For memory vectors, compiler generates nullable Memory<byte>? instead of previous behavior of non-nullable. This is more in-line with how flatbuffers treats vectors as optional fields.
  • ITypeModel has had interface changes.
  • FlatBufferUnion and derivatives no longer supply a Clone method.
  • OnInitialized partial methods for generated types now accepts a FlatBufferDeserializationContext parameter instead of no parameter.
  • Generated code requires C# 8 compiler, C# 9 for full nullable support.

4.2.2: Type Facades and 'id' attribute in FBS files

14 Feb 05:09
acfb20b
Compare
Choose a tag to compare

4.2.2 is a minor release of FlatSharp that brings a couple of new features!

'id' Attribute in FBS files

It's now possible to manually specify the 'id' attribute on table definitions in FBS files:

table MyNeatTable {
   foo:int (id:2)
   bar:int (id:1)
   baz:int (id:0)
}

ID's are an all-or-none proposition. Either all properties have IDs or none do. Thanks to @Eshva for the contribution here!

Type Facades

Type Facades are a new feature, enabling you to expose new types in FlatSharp. Facades are a handy way to extend FlatSharp's type model for types that are not natively available in FlatBuffers. The samples project has an example showing how to add Guid and DateTimeOffset Facades to your project.

Facades are currently only available when using runtime-generated serializers through FlatBufferSerializer. Compiler support is tricky since it requires plugins, but is something being considered for future releases.

Version 4.1.0: Non-Virtual Properties and FBS Annotations

17 Oct 21:39
f6115ca
Compare
Choose a tag to compare

Version 4.1.0 is a minor release and builds on the performance improvements in 4.0.0.

The main improvement in version 4.1.0 is support for new configurations for properties:

  • Non-virtual properties now supported (setters are required). Non-Virtual properties are always deserialized greedily.
  • Protected and Protected Internal setters now supported
[FlatBufferTable]
public class MyTable
{
   [FlatBufferItem(0)] public virtual int VirtualInt { get; protected set; }
   [FlatBufferItem(1)] public string NonVirtualString { get; protected internal set; } 
   [FlatBufferItem(2)] public virtual int ReadOnlyInt { get; }
}

FBS files also support these:

table MyTable // nonVirtual is supported at the table level to set a default for all properties.
{
   VirtualInt:int (setter:"protected");
   NonVirtualString:string (setter:"protectedinternal", nonVirtual);
   ReadOnlyVirtualInt:int (setter:"none");
}

Additionally, the FlatSharp compiler now supports the ObsoleteDefaultConstructor attribute on tables and structs to apply a [Obsolete] attribute to the generated default constructor. This can help create immutable objects.

Version 4.0

07 Oct 12:49
14a7edc
Compare
Choose a tag to compare

Version 4 is a significant milestone for FlatSharp, and represents the culmination of a lot of work. Hope you enjoy it, to the extent that it's possible to enjoy a serialization library!

What's new?

Glad you asked!

  • Support for optional/nullable scalars (tables only) (google/flatbuffers#6014)
  • Support for "indexed vectors", which are Vectors that look and act like Dictionaries. Under the hood, these are sorted vectors that expose a simpler programming model, so it's no longer necessary to worry about whether a vector is sorted or not. Check out the indexed vectors sample!
  • Shared strings are now supported in sorted vectors
  • New method of publishing benchmark data, benchmarks extended to include .NET 5.0

Internal stuff

  • Lots of work went into optimizing how the CLR JIT treats FlatSharp's code. Performance is increased anywhere from 10 - 30% relative to version 3.3.1.

    • Much of this improvement was changes to allow the JIT to elide virtual function calls when invoking methods on SpanReader and InputBuffer. More background is available here: dotnet/runtime#32815
    • Other changes involved removing some unnecessary branches and function calls on hot paths
  • FlatSharp's backend was completely rewritten to be more modular, so that future types can be supported more easily. It is now possible (though not advised) to write your own plugins. This amounted to a rewrite of a large part of the code.

Breaking Changes

FlatSharp adheres to semantic versioning, and there are breaking public API changes in version 4:

  • SpanWriter has been changed from a class to a struct. It is no longer inheritable. A new ISpanWriter interface has been introduced should you wish to provide your own.
  • UnsafeSpanWriter remains a class, but is sealed.
  • The base class InputBuffer has been removed. It has been replaced with IInputBuffer
    • ArrayInputBuffer, MemoryInputBuffer, ReadOnlyMemoryInputBuffer, and the unsafe variants remain the same.
  • Support for memory vectors has been dropped for all types but byte. This was to address a design oversight where precompiled serializers would produce incorrect results when running on big-endian platforms.
    • Memory<byte> and ReadOnlyMemory<byte> remain supported.

String Deduplication and Compiler Enhancements

20 Aug 05:44
b1fe59f
Compare
Choose a tag to compare

Version 3.3.0 of FlatSharp introduces a new feature: String Deduplication, also called Shared Strings. This feature (off by default), enables FlatSharp to only write one instance of a string that occurs many times within your buffer. For buffers with many repeated strings, this can save quite a bit of space in your serialized buffers. Usually, it will slow down serialization and parsing slightly, which is why it's left off by default. For more information, please take a look at the shared strings sample!

The FlatSharp compiler has been enhanced to be more friendly, courtesy of @eltone. .fbs.cs files have been moved to the obj directory where they belong, so they won't clutter your solutions any longer. Furthermore, some Unix build issues have been resolved (#54), a first-build bug has been addressed (#45, #55), and gRPC hosting has been extended to support ASP.NET core (#53). Thanks, Anthony!

Union Improvements

31 Jul 08:22
625c779
Compare
Choose a tag to compare

It's been awhile, but FlatSharp has a new release out with support for better unions when using FBS files. So what's new?

Let's talk about the problem with unions in prior releases using this FBS schema as our guide:

table Dog { ... }
table Cat { ... }
table Fish { ... }

union FavoritePet { Dog, Cat, Fish }

table Person { FavoritePet:FavoritePet; }

You'd get some code that looked like this:

[FlatBufferTable]
public class Person : object
{
     [FlatBufferItem(0)]
     public virtual FlatBufferUnion<Dog, Cat, Fish> FavoritePet { get; set; }
}

In short, you declared a FlatBufferUnion{T} instance and used the generic parameters of that type to call out the members of the union. When interacting with it, code often looked like this:

Person p = (...)
Dog dog = p.FavoritePet.Item1; // Unintuitive.

switch (p.FavoritePet.Discriminator)
{
   case 1: // What does 1 mean?
      Console.WriteLine("dog"); break;
   case 2: // cat
      Console.WriteLine("cat"); break;
   case 3:
   default:
      Console.WriteLine("fish"); break;
}

However, simply using a generic type supplied by FlatSharp wasn't very useful because it made the code harder to read. Item1 is just not a good description. The other big problem is a union that has many members. Imagine trying to plumb FlatBufferUnion<T1,...,T10> through your code.

In version 3.2.0, FlatSharp will generate custom union classes for you when using FBS schemas. In this example, you'd get a FavoritePet class that looks like this:

public class FavoritePet : FlatBufferUnion<Dog, Cat, Fish>
{
   public enum ItemKind : byte
   {
       Dog = 1,
       Cat = 2,
       Fish = 3,
   }

   public ItemKind Kind { get; }

   public Dog Dog { get; }

   public Cat Cat { get; }

   public Fish Fish { get; }
}

This should greatly increase the usability of unions. The final change is a set of methods that have been added to all Union types called Switch. The methods are semantically the same as a switch statement, but with compiler support so you'll get build breaks when a new item is added to the union. This is handy because it ensures that you explicitly address all cases in your code where the new union member could occur. Catching errors at build time is better than runtime!

FavoritePet pet = person.Pet;
string petSays = pet.Switch(
  caseDefault: () => "??",
  caseDog: () => "Woof",
  caseCat: () => "Meow",
  caseFish: () => "gurgle gurgle");

3.0.0

30 Mar 09:18
1792322
Compare
Choose a tag to compare

3.0 is a major release of FlatSharp, with new features and bug fixes. Please read the full notes below before upgrading, as there is a breaking change around enums declared in FBS files.

Compiler Improvements

  • FlatSharp generates copy constructors for you
  • Increased compatibility with the flatc compiler from Google:
    • Support includes
    • Support quoted metadata
    • Fix a bug around the default numbering for enums (read the breaking change below)

Runtime Improvements

  • Usability improvements with some new extension methods on ISerializer<T> for serializing and deserializing.
  • Support for parsing using ReadOnlyMemory<byte>
  • Support for Sorted Vectors
  • Some scenarios will see a ~10% performance uplift (see the benchmarks folder)

Breaking Changes

This release of FlatSharp fixes a bug related to enum numbering. Enums declared in FBS files in FlatSharp 2.X started their numbering at 1 if left unspecified:

enum MyEnum : ubyte {
   First, Second, Third
}

Translated to

public enum MyEnum : byte {
   First = 1,
   Second = 2,
   Third = 3,
}

This was a bug reported by @thomas-t1 in #30. The correct numbering starts at 0. In version 3.X, FlatSharp will generate this code instead:

public enum MyEnum : byte {
   First = 0,
   Second = 1,
   Third = 2
}

This is a problem for any upgrades. If you have been using FlatSharp with FBS files to generate enums, please ensure that you have explicitly set the first member to 1 like so:

enum MyEnum : ubyte {
   First = 1, Second, Third
}

This will allow you to preserve the old numbering.

Build Time Serializer Generation

30 Jan 07:51
8e414b3
Compare
Choose a tag to compare
  • Build time serializer generation! FlatSharp can now be used exclusively at build-time with the FlatSharp.Compiler and FlatSharp.Runtime packages. This removes the dependency on the Roslyn compiler at runtime.
  • NullReferenceExceptions with nested structs fixed.
  • FBS files generated formatted C# code.
  • Performance optimizations with the CacheListVectorData option.