///|
/// Stream one update through arbitrary field codecs without integrating a Doc.
/// Expansion is bounded before iterating compressed block/value counts.
fn copy_update_fields(
input : &Decoder,
output : &Encoder,
max_items : Int32,
) -> Unit raise DecodeError {
guard max_items >= 0 else { raise InvalidData("negative decode budget") }
let mut remaining = max_items
fn reserve(value : UInt64) -> Int32 raise DecodeError {
guard value <= remaining.to_uint64() else {
raise InvalidData("update exceeds decode item budget")
}
remaining -= value.to_int()
value.to_int()
}
fn count() -> Int32 raise DecodeError {
let value = Read::read_var_uint(input)
let n = reserve(value)
Write::write_var_uint(output, value)
n
}
fn raw_uint() -> UInt64 raise DecodeError {
let value = Read::read_var_uint(input)
Write::write_var_uint(output, value)
value
}
fn string() -> Unit raise DecodeError {
Write::write_string(output, Read::read_string(input))
}
fn left() -> Unit raise DecodeError {
output.write_left_id(input.read_left_id())
}
fn length() -> UInt32 raise DecodeError {
let n = input.read_len()
output.write_len(n)
n
}
for _ in 0.. ignore
for _ in 0.. ignore
continue
}
if info == 0 {
length() |> ignore
continue
}
if (info & 128) != 0 {
left()
}
if (info & 64) != 0 {
output.write_right_id(input.read_right_id())
}
if (info & 192) == 0 {
let root = input.read_parent_info()
output.write_parent_info(root)
if root {
string()
} else {
left()
}
if (info & 32) != 0 {
string()
}
}
match info & 31 {
1 => length() |> ignore
2 =>
for _ in 0.. {
let bytes = Read::read_buf(input)
// EncoderV2.write_all adds a length itself. Emit raw bytes explicitly
// to preserve the single-length content-buffer wire representation.
Write::write_var_uint(output, bytes.length().to_uint64())
for byte in bytes {
Write::write_u8(output, byte)
}
}
4 => string()
5 => output.write_json(input.read_json())
6 => {
output.write_key(input.read_key())
output.write_json(input.read_json())
}
7 => {
let kind = input.read_type_ref()
output.write_type_ref(kind)
match kind.to_int() {
3 => output.write_key(input.read_key())
7 => copy_link_fields(input, output)
0 | 1 | 2 | 4 | 5 | 6 | 9 | 15 => ()
_ => raise InvalidData("unsupported shared type reference")
}
}
8 =>
for _ in 0.. {
string()
output.write_any(input.read_any())
}
_ => raise InvalidData("invalid content reference")
}
}
}
for _ in 0.. ignore
for _ in 0.. Unit raise DecodeError {
let flags = Read::read_u8(input).to_int()
guard flags < 64 else { raise InvalidData("invalid weak link flags") }
Write::write_u8(output, flags.to_byte())
fn scope(unbounded : Bool) -> Unit raise DecodeError {
if unbounded && (flags & 32) != 0 {
Write::write_string(output, Read::read_string(input))
} else {
Write::write_var_uint(output, Read::read_var_uint(input))
Write::write_var_uint(
output,
codec_clock(Read::read_var_uint(input)).to_uint64(),
)
}
}
scope((flags & 8) != 0)
if (flags & 16) != 0 || (flags & 1) != 0 {
scope((flags & 16) != 0)
}
}
///|
pub impl Encode for Update with fn encode(self, encoder) {
// The typed v2 representation avoids a lossy JSON projection for rich text.
try! copy_update_fields(DecoderV2(self.encode_v2()), encoder, 0x7fff_ffff)
}
///|
pub impl Decode for Update with fn decode(decoder) {
let encoder = EncoderV2()
copy_update_fields(decoder, encoder, 1000000)
Update::decode_v2(encoder.to_bytes())
}
///|
pub extend Update with Encode::{encode}
///|
pub extend Update with Decode::{decode}