-
Notifications
You must be signed in to change notification settings - Fork 582
Add internal docs for C# bindings packages #2938
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Open
kazimuth
wants to merge
3
commits into
master
Choose a base branch
from
jgilles/docs/csharp-bindings
base: master
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Open
Changes from all commits
Commits
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,69 @@ | ||
> ⚠️ **Internal Project** ⚠️ | ||
> | ||
> This project is intended for internal use only. It is **not** stable and may change without notice. | ||
|
||
## Internal documentation | ||
|
||
This project contains Roslyn [incremental source generators](https://github.com/dotnet/roslyn/blob/main/docs/features/incremental-generators.md) that augment types with methods for self-describing and serialization. It relies on the [BSATN.Runtime](../BSATN.Runtime/) library in the generated code. | ||
|
||
This project provides `[SpacetimeDB.Type]`. This attribute makes types self-describing, allowing them to automatically register their structure with SpacetimeDB. It also generates serialization code to the [BSATN format](https://spacetimedb.com/docs/bsatn). Any C# type annotated with `[SpacetimeDB.Type]` can be used as a table column or reducer argument. | ||
|
||
Any `[SpacetimeDB.Type]` must be marked `partial` to allow the generated code to add new functionality. | ||
|
||
`[SpacetimeDB.Type]` also supports emulation of tagged enums in C#. For that, the struct needs to inherit a marker interface `SpacetimeDB.TaggedEnum<Variants>` where `Variants` is a named tuple of all possible variants, e.g.: | ||
|
||
```csharp | ||
[SpacetimeDB.Type] | ||
partial record Option<T> : SpacetimeDB.TaggedEnum<(T Some, Unit None)>; | ||
``` | ||
|
||
will generate inherited records `Option.Some(T Some_)` and `Option.None(Unit None_)`. It allows | ||
you to use tagged enums in C# in a similar way to Rust enums by leveraging C# pattern-matching | ||
on any instance of `Option<T>`. | ||
|
||
## What is generated | ||
|
||
See [`../Codegen.Tests/fixtures/client/snapshots`](../Codegen.Tests/fixtures/client/snapshots/) for examples of the generated code. | ||
[`../Codegen.Tests/fixtures/server/snapshots`](../Codegen.Tests/fixtures/server/snapshots/) also has examples, those filenames starting with `Type#`. | ||
In addition, in any project using this library, you can set `<EmitCompilerGeneratedFiles>true</EmitCompilerGeneratedFiles>` in the `<PropertyGroup>` of your `.csproj` to see exactly what code is geing generated for your project. | ||
|
||
`[SpacetimeDB.Type]` automatically generates correct `Equals`, `GetHashCode`, and `ToString` methods for the type. It also generates serialization code. | ||
|
||
Any `[SpacetimeDB.Type]` will have an auto-generated member struct named `BSATN`. This struct is zero-sized and implements the interface `SpacetimeDB.BSATN.IReadWrite<T>` interface. This is used to serialize and deserialize elements of the struct. | ||
|
||
```csharp | ||
[SpacetimeDB.Type] | ||
partial struct Banana { | ||
public int Freshness; | ||
public int LengthMeters; | ||
} | ||
|
||
void Example(System.IO.BinaryReader reader, System.IO.BinaryWriter writer) { | ||
Banana.BSATN serializer = new(); | ||
Banana banana1 = serializer.Read(reader); // read a BSATN-encoded Banana from the reader. | ||
Banana banana2 = serializer.Read(reader); | ||
Console.Log($"bananas: {banana1} {banana2}"); | ||
Console.Log($"equal?: {banana1.Equals(banana2)}"); | ||
serializer.write(writer, banana2); // write a BSATN-encoded Banana to the writer. | ||
serializer.write(writer, banana1); | ||
} | ||
``` | ||
|
||
Since `Banana.BSATN` takes up no space in memory, allocating one is free. We use this pattern because the C# versions we target don't support static interface methods. | ||
|
||
`[SpacetimeDB.Type]`s that do not inherit from `SpacetimeDB.TaggedEnum` implement an additional interface, `IStructuralReadWrite`. This allows them to be read without using a serializer. (This is not possible for `TaggedEnum`s because their concrete type is not known before deserialization.) | ||
|
||
```csharp | ||
void Example(System.IO.BinaryReader reader, System.IO.BinaryWriter writer) { | ||
Banana banana = new(); // has default field values. | ||
banana.ReadFields(reader); // now it is initialized. | ||
banana.WriteFields(writer); // and we can write it out directly as well. | ||
} | ||
``` | ||
|
||
The `IReadWrite` interface has an additional method, `AlgebraicType GetAlgebraicType()`. This returns a description of the type that is used during module initialization; see [`../Runtime`](../Runtime/) for more information. | ||
|
||
## Testing | ||
The testing for this project lives in two places. | ||
- [`../Codegen.Tests`](../Codegen.Tests/) contains snapshot-based tests. These verify that the generated code looks as expected and allow it to be reviewed more easily. | ||
- Randomized runtime tests live in [`../BSATN.Runtime.Tests`](../BSATN.Runtime.Tests/). These tests randomly fuzz the generated serializers for a variety of types. |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,19 @@ | ||
> ⚠️ **Internal Project** ⚠️ | ||
> | ||
> This project is intended for internal use only. It is **not** stable and may change without notice. | ||
|
||
## Internal documentation | ||
|
||
This project contains interfaces and runtime support code for [BSATN serialization](https://spacetimedb.com/docs/bsatn) in C#. It is the companion of the [BSATN.Codegen](../BSATN.Codegen/) project. | ||
|
||
See [`../BSATN.Runtime.Tests/`](../BSATN.Runtime.Tests/) for tests. | ||
|
||
### User-facing types | ||
|
||
This project contains implementations of a number of wide integer types for compatibility with SpacetimeDB. It also has implementations of a number of "special" SpacetimeDB types, including `Identity`, `ConnectionId`, `Timestamp`, `TimeDuration`, and `ScheduleAt`. These live in [`./Builtins.cs`](./Builtins.cs). It also contains the `AlgebraicType` type, which is not really user-facing but is important internally. | ||
|
||
There are also two of important interfaces: `IStructuralReadWrite` and `IReadWrite<T>`. See their documentation in [`./BSATN/Runtime.cs`](./BSATN/Runtime.cs) for more information. | ||
|
||
### Internal types | ||
|
||
This project contains the base implementation of serializers for various primitive BSATN types. These live in [`./BSATN/Runtime.cs`](./BSATN/Runtime.cs). These serializers are mainly used in code generated by `BSATN.Codegen`. |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,36 +1,17 @@ | ||
# SpacetimeDB.Codegen | ||
> ⚠️ **Internal Project** ⚠️ | ||
> | ||
> This project is intended for internal use only. It is **not** stable and may change without notice. | ||
|
||
This project contains Roslyn [incremental source generators](https://github.com/dotnet/roslyn/blob/main/docs/features/incremental-generators.md) that augment types and tables with static methods for self-describing and registration. They look for different attributes to know which types to augment: | ||
See the [C# module library reference](https://spacetimedb.com/docs/modules/c-sharp) for stable, user-facing documentation. | ||
|
||
- `[SpacetimeDB.Type]` - generates a `GetSatsTypeInfo()` static method that registers this type with the runtime and returns a `TypeInfo` object. It supports only `struct`s for now to explicitly forbid infinitely recursive types and to make the implementation simpler, as it doesn't need to deal with type references - each table is registered as an entirely self-contained type together with its nested structs if any. This is unlikely to be a problem in common scenarios, but it will be optimised in the future. | ||
## Internal documentation | ||
|
||
All the nested fields will be added to the product type. Because it's not possible to implement static extension methods on 3rd-party types (including built-ins) in C#, the codegen is responsible for manually routing different types to their `TypeInfo` descriptors. See various static `TypeInfo` properties and helper methods on `SpacetimeDB.BSATN.AlgebraicType` (`Runtime/AlgebraicType.cs`) and routing logic in `Utils.GetTypeInfo` (`Codegen/Utils.cs`) for more details. | ||
This project contains Roslyn [incremental source generators](https://github.com/dotnet/roslyn/blob/main/docs/features/incremental-generators.md) that augment tables and reducers with static methods for self-describing and registration. | ||
|
||
Also, for the same reason - absence of static extension methods in C# - the codegen expects that your struct, as well as any of its parents, is `partial` so methods can be added from extra source files generated by the codegen. | ||
SpacetimeDB modules are compiled to WebAssembly modules that expose a specific interface; see the [module ABI reference](https://spacetimedb.com/docs/webassembly-abi). This interface is implemented in the generated `FFI` class; see [`../Codegen.Tests/fixtures/server/snapshots/Module#FFI.verified.cs`](../Codegen.Tests/fixtures/server/snapshots/Module#FFI.verified.cs) for an example of what this generated code looks like. | ||
|
||
- `[SpacetimeDB.Type]` - also supports emulation of tagged enums in C#. For that, the struct needs to inherit a marker interface `SpacetimeDB.TaggedEnum<Variants>` where `Variants` is a named tuple of all possible variants, e.g.: | ||
|
||
```csharp | ||
[SpacetimeDB.Type] | ||
partial record Option<T> : SpacetimeDB.TaggedEnum<(T Some, Unit None)>; | ||
``` | ||
|
||
will generate inherited records `Option.Some(T Some_)` and `Option.None(Unit None_)`. It allows | ||
you to use tagged enums in C# in a similar way to Rust enums by leveraging C# pattern-matching | ||
on any instance of `Option<T>`. | ||
The source generators are implemented via several attributes usable in module code: | ||
|
||
- `[SpacetimeDB.Table]` - generates code to register this table in the `FFI` upon startup so that they can be enumerated by the `__describe_module__` FFI API. It implies `[SpacetimeDB.Type]`, so you must not specify both attributes on the same struct. | ||
|
||
The fields can be marked with `[SpacetimeDB.ColumnAttrs]` and those will be detected by the codegen and passed on to the runtime as well. Example: | ||
|
||
```csharp | ||
[SpacetimeDB.Table] | ||
public partial struct Person | ||
{ | ||
[SpacetimeDB.Column(ColumnAttrs.Identity)] | ||
public int Id; | ||
public string Name; | ||
} | ||
``` | ||
|
||
- `[SpacetimeDB.Reducer]` - generates code to register a static function as a SpacetimeDB reducer in the `FFI` upon startup and creates a wrapper that will parse SATS binary blob into individual arguments and invoke the underlying function for the `__call_reducer__` FFI API. |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,5 +1,23 @@ | ||
# SpacetimeDB | ||
> ⚠️ **Unstable Project** ⚠️ | ||
> | ||
> The interface of this project is **not** stable and may change without notice. | ||
|
||
These projects contain the SpacetimeDB SATS typesystem, codegen and runtime bindings for SpacetimeDB WebAssembly modules. | ||
See the [C# module library reference](https://spacetimedb.com/docs/modules/c-sharp) and the [C# client SDK reference](https://spacetimedb.com/docs/sdks/c-sharp) for stable, user-facing documentation. | ||
|
||
## Internal documentation | ||
|
||
These projects contain the SpacetimeDB SATS typesystem, codegen and runtime bindings for SpacetimeDB WebAssembly modules. It also contains serialization code for SpacetimeDB C# clients. | ||
|
||
See the | ||
|
||
The [`BSATN.Codegen`](./BSATN.Codegen/) and [`BSATN.Runtime`](./BSATN.Runtime/) libraries are used by: | ||
- C# Modules | ||
- and C# Client applications. | ||
|
||
Together they provide serialization and deserialization to the BSATN format. See their READMEs for more information. | ||
|
||
The [`Codegen`](./Codegen/) and [`Runtime`](./Runtime/) libraries are used: | ||
- only by C# Modules. | ||
|
||
They provide all of the functionality needed to write SpacetimeDB modules in C#. See their READMEs for more information. | ||
|
||
Please refer to documentation inside `Codegen` and `Runtime` folders for more details. |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This seems to be a fragment. Is the reader being instructed to see the following libraries? If so, this may just require a colon to be added to the end of the line.