.NET Formatters & Types
Core types and CBOR serialization primitives provided by the ion.runtime package.
IonFormatter
IonFormatter is a static class providing low-level CBOR serialization for all primitives:
// Signed integers IonFormatter.WriteSByte(writer, value); // i1 IonFormatter.WriteInt16(writer, value); // i2 IonFormatter.WriteInt32(writer, value); // i4 IonFormatter.WriteInt64(writer, value); // i8 IonFormatter.WriteInt128(writer, value); // i16 // Unsigned integers IonFormatter.WriteByte(writer, value); // u1 IonFormatter.WriteUInt16(writer, value); // u2 IonFormatter.WriteUInt32(writer, value); // u4 IonFormatter.WriteUInt64(writer, value); // u8 IonFormatter.WriteUInt128(writer, value); // u16 // Floats IonFormatter.WriteHalf(writer, value); // f2 IonFormatter.WriteFloat(writer, value); // f4 IonFormatter.WriteDouble(writer, value); // f8 // Special types IonFormatter.WriteString(writer, value); IonFormatter.WriteGuid(writer, value); IonFormatter.WriteDateTime(writer, value); IonFormatter.WriteBool(writer, value);
IonMaybe<T>
A Rust-style Option monad for nullable values. Generated for T? fields:
// Implicit conversions IonMaybe<string> email = "user@example.com"; IonMaybe<string> empty = default; // Pattern matching if (email.HasValue) Console.WriteLine(email.Value); // LINQ-style operations var upper = email.Map(e => e.ToUpper()); var fallback = empty.Or("default@example.com"); // Wire format: CBOR null for None, CBOR value for Some
IonPartial<T>
Tracks field modifications for sparse (PATCH-like) updates. Only modified fields are serialized:
var patch = new IonPartial<User>(); // Set specific fields patch.Set(u => u.name, "New Name"); patch.Set(u => u.email, "new@example.com"); // Check if a field was modified bool modified = patch.IsSet(u => u.name); // true bool untouched = patch.IsSet(u => u.id); // false // On the wire: only 'name' and 'email' are serialized await userService.UpdateUser(42, patch);
IonBytes
Zero-copy byte buffer type for efficient binary data transfer:
// From byte array IonBytes data = new byte[] { 0x01, 0x02, 0x03 }; // From ReadOnlyMemory IonBytes data2 = new IonBytes(memory); // Access the underlying data ReadOnlySpan<byte> span = data.Span; // Wire format: CBOR byte string
IIonUnion<T>
Marker interface for discriminated union types. Each union case is a sealed class implementing this interface:
// Generated from: union Shape { Circle(r: f4), Rectangle(w: f4, h: f4) } public interface Shape : IIonUnion<Shape> { } // Pattern match with switch Shape shape = GetShape(); var area = shape switch { Shape.Circle c => Math.PI * c.r * c.r, Shape.Rectangle r => r.w * r.h, _ => throw new NotSupportedException() };
IonFormatterStorage<T>
Type-safe formatter registry. Generated code registers formatters here at module initialization:
// Generated in moduleInit.cs IonFormatterStorage<User>.Serialize = (writer, value) => { writer.WriteArrayHeader(3); IonFormatter.WriteUInt32(writer, value.id); IonFormatter.WriteString(writer, value.name); IonFormatter.WriteString(writer, value.email); }; IonFormatterStorage<User>.Deserialize = (reader) => { reader.ReadArrayHeader(); return new User { id = IonFormatter.ReadUInt32(reader), name = IonFormatter.ReadString(reader), email = IonFormatter.ReadString(reader) }; };