// `Value` as a format: a `Serializer` that builds one and a `Deserializer`
// that reads one.
//
// This is the reference implementation of both protocols. It is also the
// bridge that makes `Value` usable as an intermediate representation, the way
// `serde_json::Value` is.
///|
/// Builds a `Value` in memory.
///
/// Nested values are serialized by `capture`, which hands each one a fresh
/// serializer. That keeps at most one compound open per instance, so no
/// explicit nesting stack is needed and a misplaced `_element` or `_end` call
/// raises rather than silently corrupting the result.
pub struct ValueSerializer {
mut out : Value?
mut items : Array[Value]?
mut entries : Array[(Value, Value)]?
mut pending_key : Value?
mut variant : String?
}
///|
pub fn ValueSerializer::new() -> ValueSerializer {
{ out: None, items: None, entries: None, pending_key: None, variant: None }
}
///|
/// Serializes one value in isolation and returns it.
pub fn[T : Serialize] ValueSerializer::capture(
value : T,
) -> Value raise SerError {
let sub = ValueSerializer::new()
value.serialize(sub)
sub.finish()
}
///|
/// The completed value. Raises if nothing was serialized, or if a compound was
/// opened and never closed.
pub fn ValueSerializer::finish(self : ValueSerializer) -> Value raise SerError {
if self.items is Some(_) || self.entries is Some(_) {
raise SerCustom(message="a compound was opened but never ended")
}
match self.out {
Some(v) => v
None => raise SerCustom(message="serializer produced no value")
}
}
///|
fn ValueSerializer::emit(self : ValueSerializer, value : Value) -> Unit {
self.out = Some(value)
}
///|
fn ValueSerializer::open_seq(self : ValueSerializer, hint : Int?) -> Unit {
self.items = Some(
match hint {
Some(n) => Array::new(capacity=n)
None => []
},
)
}
///|
fn ValueSerializer::seq_items(
self : ValueSerializer,
) -> Array[Value] raise SerError {
match self.items {
Some(items) => items
None => raise SerCustom(message="element written outside an open sequence")
}
}
///|
fn ValueSerializer::close_seq(
self : ValueSerializer,
) -> Array[Value] raise SerError {
let items = self.seq_items()
self.items = None
items
}
///|
fn ValueSerializer::map_entries(
self : ValueSerializer,
) -> Array[(Value, Value)] raise SerError {
match self.entries {
Some(entries) => entries
None => raise SerCustom(message="entry written outside an open map")
}
}
///|
fn ValueSerializer::close_map(
self : ValueSerializer,
) -> Array[(Value, Value)] raise SerError {
let entries = self.map_entries()
self.entries = None
entries
}
///|
fn ValueSerializer::take_variant(
self : ValueSerializer,
) -> String raise SerError {
match self.variant {
Some(name) => {
self.variant = None
name
}
None => raise SerCustom(message="variant ended without a matching begin")
}
}
///|
pub impl Serializer for ValueSerializer with fn serialize_unit(self) {
self.emit(Null)
}
///|
pub impl Serializer for ValueSerializer with fn serialize_bool(self, v) {
self.emit(Boolean(v))
}
///|
pub impl Serializer for ValueSerializer with fn serialize_byte(self, v) {
self.emit(UInt(v.to_uint64()))
}
///|
pub impl Serializer for ValueSerializer with fn serialize_int16(self, v) {
self.emit(Int(v.to_int64()))
}
///|
pub impl Serializer for ValueSerializer with fn serialize_uint16(self, v) {
self.emit(UInt(v.to_uint64()))
}
///|
pub impl Serializer for ValueSerializer with fn serialize_int(self, v) {
self.emit(Int(v.to_int64()))
}
///|
pub impl Serializer for ValueSerializer with fn serialize_uint(self, v) {
self.emit(UInt(v.to_uint64()))
}
///|
pub impl Serializer for ValueSerializer with fn serialize_int64(self, v) {
self.emit(Int(v))
}
///|
pub impl Serializer for ValueSerializer with fn serialize_uint64(self, v) {
self.emit(UInt(v))
}
///|
pub impl Serializer for ValueSerializer with fn serialize_float(self, v) {
self.emit(Double(v.to_double()))
}
///|
pub impl Serializer for ValueSerializer with fn serialize_double(self, v) {
self.emit(Double(v))
}
///|
pub impl Serializer for ValueSerializer with fn serialize_char(self, v) {
self.emit(Str(v.to_string()))
}
///|
pub impl Serializer for ValueSerializer with fn serialize_string(self, v) {
self.emit(Str(v))
}
///|
pub impl Serializer for ValueSerializer with fn serialize_bytes(self, v) {
self.emit(Bytes(v))
}
///|
pub impl Serializer for ValueSerializer with fn serialize_none(self) {
self.emit(Null)
}
///|
pub impl Serializer for ValueSerializer with fn serialize_some(self, v) {
self.emit(ValueSerializer::capture(v))
}
///|
pub impl Serializer for ValueSerializer with fn serialize_unit_variant(
self,
info,
) {
self.emit(Str(info.name))
}
///|
pub impl Serializer for ValueSerializer with fn serialize_newtype_variant(
self,
info,
v,
) {
self.emit(Map([(Str(info.name), ValueSerializer::capture(v))]))
}
///|
pub impl Serializer for ValueSerializer with fn serialize_seq_begin(self, hint) {
self.open_seq(hint)
}
///|
pub impl Serializer for ValueSerializer with fn serialize_seq_element(self, v) {
self.seq_items().push(ValueSerializer::capture(v))
}
///|
pub impl Serializer for ValueSerializer with fn serialize_seq_end(self) {
let items = self.close_seq()
self.emit(Seq(items))
}
///|
pub impl Serializer for ValueSerializer with fn serialize_map_begin(self, _hint) {
self.entries = Some([])
self.pending_key = None
}
///|
pub impl Serializer for ValueSerializer with fn serialize_map_key(self, k) {
self.pending_key = Some(ValueSerializer::capture(k))
}
///|
pub impl Serializer for ValueSerializer with fn serialize_map_value(self, v) {
let key = match self.pending_key {
Some(k) => k
None => raise SerCustom(message="map value written without a key")
}
self.pending_key = None
self.map_entries().push((key, ValueSerializer::capture(v)))
}
///|
pub impl Serializer for ValueSerializer with fn serialize_map_end(self) {
let entries = self.close_map()
self.emit(Map(entries))
}
///|
pub impl Serializer for ValueSerializer with fn serialize_struct_begin(
self,
_name,
_len,
) {
self.entries = Some([])
}
///|
pub impl Serializer for ValueSerializer with fn serialize_field(self, name, v) {
self.map_entries().push((Str(name), ValueSerializer::capture(v)))
}
///|
pub impl Serializer for ValueSerializer with fn serialize_struct_end(self) {
let entries = self.close_map()
self.emit(Map(entries))
}
///|
pub impl Serializer for ValueSerializer with fn serialize_tuple_variant_begin(
self,
info,
len,
) {
self.variant = Some(info.name)
self.open_seq(Some(len))
}
///|
pub impl Serializer for ValueSerializer with fn serialize_tuple_variant_end(
self,
) {
let items = self.close_seq()
let name = self.take_variant()
self.emit(Map([(Str(name), Seq(items))]))
}
///|
pub impl Serializer for ValueSerializer with fn serialize_struct_variant_begin(
self,
info,
_len,
) {
self.variant = Some(info.name)
self.entries = Some([])
}
///|
pub impl Serializer for ValueSerializer with fn serialize_struct_variant_end(
self,
) {
let entries = self.close_map()
let name = self.take_variant()
self.emit(Map([(Str(name), Map(entries))]))
}
///|
/// Reads from an in-memory `Value`.
///
/// Each nested value gets a child deserializer carrying its own `Path`, so
/// failures report where in the document they happened.
pub struct ValueDeserializer {
mut value : Value
mut path : Path
mut cursor : Int
}
///|
pub fn ValueDeserializer::new(
value : Value,
path? : Path = Root,
) -> ValueDeserializer {
{ value, path, cursor: 0 }
}
///|
fn ValueDeserializer::child(
self : ValueDeserializer,
value : Value,
path : Path,
) -> ValueDeserializer {
ignore(self)
{ value, path, cursor: 0 }
}
///|
fn[T] ValueDeserializer::mismatch(
self : ValueDeserializer,
expected : String,
) -> T raise DeError {
raise InvalidType(path=self.path, expected~, found=self.value.type_name())
}
///|
fn ValueDeserializer::as_int64(self : ValueDeserializer) -> Int64 raise DeError {
match self.value {
Int(i) => i
UInt(u) => {
let signed = u.reinterpret_as_int64()
if signed < 0L {
raise InvalidValue(
path=self.path,
expected="a signed integer",
found=u.to_string(),
)
}
signed
}
_ => self.mismatch("integer")
}
}
///|
fn ValueDeserializer::int_in_range(
self : ValueDeserializer,
lo : Int64,
hi : Int64,
what : String,
) -> Int64 raise DeError {
let i = self.as_int64()
if i < lo || i > hi {
raise InvalidValue(path=self.path, expected=what, found=i.to_string())
}
i
}
///|
fn ValueDeserializer::as_double(
self : ValueDeserializer,
) -> Double raise DeError {
match self.value {
Double(d) => d
Int(i) => i.to_double()
UInt(u) => u.to_double()
_ => self.mismatch("float")
}
}
///|
fn ValueDeserializer::seq_items(
self : ValueDeserializer,
) -> Array[Value] raise DeError {
guard self.value is Seq(items) else { self.mismatch("sequence") }
items
}
///|
fn ValueDeserializer::map_entries(
self : ValueDeserializer,
) -> Array[(Value, Value)] raise DeError {
guard self.value is Map(entries) else { self.mismatch("map") }
entries
}
///|
fn known_variant(variants : Array[String], name : String) -> Bool {
variants.is_empty() || variants.contains(name)
}
///|
pub impl Deserializer for ValueDeserializer with fn path(self) {
self.path
}
///|
pub impl Deserializer for ValueDeserializer with fn deserialize_unit(self) {
guard self.value is Null else { self.mismatch("unit") }
}
///|
pub impl Deserializer for ValueDeserializer with fn deserialize_bool(self) {
guard self.value is Boolean(b) else { self.mismatch("boolean") }
b
}
///|
pub impl Deserializer for ValueDeserializer with fn deserialize_byte(self) {
self.int_in_range(0L, 255L, "a byte").to_byte()
}
///|
pub impl Deserializer for ValueDeserializer with fn deserialize_int16(self) {
Int16::from_int64(self.int_in_range(-32768L, 32767L, "an int16"))
}
///|
pub impl Deserializer for ValueDeserializer with fn deserialize_uint16(self) {
self.int_in_range(0L, 65535L, "a uint16").to_uint16()
}
///|
pub impl Deserializer for ValueDeserializer with fn deserialize_int(self) {
self.int_in_range(-2147483648L, 2147483647L, "an int").to_int()
}
///|
pub impl Deserializer for ValueDeserializer with fn deserialize_uint(self) {
self.int_in_range(0L, 4294967295L, "a uint").reinterpret_as_uint64().to_uint()
}
///|
pub impl Deserializer for ValueDeserializer with fn deserialize_int64(self) {
self.as_int64()
}
///|
pub impl Deserializer for ValueDeserializer with fn deserialize_uint64(self) {
match self.value {
UInt(u) => u
Int(i) =>
if i < 0L {
raise InvalidValue(
path=self.path,
expected="an unsigned integer",
found=i.to_string(),
)
} else {
i.reinterpret_as_uint64()
}
_ => self.mismatch("unsigned integer")
}
}
///|
pub impl Deserializer for ValueDeserializer with fn deserialize_float(self) {
Float::from_double(self.as_double())
}
///|
pub impl Deserializer for ValueDeserializer with fn deserialize_double(self) {
self.as_double()
}
///|
pub impl Deserializer for ValueDeserializer with fn deserialize_char(self) {
guard self.value is Str(s) else { self.mismatch("char") }
let mut first : Char? = None
let mut count = 0
for c in s {
if count == 0 {
first = Some(c)
}
count = count + 1
}
match first {
Some(c) if count == 1 => c
_ =>
raise InvalidValue(path=self.path, expected="a single character", found=s)
}
}
///|
pub impl Deserializer for ValueDeserializer with fn deserialize_string(self) {
guard self.value is Str(s) else { self.mismatch("string") }
s
}
///|
pub impl Deserializer for ValueDeserializer with fn deserialize_bytes(self) {
guard self.value is Bytes(b) else { self.mismatch("byte string") }
b
}
///|
pub impl Deserializer for ValueDeserializer with fn deserialize_option(self) {
if self.value is Null {
None
} else {
Some(Deserialize::deserialize(self))
}
}
///|
pub impl Deserializer for ValueDeserializer with fn deserialize_seq_begin(self) {
let items = self.seq_items()
self.cursor = 0
Some(items.length())
}
///|
pub impl Deserializer for ValueDeserializer with fn deserialize_seq_next(self) {
let items = self.seq_items()
if self.cursor >= items.length() {
return None
}
let i = self.cursor
self.cursor = i + 1
Some(Deserialize::deserialize(self.child(items[i], self.path.index(i))))
}
///|
pub impl Deserializer for ValueDeserializer with fn deserialize_map_begin(self) {
let entries = self.map_entries()
self.cursor = 0
Some(entries.length())
}
///|
pub impl Deserializer for ValueDeserializer with fn deserialize_map_next_key(
self,
) {
let entries = self.map_entries()
if self.cursor >= entries.length() {
return None
}
let entry = entries[self.cursor]
Some(Deserialize::deserialize(self.child(entry.0, self.path)))
}
///|
pub impl Deserializer for ValueDeserializer with fn deserialize_map_value(self) {
let entries = self.map_entries()
if self.cursor >= entries.length() {
raise Eof(path=self.path)
}
let entry = entries[self.cursor]
self.cursor = self.cursor + 1
Deserialize::deserialize(self.child(entry.1, self.path))
}
///|
pub impl Deserializer for ValueDeserializer with fn deserialize_struct_begin(
self,
_name,
_fields,
) {
let _ = self.map_entries()
self.cursor = 0
}
///|
pub impl Deserializer for ValueDeserializer with fn deserialize_field_name(self) {
let entries = self.map_entries()
if self.cursor >= entries.length() {
return None
}
guard entries[self.cursor].0 is Str(name) else {
raise InvalidType(
path=self.path,
expected="a string field name",
found=entries[self.cursor].0.type_name(),
)
}
Some(name)
}
///|
pub impl Deserializer for ValueDeserializer with fn deserialize_field_value(
self,
) {
let entries = self.map_entries()
if self.cursor >= entries.length() {
raise Eof(path=self.path)
}
let entry = entries[self.cursor]
self.cursor = self.cursor + 1
let name = match entry.0 {
Str(n) => n
other => other.to_string()
}
Deserialize::deserialize(self.child(entry.1, self.path.key(name)))
}
///|
pub impl Deserializer for ValueDeserializer with fn skip_value(self) {
self.cursor = self.cursor + 1
}
///|
pub impl Deserializer for ValueDeserializer with fn deserialize_enum_begin(
self,
_name,
variants,
) {
match self.value {
// A unit variant is just its name.
Str(variant) => {
guard known_variant(variants, variant) else {
raise UnknownVariant(path=self.path, variant~, expected=variants)
}
self.value = Null
variant
}
// Anything with a payload is externally tagged: { variant: payload }.
Map([(Str(variant), payload)]) => {
guard known_variant(variants, variant) else {
raise UnknownVariant(path=self.path, variant~, expected=variants)
}
self.path = self.path.key(variant)
self.value = payload
self.cursor = 0
variant
}
_ => self.mismatch("enum")
}
}
///|
pub impl Deserializer for ValueDeserializer with fn deserialize_unit_variant(
self,
) {
ignore(self)
}
///|
pub impl Deserializer for ValueDeserializer with fn deserialize_newtype_variant(
self,
) {
Deserialize::deserialize(self)
}
///|
pub impl Deserializer for ValueDeserializer with fn deserialize_any(self) {
self.value
}