Skip to main content

Serialization

FigNet does not use one global swappable serializer. Instead, each message type registers its own serialize/deserialize functions against a message ID via FN.RegisterPayload, and Message calls the function registered for that ID.

namespace FigNet.Core
{
public static class FN
{
public static void RegisterPayload<T>(ushort msgId, SerializeFunction<T> serializeFunc, DeserializeFunction<T> deserializeFunc);
public static void RegisterPayload<T>(ushort msgId, SerializeIntoFunction<T> serializeFunc, DeserializeSpanFunction<T> deserializeFunc);
public static void UnRegisterPayload(ushort msgId);
}
}

There are two families of overload:

  • SerializeFunction<T> / DeserializeFunction<T> - return an ArraySegment<byte> / read one. Simpler to write.
  • SerializeIntoFunction<T> / DeserializeSpanFunction<T> - write into a caller-provided IBufferWriter<byte> / read a ReadOnlySpan<byte>. The zero-allocation path; this is what the built-in messages use.

Registering a Payload

Built-in messages (RegisterIdentity, Ping) register MemoryPack source-generated static methods directly on the payload type:

FN.RegisterPayload((ushort)ReservedMessageId.RegisterIdentity,
RegisterIdentityModel.Serialize<RegisterIdentityModel>,
RegisterIdentityModel.Deserialize<RegisterIdentityModel>);

FN.RegisterPayload((ushort)ReservedMessageId.Ping,
PingModel.Serialize<PingModel>,
PingModel.Deserialize<PingModel>);

Application code registers its own payload types the same way, typically also backed by a [MemoryPackable] model:

[MemoryPackable]
public partial class EchoOperation
{
public string Text;
}

FN.RegisterPayload<EchoOperation>(MyMessageIds.Echo,
EchoOperation.Serialize<EchoOperation>,
EchoOperation.Deserialize<EchoOperation>);

Entangle and FnVoice payloads follow the same convention - see EntangleModels.cs for real examples of [MemoryPackable] payload types.

Sending and Receiving

Once a payload's functions are registered, Message.Create<T> looks them up by message ID - callers do not serialize manually:

var message = Message.Create(MyMessageIds.Echo, new EchoOperation { Text = "hello" });
server.SendToAll(message, channelId, deliveryMode);

On receive, HandlerCollection dispatches the deserialized payload to the handler registered for that message ID.

Unregistering

FN.UnRegisterPayload(MyMessageIds.Echo);

Used when a module unloads, so its payload IDs don't linger in the registry.