///|
/// Tuple codecs.
///
/// On the wire an n-tuple (n >= 2) is written as a version-0 record: a
/// single `0x00` version byte followed by the element payloads. This is
/// byte-compatible with both existing implementations, where tuples share
/// the record encoding and a version-0 struct is wire-identical to a tuple
/// of the same shape (so tuples can be read as structs and vice versa).
///
/// MoonBit has no 1-tuple type; wrap the value in its own type instead.
///|
pub impl[A : BinarySerializer, B : BinarySerializer] BinarySerializer for (A, B) with fn serialize(
self,
ctx,
) {
let (a, b) = self
ctx.write_u8(b'\x00')
a.serialize(ctx)
b.serialize(ctx)
}
///|
pub impl[A : BinaryDeserializer, B : BinaryDeserializer] BinaryDeserializer for (
A,
B,
) with fn deserialize(ctx) {
expect_record_version(ctx)
(A::deserialize(ctx), B::deserialize(ctx))
}
///|
pub impl[A : BinarySerializer, B : BinarySerializer, C : BinarySerializer] BinarySerializer for (
A,
B,
C,
) with fn serialize(self, ctx) {
let (a, b, c) = self
ctx.write_u8(b'\x00')
a.serialize(ctx)
b.serialize(ctx)
c.serialize(ctx)
}
///|
pub impl[A : BinaryDeserializer, B : BinaryDeserializer, C : BinaryDeserializer] BinaryDeserializer for (
A,
B,
C,
) with fn deserialize(ctx) {
expect_record_version(ctx)
(A::deserialize(ctx), B::deserialize(ctx), C::deserialize(ctx))
}
///|
pub impl[
A : BinarySerializer,
B : BinarySerializer,
C : BinarySerializer,
D : BinarySerializer,
] BinarySerializer for (A, B, C, D) with fn serialize(self, ctx) {
let (a, b, c, d) = self
ctx.write_u8(b'\x00')
a.serialize(ctx)
b.serialize(ctx)
c.serialize(ctx)
d.serialize(ctx)
}
///|
pub impl[
A : BinaryDeserializer,
B : BinaryDeserializer,
C : BinaryDeserializer,
D : BinaryDeserializer,
] BinaryDeserializer for (A, B, C, D) with fn deserialize(ctx) {
expect_record_version(ctx)
(
A::deserialize(ctx),
B::deserialize(ctx),
C::deserialize(ctx),
D::deserialize(ctx),
)
}
///|
pub impl[
A : BinarySerializer,
B : BinarySerializer,
C : BinarySerializer,
D : BinarySerializer,
E : BinarySerializer,
] BinarySerializer for (A, B, C, D, E) with fn serialize(self, ctx) {
let (a, b, c, d, e) = self
ctx.write_u8(b'\x00')
a.serialize(ctx)
b.serialize(ctx)
c.serialize(ctx)
d.serialize(ctx)
e.serialize(ctx)
}
///|
pub impl[
A : BinaryDeserializer,
B : BinaryDeserializer,
C : BinaryDeserializer,
D : BinaryDeserializer,
E : BinaryDeserializer,
] BinaryDeserializer for (A, B, C, D, E) with fn deserialize(ctx) {
expect_record_version(ctx)
(
A::deserialize(ctx),
B::deserialize(ctx),
C::deserialize(ctx),
D::deserialize(ctx),
E::deserialize(ctx),
)
}
///|
pub impl[
A : BinarySerializer,
B : BinarySerializer,
C : BinarySerializer,
D : BinarySerializer,
E : BinarySerializer,
F : BinarySerializer,
] BinarySerializer for (A, B, C, D, E, F) with fn serialize(self, ctx) {
let (a, b, c, d, e, f) = self
ctx.write_u8(b'\x00')
a.serialize(ctx)
b.serialize(ctx)
c.serialize(ctx)
d.serialize(ctx)
e.serialize(ctx)
f.serialize(ctx)
}
///|
pub impl[
A : BinaryDeserializer,
B : BinaryDeserializer,
C : BinaryDeserializer,
D : BinaryDeserializer,
E : BinaryDeserializer,
F : BinaryDeserializer,
] BinaryDeserializer for (A, B, C, D, E, F) with fn deserialize(ctx) {
expect_record_version(ctx)
(
A::deserialize(ctx),
B::deserialize(ctx),
C::deserialize(ctx),
D::deserialize(ctx),
E::deserialize(ctx),
F::deserialize(ctx),
)
}
///|
/// Record-shaped values (tuples, and later derived records) start with a
/// version byte; version 0 means "no evolution header, fields follow".
/// Non-zero versions belong to the evolution machinery and are rejected by
/// plain record readers.
fn expect_record_version(
ctx : DeserializationContext,
) -> Unit raise DesertFailure {
match ctx.input.read_u8() {
b'\x00' => ()
other =>
raise DeserializationFailure(
"Unsupported record version: \{other.to_int()} (evolution support is not enabled for this type)",
)
}
}