9.5 Пользовательские сериализаторы
Уровень 1 — представление через другой тип (Repr), действует во всех форматах и в схемах:
@repr(i64)
data Money { minor: i64 }
impl Repr<i64> for Money {
fn toRepr() -> i64 => minor
static fn fromRepr(v: i64) -> Money | DecodeError => Money{ minor: v }
}Уровень 2 — кодек на тип или поле, в том числе для отдельного формата:
@explicit interface Codec<T> {
static fn encode(x: &T, w: &var Encoder) -> () | EncodeError
static fn decode(r: &var Decoder) -> T | DecodeError
static fn schema() -> Schema // для oxl export
}
data Event {
@codec(json: Iso8601) at: Time // в JSON — строка ISO 8601, в бинарном — по умолчанию
@codec(Base64Url) token: bytes // во всех форматах
}
@codec(GeoHashCodec) data Point { lat: f64; lon: f64 }@codec(C)— для всех форматов;@codec(json: C1, oxl: C2)— по форматам.CДОЛЖЕН реализовыватьCodec<T>для типа поля.Encoder/Decoder— абстрактный интерфейс формата:writeI64,writeStr,beginMessage,field(tag, name)и т. д. (часть II,std.ser).- Изменение кодека поля — изменение типа поля по таблице 9.2: компилятор сравнивает
schema()старого и нового кодека.
Encoder и Decoder — интерфейсы std.ser; написанные как тип (w: &var Encoder, -> Decoder), означают dyn Encoder и dyn Decoder. В Encoder все методы имеют реализации по умолчанию (пустые): beginMessage(name), endMessage(), field(tag, name), writeI64, writeU64, writeF64, writeBool, writeStr, writeBytes, writeNull, beginList(len), endList(), beginMap(len), endMap() и finish() -> bytes (единственный способ вернуть накопленные байты). Decoder содержит методы чтения, парные к записи; реализации по умолчанию сообщают DecodeError.Malformed.
Уровень 3 — собственный формат. Тип, реализующий интерфейс Format (name() -> str, encoder() -> Encoder, decoder(input: bytes) -> Decoder), регистрируется comptime-вызовом std.ser.register(MyFormat) и становится доступен как encode<T>(x, MyFormat). Реализация строится на событиях Encoder/Decoder и reflect(T) (§15). Имя Format в позиции аргумента encode/decode обозначает и перечисление встроенных форматов (Format.Json), и интерфейс Format для реализаций; различаются по позиции: impl Format for T реализует интерфейс (D-8053; DIV-007; D-7620).
Определяется реализацией. Декодирование собственным форматом (D-8053; DIV-007; D-7621).
decode<T>(b, MyFormat)обходит типTи запрашивает значения уDecoderв том порядке, в которомencodeпередал бы ихEncoder(D-8344):readI64/readU64/readF64/readBool/readStr/readBytesдля скаляров,beginMessage/nextField/endMessageдля сообщений (поле находится поtag, приtag == 0— по имени),beginList/endListиbeginMap/endMapдля коллекций,readNullдляT?. Ограничения этой реализации: уDecoderнет пропуска значения, поэтому неизвестное поле сообщения — ошибка (Invalid); неизвестное число открытогоenumне читается. Кодирование и декодирование собственным форматом поддерживаются.
Связанные диагностики
См. также
Исходник: docs/spec/oxl-standard.md