From 846b164f8014f729d48fa352cc5334defe5d1970 Mon Sep 17 00:00:00 2001 From: Ben Jackson Date: Tue, 25 Nov 2025 00:08:06 +0000 Subject: [PATCH 01/29] Initial partial JSON encoder implementation We simply write synchronously to a std::io::Write. The codec supports all types that the C++ codec supports, along with the flatten, hex and base64 annotations. It does not support discriminated unions yet. It supports only encode, no decode. It's not fast, efficient, or especially good. --- capnp/json.capnp | 127 ++++ capnp/src/json.rs | 359 +++++++++ capnp/src/json_capnp.rs | 1521 +++++++++++++++++++++++++++++++++++++++ capnp/src/lib.rs | 3 + capnpc/Cargo.toml | 1 - capnpc/test/build.rs | 1 + capnpc/test/json.rs | 243 +++++++ capnpc/test/test.capnp | 83 +++ capnpc/test/test.rs | 3 + 9 files changed, 2340 insertions(+), 1 deletion(-) create mode 100644 capnp/json.capnp create mode 100644 capnp/src/json.rs create mode 100644 capnp/src/json_capnp.rs create mode 100644 capnpc/test/json.rs diff --git a/capnp/json.capnp b/capnp/json.capnp new file mode 100644 index 000000000..e5d1870c0 --- /dev/null +++ b/capnp/json.capnp @@ -0,0 +1,127 @@ +# Copyright (c) 2015 Sandstorm Development Group, Inc. and contributors +# Licensed under the MIT License: +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in +# all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +# THE SOFTWARE. + +@0x8ef99297a43a5e34; + +$import "/capnp/c++.capnp".namespace("capnp::json"); + +struct Value { + union { + null @0 :Void; + boolean @1 :Bool; + number @2 :Float64; + string @3 :Text; + array @4 :List(Value); + object @5 :List(Field); + # Standard JSON values. + + call @6 :Call; + # Non-standard: A "function call", applying a named function (named by a single identifier) + # to a parameter list. Examples: + # + # BinData(0, "Zm9vCg==") + # ISODate("2015-04-15T08:44:50.218Z") + # + # Mongo DB users will recognize the above as exactly the syntax Mongo uses to represent BSON + # "binary" and "date" types in text, since JSON has no analog of these. This is basically the + # reason this extension exists. We do NOT recommend using `call` unless you specifically need + # to be compatible with some silly format that uses this syntax. + + raw @7 :Text; + # Used to indicate that the text should be written directly to the output without + # modifications. Use this if you have an already serialized JSON value and don't want + # to feel the cost of deserializing the value just to serialize it again. + # + # The parser will never produce a `raw` value -- this is only useful for serialization. + # + # WARNING: You MUST ensure that the value is valid stand-alone JSOn. It will not be verified. + # Invalid JSON could mjake the whole message unparsable. Worse, a malicious raw value could + # perform JSON injection attacks. Make sure that the value was produced by a trustworthy JSON + # encoder. + } + + struct Field { + name @0 :Text; + value @1 :Value; + } + + struct Call { + function @0 :Text; + params @1 :List(Value); + } +} + +# ======================================================================================== +# Annotations to control parsing. Typical usage: +# +# using Json = import "/capnp/compat/json.capnp"; +# +# And then later on: +# +# myField @0 :Text $Json.name("my_field"); + +annotation name @0xfa5b1fd61c2e7c3d (field, enumerant, method, group, union) :Text; +# Define an alternative name to use when encoding the given item in JSON. This can be used, for +# example, to use snake_case names where needed, even though Cap'n Proto uses strictly camelCase. +# +# (However, because JSON is derived from JavaScript, you *should* use camelCase names when +# defining JSON-based APIs. But, when supporting a pre-existing API you may not have a choice.) + +annotation flatten @0x82d3e852af0336bf (field, group, union) :FlattenOptions; +# Specifies that an aggregate field should be flattened into its parent. +# +# In order to flatten a member of a union, the union (or, for an anonymous union, the parent +# struct type) must have the $jsonDiscriminator annotation. +# +# TODO(someday): Maybe support "flattening" a List(Value.Field) as a way to support unknown JSON +# fields? + +struct FlattenOptions { + prefix @0 :Text = ""; + # Optional: Adds the given prefix to flattened field names. +} + +annotation discriminator @0xcfa794e8d19a0162 (struct, union) :DiscriminatorOptions; +# Specifies that a union's variant will be decided not by which fields are present, but instead +# by a special discriminator field. The value of the discriminator field is a string naming which +# variant is active. This allows the members of the union to have the $jsonFlatten annotation, or +# to all have the same name. + +struct DiscriminatorOptions { + name @0 :Text; + # The name of the discriminator field. Defaults to matching the name of the union. + + valueName @1 :Text; + # If non-null, specifies that the union's value shall have the given field name, rather than the + # value's name. In this case the union's variant can only be determined by looking at the + # discriminant field, not by inspecting which value field is present. + # + # It is an error to use `valueName` while also declaring some variants as $flatten. +} + +annotation base64 @0xd7d879450a253e4b (field) :Void; +# Place on a field of type `Data` to indicate that its JSON representation is a Base64 string. + +annotation hex @0xf061e22f0ae5c7b5 (field) :Void; +# Place on a field of type `Data` to indicate that its JSON representation is a hex string. + +annotation notification @0xa0a054dea32fd98c (method) :Void; +# Indicates that this method is a JSON-RPC "notification", meaning it expects no response. diff --git a/capnp/src/json.rs b/capnp/src/json.rs new file mode 100644 index 000000000..6764af3c6 --- /dev/null +++ b/capnp/src/json.rs @@ -0,0 +1,359 @@ +// TODO: Turn these write_* into an encoding trait that can be implemented for +// different Reader types, in particular for particualr Reader types? +// In particular, encoding Data as an array of bytes is compatible with upstream +// encoder, but still dumb as bricks, probably. +// +// e.g. +// impl ToJson for crate::dynamic_value::Reader<'_> { ... } +// impl ToJson for mycrate::my_capnp::my_struct::Reader<'_> { ... } // more specific +// +// does that work in rust without specdialization? +// + +// TODO: Support for discriminators + +pub fn to_json(reader: crate::dynamic_value::Reader<'_>) -> crate::Result { + let mut writer = std::io::Cursor::new(Vec::with_capacity(4096)); + serialize_json_to(&mut writer, reader)?; + String::from_utf8(writer.into_inner()).map_err(|e| e.into()) +} + +pub fn serialize_json_to( + writer: &mut W, + reader: crate::dynamic_value::Reader<'_>, +) -> crate::Result<()> +where + W: std::io::Write, +{ + let meta = EncodingOptions { + name: "", + flatten: None, + discriminator: None, + data_encoding: DataEncoding::Default, + }; + serialize_value_to(writer, reader, &meta) +} + +use crate::json_capnp; + +#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)] +enum DataEncoding { + #[default] + Default, + Base64, + Hex, +} + +#[derive(Debug)] +struct EncodingOptions<'schema> { + name: &'schema str, + flatten: Option>, + discriminator: Option>, + data_encoding: DataEncoding, +} + +impl<'schema> EncodingOptions<'schema> { + fn from_field(field: &crate::schema::Field) -> crate::Result { + let field_name = match field + .get_annotations()? + .iter() + .find(|a| a.get_id() == json_capnp::name::ID) + { + Some(name_annotation) => name_annotation + .get_value()? + .downcast::() + .to_str()?, + None => field.get_proto().get_name()?.to_str()?, + }; + let data_encoding = match field + .get_annotations()? + .iter() + .find(|a| a.get_id() == json_capnp::base64::ID) + { + Some(_) => DataEncoding::Base64, + None => match field + .get_annotations()? + .iter() + .find(|a| a.get_id() == json_capnp::hex::ID) + { + Some(_) => DataEncoding::Hex, + None => DataEncoding::Default, + }, + }; + if data_encoding != DataEncoding::Default { + let element_type = if let crate::introspect::TypeVariant::List(element_type) = + field.get_type().which() + { + element_type.which() + } else { + field.get_type().which() + }; + if !matches!(element_type, crate::introspect::TypeVariant::Data) { + return Err(crate::Error::failed( + "base64/hex annotation can only be applied to Data fields".into(), + )); + } + } + let flatten_options = match field + .get_annotations()? + .iter() + .find(|a| a.get_id() == json_capnp::flatten::ID) + { + Some(annotation) => Some( + annotation + .get_value()? + .downcast_struct::(), + ), + None => None, + }; + let discriminator_options = match field + .get_annotations()? + .iter() + .find(|a| a.get_id() == json_capnp::discriminator::ID) + { + Some(annotation) => Some( + annotation + .get_value()? + .downcast_struct::(), + ), + None => None, + }; + Ok(Self { + name: field_name, + flatten: flatten_options, + discriminator: discriminator_options, + data_encoding, + }) + } +} + +fn serialize_value_to( + writer: &mut W, + reader: crate::dynamic_value::Reader<'_>, + meta: &EncodingOptions<'_>, +) -> crate::Result<()> +where + W: std::io::Write, +{ + match reader { + crate::dynamic_value::Reader::Void => write!(writer, "null").map_err(|e| e.into()), + crate::dynamic_value::Reader::Bool(value) => if value { + write!(writer, "true") + } else { + write!(writer, "false") + } + .map_err(|e| e.into()), + crate::dynamic_value::Reader::Int8(value) => write_signed_number(writer, value as i64), + crate::dynamic_value::Reader::Int16(value) => write_signed_number(writer, value as i64), + crate::dynamic_value::Reader::Int32(value) => write_signed_number(writer, value as i64), + crate::dynamic_value::Reader::Int64(value) => write_signed_number(writer, value), + crate::dynamic_value::Reader::UInt8(value) => write_unsigned_number(writer, value as u64), + crate::dynamic_value::Reader::UInt16(value) => write_unsigned_number(writer, value as u64), + crate::dynamic_value::Reader::UInt32(value) => write_unsigned_number(writer, value as u64), + crate::dynamic_value::Reader::UInt64(value) => write_unsigned_number(writer, value), + crate::dynamic_value::Reader::Float32(value) => write_float_number(writer, value as f64), + crate::dynamic_value::Reader::Float64(value) => write_float_number(writer, value), + crate::dynamic_value::Reader::Enum(value) => { + if let Some(enumerant) = value.get_enumerant()? { + write_string(writer, enumerant.get_proto().get_name()?.to_str()?) + } else { + write_unsigned_number(writer, value.get_value() as u64) + } + } + crate::dynamic_value::Reader::Text(reader) => write_string(writer, reader.to_str()?), + crate::dynamic_value::Reader::Data(data) => write_data(writer, data, meta.data_encoding), + crate::dynamic_value::Reader::Struct(reader) => write_object(writer, reader, meta), + crate::dynamic_value::Reader::List(reader) => write_array(writer, reader.iter(), meta), + crate::dynamic_value::Reader::AnyPointer(_) => Err(crate::Error::unimplemented( + "AnyPointer cannot be represented in JSON".into(), + )), + crate::dynamic_value::Reader::Capability(_) => Err(crate::Error::unimplemented( + "Capability cannot be represented in JSON".into(), + )), + } +} + +// TODO: use crate::io::Write ? +fn write_unsigned_number(writer: &mut W, value: u64) -> crate::Result<()> { + write!(writer, "{}", value)?; + Ok(()) +} +fn write_signed_number(writer: &mut W, value: i64) -> crate::Result<()> { + write!(writer, "{}", value)?; + Ok(()) +} + +fn write_float_number(writer: &mut W, value: f64) -> crate::Result<()> { + if value.is_finite() { + write!(writer, "{}", value)?; + } else if value.is_nan() { + write_string(writer, "NaN")?; + } else if value.is_infinite() { + if value.is_sign_positive() { + write_string(writer, "Infinity")?; + } else { + write_string(writer, "-Infinity")?; + } + } + Ok(()) +} + +fn write_string(writer: &mut W, value: &str) -> crate::Result<()> { + write!(writer, "\"")?; + for c in value.chars() { + match c { + '\"' => write!(writer, "\\\"")?, + '\\' => write!(writer, "\\\\")?, + '\n' => write!(writer, "\\n")?, + '\r' => write!(writer, "\\r")?, + '\t' => write!(writer, "\\t")?, + '\u{08}' => write!(writer, "\\b")?, + '\u{0C}' => write!(writer, "\\f")?, + c if c.is_control() => write!(writer, "\\u{:04x}", c as u32)?, + c => write!(writer, "{}", c)?, + } + } + write!(writer, "\"")?; + Ok(()) +} + +fn write_array<'reader, W: std::io::Write, I>( + writer: &mut W, + items: I, + meta: &EncodingOptions, +) -> crate::Result<()> +where + I: Iterator>>, +{ + write!(writer, "[")?; + let mut first = true; + for item in items { + if !first { + write!(writer, ",")?; + } + first = false; + serialize_value_to(writer, item?, meta)?; + } + write!(writer, "]")?; + Ok(()) +} + +fn write_object<'reader, W: std::io::Write>( + writer: &mut W, + reader: crate::dynamic_struct::Reader<'reader>, + meta: &EncodingOptions<'_>, +) -> crate::Result<()> { + let (flatten, field_prefix) = if let Some(flatten_options) = &meta.flatten { + (true, flatten_options.get_prefix()?.to_str()?) + } else { + (false, "") + }; + + if !flatten { + write!(writer, "{{")?; + } + let mut first = true; + for field in reader.get_schema().get_fields()? { + if !reader.has(field)? { + continue; + } + if field.get_proto().get_discriminant_value() != crate::schema_capnp::field::NO_DISCRIMINANT + { + if let Some(active_union_member) = reader.which()? { + if field.get_proto().get_discriminant_value() + != active_union_member.get_proto().get_discriminant_value() + { + // Skip union members that are not set. + continue; + } + // TODO: there's a specific annotation 'discriminator' which says to + // write out the discriminant field name as a field in the object, + // allowing to use flatten on the union member (only for named union + // fields). + } + } + let meta = EncodingOptions::from_field(&field)?; + if !first { + write!(writer, ",")?; + } + first = false; + if meta.flatten.is_none() { + write_string(writer, format!("{}{}", field_prefix, meta.name).as_str())?; + write!(writer, ":")?; + } + let field_value = reader.get(field)?; + serialize_value_to(writer, field_value, &meta)?; + } + if !flatten { + write!(writer, "}}")?; + } + Ok(()) +} + +fn write_data( + writer: &mut W, + data: crate::data::Reader<'_>, + encoding: DataEncoding, +) -> crate::Result<()> { + match encoding { + DataEncoding::Default => { + write!(writer, "[")?; + let mut first = true; + for byte in data.iter() { + if !first { + write!(writer, ",")?; + } + first = false; + write!(writer, "{}", byte)?; + } + write!(writer, "]")?; + Ok(()) + } + DataEncoding::Base64 => write_string(writer, encode_base64(data).as_str()), + DataEncoding::Hex => write_string(writer, encode_hex(data).as_str()), + } +} + +fn encode_base64(data: &[u8]) -> String { + // We don't want to pull in base64 crate just for this. So hand-rolling a + // base64 encoder. + const BASE64_CHARS: &[u8; 64] = + b"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; + let mut encoded = String::with_capacity(data.len().div_ceil(3) * 4); + for chunk in data.chunks(3) { + #[allow(clippy::get_first)] + let b0 = chunk.get(0).copied().unwrap_or(0); + let b1 = chunk.get(1).copied().unwrap_or(0); + let b2 = chunk.get(2).copied().unwrap_or(0); + let n = ((b0 as u32) << 16) | ((b1 as u32) << 8) | (b2 as u32); + let c0 = BASE64_CHARS[((n >> 18) & 0x3F) as usize]; + let c1 = BASE64_CHARS[((n >> 12) & 0x3F) as usize]; + let c2 = if chunk.len() > 1 { + BASE64_CHARS[((n >> 6) & 0x3F) as usize] + } else { + b'=' + }; + let c3 = if chunk.len() > 2 { + BASE64_CHARS[(n & 0x3F) as usize] + } else { + b'=' + }; + encoded.push(c0 as char); + encoded.push(c1 as char); + encoded.push(c2 as char); + encoded.push(c3 as char); + } + encoded +} + +fn encode_hex(data: &[u8]) -> String { + const HEX_CHARS: &[u8; 16] = b"0123456789abcdef"; + let mut encoded = String::with_capacity(data.len() * 2); + for &byte in data { + let high = HEX_CHARS[(byte >> 4) as usize]; + let low = HEX_CHARS[(byte & 0x0F) as usize]; + encoded.push(high as char); + encoded.push(low as char); + } + encoded +} diff --git a/capnp/src/json_capnp.rs b/capnp/src/json_capnp.rs new file mode 100644 index 000000000..4edcd7673 --- /dev/null +++ b/capnp/src/json_capnp.rs @@ -0,0 +1,1521 @@ +// @generated by the capnpc-rust plugin to the Cap'n Proto schema compiler. +// DO NOT EDIT. +// source: json.capnp + + +pub mod value { + pub use self::Which::{Null,Boolean,Number,String,Array,Object,Call,Raw}; + + #[derive(Copy, Clone)] + pub struct Owned(()); + impl crate::introspect::Introspect for Owned { fn introspect() -> crate::introspect::Type { crate::introspect::TypeVariant::Struct(crate::introspect::RawBrandedStructSchema { generic: &_private::RAW_SCHEMA, field_types: _private::get_field_types, annotation_types: _private::get_annotation_types }).into() } } + impl crate::traits::Owned for Owned { type Reader<'a> = Reader<'a>; type Builder<'a> = Builder<'a>; } + impl crate::traits::OwnedStruct for Owned { type Reader<'a> = Reader<'a>; type Builder<'a> = Builder<'a>; } + impl crate::traits::Pipelined for Owned { type Pipeline = Pipeline; } + + pub struct Reader<'a> { reader: crate::private::layout::StructReader<'a> } + impl <> ::core::marker::Copy for Reader<'_,> {} + impl <> ::core::clone::Clone for Reader<'_,> { + fn clone(&self) -> Self { *self } + } + + impl <> crate::traits::HasTypeId for Reader<'_,> { + const TYPE_ID: u64 = _private::TYPE_ID; + } + impl <'a,> ::core::convert::From> for Reader<'a,> { + fn from(reader: crate::private::layout::StructReader<'a>) -> Self { + Self { reader, } + } + } + + impl <'a,> ::core::convert::From> for crate::dynamic_value::Reader<'a> { + fn from(reader: Reader<'a,>) -> Self { + Self::Struct(crate::dynamic_struct::Reader::new(reader.reader, crate::schema::StructSchema::new(crate::introspect::RawBrandedStructSchema { generic: &_private::RAW_SCHEMA, field_types: _private::get_field_types::<>, annotation_types: _private::get_annotation_types::<>}))) + } + } + + impl <> ::core::fmt::Debug for Reader<'_,> { + fn fmt(&self, f: &mut ::core::fmt::Formatter<'_>) -> ::core::result::Result<(), ::core::fmt::Error> { + core::fmt::Debug::fmt(&::core::convert::Into::>::into(*self), f) + } + } + + impl <'a,> crate::traits::FromPointerReader<'a> for Reader<'a,> { + fn get_from_pointer(reader: &crate::private::layout::PointerReader<'a>, default: ::core::option::Option<&'a [crate::Word]>) -> crate::Result { + ::core::result::Result::Ok(reader.get_struct(default)?.into()) + } + } + + impl <'a,> crate::traits::IntoInternalStructReader<'a> for Reader<'a,> { + fn into_internal_struct_reader(self) -> crate::private::layout::StructReader<'a> { + self.reader + } + } + + impl <'a,> crate::traits::Imbue<'a> for Reader<'a,> { + fn imbue(&mut self, cap_table: &'a crate::private::layout::CapTable) { + self.reader.imbue(crate::private::layout::CapTableReader::Plain(cap_table)) + } + } + + impl <'a,> Reader<'a,> { + pub fn reborrow(&self) -> Reader<'_,> { + Self { .. *self } + } + + pub fn total_size(&self) -> crate::Result { + self.reader.total_size() + } + #[inline] + pub fn has_string(&self) -> bool { + if self.reader.get_data_field::(0) != 3 { return false; } + !self.reader.get_pointer_field(0).is_null() + } + #[inline] + pub fn has_array(&self) -> bool { + if self.reader.get_data_field::(0) != 4 { return false; } + !self.reader.get_pointer_field(0).is_null() + } + #[inline] + pub fn has_object(&self) -> bool { + if self.reader.get_data_field::(0) != 5 { return false; } + !self.reader.get_pointer_field(0).is_null() + } + #[inline] + pub fn has_call(&self) -> bool { + if self.reader.get_data_field::(0) != 6 { return false; } + !self.reader.get_pointer_field(0).is_null() + } + #[inline] + pub fn has_raw(&self) -> bool { + if self.reader.get_data_field::(0) != 7 { return false; } + !self.reader.get_pointer_field(0).is_null() + } + #[inline] + pub fn which(self) -> ::core::result::Result, crate::NotInSchema> { + match self.reader.get_data_field::(0) { + 0 => { + ::core::result::Result::Ok(Null( + () + )) + } + 1 => { + ::core::result::Result::Ok(Boolean( + self.reader.get_bool_field(16) + )) + } + 2 => { + ::core::result::Result::Ok(Number( + self.reader.get_data_field::(1) + )) + } + 3 => { + ::core::result::Result::Ok(String( + crate::traits::FromPointerReader::get_from_pointer(&self.reader.get_pointer_field(0), ::core::option::Option::None) + )) + } + 4 => { + ::core::result::Result::Ok(Array( + crate::traits::FromPointerReader::get_from_pointer(&self.reader.get_pointer_field(0), ::core::option::Option::None) + )) + } + 5 => { + ::core::result::Result::Ok(Object( + crate::traits::FromPointerReader::get_from_pointer(&self.reader.get_pointer_field(0), ::core::option::Option::None) + )) + } + 6 => { + ::core::result::Result::Ok(Call( + crate::traits::FromPointerReader::get_from_pointer(&self.reader.get_pointer_field(0), ::core::option::Option::None) + )) + } + 7 => { + ::core::result::Result::Ok(Raw( + crate::traits::FromPointerReader::get_from_pointer(&self.reader.get_pointer_field(0), ::core::option::Option::None) + )) + } + x => ::core::result::Result::Err(crate::NotInSchema(x)) + } + } + } + + pub struct Builder<'a> { builder: crate::private::layout::StructBuilder<'a> } + impl <> crate::traits::HasStructSize for Builder<'_,> { + const STRUCT_SIZE: crate::private::layout::StructSize = crate::private::layout::StructSize { data: 2, pointers: 1 }; + } + impl <> crate::traits::HasTypeId for Builder<'_,> { + const TYPE_ID: u64 = _private::TYPE_ID; + } + impl <'a,> ::core::convert::From> for Builder<'a,> { + fn from(builder: crate::private::layout::StructBuilder<'a>) -> Self { + Self { builder, } + } + } + + impl <'a,> ::core::convert::From> for crate::dynamic_value::Builder<'a> { + fn from(builder: Builder<'a,>) -> Self { + Self::Struct(crate::dynamic_struct::Builder::new(builder.builder, crate::schema::StructSchema::new(crate::introspect::RawBrandedStructSchema { generic: &_private::RAW_SCHEMA, field_types: _private::get_field_types::<>, annotation_types: _private::get_annotation_types::<>}))) + } + } + + impl <'a,> crate::traits::ImbueMut<'a> for Builder<'a,> { + fn imbue_mut(&mut self, cap_table: &'a mut crate::private::layout::CapTable) { + self.builder.imbue(crate::private::layout::CapTableBuilder::Plain(cap_table)) + } + } + + impl <'a,> crate::traits::FromPointerBuilder<'a> for Builder<'a,> { + fn init_pointer(builder: crate::private::layout::PointerBuilder<'a>, _size: u32) -> Self { + builder.init_struct(::STRUCT_SIZE).into() + } + fn get_from_pointer(builder: crate::private::layout::PointerBuilder<'a>, default: ::core::option::Option<&'a [crate::Word]>) -> crate::Result { + ::core::result::Result::Ok(builder.get_struct(::STRUCT_SIZE, default)?.into()) + } + } + + impl <> crate::traits::SetterInput> for Reader<'_,> { + fn set_pointer_builder(mut pointer: crate::private::layout::PointerBuilder<'_>, value: Self, canonicalize: bool) -> crate::Result<()> { pointer.set_struct(&value.reader, canonicalize) } + } + + impl <'a,> Builder<'a,> { + pub fn into_reader(self) -> Reader<'a,> { + self.builder.into_reader().into() + } + pub fn reborrow(&mut self) -> Builder<'_,> { + Builder { builder: self.builder.reborrow() } + } + pub fn reborrow_as_reader(&self) -> Reader<'_,> { + self.builder.as_reader().into() + } + + pub fn total_size(&self) -> crate::Result { + self.builder.as_reader().total_size() + } + #[inline] + pub fn set_null(&mut self, _value: ()) { + self.builder.set_data_field::(0, 0); + } + #[inline] + pub fn set_boolean(&mut self, value: bool) { + self.builder.set_data_field::(0, 1); + self.builder.set_bool_field(16, value); + } + #[inline] + pub fn set_number(&mut self, value: f64) { + self.builder.set_data_field::(0, 2); + self.builder.set_data_field::(1, value); + } + #[inline] + pub fn set_string(&mut self, value: impl crate::traits::SetterInput) { + self.builder.set_data_field::(0, 3); + crate::traits::SetterInput::set_pointer_builder(self.builder.reborrow().get_pointer_field(0), value, false).unwrap() + } + #[inline] + pub fn init_string(self, size: u32) -> crate::text::Builder<'a> { + self.builder.set_data_field::(0, 3); + self.builder.get_pointer_field(0).init_text(size) + } + #[inline] + pub fn has_string(&self) -> bool { + if self.builder.get_data_field::(0) != 3 { return false; } + !self.builder.is_pointer_field_null(0) + } + #[inline] + pub fn set_array(&mut self, value: crate::struct_list::Reader<'_,crate::json_capnp::value::Owned>) -> crate::Result<()> { + self.builder.set_data_field::(0, 4); + crate::traits::SetterInput::set_pointer_builder(self.builder.reborrow().get_pointer_field(0), value, false) + } + #[inline] + pub fn init_array(self, size: u32) -> crate::struct_list::Builder<'a,crate::json_capnp::value::Owned> { + self.builder.set_data_field::(0, 4); + crate::traits::FromPointerBuilder::init_pointer(self.builder.get_pointer_field(0), size) + } + #[inline] + pub fn has_array(&self) -> bool { + if self.builder.get_data_field::(0) != 4 { return false; } + !self.builder.is_pointer_field_null(0) + } + #[inline] + pub fn set_object(&mut self, value: crate::struct_list::Reader<'_,crate::json_capnp::value::field::Owned>) -> crate::Result<()> { + self.builder.set_data_field::(0, 5); + crate::traits::SetterInput::set_pointer_builder(self.builder.reborrow().get_pointer_field(0), value, false) + } + #[inline] + pub fn init_object(self, size: u32) -> crate::struct_list::Builder<'a,crate::json_capnp::value::field::Owned> { + self.builder.set_data_field::(0, 5); + crate::traits::FromPointerBuilder::init_pointer(self.builder.get_pointer_field(0), size) + } + #[inline] + pub fn has_object(&self) -> bool { + if self.builder.get_data_field::(0) != 5 { return false; } + !self.builder.is_pointer_field_null(0) + } + #[inline] + pub fn set_call(&mut self, value: crate::json_capnp::value::call::Reader<'_>) -> crate::Result<()> { + self.builder.set_data_field::(0, 6); + crate::traits::SetterInput::set_pointer_builder(self.builder.reborrow().get_pointer_field(0), value, false) + } + #[inline] + pub fn init_call(self, ) -> crate::json_capnp::value::call::Builder<'a> { + self.builder.set_data_field::(0, 6); + crate::traits::FromPointerBuilder::init_pointer(self.builder.get_pointer_field(0), 0) + } + #[inline] + pub fn has_call(&self) -> bool { + if self.builder.get_data_field::(0) != 6 { return false; } + !self.builder.is_pointer_field_null(0) + } + #[inline] + pub fn set_raw(&mut self, value: impl crate::traits::SetterInput) { + self.builder.set_data_field::(0, 7); + crate::traits::SetterInput::set_pointer_builder(self.builder.reborrow().get_pointer_field(0), value, false).unwrap() + } + #[inline] + pub fn init_raw(self, size: u32) -> crate::text::Builder<'a> { + self.builder.set_data_field::(0, 7); + self.builder.get_pointer_field(0).init_text(size) + } + #[inline] + pub fn has_raw(&self) -> bool { + if self.builder.get_data_field::(0) != 7 { return false; } + !self.builder.is_pointer_field_null(0) + } + #[inline] + pub fn which(self) -> ::core::result::Result, crate::NotInSchema> { + match self.builder.get_data_field::(0) { + 0 => { + ::core::result::Result::Ok(Null( + () + )) + } + 1 => { + ::core::result::Result::Ok(Boolean( + self.builder.get_bool_field(16) + )) + } + 2 => { + ::core::result::Result::Ok(Number( + self.builder.get_data_field::(1) + )) + } + 3 => { + ::core::result::Result::Ok(String( + crate::traits::FromPointerBuilder::get_from_pointer(self.builder.get_pointer_field(0), ::core::option::Option::None) + )) + } + 4 => { + ::core::result::Result::Ok(Array( + crate::traits::FromPointerBuilder::get_from_pointer(self.builder.get_pointer_field(0), ::core::option::Option::None) + )) + } + 5 => { + ::core::result::Result::Ok(Object( + crate::traits::FromPointerBuilder::get_from_pointer(self.builder.get_pointer_field(0), ::core::option::Option::None) + )) + } + 6 => { + ::core::result::Result::Ok(Call( + crate::traits::FromPointerBuilder::get_from_pointer(self.builder.get_pointer_field(0), ::core::option::Option::None) + )) + } + 7 => { + ::core::result::Result::Ok(Raw( + crate::traits::FromPointerBuilder::get_from_pointer(self.builder.get_pointer_field(0), ::core::option::Option::None) + )) + } + x => ::core::result::Result::Err(crate::NotInSchema(x)) + } + } + } + + pub struct Pipeline { _typeless: crate::any_pointer::Pipeline } + impl crate::capability::FromTypelessPipeline for Pipeline { + fn new(typeless: crate::any_pointer::Pipeline) -> Self { + Self { _typeless: typeless, } + } + } + impl Pipeline { + } + mod _private { + pub static ENCODED_NODE: [crate::Word; 152] = [ + crate::word(0, 0, 0, 0, 6, 0, 6, 0), + crate::word(131, 221, 25, 249, 69, 120, 250, 163), + crate::word(11, 0, 0, 0, 1, 0, 2, 0), + crate::word(52, 94, 58, 164, 151, 146, 249, 142), + crate::word(1, 0, 7, 0, 0, 0, 8, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(216, 4, 0, 0, 47, 11, 0, 0), + crate::word(21, 0, 0, 0, 138, 0, 0, 0), + crate::word(29, 0, 0, 0, 39, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(49, 0, 0, 0, 199, 1, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(106, 115, 111, 110, 46, 99, 97, 112), + crate::word(110, 112, 58, 86, 97, 108, 117, 101), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(8, 0, 0, 0, 1, 0, 1, 0), + crate::word(223, 157, 214, 53, 231, 38, 16, 227), + crate::word(9, 0, 0, 0, 50, 0, 0, 0), + crate::word(72, 61, 201, 161, 236, 246, 217, 160), + crate::word(5, 0, 0, 0, 42, 0, 0, 0), + crate::word(70, 105, 101, 108, 100, 0, 0, 0), + crate::word(67, 97, 108, 108, 0, 0, 0, 0), + crate::word(32, 0, 0, 0, 3, 0, 4, 0), + crate::word(0, 0, 255, 255, 0, 0, 0, 0), + crate::word(0, 0, 1, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(209, 0, 0, 0, 42, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(204, 0, 0, 0, 3, 0, 1, 0), + crate::word(216, 0, 0, 0, 2, 0, 1, 0), + crate::word(1, 0, 254, 255, 16, 0, 0, 0), + crate::word(0, 0, 1, 0, 1, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(213, 0, 0, 0, 66, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(208, 0, 0, 0, 3, 0, 1, 0), + crate::word(220, 0, 0, 0, 2, 0, 1, 0), + crate::word(2, 0, 253, 255, 1, 0, 0, 0), + crate::word(0, 0, 1, 0, 2, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(217, 0, 0, 0, 58, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(212, 0, 0, 0, 3, 0, 1, 0), + crate::word(224, 0, 0, 0, 2, 0, 1, 0), + crate::word(3, 0, 252, 255, 0, 0, 0, 0), + crate::word(0, 0, 1, 0, 3, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(221, 0, 0, 0, 58, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(216, 0, 0, 0, 3, 0, 1, 0), + crate::word(228, 0, 0, 0, 2, 0, 1, 0), + crate::word(4, 0, 251, 255, 0, 0, 0, 0), + crate::word(0, 0, 1, 0, 4, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(225, 0, 0, 0, 50, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(220, 0, 0, 0, 3, 0, 1, 0), + crate::word(248, 0, 0, 0, 2, 0, 1, 0), + crate::word(5, 0, 250, 255, 0, 0, 0, 0), + crate::word(0, 0, 1, 0, 5, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(245, 0, 0, 0, 58, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(240, 0, 0, 0, 3, 0, 1, 0), + crate::word(12, 1, 0, 0, 2, 0, 1, 0), + crate::word(6, 0, 249, 255, 0, 0, 0, 0), + crate::word(0, 0, 1, 0, 6, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(9, 1, 0, 0, 42, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(4, 1, 0, 0, 3, 0, 1, 0), + crate::word(16, 1, 0, 0, 2, 0, 1, 0), + crate::word(7, 0, 248, 255, 0, 0, 0, 0), + crate::word(0, 0, 1, 0, 7, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(13, 1, 0, 0, 34, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(8, 1, 0, 0, 3, 0, 1, 0), + crate::word(20, 1, 0, 0, 2, 0, 1, 0), + crate::word(110, 117, 108, 108, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(98, 111, 111, 108, 101, 97, 110, 0), + crate::word(1, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(1, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(110, 117, 109, 98, 101, 114, 0, 0), + crate::word(11, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(11, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(115, 116, 114, 105, 110, 103, 0, 0), + crate::word(12, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(12, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(97, 114, 114, 97, 121, 0, 0, 0), + crate::word(14, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 3, 0, 1, 0), + crate::word(16, 0, 0, 0, 0, 0, 0, 0), + crate::word(131, 221, 25, 249, 69, 120, 250, 163), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(14, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(111, 98, 106, 101, 99, 116, 0, 0), + crate::word(14, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 3, 0, 1, 0), + crate::word(16, 0, 0, 0, 0, 0, 0, 0), + crate::word(223, 157, 214, 53, 231, 38, 16, 227), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(14, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(99, 97, 108, 108, 0, 0, 0, 0), + crate::word(16, 0, 0, 0, 0, 0, 0, 0), + crate::word(72, 61, 201, 161, 236, 246, 217, 160), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(16, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(114, 97, 119, 0, 0, 0, 0, 0), + crate::word(12, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(12, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + ]; + pub fn get_field_types(index: u16) -> crate::introspect::Type { + match index { + 0 => <() as crate::introspect::Introspect>::introspect(), + 1 => ::introspect(), + 2 => ::introspect(), + 3 => ::introspect(), + 4 => as crate::introspect::Introspect>::introspect(), + 5 => as crate::introspect::Introspect>::introspect(), + 6 => ::introspect(), + 7 => ::introspect(), + _ => crate::introspect::panic_invalid_field_index(index), + } + } + pub fn get_annotation_types(child_index: Option, index: u32) -> crate::introspect::Type { + crate::introspect::panic_invalid_annotation_indices(child_index, index) + } + pub static RAW_SCHEMA: crate::introspect::RawStructSchema = crate::introspect::RawStructSchema { + encoded_node: &ENCODED_NODE, + nonunion_members: NONUNION_MEMBERS, + members_by_discriminant: MEMBERS_BY_DISCRIMINANT, + members_by_name: MEMBERS_BY_NAME, + }; + pub static NONUNION_MEMBERS : &[u16] = &[]; + pub static MEMBERS_BY_DISCRIMINANT : &[u16] = &[0,1,2,3,4,5,6,7]; + pub static MEMBERS_BY_NAME : &[u16] = &[4,1,6,0,2,5,7,3]; + pub const TYPE_ID: u64 = 0xa3fa_7845_f919_dd83; + } + pub enum Which { + Null(()), + Boolean(bool), + Number(f64), + String(A0), + Array(A1), + Object(A2), + Call(A3), + Raw(A4), + } + pub type WhichReader<'a,> = Which>,crate::Result>,crate::Result>,crate::Result>,crate::Result>>; + pub type WhichBuilder<'a,> = Which>,crate::Result>,crate::Result>,crate::Result>,crate::Result>>; + + pub mod field { + #[derive(Copy, Clone)] + pub struct Owned(()); + impl crate::introspect::Introspect for Owned { fn introspect() -> crate::introspect::Type { crate::introspect::TypeVariant::Struct(crate::introspect::RawBrandedStructSchema { generic: &_private::RAW_SCHEMA, field_types: _private::get_field_types, annotation_types: _private::get_annotation_types }).into() } } + impl crate::traits::Owned for Owned { type Reader<'a> = Reader<'a>; type Builder<'a> = Builder<'a>; } + impl crate::traits::OwnedStruct for Owned { type Reader<'a> = Reader<'a>; type Builder<'a> = Builder<'a>; } + impl crate::traits::Pipelined for Owned { type Pipeline = Pipeline; } + + pub struct Reader<'a> { reader: crate::private::layout::StructReader<'a> } + impl <> ::core::marker::Copy for Reader<'_,> {} + impl <> ::core::clone::Clone for Reader<'_,> { + fn clone(&self) -> Self { *self } + } + + impl <> crate::traits::HasTypeId for Reader<'_,> { + const TYPE_ID: u64 = _private::TYPE_ID; + } + impl <'a,> ::core::convert::From> for Reader<'a,> { + fn from(reader: crate::private::layout::StructReader<'a>) -> Self { + Self { reader, } + } + } + + impl <'a,> ::core::convert::From> for crate::dynamic_value::Reader<'a> { + fn from(reader: Reader<'a,>) -> Self { + Self::Struct(crate::dynamic_struct::Reader::new(reader.reader, crate::schema::StructSchema::new(crate::introspect::RawBrandedStructSchema { generic: &_private::RAW_SCHEMA, field_types: _private::get_field_types::<>, annotation_types: _private::get_annotation_types::<>}))) + } + } + + impl <> ::core::fmt::Debug for Reader<'_,> { + fn fmt(&self, f: &mut ::core::fmt::Formatter<'_>) -> ::core::result::Result<(), ::core::fmt::Error> { + core::fmt::Debug::fmt(&::core::convert::Into::>::into(*self), f) + } + } + + impl <'a,> crate::traits::FromPointerReader<'a> for Reader<'a,> { + fn get_from_pointer(reader: &crate::private::layout::PointerReader<'a>, default: ::core::option::Option<&'a [crate::Word]>) -> crate::Result { + ::core::result::Result::Ok(reader.get_struct(default)?.into()) + } + } + + impl <'a,> crate::traits::IntoInternalStructReader<'a> for Reader<'a,> { + fn into_internal_struct_reader(self) -> crate::private::layout::StructReader<'a> { + self.reader + } + } + + impl <'a,> crate::traits::Imbue<'a> for Reader<'a,> { + fn imbue(&mut self, cap_table: &'a crate::private::layout::CapTable) { + self.reader.imbue(crate::private::layout::CapTableReader::Plain(cap_table)) + } + } + + impl <'a,> Reader<'a,> { + pub fn reborrow(&self) -> Reader<'_,> { + Self { .. *self } + } + + pub fn total_size(&self) -> crate::Result { + self.reader.total_size() + } + #[inline] + pub fn get_name(self) -> crate::Result> { + crate::traits::FromPointerReader::get_from_pointer(&self.reader.get_pointer_field(0), ::core::option::Option::None) + } + #[inline] + pub fn has_name(&self) -> bool { + !self.reader.get_pointer_field(0).is_null() + } + #[inline] + pub fn get_value(self) -> crate::Result> { + crate::traits::FromPointerReader::get_from_pointer(&self.reader.get_pointer_field(1), ::core::option::Option::None) + } + #[inline] + pub fn has_value(&self) -> bool { + !self.reader.get_pointer_field(1).is_null() + } + } + + pub struct Builder<'a> { builder: crate::private::layout::StructBuilder<'a> } + impl <> crate::traits::HasStructSize for Builder<'_,> { + const STRUCT_SIZE: crate::private::layout::StructSize = crate::private::layout::StructSize { data: 0, pointers: 2 }; + } + impl <> crate::traits::HasTypeId for Builder<'_,> { + const TYPE_ID: u64 = _private::TYPE_ID; + } + impl <'a,> ::core::convert::From> for Builder<'a,> { + fn from(builder: crate::private::layout::StructBuilder<'a>) -> Self { + Self { builder, } + } + } + + impl <'a,> ::core::convert::From> for crate::dynamic_value::Builder<'a> { + fn from(builder: Builder<'a,>) -> Self { + Self::Struct(crate::dynamic_struct::Builder::new(builder.builder, crate::schema::StructSchema::new(crate::introspect::RawBrandedStructSchema { generic: &_private::RAW_SCHEMA, field_types: _private::get_field_types::<>, annotation_types: _private::get_annotation_types::<>}))) + } + } + + impl <'a,> crate::traits::ImbueMut<'a> for Builder<'a,> { + fn imbue_mut(&mut self, cap_table: &'a mut crate::private::layout::CapTable) { + self.builder.imbue(crate::private::layout::CapTableBuilder::Plain(cap_table)) + } + } + + impl <'a,> crate::traits::FromPointerBuilder<'a> for Builder<'a,> { + fn init_pointer(builder: crate::private::layout::PointerBuilder<'a>, _size: u32) -> Self { + builder.init_struct(::STRUCT_SIZE).into() + } + fn get_from_pointer(builder: crate::private::layout::PointerBuilder<'a>, default: ::core::option::Option<&'a [crate::Word]>) -> crate::Result { + ::core::result::Result::Ok(builder.get_struct(::STRUCT_SIZE, default)?.into()) + } + } + + impl <> crate::traits::SetterInput> for Reader<'_,> { + fn set_pointer_builder(mut pointer: crate::private::layout::PointerBuilder<'_>, value: Self, canonicalize: bool) -> crate::Result<()> { pointer.set_struct(&value.reader, canonicalize) } + } + + impl <'a,> Builder<'a,> { + pub fn into_reader(self) -> Reader<'a,> { + self.builder.into_reader().into() + } + pub fn reborrow(&mut self) -> Builder<'_,> { + Builder { builder: self.builder.reborrow() } + } + pub fn reborrow_as_reader(&self) -> Reader<'_,> { + self.builder.as_reader().into() + } + + pub fn total_size(&self) -> crate::Result { + self.builder.as_reader().total_size() + } + #[inline] + pub fn get_name(self) -> crate::Result> { + crate::traits::FromPointerBuilder::get_from_pointer(self.builder.get_pointer_field(0), ::core::option::Option::None) + } + #[inline] + pub fn set_name(&mut self, value: impl crate::traits::SetterInput) { + crate::traits::SetterInput::set_pointer_builder(self.builder.reborrow().get_pointer_field(0), value, false).unwrap() + } + #[inline] + pub fn init_name(self, size: u32) -> crate::text::Builder<'a> { + self.builder.get_pointer_field(0).init_text(size) + } + #[inline] + pub fn has_name(&self) -> bool { + !self.builder.is_pointer_field_null(0) + } + #[inline] + pub fn get_value(self) -> crate::Result> { + crate::traits::FromPointerBuilder::get_from_pointer(self.builder.get_pointer_field(1), ::core::option::Option::None) + } + #[inline] + pub fn set_value(&mut self, value: crate::json_capnp::value::Reader<'_>) -> crate::Result<()> { + crate::traits::SetterInput::set_pointer_builder(self.builder.reborrow().get_pointer_field(1), value, false) + } + #[inline] + pub fn init_value(self, ) -> crate::json_capnp::value::Builder<'a> { + crate::traits::FromPointerBuilder::init_pointer(self.builder.get_pointer_field(1), 0) + } + #[inline] + pub fn has_value(&self) -> bool { + !self.builder.is_pointer_field_null(1) + } + } + + pub struct Pipeline { _typeless: crate::any_pointer::Pipeline } + impl crate::capability::FromTypelessPipeline for Pipeline { + fn new(typeless: crate::any_pointer::Pipeline) -> Self { + Self { _typeless: typeless, } + } + } + impl Pipeline { + pub fn get_value(&self) -> crate::json_capnp::value::Pipeline { + crate::capability::FromTypelessPipeline::new(self._typeless.get_pointer_field(1)) + } + } + mod _private { + pub static ENCODED_NODE: [crate::Word; 48] = [ + crate::word(0, 0, 0, 0, 6, 0, 6, 0), + crate::word(223, 157, 214, 53, 231, 38, 16, 227), + crate::word(17, 0, 0, 0, 1, 0, 0, 0), + crate::word(131, 221, 25, 249, 69, 120, 250, 163), + crate::word(2, 0, 7, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(171, 10, 0, 0, 229, 10, 0, 0), + crate::word(21, 0, 0, 0, 186, 0, 0, 0), + crate::word(29, 0, 0, 0, 7, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(25, 0, 0, 0, 119, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(106, 115, 111, 110, 46, 99, 97, 112), + crate::word(110, 112, 58, 86, 97, 108, 117, 101), + crate::word(46, 70, 105, 101, 108, 100, 0, 0), + crate::word(0, 0, 0, 0, 1, 0, 1, 0), + crate::word(8, 0, 0, 0, 3, 0, 4, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 1, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(41, 0, 0, 0, 42, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(36, 0, 0, 0, 3, 0, 1, 0), + crate::word(48, 0, 0, 0, 2, 0, 1, 0), + crate::word(1, 0, 0, 0, 1, 0, 0, 0), + crate::word(0, 0, 1, 0, 1, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(45, 0, 0, 0, 50, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(40, 0, 0, 0, 3, 0, 1, 0), + crate::word(52, 0, 0, 0, 2, 0, 1, 0), + crate::word(110, 97, 109, 101, 0, 0, 0, 0), + crate::word(12, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(12, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(118, 97, 108, 117, 101, 0, 0, 0), + crate::word(16, 0, 0, 0, 0, 0, 0, 0), + crate::word(131, 221, 25, 249, 69, 120, 250, 163), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(16, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + ]; + pub fn get_field_types(index: u16) -> crate::introspect::Type { + match index { + 0 => ::introspect(), + 1 => ::introspect(), + _ => crate::introspect::panic_invalid_field_index(index), + } + } + pub fn get_annotation_types(child_index: Option, index: u32) -> crate::introspect::Type { + crate::introspect::panic_invalid_annotation_indices(child_index, index) + } + pub static RAW_SCHEMA: crate::introspect::RawStructSchema = crate::introspect::RawStructSchema { + encoded_node: &ENCODED_NODE, + nonunion_members: NONUNION_MEMBERS, + members_by_discriminant: MEMBERS_BY_DISCRIMINANT, + members_by_name: MEMBERS_BY_NAME, + }; + pub static NONUNION_MEMBERS : &[u16] = &[0,1]; + pub static MEMBERS_BY_DISCRIMINANT : &[u16] = &[]; + pub static MEMBERS_BY_NAME : &[u16] = &[0,1]; + pub const TYPE_ID: u64 = 0xe310_26e7_35d6_9ddf; + } + } + + pub mod call { + #[derive(Copy, Clone)] + pub struct Owned(()); + impl crate::introspect::Introspect for Owned { fn introspect() -> crate::introspect::Type { crate::introspect::TypeVariant::Struct(crate::introspect::RawBrandedStructSchema { generic: &_private::RAW_SCHEMA, field_types: _private::get_field_types, annotation_types: _private::get_annotation_types }).into() } } + impl crate::traits::Owned for Owned { type Reader<'a> = Reader<'a>; type Builder<'a> = Builder<'a>; } + impl crate::traits::OwnedStruct for Owned { type Reader<'a> = Reader<'a>; type Builder<'a> = Builder<'a>; } + impl crate::traits::Pipelined for Owned { type Pipeline = Pipeline; } + + pub struct Reader<'a> { reader: crate::private::layout::StructReader<'a> } + impl <> ::core::marker::Copy for Reader<'_,> {} + impl <> ::core::clone::Clone for Reader<'_,> { + fn clone(&self) -> Self { *self } + } + + impl <> crate::traits::HasTypeId for Reader<'_,> { + const TYPE_ID: u64 = _private::TYPE_ID; + } + impl <'a,> ::core::convert::From> for Reader<'a,> { + fn from(reader: crate::private::layout::StructReader<'a>) -> Self { + Self { reader, } + } + } + + impl <'a,> ::core::convert::From> for crate::dynamic_value::Reader<'a> { + fn from(reader: Reader<'a,>) -> Self { + Self::Struct(crate::dynamic_struct::Reader::new(reader.reader, crate::schema::StructSchema::new(crate::introspect::RawBrandedStructSchema { generic: &_private::RAW_SCHEMA, field_types: _private::get_field_types::<>, annotation_types: _private::get_annotation_types::<>}))) + } + } + + impl <> ::core::fmt::Debug for Reader<'_,> { + fn fmt(&self, f: &mut ::core::fmt::Formatter<'_>) -> ::core::result::Result<(), ::core::fmt::Error> { + core::fmt::Debug::fmt(&::core::convert::Into::>::into(*self), f) + } + } + + impl <'a,> crate::traits::FromPointerReader<'a> for Reader<'a,> { + fn get_from_pointer(reader: &crate::private::layout::PointerReader<'a>, default: ::core::option::Option<&'a [crate::Word]>) -> crate::Result { + ::core::result::Result::Ok(reader.get_struct(default)?.into()) + } + } + + impl <'a,> crate::traits::IntoInternalStructReader<'a> for Reader<'a,> { + fn into_internal_struct_reader(self) -> crate::private::layout::StructReader<'a> { + self.reader + } + } + + impl <'a,> crate::traits::Imbue<'a> for Reader<'a,> { + fn imbue(&mut self, cap_table: &'a crate::private::layout::CapTable) { + self.reader.imbue(crate::private::layout::CapTableReader::Plain(cap_table)) + } + } + + impl <'a,> Reader<'a,> { + pub fn reborrow(&self) -> Reader<'_,> { + Self { .. *self } + } + + pub fn total_size(&self) -> crate::Result { + self.reader.total_size() + } + #[inline] + pub fn get_function(self) -> crate::Result> { + crate::traits::FromPointerReader::get_from_pointer(&self.reader.get_pointer_field(0), ::core::option::Option::None) + } + #[inline] + pub fn has_function(&self) -> bool { + !self.reader.get_pointer_field(0).is_null() + } + #[inline] + pub fn get_params(self) -> crate::Result> { + crate::traits::FromPointerReader::get_from_pointer(&self.reader.get_pointer_field(1), ::core::option::Option::None) + } + #[inline] + pub fn has_params(&self) -> bool { + !self.reader.get_pointer_field(1).is_null() + } + } + + pub struct Builder<'a> { builder: crate::private::layout::StructBuilder<'a> } + impl <> crate::traits::HasStructSize for Builder<'_,> { + const STRUCT_SIZE: crate::private::layout::StructSize = crate::private::layout::StructSize { data: 0, pointers: 2 }; + } + impl <> crate::traits::HasTypeId for Builder<'_,> { + const TYPE_ID: u64 = _private::TYPE_ID; + } + impl <'a,> ::core::convert::From> for Builder<'a,> { + fn from(builder: crate::private::layout::StructBuilder<'a>) -> Self { + Self { builder, } + } + } + + impl <'a,> ::core::convert::From> for crate::dynamic_value::Builder<'a> { + fn from(builder: Builder<'a,>) -> Self { + Self::Struct(crate::dynamic_struct::Builder::new(builder.builder, crate::schema::StructSchema::new(crate::introspect::RawBrandedStructSchema { generic: &_private::RAW_SCHEMA, field_types: _private::get_field_types::<>, annotation_types: _private::get_annotation_types::<>}))) + } + } + + impl <'a,> crate::traits::ImbueMut<'a> for Builder<'a,> { + fn imbue_mut(&mut self, cap_table: &'a mut crate::private::layout::CapTable) { + self.builder.imbue(crate::private::layout::CapTableBuilder::Plain(cap_table)) + } + } + + impl <'a,> crate::traits::FromPointerBuilder<'a> for Builder<'a,> { + fn init_pointer(builder: crate::private::layout::PointerBuilder<'a>, _size: u32) -> Self { + builder.init_struct(::STRUCT_SIZE).into() + } + fn get_from_pointer(builder: crate::private::layout::PointerBuilder<'a>, default: ::core::option::Option<&'a [crate::Word]>) -> crate::Result { + ::core::result::Result::Ok(builder.get_struct(::STRUCT_SIZE, default)?.into()) + } + } + + impl <> crate::traits::SetterInput> for Reader<'_,> { + fn set_pointer_builder(mut pointer: crate::private::layout::PointerBuilder<'_>, value: Self, canonicalize: bool) -> crate::Result<()> { pointer.set_struct(&value.reader, canonicalize) } + } + + impl <'a,> Builder<'a,> { + pub fn into_reader(self) -> Reader<'a,> { + self.builder.into_reader().into() + } + pub fn reborrow(&mut self) -> Builder<'_,> { + Builder { builder: self.builder.reborrow() } + } + pub fn reborrow_as_reader(&self) -> Reader<'_,> { + self.builder.as_reader().into() + } + + pub fn total_size(&self) -> crate::Result { + self.builder.as_reader().total_size() + } + #[inline] + pub fn get_function(self) -> crate::Result> { + crate::traits::FromPointerBuilder::get_from_pointer(self.builder.get_pointer_field(0), ::core::option::Option::None) + } + #[inline] + pub fn set_function(&mut self, value: impl crate::traits::SetterInput) { + crate::traits::SetterInput::set_pointer_builder(self.builder.reborrow().get_pointer_field(0), value, false).unwrap() + } + #[inline] + pub fn init_function(self, size: u32) -> crate::text::Builder<'a> { + self.builder.get_pointer_field(0).init_text(size) + } + #[inline] + pub fn has_function(&self) -> bool { + !self.builder.is_pointer_field_null(0) + } + #[inline] + pub fn get_params(self) -> crate::Result> { + crate::traits::FromPointerBuilder::get_from_pointer(self.builder.get_pointer_field(1), ::core::option::Option::None) + } + #[inline] + pub fn set_params(&mut self, value: crate::struct_list::Reader<'_,crate::json_capnp::value::Owned>) -> crate::Result<()> { + crate::traits::SetterInput::set_pointer_builder(self.builder.reborrow().get_pointer_field(1), value, false) + } + #[inline] + pub fn init_params(self, size: u32) -> crate::struct_list::Builder<'a,crate::json_capnp::value::Owned> { + crate::traits::FromPointerBuilder::init_pointer(self.builder.get_pointer_field(1), size) + } + #[inline] + pub fn has_params(&self) -> bool { + !self.builder.is_pointer_field_null(1) + } + } + + pub struct Pipeline { _typeless: crate::any_pointer::Pipeline } + impl crate::capability::FromTypelessPipeline for Pipeline { + fn new(typeless: crate::any_pointer::Pipeline) -> Self { + Self { _typeless: typeless, } + } + } + impl Pipeline { + } + mod _private { + pub static ENCODED_NODE: [crate::Word; 53] = [ + crate::word(0, 0, 0, 0, 6, 0, 6, 0), + crate::word(72, 61, 201, 161, 236, 246, 217, 160), + crate::word(17, 0, 0, 0, 1, 0, 0, 0), + crate::word(131, 221, 25, 249, 69, 120, 250, 163), + crate::word(2, 0, 7, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(233, 10, 0, 0, 45, 11, 0, 0), + crate::word(21, 0, 0, 0, 178, 0, 0, 0), + crate::word(29, 0, 0, 0, 7, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(25, 0, 0, 0, 119, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(106, 115, 111, 110, 46, 99, 97, 112), + crate::word(110, 112, 58, 86, 97, 108, 117, 101), + crate::word(46, 67, 97, 108, 108, 0, 0, 0), + crate::word(0, 0, 0, 0, 1, 0, 1, 0), + crate::word(8, 0, 0, 0, 3, 0, 4, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 1, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(41, 0, 0, 0, 74, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(40, 0, 0, 0, 3, 0, 1, 0), + crate::word(52, 0, 0, 0, 2, 0, 1, 0), + crate::word(1, 0, 0, 0, 1, 0, 0, 0), + crate::word(0, 0, 1, 0, 1, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(49, 0, 0, 0, 58, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(44, 0, 0, 0, 3, 0, 1, 0), + crate::word(72, 0, 0, 0, 2, 0, 1, 0), + crate::word(102, 117, 110, 99, 116, 105, 111, 110), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(12, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(12, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(112, 97, 114, 97, 109, 115, 0, 0), + crate::word(14, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 3, 0, 1, 0), + crate::word(16, 0, 0, 0, 0, 0, 0, 0), + crate::word(131, 221, 25, 249, 69, 120, 250, 163), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(14, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + ]; + pub fn get_field_types(index: u16) -> crate::introspect::Type { + match index { + 0 => ::introspect(), + 1 => as crate::introspect::Introspect>::introspect(), + _ => crate::introspect::panic_invalid_field_index(index), + } + } + pub fn get_annotation_types(child_index: Option, index: u32) -> crate::introspect::Type { + crate::introspect::panic_invalid_annotation_indices(child_index, index) + } + pub static RAW_SCHEMA: crate::introspect::RawStructSchema = crate::introspect::RawStructSchema { + encoded_node: &ENCODED_NODE, + nonunion_members: NONUNION_MEMBERS, + members_by_discriminant: MEMBERS_BY_DISCRIMINANT, + members_by_name: MEMBERS_BY_NAME, + }; + pub static NONUNION_MEMBERS : &[u16] = &[0,1]; + pub static MEMBERS_BY_DISCRIMINANT : &[u16] = &[]; + pub static MEMBERS_BY_NAME : &[u16] = &[0,1]; + pub const TYPE_ID: u64 = 0xa0d9_f6ec_a1c9_3d48; + } + } +} +pub mod name { + pub const ID: u64 = 0xfa5b1fd61c2e7c3d; + pub fn get_type() -> crate::introspect::Type { ::introspect() } +} +pub mod flatten { + pub const ID: u64 = 0x82d3e852af0336bf; + pub fn get_type() -> crate::introspect::Type { ::introspect() } +} + +pub mod flatten_options { + #[derive(Copy, Clone)] + pub struct Owned(()); + impl crate::introspect::Introspect for Owned { fn introspect() -> crate::introspect::Type { crate::introspect::TypeVariant::Struct(crate::introspect::RawBrandedStructSchema { generic: &_private::RAW_SCHEMA, field_types: _private::get_field_types, annotation_types: _private::get_annotation_types }).into() } } + impl crate::traits::Owned for Owned { type Reader<'a> = Reader<'a>; type Builder<'a> = Builder<'a>; } + impl crate::traits::OwnedStruct for Owned { type Reader<'a> = Reader<'a>; type Builder<'a> = Builder<'a>; } + impl crate::traits::Pipelined for Owned { type Pipeline = Pipeline; } + + pub struct Reader<'a> { reader: crate::private::layout::StructReader<'a> } + impl <> ::core::marker::Copy for Reader<'_,> {} + impl <> ::core::clone::Clone for Reader<'_,> { + fn clone(&self) -> Self { *self } + } + + impl <> crate::traits::HasTypeId for Reader<'_,> { + const TYPE_ID: u64 = _private::TYPE_ID; + } + impl <'a,> ::core::convert::From> for Reader<'a,> { + fn from(reader: crate::private::layout::StructReader<'a>) -> Self { + Self { reader, } + } + } + + impl <'a,> ::core::convert::From> for crate::dynamic_value::Reader<'a> { + fn from(reader: Reader<'a,>) -> Self { + Self::Struct(crate::dynamic_struct::Reader::new(reader.reader, crate::schema::StructSchema::new(crate::introspect::RawBrandedStructSchema { generic: &_private::RAW_SCHEMA, field_types: _private::get_field_types::<>, annotation_types: _private::get_annotation_types::<>}))) + } + } + + impl <> ::core::fmt::Debug for Reader<'_,> { + fn fmt(&self, f: &mut ::core::fmt::Formatter<'_>) -> ::core::result::Result<(), ::core::fmt::Error> { + core::fmt::Debug::fmt(&::core::convert::Into::>::into(*self), f) + } + } + + impl <'a,> crate::traits::FromPointerReader<'a> for Reader<'a,> { + fn get_from_pointer(reader: &crate::private::layout::PointerReader<'a>, default: ::core::option::Option<&'a [crate::Word]>) -> crate::Result { + ::core::result::Result::Ok(reader.get_struct(default)?.into()) + } + } + + impl <'a,> crate::traits::IntoInternalStructReader<'a> for Reader<'a,> { + fn into_internal_struct_reader(self) -> crate::private::layout::StructReader<'a> { + self.reader + } + } + + impl <'a,> crate::traits::Imbue<'a> for Reader<'a,> { + fn imbue(&mut self, cap_table: &'a crate::private::layout::CapTable) { + self.reader.imbue(crate::private::layout::CapTableReader::Plain(cap_table)) + } + } + + impl <'a,> Reader<'a,> { + pub fn reborrow(&self) -> Reader<'_,> { + Self { .. *self } + } + + pub fn total_size(&self) -> crate::Result { + self.reader.total_size() + } + #[inline] + pub fn get_prefix(self) -> crate::Result> { + crate::traits::FromPointerReader::get_from_pointer(&self.reader.get_pointer_field(0), ::core::option::Option::Some(&_private::DEFAULT_PREFIX[..])) + } + #[inline] + pub fn has_prefix(&self) -> bool { + !self.reader.get_pointer_field(0).is_null() + } + } + + pub struct Builder<'a> { builder: crate::private::layout::StructBuilder<'a> } + impl <> crate::traits::HasStructSize for Builder<'_,> { + const STRUCT_SIZE: crate::private::layout::StructSize = crate::private::layout::StructSize { data: 0, pointers: 1 }; + } + impl <> crate::traits::HasTypeId for Builder<'_,> { + const TYPE_ID: u64 = _private::TYPE_ID; + } + impl <'a,> ::core::convert::From> for Builder<'a,> { + fn from(builder: crate::private::layout::StructBuilder<'a>) -> Self { + Self { builder, } + } + } + + impl <'a,> ::core::convert::From> for crate::dynamic_value::Builder<'a> { + fn from(builder: Builder<'a,>) -> Self { + Self::Struct(crate::dynamic_struct::Builder::new(builder.builder, crate::schema::StructSchema::new(crate::introspect::RawBrandedStructSchema { generic: &_private::RAW_SCHEMA, field_types: _private::get_field_types::<>, annotation_types: _private::get_annotation_types::<>}))) + } + } + + impl <'a,> crate::traits::ImbueMut<'a> for Builder<'a,> { + fn imbue_mut(&mut self, cap_table: &'a mut crate::private::layout::CapTable) { + self.builder.imbue(crate::private::layout::CapTableBuilder::Plain(cap_table)) + } + } + + impl <'a,> crate::traits::FromPointerBuilder<'a> for Builder<'a,> { + fn init_pointer(builder: crate::private::layout::PointerBuilder<'a>, _size: u32) -> Self { + builder.init_struct(::STRUCT_SIZE).into() + } + fn get_from_pointer(builder: crate::private::layout::PointerBuilder<'a>, default: ::core::option::Option<&'a [crate::Word]>) -> crate::Result { + ::core::result::Result::Ok(builder.get_struct(::STRUCT_SIZE, default)?.into()) + } + } + + impl <> crate::traits::SetterInput> for Reader<'_,> { + fn set_pointer_builder(mut pointer: crate::private::layout::PointerBuilder<'_>, value: Self, canonicalize: bool) -> crate::Result<()> { pointer.set_struct(&value.reader, canonicalize) } + } + + impl <'a,> Builder<'a,> { + pub fn into_reader(self) -> Reader<'a,> { + self.builder.into_reader().into() + } + pub fn reborrow(&mut self) -> Builder<'_,> { + Builder { builder: self.builder.reborrow() } + } + pub fn reborrow_as_reader(&self) -> Reader<'_,> { + self.builder.as_reader().into() + } + + pub fn total_size(&self) -> crate::Result { + self.builder.as_reader().total_size() + } + #[inline] + pub fn get_prefix(self) -> crate::Result> { + crate::traits::FromPointerBuilder::get_from_pointer(self.builder.get_pointer_field(0), ::core::option::Option::Some(&_private::DEFAULT_PREFIX[..])) + } + #[inline] + pub fn set_prefix(&mut self, value: impl crate::traits::SetterInput) { + crate::traits::SetterInput::set_pointer_builder(self.builder.reborrow().get_pointer_field(0), value, false).unwrap() + } + #[inline] + pub fn init_prefix(self, size: u32) -> crate::text::Builder<'a> { + self.builder.get_pointer_field(0).init_text(size) + } + #[inline] + pub fn has_prefix(&self) -> bool { + !self.builder.is_pointer_field_null(0) + } + } + + pub struct Pipeline { _typeless: crate::any_pointer::Pipeline } + impl crate::capability::FromTypelessPipeline for Pipeline { + fn new(typeless: crate::any_pointer::Pipeline) -> Self { + Self { _typeless: typeless, } + } + } + impl Pipeline { + } + mod _private { + pub static ENCODED_NODE: [crate::Word; 35] = [ + crate::word(0, 0, 0, 0, 6, 0, 6, 0), + crate::word(97, 234, 194, 123, 37, 19, 223, 196), + crate::word(11, 0, 0, 0, 1, 0, 0, 0), + crate::word(52, 94, 58, 164, 151, 146, 249, 142), + crate::word(1, 0, 7, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(180, 15, 0, 0, 35, 16, 0, 0), + crate::word(21, 0, 0, 0, 210, 0, 0, 0), + crate::word(33, 0, 0, 0, 7, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(29, 0, 0, 0, 63, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(106, 115, 111, 110, 46, 99, 97, 112), + crate::word(110, 112, 58, 70, 108, 97, 116, 116), + crate::word(101, 110, 79, 112, 116, 105, 111, 110), + crate::word(115, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 1, 0, 1, 0), + crate::word(4, 0, 0, 0, 3, 0, 4, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 1, 0, 0, 0, 0, 0), + crate::word(1, 0, 0, 0, 0, 0, 0, 0), + crate::word(13, 0, 0, 0, 58, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(8, 0, 0, 0, 3, 0, 1, 0), + crate::word(20, 0, 0, 0, 2, 0, 1, 0), + crate::word(112, 114, 101, 102, 105, 120, 0, 0), + crate::word(12, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(12, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(1, 0, 0, 0, 10, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + ]; + pub fn get_field_types(index: u16) -> crate::introspect::Type { + match index { + 0 => ::introspect(), + _ => crate::introspect::panic_invalid_field_index(index), + } + } + pub fn get_annotation_types(child_index: Option, index: u32) -> crate::introspect::Type { + crate::introspect::panic_invalid_annotation_indices(child_index, index) + } + pub static RAW_SCHEMA: crate::introspect::RawStructSchema = crate::introspect::RawStructSchema { + encoded_node: &ENCODED_NODE, + nonunion_members: NONUNION_MEMBERS, + members_by_discriminant: MEMBERS_BY_DISCRIMINANT, + members_by_name: MEMBERS_BY_NAME, + }; + pub static NONUNION_MEMBERS : &[u16] = &[0]; + pub static MEMBERS_BY_DISCRIMINANT : &[u16] = &[]; + pub static MEMBERS_BY_NAME : &[u16] = &[0]; + pub static DEFAULT_PREFIX: [crate::Word; 2] = [ + crate::word(1, 0, 0, 0, 10, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + ]; + pub const TYPE_ID: u64 = 0xc4df_1325_7bc2_ea61; + } +} +pub mod discriminator { + pub const ID: u64 = 0xcfa794e8d19a0162; + pub fn get_type() -> crate::introspect::Type { ::introspect() } +} + +pub mod discriminator_options { + #[derive(Copy, Clone)] + pub struct Owned(()); + impl crate::introspect::Introspect for Owned { fn introspect() -> crate::introspect::Type { crate::introspect::TypeVariant::Struct(crate::introspect::RawBrandedStructSchema { generic: &_private::RAW_SCHEMA, field_types: _private::get_field_types, annotation_types: _private::get_annotation_types }).into() } } + impl crate::traits::Owned for Owned { type Reader<'a> = Reader<'a>; type Builder<'a> = Builder<'a>; } + impl crate::traits::OwnedStruct for Owned { type Reader<'a> = Reader<'a>; type Builder<'a> = Builder<'a>; } + impl crate::traits::Pipelined for Owned { type Pipeline = Pipeline; } + + pub struct Reader<'a> { reader: crate::private::layout::StructReader<'a> } + impl <> ::core::marker::Copy for Reader<'_,> {} + impl <> ::core::clone::Clone for Reader<'_,> { + fn clone(&self) -> Self { *self } + } + + impl <> crate::traits::HasTypeId for Reader<'_,> { + const TYPE_ID: u64 = _private::TYPE_ID; + } + impl <'a,> ::core::convert::From> for Reader<'a,> { + fn from(reader: crate::private::layout::StructReader<'a>) -> Self { + Self { reader, } + } + } + + impl <'a,> ::core::convert::From> for crate::dynamic_value::Reader<'a> { + fn from(reader: Reader<'a,>) -> Self { + Self::Struct(crate::dynamic_struct::Reader::new(reader.reader, crate::schema::StructSchema::new(crate::introspect::RawBrandedStructSchema { generic: &_private::RAW_SCHEMA, field_types: _private::get_field_types::<>, annotation_types: _private::get_annotation_types::<>}))) + } + } + + impl <> ::core::fmt::Debug for Reader<'_,> { + fn fmt(&self, f: &mut ::core::fmt::Formatter<'_>) -> ::core::result::Result<(), ::core::fmt::Error> { + core::fmt::Debug::fmt(&::core::convert::Into::>::into(*self), f) + } + } + + impl <'a,> crate::traits::FromPointerReader<'a> for Reader<'a,> { + fn get_from_pointer(reader: &crate::private::layout::PointerReader<'a>, default: ::core::option::Option<&'a [crate::Word]>) -> crate::Result { + ::core::result::Result::Ok(reader.get_struct(default)?.into()) + } + } + + impl <'a,> crate::traits::IntoInternalStructReader<'a> for Reader<'a,> { + fn into_internal_struct_reader(self) -> crate::private::layout::StructReader<'a> { + self.reader + } + } + + impl <'a,> crate::traits::Imbue<'a> for Reader<'a,> { + fn imbue(&mut self, cap_table: &'a crate::private::layout::CapTable) { + self.reader.imbue(crate::private::layout::CapTableReader::Plain(cap_table)) + } + } + + impl <'a,> Reader<'a,> { + pub fn reborrow(&self) -> Reader<'_,> { + Self { .. *self } + } + + pub fn total_size(&self) -> crate::Result { + self.reader.total_size() + } + #[inline] + pub fn get_name(self) -> crate::Result> { + crate::traits::FromPointerReader::get_from_pointer(&self.reader.get_pointer_field(0), ::core::option::Option::None) + } + #[inline] + pub fn has_name(&self) -> bool { + !self.reader.get_pointer_field(0).is_null() + } + #[inline] + pub fn get_value_name(self) -> crate::Result> { + crate::traits::FromPointerReader::get_from_pointer(&self.reader.get_pointer_field(1), ::core::option::Option::None) + } + #[inline] + pub fn has_value_name(&self) -> bool { + !self.reader.get_pointer_field(1).is_null() + } + } + + pub struct Builder<'a> { builder: crate::private::layout::StructBuilder<'a> } + impl <> crate::traits::HasStructSize for Builder<'_,> { + const STRUCT_SIZE: crate::private::layout::StructSize = crate::private::layout::StructSize { data: 0, pointers: 2 }; + } + impl <> crate::traits::HasTypeId for Builder<'_,> { + const TYPE_ID: u64 = _private::TYPE_ID; + } + impl <'a,> ::core::convert::From> for Builder<'a,> { + fn from(builder: crate::private::layout::StructBuilder<'a>) -> Self { + Self { builder, } + } + } + + impl <'a,> ::core::convert::From> for crate::dynamic_value::Builder<'a> { + fn from(builder: Builder<'a,>) -> Self { + Self::Struct(crate::dynamic_struct::Builder::new(builder.builder, crate::schema::StructSchema::new(crate::introspect::RawBrandedStructSchema { generic: &_private::RAW_SCHEMA, field_types: _private::get_field_types::<>, annotation_types: _private::get_annotation_types::<>}))) + } + } + + impl <'a,> crate::traits::ImbueMut<'a> for Builder<'a,> { + fn imbue_mut(&mut self, cap_table: &'a mut crate::private::layout::CapTable) { + self.builder.imbue(crate::private::layout::CapTableBuilder::Plain(cap_table)) + } + } + + impl <'a,> crate::traits::FromPointerBuilder<'a> for Builder<'a,> { + fn init_pointer(builder: crate::private::layout::PointerBuilder<'a>, _size: u32) -> Self { + builder.init_struct(::STRUCT_SIZE).into() + } + fn get_from_pointer(builder: crate::private::layout::PointerBuilder<'a>, default: ::core::option::Option<&'a [crate::Word]>) -> crate::Result { + ::core::result::Result::Ok(builder.get_struct(::STRUCT_SIZE, default)?.into()) + } + } + + impl <> crate::traits::SetterInput> for Reader<'_,> { + fn set_pointer_builder(mut pointer: crate::private::layout::PointerBuilder<'_>, value: Self, canonicalize: bool) -> crate::Result<()> { pointer.set_struct(&value.reader, canonicalize) } + } + + impl <'a,> Builder<'a,> { + pub fn into_reader(self) -> Reader<'a,> { + self.builder.into_reader().into() + } + pub fn reborrow(&mut self) -> Builder<'_,> { + Builder { builder: self.builder.reborrow() } + } + pub fn reborrow_as_reader(&self) -> Reader<'_,> { + self.builder.as_reader().into() + } + + pub fn total_size(&self) -> crate::Result { + self.builder.as_reader().total_size() + } + #[inline] + pub fn get_name(self) -> crate::Result> { + crate::traits::FromPointerBuilder::get_from_pointer(self.builder.get_pointer_field(0), ::core::option::Option::None) + } + #[inline] + pub fn set_name(&mut self, value: impl crate::traits::SetterInput) { + crate::traits::SetterInput::set_pointer_builder(self.builder.reborrow().get_pointer_field(0), value, false).unwrap() + } + #[inline] + pub fn init_name(self, size: u32) -> crate::text::Builder<'a> { + self.builder.get_pointer_field(0).init_text(size) + } + #[inline] + pub fn has_name(&self) -> bool { + !self.builder.is_pointer_field_null(0) + } + #[inline] + pub fn get_value_name(self) -> crate::Result> { + crate::traits::FromPointerBuilder::get_from_pointer(self.builder.get_pointer_field(1), ::core::option::Option::None) + } + #[inline] + pub fn set_value_name(&mut self, value: impl crate::traits::SetterInput) { + crate::traits::SetterInput::set_pointer_builder(self.builder.reborrow().get_pointer_field(1), value, false).unwrap() + } + #[inline] + pub fn init_value_name(self, size: u32) -> crate::text::Builder<'a> { + self.builder.get_pointer_field(1).init_text(size) + } + #[inline] + pub fn has_value_name(&self) -> bool { + !self.builder.is_pointer_field_null(1) + } + } + + pub struct Pipeline { _typeless: crate::any_pointer::Pipeline } + impl crate::capability::FromTypelessPipeline for Pipeline { + fn new(typeless: crate::any_pointer::Pipeline) -> Self { + Self { _typeless: typeless, } + } + } + impl Pipeline { + } + mod _private { + pub static ENCODED_NODE: [crate::Word; 50] = [ + crate::word(0, 0, 0, 0, 6, 0, 6, 0), + crate::word(25, 83, 62, 41, 12, 194, 248, 194), + crate::word(11, 0, 0, 0, 1, 0, 0, 0), + crate::word(52, 94, 58, 164, 151, 146, 249, 142), + crate::word(2, 0, 7, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(187, 17, 0, 0, 184, 19, 0, 0), + crate::word(21, 0, 0, 0, 2, 1, 0, 0), + crate::word(33, 0, 0, 0, 7, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(29, 0, 0, 0, 119, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(106, 115, 111, 110, 46, 99, 97, 112), + crate::word(110, 112, 58, 68, 105, 115, 99, 114), + crate::word(105, 109, 105, 110, 97, 116, 111, 114), + crate::word(79, 112, 116, 105, 111, 110, 115, 0), + crate::word(0, 0, 0, 0, 1, 0, 1, 0), + crate::word(8, 0, 0, 0, 3, 0, 4, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 1, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(41, 0, 0, 0, 42, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(36, 0, 0, 0, 3, 0, 1, 0), + crate::word(48, 0, 0, 0, 2, 0, 1, 0), + crate::word(1, 0, 0, 0, 1, 0, 0, 0), + crate::word(0, 0, 1, 0, 1, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(45, 0, 0, 0, 82, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(44, 0, 0, 0, 3, 0, 1, 0), + crate::word(56, 0, 0, 0, 2, 0, 1, 0), + crate::word(110, 97, 109, 101, 0, 0, 0, 0), + crate::word(12, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(12, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(118, 97, 108, 117, 101, 78, 97, 109), + crate::word(101, 0, 0, 0, 0, 0, 0, 0), + crate::word(12, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(12, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + crate::word(0, 0, 0, 0, 0, 0, 0, 0), + ]; + pub fn get_field_types(index: u16) -> crate::introspect::Type { + match index { + 0 => ::introspect(), + 1 => ::introspect(), + _ => crate::introspect::panic_invalid_field_index(index), + } + } + pub fn get_annotation_types(child_index: Option, index: u32) -> crate::introspect::Type { + crate::introspect::panic_invalid_annotation_indices(child_index, index) + } + pub static RAW_SCHEMA: crate::introspect::RawStructSchema = crate::introspect::RawStructSchema { + encoded_node: &ENCODED_NODE, + nonunion_members: NONUNION_MEMBERS, + members_by_discriminant: MEMBERS_BY_DISCRIMINANT, + members_by_name: MEMBERS_BY_NAME, + }; + pub static NONUNION_MEMBERS : &[u16] = &[0,1]; + pub static MEMBERS_BY_DISCRIMINANT : &[u16] = &[]; + pub static MEMBERS_BY_NAME : &[u16] = &[0,1]; + pub const TYPE_ID: u64 = 0xc2f8_c20c_293e_5319; + } +} +pub mod base64 { + pub const ID: u64 = 0xd7d879450a253e4b; + pub fn get_type() -> crate::introspect::Type { <() as crate::introspect::Introspect>::introspect() } +} +pub mod hex { + pub const ID: u64 = 0xf061e22f0ae5c7b5; + pub fn get_type() -> crate::introspect::Type { <() as crate::introspect::Introspect>::introspect() } +} +pub mod notification { + pub const ID: u64 = 0xa0a054dea32fd98c; + pub fn get_type() -> crate::introspect::Type { <() as crate::introspect::Introspect>::introspect() } +} diff --git a/capnp/src/lib.rs b/capnp/src/lib.rs index 9a21f8fb4..67a0d6738 100644 --- a/capnp/src/lib.rs +++ b/capnp/src/lib.rs @@ -37,6 +37,8 @@ extern crate alloc; /// [schema.capnp](https://github.com/capnproto/capnproto/blob/master/c%2B%2B/src/capnp/schema.capnp). pub mod schema_capnp; +pub mod json_capnp; + pub mod any_pointer; pub mod any_pointer_list; pub mod capability; @@ -50,6 +52,7 @@ pub mod dynamic_value; pub mod enum_list; pub mod introspect; pub mod io; +pub mod json; pub mod list_list; pub mod message; pub mod primitive_list; diff --git a/capnpc/Cargo.toml b/capnpc/Cargo.toml index 07b0e3deb..0ca61ecd0 100644 --- a/capnpc/Cargo.toml +++ b/capnpc/Cargo.toml @@ -23,7 +23,6 @@ path = "src/capnpc-rust.rs" name = "capnpc-rust-bootstrap" path = "src/capnpc-rust-bootstrap.rs" - [dependencies.capnp] version = "0.23.0" path = "../capnp" diff --git a/capnpc/test/build.rs b/capnpc/test/build.rs index d40690898..2f9571d7a 100644 --- a/capnpc/test/build.rs +++ b/capnpc/test/build.rs @@ -1,6 +1,7 @@ fn main() { capnpc::CompilerCommand::new() .crate_provides("external_crate", [0xe6f94f52f7be8fe2]) + .crate_provides("capnp", [0x8ef99297a43a5e34]) // json.capnp .file("test.capnp") .file("in-submodule.capnp") .file("in-other-submodule.capnp") diff --git a/capnpc/test/json.rs b/capnpc/test/json.rs new file mode 100644 index 000000000..065802b5d --- /dev/null +++ b/capnpc/test/json.rs @@ -0,0 +1,243 @@ +// Copyright (c) 2025 Ben Jackson [puremourning@gmail.com] and Cap'n Proto contributors +// Licensed under the MIT License: +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. + +use crate::test_capnp::{ + test_json_flatten_union, test_json_types, test_union, test_unnamed_union, TestEnum, +}; +use capnp::dynamic_value; +use capnp::message::{self}; + +use capnp::json::{self}; + +// Primitive and Pointer field encoding + +#[test] +fn test_encode_json_types_default() { + let mut builder = message::Builder::new_default(); + let root: test_json_types::Builder<'_> = builder.init_root(); + let root: dynamic_value::Builder<'_> = root.into(); + + let msg = root.into_reader(); + let json_str = json::to_json(msg).unwrap(); + let expected = r#"{"voidField":null,"boolField":false,"int8Field":0,"int16Field":0,"int32Field":0,"int64Field":0,"uInt8Field":0,"uInt16Field":0,"uInt32Field":0,"uInt64Field":0,"float32Field":0,"float64Field":0,"enumField":"foo"}"#; + assert_eq!(expected, json_str); +} + +#[test] +fn test_encode_all_json_types() { + let mut builder = message::Builder::new_default(); + let mut root: test_json_types::Builder<'_> = builder.init_root(); + root.set_int8_field(-8); + root.set_int16_field(-16); + root.set_int32_field(-32); + root.set_int64_field(-64); + root.set_u_int8_field(8); + root.set_u_int16_field(16); + root.set_u_int32_field(32); + root.set_u_int64_field(64); + root.set_bool_field(true); + root.set_void_field(()); + root.set_text_field("hello"); + root.set_float32_field(1.32); + root.set_float64_field(1.64); + root.set_data_field(&[0xde, 0xad, 0xbe, 0xef, 0xca, 0xfe, 0xba, 0xbe]); + root.set_base64_field(&[0xde, 0xad, 0xbe, 0xef, 0xca, 0xfe, 0xba, 0xbe]); + root.set_hex_field(&[0xde, 0xad, 0xbe, 0xef, 0xca, 0xfe, 0xba, 0xbe]); + { + let mut embedded = root.reborrow().init_struct_field(); + let mut text_list = embedded.reborrow().init_text_list(2); + text_list.set(0, "frist"); + text_list.set(1, "segund"); + embedded.set_text_field("inner"); + let mut hex_list = embedded.reborrow().init_hex_list(2); + hex_list.set(0, &[0xde, 0xad, 0xbe, 0xef]); + hex_list.set(1, &[0xba, 0xdf, 0x00, 0xd0]); + let mut based_list = embedded.reborrow().init_base64_list(2); + based_list.set(0, &[0xde, 0xad, 0xbe, 0xef]); + based_list.set(1, &[0xba, 0xdf, 0x00, 0xd0]); + } + root.set_enum_field(TestEnum::Quux); + { + let mut enum_list = root.reborrow().init_enum_list(3); + enum_list.set(0, TestEnum::Foo); + enum_list.set(1, TestEnum::Bar); + enum_list.set(2, TestEnum::Garply); + } + + let root: dynamic_value::Builder<'_> = root.into(); + + let msg = root.into_reader(); + let json_str = json::to_json(msg).unwrap(); + let expected = concat!( + "{", + r#""voidField":null,"#, + r#""boolField":true,"#, + r#""int8Field":-8,"#, + r#""int16Field":-16,"#, + r#""int32Field":-32,"#, + r#""int64Field":-64,"#, + r#""uInt8Field":8,"#, + r#""uInt16Field":16,"#, + r#""uInt32Field":32,"#, + r#""uInt64Field":64,"#, + r#""float32Field":1.3200000524520874,"#, + r#""float64Field":1.64,"#, + r#""textField":"hello","#, + r#""dataField":[222,173,190,239,202,254,186,190],"#, + r#""base64Field":"3q2+78r+ur4=","#, + r#""hexField":"deadbeefcafebabe","#, + r#""structField":{"#, + r#""voidField":null,"#, + r#""boolField":false,"#, + r#""int8Field":0,"#, + r#""int16Field":0,"#, + r#""int32Field":0,"#, + r#""int64Field":0,"#, + r#""uInt8Field":0,"#, + r#""uInt16Field":0,"#, + r#""uInt32Field":0,"#, + r#""uInt64Field":0,"#, + r#""float32Field":0,"#, + r#""float64Field":0,"#, + r#""textField":"inner","#, + r#""enumField":"foo","#, + r#""textList":["frist","segund"],"#, + r#""base64List":["3q2+7w==","ut8A0A=="],"#, + r#""hexList":["deadbeef","badf00d0"]"#, + "},", + r#""enumField":"quux","#, + r#""enumList":["foo","bar","garply"]"#, + "}" + ); + assert_eq!(expected, json_str); +} + +#[test] +fn test_integer_encoding() {} + +#[test] +fn test_float_encoding() {} + +#[test] +fn test_hex_encoding() {} + +#[test] +fn test_base64_encoding() {} + +#[test] +fn test_string_encoding() {} + +#[test] +fn test_array_encoding() {} + +// Union encoding with flattening + +#[test] +fn test_named_union_non_flattened() { + let mut builder = message::Builder::new_default(); + let mut root: test_union::Builder<'_> = builder.init_root(); + root.set_bit0(true); + root.set_bit2(false); + root.set_bit3(true); + root.set_bit4(false); + root.set_bit5(true); + root.set_bit6(false); + root.set_bit7(true); + root.set_byte0(0xAA); + let mut union0 = root.reborrow().init_union0(); + union0.set_u0f0sp("not this one"); + union0.set_u0f0s16(-12345); + + let root: dynamic_value::Builder<'_> = root.into(); + let msg = root.into_reader(); + let json_str = json::to_json(msg).unwrap(); + + let expected = concat!( + "{", + r#""union0":{"u0f0s16":-12345},"#, + r#""union1":{"u1f0s0":null},"#, + r#""union2":{"u2f0s1":false},"#, + r#""union3":{"u3f0s1":false},"#, + r#""bit0":true,"#, + r#""bit2":false,"#, + r#""bit3":true,"#, + r#""bit4":false,"#, + r#""bit5":true,"#, + r#""bit6":false,"#, + r#""bit7":true,"#, + r#""byte0":170"#, + "}", + ); + + assert_eq!(expected, json_str); +} + +#[test] +fn test_unnamed_union() { + let mut builder = message::Builder::new_default(); + let mut root: test_unnamed_union::Builder<'_> = builder.init_root(); + root.set_before("before"); + root.set_middle(1234); + root.set_after("after"); + root.set_foo(16); + root.set_bar(32); + let root: dynamic_value::Builder<'_> = root.into(); + let msg = root.into_reader(); + let json_str = json::to_json(msg).unwrap(); + let expected = concat!( + "{", + r#""before":"before","#, + r#""middle":1234,"#, + r#""bar":32,"#, + r#""after":"after""#, + "}", + ); + assert_eq!(expected, json_str); +} + +#[test] +fn test_named_union_flattened() { + let mut builder = message::Builder::new_default(); + let mut root: test_json_flatten_union::Builder<'_> = builder.init_root(); + root.set_before("before"); + root.set_middle(1234); + root.set_after("after"); + let mut maybe = root.reborrow().init_maybe(); + maybe.set_foo(16); + maybe.set_bar(32); + + let root: dynamic_value::Builder<'_> = root.into(); + let msg = root.into_reader(); + let json_str = json::to_json(msg).unwrap(); + let expected = concat!( + "{", + r#""before":"before","#, + r#""maybe_bar":32,"#, + r#""middle":1234,"#, + r#""after":"after","#, + r#""foo":0,"#, + r#""bar":0,"#, + r#""nested_baz":0,"#, + r#""baz":0"#, + "}", + ); + assert_eq!(expected, json_str); +} diff --git a/capnpc/test/test.capnp b/capnpc/test/test.capnp index d8840052a..ef7527c27 100644 --- a/capnpc/test/test.capnp +++ b/capnpc/test/test.capnp @@ -24,6 +24,7 @@ using Rust = import "rust.capnp"; using External = import "./external-crate/external.capnp"; +using Json = import "/capnp/compat/json.capnp"; # The test case is that this builds. This ensure we're able to refer to a struct # (external_capnp::opts) in the generated code. @@ -865,3 +866,85 @@ struct Issue260(T, Q) { interface TestStream { send @0 (data : Data) -> stream; } + +struct TestJsonTypes { + voidField @0 : Void; + boolField @1 : Bool; + int8Field @2 : Int8; + int16Field @3 : Int16; + int32Field @4 : Int32; + int64Field @5 : Int64; + uInt8Field @6 : UInt8; + uInt16Field @7 : UInt16; + uInt32Field @8 : UInt32; + uInt64Field @9 : UInt64; + float32Field @10 : Float32; + float64Field @11 : Float64; + textField @12 : Text; + dataField @13 : Data; + base64Field @14 : Data $Json.base64; + hexField @15 : Data $Json.hex; + structField @16 : TestJsonTypes; + enumField @17 : TestEnum; + + voidList @18 : List(Void); + boolList @19 : List(Bool); + int8List @20 : List(Int8); + int16List @21 : List(Int16); + int32List @22 : List(Int32); + int64List @23 : List(Int64); + uInt8List @24 : List(UInt8); + uInt16List @25 : List(UInt16); + uInt32List @26 : List(UInt32); + uInt64List @27 : List(UInt64); + float32List @28 : List(Float32); + float64List @29 : List(Float64); + textList @30 : List(Text); + dataList @31 : List(Data); + base64List @32 : List(Data) $Json.base64; + hexList @33 : List(Data) $Json.hex; + structList @34 : List(TestJsonTypes); + enumList @35 : List(TestEnum); +} + +struct TestJsonFlattenUnion { + before @0 :Text; + + maybe :union $Json.flatten("maybe_") { # field, group, union to test + foo @1 :UInt16; + bar @3 :UInt32; + } + + groupie :group $Json.flatten() { + foo @5 :UInt16; + bar @6 :UInt32; + prefixed :group $Json.flatten("nested_") { + baz @7 :UInt8; + } + nested :group $Json.flatten() { + baz @8 :UInt8; + } + } + + middle @2 :UInt16; + + after @4 :Text; +} + +struct TestJsonDiscriminatedUnion $Json.discriminator() { + before @0 :Text; + + maybe :union $Json.flatten("maybe_") $Json.discriminator() { # field, group, union to test + foo @1 :UInt16; + bar @3 :UInt32; + } + + middle @2 :UInt16; + + after @4 :Text; + + union { + a @5 :UInt8; + b @6 :Text; + } +} diff --git a/capnpc/test/test.rs b/capnpc/test/test.rs index 26ace4153..5b2037b85 100644 --- a/capnpc/test/test.rs +++ b/capnpc/test/test.rs @@ -59,6 +59,9 @@ mod test_util; #[cfg(test)] mod dynamic; +#[cfg(test)] +mod json; + #[cfg(test)] mod tests { use crate::test_util::{init_test_message, CheckTestMessage}; From 74604e233cdf83585c886886e12c1965636fe9e1 Mon Sep 17 00:00:00 2001 From: Ben Jackson Date: Tue, 25 Nov 2025 22:10:52 +0000 Subject: [PATCH 02/29] Implement support for distriminators and nested prefixes; use the test schema from c++ repo --- capnp/src/json.rs | 80 +++++++++++++++++++---- capnpc/test/build.rs | 1 + capnpc/test/json-test.capnp | 123 ++++++++++++++++++++++++++++++++++++ capnpc/test/json.rs | 92 +++++++++++++++++++++++++++ capnpc/test/test.capnp | 18 ------ capnpc/test/test.rs | 1 + 6 files changed, 284 insertions(+), 31 deletions(-) create mode 100644 capnpc/test/json-test.capnp diff --git a/capnp/src/json.rs b/capnp/src/json.rs index 6764af3c6..26103badf 100644 --- a/capnp/src/json.rs +++ b/capnp/src/json.rs @@ -10,8 +10,6 @@ // does that work in rust without specdialization? // -// TODO: Support for discriminators - pub fn to_json(reader: crate::dynamic_value::Reader<'_>) -> crate::Result { let mut writer = std::io::Cursor::new(Vec::with_capacity(4096)); serialize_json_to(&mut writer, reader)?; @@ -26,6 +24,7 @@ where W: std::io::Write, { let meta = EncodingOptions { + prefix: "".into(), name: "", flatten: None, discriminator: None, @@ -46,14 +45,16 @@ enum DataEncoding { #[derive(Debug)] struct EncodingOptions<'schema> { + prefix: String, name: &'schema str, flatten: Option>, + discriminator: Option>, data_encoding: DataEncoding, } impl<'schema> EncodingOptions<'schema> { - fn from_field(field: &crate::schema::Field) -> crate::Result { + fn from_field(prefix: String, field: &crate::schema::Field) -> crate::Result { let field_name = match field .get_annotations()? .iter() @@ -119,6 +120,7 @@ impl<'schema> EncodingOptions<'schema> { None => None, }; Ok(Self { + prefix, name: field_name, flatten: flatten_options, discriminator: discriminator_options, @@ -244,11 +246,36 @@ fn write_object<'reader, W: std::io::Write>( meta: &EncodingOptions<'_>, ) -> crate::Result<()> { let (flatten, field_prefix) = if let Some(flatten_options) = &meta.flatten { - (true, flatten_options.get_prefix()?.to_str()?) + ( + true, + format!("{}{}", meta.prefix, flatten_options.get_prefix()?.to_str()?), + ) } else { - (false, "") + (false, "".into()) }; + // Comment copied verbatim from the Cap'n Proto C++ implementation: + // There are two cases of unions: + // * Named unions, which are special cases of named groups. In this case, the union may be + // annotated by annotating the field. In this case, we receive a non-null `discriminator` + // as a constructor parameter, and schemaProto.getAnnotations() must be empty because + // it's not possible to annotate a group's type (because the type is anonymous). + // * Unnamed unions, of which there can only be one in any particular scope. In this case, + // the parent struct type itself is annotated. + // So if we received `null` as the constructor parameter, check for annotations on the struct + // type. + let struct_discriminator = reader + .get_schema() + .get_annotations()? + .iter() + .find(|a| a.get_id() == json_capnp::discriminator::ID) + .and_then(|annotation| { + annotation + .get_value() + .ok() + .map(|v| v.downcast_struct::()) + }); + if !flatten { write!(writer, "{{")?; } @@ -257,32 +284,59 @@ fn write_object<'reader, W: std::io::Write>( if !reader.has(field)? { continue; } + let field_meta = EncodingOptions::from_field(field_prefix.clone(), &field)?; + let mut value_name = field_meta.name; if field.get_proto().get_discriminant_value() != crate::schema_capnp::field::NO_DISCRIMINANT { if let Some(active_union_member) = reader.which()? { + let active_union_member_meta = + EncodingOptions::from_field(field_prefix.clone(), &active_union_member)?; if field.get_proto().get_discriminant_value() != active_union_member.get_proto().get_discriminant_value() { // Skip union members that are not set. continue; } - // TODO: there's a specific annotation 'discriminator' which says to - // write out the discriminant field name as a field in the object, - // allowing to use flatten on the union member (only for named union - // fields). + let discriminator = match meta.discriminator { + Some(ref d) => Some(d), + None => struct_discriminator.as_ref(), + }; + if let Some(discriminator) = discriminator { + // write out the discriminator + if !first { + write!(writer, ",")?; + } + first = false; + let discriminator_name = if discriminator.has_name() { + discriminator.get_name()?.to_str()? + } else { + meta.name + }; + if discriminator.has_value_name() { + value_name = discriminator.get_value_name()?.to_str()?; + } + + write_string( + writer, + format!("{}{}", field_prefix, discriminator_name).as_str(), + )?; + write!(writer, ":")?; + write_string(writer, active_union_member_meta.name)?; + } + // TODO: value_name. should that just change meta.name printed + // below? } } - let meta = EncodingOptions::from_field(&field)?; if !first { write!(writer, ",")?; } first = false; - if meta.flatten.is_none() { - write_string(writer, format!("{}{}", field_prefix, meta.name).as_str())?; + if field_meta.flatten.is_none() { + write_string(writer, format!("{}{}", field_prefix, value_name).as_str())?; write!(writer, ":")?; } let field_value = reader.get(field)?; - serialize_value_to(writer, field_value, &meta)?; + serialize_value_to(writer, field_value, &field_meta)?; } if !flatten { write!(writer, "}}")?; diff --git a/capnpc/test/build.rs b/capnpc/test/build.rs index 2f9571d7a..37e1250a9 100644 --- a/capnpc/test/build.rs +++ b/capnpc/test/build.rs @@ -3,6 +3,7 @@ fn main() { .crate_provides("external_crate", [0xe6f94f52f7be8fe2]) .crate_provides("capnp", [0x8ef99297a43a5e34]) // json.capnp .file("test.capnp") + .file("json-test.capnp") .file("in-submodule.capnp") .file("in-other-submodule.capnp") .file("schema/test-in-dir.capnp") diff --git a/capnpc/test/json-test.capnp b/capnpc/test/json-test.capnp new file mode 100644 index 000000000..4406fd24b --- /dev/null +++ b/capnpc/test/json-test.capnp @@ -0,0 +1,123 @@ +# Copyright (c) 2018 Cloudflare, Inc. and contributors +# Licensed under the MIT License: +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in +# all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +# THE SOFTWARE. + +@0xc9d405cf4333e4c9; + +using Json = import "/capnp/compat/json.capnp"; + +$import "/capnp/c++.capnp".namespace("capnp"); + +struct TestJsonAnnotations { + someField @0 :Text $Json.name("names-can_contain!anything Really"); + + aGroup :group $Json.flatten() { + flatFoo @1 :UInt32; + flatBar @2 :Text; + flatBaz :group $Json.name("renamed-flatBaz") { + hello @3 :Bool; + } + doubleFlat :group $Json.flatten() { + flatQux @4 :Text; + } + } + + prefixedGroup :group $Json.flatten(prefix = "pfx.") { + foo @5 :Text; + bar @6 :UInt32 $Json.name("renamed-bar"); + baz :group { + hello @7 :Bool; + } + morePrefix :group $Json.flatten(prefix = "xfp.") { + qux @8 :Text; + } + } + + aUnion :union $Json.flatten() $Json.discriminator(name = "union-type") { + foo :group $Json.flatten() { + fooMember @9 :Text; + multiMember @10 :UInt32; + } + bar :group $Json.flatten() $Json.name("renamed-bar") { + barMember @11 :UInt32; + multiMember @12 :Text; + } + } + + dependency @13 :TestJsonAnnotations2; + # To test that dependencies are loaded even if not flattened. + + simpleGroup :group { + # To test that group types are loaded even if not flattened. + grault @14 :Text $Json.name("renamed-grault"); + } + + enums @15 :List(TestJsonAnnotatedEnum); + + innerJson @16 :Json.Value; + + customFieldHandler @17 :Text; + + testBase64 @18 :Data $Json.base64; + testHex @19 :Data $Json.hex; + + bUnion :union $Json.flatten() $Json.discriminator(valueName = "bValue") { + foo @20 :Text; + bar @21 :UInt32 $Json.name("renamed-bar"); + } + + externalUnion @22 :TestJsonAnnotations3; + + unionWithVoid :union $Json.discriminator(name = "type") { + intValue @23 :UInt32; + voidValue @24 :Void; + textValue @25 :Text; + } +} + +struct TestJsonAnnotations2 { + foo @0 :Text $Json.name("renamed-foo"); + cycle @1 :TestJsonAnnotations; +} + +struct TestJsonAnnotations3 $Json.discriminator(name = "type") { + union { + foo @0 :UInt32; + bar @1 :TestFlattenedStruct $Json.flatten(); + } +} + +struct TestFlattenedStruct { + value @0 :Text; +} + +enum TestJsonAnnotatedEnum { + foo @0; + bar @1 $Json.name("renamed-bar"); + baz @2 $Json.name("renamed-baz"); + qux @3; +} + +struct TestBase64Union { + union { + foo @0 :Data $Json.base64; + bar @1 :Text; + } +} diff --git a/capnpc/test/json.rs b/capnpc/test/json.rs index 065802b5d..d6e5e62ba 100644 --- a/capnpc/test/json.rs +++ b/capnpc/test/json.rs @@ -19,6 +19,7 @@ // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. +use crate::json_test_capnp::test_json_annotations; use crate::test_capnp::{ test_json_flatten_union, test_json_types, test_union, test_unnamed_union, TestEnum, }; @@ -241,3 +242,94 @@ fn test_named_union_flattened() { ); assert_eq!(expected, json_str); } + +#[test] +fn test_discriminated_union() { + let mut builder = message::Builder::new_default(); + let mut root: test_json_annotations::Builder<'_> = builder.init_root(); + + let mut expected = String::from("{"); + + root.set_some_field("Some Field"); + expected.push_str(r#""names-can_contain!anything Really":"Some Field","#); + + { + let mut a_group = root.reborrow().init_a_group(); + // a_group is flattenned + a_group.set_flat_foo(0xF00); + expected.push_str(r#""flatFoo":3840,"#); + + a_group.set_flat_bar("0xBaa"); + expected.push_str(r#""flatBar":"0xBaa","#); + + a_group.reborrow().init_flat_baz().set_hello(true); + expected.push_str(r#""renamed-flatBaz":{"hello":true},"#); + + a_group.reborrow().init_double_flat().set_flat_qux("Qux"); + expected.push_str(r#""flatQux":"Qux","#); + } + + { + let mut prefixed_group = root.reborrow().init_prefixed_group(); + prefixed_group.set_foo("Foo"); + expected.push_str(r#""pfx.foo":"Foo","#); + + prefixed_group.set_bar(0xBAA); + expected.push_str(r#""pfx.renamed-bar":2986,"#); + + prefixed_group.reborrow().init_baz().set_hello(false); + expected.push_str(r#""pfx.baz":{"hello":false},"#); + + prefixed_group.reborrow().init_more_prefix().set_qux("Qux"); + expected.push_str(r#""pfx.xfp.qux":"Qux","#); + } + + { + let mut a_union_bar = root.reborrow().init_a_union().init_bar(); + expected.push_str(r#""union-type":"renamed-bar","#); + a_union_bar.set_bar_member(0xAAB); + expected.push_str(r#""barMember":2731,"#); + a_union_bar.set_multi_member("Member"); + expected.push_str(r#""multiMember":"Member","#); + } + + { + let mut dependency = root.reborrow().init_dependency(); + dependency.set_foo("dep-foo"); + expected.push_str(r#""dependency":{"renamed-foo":"dep-foo"},"#); + } + + { + let mut simple_group = root.reborrow().init_simple_group(); + simple_group.set_grault("grault"); + expected.push_str(r#""simpleGroup":{"renamed-grault":"grault"},"#); + } + + { + let mut b_union = root.reborrow().init_b_union(); + expected.push_str(r#""bUnion":"foo","#); + b_union.set_foo("b-free"); + expected.push_str(r#""bValue":"b-free","#); + } + + { + let mut external_union = root.reborrow().init_external_union(); + external_union.reborrow().init_bar().set_value("Value"); + expected.push_str(r#""externalUnion":{"type":"bar","value":"Value"},"#); + } + + { + let mut union_with_void = root.reborrow().init_union_with_void(); + union_with_void.set_void_value(()); + expected.push_str(r#""unionWithVoid":{"type":"voidValue","voidValue":null},"#); + } + + expected.pop(); // Remove trailing comma + expected.push('}'); + + let root: dynamic_value::Builder<'_> = root.into(); + let msg = root.into_reader(); + let json_str = json::to_json(msg).unwrap(); + assert_eq!(expected, json_str); +} + diff --git a/capnpc/test/test.capnp b/capnpc/test/test.capnp index ef7527c27..0ce26d52f 100644 --- a/capnpc/test/test.capnp +++ b/capnpc/test/test.capnp @@ -930,21 +930,3 @@ struct TestJsonFlattenUnion { after @4 :Text; } - -struct TestJsonDiscriminatedUnion $Json.discriminator() { - before @0 :Text; - - maybe :union $Json.flatten("maybe_") $Json.discriminator() { # field, group, union to test - foo @1 :UInt16; - bar @3 :UInt32; - } - - middle @2 :UInt16; - - after @4 :Text; - - union { - a @5 :UInt8; - b @6 :Text; - } -} diff --git a/capnpc/test/test.rs b/capnpc/test/test.rs index 5b2037b85..368ce5fd7 100644 --- a/capnpc/test/test.rs +++ b/capnpc/test/test.rs @@ -24,6 +24,7 @@ #![allow(clippy::bool_assert_comparison, clippy::approx_constant)] capnp::generated_code!(pub mod test_capnp); +capnp::generated_code!(pub mod json_test_capnp); pub mod foo { pub mod bar { From 07575a035fdff32cf5ecb3db328e3b98f18a56f9 Mon Sep 17 00:00:00 2001 From: Ben Jackson Date: Tue, 25 Nov 2025 22:35:58 +0000 Subject: [PATCH 03/29] Implement renaming of enum values --- capnp/src/json.rs | 42 +++++++++++++++++++++++++++++------------- capnpc/test/json.rs | 16 ++++++++++++---- 2 files changed, 41 insertions(+), 17 deletions(-) diff --git a/capnp/src/json.rs b/capnp/src/json.rs index 26103badf..b6c406d70 100644 --- a/capnp/src/json.rs +++ b/capnp/src/json.rs @@ -24,7 +24,7 @@ where W: std::io::Write, { let meta = EncodingOptions { - prefix: "".into(), + prefix: &std::borrow::Cow::Borrowed(""), name: "", flatten: None, discriminator: None, @@ -44,17 +44,19 @@ enum DataEncoding { } #[derive(Debug)] -struct EncodingOptions<'schema> { - prefix: String, +struct EncodingOptions<'schema, 'prefix> { + prefix: &'prefix std::borrow::Cow<'schema, str>, name: &'schema str, flatten: Option>, - discriminator: Option>, data_encoding: DataEncoding, } -impl<'schema> EncodingOptions<'schema> { - fn from_field(prefix: String, field: &crate::schema::Field) -> crate::Result { +impl<'schema, 'prefix> EncodingOptions<'schema, 'prefix> { + fn from_field( + prefix: &'prefix std::borrow::Cow<'schema, str>, + field: &crate::schema::Field, + ) -> crate::Result { let field_name = match field .get_annotations()? .iter() @@ -132,7 +134,7 @@ impl<'schema> EncodingOptions<'schema> { fn serialize_value_to( writer: &mut W, reader: crate::dynamic_value::Reader<'_>, - meta: &EncodingOptions<'_>, + meta: &EncodingOptions<'_, '_>, ) -> crate::Result<()> where W: std::io::Write, @@ -157,7 +159,17 @@ where crate::dynamic_value::Reader::Float64(value) => write_float_number(writer, value), crate::dynamic_value::Reader::Enum(value) => { if let Some(enumerant) = value.get_enumerant()? { - write_string(writer, enumerant.get_proto().get_name()?.to_str()?) + let value = enumerant + .get_annotations()? + .iter() + .find(|a| a.get_id() == json_capnp::name::ID) + .and_then(|a| { + a.get_value() + .ok() + .and_then(|v| v.downcast::().to_str().ok()) + }) + .unwrap_or(enumerant.get_proto().get_name()?.to_str()?); + write_string(writer, value) } else { write_unsigned_number(writer, value.get_value() as u64) } @@ -243,15 +255,19 @@ where fn write_object<'reader, W: std::io::Write>( writer: &mut W, reader: crate::dynamic_struct::Reader<'reader>, - meta: &EncodingOptions<'_>, + meta: &EncodingOptions<'_, '_>, ) -> crate::Result<()> { let (flatten, field_prefix) = if let Some(flatten_options) = &meta.flatten { ( true, - format!("{}{}", meta.prefix, flatten_options.get_prefix()?.to_str()?), + std::borrow::Cow::Owned(format!( + "{}{}", + meta.prefix, + flatten_options.get_prefix()?.to_str()? + )), ) } else { - (false, "".into()) + (false, std::borrow::Cow::Borrowed("")) }; // Comment copied verbatim from the Cap'n Proto C++ implementation: @@ -284,13 +300,13 @@ fn write_object<'reader, W: std::io::Write>( if !reader.has(field)? { continue; } - let field_meta = EncodingOptions::from_field(field_prefix.clone(), &field)?; + let field_meta = EncodingOptions::from_field(&field_prefix, &field)?; let mut value_name = field_meta.name; if field.get_proto().get_discriminant_value() != crate::schema_capnp::field::NO_DISCRIMINANT { if let Some(active_union_member) = reader.which()? { let active_union_member_meta = - EncodingOptions::from_field(field_prefix.clone(), &active_union_member)?; + EncodingOptions::from_field(&field_prefix, &active_union_member)?; if field.get_proto().get_discriminant_value() != active_union_member.get_proto().get_discriminant_value() { diff --git a/capnpc/test/json.rs b/capnpc/test/json.rs index d6e5e62ba..63940d503 100644 --- a/capnpc/test/json.rs +++ b/capnpc/test/json.rs @@ -305,11 +305,20 @@ fn test_discriminated_union() { expected.push_str(r#""simpleGroup":{"renamed-grault":"grault"},"#); } + { + let mut e = root.reborrow().init_enums(4); + e.set(0, crate::json_test_capnp::TestJsonAnnotatedEnum::Foo); + e.set(1, crate::json_test_capnp::TestJsonAnnotatedEnum::Bar); + e.set(2, crate::json_test_capnp::TestJsonAnnotatedEnum::Baz); + e.set(3, crate::json_test_capnp::TestJsonAnnotatedEnum::Qux); + expected.push_str(r#""enums":["foo","renamed-bar","renamed-baz","qux"],"#); + } + { let mut b_union = root.reborrow().init_b_union(); - expected.push_str(r#""bUnion":"foo","#); - b_union.set_foo("b-free"); - expected.push_str(r#""bValue":"b-free","#); + expected.push_str(r#""bUnion":"renamed-bar","#); + b_union.set_bar(100); + expected.push_str(r#""bValue":100,"#); } { @@ -332,4 +341,3 @@ fn test_discriminated_union() { let json_str = json::to_json(msg).unwrap(); assert_eq!(expected, json_str); } - From ed499bf6f8f1934d9a38614d78c8924d8dbdd2d4 Mon Sep 17 00:00:00 2001 From: Ben Jackson Date: Tue, 25 Nov 2025 23:02:08 +0000 Subject: [PATCH 04/29] Test Inf/NaN --- capnp/src/json.rs | 9 +++++--- capnpc/test/json.rs | 50 +++++++++++++++++++++++++++++---------------- 2 files changed, 38 insertions(+), 21 deletions(-) diff --git a/capnp/src/json.rs b/capnp/src/json.rs index b6c406d70..9cd092f48 100644 --- a/capnp/src/json.rs +++ b/capnp/src/json.rs @@ -166,10 +166,10 @@ where .and_then(|a| { a.get_value() .ok() - .and_then(|v| v.downcast::().to_str().ok()) + .map(|v| v.downcast::().to_str()) }) - .unwrap_or(enumerant.get_proto().get_name()?.to_str()?); - write_string(writer, value) + .unwrap_or(enumerant.get_proto().get_name()?.to_str()); + write_string(writer, value?) } else { write_unsigned_number(writer, value.get_value() as u64) } @@ -198,6 +198,9 @@ fn write_signed_number(writer: &mut W, value: i64) -> crate:: } fn write_float_number(writer: &mut W, value: f64) -> crate::Result<()> { + // From the C++ codec comments: + // Inf, -inf and NaN are not allowed in the JSON spec. Storing into string. + if value.is_finite() { write!(writer, "{}", value)?; } else if value.is_nan() { diff --git a/capnpc/test/json.rs b/capnpc/test/json.rs index 63940d503..76a6644ab 100644 --- a/capnpc/test/json.rs +++ b/capnpc/test/json.rs @@ -82,6 +82,18 @@ fn test_encode_all_json_types() { enum_list.set(1, TestEnum::Bar); enum_list.set(2, TestEnum::Garply); } + { + let mut floats = root.reborrow().init_float32_list(3); + floats.set(0, f32::NAN); + floats.set(1, f32::INFINITY); + floats.set(2, f32::NEG_INFINITY); + } + { + let mut floats = root.reborrow().init_float64_list(3); + floats.set(0, f64::NAN); + floats.set(1, f64::INFINITY); + floats.set(2, f64::NEG_INFINITY); + } let root: dynamic_value::Builder<'_> = root.into(); @@ -125,30 +137,14 @@ fn test_encode_all_json_types() { r#""hexList":["deadbeef","badf00d0"]"#, "},", r#""enumField":"quux","#, + r#""float32List":["NaN","Infinity","-Infinity"],"#, + r#""float64List":["NaN","Infinity","-Infinity"],"#, r#""enumList":["foo","bar","garply"]"#, "}" ); assert_eq!(expected, json_str); } -#[test] -fn test_integer_encoding() {} - -#[test] -fn test_float_encoding() {} - -#[test] -fn test_hex_encoding() {} - -#[test] -fn test_base64_encoding() {} - -#[test] -fn test_string_encoding() {} - -#[test] -fn test_array_encoding() {} - // Union encoding with flattening #[test] @@ -341,3 +337,21 @@ fn test_discriminated_union() { let json_str = json::to_json(msg).unwrap(); assert_eq!(expected, json_str); } + +#[test] +fn test_base64_union() { + let mut builder = message::Builder::new_default(); + let mut root: crate::json_test_capnp::test_base64_union::Builder<'_> = builder.init_root(); + + let mut expected = String::from("{"); + root.set_foo(&[0xde, 0xad, 0xbe, 0xef]); + expected.push_str(r#""foo":"3q2+7w==","#); + + expected.pop(); // Remove trailing comma + expected.push('}'); + + let root: dynamic_value::Builder<'_> = root.into(); + let msg = root.into_reader(); + let json_str = json::to_json(msg).unwrap(); + assert_eq!(expected, json_str); +} From dba8cc4d3da11246369436f7be03064d2743a8b0 Mon Sep 17 00:00:00 2001 From: Ben Jackson Date: Tue, 25 Nov 2025 23:11:57 +0000 Subject: [PATCH 05/29] Test string encoding --- capnpc/test/json.rs | 35 +++++++++++++++++++++++++++++++++++ 1 file changed, 35 insertions(+) diff --git a/capnpc/test/json.rs b/capnpc/test/json.rs index 76a6644ab..a1f24bd90 100644 --- a/capnpc/test/json.rs +++ b/capnpc/test/json.rs @@ -355,3 +355,38 @@ fn test_base64_union() { let json_str = json::to_json(msg).unwrap(); assert_eq!(expected, json_str); } + +#[test] +fn test_string_encoding() { + let mut builder = message::Builder::new_default(); + let mut root: crate::json_test_capnp::test_flattened_struct::Builder<'_> = builder.init_root(); + root.set_value(""); + assert_eq!( + r#"{"value":""}"#, + json::to_json(root.reborrow_as_reader().into()).unwrap() + ); + + root.set_value("tab: \t, newline: \n, carriage return: \r, quote: \", backslash: \\"); + assert_eq!( + r#"{"value":"tab: \t, newline: \n, carriage return: \r, quote: \", backslash: \\"}"#, + json::to_json(root.reborrow_as_reader().into()).unwrap() + ); + + root.set_value("unicode: †eśt"); + assert_eq!( + r#"{"value":"unicode: †eśt"}"#, + json::to_json(root.reborrow_as_reader().into()).unwrap() + ); + + root.set_value("backspace: \u{0008}, formfeed: \u{000C}"); + assert_eq!( + r#"{"value":"backspace: \b, formfeed: \f"}"#, + json::to_json(root.reborrow_as_reader().into()).unwrap() + ); + + root.set_value("bell: \u{0007}, SOH: \u{0001}"); + assert_eq!( + r#"{"value":"bell: \u0007, SOH: \u0001"}"#, + json::to_json(root.reborrow_as_reader().into()).unwrap() + ); +} From 6da310e26173e6b7e9ca03a690ff105618d4bba6 Mon Sep 17 00:00:00 2001 From: Ben Jackson Date: Tue, 25 Nov 2025 23:27:45 +0000 Subject: [PATCH 06/29] Tidy API; take any reader type --- capnp/src/json.rs | 10 +++++--- capnpc/test/json.rs | 59 ++++++++++++--------------------------------- 2 files changed, 22 insertions(+), 47 deletions(-) diff --git a/capnp/src/json.rs b/capnp/src/json.rs index 9cd092f48..fc9813a63 100644 --- a/capnp/src/json.rs +++ b/capnp/src/json.rs @@ -10,15 +10,17 @@ // does that work in rust without specdialization? // -pub fn to_json(reader: crate::dynamic_value::Reader<'_>) -> crate::Result { +pub fn to_json<'reader>( + reader: impl Into>, +) -> crate::Result { let mut writer = std::io::Cursor::new(Vec::with_capacity(4096)); serialize_json_to(&mut writer, reader)?; String::from_utf8(writer.into_inner()).map_err(|e| e.into()) } -pub fn serialize_json_to( +pub fn serialize_json_to<'reader, W>( writer: &mut W, - reader: crate::dynamic_value::Reader<'_>, + reader: impl Into>, ) -> crate::Result<()> where W: std::io::Write, @@ -30,7 +32,7 @@ where discriminator: None, data_encoding: DataEncoding::Default, }; - serialize_value_to(writer, reader, &meta) + serialize_value_to(writer, reader.into(), &meta) } use crate::json_capnp; diff --git a/capnpc/test/json.rs b/capnpc/test/json.rs index a1f24bd90..844d1c030 100644 --- a/capnpc/test/json.rs +++ b/capnpc/test/json.rs @@ -23,7 +23,6 @@ use crate::json_test_capnp::test_json_annotations; use crate::test_capnp::{ test_json_flatten_union, test_json_types, test_union, test_unnamed_union, TestEnum, }; -use capnp::dynamic_value; use capnp::message::{self}; use capnp::json::{self}; @@ -34,12 +33,8 @@ use capnp::json::{self}; fn test_encode_json_types_default() { let mut builder = message::Builder::new_default(); let root: test_json_types::Builder<'_> = builder.init_root(); - let root: dynamic_value::Builder<'_> = root.into(); - - let msg = root.into_reader(); - let json_str = json::to_json(msg).unwrap(); let expected = r#"{"voidField":null,"boolField":false,"int8Field":0,"int16Field":0,"int32Field":0,"int64Field":0,"uInt8Field":0,"uInt16Field":0,"uInt32Field":0,"uInt64Field":0,"float32Field":0,"float64Field":0,"enumField":"foo"}"#; - assert_eq!(expected, json_str); + assert_eq!(expected, json::to_json(root.reborrow_as_reader()).unwrap()); } #[test] @@ -95,10 +90,6 @@ fn test_encode_all_json_types() { floats.set(2, f64::NEG_INFINITY); } - let root: dynamic_value::Builder<'_> = root.into(); - - let msg = root.into_reader(); - let json_str = json::to_json(msg).unwrap(); let expected = concat!( "{", r#""voidField":null,"#, @@ -142,7 +133,7 @@ fn test_encode_all_json_types() { r#""enumList":["foo","bar","garply"]"#, "}" ); - assert_eq!(expected, json_str); + assert_eq!(expected, json::to_json(root.reborrow_as_reader()).unwrap()); } // Union encoding with flattening @@ -163,10 +154,6 @@ fn test_named_union_non_flattened() { union0.set_u0f0sp("not this one"); union0.set_u0f0s16(-12345); - let root: dynamic_value::Builder<'_> = root.into(); - let msg = root.into_reader(); - let json_str = json::to_json(msg).unwrap(); - let expected = concat!( "{", r#""union0":{"u0f0s16":-12345},"#, @@ -184,7 +171,7 @@ fn test_named_union_non_flattened() { "}", ); - assert_eq!(expected, json_str); + assert_eq!(expected, json::to_json(root.reborrow_as_reader()).unwrap()); } #[test] @@ -196,9 +183,6 @@ fn test_unnamed_union() { root.set_after("after"); root.set_foo(16); root.set_bar(32); - let root: dynamic_value::Builder<'_> = root.into(); - let msg = root.into_reader(); - let json_str = json::to_json(msg).unwrap(); let expected = concat!( "{", r#""before":"before","#, @@ -207,7 +191,7 @@ fn test_unnamed_union() { r#""after":"after""#, "}", ); - assert_eq!(expected, json_str); + assert_eq!(expected, json::to_json(root.reborrow_as_reader()).unwrap()); } #[test] @@ -221,9 +205,6 @@ fn test_named_union_flattened() { maybe.set_foo(16); maybe.set_bar(32); - let root: dynamic_value::Builder<'_> = root.into(); - let msg = root.into_reader(); - let json_str = json::to_json(msg).unwrap(); let expected = concat!( "{", r#""before":"before","#, @@ -236,7 +217,7 @@ fn test_named_union_flattened() { r#""baz":0"#, "}", ); - assert_eq!(expected, json_str); + assert_eq!(expected, json::to_json(root.reborrow_as_reader()).unwrap()); } #[test] @@ -332,10 +313,7 @@ fn test_discriminated_union() { expected.pop(); // Remove trailing comma expected.push('}'); - let root: dynamic_value::Builder<'_> = root.into(); - let msg = root.into_reader(); - let json_str = json::to_json(msg).unwrap(); - assert_eq!(expected, json_str); + assert_eq!(expected, json::to_json(root.reborrow_as_reader()).unwrap()); } #[test] @@ -343,50 +321,45 @@ fn test_base64_union() { let mut builder = message::Builder::new_default(); let mut root: crate::json_test_capnp::test_base64_union::Builder<'_> = builder.init_root(); - let mut expected = String::from("{"); root.set_foo(&[0xde, 0xad, 0xbe, 0xef]); - expected.push_str(r#""foo":"3q2+7w==","#); - - expected.pop(); // Remove trailing comma - expected.push('}'); - - let root: dynamic_value::Builder<'_> = root.into(); - let msg = root.into_reader(); - let json_str = json::to_json(msg).unwrap(); - assert_eq!(expected, json_str); + assert_eq!( + r#"{"foo":"3q2+7w=="}"#, + json::to_json(root.reborrow_as_reader()).unwrap() + ); } #[test] fn test_string_encoding() { let mut builder = message::Builder::new_default(); let mut root: crate::json_test_capnp::test_flattened_struct::Builder<'_> = builder.init_root(); + root.set_value(""); assert_eq!( r#"{"value":""}"#, - json::to_json(root.reborrow_as_reader().into()).unwrap() + json::to_json(root.reborrow_as_reader()).unwrap() ); root.set_value("tab: \t, newline: \n, carriage return: \r, quote: \", backslash: \\"); assert_eq!( r#"{"value":"tab: \t, newline: \n, carriage return: \r, quote: \", backslash: \\"}"#, - json::to_json(root.reborrow_as_reader().into()).unwrap() + json::to_json(root.reborrow_as_reader()).unwrap() ); root.set_value("unicode: †eśt"); assert_eq!( r#"{"value":"unicode: †eśt"}"#, - json::to_json(root.reborrow_as_reader().into()).unwrap() + json::to_json(root.reborrow_as_reader()).unwrap() ); root.set_value("backspace: \u{0008}, formfeed: \u{000C}"); assert_eq!( r#"{"value":"backspace: \b, formfeed: \f"}"#, - json::to_json(root.reborrow_as_reader().into()).unwrap() + json::to_json(root.reborrow_as_reader()).unwrap() ); root.set_value("bell: \u{0007}, SOH: \u{0001}"); assert_eq!( r#"{"value":"bell: \u0007, SOH: \u0001"}"#, - json::to_json(root.reborrow_as_reader().into()).unwrap() + json::to_json(root.reborrow_as_reader()).unwrap() ); } From 2a9ca68a2fbc80a270f7d267555ce5c90ef491ae Mon Sep 17 00:00:00 2001 From: Ben Jackson Date: Tue, 25 Nov 2025 23:53:38 +0000 Subject: [PATCH 07/29] Nested Data encoding --- capnp/src/json.rs | 12 +++++------- capnpc/test/json-test.capnp | 4 ++++ capnpc/test/json.rs | 24 ++++++++++++++++++++---- 3 files changed, 29 insertions(+), 11 deletions(-) diff --git a/capnp/src/json.rs b/capnp/src/json.rs index fc9813a63..816c5b7e9 100644 --- a/capnp/src/json.rs +++ b/capnp/src/json.rs @@ -86,14 +86,12 @@ impl<'schema, 'prefix> EncodingOptions<'schema, 'prefix> { }, }; if data_encoding != DataEncoding::Default { - let element_type = if let crate::introspect::TypeVariant::List(element_type) = - field.get_type().which() + let mut element_type = field.get_type(); + while let crate::introspect::TypeVariant::List(sub_element_type) = element_type.which() { - element_type.which() - } else { - field.get_type().which() - }; - if !matches!(element_type, crate::introspect::TypeVariant::Data) { + element_type = sub_element_type; + } + if !matches!(element_type.which(), crate::introspect::TypeVariant::Data) { return Err(crate::Error::failed( "base64/hex annotation can only be applied to Data fields".into(), )); diff --git a/capnpc/test/json-test.capnp b/capnpc/test/json-test.capnp index 4406fd24b..d52188063 100644 --- a/capnpc/test/json-test.capnp +++ b/capnpc/test/json-test.capnp @@ -121,3 +121,7 @@ struct TestBase64Union { bar @1 :Text; } } + +struct NestedHex { + dataAllTheWayDown @0 : List(List(Data)) $Json.hex; +} diff --git a/capnpc/test/json.rs b/capnpc/test/json.rs index 844d1c030..1f5d38025 100644 --- a/capnpc/test/json.rs +++ b/capnpc/test/json.rs @@ -23,11 +23,8 @@ use crate::json_test_capnp::test_json_annotations; use crate::test_capnp::{ test_json_flatten_union, test_json_types, test_union, test_unnamed_union, TestEnum, }; -use capnp::message::{self}; - use capnp::json::{self}; - -// Primitive and Pointer field encoding +use capnp::message::{self}; #[test] fn test_encode_json_types_default() { @@ -363,3 +360,22 @@ fn test_string_encoding() { json::to_json(root.reborrow_as_reader()).unwrap() ); } + +#[test] +fn test_nested_data_list() -> capnp::Result<()> { + let mut builder = message::Builder::new_default(); + let mut root = builder.init_root::>(); + let mut awd = root.reborrow().init_data_all_the_way_down(2); + let mut first = awd.reborrow().init(0, 2); + first.set(0, &[0xde, 0xad, 0xbe, 0xef]); + first.set(1, &[0xef, 0xbe, 0xad, 0xde]); + let mut second = awd.reborrow().init(1, 1); + second.set(0, &[0xba, 0xdf, 0x00, 0xd0]); + + assert_eq!( + r#"{"dataAllTheWayDown":[["deadbeef","efbeadde"],["badf00d0"]]}"#, + json::to_json(root.reborrow_as_reader())? + ); + + Ok(()) +} From 0d13e4265ca9712d1c3b0fb66013df109a11dea3 Mon Sep 17 00:00:00 2001 From: Ben Jackson Date: Wed, 26 Nov 2025 00:03:47 +0000 Subject: [PATCH 08/29] Slightly less dump annotation parser --- capnp/src/json.rs | 107 ++++++++++++++++++++++------------------------ 1 file changed, 50 insertions(+), 57 deletions(-) diff --git a/capnp/src/json.rs b/capnp/src/json.rs index 816c5b7e9..2798e8ba7 100644 --- a/capnp/src/json.rs +++ b/capnp/src/json.rs @@ -59,33 +59,56 @@ impl<'schema, 'prefix> EncodingOptions<'schema, 'prefix> { prefix: &'prefix std::borrow::Cow<'schema, str>, field: &crate::schema::Field, ) -> crate::Result { - let field_name = match field - .get_annotations()? - .iter() - .find(|a| a.get_id() == json_capnp::name::ID) - { - Some(name_annotation) => name_annotation - .get_value()? - .downcast::() - .to_str()?, - None => field.get_proto().get_name()?.to_str()?, - }; - let data_encoding = match field - .get_annotations()? - .iter() - .find(|a| a.get_id() == json_capnp::base64::ID) - { - Some(_) => DataEncoding::Base64, - None => match field - .get_annotations()? - .iter() - .find(|a| a.get_id() == json_capnp::hex::ID) - { - Some(_) => DataEncoding::Hex, - None => DataEncoding::Default, - }, + let mut options = Self { + prefix, + name: field.get_proto().get_name()?.to_str()?, + flatten: None, + discriminator: None, + data_encoding: DataEncoding::Default, }; - if data_encoding != DataEncoding::Default { + + for anno in field.get_annotations()?.iter() { + match anno.get_id() { + json_capnp::name::ID => { + options.name = anno + .get_value()? + .downcast::() + .to_str()?; + } + json_capnp::base64::ID => { + if options.data_encoding != DataEncoding::Default { + return Err(crate::Error::failed( + "Cannot specify both base64 and hex annotations on the same field" + .into(), + )); + } + options.data_encoding = DataEncoding::Base64; + } + json_capnp::hex::ID => { + if options.data_encoding != DataEncoding::Default { + return Err(crate::Error::failed( + "Cannot specify both base64 and hex annotations on the same field" + .into(), + )); + } + options.data_encoding = DataEncoding::Hex; + } + json_capnp::flatten::ID => { + options.flatten = Some( + anno.get_value()? + .downcast_struct::(), + ); + } + json_capnp::discriminator::ID => { + options.discriminator = Some( + anno.get_value()? + .downcast_struct::(), + ); + } + _ => {} + } + } + if options.data_encoding != DataEncoding::Default { let mut element_type = field.get_type(); while let crate::introspect::TypeVariant::List(sub_element_type) = element_type.which() { @@ -97,37 +120,7 @@ impl<'schema, 'prefix> EncodingOptions<'schema, 'prefix> { )); } } - let flatten_options = match field - .get_annotations()? - .iter() - .find(|a| a.get_id() == json_capnp::flatten::ID) - { - Some(annotation) => Some( - annotation - .get_value()? - .downcast_struct::(), - ), - None => None, - }; - let discriminator_options = match field - .get_annotations()? - .iter() - .find(|a| a.get_id() == json_capnp::discriminator::ID) - { - Some(annotation) => Some( - annotation - .get_value()? - .downcast_struct::(), - ), - None => None, - }; - Ok(Self { - prefix, - name: field_name, - flatten: flatten_options, - discriminator: discriminator_options, - data_encoding, - }) + Ok(options) } } From 1b5fb8bb6979acbda12073ba8e023cb36d8f4860 Mon Sep 17 00:00:00 2001 From: Ben Jackson Date: Thu, 27 Nov 2025 23:05:43 +0000 Subject: [PATCH 09/29] Add basic parsing with no unflattening and no unions --- capnp/src/json.rs | 1277 ++++++++++++++++++++++++++++++++++--------- capnpc/test/json.rs | 127 +++++ 2 files changed, 1135 insertions(+), 269 deletions(-) diff --git a/capnp/src/json.rs b/capnp/src/json.rs index 2798e8ba7..17a3cf661 100644 --- a/capnp/src/json.rs +++ b/capnp/src/json.rs @@ -14,25 +14,20 @@ pub fn to_json<'reader>( reader: impl Into>, ) -> crate::Result { let mut writer = std::io::Cursor::new(Vec::with_capacity(4096)); - serialize_json_to(&mut writer, reader)?; + encode::serialize_json_to(&mut writer, reader)?; String::from_utf8(writer.into_inner()).map_err(|e| e.into()) } -pub fn serialize_json_to<'reader, W>( - writer: &mut W, - reader: impl Into>, -) -> crate::Result<()> -where - W: std::io::Write, -{ - let meta = EncodingOptions { - prefix: &std::borrow::Cow::Borrowed(""), - name: "", - flatten: None, - discriminator: None, - data_encoding: DataEncoding::Default, +pub fn from_json<'segments>( + json: &str, + builder: impl Into>, +) -> crate::Result<()> { + let crate::dynamic_value::Builder::Struct(builder) = builder.into() else { + return Err(crate::Error::failed( + "Top-level JSON value must be an object".into(), + )); }; - serialize_value_to(writer, reader.into(), &meta) + decode::parse(json, builder) } use crate::json_capnp; @@ -124,302 +119,1046 @@ impl<'schema, 'prefix> EncodingOptions<'schema, 'prefix> { } } -fn serialize_value_to( - writer: &mut W, - reader: crate::dynamic_value::Reader<'_>, - meta: &EncodingOptions<'_, '_>, -) -> crate::Result<()> -where - W: std::io::Write, -{ - match reader { - crate::dynamic_value::Reader::Void => write!(writer, "null").map_err(|e| e.into()), - crate::dynamic_value::Reader::Bool(value) => if value { - write!(writer, "true") - } else { - write!(writer, "false") +// Serialisation + +pub mod encode { + use super::*; + + pub fn serialize_json_to<'reader, W>( + writer: &mut W, + reader: impl Into>, + ) -> crate::Result<()> + where + W: std::io::Write, + { + let meta = EncodingOptions { + prefix: &std::borrow::Cow::Borrowed(""), + name: "", + flatten: None, + discriminator: None, + data_encoding: DataEncoding::Default, + }; + serialize_value_to(writer, reader.into(), &meta) + } + + fn serialize_value_to( + writer: &mut W, + reader: crate::dynamic_value::Reader<'_>, + meta: &EncodingOptions<'_, '_>, + ) -> crate::Result<()> + where + W: std::io::Write, + { + match reader { + crate::dynamic_value::Reader::Void => write!(writer, "null").map_err(|e| e.into()), + crate::dynamic_value::Reader::Bool(value) => if value { + write!(writer, "true") + } else { + write!(writer, "false") + } + .map_err(|e| e.into()), + crate::dynamic_value::Reader::Int8(value) => write_signed_number(writer, value as i64), + crate::dynamic_value::Reader::Int16(value) => write_signed_number(writer, value as i64), + crate::dynamic_value::Reader::Int32(value) => write_signed_number(writer, value as i64), + crate::dynamic_value::Reader::Int64(value) => write_signed_number(writer, value), + crate::dynamic_value::Reader::UInt8(value) => { + write_unsigned_number(writer, value as u64) + } + crate::dynamic_value::Reader::UInt16(value) => { + write_unsigned_number(writer, value as u64) + } + crate::dynamic_value::Reader::UInt32(value) => { + write_unsigned_number(writer, value as u64) + } + crate::dynamic_value::Reader::UInt64(value) => write_unsigned_number(writer, value), + crate::dynamic_value::Reader::Float32(value) => { + write_float_number(writer, value as f64) + } + crate::dynamic_value::Reader::Float64(value) => write_float_number(writer, value), + crate::dynamic_value::Reader::Enum(value) => { + if let Some(enumerant) = value.get_enumerant()? { + let value = enumerant + .get_annotations()? + .iter() + .find(|a| a.get_id() == json_capnp::name::ID) + .and_then(|a| { + a.get_value() + .ok() + .map(|v| v.downcast::().to_str()) + }) + .unwrap_or(enumerant.get_proto().get_name()?.to_str()); + write_string(writer, value?) + } else { + write_unsigned_number(writer, value.get_value() as u64) + } + } + crate::dynamic_value::Reader::Text(reader) => write_string(writer, reader.to_str()?), + crate::dynamic_value::Reader::Data(data) => { + write_data(writer, data, meta.data_encoding) + } + crate::dynamic_value::Reader::Struct(reader) => write_object(writer, reader, meta), + crate::dynamic_value::Reader::List(reader) => write_array(writer, reader.iter(), meta), + crate::dynamic_value::Reader::AnyPointer(_) => Err(crate::Error::unimplemented( + "AnyPointer cannot be represented in JSON".into(), + )), + crate::dynamic_value::Reader::Capability(_) => Err(crate::Error::unimplemented( + "Capability cannot be represented in JSON".into(), + )), } - .map_err(|e| e.into()), - crate::dynamic_value::Reader::Int8(value) => write_signed_number(writer, value as i64), - crate::dynamic_value::Reader::Int16(value) => write_signed_number(writer, value as i64), - crate::dynamic_value::Reader::Int32(value) => write_signed_number(writer, value as i64), - crate::dynamic_value::Reader::Int64(value) => write_signed_number(writer, value), - crate::dynamic_value::Reader::UInt8(value) => write_unsigned_number(writer, value as u64), - crate::dynamic_value::Reader::UInt16(value) => write_unsigned_number(writer, value as u64), - crate::dynamic_value::Reader::UInt32(value) => write_unsigned_number(writer, value as u64), - crate::dynamic_value::Reader::UInt64(value) => write_unsigned_number(writer, value), - crate::dynamic_value::Reader::Float32(value) => write_float_number(writer, value as f64), - crate::dynamic_value::Reader::Float64(value) => write_float_number(writer, value), - crate::dynamic_value::Reader::Enum(value) => { - if let Some(enumerant) = value.get_enumerant()? { - let value = enumerant - .get_annotations()? - .iter() - .find(|a| a.get_id() == json_capnp::name::ID) - .and_then(|a| { - a.get_value() - .ok() - .map(|v| v.downcast::().to_str()) - }) - .unwrap_or(enumerant.get_proto().get_name()?.to_str()); - write_string(writer, value?) + } + + // TODO: use crate::io::Write ? + fn write_unsigned_number(writer: &mut W, value: u64) -> crate::Result<()> { + write!(writer, "{}", value)?; + Ok(()) + } + fn write_signed_number(writer: &mut W, value: i64) -> crate::Result<()> { + write!(writer, "{}", value)?; + Ok(()) + } + + fn write_float_number(writer: &mut W, value: f64) -> crate::Result<()> { + // From the C++ codec comments: + // Inf, -inf and NaN are not allowed in the JSON spec. Storing into string. + + if value.is_finite() { + write!(writer, "{}", value)?; + } else if value.is_nan() { + write_string(writer, "NaN")?; + } else if value.is_infinite() { + if value.is_sign_positive() { + write_string(writer, "Infinity")?; } else { - write_unsigned_number(writer, value.get_value() as u64) + write_string(writer, "-Infinity")?; } } - crate::dynamic_value::Reader::Text(reader) => write_string(writer, reader.to_str()?), - crate::dynamic_value::Reader::Data(data) => write_data(writer, data, meta.data_encoding), - crate::dynamic_value::Reader::Struct(reader) => write_object(writer, reader, meta), - crate::dynamic_value::Reader::List(reader) => write_array(writer, reader.iter(), meta), - crate::dynamic_value::Reader::AnyPointer(_) => Err(crate::Error::unimplemented( - "AnyPointer cannot be represented in JSON".into(), - )), - crate::dynamic_value::Reader::Capability(_) => Err(crate::Error::unimplemented( - "Capability cannot be represented in JSON".into(), - )), + Ok(()) } -} -// TODO: use crate::io::Write ? -fn write_unsigned_number(writer: &mut W, value: u64) -> crate::Result<()> { - write!(writer, "{}", value)?; - Ok(()) -} -fn write_signed_number(writer: &mut W, value: i64) -> crate::Result<()> { - write!(writer, "{}", value)?; - Ok(()) -} + fn write_string(writer: &mut W, value: &str) -> crate::Result<()> { + write!(writer, "\"")?; + for c in value.chars() { + match c { + '\"' => write!(writer, "\\\"")?, + '\\' => write!(writer, "\\\\")?, + '\n' => write!(writer, "\\n")?, + '\r' => write!(writer, "\\r")?, + '\t' => write!(writer, "\\t")?, + '\u{08}' => write!(writer, "\\b")?, + '\u{0C}' => write!(writer, "\\f")?, + c if c.is_control() => write!(writer, "\\u{:04x}", c as u32)?, + c => write!(writer, "{}", c)?, + } + } + write!(writer, "\"")?; + Ok(()) + } -fn write_float_number(writer: &mut W, value: f64) -> crate::Result<()> { - // From the C++ codec comments: - // Inf, -inf and NaN are not allowed in the JSON spec. Storing into string. + fn write_array<'reader, W: std::io::Write, I>( + writer: &mut W, + items: I, + meta: &EncodingOptions, + ) -> crate::Result<()> + where + I: Iterator>>, + { + write!(writer, "[")?; + let mut first = true; + for item in items { + if !first { + write!(writer, ",")?; + } + first = false; + serialize_value_to(writer, item?, meta)?; + } + write!(writer, "]")?; + Ok(()) + } - if value.is_finite() { - write!(writer, "{}", value)?; - } else if value.is_nan() { - write_string(writer, "NaN")?; - } else if value.is_infinite() { - if value.is_sign_positive() { - write_string(writer, "Infinity")?; + fn write_object<'reader, W: std::io::Write>( + writer: &mut W, + reader: crate::dynamic_struct::Reader<'reader>, + meta: &EncodingOptions<'_, '_>, + ) -> crate::Result<()> { + let (flatten, field_prefix) = if let Some(flatten_options) = &meta.flatten { + ( + true, + std::borrow::Cow::Owned(format!( + "{}{}", + meta.prefix, + flatten_options.get_prefix()?.to_str()? + )), + ) } else { - write_string(writer, "-Infinity")?; + (false, std::borrow::Cow::Borrowed("")) + }; + + // Comment copied verbatim from the Cap'n Proto C++ implementation: + // There are two cases of unions: + // * Named unions, which are special cases of named groups. In this case, the union may be + // annotated by annotating the field. In this case, we receive a non-null `discriminator` + // as a constructor parameter, and schemaProto.getAnnotations() must be empty because + // it's not possible to annotate a group's type (because the type is anonymous). + // * Unnamed unions, of which there can only be one in any particular scope. In this case, + // the parent struct type itself is annotated. + // So if we received `null` as the constructor parameter, check for annotations on the struct + // type. + let struct_discriminator = reader + .get_schema() + .get_annotations()? + .iter() + .find(|a| a.get_id() == json_capnp::discriminator::ID) + .and_then(|annotation| { + annotation + .get_value() + .ok() + .map(|v| v.downcast_struct::()) + }); + + if !flatten { + write!(writer, "{{")?; + } + let mut first = true; + for field in reader.get_schema().get_fields()? { + if !reader.has(field)? { + continue; + } + let field_meta = EncodingOptions::from_field(&field_prefix, &field)?; + let mut value_name = field_meta.name; + if field.get_proto().get_discriminant_value() + != crate::schema_capnp::field::NO_DISCRIMINANT + { + if let Some(active_union_member) = reader.which()? { + let active_union_member_meta = + EncodingOptions::from_field(&field_prefix, &active_union_member)?; + if field.get_proto().get_discriminant_value() + != active_union_member.get_proto().get_discriminant_value() + { + // Skip union members that are not set. + continue; + } + let discriminator = match meta.discriminator { + Some(ref d) => Some(d), + None => struct_discriminator.as_ref(), + }; + if let Some(discriminator) = discriminator { + // write out the discriminator + if !first { + write!(writer, ",")?; + } + first = false; + let discriminator_name = if discriminator.has_name() { + discriminator.get_name()?.to_str()? + } else { + meta.name + }; + if discriminator.has_value_name() { + value_name = discriminator.get_value_name()?.to_str()?; + } + + write_string( + writer, + format!("{}{}", field_prefix, discriminator_name).as_str(), + )?; + write!(writer, ":")?; + write_string(writer, active_union_member_meta.name)?; + } + } + } + if !first { + write!(writer, ",")?; + } + first = false; + if field_meta.flatten.is_none() { + write_string(writer, format!("{}{}", field_prefix, value_name).as_str())?; + write!(writer, ":")?; + } + let field_value = reader.get(field)?; + serialize_value_to(writer, field_value, &field_meta)?; + } + if !flatten { + write!(writer, "}}")?; } + Ok(()) } - Ok(()) -} -fn write_string(writer: &mut W, value: &str) -> crate::Result<()> { - write!(writer, "\"")?; - for c in value.chars() { - match c { - '\"' => write!(writer, "\\\"")?, - '\\' => write!(writer, "\\\\")?, - '\n' => write!(writer, "\\n")?, - '\r' => write!(writer, "\\r")?, - '\t' => write!(writer, "\\t")?, - '\u{08}' => write!(writer, "\\b")?, - '\u{0C}' => write!(writer, "\\f")?, - c if c.is_control() => write!(writer, "\\u{:04x}", c as u32)?, - c => write!(writer, "{}", c)?, + fn write_data( + writer: &mut W, + data: crate::data::Reader<'_>, + encoding: DataEncoding, + ) -> crate::Result<()> { + match encoding { + DataEncoding::Default => { + write!(writer, "[")?; + let mut first = true; + for byte in data.iter() { + if !first { + write!(writer, ",")?; + } + first = false; + write!(writer, "{}", byte)?; + } + write!(writer, "]")?; + Ok(()) + } + DataEncoding::Base64 => write_string(writer, base64::encode(data).as_str()), + DataEncoding::Hex => write_string(writer, hex::encode(data).as_str()), } } - write!(writer, "\"")?; - Ok(()) } -fn write_array<'reader, W: std::io::Write, I>( - writer: &mut W, - items: I, - meta: &EncodingOptions, -) -> crate::Result<()> -where - I: Iterator>>, -{ - write!(writer, "[")?; - let mut first = true; - for item in items { - if !first { - write!(writer, ",")?; +// Deserialisation + +pub mod decode { + use super::*; + + enum ParseError { + UnexpectedEndOfInput, + InvalidToken(char), + Other(String), + } + + impl From for crate::Error { + fn from(err: ParseError) -> Self { + match err { + ParseError::UnexpectedEndOfInput => { + crate::Error::failed("Unexpected end of input while parsing JSON".into()) + } + ParseError::InvalidToken(c) => { + crate::Error::failed(format!("Invalid token '{c}' while parsing JSON")) + } + // TODO: Use better values here? + ParseError::Other(msg) => crate::Error::failed(msg), + } } - first = false; - serialize_value_to(writer, item?, meta)?; } - write!(writer, "]")?; - Ok(()) -} -fn write_object<'reader, W: std::io::Write>( - writer: &mut W, - reader: crate::dynamic_struct::Reader<'reader>, - meta: &EncodingOptions<'_, '_>, -) -> crate::Result<()> { - let (flatten, field_prefix) = if let Some(flatten_options) = &meta.flatten { - ( - true, - std::borrow::Cow::Owned(format!( - "{}{}", - meta.prefix, - flatten_options.get_prefix()?.to_str()? - )), - ) - } else { - (false, std::borrow::Cow::Borrowed("")) - }; + use std::collections::HashMap; + + // FIXME: The String valued below could be Cow<'input, str> as they only really + // need to be allocated if the input contains escaped characters. That would be + // a little more tricky lower down, but not by a lot. + enum JsonValue { + Null, + Boolean(bool), + Number(f64), + String(String), + Array(Vec), + Object(HashMap), + + DataBuffer(Vec), // HACK: This is so we have somewhere to store the data + // temporarily when we are decoding data fields into + // Readers + } - // Comment copied verbatim from the Cap'n Proto C++ implementation: - // There are two cases of unions: - // * Named unions, which are special cases of named groups. In this case, the union may be - // annotated by annotating the field. In this case, we receive a non-null `discriminator` - // as a constructor parameter, and schemaProto.getAnnotations() must be empty because - // it's not possible to annotate a group's type (because the type is anonymous). - // * Unnamed unions, of which there can only be one in any particular scope. In this case, - // the parent struct type itself is annotated. - // So if we received `null` as the constructor parameter, check for annotations on the struct - // type. - let struct_discriminator = reader - .get_schema() - .get_annotations()? - .iter() - .find(|a| a.get_id() == json_capnp::discriminator::ID) - .and_then(|annotation| { - annotation - .get_value() - .ok() - .map(|v| v.downcast_struct::()) - }); - - if !flatten { - write!(writer, "{{")?; + struct Parser + where + I: Iterator, + { + // FIXME: By using an iter over char here, we restrict ourselves to not + // being able to use string slices for must of the parsing. THis is piggy. + // It would be better to just have a &str and an index probably. + input_iter: std::iter::Peekable>, } - let mut first = true; - for field in reader.get_schema().get_fields()? { - if !reader.has(field)? { - continue; + + impl Parser + where + I: Iterator, + { + fn new(iter: I) -> Self { + Self { + input_iter: iter.fuse().peekable(), + } } - let field_meta = EncodingOptions::from_field(&field_prefix, &field)?; - let mut value_name = field_meta.name; - if field.get_proto().get_discriminant_value() != crate::schema_capnp::field::NO_DISCRIMINANT - { - if let Some(active_union_member) = reader.which()? { - let active_union_member_meta = - EncodingOptions::from_field(&field_prefix, &active_union_member)?; - if field.get_proto().get_discriminant_value() - != active_union_member.get_proto().get_discriminant_value() - { - // Skip union members that are not set. - continue; - } - let discriminator = match meta.discriminator { - Some(ref d) => Some(d), - None => struct_discriminator.as_ref(), - }; - if let Some(discriminator) = discriminator { - // write out the discriminator - if !first { - write!(writer, ",")?; + + fn advance(&mut self) -> crate::Result { + self.input_iter + .next() + .ok_or(ParseError::UnexpectedEndOfInput.into()) + } + + fn peek(&mut self) -> Option { + self.input_iter.peek().copied() + } + + fn consume(&mut self, c: char) -> crate::Result { + self.discard_whitespace(); + match self.advance()? { + p if p == c => Ok(p), + p => Err(ParseError::InvalidToken(p).into()), + } + } + + fn discard_whitespace(&mut self) { + while let Some(c) = self.peek() { + if c.is_whitespace() { + self.advance().ok(); + } else { + break; + } + } + } + + fn discard_peek(&mut self) -> Option { + self.discard_whitespace(); + self.peek() + } + + fn parse_value(&mut self) -> crate::Result { + match self.discard_peek() { + None => Err(ParseError::UnexpectedEndOfInput.into()), + Some('n') => { + self.consume('n')?; + self.consume('u')?; + self.consume('l')?; + self.consume('l')?; + Ok(JsonValue::Null) + } + Some('t') => { + self.consume('t')?; + self.consume('r')?; + self.consume('u')?; + self.consume('e')?; + Ok(JsonValue::Boolean(true)) + } + Some('f') => { + self.consume('f')?; + self.consume('a')?; + self.consume('l')?; + self.consume('s')?; + self.consume('e')?; + Ok(JsonValue::Boolean(false)) + } + Some('\"') => Ok(JsonValue::String(self.parse_string()?)), + Some('0'..='9') | Some('-') => { + let num_str = self.parse_number()?; + let num = num_str + .parse::() + .map_err(|e| ParseError::Other(format!("Invalid number format: {}", e)))?; + Ok(JsonValue::Number(num)) + } + Some('[') => { + self.consume('[')?; + let mut items = Vec::new(); + let mut require_comma = false; + while self.discard_peek().is_some_and(|c| c != ']') { + if require_comma { + self.consume(',')?; + } + require_comma = true; + let item = self.parse_value()?; + items.push(item); } - first = false; - let discriminator_name = if discriminator.has_name() { - discriminator.get_name()?.to_str()? - } else { - meta.name - }; - if discriminator.has_value_name() { - value_name = discriminator.get_value_name()?.to_str()?; + self.consume(']')?; + Ok(JsonValue::Array(items)) + } + Some('{') => { + self.consume('{')?; + let mut members = HashMap::new(); + let mut require_comma = false; + while self.discard_peek().is_some_and(|c| c != '}') { + if require_comma { + self.consume(',')?; + } + require_comma = true; + let key = self.parse_string()?; + self.consume(':')?; + let value = self.parse_value()?; + if members.insert(key.clone(), value).is_some() { + return Err(ParseError::Other(format!( + "Duplicate key in object: {}", + key + )) + .into()); + } } + self.consume('}')?; + Ok(JsonValue::Object(members)) + } + Some(c) => Err(ParseError::InvalidToken(c).into()), + } + } - write_string( - writer, - format!("{}{}", field_prefix, discriminator_name).as_str(), - )?; - write!(writer, ":")?; - write_string(writer, active_union_member_meta.name)?; + fn parse_string(&mut self) -> crate::Result { + self.consume('\"')?; + let mut result = String::new(); + loop { + let c = self.advance()?; + match c { + '\"' => return Ok(result), + '\\' => { + let escaped = self.advance()?; + match escaped { + '\"' => result.push('\"'), + '\\' => result.push('\\'), + '/' => result.push('/'), + 'b' => result.push('\u{08}'), + 'f' => result.push('\u{0C}'), + 'n' => result.push('\n'), + 'r' => result.push('\r'), + 't' => result.push('\t'), + 'u' => { + let mut hex = String::new(); + for _ in 0..4 { + hex.push(self.advance()?); + } + let code_point = u16::from_str_radix(&hex, 16).map_err(|_| { + ParseError::Other(format!("Invalid unicode escape: \\u{}", hex)) + })?; + if let Some(ch) = std::char::from_u32(code_point as u32) { + result.push(ch); + } else { + return Err(ParseError::Other(format!( + "Invalid unicode code point: \\u{}", + hex + )) + .into()); + } + } + other => { + return Err(ParseError::Other(format!( + "Invalid escape character: \\{}", + other + )) + .into()); + } + } + } + other => result.push(other), } - // TODO: value_name. should that just change meta.name printed - // below? } } - if !first { - write!(writer, ",")?; + + fn parse_number(&mut self) -> crate::Result { + let mut num_str = String::new(); + if self.discard_peek().is_some_and(|c| c == '-') { + num_str.push(self.advance()?); + } + while self.peek().is_some_and(|c| c.is_ascii_digit()) { + num_str.push(self.advance()?); + } + if self.peek().is_some_and(|c| c == '.') { + num_str.push(self.advance()?); + while self.peek().is_some_and(|c| c.is_ascii_digit()) { + num_str.push(self.advance()?); + } + } + if self.peek().is_some_and(|c| c == 'e' || c == 'E') { + num_str.push(self.advance()?); + if self.peek().is_some_and(|c| c == '+' || c == '-') { + num_str.push(self.advance()?); + } + while self.peek().is_some_and(|c| c.is_ascii_digit()) { + num_str.push(self.advance()?); + } + } + Ok(num_str) } - first = false; - if field_meta.flatten.is_none() { - write_string(writer, format!("{}{}", field_prefix, value_name).as_str())?; - write!(writer, ":")?; + } + + pub fn parse(json: &str, builder: crate::dynamic_struct::Builder<'_>) -> crate::Result<()> { + let mut parser = Parser::new(json.chars()); + let value = parser.parse_value()?; + let meta = EncodingOptions { + prefix: &std::borrow::Cow::Borrowed(""), + name: "", + flatten: None, + discriminator: None, + data_encoding: DataEncoding::Default, + }; + let JsonValue::Object(value) = value else { + return Err(crate::Error::failed( + "Top-level JSON value must be an object".into(), + )); + }; + decode_struct(value, builder, &meta) + } + + fn decode_primitive<'json, 'meta>( + field_value: &'json mut JsonValue, + field_type: &'meta crate::introspect::Type, + field_meta: &'meta EncodingOptions, + ) -> crate::Result> { + match field_type.which() { + crate::introspect::TypeVariant::Void => { + if !matches!(field_value, JsonValue::Null) { + Err(crate::Error::failed(format!( + "Expected null for void field {}", + field_meta.name + ))) + } else { + Ok(crate::dynamic_value::Reader::Void) + } + } + crate::introspect::TypeVariant::Bool => { + let JsonValue::Boolean(field_value) = field_value else { + return Err(crate::Error::failed(format!( + "Expected boolean for field {}", + field_meta.name + ))); + }; + Ok((*field_value).into()) + } + crate::introspect::TypeVariant::Int8 => { + let JsonValue::Number(field_value) = field_value else { + return Err(crate::Error::failed(format!( + "Expected number for field {}", + field_meta.name + ))); + }; + Ok((*field_value as i8).into()) + } + crate::introspect::TypeVariant::Int16 => { + let JsonValue::Number(field_value) = field_value else { + return Err(crate::Error::failed(format!( + "Expected number for field {}", + field_meta.name + ))); + }; + Ok((*field_value as i16).into()) + } + crate::introspect::TypeVariant::Int32 => { + let JsonValue::Number(field_value) = field_value else { + return Err(crate::Error::failed(format!( + "Expected number for field {}", + field_meta.name + ))); + }; + Ok((*field_value as i32).into()) + } + crate::introspect::TypeVariant::Int64 => { + let JsonValue::Number(field_value) = field_value else { + return Err(crate::Error::failed(format!( + "Expected number for field {}", + field_meta.name + ))); + }; + Ok((*field_value as i64).into()) + } + crate::introspect::TypeVariant::UInt8 => { + let JsonValue::Number(field_value) = field_value else { + return Err(crate::Error::failed(format!( + "Expected number for field {}", + field_meta.name + ))); + }; + Ok((*field_value as u8).into()) + } + crate::introspect::TypeVariant::UInt16 => { + let JsonValue::Number(field_value) = field_value else { + return Err(crate::Error::failed(format!( + "Expected number for field {}", + field_meta.name + ))); + }; + Ok((*field_value as u16).into()) + } + crate::introspect::TypeVariant::UInt32 => { + let JsonValue::Number(field_value) = field_value else { + return Err(crate::Error::failed(format!( + "Expected number for field {}", + field_meta.name + ))); + }; + Ok((*field_value as u32).into()) + } + crate::introspect::TypeVariant::UInt64 => { + let JsonValue::Number(field_value) = field_value else { + return Err(crate::Error::failed(format!( + "Expected number for field {}", + field_meta.name + ))); + }; + Ok((*field_value as u64).into()) + } + crate::introspect::TypeVariant::Float32 => { + let field_value = match field_value { + JsonValue::Number(field_value) => *field_value as f32, + JsonValue::String(field_value) => match field_value.as_str() { + "NaN" => f32::NAN, + "Infinity" => f32::INFINITY, + "-Infinity" => f32::NEG_INFINITY, + _ => { + return Err(crate::Error::failed(format!( + "Expected number for field {}", + field_meta.name + ))); + } + }, + _ => { + return Err(crate::Error::failed(format!( + "Expected number for field {}", + field_meta.name + ))); + } + }; + Ok(field_value.into()) + } + crate::introspect::TypeVariant::Float64 => { + let field_value = match field_value { + JsonValue::Number(field_value) => *field_value, + JsonValue::String(field_value) => match field_value.as_str() { + "NaN" => f64::NAN, + "Infinity" => f64::INFINITY, + "-Infinity" => f64::NEG_INFINITY, + _ => { + return Err(crate::Error::failed(format!( + "Expected number for field {}", + field_meta.name + ))); + } + }, + _ => { + return Err(crate::Error::failed(format!( + "Expected number for field {}", + field_meta.name + ))); + } + }; + Ok(field_value.into()) + } + crate::introspect::TypeVariant::Text => { + let JsonValue::String(field_value) = field_value else { + return Err(crate::Error::failed(format!( + "Expected string for field {}", + field_meta.name + ))); + }; + Ok((*field_value.as_str()).into()) + } + crate::introspect::TypeVariant::Enum(enum_schema) => match field_value { + JsonValue::String(field_value) => { + let enum_schema = crate::schema::EnumSchema::new(enum_schema); + let Some(enum_value) = enum_schema.get_enumerants()?.iter().find(|e| { + e.get_proto() + .get_name() + .ok() + .and_then(|n| n.to_str().ok()) + .is_some_and(|s| s == field_value) + }) else { + return Err(crate::Error::failed(format!( + "Invalid enum value '{}' for field {}", + field_value, field_meta.name + ))); + }; + + Ok(crate::dynamic_value::Reader::Enum( + crate::dynamic_value::Enum::new( + enum_value.get_ordinal(), + enum_value.get_containing_enum(), + ), + )) + } + JsonValue::Number(enum_value) => { + let enum_schema = crate::schema::EnumSchema::new(enum_schema); + Ok(crate::dynamic_value::Reader::Enum( + crate::dynamic_value::Enum::new(*enum_value as u16, enum_schema), + )) + } + _ => Err(crate::Error::failed(format!( + "Expected string or number for enum field {}", + field_meta.name + ))), + }, + crate::introspect::TypeVariant::Data => match field_meta.data_encoding { + // The reason we have this ugly DataBuffer hack is to ensure that we + // can return a Reader from this function whose lifetime is tied to + // the field_value, as there is no other buffer we can use. We don't + // currently support Orphans, but if we did, most of this Reader + // dance could probably be avoided. + DataEncoding::Default => { + let JsonValue::Array(data_value) = field_value else { + return Err(crate::Error::failed(format!( + "Expected array for data field {}", + field_meta.name + ))); + }; + let mut data = Vec::with_capacity(data_value.len()); + for byte_value in data_value.drain(..) { + let JsonValue::Number(byte_value) = byte_value else { + return Err(crate::Error::failed(format!( + "Expected number for data byte in field {}", + field_meta.name + ))); + }; + data.push(byte_value as u8); + } + *field_value = JsonValue::DataBuffer(data); + Ok(crate::dynamic_value::Reader::Data(match field_value { + JsonValue::DataBuffer(ref data) => data.as_slice(), + _ => unreachable!(), + })) + } + DataEncoding::Base64 => { + let JsonValue::String(data_value) = field_value else { + return Err(crate::Error::failed(format!( + "Expected string for base64 data field {}", + field_meta.name + ))); + }; + *field_value = JsonValue::DataBuffer(base64::decode(data_value)?); + Ok(crate::dynamic_value::Reader::Data(match field_value { + JsonValue::DataBuffer(ref data) => data.as_slice(), + _ => unreachable!(), + })) + } + DataEncoding::Hex => { + let JsonValue::String(data_value) = field_value else { + return Err(crate::Error::failed(format!( + "Expected string for hex data field {}", + field_meta.name + ))); + }; + *field_value = JsonValue::DataBuffer(hex::decode(data_value)?); + Ok(crate::dynamic_value::Reader::Data(match field_value { + JsonValue::DataBuffer(ref data) => data.as_slice(), + _ => unreachable!(), + })) + } + }, + _ => Err(crate::Error::failed(format!( + "Unsupported primitive type for field {}", + field_meta.name + ))), } - let field_value = reader.get(field)?; - serialize_value_to(writer, field_value, &field_meta)?; } - if !flatten { - write!(writer, "}}")?; + + fn decode_list( + mut field_values: Vec, + mut list_builder: crate::dynamic_list::Builder, + field_meta: &EncodingOptions, + ) -> crate::Result<()> { + match list_builder.element_type().which() { + crate::introspect::TypeVariant::Struct(_sub_element_schema) => { + for (i, item_value) in field_values.drain(..).enumerate() { + let JsonValue::Object(item_value) = item_value else { + return Err(crate::Error::failed(format!( + "Expected object for struct list field {}", + field_meta.name + ))); + }; + let struct_builder = list_builder + .reborrow() + .get(i as u32)? + .downcast::(); + decode_struct(item_value, struct_builder, field_meta)?; + } + Ok(()) + } + crate::introspect::TypeVariant::List(_sub_element_type) => { + for (i, item_value) in field_values.drain(..).enumerate() { + let JsonValue::Array(item_value) = item_value else { + return Err(crate::Error::failed(format!( + "Expected array for list field {}", + field_meta.name + ))); + }; + let sub_element_builder = list_builder + .reborrow() + .init(i as u32, item_value.len() as u32)? + .downcast::(); + decode_list(item_value, sub_element_builder, field_meta)?; + } + Ok(()) + } + _ => { + for (i, mut item_value) in field_values.drain(..).enumerate() { + list_builder.set( + i as u32, + decode_primitive( + &mut item_value, + &list_builder.element_type(), + field_meta, + )?, + )?; + } + Ok(()) + } + } } - Ok(()) -} -fn write_data( - writer: &mut W, - data: crate::data::Reader<'_>, - encoding: DataEncoding, -) -> crate::Result<()> { - match encoding { - DataEncoding::Default => { - write!(writer, "[")?; - let mut first = true; - for byte in data.iter() { - if !first { - write!(writer, ",")?; - } - first = false; - write!(writer, "{}", byte)?; - } - write!(writer, "]")?; - Ok(()) + fn decode_struct( + mut value: HashMap, + mut builder: crate::dynamic_struct::Builder<'_>, + meta: &EncodingOptions, + ) -> crate::Result<()> { + for field in builder.get_schema().get_fields()? { + let field_meta = EncodingOptions::from_field(meta.prefix, &field)?; + let mut field_value = match value.remove(field_meta.name) { + Some(v) => v, + None => continue, + }; + + // TODO: Handle (un)flattening, unions, discriminators, etc. + + match field.get_type().which() { + crate::introspect::TypeVariant::Struct(_struct_schema) => { + let JsonValue::Object(field_value) = field_value else { + return Err(crate::Error::failed(format!( + "Expected object for field {}", + field_meta.name + ))); + }; + let struct_builder = builder + .reborrow() + .init(field)? + .downcast::(); + decode_struct(field_value, struct_builder, &field_meta)?; + } + crate::introspect::TypeVariant::List(_element_type) => { + let JsonValue::Array(field_value) = field_value else { + return Err(crate::Error::failed(format!( + "Expected array for field {}", + field_meta.name + ))); + }; + let list_builder = builder + .reborrow() + .initn(field, field_value.len() as u32)? + .downcast::(); + decode_list(field_value, list_builder, &field_meta)?; + } + + crate::introspect::TypeVariant::AnyPointer => { + return Err(crate::Error::unimplemented( + "AnyPointer cannot be represented in JSON".into(), + )) + } + crate::introspect::TypeVariant::Capability => { + return Err(crate::Error::unimplemented( + "Capability cannot be represented in JSON".into(), + )) + } + + _ => { + builder.set( + field, + decode_primitive(&mut field_value, &field.get_type(), &field_meta)?, + )?; + } + } } - DataEncoding::Base64 => write_string(writer, encode_base64(data).as_str()), - DataEncoding::Hex => write_string(writer, encode_hex(data).as_str()), + + Ok(()) } } -fn encode_base64(data: &[u8]) -> String { - // We don't want to pull in base64 crate just for this. So hand-rolling a - // base64 encoder. +mod base64 { const BASE64_CHARS: &[u8; 64] = b"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; - let mut encoded = String::with_capacity(data.len().div_ceil(3) * 4); - for chunk in data.chunks(3) { - #[allow(clippy::get_first)] - let b0 = chunk.get(0).copied().unwrap_or(0); - let b1 = chunk.get(1).copied().unwrap_or(0); - let b2 = chunk.get(2).copied().unwrap_or(0); - let n = ((b0 as u32) << 16) | ((b1 as u32) << 8) | (b2 as u32); - let c0 = BASE64_CHARS[((n >> 18) & 0x3F) as usize]; - let c1 = BASE64_CHARS[((n >> 12) & 0x3F) as usize]; - let c2 = if chunk.len() > 1 { - BASE64_CHARS[((n >> 6) & 0x3F) as usize] - } else { - b'=' - }; - let c3 = if chunk.len() > 2 { - BASE64_CHARS[(n & 0x3F) as usize] - } else { - b'=' - }; - encoded.push(c0 as char); - encoded.push(c1 as char); - encoded.push(c2 as char); - encoded.push(c3 as char); + + pub fn encode(data: &[u8]) -> String { + // We don't want to pull in base64 crate just for this. So hand-rolling a + // base64 encoder. + let mut encoded = String::with_capacity(data.len().div_ceil(3) * 4); + for chunk in data.chunks(3) { + #[allow(clippy::get_first)] + let b0 = chunk.get(0).copied().unwrap_or(0); + let b1 = chunk.get(1).copied().unwrap_or(0); + let b2 = chunk.get(2).copied().unwrap_or(0); + let n = ((b0 as u32) << 16) | ((b1 as u32) << 8) | (b2 as u32); + let c0 = BASE64_CHARS[((n >> 18) & 0x3F) as usize]; + let c1 = BASE64_CHARS[((n >> 12) & 0x3F) as usize]; + let c2 = if chunk.len() > 1 { + BASE64_CHARS[((n >> 6) & 0x3F) as usize] + } else { + b'=' + }; + let c3 = if chunk.len() > 2 { + BASE64_CHARS[(n & 0x3F) as usize] + } else { + b'=' + }; + encoded.push(c0 as char); + encoded.push(c1 as char); + encoded.push(c2 as char); + encoded.push(c3 as char); + } + encoded + } + + pub fn decode(data: &str) -> crate::Result> { + let bytes = data.as_bytes(); + if bytes.len() % 4 != 0 { + return Err(crate::Error::failed( + "Base64 string length must be a multiple of 4".into(), + )); + } + let mut decoded = Vec::with_capacity(bytes.len() / 4 * 3); + for chunk in bytes.chunks(4) { + let mut n: u32 = 0; + let mut padding = 0; + for &c in chunk { + n <<= 6; + match c { + b'A'..=b'Z' => n |= (c - b'A') as u32, + b'a'..=b'z' => n |= (c - b'a' + 26) as u32, + b'0'..=b'9' => n |= (c - b'0' + 52) as u32, + b'+' => n |= 62, + b'/' => n |= 63, + b'=' => { + n |= 0; + padding += 1; + } + _ => { + return Err(crate::Error::failed(format!( + "Invalid base64 character: {}", + c as char + ))); + } + } + } + decoded.push(((n >> 16) & 0xFF) as u8); + if padding < 2 { + decoded.push(((n >> 8) & 0xFF) as u8); + } + if padding < 1 { + decoded.push((n & 0xFF) as u8); + } + } + Ok(decoded) } - encoded } -fn encode_hex(data: &[u8]) -> String { +mod hex { const HEX_CHARS: &[u8; 16] = b"0123456789abcdef"; - let mut encoded = String::with_capacity(data.len() * 2); - for &byte in data { - let high = HEX_CHARS[(byte >> 4) as usize]; - let low = HEX_CHARS[(byte & 0x0F) as usize]; - encoded.push(high as char); - encoded.push(low as char); + fn hex_char_to_value(c: u8) -> crate::Result { + match c { + b'0'..=b'9' => Ok(c - b'0'), + b'a'..=b'f' => Ok(c - b'a' + 10), + b'A'..=b'F' => Ok(c - b'A' + 10), + _ => Err(crate::Error::failed(format!( + "Invalid hex character: {}", + c as char + ))), + } + } + + pub fn encode(data: &[u8]) -> String { + let mut encoded = String::with_capacity(data.len() * 2); + for &byte in data { + let high = HEX_CHARS[(byte >> 4) as usize]; + let low = HEX_CHARS[(byte & 0x0F) as usize]; + encoded.push(high as char); + encoded.push(low as char); + } + encoded + } + + pub fn decode(data: &str) -> crate::Result> { + if data.len() % 2 != 0 { + return Err(crate::Error::failed( + "Hex string must have even length".into(), + )); + } + let mut decoded = Vec::with_capacity(data.len() / 2); + let bytes = data.as_bytes(); + for i in (0..data.len()).step_by(2) { + let high = hex_char_to_value(bytes[i])?; + let low = hex_char_to_value(bytes[i + 1])?; + decoded.push((high << 4) | low); + } + Ok(decoded) } - encoded } + diff --git a/capnpc/test/json.rs b/capnpc/test/json.rs index 1f5d38025..5e5f6ae4b 100644 --- a/capnpc/test/json.rs +++ b/capnpc/test/json.rs @@ -379,3 +379,130 @@ fn test_nested_data_list() -> capnp::Result<()> { Ok(()) } + +// Decode + +#[test] +fn test_decode_simple() -> capnp::Result<()> { + let mut builder = message::Builder::new_default(); + let mut root: test_json_types::Builder<'_> = builder.init_root(); + json::from_json( + r#" + { + "voidField": null, + "boolField": true, + "int8Field": -8, + "int16Field": -16, + "int32Field": -32, + "int64Field": -64, + "uInt8Field": 8, + "uInt16Field": 16, + "uInt32Field": 32, + "uInt64Field": 64, + "float32Field": 1.3200000524520874, + "float64Field": 0.164e2, + "textField": "hello", + "dataField": [ + 222, + 173 + + , + + 190, + 239, + 202, + 254, + 186, + 190 + ], + "base64Field": "3q2+78r+ur4=", + "hexField": "deadbeefcafebabe", + "structField": { + "voidField": null, + "boolField": false, + "int8Field": 0, + "int16Field": 0, + "int32Field": 0, + "int64Field": 0, + "uInt8Field": 0, + "uInt16Field" + : 0, + "uInt32Field": 0, + "uInt64Field": 0, + "float32Field": 0, + "float64Field": 0, + "textField": "inner", + "enumField": "foo", + "textList": [ + "frist", + "segund" + ], + "base64List": [ + "3q2+7w==", + "ut8A0A==" + ], + "hexList": [ + "deadbeef", + "badf00d0" + ] + }, + "enumField": "quux", + "float32List": [ + "NaN", + "Infinity", + "-Infinity" + ], + "float64List": [ + "NaN", + "Infinity" , + "-Infinity" + ], + "enumList": [ + "foo", + "bar", + "garply" + ], + "int64List": [ + 1, + 2, + 4, + 8 + ] + } + "#, + root.reborrow(), + )?; + + let reader = root.into_reader(); + assert_eq!((), reader.get_void_field()); + assert_eq!(true, reader.get_bool_field()); + assert_eq!(-8, reader.get_int8_field()); + assert_eq!(-16, reader.get_int16_field()); + assert_eq!(-32, reader.get_int32_field()); + assert_eq!(-64, reader.get_int64_field()); + assert_eq!(8, reader.get_u_int8_field()); + assert_eq!(16, reader.get_u_int16_field()); + assert_eq!(32, reader.get_u_int32_field()); + assert_eq!(64, reader.get_u_int64_field()); + assert_eq!(1.32, reader.get_float32_field()); + assert_eq!(16.4, reader.get_float64_field()); + assert_eq!("hello", reader.get_text_field()?.to_str()?); + assert_eq!( + [0xde, 0xad, 0xbe, 0xef, 0xca, 0xfe, 0xba, 0xbe], + reader.get_data_field()? + ); + assert_eq!( + [0xde, 0xad, 0xbe, 0xef, 0xca, 0xfe, 0xba, 0xbe], + reader.get_base64_field()? + ); + assert_eq!( + [0xde, 0xad, 0xbe, 0xef, 0xca, 0xfe, 0xba, 0xbe], + reader.get_hex_field()? + ); + + for i in 0..4 { + assert_eq!(1 << i, reader.get_int64_list()?.get(i as u32)); + } + + Ok(()) +} From 11edd946911ef0ae20a7fc3e0258cf689bae2c58 Mon Sep 17 00:00:00 2001 From: Ben Jackson Date: Thu, 27 Nov 2025 23:37:17 +0000 Subject: [PATCH 10/29] Slight parsing refactor --- capnp/src/json.rs | 54 +++++++++++++++++++++++++++++------------------ 1 file changed, 33 insertions(+), 21 deletions(-) diff --git a/capnp/src/json.rs b/capnp/src/json.rs index 17a3cf661..a1c6e0799 100644 --- a/capnp/src/json.rs +++ b/capnp/src/json.rs @@ -471,17 +471,34 @@ pub mod decode { } } + /// Advance past any whitespace and peek at next value + fn peek_next(&mut self) -> Option { + self.discard_whitespace(); + self.peek() + } + + /// Peek at the current value + fn peek(&mut self) -> Option { + self.input_iter.peek().copied() + } + + /// Consume the current value fn advance(&mut self) -> crate::Result { self.input_iter .next() .ok_or(ParseError::UnexpectedEndOfInput.into()) } - fn peek(&mut self) -> Option { - self.input_iter.peek().copied() + /// Consume the current value if it matches `c`, otherwise error + fn consume(&mut self, c: char) -> crate::Result { + match self.advance()? { + p if p == c => Ok(p), + p => Err(ParseError::InvalidToken(p).into()), + } } - fn consume(&mut self, c: char) -> crate::Result { + /// Advance past any whitespace and consume the current value if it matches `c`, otherwise error + fn consume_next(&mut self, c: char) -> crate::Result { self.discard_whitespace(); match self.advance()? { p if p == c => Ok(p), @@ -499,30 +516,25 @@ pub mod decode { } } - fn discard_peek(&mut self) -> Option { - self.discard_whitespace(); - self.peek() - } - fn parse_value(&mut self) -> crate::Result { - match self.discard_peek() { + match self.peek_next() { None => Err(ParseError::UnexpectedEndOfInput.into()), Some('n') => { - self.consume('n')?; + self.advance()?; self.consume('u')?; self.consume('l')?; self.consume('l')?; Ok(JsonValue::Null) } Some('t') => { - self.consume('t')?; + self.advance()?; self.consume('r')?; self.consume('u')?; self.consume('e')?; Ok(JsonValue::Boolean(true)) } Some('f') => { - self.consume('f')?; + self.advance()?; self.consume('a')?; self.consume('l')?; self.consume('s')?; @@ -538,10 +550,10 @@ pub mod decode { Ok(JsonValue::Number(num)) } Some('[') => { - self.consume('[')?; + self.advance()?; let mut items = Vec::new(); let mut require_comma = false; - while self.discard_peek().is_some_and(|c| c != ']') { + while self.peek_next().is_some_and(|c| c != ']') { if require_comma { self.consume(',')?; } @@ -549,20 +561,20 @@ pub mod decode { let item = self.parse_value()?; items.push(item); } - self.consume(']')?; + self.consume_next(']')?; Ok(JsonValue::Array(items)) } Some('{') => { - self.consume('{')?; + self.advance()?; let mut members = HashMap::new(); let mut require_comma = false; - while self.discard_peek().is_some_and(|c| c != '}') { + while self.peek_next().is_some_and(|c| c != '}') { if require_comma { self.consume(',')?; } require_comma = true; let key = self.parse_string()?; - self.consume(':')?; + self.consume_next(':')?; let value = self.parse_value()?; if members.insert(key.clone(), value).is_some() { return Err(ParseError::Other(format!( @@ -572,7 +584,7 @@ pub mod decode { .into()); } } - self.consume('}')?; + self.consume_next('}')?; Ok(JsonValue::Object(members)) } Some(c) => Err(ParseError::InvalidToken(c).into()), @@ -580,7 +592,7 @@ pub mod decode { } fn parse_string(&mut self) -> crate::Result { - self.consume('\"')?; + self.consume_next('\"')?; let mut result = String::new(); loop { let c = self.advance()?; @@ -631,7 +643,7 @@ pub mod decode { fn parse_number(&mut self) -> crate::Result { let mut num_str = String::new(); - if self.discard_peek().is_some_and(|c| c == '-') { + if self.peek_next().is_some_and(|c| c == '-') { num_str.push(self.advance()?); } while self.peek().is_some_and(|c| c.is_ascii_digit()) { From 1bb665af45ad149c50facaaff5776c1b753ffcb3 Mon Sep 17 00:00:00 2001 From: Ben Jackson Date: Wed, 3 Dec 2025 20:36:56 +0000 Subject: [PATCH 11/29] Very dumb, but seemingly working, union parsing --- capnp/src/json.rs | 324 +++++++++++++++++++++++++++++++++----------- capnpc/test/json.rs | 141 ++++++++++++++++++- 2 files changed, 385 insertions(+), 80 deletions(-) diff --git a/capnp/src/json.rs b/capnp/src/json.rs index a1c6e0799..ee7447c75 100644 --- a/capnp/src/json.rs +++ b/capnp/src/json.rs @@ -138,13 +138,14 @@ pub mod encode { discriminator: None, data_encoding: DataEncoding::Default, }; - serialize_value_to(writer, reader.into(), &meta) + serialize_value_to(writer, reader.into(), &meta, &mut true) } fn serialize_value_to( writer: &mut W, reader: crate::dynamic_value::Reader<'_>, meta: &EncodingOptions<'_, '_>, + first: &mut bool, ) -> crate::Result<()> where W: std::io::Write, @@ -196,7 +197,9 @@ pub mod encode { crate::dynamic_value::Reader::Data(data) => { write_data(writer, data, meta.data_encoding) } - crate::dynamic_value::Reader::Struct(reader) => write_object(writer, reader, meta), + crate::dynamic_value::Reader::Struct(reader) => { + write_object(writer, reader, meta, first) + } crate::dynamic_value::Reader::List(reader) => write_array(writer, reader.iter(), meta), crate::dynamic_value::Reader::AnyPointer(_) => Err(crate::Error::unimplemented( "AnyPointer cannot be represented in JSON".into(), @@ -269,7 +272,7 @@ pub mod encode { write!(writer, ",")?; } first = false; - serialize_value_to(writer, item?, meta)?; + serialize_value_to(writer, item?, meta, &mut true)?; } write!(writer, "]")?; Ok(()) @@ -279,6 +282,7 @@ pub mod encode { writer: &mut W, reader: crate::dynamic_struct::Reader<'reader>, meta: &EncodingOptions<'_, '_>, + first: &mut bool, ) -> crate::Result<()> { let (flatten, field_prefix) = if let Some(flatten_options) = &meta.flatten { ( @@ -293,6 +297,34 @@ pub mod encode { (false, std::borrow::Cow::Borrowed("")) }; + let mut my_first = true; + + let first = if !flatten { + write!(writer, "{{")?; + &mut my_first + } else { + first + }; + for field in reader.get_schema().get_non_union_fields()? { + if !reader.has(field)? { + continue; + } + let field_meta = EncodingOptions::from_field(&field_prefix, &field)?; + if field_meta.flatten.is_none() { + if !*first { + write!(writer, ",")?; + } + *first = false; + write_string( + writer, + format!("{}{}", field_prefix, field_meta.name).as_str(), + )?; + write!(writer, ":")?; + } + let field_value = reader.get(field)?; + serialize_value_to(writer, field_value, &field_meta, first)?; + } + // Comment copied verbatim from the Cap'n Proto C++ implementation: // There are two cases of unions: // * Named unions, which are special cases of named groups. In this case, the union may be @@ -314,67 +346,46 @@ pub mod encode { .ok() .map(|v| v.downcast_struct::()) }); + let discriminator = meta.discriminator.or(struct_discriminator); - if !flatten { - write!(writer, "{{")?; - } - let mut first = true; - for field in reader.get_schema().get_fields()? { - if !reader.has(field)? { - continue; - } - let field_meta = EncodingOptions::from_field(&field_prefix, &field)?; - let mut value_name = field_meta.name; - if field.get_proto().get_discriminant_value() - != crate::schema_capnp::field::NO_DISCRIMINANT - { - if let Some(active_union_member) = reader.which()? { - let active_union_member_meta = - EncodingOptions::from_field(&field_prefix, &active_union_member)?; - if field.get_proto().get_discriminant_value() - != active_union_member.get_proto().get_discriminant_value() - { - // Skip union members that are not set. - continue; + if let Some(active_union_member) = reader.which()? { + let active_union_member_meta = + EncodingOptions::from_field(&field_prefix, &active_union_member)?; + if reader.has(active_union_member)? { + let mut value_name = active_union_member_meta.name; + if let Some(discriminator) = discriminator { + // write out the discriminator + if !*first { + write!(writer, ",")?; } - let discriminator = match meta.discriminator { - Some(ref d) => Some(d), - None => struct_discriminator.as_ref(), + *first = false; + let discriminator_name = if discriminator.has_name() { + discriminator.get_name()?.to_str()? + } else { + meta.name }; - if let Some(discriminator) = discriminator { - // write out the discriminator - if !first { - write!(writer, ",")?; - } - first = false; - let discriminator_name = if discriminator.has_name() { - discriminator.get_name()?.to_str()? - } else { - meta.name - }; - if discriminator.has_value_name() { - value_name = discriminator.get_value_name()?.to_str()?; - } + if discriminator.has_value_name() { + value_name = discriminator.get_value_name()?.to_str()?; + } - write_string( - writer, - format!("{}{}", field_prefix, discriminator_name).as_str(), - )?; - write!(writer, ":")?; - write_string(writer, active_union_member_meta.name)?; + write_string( + writer, + format!("{}{}", field_prefix, discriminator_name).as_str(), + )?; + write!(writer, ":")?; + write_string(writer, active_union_member_meta.name)?; + } + if active_union_member_meta.flatten.is_none() { + if !*first { + write!(writer, ",")?; } + *first = false; + write_string(writer, format!("{}{}", field_prefix, value_name).as_str())?; + write!(writer, ":")?; } + let field_value = reader.get(active_union_member)?; + serialize_value_to(writer, field_value, &active_union_member_meta, first)?; } - if !first { - write!(writer, ",")?; - } - first = false; - if field_meta.flatten.is_none() { - write_string(writer, format!("{}{}", field_prefix, value_name).as_str())?; - write!(writer, ":")?; - } - let field_value = reader.get(field)?; - serialize_value_to(writer, field_value, &field_meta)?; } if !flatten { write!(writer, "}}")?; @@ -678,12 +689,12 @@ pub mod decode { discriminator: None, data_encoding: DataEncoding::Default, }; - let JsonValue::Object(value) = value else { + let JsonValue::Object(mut value) = value else { return Err(crate::Error::failed( "Top-level JSON value must be an object".into(), )); }; - decode_struct(value, builder, &meta) + decode_struct(&mut value, builder, &meta) } fn decode_primitive<'json, 'meta>( @@ -943,7 +954,7 @@ pub mod decode { match list_builder.element_type().which() { crate::introspect::TypeVariant::Struct(_sub_element_schema) => { for (i, item_value) in field_values.drain(..).enumerate() { - let JsonValue::Object(item_value) = item_value else { + let JsonValue::Object(mut item_value) = item_value else { return Err(crate::Error::failed(format!( "Expected object for struct list field {}", field_meta.name @@ -953,7 +964,7 @@ pub mod decode { .reborrow() .get(i as u32)? .downcast::(); - decode_struct(item_value, struct_builder, field_meta)?; + decode_struct(&mut item_value, struct_builder, field_meta)?; } Ok(()) } @@ -990,34 +1001,57 @@ pub mod decode { } fn decode_struct( - mut value: HashMap, + value: &mut HashMap, mut builder: crate::dynamic_struct::Builder<'_>, meta: &EncodingOptions, ) -> crate::Result<()> { - for field in builder.get_schema().get_fields()? { - let field_meta = EncodingOptions::from_field(meta.prefix, &field)?; - let mut field_value = match value.remove(field_meta.name) { - Some(v) => v, - None => continue, - }; + let field_prefix = if let Some(flatten_options) = &meta.flatten { + std::borrow::Cow::Owned(format!( + "{}{}", + meta.prefix, + flatten_options.get_prefix()?.to_str()? + )) + } else { + std::borrow::Cow::Borrowed("") + }; - // TODO: Handle (un)flattening, unions, discriminators, etc. + for field in builder.get_schema().get_non_union_fields()? { + // + // TODO: Handle unions, discriminators, etc. + // + let field_meta = EncodingOptions::from_field(meta.prefix, &field)?; + let field_name = format!("{}{}", field_prefix, field_meta.name); match field.get_type().which() { crate::introspect::TypeVariant::Struct(_struct_schema) => { - let JsonValue::Object(field_value) = field_value else { - return Err(crate::Error::failed(format!( - "Expected object for field {}", - field_meta.name - ))); - }; let struct_builder = builder .reborrow() .init(field)? .downcast::(); - decode_struct(field_value, struct_builder, &field_meta)?; + if field_meta.flatten.is_none() { + let field_value = match value.remove(&field_name) { + Some(v) => v, + None => continue, + }; + + let JsonValue::Object(mut field_value) = field_value else { + return Err(crate::Error::failed(format!( + "Expected object for field {}", + field_meta.name + ))); + }; + decode_struct(&mut field_value, struct_builder, &field_meta)?; + } else { + // Flattened struct; pass the JsonValue at this level down + decode_struct(value, struct_builder, &field_meta)?; + } } crate::introspect::TypeVariant::List(_element_type) => { + let field_value = match value.remove(&field_name) { + Some(v) => v, + None => continue, + }; + let JsonValue::Array(field_value) = field_value else { return Err(crate::Error::failed(format!( "Expected array for field {}", @@ -1043,6 +1077,11 @@ pub mod decode { } _ => { + let mut field_value = match value.remove(&field_name) { + Some(v) => v, + None => continue, + }; + builder.set( field, decode_primitive(&mut field_value, &field.get_type(), &field_meta)?, @@ -1051,17 +1090,143 @@ pub mod decode { } } + let struct_discriminator = builder + .get_schema() + .get_annotations()? + .iter() + .find(|a| a.get_id() == json_capnp::discriminator::ID) + .and_then(|annotation| { + annotation + .get_value() + .ok() + .map(|v| v.downcast_struct::()) + }); + let discriminator = meta.discriminator.or(struct_discriminator); + + let discriminant = match discriminator { + Some(discriminator) => { + let discriminator_name = if discriminator.has_name() { + discriminator.get_name()?.to_str()? + } else { + meta.name + }; + let field_name = format!("{}{}", field_prefix, discriminator_name); + if let Some(JsonValue::String(discriminant)) = value.remove(&field_name) { + Some(discriminant) + } else { + None + } + } + None => { + // find the first field that exists matching a union field? + let mut discriminant = None; + for field in builder.get_schema().get_union_fields()? { + let field_meta = EncodingOptions::from_field(meta.prefix, &field)?; + let field_name = format!("{}{}", field_prefix, field_meta.name); + if value.contains_key(&field_name) { + discriminant = Some(field_meta.name.to_string()); + break; + } + } + discriminant + } + }; + if let Some(discriminant) = discriminant { + for field in builder.get_schema().get_union_fields()? { + let field_meta = EncodingOptions::from_field(meta.prefix, &field)?; + if field_meta.name != discriminant { + continue; + } + let value_name = if let Some(discriminator) = discriminator { + if discriminator.has_value_name() { + discriminator.get_value_name()?.to_str()? + } else { + field_meta.name + } + } else { + field_meta.name + }; + match field.get_type().which() { + crate::introspect::TypeVariant::Struct(_struct_schema) => { + let struct_builder = builder + .reborrow() + .init(field)? + .downcast::(); + if field_meta.flatten.is_none() { + let field_value = match value.remove(value_name) { + Some(v) => v, + None => continue, + }; + + let JsonValue::Object(mut field_value) = field_value else { + return Err(crate::Error::failed(format!( + "Expected object for field {}", + field_meta.name + ))); + }; + decode_struct(&mut field_value, struct_builder, &field_meta)?; + } else { + // Flattened struct; pass the JsonValue at this level down + decode_struct(value, struct_builder, &field_meta)?; + } + } + crate::introspect::TypeVariant::List(_element_type) => { + let field_value = match value.remove(value_name) { + Some(v) => v, + None => continue, + }; + + let JsonValue::Array(field_value) = field_value else { + return Err(crate::Error::failed(format!( + "Expected array for field {}", + field_meta.name + ))); + }; + let list_builder = builder + .reborrow() + .initn(field, field_value.len() as u32)? + .downcast::(); + decode_list(field_value, list_builder, &field_meta)?; + } + + crate::introspect::TypeVariant::AnyPointer => { + return Err(crate::Error::unimplemented( + "AnyPointer cannot be represented in JSON".into(), + )) + } + crate::introspect::TypeVariant::Capability => { + return Err(crate::Error::unimplemented( + "Capability cannot be represented in JSON".into(), + )) + } + + _ => { + let mut field_value = match value.remove(value_name) { + Some(v) => v, + None => continue, + }; + + builder.set( + field, + decode_primitive(&mut field_value, &field.get_type(), &field_meta)?, + )?; + } + } + } + } + Ok(()) } } mod base64 { + // We don't want to pull in base64 crate just for this. So hand-rolling a + // base64 codec. + const BASE64_CHARS: &[u8; 64] = b"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; pub fn encode(data: &[u8]) -> String { - // We don't want to pull in base64 crate just for this. So hand-rolling a - // base64 encoder. let mut encoded = String::with_capacity(data.len().div_ceil(3) * 4); for chunk in data.chunks(3) { #[allow(clippy::get_first)] @@ -1133,6 +1298,9 @@ mod base64 { } mod hex { + // We don't want to pull in hex crate just for this. So hand-rolling a + // hex codec. + const HEX_CHARS: &[u8; 16] = b"0123456789abcdef"; fn hex_char_to_value(c: u8) -> crate::Result { match c { diff --git a/capnpc/test/json.rs b/capnpc/test/json.rs index 5e5f6ae4b..31e6ca729 100644 --- a/capnpc/test/json.rs +++ b/capnpc/test/json.rs @@ -184,8 +184,8 @@ fn test_unnamed_union() { "{", r#""before":"before","#, r#""middle":1234,"#, - r#""bar":32,"#, - r#""after":"after""#, + r#""after":"after","#, + r#""bar":32"#, "}", ); assert_eq!(expected, json::to_json(root.reborrow_as_reader()).unwrap()); @@ -506,3 +506,140 @@ fn test_decode_simple() -> capnp::Result<()> { Ok(()) } + +#[test] +fn test_encode_with_empty_flattened() -> capnp::Result<()> { + let mut builder = capnp::message::Builder::new_default(); + let root = builder.init_root::>(); + + assert_eq!( + r#"{"flatFoo":0,"renamed-flatBaz":{"hello":false},"pfx.renamed-bar":0,"pfx.baz":{"hello":false},"union-type":"foo","multiMember":0,"simpleGroup":{},"unionWithVoid":{"type":"intValue","intValue":0}}"#, + json::to_json(root.reborrow_as_reader())? + ); + + Ok(()) +} + +#[test] +fn test_decode_flattened() -> capnp::Result<()> { + let j = r#" + { + "names-can_contain!anything Really": "Some Field", + "flatFoo": 1234, + "flatBar": "0xBaa", + "renamed-flatBaz": {"hello": true}, + "flatQux": "Qux", + "pfx.baz": {"hello": true}, + "union-type": "renamed-bar", + "barMember": 2731, + "multiMember": "Member", + "bUnion": "renamed-bar", + "bValue": 100 + } + "#; + let mut builder = capnp::message::Builder::new_default(); + let mut root = + builder.init_root::>(); + json::from_json(j, root.reborrow())?; + + println!("{}", json::to_json(root.reborrow_as_reader())?); + + let reader = root.into_reader(); + assert_eq!("Some Field", reader.get_some_field()?.to_str()?); + assert_eq!(1234, reader.get_a_group().get_flat_foo()); + assert_eq!("0xBaa", reader.get_a_group().get_flat_bar()?.to_str()?); + assert_eq!(true, reader.get_a_group().get_flat_baz().get_hello()); + assert_eq!( + "Qux", + reader + .get_a_group() + .get_double_flat() + .get_flat_qux()? + .to_str()? + ); + assert_eq!(true, reader.get_prefixed_group().get_baz().get_hello()); + assert!(matches!( + reader.get_a_union().which()?, + crate::json_test_capnp::test_json_annotations::a_union::Bar(_) + )); + { + let bar = match reader.get_a_union().which()? { + crate::json_test_capnp::test_json_annotations::a_union::Bar(b) => b, + _ => panic!("Expected Bar"), + }; + assert_eq!(2731, bar.get_bar_member()); + assert_eq!("Member", bar.get_multi_member()?.to_str()?); + } + assert!(matches!( + reader.get_b_union().which()?, + crate::json_test_capnp::test_json_annotations::b_union::Bar(_) + )); + { + let bar = match reader.get_b_union().which()? { + crate::json_test_capnp::test_json_annotations::b_union::Bar(b) => b, + _ => panic!("Expected Bar"), + }; + assert_eq!(100, bar); + } + + Ok(()) +} + +#[test] +fn test_decode_base64_union() -> capnp::Result<()> { + { + let j = r#" + { + "foo":"3q2+7w==" + } + "#; + let mut builder = capnp::message::Builder::new_default(); + let mut root = + builder.init_root::>(); + json::from_json(j, root.reborrow())?; + + println!("{}", json::to_json(root.reborrow_as_reader())?); + + let reader = root.into_reader(); + assert!(matches!( + reader.which()?, + crate::json_test_capnp::test_base64_union::Foo(_) + )); + { + let foo = match reader.which()? { + crate::json_test_capnp::test_base64_union::Foo(f) => f, + _ => panic!("Expected Foo"), + }?; + assert_eq!(&[0xde, 0xad, 0xbe, 0xef], foo); + } + } + + { + let j = r#" + { + "bar":"To the bar!" + } + "#; + let mut builder = capnp::message::Builder::new_default(); + let mut root = + builder.init_root::>(); + json::from_json(j, root.reborrow())?; + + println!("{}", json::to_json(root.reborrow_as_reader())?); + + let reader = root.into_reader(); + assert!(matches!( + reader.which()?, + crate::json_test_capnp::test_base64_union::Bar(_) + )); + { + let bar = match reader.which()? { + crate::json_test_capnp::test_base64_union::Bar(b) => b?, + _ => panic!("Expected Foo"), + }; + assert_eq!("To the bar!", bar.to_str()?); + } + } + Ok(()) +} + From 7597620b29cad275fd41acc2fe0864acab32a00e Mon Sep 17 00:00:00 2001 From: Ben Jackson Date: Wed, 3 Dec 2025 20:47:39 +0000 Subject: [PATCH 12/29] Test for renaming with anon unions --- capnp/src/json.rs | 2 + capnpc/test/json-test.capnp | 7 +++ capnpc/test/json.rs | 101 +++++++++++++++++++++++++++++++++--- 3 files changed, 102 insertions(+), 8 deletions(-) diff --git a/capnp/src/json.rs b/capnp/src/json.rs index ee7447c75..972531f73 100644 --- a/capnp/src/json.rs +++ b/capnp/src/json.rs @@ -1146,6 +1146,8 @@ pub mod decode { } else { field_meta.name }; + // TODO: factor out the following block (it's copypaste) + // The problem is we have continue and stuff in the block match field.get_type().which() { crate::introspect::TypeVariant::Struct(_struct_schema) => { let struct_builder = builder diff --git a/capnpc/test/json-test.capnp b/capnpc/test/json-test.capnp index d52188063..58234942b 100644 --- a/capnpc/test/json-test.capnp +++ b/capnpc/test/json-test.capnp @@ -122,6 +122,13 @@ struct TestBase64Union { } } +struct TestRenamedAnonUnion { + union { + foo @0 :Data $Json.base64 $Json.name("renamed-foo"); + bar @1 :Text; + } +} + struct NestedHex { dataAllTheWayDown @0 : List(List(Data)) $Json.hex; } diff --git a/capnpc/test/json.rs b/capnpc/test/json.rs index 31e6ca729..6dfb641e2 100644 --- a/capnpc/test/json.rs +++ b/capnpc/test/json.rs @@ -589,10 +589,10 @@ fn test_decode_flattened() -> capnp::Result<()> { fn test_decode_base64_union() -> capnp::Result<()> { { let j = r#" - { - "foo":"3q2+7w==" - } - "#; + { + "foo":"3q2+7w==" + } + "#; let mut builder = capnp::message::Builder::new_default(); let mut root = builder.init_root::>(); @@ -616,10 +616,10 @@ fn test_decode_base64_union() -> capnp::Result<()> { { let j = r#" - { - "bar":"To the bar!" - } - "#; + { + "bar":"To the bar!" + } + "#; let mut builder = capnp::message::Builder::new_default(); let mut root = builder.init_root::>(); @@ -640,6 +640,91 @@ fn test_decode_base64_union() -> capnp::Result<()> { assert_eq!("To the bar!", bar.to_str()?); } } + + // When both variants are present, we pick the first one in the spec + { + let j = r#" + { + "bar":"To the bar!", + "foo":"3q2+7w==" + } + "#; + let mut builder = capnp::message::Builder::new_default(); + let mut root = + builder.init_root::>(); + json::from_json(j, root.reborrow())?; + + println!("{}", json::to_json(root.reborrow_as_reader())?); + + let reader = root.into_reader(); + assert!(matches!( + reader.which()?, + crate::json_test_capnp::test_base64_union::Foo(_) + )); + { + let foo = match reader.which()? { + crate::json_test_capnp::test_base64_union::Foo(f) => f, + _ => panic!("Expected Foo"), + }?; + assert_eq!(&[0xde, 0xad, 0xbe, 0xef], foo); + } + } + + { + let j = r#" + { + "bar":"To the bar!", + "foo":"3q2+7w==" + } + "#; + let mut builder = capnp::message::Builder::new_default(); + let mut root = + builder.init_root::>(); + json::from_json(j, root.reborrow())?; + + println!("{}", json::to_json(root.reborrow_as_reader())?); + + let reader = root.into_reader(); + assert!(matches!( + reader.which()?, + crate::json_test_capnp::test_renamed_anon_union::Bar(_) + )); + { + let bar = match reader.which()? { + crate::json_test_capnp::test_renamed_anon_union::Bar(b) => b?, + _ => panic!("Expected Foo"), + }; + assert_eq!("To the bar!", bar.to_str()?); + } + } + + { + let j = r#" + { + "bar":"To the bar!", + "renamed-foo":"3q2+7w==" + } + "#; + let mut builder = capnp::message::Builder::new_default(); + let mut root = + builder.init_root::>(); + json::from_json(j, root.reborrow())?; + + println!("{}", json::to_json(root.reborrow_as_reader())?); + + let reader = root.into_reader(); + assert!(matches!( + reader.which()?, + crate::json_test_capnp::test_renamed_anon_union::Foo(_) + )); + { + let foo = match reader.which()? { + crate::json_test_capnp::test_renamed_anon_union::Foo(f) => f, + _ => panic!("Expected Foo"), + }?; + assert_eq!(&[0xde, 0xad, 0xbe, 0xef], foo); + } + } Ok(()) } From c2ce7936983b44c96d85ca01798cc28288780317 Mon Sep 17 00:00:00 2001 From: Ben Jackson Date: Wed, 3 Dec 2025 21:08:51 +0000 Subject: [PATCH 13/29] Factor out duplicated struct member parsing --- capnp/src/json.rs | 127 ++++++++++++-------------------------------- capnpc/test/json.rs | 12 ----- 2 files changed, 34 insertions(+), 105 deletions(-) diff --git a/capnp/src/json.rs b/capnp/src/json.rs index 972531f73..71906a461 100644 --- a/capnp/src/json.rs +++ b/capnp/src/json.rs @@ -1015,13 +1015,13 @@ pub mod decode { std::borrow::Cow::Borrowed("") }; - for field in builder.get_schema().get_non_union_fields()? { - // - // TODO: Handle unions, discriminators, etc. - // - let field_meta = EncodingOptions::from_field(meta.prefix, &field)?; - let field_name = format!("{}{}", field_prefix, field_meta.name); - + fn decode_member( + mut builder: crate::dynamic_struct::Builder<'_>, + field: crate::schema::Field, + field_meta: &EncodingOptions, + value: &mut HashMap, + value_name: &str, + ) -> crate::Result<()> { match field.get_type().which() { crate::introspect::TypeVariant::Struct(_struct_schema) => { let struct_builder = builder @@ -1029,9 +1029,9 @@ pub mod decode { .init(field)? .downcast::(); if field_meta.flatten.is_none() { - let field_value = match value.remove(&field_name) { + let field_value = match value.remove(value_name) { Some(v) => v, - None => continue, + None => return Ok(()), }; let JsonValue::Object(mut field_value) = field_value else { @@ -1040,16 +1040,15 @@ pub mod decode { field_meta.name ))); }; - decode_struct(&mut field_value, struct_builder, &field_meta)?; + decode_struct(&mut field_value, struct_builder, field_meta)?; } else { // Flattened struct; pass the JsonValue at this level down - decode_struct(value, struct_builder, &field_meta)?; + decode_struct(value, struct_builder, field_meta)?; } } crate::introspect::TypeVariant::List(_element_type) => { - let field_value = match value.remove(&field_name) { - Some(v) => v, - None => continue, + let Some(field_value) = value.remove(value_name) else { + return Ok(()); }; let JsonValue::Array(field_value) = field_value else { @@ -1062,7 +1061,7 @@ pub mod decode { .reborrow() .initn(field, field_value.len() as u32)? .downcast::(); - decode_list(field_value, list_builder, &field_meta)?; + decode_list(field_value, list_builder, field_meta)?; } crate::introspect::TypeVariant::AnyPointer => { @@ -1077,17 +1076,24 @@ pub mod decode { } _ => { - let mut field_value = match value.remove(&field_name) { - Some(v) => v, - None => continue, + let Some(mut field_value) = value.remove(value_name) else { + return Ok(()); }; builder.set( field, - decode_primitive(&mut field_value, &field.get_type(), &field_meta)?, + decode_primitive(&mut field_value, &field.get_type(), field_meta)?, )?; } } + Ok(()) + } + + for field in builder.get_schema().get_non_union_fields()? { + let field_meta = EncodingOptions::from_field(meta.prefix, &field)?; + let field_name = format!("{}{}", field_prefix, field_meta.name); + + decode_member(builder.reborrow(), field, &field_meta, value, &field_name)?; } let struct_discriminator = builder @@ -1103,6 +1109,9 @@ pub mod decode { }); let discriminator = meta.discriminator.or(struct_discriminator); + // FIXME: refactor this to only loop through union memberes once; each + // iteration check if it matches the discriminant, *or* the requisite + // named field is present, then decode and break; let discriminant = match discriminator { Some(discriminator) => { let discriminator_name = if discriminator.has_name() { @@ -1146,74 +1155,8 @@ pub mod decode { } else { field_meta.name }; - // TODO: factor out the following block (it's copypaste) - // The problem is we have continue and stuff in the block - match field.get_type().which() { - crate::introspect::TypeVariant::Struct(_struct_schema) => { - let struct_builder = builder - .reborrow() - .init(field)? - .downcast::(); - if field_meta.flatten.is_none() { - let field_value = match value.remove(value_name) { - Some(v) => v, - None => continue, - }; - - let JsonValue::Object(mut field_value) = field_value else { - return Err(crate::Error::failed(format!( - "Expected object for field {}", - field_meta.name - ))); - }; - decode_struct(&mut field_value, struct_builder, &field_meta)?; - } else { - // Flattened struct; pass the JsonValue at this level down - decode_struct(value, struct_builder, &field_meta)?; - } - } - crate::introspect::TypeVariant::List(_element_type) => { - let field_value = match value.remove(value_name) { - Some(v) => v, - None => continue, - }; - - let JsonValue::Array(field_value) = field_value else { - return Err(crate::Error::failed(format!( - "Expected array for field {}", - field_meta.name - ))); - }; - let list_builder = builder - .reborrow() - .initn(field, field_value.len() as u32)? - .downcast::(); - decode_list(field_value, list_builder, &field_meta)?; - } - - crate::introspect::TypeVariant::AnyPointer => { - return Err(crate::Error::unimplemented( - "AnyPointer cannot be represented in JSON".into(), - )) - } - crate::introspect::TypeVariant::Capability => { - return Err(crate::Error::unimplemented( - "Capability cannot be represented in JSON".into(), - )) - } - - _ => { - let mut field_value = match value.remove(value_name) { - Some(v) => v, - None => continue, - }; - - builder.set( - field, - decode_primitive(&mut field_value, &field.get_type(), &field_meta)?, - )?; - } - } + decode_member(builder.reborrow(), field, &field_meta, value, value_name)?; + break; } } @@ -1221,10 +1164,9 @@ pub mod decode { } } +// We don't want to pull in base64 crate just for this. So hand-rolling a +// base64 codec. mod base64 { - // We don't want to pull in base64 crate just for this. So hand-rolling a - // base64 codec. - const BASE64_CHARS: &[u8; 64] = b"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; @@ -1299,10 +1241,9 @@ mod base64 { } } +// We don't want to pull in hex crate just for this. So hand-rolling a +// hex codec. mod hex { - // We don't want to pull in hex crate just for this. So hand-rolling a - // hex codec. - const HEX_CHARS: &[u8; 16] = b"0123456789abcdef"; fn hex_char_to_value(c: u8) -> crate::Result { match c { diff --git a/capnpc/test/json.rs b/capnpc/test/json.rs index 6dfb641e2..bb50ed82c 100644 --- a/capnpc/test/json.rs +++ b/capnpc/test/json.rs @@ -542,8 +542,6 @@ fn test_decode_flattened() -> capnp::Result<()> { builder.init_root::>(); json::from_json(j, root.reborrow())?; - println!("{}", json::to_json(root.reborrow_as_reader())?); - let reader = root.into_reader(); assert_eq!("Some Field", reader.get_some_field()?.to_str()?); assert_eq!(1234, reader.get_a_group().get_flat_foo()); @@ -598,8 +596,6 @@ fn test_decode_base64_union() -> capnp::Result<()> { builder.init_root::>(); json::from_json(j, root.reborrow())?; - println!("{}", json::to_json(root.reborrow_as_reader())?); - let reader = root.into_reader(); assert!(matches!( reader.which()?, @@ -625,8 +621,6 @@ fn test_decode_base64_union() -> capnp::Result<()> { builder.init_root::>(); json::from_json(j, root.reborrow())?; - println!("{}", json::to_json(root.reborrow_as_reader())?); - let reader = root.into_reader(); assert!(matches!( reader.which()?, @@ -654,8 +648,6 @@ fn test_decode_base64_union() -> capnp::Result<()> { builder.init_root::>(); json::from_json(j, root.reborrow())?; - println!("{}", json::to_json(root.reborrow_as_reader())?); - let reader = root.into_reader(); assert!(matches!( reader.which()?, @@ -682,8 +674,6 @@ fn test_decode_base64_union() -> capnp::Result<()> { builder.init_root::>(); json::from_json(j, root.reborrow())?; - println!("{}", json::to_json(root.reborrow_as_reader())?); - let reader = root.into_reader(); assert!(matches!( reader.which()?, @@ -710,8 +700,6 @@ fn test_decode_base64_union() -> capnp::Result<()> { builder.init_root::>(); json::from_json(j, root.reborrow())?; - println!("{}", json::to_json(root.reborrow_as_reader())?); - let reader = root.into_reader(); assert!(matches!( reader.which()?, From 23222deae529e2999f61e929b5d9c62d227671d4 Mon Sep 17 00:00:00 2001 From: Ben Jackson Date: Wed, 3 Dec 2025 21:55:05 +0000 Subject: [PATCH 14/29] Move to capnp-json crate --- Cargo.toml | 2 + capnp-json/Cargo.toml | 20 + {capnp => capnp-json}/json.capnp | 0 {capnp => capnp-json}/src/json.rs | 288 ++-- capnp-json/src/json_capnp.rs | 1521 +++++++++++++++++++ capnp-json/src/lib.rs | 5 + capnp-json/test/Cargo.toml | 20 + capnp-json/test/build.rs | 9 + {capnpc => capnp-json}/test/json-test.capnp | 0 capnp-json/test/json.rs | 725 +++++++++ capnp-json/test/test.capnp | 863 +++++++++++ capnp/src/json_capnp.rs | 1521 ------------------- capnp/src/lib.rs | 3 - capnpc/test-edition-2015/Cargo.toml | 2 +- capnpc/test-edition-2018/Cargo.toml | 2 +- capnpc/test/build.rs | 2 - capnpc/test/json.rs | 718 --------- capnpc/test/test.capnp | 65 - capnpc/test/test.rs | 4 - 19 files changed, 3311 insertions(+), 2459 deletions(-) create mode 100644 capnp-json/Cargo.toml rename {capnp => capnp-json}/json.capnp (100%) rename {capnp => capnp-json}/src/json.rs (84%) create mode 100644 capnp-json/src/json_capnp.rs create mode 100644 capnp-json/src/lib.rs create mode 100644 capnp-json/test/Cargo.toml create mode 100644 capnp-json/test/build.rs rename {capnpc => capnp-json}/test/json-test.capnp (100%) create mode 100644 capnp-json/test/json.rs create mode 100644 capnp-json/test/test.capnp delete mode 100644 capnp/src/json_capnp.rs delete mode 100644 capnpc/test/json.rs diff --git a/Cargo.toml b/Cargo.toml index 38e9cb9d1..b682b35eb 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -11,6 +11,7 @@ members = [ "capnpc", "capnp-futures", "capnp-rpc", + "capnp-json", # testing and examples "async-byte-channel", @@ -30,6 +31,7 @@ members = [ "example/addressbook", "example/addressbook_send", "example/fill_random_values", + "capnp-json/test", ] default-members = [ "capnp", diff --git a/capnp-json/Cargo.toml b/capnp-json/Cargo.toml new file mode 100644 index 000000000..eea33e87d --- /dev/null +++ b/capnp-json/Cargo.toml @@ -0,0 +1,20 @@ +[package] + +name = "capnp-json" +version = "0.23.0" +authors = [ "Ben Jackson " ] +license = "MIT" +description = "implementation of the Cap'n Proto JSON codec in rust" +repository = "https://github.com/capnproto/capnproto-rust" +documentation = "https://docs.rs/capnp-rpc/" +categories = ["network-programming"] +autoexamples = false +edition = "2021" + +readme = "README.md" + +[dependencies] +capnp = {version = "0.23.0", path = "../capnp"} + +#[lints] +#workspace = true diff --git a/capnp/json.capnp b/capnp-json/json.capnp similarity index 100% rename from capnp/json.capnp rename to capnp-json/json.capnp diff --git a/capnp/src/json.rs b/capnp-json/src/json.rs similarity index 84% rename from capnp/src/json.rs rename to capnp-json/src/json.rs index 71906a461..c11e87807 100644 --- a/capnp/src/json.rs +++ b/capnp-json/src/json.rs @@ -4,15 +4,15 @@ // encoder, but still dumb as bricks, probably. // // e.g. -// impl ToJson for crate::dynamic_value::Reader<'_> { ... } -// impl ToJson for mycrate::my_capnp::my_struct::Reader<'_> { ... } // more specific +// impl ToJson for capnp::dynamic_value::Reader<'_> { ... } +// impl ToJson for mycapnp::my_capnp::my_struct::Reader<'_> { ... } // more specific // // does that work in rust without specdialization? // pub fn to_json<'reader>( - reader: impl Into>, -) -> crate::Result { + reader: impl Into>, +) -> capnp::Result { let mut writer = std::io::Cursor::new(Vec::with_capacity(4096)); encode::serialize_json_to(&mut writer, reader)?; String::from_utf8(writer.into_inner()).map_err(|e| e.into()) @@ -20,10 +20,10 @@ pub fn to_json<'reader>( pub fn from_json<'segments>( json: &str, - builder: impl Into>, -) -> crate::Result<()> { - let crate::dynamic_value::Builder::Struct(builder) = builder.into() else { - return Err(crate::Error::failed( + builder: impl Into>, +) -> capnp::Result<()> { + let capnp::dynamic_value::Builder::Struct(builder) = builder.into() else { + return Err(capnp::Error::failed( "Top-level JSON value must be an object".into(), )); }; @@ -52,8 +52,8 @@ struct EncodingOptions<'schema, 'prefix> { impl<'schema, 'prefix> EncodingOptions<'schema, 'prefix> { fn from_field( prefix: &'prefix std::borrow::Cow<'schema, str>, - field: &crate::schema::Field, - ) -> crate::Result { + field: &capnp::schema::Field, + ) -> capnp::Result { let mut options = Self { prefix, name: field.get_proto().get_name()?.to_str()?, @@ -67,12 +67,12 @@ impl<'schema, 'prefix> EncodingOptions<'schema, 'prefix> { json_capnp::name::ID => { options.name = anno .get_value()? - .downcast::() + .downcast::() .to_str()?; } json_capnp::base64::ID => { if options.data_encoding != DataEncoding::Default { - return Err(crate::Error::failed( + return Err(capnp::Error::failed( "Cannot specify both base64 and hex annotations on the same field" .into(), )); @@ -81,7 +81,7 @@ impl<'schema, 'prefix> EncodingOptions<'schema, 'prefix> { } json_capnp::hex::ID => { if options.data_encoding != DataEncoding::Default { - return Err(crate::Error::failed( + return Err(capnp::Error::failed( "Cannot specify both base64 and hex annotations on the same field" .into(), )); @@ -105,12 +105,12 @@ impl<'schema, 'prefix> EncodingOptions<'schema, 'prefix> { } if options.data_encoding != DataEncoding::Default { let mut element_type = field.get_type(); - while let crate::introspect::TypeVariant::List(sub_element_type) = element_type.which() + while let capnp::introspect::TypeVariant::List(sub_element_type) = element_type.which() { element_type = sub_element_type; } - if !matches!(element_type.which(), crate::introspect::TypeVariant::Data) { - return Err(crate::Error::failed( + if !matches!(element_type.which(), capnp::introspect::TypeVariant::Data) { + return Err(capnp::Error::failed( "base64/hex annotation can only be applied to Data fields".into(), )); } @@ -126,8 +126,8 @@ pub mod encode { pub fn serialize_json_to<'reader, W>( writer: &mut W, - reader: impl Into>, - ) -> crate::Result<()> + reader: impl Into>, + ) -> capnp::Result<()> where W: std::io::Write, { @@ -143,40 +143,40 @@ pub mod encode { fn serialize_value_to( writer: &mut W, - reader: crate::dynamic_value::Reader<'_>, + reader: capnp::dynamic_value::Reader<'_>, meta: &EncodingOptions<'_, '_>, first: &mut bool, - ) -> crate::Result<()> + ) -> capnp::Result<()> where W: std::io::Write, { match reader { - crate::dynamic_value::Reader::Void => write!(writer, "null").map_err(|e| e.into()), - crate::dynamic_value::Reader::Bool(value) => if value { + capnp::dynamic_value::Reader::Void => write!(writer, "null").map_err(|e| e.into()), + capnp::dynamic_value::Reader::Bool(value) => if value { write!(writer, "true") } else { write!(writer, "false") } .map_err(|e| e.into()), - crate::dynamic_value::Reader::Int8(value) => write_signed_number(writer, value as i64), - crate::dynamic_value::Reader::Int16(value) => write_signed_number(writer, value as i64), - crate::dynamic_value::Reader::Int32(value) => write_signed_number(writer, value as i64), - crate::dynamic_value::Reader::Int64(value) => write_signed_number(writer, value), - crate::dynamic_value::Reader::UInt8(value) => { + capnp::dynamic_value::Reader::Int8(value) => write_signed_number(writer, value as i64), + capnp::dynamic_value::Reader::Int16(value) => write_signed_number(writer, value as i64), + capnp::dynamic_value::Reader::Int32(value) => write_signed_number(writer, value as i64), + capnp::dynamic_value::Reader::Int64(value) => write_signed_number(writer, value), + capnp::dynamic_value::Reader::UInt8(value) => { write_unsigned_number(writer, value as u64) } - crate::dynamic_value::Reader::UInt16(value) => { + capnp::dynamic_value::Reader::UInt16(value) => { write_unsigned_number(writer, value as u64) } - crate::dynamic_value::Reader::UInt32(value) => { + capnp::dynamic_value::Reader::UInt32(value) => { write_unsigned_number(writer, value as u64) } - crate::dynamic_value::Reader::UInt64(value) => write_unsigned_number(writer, value), - crate::dynamic_value::Reader::Float32(value) => { + capnp::dynamic_value::Reader::UInt64(value) => write_unsigned_number(writer, value), + capnp::dynamic_value::Reader::Float32(value) => { write_float_number(writer, value as f64) } - crate::dynamic_value::Reader::Float64(value) => write_float_number(writer, value), - crate::dynamic_value::Reader::Enum(value) => { + capnp::dynamic_value::Reader::Float64(value) => write_float_number(writer, value), + capnp::dynamic_value::Reader::Enum(value) => { if let Some(enumerant) = value.get_enumerant()? { let value = enumerant .get_annotations()? @@ -185,7 +185,7 @@ pub mod encode { .and_then(|a| { a.get_value() .ok() - .map(|v| v.downcast::().to_str()) + .map(|v| v.downcast::().to_str()) }) .unwrap_or(enumerant.get_proto().get_name()?.to_str()); write_string(writer, value?) @@ -193,34 +193,34 @@ pub mod encode { write_unsigned_number(writer, value.get_value() as u64) } } - crate::dynamic_value::Reader::Text(reader) => write_string(writer, reader.to_str()?), - crate::dynamic_value::Reader::Data(data) => { + capnp::dynamic_value::Reader::Text(reader) => write_string(writer, reader.to_str()?), + capnp::dynamic_value::Reader::Data(data) => { write_data(writer, data, meta.data_encoding) } - crate::dynamic_value::Reader::Struct(reader) => { + capnp::dynamic_value::Reader::Struct(reader) => { write_object(writer, reader, meta, first) } - crate::dynamic_value::Reader::List(reader) => write_array(writer, reader.iter(), meta), - crate::dynamic_value::Reader::AnyPointer(_) => Err(crate::Error::unimplemented( + capnp::dynamic_value::Reader::List(reader) => write_array(writer, reader.iter(), meta), + capnp::dynamic_value::Reader::AnyPointer(_) => Err(capnp::Error::unimplemented( "AnyPointer cannot be represented in JSON".into(), )), - crate::dynamic_value::Reader::Capability(_) => Err(crate::Error::unimplemented( + capnp::dynamic_value::Reader::Capability(_) => Err(capnp::Error::unimplemented( "Capability cannot be represented in JSON".into(), )), } } - // TODO: use crate::io::Write ? - fn write_unsigned_number(writer: &mut W, value: u64) -> crate::Result<()> { + // TODO: use capnp::io::Write ? + fn write_unsigned_number(writer: &mut W, value: u64) -> capnp::Result<()> { write!(writer, "{}", value)?; Ok(()) } - fn write_signed_number(writer: &mut W, value: i64) -> crate::Result<()> { + fn write_signed_number(writer: &mut W, value: i64) -> capnp::Result<()> { write!(writer, "{}", value)?; Ok(()) } - fn write_float_number(writer: &mut W, value: f64) -> crate::Result<()> { + fn write_float_number(writer: &mut W, value: f64) -> capnp::Result<()> { // From the C++ codec comments: // Inf, -inf and NaN are not allowed in the JSON spec. Storing into string. @@ -238,7 +238,7 @@ pub mod encode { Ok(()) } - fn write_string(writer: &mut W, value: &str) -> crate::Result<()> { + fn write_string(writer: &mut W, value: &str) -> capnp::Result<()> { write!(writer, "\"")?; for c in value.chars() { match c { @@ -261,9 +261,9 @@ pub mod encode { writer: &mut W, items: I, meta: &EncodingOptions, - ) -> crate::Result<()> + ) -> capnp::Result<()> where - I: Iterator>>, + I: Iterator>>, { write!(writer, "[")?; let mut first = true; @@ -280,10 +280,10 @@ pub mod encode { fn write_object<'reader, W: std::io::Write>( writer: &mut W, - reader: crate::dynamic_struct::Reader<'reader>, + reader: capnp::dynamic_struct::Reader<'reader>, meta: &EncodingOptions<'_, '_>, first: &mut bool, - ) -> crate::Result<()> { + ) -> capnp::Result<()> { let (flatten, field_prefix) = if let Some(flatten_options) = &meta.flatten { ( true, @@ -395,9 +395,9 @@ pub mod encode { fn write_data( writer: &mut W, - data: crate::data::Reader<'_>, + data: capnp::data::Reader<'_>, encoding: DataEncoding, - ) -> crate::Result<()> { + ) -> capnp::Result<()> { match encoding { DataEncoding::Default => { write!(writer, "[")?; @@ -429,17 +429,17 @@ pub mod decode { Other(String), } - impl From for crate::Error { + impl From for capnp::Error { fn from(err: ParseError) -> Self { match err { ParseError::UnexpectedEndOfInput => { - crate::Error::failed("Unexpected end of input while parsing JSON".into()) + capnp::Error::failed("Unexpected end of input while parsing JSON".into()) } ParseError::InvalidToken(c) => { - crate::Error::failed(format!("Invalid token '{c}' while parsing JSON")) + capnp::Error::failed(format!("Invalid token '{c}' while parsing JSON")) } // TODO: Use better values here? - ParseError::Other(msg) => crate::Error::failed(msg), + ParseError::Other(msg) => capnp::Error::failed(msg), } } } @@ -494,14 +494,14 @@ pub mod decode { } /// Consume the current value - fn advance(&mut self) -> crate::Result { + fn advance(&mut self) -> capnp::Result { self.input_iter .next() .ok_or(ParseError::UnexpectedEndOfInput.into()) } /// Consume the current value if it matches `c`, otherwise error - fn consume(&mut self, c: char) -> crate::Result { + fn consume(&mut self, c: char) -> capnp::Result { match self.advance()? { p if p == c => Ok(p), p => Err(ParseError::InvalidToken(p).into()), @@ -509,7 +509,7 @@ pub mod decode { } /// Advance past any whitespace and consume the current value if it matches `c`, otherwise error - fn consume_next(&mut self, c: char) -> crate::Result { + fn consume_next(&mut self, c: char) -> capnp::Result { self.discard_whitespace(); match self.advance()? { p if p == c => Ok(p), @@ -527,7 +527,7 @@ pub mod decode { } } - fn parse_value(&mut self) -> crate::Result { + fn parse_value(&mut self) -> capnp::Result { match self.peek_next() { None => Err(ParseError::UnexpectedEndOfInput.into()), Some('n') => { @@ -602,7 +602,7 @@ pub mod decode { } } - fn parse_string(&mut self) -> crate::Result { + fn parse_string(&mut self) -> capnp::Result { self.consume_next('\"')?; let mut result = String::new(); loop { @@ -652,7 +652,7 @@ pub mod decode { } } - fn parse_number(&mut self) -> crate::Result { + fn parse_number(&mut self) -> capnp::Result { let mut num_str = String::new(); if self.peek_next().is_some_and(|c| c == '-') { num_str.push(self.advance()?); @@ -679,7 +679,7 @@ pub mod decode { } } - pub fn parse(json: &str, builder: crate::dynamic_struct::Builder<'_>) -> crate::Result<()> { + pub fn parse(json: &str, builder: capnp::dynamic_struct::Builder<'_>) -> capnp::Result<()> { let mut parser = Parser::new(json.chars()); let value = parser.parse_value()?; let meta = EncodingOptions { @@ -690,7 +690,7 @@ pub mod decode { data_encoding: DataEncoding::Default, }; let JsonValue::Object(mut value) = value else { - return Err(crate::Error::failed( + return Err(capnp::Error::failed( "Top-level JSON value must be an object".into(), )); }; @@ -699,102 +699,102 @@ pub mod decode { fn decode_primitive<'json, 'meta>( field_value: &'json mut JsonValue, - field_type: &'meta crate::introspect::Type, + field_type: &'meta capnp::introspect::Type, field_meta: &'meta EncodingOptions, - ) -> crate::Result> { + ) -> capnp::Result> { match field_type.which() { - crate::introspect::TypeVariant::Void => { + capnp::introspect::TypeVariant::Void => { if !matches!(field_value, JsonValue::Null) { - Err(crate::Error::failed(format!( + Err(capnp::Error::failed(format!( "Expected null for void field {}", field_meta.name ))) } else { - Ok(crate::dynamic_value::Reader::Void) + Ok(capnp::dynamic_value::Reader::Void) } } - crate::introspect::TypeVariant::Bool => { + capnp::introspect::TypeVariant::Bool => { let JsonValue::Boolean(field_value) = field_value else { - return Err(crate::Error::failed(format!( + return Err(capnp::Error::failed(format!( "Expected boolean for field {}", field_meta.name ))); }; Ok((*field_value).into()) } - crate::introspect::TypeVariant::Int8 => { + capnp::introspect::TypeVariant::Int8 => { let JsonValue::Number(field_value) = field_value else { - return Err(crate::Error::failed(format!( + return Err(capnp::Error::failed(format!( "Expected number for field {}", field_meta.name ))); }; Ok((*field_value as i8).into()) } - crate::introspect::TypeVariant::Int16 => { + capnp::introspect::TypeVariant::Int16 => { let JsonValue::Number(field_value) = field_value else { - return Err(crate::Error::failed(format!( + return Err(capnp::Error::failed(format!( "Expected number for field {}", field_meta.name ))); }; Ok((*field_value as i16).into()) } - crate::introspect::TypeVariant::Int32 => { + capnp::introspect::TypeVariant::Int32 => { let JsonValue::Number(field_value) = field_value else { - return Err(crate::Error::failed(format!( + return Err(capnp::Error::failed(format!( "Expected number for field {}", field_meta.name ))); }; Ok((*field_value as i32).into()) } - crate::introspect::TypeVariant::Int64 => { + capnp::introspect::TypeVariant::Int64 => { let JsonValue::Number(field_value) = field_value else { - return Err(crate::Error::failed(format!( + return Err(capnp::Error::failed(format!( "Expected number for field {}", field_meta.name ))); }; Ok((*field_value as i64).into()) } - crate::introspect::TypeVariant::UInt8 => { + capnp::introspect::TypeVariant::UInt8 => { let JsonValue::Number(field_value) = field_value else { - return Err(crate::Error::failed(format!( + return Err(capnp::Error::failed(format!( "Expected number for field {}", field_meta.name ))); }; Ok((*field_value as u8).into()) } - crate::introspect::TypeVariant::UInt16 => { + capnp::introspect::TypeVariant::UInt16 => { let JsonValue::Number(field_value) = field_value else { - return Err(crate::Error::failed(format!( + return Err(capnp::Error::failed(format!( "Expected number for field {}", field_meta.name ))); }; Ok((*field_value as u16).into()) } - crate::introspect::TypeVariant::UInt32 => { + capnp::introspect::TypeVariant::UInt32 => { let JsonValue::Number(field_value) = field_value else { - return Err(crate::Error::failed(format!( + return Err(capnp::Error::failed(format!( "Expected number for field {}", field_meta.name ))); }; Ok((*field_value as u32).into()) } - crate::introspect::TypeVariant::UInt64 => { + capnp::introspect::TypeVariant::UInt64 => { let JsonValue::Number(field_value) = field_value else { - return Err(crate::Error::failed(format!( + return Err(capnp::Error::failed(format!( "Expected number for field {}", field_meta.name ))); }; Ok((*field_value as u64).into()) } - crate::introspect::TypeVariant::Float32 => { + capnp::introspect::TypeVariant::Float32 => { let field_value = match field_value { JsonValue::Number(field_value) => *field_value as f32, JsonValue::String(field_value) => match field_value.as_str() { @@ -802,14 +802,14 @@ pub mod decode { "Infinity" => f32::INFINITY, "-Infinity" => f32::NEG_INFINITY, _ => { - return Err(crate::Error::failed(format!( + return Err(capnp::Error::failed(format!( "Expected number for field {}", field_meta.name ))); } }, _ => { - return Err(crate::Error::failed(format!( + return Err(capnp::Error::failed(format!( "Expected number for field {}", field_meta.name ))); @@ -817,7 +817,7 @@ pub mod decode { }; Ok(field_value.into()) } - crate::introspect::TypeVariant::Float64 => { + capnp::introspect::TypeVariant::Float64 => { let field_value = match field_value { JsonValue::Number(field_value) => *field_value, JsonValue::String(field_value) => match field_value.as_str() { @@ -825,14 +825,14 @@ pub mod decode { "Infinity" => f64::INFINITY, "-Infinity" => f64::NEG_INFINITY, _ => { - return Err(crate::Error::failed(format!( + return Err(capnp::Error::failed(format!( "Expected number for field {}", field_meta.name ))); } }, _ => { - return Err(crate::Error::failed(format!( + return Err(capnp::Error::failed(format!( "Expected number for field {}", field_meta.name ))); @@ -840,18 +840,18 @@ pub mod decode { }; Ok(field_value.into()) } - crate::introspect::TypeVariant::Text => { + capnp::introspect::TypeVariant::Text => { let JsonValue::String(field_value) = field_value else { - return Err(crate::Error::failed(format!( + return Err(capnp::Error::failed(format!( "Expected string for field {}", field_meta.name ))); }; Ok((*field_value.as_str()).into()) } - crate::introspect::TypeVariant::Enum(enum_schema) => match field_value { + capnp::introspect::TypeVariant::Enum(enum_schema) => match field_value { JsonValue::String(field_value) => { - let enum_schema = crate::schema::EnumSchema::new(enum_schema); + let enum_schema = capnp::schema::EnumSchema::new(enum_schema); let Some(enum_value) = enum_schema.get_enumerants()?.iter().find(|e| { e.get_proto() .get_name() @@ -859,31 +859,31 @@ pub mod decode { .and_then(|n| n.to_str().ok()) .is_some_and(|s| s == field_value) }) else { - return Err(crate::Error::failed(format!( + return Err(capnp::Error::failed(format!( "Invalid enum value '{}' for field {}", field_value, field_meta.name ))); }; - Ok(crate::dynamic_value::Reader::Enum( - crate::dynamic_value::Enum::new( + Ok(capnp::dynamic_value::Reader::Enum( + capnp::dynamic_value::Enum::new( enum_value.get_ordinal(), enum_value.get_containing_enum(), ), )) } JsonValue::Number(enum_value) => { - let enum_schema = crate::schema::EnumSchema::new(enum_schema); - Ok(crate::dynamic_value::Reader::Enum( - crate::dynamic_value::Enum::new(*enum_value as u16, enum_schema), + let enum_schema = capnp::schema::EnumSchema::new(enum_schema); + Ok(capnp::dynamic_value::Reader::Enum( + capnp::dynamic_value::Enum::new(*enum_value as u16, enum_schema), )) } - _ => Err(crate::Error::failed(format!( + _ => Err(capnp::Error::failed(format!( "Expected string or number for enum field {}", field_meta.name ))), }, - crate::introspect::TypeVariant::Data => match field_meta.data_encoding { + capnp::introspect::TypeVariant::Data => match field_meta.data_encoding { // The reason we have this ugly DataBuffer hack is to ensure that we // can return a Reader from this function whose lifetime is tied to // the field_value, as there is no other buffer we can use. We don't @@ -891,7 +891,7 @@ pub mod decode { // dance could probably be avoided. DataEncoding::Default => { let JsonValue::Array(data_value) = field_value else { - return Err(crate::Error::failed(format!( + return Err(capnp::Error::failed(format!( "Expected array for data field {}", field_meta.name ))); @@ -899,7 +899,7 @@ pub mod decode { let mut data = Vec::with_capacity(data_value.len()); for byte_value in data_value.drain(..) { let JsonValue::Number(byte_value) = byte_value else { - return Err(crate::Error::failed(format!( + return Err(capnp::Error::failed(format!( "Expected number for data byte in field {}", field_meta.name ))); @@ -907,39 +907,39 @@ pub mod decode { data.push(byte_value as u8); } *field_value = JsonValue::DataBuffer(data); - Ok(crate::dynamic_value::Reader::Data(match field_value { + Ok(capnp::dynamic_value::Reader::Data(match field_value { JsonValue::DataBuffer(ref data) => data.as_slice(), _ => unreachable!(), })) } DataEncoding::Base64 => { let JsonValue::String(data_value) = field_value else { - return Err(crate::Error::failed(format!( + return Err(capnp::Error::failed(format!( "Expected string for base64 data field {}", field_meta.name ))); }; *field_value = JsonValue::DataBuffer(base64::decode(data_value)?); - Ok(crate::dynamic_value::Reader::Data(match field_value { + Ok(capnp::dynamic_value::Reader::Data(match field_value { JsonValue::DataBuffer(ref data) => data.as_slice(), _ => unreachable!(), })) } DataEncoding::Hex => { let JsonValue::String(data_value) = field_value else { - return Err(crate::Error::failed(format!( + return Err(capnp::Error::failed(format!( "Expected string for hex data field {}", field_meta.name ))); }; *field_value = JsonValue::DataBuffer(hex::decode(data_value)?); - Ok(crate::dynamic_value::Reader::Data(match field_value { + Ok(capnp::dynamic_value::Reader::Data(match field_value { JsonValue::DataBuffer(ref data) => data.as_slice(), _ => unreachable!(), })) } }, - _ => Err(crate::Error::failed(format!( + _ => Err(capnp::Error::failed(format!( "Unsupported primitive type for field {}", field_meta.name ))), @@ -948,14 +948,14 @@ pub mod decode { fn decode_list( mut field_values: Vec, - mut list_builder: crate::dynamic_list::Builder, + mut list_builder: capnp::dynamic_list::Builder, field_meta: &EncodingOptions, - ) -> crate::Result<()> { + ) -> capnp::Result<()> { match list_builder.element_type().which() { - crate::introspect::TypeVariant::Struct(_sub_element_schema) => { + capnp::introspect::TypeVariant::Struct(_sub_element_schema) => { for (i, item_value) in field_values.drain(..).enumerate() { let JsonValue::Object(mut item_value) = item_value else { - return Err(crate::Error::failed(format!( + return Err(capnp::Error::failed(format!( "Expected object for struct list field {}", field_meta.name ))); @@ -963,15 +963,15 @@ pub mod decode { let struct_builder = list_builder .reborrow() .get(i as u32)? - .downcast::(); + .downcast::(); decode_struct(&mut item_value, struct_builder, field_meta)?; } Ok(()) } - crate::introspect::TypeVariant::List(_sub_element_type) => { + capnp::introspect::TypeVariant::List(_sub_element_type) => { for (i, item_value) in field_values.drain(..).enumerate() { let JsonValue::Array(item_value) = item_value else { - return Err(crate::Error::failed(format!( + return Err(capnp::Error::failed(format!( "Expected array for list field {}", field_meta.name ))); @@ -979,7 +979,7 @@ pub mod decode { let sub_element_builder = list_builder .reborrow() .init(i as u32, item_value.len() as u32)? - .downcast::(); + .downcast::(); decode_list(item_value, sub_element_builder, field_meta)?; } Ok(()) @@ -1002,9 +1002,9 @@ pub mod decode { fn decode_struct( value: &mut HashMap, - mut builder: crate::dynamic_struct::Builder<'_>, + mut builder: capnp::dynamic_struct::Builder<'_>, meta: &EncodingOptions, - ) -> crate::Result<()> { + ) -> capnp::Result<()> { let field_prefix = if let Some(flatten_options) = &meta.flatten { std::borrow::Cow::Owned(format!( "{}{}", @@ -1016,18 +1016,18 @@ pub mod decode { }; fn decode_member( - mut builder: crate::dynamic_struct::Builder<'_>, - field: crate::schema::Field, + mut builder: capnp::dynamic_struct::Builder<'_>, + field: capnp::schema::Field, field_meta: &EncodingOptions, value: &mut HashMap, value_name: &str, - ) -> crate::Result<()> { + ) -> capnp::Result<()> { match field.get_type().which() { - crate::introspect::TypeVariant::Struct(_struct_schema) => { + capnp::introspect::TypeVariant::Struct(_struct_schema) => { let struct_builder = builder .reborrow() .init(field)? - .downcast::(); + .downcast::(); if field_meta.flatten.is_none() { let field_value = match value.remove(value_name) { Some(v) => v, @@ -1035,7 +1035,7 @@ pub mod decode { }; let JsonValue::Object(mut field_value) = field_value else { - return Err(crate::Error::failed(format!( + return Err(capnp::Error::failed(format!( "Expected object for field {}", field_meta.name ))); @@ -1046,13 +1046,13 @@ pub mod decode { decode_struct(value, struct_builder, field_meta)?; } } - crate::introspect::TypeVariant::List(_element_type) => { + capnp::introspect::TypeVariant::List(_element_type) => { let Some(field_value) = value.remove(value_name) else { return Ok(()); }; let JsonValue::Array(field_value) = field_value else { - return Err(crate::Error::failed(format!( + return Err(capnp::Error::failed(format!( "Expected array for field {}", field_meta.name ))); @@ -1060,17 +1060,17 @@ pub mod decode { let list_builder = builder .reborrow() .initn(field, field_value.len() as u32)? - .downcast::(); + .downcast::(); decode_list(field_value, list_builder, field_meta)?; } - crate::introspect::TypeVariant::AnyPointer => { - return Err(crate::Error::unimplemented( + capnp::introspect::TypeVariant::AnyPointer => { + return Err(capnp::Error::unimplemented( "AnyPointer cannot be represented in JSON".into(), )) } - crate::introspect::TypeVariant::Capability => { - return Err(crate::Error::unimplemented( + capnp::introspect::TypeVariant::Capability => { + return Err(capnp::Error::unimplemented( "Capability cannot be represented in JSON".into(), )) } @@ -1198,10 +1198,10 @@ mod base64 { encoded } - pub fn decode(data: &str) -> crate::Result> { + pub fn decode(data: &str) -> capnp::Result> { let bytes = data.as_bytes(); - if bytes.len() % 4 != 0 { - return Err(crate::Error::failed( + if !bytes.len().is_multiple_of(4) { + return Err(capnp::Error::failed( "Base64 string length must be a multiple of 4".into(), )); } @@ -1222,7 +1222,7 @@ mod base64 { padding += 1; } _ => { - return Err(crate::Error::failed(format!( + return Err(capnp::Error::failed(format!( "Invalid base64 character: {}", c as char ))); @@ -1245,12 +1245,12 @@ mod base64 { // hex codec. mod hex { const HEX_CHARS: &[u8; 16] = b"0123456789abcdef"; - fn hex_char_to_value(c: u8) -> crate::Result { + fn hex_char_to_value(c: u8) -> capnp::Result { match c { b'0'..=b'9' => Ok(c - b'0'), b'a'..=b'f' => Ok(c - b'a' + 10), b'A'..=b'F' => Ok(c - b'A' + 10), - _ => Err(crate::Error::failed(format!( + _ => Err(capnp::Error::failed(format!( "Invalid hex character: {}", c as char ))), @@ -1268,9 +1268,9 @@ mod hex { encoded } - pub fn decode(data: &str) -> crate::Result> { - if data.len() % 2 != 0 { - return Err(crate::Error::failed( + pub fn decode(data: &str) -> capnp::Result> { + if !data.len().is_multiple_of(2) { + return Err(capnp::Error::failed( "Hex string must have even length".into(), )); } diff --git a/capnp-json/src/json_capnp.rs b/capnp-json/src/json_capnp.rs new file mode 100644 index 000000000..9c35a896f --- /dev/null +++ b/capnp-json/src/json_capnp.rs @@ -0,0 +1,1521 @@ +// @generated by the capnpc-rust plugin to the Cap'n Proto schema compiler. +// DO NOT EDIT. +// source: json.capnp + + +pub mod value { + pub use self::Which::{Null,Boolean,Number,String,Array,Object,Call,Raw}; + + #[derive(Copy, Clone)] + pub struct Owned(()); + impl ::capnp::introspect::Introspect for Owned { fn introspect() -> ::capnp::introspect::Type { ::capnp::introspect::TypeVariant::Struct(::capnp::introspect::RawBrandedStructSchema { generic: &_private::RAW_SCHEMA, field_types: _private::get_field_types, annotation_types: _private::get_annotation_types }).into() } } + impl ::capnp::traits::Owned for Owned { type Reader<'a> = Reader<'a>; type Builder<'a> = Builder<'a>; } + impl ::capnp::traits::OwnedStruct for Owned { type Reader<'a> = Reader<'a>; type Builder<'a> = Builder<'a>; } + impl ::capnp::traits::Pipelined for Owned { type Pipeline = Pipeline; } + + pub struct Reader<'a> { reader: ::capnp::private::layout::StructReader<'a> } + impl <> ::core::marker::Copy for Reader<'_,> {} + impl <> ::core::clone::Clone for Reader<'_,> { + fn clone(&self) -> Self { *self } + } + + impl <> ::capnp::traits::HasTypeId for Reader<'_,> { + const TYPE_ID: u64 = _private::TYPE_ID; + } + impl <'a,> ::core::convert::From<::capnp::private::layout::StructReader<'a>> for Reader<'a,> { + fn from(reader: ::capnp::private::layout::StructReader<'a>) -> Self { + Self { reader, } + } + } + + impl <'a,> ::core::convert::From> for ::capnp::dynamic_value::Reader<'a> { + fn from(reader: Reader<'a,>) -> Self { + Self::Struct(::capnp::dynamic_struct::Reader::new(reader.reader, ::capnp::schema::StructSchema::new(::capnp::introspect::RawBrandedStructSchema { generic: &_private::RAW_SCHEMA, field_types: _private::get_field_types::<>, annotation_types: _private::get_annotation_types::<>}))) + } + } + + impl <> ::core::fmt::Debug for Reader<'_,> { + fn fmt(&self, f: &mut ::core::fmt::Formatter<'_>) -> ::core::result::Result<(), ::core::fmt::Error> { + core::fmt::Debug::fmt(&::core::convert::Into::<::capnp::dynamic_value::Reader<'_>>::into(*self), f) + } + } + + impl <'a,> ::capnp::traits::FromPointerReader<'a> for Reader<'a,> { + fn get_from_pointer(reader: &::capnp::private::layout::PointerReader<'a>, default: ::core::option::Option<&'a [::capnp::Word]>) -> ::capnp::Result { + ::core::result::Result::Ok(reader.get_struct(default)?.into()) + } + } + + impl <'a,> ::capnp::traits::IntoInternalStructReader<'a> for Reader<'a,> { + fn into_internal_struct_reader(self) -> ::capnp::private::layout::StructReader<'a> { + self.reader + } + } + + impl <'a,> ::capnp::traits::Imbue<'a> for Reader<'a,> { + fn imbue(&mut self, cap_table: &'a ::capnp::private::layout::CapTable) { + self.reader.imbue(::capnp::private::layout::CapTableReader::Plain(cap_table)) + } + } + + impl <'a,> Reader<'a,> { + pub fn reborrow(&self) -> Reader<'_,> { + Self { .. *self } + } + + pub fn total_size(&self) -> ::capnp::Result<::capnp::MessageSize> { + self.reader.total_size() + } + #[inline] + pub fn has_string(&self) -> bool { + if self.reader.get_data_field::(0) != 3 { return false; } + !self.reader.get_pointer_field(0).is_null() + } + #[inline] + pub fn has_array(&self) -> bool { + if self.reader.get_data_field::(0) != 4 { return false; } + !self.reader.get_pointer_field(0).is_null() + } + #[inline] + pub fn has_object(&self) -> bool { + if self.reader.get_data_field::(0) != 5 { return false; } + !self.reader.get_pointer_field(0).is_null() + } + #[inline] + pub fn has_call(&self) -> bool { + if self.reader.get_data_field::(0) != 6 { return false; } + !self.reader.get_pointer_field(0).is_null() + } + #[inline] + pub fn has_raw(&self) -> bool { + if self.reader.get_data_field::(0) != 7 { return false; } + !self.reader.get_pointer_field(0).is_null() + } + #[inline] + pub fn which(self) -> ::core::result::Result, ::capnp::NotInSchema> { + match self.reader.get_data_field::(0) { + 0 => { + ::core::result::Result::Ok(Null( + () + )) + } + 1 => { + ::core::result::Result::Ok(Boolean( + self.reader.get_bool_field(16) + )) + } + 2 => { + ::core::result::Result::Ok(Number( + self.reader.get_data_field::(1) + )) + } + 3 => { + ::core::result::Result::Ok(String( + ::capnp::traits::FromPointerReader::get_from_pointer(&self.reader.get_pointer_field(0), ::core::option::Option::None) + )) + } + 4 => { + ::core::result::Result::Ok(Array( + ::capnp::traits::FromPointerReader::get_from_pointer(&self.reader.get_pointer_field(0), ::core::option::Option::None) + )) + } + 5 => { + ::core::result::Result::Ok(Object( + ::capnp::traits::FromPointerReader::get_from_pointer(&self.reader.get_pointer_field(0), ::core::option::Option::None) + )) + } + 6 => { + ::core::result::Result::Ok(Call( + ::capnp::traits::FromPointerReader::get_from_pointer(&self.reader.get_pointer_field(0), ::core::option::Option::None) + )) + } + 7 => { + ::core::result::Result::Ok(Raw( + ::capnp::traits::FromPointerReader::get_from_pointer(&self.reader.get_pointer_field(0), ::core::option::Option::None) + )) + } + x => ::core::result::Result::Err(::capnp::NotInSchema(x)) + } + } + } + + pub struct Builder<'a> { builder: ::capnp::private::layout::StructBuilder<'a> } + impl <> ::capnp::traits::HasStructSize for Builder<'_,> { + const STRUCT_SIZE: ::capnp::private::layout::StructSize = ::capnp::private::layout::StructSize { data: 2, pointers: 1 }; + } + impl <> ::capnp::traits::HasTypeId for Builder<'_,> { + const TYPE_ID: u64 = _private::TYPE_ID; + } + impl <'a,> ::core::convert::From<::capnp::private::layout::StructBuilder<'a>> for Builder<'a,> { + fn from(builder: ::capnp::private::layout::StructBuilder<'a>) -> Self { + Self { builder, } + } + } + + impl <'a,> ::core::convert::From> for ::capnp::dynamic_value::Builder<'a> { + fn from(builder: Builder<'a,>) -> Self { + Self::Struct(::capnp::dynamic_struct::Builder::new(builder.builder, ::capnp::schema::StructSchema::new(::capnp::introspect::RawBrandedStructSchema { generic: &_private::RAW_SCHEMA, field_types: _private::get_field_types::<>, annotation_types: _private::get_annotation_types::<>}))) + } + } + + impl <'a,> ::capnp::traits::ImbueMut<'a> for Builder<'a,> { + fn imbue_mut(&mut self, cap_table: &'a mut ::capnp::private::layout::CapTable) { + self.builder.imbue(::capnp::private::layout::CapTableBuilder::Plain(cap_table)) + } + } + + impl <'a,> ::capnp::traits::FromPointerBuilder<'a> for Builder<'a,> { + fn init_pointer(builder: ::capnp::private::layout::PointerBuilder<'a>, _size: u32) -> Self { + builder.init_struct(::STRUCT_SIZE).into() + } + fn get_from_pointer(builder: ::capnp::private::layout::PointerBuilder<'a>, default: ::core::option::Option<&'a [::capnp::Word]>) -> ::capnp::Result { + ::core::result::Result::Ok(builder.get_struct(::STRUCT_SIZE, default)?.into()) + } + } + + impl <> ::capnp::traits::SetterInput> for Reader<'_,> { + fn set_pointer_builder(mut pointer: ::capnp::private::layout::PointerBuilder<'_>, value: Self, canonicalize: bool) -> ::capnp::Result<()> { pointer.set_struct(&value.reader, canonicalize) } + } + + impl <'a,> Builder<'a,> { + pub fn into_reader(self) -> Reader<'a,> { + self.builder.into_reader().into() + } + pub fn reborrow(&mut self) -> Builder<'_,> { + Builder { builder: self.builder.reborrow() } + } + pub fn reborrow_as_reader(&self) -> Reader<'_,> { + self.builder.as_reader().into() + } + + pub fn total_size(&self) -> ::capnp::Result<::capnp::MessageSize> { + self.builder.as_reader().total_size() + } + #[inline] + pub fn set_null(&mut self, _value: ()) { + self.builder.set_data_field::(0, 0); + } + #[inline] + pub fn set_boolean(&mut self, value: bool) { + self.builder.set_data_field::(0, 1); + self.builder.set_bool_field(16, value); + } + #[inline] + pub fn set_number(&mut self, value: f64) { + self.builder.set_data_field::(0, 2); + self.builder.set_data_field::(1, value); + } + #[inline] + pub fn set_string(&mut self, value: impl ::capnp::traits::SetterInput<::capnp::text::Owned>) { + self.builder.set_data_field::(0, 3); + ::capnp::traits::SetterInput::set_pointer_builder(self.builder.reborrow().get_pointer_field(0), value, false).unwrap() + } + #[inline] + pub fn init_string(self, size: u32) -> ::capnp::text::Builder<'a> { + self.builder.set_data_field::(0, 3); + self.builder.get_pointer_field(0).init_text(size) + } + #[inline] + pub fn has_string(&self) -> bool { + if self.builder.get_data_field::(0) != 3 { return false; } + !self.builder.is_pointer_field_null(0) + } + #[inline] + pub fn set_array(&mut self, value: ::capnp::struct_list::Reader<'_,crate::json_capnp::value::Owned>) -> ::capnp::Result<()> { + self.builder.set_data_field::(0, 4); + ::capnp::traits::SetterInput::set_pointer_builder(self.builder.reborrow().get_pointer_field(0), value, false) + } + #[inline] + pub fn init_array(self, size: u32) -> ::capnp::struct_list::Builder<'a,crate::json_capnp::value::Owned> { + self.builder.set_data_field::(0, 4); + ::capnp::traits::FromPointerBuilder::init_pointer(self.builder.get_pointer_field(0), size) + } + #[inline] + pub fn has_array(&self) -> bool { + if self.builder.get_data_field::(0) != 4 { return false; } + !self.builder.is_pointer_field_null(0) + } + #[inline] + pub fn set_object(&mut self, value: ::capnp::struct_list::Reader<'_,crate::json_capnp::value::field::Owned>) -> ::capnp::Result<()> { + self.builder.set_data_field::(0, 5); + ::capnp::traits::SetterInput::set_pointer_builder(self.builder.reborrow().get_pointer_field(0), value, false) + } + #[inline] + pub fn init_object(self, size: u32) -> ::capnp::struct_list::Builder<'a,crate::json_capnp::value::field::Owned> { + self.builder.set_data_field::(0, 5); + ::capnp::traits::FromPointerBuilder::init_pointer(self.builder.get_pointer_field(0), size) + } + #[inline] + pub fn has_object(&self) -> bool { + if self.builder.get_data_field::(0) != 5 { return false; } + !self.builder.is_pointer_field_null(0) + } + #[inline] + pub fn set_call(&mut self, value: crate::json_capnp::value::call::Reader<'_>) -> ::capnp::Result<()> { + self.builder.set_data_field::(0, 6); + ::capnp::traits::SetterInput::set_pointer_builder(self.builder.reborrow().get_pointer_field(0), value, false) + } + #[inline] + pub fn init_call(self, ) -> crate::json_capnp::value::call::Builder<'a> { + self.builder.set_data_field::(0, 6); + ::capnp::traits::FromPointerBuilder::init_pointer(self.builder.get_pointer_field(0), 0) + } + #[inline] + pub fn has_call(&self) -> bool { + if self.builder.get_data_field::(0) != 6 { return false; } + !self.builder.is_pointer_field_null(0) + } + #[inline] + pub fn set_raw(&mut self, value: impl ::capnp::traits::SetterInput<::capnp::text::Owned>) { + self.builder.set_data_field::(0, 7); + ::capnp::traits::SetterInput::set_pointer_builder(self.builder.reborrow().get_pointer_field(0), value, false).unwrap() + } + #[inline] + pub fn init_raw(self, size: u32) -> ::capnp::text::Builder<'a> { + self.builder.set_data_field::(0, 7); + self.builder.get_pointer_field(0).init_text(size) + } + #[inline] + pub fn has_raw(&self) -> bool { + if self.builder.get_data_field::(0) != 7 { return false; } + !self.builder.is_pointer_field_null(0) + } + #[inline] + pub fn which(self) -> ::core::result::Result, ::capnp::NotInSchema> { + match self.builder.get_data_field::(0) { + 0 => { + ::core::result::Result::Ok(Null( + () + )) + } + 1 => { + ::core::result::Result::Ok(Boolean( + self.builder.get_bool_field(16) + )) + } + 2 => { + ::core::result::Result::Ok(Number( + self.builder.get_data_field::(1) + )) + } + 3 => { + ::core::result::Result::Ok(String( + ::capnp::traits::FromPointerBuilder::get_from_pointer(self.builder.get_pointer_field(0), ::core::option::Option::None) + )) + } + 4 => { + ::core::result::Result::Ok(Array( + ::capnp::traits::FromPointerBuilder::get_from_pointer(self.builder.get_pointer_field(0), ::core::option::Option::None) + )) + } + 5 => { + ::core::result::Result::Ok(Object( + ::capnp::traits::FromPointerBuilder::get_from_pointer(self.builder.get_pointer_field(0), ::core::option::Option::None) + )) + } + 6 => { + ::core::result::Result::Ok(Call( + ::capnp::traits::FromPointerBuilder::get_from_pointer(self.builder.get_pointer_field(0), ::core::option::Option::None) + )) + } + 7 => { + ::core::result::Result::Ok(Raw( + ::capnp::traits::FromPointerBuilder::get_from_pointer(self.builder.get_pointer_field(0), ::core::option::Option::None) + )) + } + x => ::core::result::Result::Err(::capnp::NotInSchema(x)) + } + } + } + + pub struct Pipeline { _typeless: ::capnp::any_pointer::Pipeline } + impl ::capnp::capability::FromTypelessPipeline for Pipeline { + fn new(typeless: ::capnp::any_pointer::Pipeline) -> Self { + Self { _typeless: typeless, } + } + } + impl Pipeline { + } + mod _private { + pub static ENCODED_NODE: [::capnp::Word; 152] = [ + ::capnp::word(0, 0, 0, 0, 6, 0, 6, 0), + ::capnp::word(131, 221, 25, 249, 69, 120, 250, 163), + ::capnp::word(11, 0, 0, 0, 1, 0, 2, 0), + ::capnp::word(52, 94, 58, 164, 151, 146, 249, 142), + ::capnp::word(1, 0, 7, 0, 0, 0, 8, 0), + ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(216, 4, 0, 0, 47, 11, 0, 0), + ::capnp::word(21, 0, 0, 0, 138, 0, 0, 0), + ::capnp::word(29, 0, 0, 0, 39, 0, 0, 0), + ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(49, 0, 0, 0, 199, 1, 0, 0), + ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(106, 115, 111, 110, 46, 99, 97, 112), + ::capnp::word(110, 112, 58, 86, 97, 108, 117, 101), + ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(8, 0, 0, 0, 1, 0, 1, 0), + ::capnp::word(223, 157, 214, 53, 231, 38, 16, 227), + ::capnp::word(9, 0, 0, 0, 50, 0, 0, 0), + ::capnp::word(72, 61, 201, 161, 236, 246, 217, 160), + ::capnp::word(5, 0, 0, 0, 42, 0, 0, 0), + ::capnp::word(70, 105, 101, 108, 100, 0, 0, 0), + ::capnp::word(67, 97, 108, 108, 0, 0, 0, 0), + ::capnp::word(32, 0, 0, 0, 3, 0, 4, 0), + ::capnp::word(0, 0, 255, 255, 0, 0, 0, 0), + ::capnp::word(0, 0, 1, 0, 0, 0, 0, 0), + ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(209, 0, 0, 0, 42, 0, 0, 0), + ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(204, 0, 0, 0, 3, 0, 1, 0), + ::capnp::word(216, 0, 0, 0, 2, 0, 1, 0), + ::capnp::word(1, 0, 254, 255, 16, 0, 0, 0), + ::capnp::word(0, 0, 1, 0, 1, 0, 0, 0), + ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(213, 0, 0, 0, 66, 0, 0, 0), + ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(208, 0, 0, 0, 3, 0, 1, 0), + ::capnp::word(220, 0, 0, 0, 2, 0, 1, 0), + ::capnp::word(2, 0, 253, 255, 1, 0, 0, 0), + ::capnp::word(0, 0, 1, 0, 2, 0, 0, 0), + ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(217, 0, 0, 0, 58, 0, 0, 0), + ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(212, 0, 0, 0, 3, 0, 1, 0), + ::capnp::word(224, 0, 0, 0, 2, 0, 1, 0), + ::capnp::word(3, 0, 252, 255, 0, 0, 0, 0), + ::capnp::word(0, 0, 1, 0, 3, 0, 0, 0), + ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(221, 0, 0, 0, 58, 0, 0, 0), + ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(216, 0, 0, 0, 3, 0, 1, 0), + ::capnp::word(228, 0, 0, 0, 2, 0, 1, 0), + ::capnp::word(4, 0, 251, 255, 0, 0, 0, 0), + ::capnp::word(0, 0, 1, 0, 4, 0, 0, 0), + ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(225, 0, 0, 0, 50, 0, 0, 0), + ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(220, 0, 0, 0, 3, 0, 1, 0), + ::capnp::word(248, 0, 0, 0, 2, 0, 1, 0), + ::capnp::word(5, 0, 250, 255, 0, 0, 0, 0), + ::capnp::word(0, 0, 1, 0, 5, 0, 0, 0), + ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(245, 0, 0, 0, 58, 0, 0, 0), + ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(240, 0, 0, 0, 3, 0, 1, 0), + ::capnp::word(12, 1, 0, 0, 2, 0, 1, 0), + ::capnp::word(6, 0, 249, 255, 0, 0, 0, 0), + ::capnp::word(0, 0, 1, 0, 6, 0, 0, 0), + ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(9, 1, 0, 0, 42, 0, 0, 0), + ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(4, 1, 0, 0, 3, 0, 1, 0), + ::capnp::word(16, 1, 0, 0, 2, 0, 1, 0), + ::capnp::word(7, 0, 248, 255, 0, 0, 0, 0), + ::capnp::word(0, 0, 1, 0, 7, 0, 0, 0), + ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(13, 1, 0, 0, 34, 0, 0, 0), + ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(8, 1, 0, 0, 3, 0, 1, 0), + ::capnp::word(20, 1, 0, 0, 2, 0, 1, 0), + ::capnp::word(110, 117, 108, 108, 0, 0, 0, 0), + ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(98, 111, 111, 108, 101, 97, 110, 0), + ::capnp::word(1, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(1, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(110, 117, 109, 98, 101, 114, 0, 0), + ::capnp::word(11, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(11, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(115, 116, 114, 105, 110, 103, 0, 0), + ::capnp::word(12, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(12, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(97, 114, 114, 97, 121, 0, 0, 0), + ::capnp::word(14, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(0, 0, 0, 0, 3, 0, 1, 0), + ::capnp::word(16, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(131, 221, 25, 249, 69, 120, 250, 163), + ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(14, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(111, 98, 106, 101, 99, 116, 0, 0), + ::capnp::word(14, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(0, 0, 0, 0, 3, 0, 1, 0), + ::capnp::word(16, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(223, 157, 214, 53, 231, 38, 16, 227), + ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(14, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(99, 97, 108, 108, 0, 0, 0, 0), + ::capnp::word(16, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(72, 61, 201, 161, 236, 246, 217, 160), + ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(16, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(114, 97, 119, 0, 0, 0, 0, 0), + ::capnp::word(12, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(12, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), + ]; + pub fn get_field_types(index: u16) -> ::capnp::introspect::Type { + match index { + 0 => <() as ::capnp::introspect::Introspect>::introspect(), + 1 => ::introspect(), + 2 => ::introspect(), + 3 => <::capnp::text::Owned as ::capnp::introspect::Introspect>::introspect(), + 4 => <::capnp::struct_list::Owned as ::capnp::introspect::Introspect>::introspect(), + 5 => <::capnp::struct_list::Owned as ::capnp::introspect::Introspect>::introspect(), + 6 => ::introspect(), + 7 => <::capnp::text::Owned as ::capnp::introspect::Introspect>::introspect(), + _ => ::capnp::introspect::panic_invalid_field_index(index), + } + } + pub fn get_annotation_types(child_index: Option, index: u32) -> ::capnp::introspect::Type { + ::capnp::introspect::panic_invalid_annotation_indices(child_index, index) + } + pub static RAW_SCHEMA: ::capnp::introspect::RawStructSchema = ::capnp::introspect::RawStructSchema { + encoded_node: &ENCODED_NODE, + nonunion_members: NONUNION_MEMBERS, + members_by_discriminant: MEMBERS_BY_DISCRIMINANT, + members_by_name: MEMBERS_BY_NAME, + }; + pub static NONUNION_MEMBERS : &[u16] = &[]; + pub static MEMBERS_BY_DISCRIMINANT : &[u16] = &[0,1,2,3,4,5,6,7]; + pub static MEMBERS_BY_NAME : &[u16] = &[4,1,6,0,2,5,7,3]; + pub const TYPE_ID: u64 = 0xa3fa_7845_f919_dd83; + } + pub enum Which { + Null(()), + Boolean(bool), + Number(f64), + String(A0), + Array(A1), + Object(A2), + Call(A3), + Raw(A4), + } + pub type WhichReader<'a,> = Which<::capnp::Result<::capnp::text::Reader<'a>>,::capnp::Result<::capnp::struct_list::Reader<'a,crate::json_capnp::value::Owned>>,::capnp::Result<::capnp::struct_list::Reader<'a,crate::json_capnp::value::field::Owned>>,::capnp::Result>,::capnp::Result<::capnp::text::Reader<'a>>>; + pub type WhichBuilder<'a,> = Which<::capnp::Result<::capnp::text::Builder<'a>>,::capnp::Result<::capnp::struct_list::Builder<'a,crate::json_capnp::value::Owned>>,::capnp::Result<::capnp::struct_list::Builder<'a,crate::json_capnp::value::field::Owned>>,::capnp::Result>,::capnp::Result<::capnp::text::Builder<'a>>>; + + pub mod field { + #[derive(Copy, Clone)] + pub struct Owned(()); + impl ::capnp::introspect::Introspect for Owned { fn introspect() -> ::capnp::introspect::Type { ::capnp::introspect::TypeVariant::Struct(::capnp::introspect::RawBrandedStructSchema { generic: &_private::RAW_SCHEMA, field_types: _private::get_field_types, annotation_types: _private::get_annotation_types }).into() } } + impl ::capnp::traits::Owned for Owned { type Reader<'a> = Reader<'a>; type Builder<'a> = Builder<'a>; } + impl ::capnp::traits::OwnedStruct for Owned { type Reader<'a> = Reader<'a>; type Builder<'a> = Builder<'a>; } + impl ::capnp::traits::Pipelined for Owned { type Pipeline = Pipeline; } + + pub struct Reader<'a> { reader: ::capnp::private::layout::StructReader<'a> } + impl <> ::core::marker::Copy for Reader<'_,> {} + impl <> ::core::clone::Clone for Reader<'_,> { + fn clone(&self) -> Self { *self } + } + + impl <> ::capnp::traits::HasTypeId for Reader<'_,> { + const TYPE_ID: u64 = _private::TYPE_ID; + } + impl <'a,> ::core::convert::From<::capnp::private::layout::StructReader<'a>> for Reader<'a,> { + fn from(reader: ::capnp::private::layout::StructReader<'a>) -> Self { + Self { reader, } + } + } + + impl <'a,> ::core::convert::From> for ::capnp::dynamic_value::Reader<'a> { + fn from(reader: Reader<'a,>) -> Self { + Self::Struct(::capnp::dynamic_struct::Reader::new(reader.reader, ::capnp::schema::StructSchema::new(::capnp::introspect::RawBrandedStructSchema { generic: &_private::RAW_SCHEMA, field_types: _private::get_field_types::<>, annotation_types: _private::get_annotation_types::<>}))) + } + } + + impl <> ::core::fmt::Debug for Reader<'_,> { + fn fmt(&self, f: &mut ::core::fmt::Formatter<'_>) -> ::core::result::Result<(), ::core::fmt::Error> { + core::fmt::Debug::fmt(&::core::convert::Into::<::capnp::dynamic_value::Reader<'_>>::into(*self), f) + } + } + + impl <'a,> ::capnp::traits::FromPointerReader<'a> for Reader<'a,> { + fn get_from_pointer(reader: &::capnp::private::layout::PointerReader<'a>, default: ::core::option::Option<&'a [::capnp::Word]>) -> ::capnp::Result { + ::core::result::Result::Ok(reader.get_struct(default)?.into()) + } + } + + impl <'a,> ::capnp::traits::IntoInternalStructReader<'a> for Reader<'a,> { + fn into_internal_struct_reader(self) -> ::capnp::private::layout::StructReader<'a> { + self.reader + } + } + + impl <'a,> ::capnp::traits::Imbue<'a> for Reader<'a,> { + fn imbue(&mut self, cap_table: &'a ::capnp::private::layout::CapTable) { + self.reader.imbue(::capnp::private::layout::CapTableReader::Plain(cap_table)) + } + } + + impl <'a,> Reader<'a,> { + pub fn reborrow(&self) -> Reader<'_,> { + Self { .. *self } + } + + pub fn total_size(&self) -> ::capnp::Result<::capnp::MessageSize> { + self.reader.total_size() + } + #[inline] + pub fn get_name(self) -> ::capnp::Result<::capnp::text::Reader<'a>> { + ::capnp::traits::FromPointerReader::get_from_pointer(&self.reader.get_pointer_field(0), ::core::option::Option::None) + } + #[inline] + pub fn has_name(&self) -> bool { + !self.reader.get_pointer_field(0).is_null() + } + #[inline] + pub fn get_value(self) -> ::capnp::Result> { + ::capnp::traits::FromPointerReader::get_from_pointer(&self.reader.get_pointer_field(1), ::core::option::Option::None) + } + #[inline] + pub fn has_value(&self) -> bool { + !self.reader.get_pointer_field(1).is_null() + } + } + + pub struct Builder<'a> { builder: ::capnp::private::layout::StructBuilder<'a> } + impl <> ::capnp::traits::HasStructSize for Builder<'_,> { + const STRUCT_SIZE: ::capnp::private::layout::StructSize = ::capnp::private::layout::StructSize { data: 0, pointers: 2 }; + } + impl <> ::capnp::traits::HasTypeId for Builder<'_,> { + const TYPE_ID: u64 = _private::TYPE_ID; + } + impl <'a,> ::core::convert::From<::capnp::private::layout::StructBuilder<'a>> for Builder<'a,> { + fn from(builder: ::capnp::private::layout::StructBuilder<'a>) -> Self { + Self { builder, } + } + } + + impl <'a,> ::core::convert::From> for ::capnp::dynamic_value::Builder<'a> { + fn from(builder: Builder<'a,>) -> Self { + Self::Struct(::capnp::dynamic_struct::Builder::new(builder.builder, ::capnp::schema::StructSchema::new(::capnp::introspect::RawBrandedStructSchema { generic: &_private::RAW_SCHEMA, field_types: _private::get_field_types::<>, annotation_types: _private::get_annotation_types::<>}))) + } + } + + impl <'a,> ::capnp::traits::ImbueMut<'a> for Builder<'a,> { + fn imbue_mut(&mut self, cap_table: &'a mut ::capnp::private::layout::CapTable) { + self.builder.imbue(::capnp::private::layout::CapTableBuilder::Plain(cap_table)) + } + } + + impl <'a,> ::capnp::traits::FromPointerBuilder<'a> for Builder<'a,> { + fn init_pointer(builder: ::capnp::private::layout::PointerBuilder<'a>, _size: u32) -> Self { + builder.init_struct(::STRUCT_SIZE).into() + } + fn get_from_pointer(builder: ::capnp::private::layout::PointerBuilder<'a>, default: ::core::option::Option<&'a [::capnp::Word]>) -> ::capnp::Result { + ::core::result::Result::Ok(builder.get_struct(::STRUCT_SIZE, default)?.into()) + } + } + + impl <> ::capnp::traits::SetterInput> for Reader<'_,> { + fn set_pointer_builder(mut pointer: ::capnp::private::layout::PointerBuilder<'_>, value: Self, canonicalize: bool) -> ::capnp::Result<()> { pointer.set_struct(&value.reader, canonicalize) } + } + + impl <'a,> Builder<'a,> { + pub fn into_reader(self) -> Reader<'a,> { + self.builder.into_reader().into() + } + pub fn reborrow(&mut self) -> Builder<'_,> { + Builder { builder: self.builder.reborrow() } + } + pub fn reborrow_as_reader(&self) -> Reader<'_,> { + self.builder.as_reader().into() + } + + pub fn total_size(&self) -> ::capnp::Result<::capnp::MessageSize> { + self.builder.as_reader().total_size() + } + #[inline] + pub fn get_name(self) -> ::capnp::Result<::capnp::text::Builder<'a>> { + ::capnp::traits::FromPointerBuilder::get_from_pointer(self.builder.get_pointer_field(0), ::core::option::Option::None) + } + #[inline] + pub fn set_name(&mut self, value: impl ::capnp::traits::SetterInput<::capnp::text::Owned>) { + ::capnp::traits::SetterInput::set_pointer_builder(self.builder.reborrow().get_pointer_field(0), value, false).unwrap() + } + #[inline] + pub fn init_name(self, size: u32) -> ::capnp::text::Builder<'a> { + self.builder.get_pointer_field(0).init_text(size) + } + #[inline] + pub fn has_name(&self) -> bool { + !self.builder.is_pointer_field_null(0) + } + #[inline] + pub fn get_value(self) -> ::capnp::Result> { + ::capnp::traits::FromPointerBuilder::get_from_pointer(self.builder.get_pointer_field(1), ::core::option::Option::None) + } + #[inline] + pub fn set_value(&mut self, value: crate::json_capnp::value::Reader<'_>) -> ::capnp::Result<()> { + ::capnp::traits::SetterInput::set_pointer_builder(self.builder.reborrow().get_pointer_field(1), value, false) + } + #[inline] + pub fn init_value(self, ) -> crate::json_capnp::value::Builder<'a> { + ::capnp::traits::FromPointerBuilder::init_pointer(self.builder.get_pointer_field(1), 0) + } + #[inline] + pub fn has_value(&self) -> bool { + !self.builder.is_pointer_field_null(1) + } + } + + pub struct Pipeline { _typeless: ::capnp::any_pointer::Pipeline } + impl ::capnp::capability::FromTypelessPipeline for Pipeline { + fn new(typeless: ::capnp::any_pointer::Pipeline) -> Self { + Self { _typeless: typeless, } + } + } + impl Pipeline { + pub fn get_value(&self) -> crate::json_capnp::value::Pipeline { + ::capnp::capability::FromTypelessPipeline::new(self._typeless.get_pointer_field(1)) + } + } + mod _private { + pub static ENCODED_NODE: [::capnp::Word; 48] = [ + ::capnp::word(0, 0, 0, 0, 6, 0, 6, 0), + ::capnp::word(223, 157, 214, 53, 231, 38, 16, 227), + ::capnp::word(17, 0, 0, 0, 1, 0, 0, 0), + ::capnp::word(131, 221, 25, 249, 69, 120, 250, 163), + ::capnp::word(2, 0, 7, 0, 0, 0, 0, 0), + ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(171, 10, 0, 0, 229, 10, 0, 0), + ::capnp::word(21, 0, 0, 0, 186, 0, 0, 0), + ::capnp::word(29, 0, 0, 0, 7, 0, 0, 0), + ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(25, 0, 0, 0, 119, 0, 0, 0), + ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(106, 115, 111, 110, 46, 99, 97, 112), + ::capnp::word(110, 112, 58, 86, 97, 108, 117, 101), + ::capnp::word(46, 70, 105, 101, 108, 100, 0, 0), + ::capnp::word(0, 0, 0, 0, 1, 0, 1, 0), + ::capnp::word(8, 0, 0, 0, 3, 0, 4, 0), + ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(0, 0, 1, 0, 0, 0, 0, 0), + ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(41, 0, 0, 0, 42, 0, 0, 0), + ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(36, 0, 0, 0, 3, 0, 1, 0), + ::capnp::word(48, 0, 0, 0, 2, 0, 1, 0), + ::capnp::word(1, 0, 0, 0, 1, 0, 0, 0), + ::capnp::word(0, 0, 1, 0, 1, 0, 0, 0), + ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(45, 0, 0, 0, 50, 0, 0, 0), + ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(40, 0, 0, 0, 3, 0, 1, 0), + ::capnp::word(52, 0, 0, 0, 2, 0, 1, 0), + ::capnp::word(110, 97, 109, 101, 0, 0, 0, 0), + ::capnp::word(12, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(12, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(118, 97, 108, 117, 101, 0, 0, 0), + ::capnp::word(16, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(131, 221, 25, 249, 69, 120, 250, 163), + ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(16, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), + ]; + pub fn get_field_types(index: u16) -> ::capnp::introspect::Type { + match index { + 0 => <::capnp::text::Owned as ::capnp::introspect::Introspect>::introspect(), + 1 => ::introspect(), + _ => ::capnp::introspect::panic_invalid_field_index(index), + } + } + pub fn get_annotation_types(child_index: Option, index: u32) -> ::capnp::introspect::Type { + ::capnp::introspect::panic_invalid_annotation_indices(child_index, index) + } + pub static RAW_SCHEMA: ::capnp::introspect::RawStructSchema = ::capnp::introspect::RawStructSchema { + encoded_node: &ENCODED_NODE, + nonunion_members: NONUNION_MEMBERS, + members_by_discriminant: MEMBERS_BY_DISCRIMINANT, + members_by_name: MEMBERS_BY_NAME, + }; + pub static NONUNION_MEMBERS : &[u16] = &[0,1]; + pub static MEMBERS_BY_DISCRIMINANT : &[u16] = &[]; + pub static MEMBERS_BY_NAME : &[u16] = &[0,1]; + pub const TYPE_ID: u64 = 0xe310_26e7_35d6_9ddf; + } + } + + pub mod call { + #[derive(Copy, Clone)] + pub struct Owned(()); + impl ::capnp::introspect::Introspect for Owned { fn introspect() -> ::capnp::introspect::Type { ::capnp::introspect::TypeVariant::Struct(::capnp::introspect::RawBrandedStructSchema { generic: &_private::RAW_SCHEMA, field_types: _private::get_field_types, annotation_types: _private::get_annotation_types }).into() } } + impl ::capnp::traits::Owned for Owned { type Reader<'a> = Reader<'a>; type Builder<'a> = Builder<'a>; } + impl ::capnp::traits::OwnedStruct for Owned { type Reader<'a> = Reader<'a>; type Builder<'a> = Builder<'a>; } + impl ::capnp::traits::Pipelined for Owned { type Pipeline = Pipeline; } + + pub struct Reader<'a> { reader: ::capnp::private::layout::StructReader<'a> } + impl <> ::core::marker::Copy for Reader<'_,> {} + impl <> ::core::clone::Clone for Reader<'_,> { + fn clone(&self) -> Self { *self } + } + + impl <> ::capnp::traits::HasTypeId for Reader<'_,> { + const TYPE_ID: u64 = _private::TYPE_ID; + } + impl <'a,> ::core::convert::From<::capnp::private::layout::StructReader<'a>> for Reader<'a,> { + fn from(reader: ::capnp::private::layout::StructReader<'a>) -> Self { + Self { reader, } + } + } + + impl <'a,> ::core::convert::From> for ::capnp::dynamic_value::Reader<'a> { + fn from(reader: Reader<'a,>) -> Self { + Self::Struct(::capnp::dynamic_struct::Reader::new(reader.reader, ::capnp::schema::StructSchema::new(::capnp::introspect::RawBrandedStructSchema { generic: &_private::RAW_SCHEMA, field_types: _private::get_field_types::<>, annotation_types: _private::get_annotation_types::<>}))) + } + } + + impl <> ::core::fmt::Debug for Reader<'_,> { + fn fmt(&self, f: &mut ::core::fmt::Formatter<'_>) -> ::core::result::Result<(), ::core::fmt::Error> { + core::fmt::Debug::fmt(&::core::convert::Into::<::capnp::dynamic_value::Reader<'_>>::into(*self), f) + } + } + + impl <'a,> ::capnp::traits::FromPointerReader<'a> for Reader<'a,> { + fn get_from_pointer(reader: &::capnp::private::layout::PointerReader<'a>, default: ::core::option::Option<&'a [::capnp::Word]>) -> ::capnp::Result { + ::core::result::Result::Ok(reader.get_struct(default)?.into()) + } + } + + impl <'a,> ::capnp::traits::IntoInternalStructReader<'a> for Reader<'a,> { + fn into_internal_struct_reader(self) -> ::capnp::private::layout::StructReader<'a> { + self.reader + } + } + + impl <'a,> ::capnp::traits::Imbue<'a> for Reader<'a,> { + fn imbue(&mut self, cap_table: &'a ::capnp::private::layout::CapTable) { + self.reader.imbue(::capnp::private::layout::CapTableReader::Plain(cap_table)) + } + } + + impl <'a,> Reader<'a,> { + pub fn reborrow(&self) -> Reader<'_,> { + Self { .. *self } + } + + pub fn total_size(&self) -> ::capnp::Result<::capnp::MessageSize> { + self.reader.total_size() + } + #[inline] + pub fn get_function(self) -> ::capnp::Result<::capnp::text::Reader<'a>> { + ::capnp::traits::FromPointerReader::get_from_pointer(&self.reader.get_pointer_field(0), ::core::option::Option::None) + } + #[inline] + pub fn has_function(&self) -> bool { + !self.reader.get_pointer_field(0).is_null() + } + #[inline] + pub fn get_params(self) -> ::capnp::Result<::capnp::struct_list::Reader<'a,crate::json_capnp::value::Owned>> { + ::capnp::traits::FromPointerReader::get_from_pointer(&self.reader.get_pointer_field(1), ::core::option::Option::None) + } + #[inline] + pub fn has_params(&self) -> bool { + !self.reader.get_pointer_field(1).is_null() + } + } + + pub struct Builder<'a> { builder: ::capnp::private::layout::StructBuilder<'a> } + impl <> ::capnp::traits::HasStructSize for Builder<'_,> { + const STRUCT_SIZE: ::capnp::private::layout::StructSize = ::capnp::private::layout::StructSize { data: 0, pointers: 2 }; + } + impl <> ::capnp::traits::HasTypeId for Builder<'_,> { + const TYPE_ID: u64 = _private::TYPE_ID; + } + impl <'a,> ::core::convert::From<::capnp::private::layout::StructBuilder<'a>> for Builder<'a,> { + fn from(builder: ::capnp::private::layout::StructBuilder<'a>) -> Self { + Self { builder, } + } + } + + impl <'a,> ::core::convert::From> for ::capnp::dynamic_value::Builder<'a> { + fn from(builder: Builder<'a,>) -> Self { + Self::Struct(::capnp::dynamic_struct::Builder::new(builder.builder, ::capnp::schema::StructSchema::new(::capnp::introspect::RawBrandedStructSchema { generic: &_private::RAW_SCHEMA, field_types: _private::get_field_types::<>, annotation_types: _private::get_annotation_types::<>}))) + } + } + + impl <'a,> ::capnp::traits::ImbueMut<'a> for Builder<'a,> { + fn imbue_mut(&mut self, cap_table: &'a mut ::capnp::private::layout::CapTable) { + self.builder.imbue(::capnp::private::layout::CapTableBuilder::Plain(cap_table)) + } + } + + impl <'a,> ::capnp::traits::FromPointerBuilder<'a> for Builder<'a,> { + fn init_pointer(builder: ::capnp::private::layout::PointerBuilder<'a>, _size: u32) -> Self { + builder.init_struct(::STRUCT_SIZE).into() + } + fn get_from_pointer(builder: ::capnp::private::layout::PointerBuilder<'a>, default: ::core::option::Option<&'a [::capnp::Word]>) -> ::capnp::Result { + ::core::result::Result::Ok(builder.get_struct(::STRUCT_SIZE, default)?.into()) + } + } + + impl <> ::capnp::traits::SetterInput> for Reader<'_,> { + fn set_pointer_builder(mut pointer: ::capnp::private::layout::PointerBuilder<'_>, value: Self, canonicalize: bool) -> ::capnp::Result<()> { pointer.set_struct(&value.reader, canonicalize) } + } + + impl <'a,> Builder<'a,> { + pub fn into_reader(self) -> Reader<'a,> { + self.builder.into_reader().into() + } + pub fn reborrow(&mut self) -> Builder<'_,> { + Builder { builder: self.builder.reborrow() } + } + pub fn reborrow_as_reader(&self) -> Reader<'_,> { + self.builder.as_reader().into() + } + + pub fn total_size(&self) -> ::capnp::Result<::capnp::MessageSize> { + self.builder.as_reader().total_size() + } + #[inline] + pub fn get_function(self) -> ::capnp::Result<::capnp::text::Builder<'a>> { + ::capnp::traits::FromPointerBuilder::get_from_pointer(self.builder.get_pointer_field(0), ::core::option::Option::None) + } + #[inline] + pub fn set_function(&mut self, value: impl ::capnp::traits::SetterInput<::capnp::text::Owned>) { + ::capnp::traits::SetterInput::set_pointer_builder(self.builder.reborrow().get_pointer_field(0), value, false).unwrap() + } + #[inline] + pub fn init_function(self, size: u32) -> ::capnp::text::Builder<'a> { + self.builder.get_pointer_field(0).init_text(size) + } + #[inline] + pub fn has_function(&self) -> bool { + !self.builder.is_pointer_field_null(0) + } + #[inline] + pub fn get_params(self) -> ::capnp::Result<::capnp::struct_list::Builder<'a,crate::json_capnp::value::Owned>> { + ::capnp::traits::FromPointerBuilder::get_from_pointer(self.builder.get_pointer_field(1), ::core::option::Option::None) + } + #[inline] + pub fn set_params(&mut self, value: ::capnp::struct_list::Reader<'_,crate::json_capnp::value::Owned>) -> ::capnp::Result<()> { + ::capnp::traits::SetterInput::set_pointer_builder(self.builder.reborrow().get_pointer_field(1), value, false) + } + #[inline] + pub fn init_params(self, size: u32) -> ::capnp::struct_list::Builder<'a,crate::json_capnp::value::Owned> { + ::capnp::traits::FromPointerBuilder::init_pointer(self.builder.get_pointer_field(1), size) + } + #[inline] + pub fn has_params(&self) -> bool { + !self.builder.is_pointer_field_null(1) + } + } + + pub struct Pipeline { _typeless: ::capnp::any_pointer::Pipeline } + impl ::capnp::capability::FromTypelessPipeline for Pipeline { + fn new(typeless: ::capnp::any_pointer::Pipeline) -> Self { + Self { _typeless: typeless, } + } + } + impl Pipeline { + } + mod _private { + pub static ENCODED_NODE: [::capnp::Word; 53] = [ + ::capnp::word(0, 0, 0, 0, 6, 0, 6, 0), + ::capnp::word(72, 61, 201, 161, 236, 246, 217, 160), + ::capnp::word(17, 0, 0, 0, 1, 0, 0, 0), + ::capnp::word(131, 221, 25, 249, 69, 120, 250, 163), + ::capnp::word(2, 0, 7, 0, 0, 0, 0, 0), + ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(233, 10, 0, 0, 45, 11, 0, 0), + ::capnp::word(21, 0, 0, 0, 178, 0, 0, 0), + ::capnp::word(29, 0, 0, 0, 7, 0, 0, 0), + ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(25, 0, 0, 0, 119, 0, 0, 0), + ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(106, 115, 111, 110, 46, 99, 97, 112), + ::capnp::word(110, 112, 58, 86, 97, 108, 117, 101), + ::capnp::word(46, 67, 97, 108, 108, 0, 0, 0), + ::capnp::word(0, 0, 0, 0, 1, 0, 1, 0), + ::capnp::word(8, 0, 0, 0, 3, 0, 4, 0), + ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(0, 0, 1, 0, 0, 0, 0, 0), + ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(41, 0, 0, 0, 74, 0, 0, 0), + ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(40, 0, 0, 0, 3, 0, 1, 0), + ::capnp::word(52, 0, 0, 0, 2, 0, 1, 0), + ::capnp::word(1, 0, 0, 0, 1, 0, 0, 0), + ::capnp::word(0, 0, 1, 0, 1, 0, 0, 0), + ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(49, 0, 0, 0, 58, 0, 0, 0), + ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(44, 0, 0, 0, 3, 0, 1, 0), + ::capnp::word(72, 0, 0, 0, 2, 0, 1, 0), + ::capnp::word(102, 117, 110, 99, 116, 105, 111, 110), + ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(12, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(12, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(112, 97, 114, 97, 109, 115, 0, 0), + ::capnp::word(14, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(0, 0, 0, 0, 3, 0, 1, 0), + ::capnp::word(16, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(131, 221, 25, 249, 69, 120, 250, 163), + ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(14, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), + ]; + pub fn get_field_types(index: u16) -> ::capnp::introspect::Type { + match index { + 0 => <::capnp::text::Owned as ::capnp::introspect::Introspect>::introspect(), + 1 => <::capnp::struct_list::Owned as ::capnp::introspect::Introspect>::introspect(), + _ => ::capnp::introspect::panic_invalid_field_index(index), + } + } + pub fn get_annotation_types(child_index: Option, index: u32) -> ::capnp::introspect::Type { + ::capnp::introspect::panic_invalid_annotation_indices(child_index, index) + } + pub static RAW_SCHEMA: ::capnp::introspect::RawStructSchema = ::capnp::introspect::RawStructSchema { + encoded_node: &ENCODED_NODE, + nonunion_members: NONUNION_MEMBERS, + members_by_discriminant: MEMBERS_BY_DISCRIMINANT, + members_by_name: MEMBERS_BY_NAME, + }; + pub static NONUNION_MEMBERS : &[u16] = &[0,1]; + pub static MEMBERS_BY_DISCRIMINANT : &[u16] = &[]; + pub static MEMBERS_BY_NAME : &[u16] = &[0,1]; + pub const TYPE_ID: u64 = 0xa0d9_f6ec_a1c9_3d48; + } + } +} +pub mod name { + pub const ID: u64 = 0xfa5b1fd61c2e7c3d; + pub fn get_type() -> ::capnp::introspect::Type { <::capnp::text::Owned as ::capnp::introspect::Introspect>::introspect() } +} +pub mod flatten { + pub const ID: u64 = 0x82d3e852af0336bf; + pub fn get_type() -> ::capnp::introspect::Type { ::introspect() } +} + +pub mod flatten_options { + #[derive(Copy, Clone)] + pub struct Owned(()); + impl ::capnp::introspect::Introspect for Owned { fn introspect() -> ::capnp::introspect::Type { ::capnp::introspect::TypeVariant::Struct(::capnp::introspect::RawBrandedStructSchema { generic: &_private::RAW_SCHEMA, field_types: _private::get_field_types, annotation_types: _private::get_annotation_types }).into() } } + impl ::capnp::traits::Owned for Owned { type Reader<'a> = Reader<'a>; type Builder<'a> = Builder<'a>; } + impl ::capnp::traits::OwnedStruct for Owned { type Reader<'a> = Reader<'a>; type Builder<'a> = Builder<'a>; } + impl ::capnp::traits::Pipelined for Owned { type Pipeline = Pipeline; } + + pub struct Reader<'a> { reader: ::capnp::private::layout::StructReader<'a> } + impl <> ::core::marker::Copy for Reader<'_,> {} + impl <> ::core::clone::Clone for Reader<'_,> { + fn clone(&self) -> Self { *self } + } + + impl <> ::capnp::traits::HasTypeId for Reader<'_,> { + const TYPE_ID: u64 = _private::TYPE_ID; + } + impl <'a,> ::core::convert::From<::capnp::private::layout::StructReader<'a>> for Reader<'a,> { + fn from(reader: ::capnp::private::layout::StructReader<'a>) -> Self { + Self { reader, } + } + } + + impl <'a,> ::core::convert::From> for ::capnp::dynamic_value::Reader<'a> { + fn from(reader: Reader<'a,>) -> Self { + Self::Struct(::capnp::dynamic_struct::Reader::new(reader.reader, ::capnp::schema::StructSchema::new(::capnp::introspect::RawBrandedStructSchema { generic: &_private::RAW_SCHEMA, field_types: _private::get_field_types::<>, annotation_types: _private::get_annotation_types::<>}))) + } + } + + impl <> ::core::fmt::Debug for Reader<'_,> { + fn fmt(&self, f: &mut ::core::fmt::Formatter<'_>) -> ::core::result::Result<(), ::core::fmt::Error> { + core::fmt::Debug::fmt(&::core::convert::Into::<::capnp::dynamic_value::Reader<'_>>::into(*self), f) + } + } + + impl <'a,> ::capnp::traits::FromPointerReader<'a> for Reader<'a,> { + fn get_from_pointer(reader: &::capnp::private::layout::PointerReader<'a>, default: ::core::option::Option<&'a [::capnp::Word]>) -> ::capnp::Result { + ::core::result::Result::Ok(reader.get_struct(default)?.into()) + } + } + + impl <'a,> ::capnp::traits::IntoInternalStructReader<'a> for Reader<'a,> { + fn into_internal_struct_reader(self) -> ::capnp::private::layout::StructReader<'a> { + self.reader + } + } + + impl <'a,> ::capnp::traits::Imbue<'a> for Reader<'a,> { + fn imbue(&mut self, cap_table: &'a ::capnp::private::layout::CapTable) { + self.reader.imbue(::capnp::private::layout::CapTableReader::Plain(cap_table)) + } + } + + impl <'a,> Reader<'a,> { + pub fn reborrow(&self) -> Reader<'_,> { + Self { .. *self } + } + + pub fn total_size(&self) -> ::capnp::Result<::capnp::MessageSize> { + self.reader.total_size() + } + #[inline] + pub fn get_prefix(self) -> ::capnp::Result<::capnp::text::Reader<'a>> { + ::capnp::traits::FromPointerReader::get_from_pointer(&self.reader.get_pointer_field(0), ::core::option::Option::Some(&_private::DEFAULT_PREFIX[..])) + } + #[inline] + pub fn has_prefix(&self) -> bool { + !self.reader.get_pointer_field(0).is_null() + } + } + + pub struct Builder<'a> { builder: ::capnp::private::layout::StructBuilder<'a> } + impl <> ::capnp::traits::HasStructSize for Builder<'_,> { + const STRUCT_SIZE: ::capnp::private::layout::StructSize = ::capnp::private::layout::StructSize { data: 0, pointers: 1 }; + } + impl <> ::capnp::traits::HasTypeId for Builder<'_,> { + const TYPE_ID: u64 = _private::TYPE_ID; + } + impl <'a,> ::core::convert::From<::capnp::private::layout::StructBuilder<'a>> for Builder<'a,> { + fn from(builder: ::capnp::private::layout::StructBuilder<'a>) -> Self { + Self { builder, } + } + } + + impl <'a,> ::core::convert::From> for ::capnp::dynamic_value::Builder<'a> { + fn from(builder: Builder<'a,>) -> Self { + Self::Struct(::capnp::dynamic_struct::Builder::new(builder.builder, ::capnp::schema::StructSchema::new(::capnp::introspect::RawBrandedStructSchema { generic: &_private::RAW_SCHEMA, field_types: _private::get_field_types::<>, annotation_types: _private::get_annotation_types::<>}))) + } + } + + impl <'a,> ::capnp::traits::ImbueMut<'a> for Builder<'a,> { + fn imbue_mut(&mut self, cap_table: &'a mut ::capnp::private::layout::CapTable) { + self.builder.imbue(::capnp::private::layout::CapTableBuilder::Plain(cap_table)) + } + } + + impl <'a,> ::capnp::traits::FromPointerBuilder<'a> for Builder<'a,> { + fn init_pointer(builder: ::capnp::private::layout::PointerBuilder<'a>, _size: u32) -> Self { + builder.init_struct(::STRUCT_SIZE).into() + } + fn get_from_pointer(builder: ::capnp::private::layout::PointerBuilder<'a>, default: ::core::option::Option<&'a [::capnp::Word]>) -> ::capnp::Result { + ::core::result::Result::Ok(builder.get_struct(::STRUCT_SIZE, default)?.into()) + } + } + + impl <> ::capnp::traits::SetterInput> for Reader<'_,> { + fn set_pointer_builder(mut pointer: ::capnp::private::layout::PointerBuilder<'_>, value: Self, canonicalize: bool) -> ::capnp::Result<()> { pointer.set_struct(&value.reader, canonicalize) } + } + + impl <'a,> Builder<'a,> { + pub fn into_reader(self) -> Reader<'a,> { + self.builder.into_reader().into() + } + pub fn reborrow(&mut self) -> Builder<'_,> { + Builder { builder: self.builder.reborrow() } + } + pub fn reborrow_as_reader(&self) -> Reader<'_,> { + self.builder.as_reader().into() + } + + pub fn total_size(&self) -> ::capnp::Result<::capnp::MessageSize> { + self.builder.as_reader().total_size() + } + #[inline] + pub fn get_prefix(self) -> ::capnp::Result<::capnp::text::Builder<'a>> { + ::capnp::traits::FromPointerBuilder::get_from_pointer(self.builder.get_pointer_field(0), ::core::option::Option::Some(&_private::DEFAULT_PREFIX[..])) + } + #[inline] + pub fn set_prefix(&mut self, value: impl ::capnp::traits::SetterInput<::capnp::text::Owned>) { + ::capnp::traits::SetterInput::set_pointer_builder(self.builder.reborrow().get_pointer_field(0), value, false).unwrap() + } + #[inline] + pub fn init_prefix(self, size: u32) -> ::capnp::text::Builder<'a> { + self.builder.get_pointer_field(0).init_text(size) + } + #[inline] + pub fn has_prefix(&self) -> bool { + !self.builder.is_pointer_field_null(0) + } + } + + pub struct Pipeline { _typeless: ::capnp::any_pointer::Pipeline } + impl ::capnp::capability::FromTypelessPipeline for Pipeline { + fn new(typeless: ::capnp::any_pointer::Pipeline) -> Self { + Self { _typeless: typeless, } + } + } + impl Pipeline { + } + mod _private { + pub static ENCODED_NODE: [::capnp::Word; 35] = [ + ::capnp::word(0, 0, 0, 0, 6, 0, 6, 0), + ::capnp::word(97, 234, 194, 123, 37, 19, 223, 196), + ::capnp::word(11, 0, 0, 0, 1, 0, 0, 0), + ::capnp::word(52, 94, 58, 164, 151, 146, 249, 142), + ::capnp::word(1, 0, 7, 0, 0, 0, 0, 0), + ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(180, 15, 0, 0, 35, 16, 0, 0), + ::capnp::word(21, 0, 0, 0, 210, 0, 0, 0), + ::capnp::word(33, 0, 0, 0, 7, 0, 0, 0), + ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(29, 0, 0, 0, 63, 0, 0, 0), + ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(106, 115, 111, 110, 46, 99, 97, 112), + ::capnp::word(110, 112, 58, 70, 108, 97, 116, 116), + ::capnp::word(101, 110, 79, 112, 116, 105, 111, 110), + ::capnp::word(115, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(0, 0, 0, 0, 1, 0, 1, 0), + ::capnp::word(4, 0, 0, 0, 3, 0, 4, 0), + ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(0, 0, 1, 0, 0, 0, 0, 0), + ::capnp::word(1, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(13, 0, 0, 0, 58, 0, 0, 0), + ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(8, 0, 0, 0, 3, 0, 1, 0), + ::capnp::word(20, 0, 0, 0, 2, 0, 1, 0), + ::capnp::word(112, 114, 101, 102, 105, 120, 0, 0), + ::capnp::word(12, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(12, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(1, 0, 0, 0, 10, 0, 0, 0), + ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), + ]; + pub fn get_field_types(index: u16) -> ::capnp::introspect::Type { + match index { + 0 => <::capnp::text::Owned as ::capnp::introspect::Introspect>::introspect(), + _ => ::capnp::introspect::panic_invalid_field_index(index), + } + } + pub fn get_annotation_types(child_index: Option, index: u32) -> ::capnp::introspect::Type { + ::capnp::introspect::panic_invalid_annotation_indices(child_index, index) + } + pub static RAW_SCHEMA: ::capnp::introspect::RawStructSchema = ::capnp::introspect::RawStructSchema { + encoded_node: &ENCODED_NODE, + nonunion_members: NONUNION_MEMBERS, + members_by_discriminant: MEMBERS_BY_DISCRIMINANT, + members_by_name: MEMBERS_BY_NAME, + }; + pub static NONUNION_MEMBERS : &[u16] = &[0]; + pub static MEMBERS_BY_DISCRIMINANT : &[u16] = &[]; + pub static MEMBERS_BY_NAME : &[u16] = &[0]; + pub static DEFAULT_PREFIX: [::capnp::Word; 2] = [ + ::capnp::word(1, 0, 0, 0, 10, 0, 0, 0), + ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), + ]; + pub const TYPE_ID: u64 = 0xc4df_1325_7bc2_ea61; + } +} +pub mod discriminator { + pub const ID: u64 = 0xcfa794e8d19a0162; + pub fn get_type() -> ::capnp::introspect::Type { ::introspect() } +} + +pub mod discriminator_options { + #[derive(Copy, Clone)] + pub struct Owned(()); + impl ::capnp::introspect::Introspect for Owned { fn introspect() -> ::capnp::introspect::Type { ::capnp::introspect::TypeVariant::Struct(::capnp::introspect::RawBrandedStructSchema { generic: &_private::RAW_SCHEMA, field_types: _private::get_field_types, annotation_types: _private::get_annotation_types }).into() } } + impl ::capnp::traits::Owned for Owned { type Reader<'a> = Reader<'a>; type Builder<'a> = Builder<'a>; } + impl ::capnp::traits::OwnedStruct for Owned { type Reader<'a> = Reader<'a>; type Builder<'a> = Builder<'a>; } + impl ::capnp::traits::Pipelined for Owned { type Pipeline = Pipeline; } + + pub struct Reader<'a> { reader: ::capnp::private::layout::StructReader<'a> } + impl <> ::core::marker::Copy for Reader<'_,> {} + impl <> ::core::clone::Clone for Reader<'_,> { + fn clone(&self) -> Self { *self } + } + + impl <> ::capnp::traits::HasTypeId for Reader<'_,> { + const TYPE_ID: u64 = _private::TYPE_ID; + } + impl <'a,> ::core::convert::From<::capnp::private::layout::StructReader<'a>> for Reader<'a,> { + fn from(reader: ::capnp::private::layout::StructReader<'a>) -> Self { + Self { reader, } + } + } + + impl <'a,> ::core::convert::From> for ::capnp::dynamic_value::Reader<'a> { + fn from(reader: Reader<'a,>) -> Self { + Self::Struct(::capnp::dynamic_struct::Reader::new(reader.reader, ::capnp::schema::StructSchema::new(::capnp::introspect::RawBrandedStructSchema { generic: &_private::RAW_SCHEMA, field_types: _private::get_field_types::<>, annotation_types: _private::get_annotation_types::<>}))) + } + } + + impl <> ::core::fmt::Debug for Reader<'_,> { + fn fmt(&self, f: &mut ::core::fmt::Formatter<'_>) -> ::core::result::Result<(), ::core::fmt::Error> { + core::fmt::Debug::fmt(&::core::convert::Into::<::capnp::dynamic_value::Reader<'_>>::into(*self), f) + } + } + + impl <'a,> ::capnp::traits::FromPointerReader<'a> for Reader<'a,> { + fn get_from_pointer(reader: &::capnp::private::layout::PointerReader<'a>, default: ::core::option::Option<&'a [::capnp::Word]>) -> ::capnp::Result { + ::core::result::Result::Ok(reader.get_struct(default)?.into()) + } + } + + impl <'a,> ::capnp::traits::IntoInternalStructReader<'a> for Reader<'a,> { + fn into_internal_struct_reader(self) -> ::capnp::private::layout::StructReader<'a> { + self.reader + } + } + + impl <'a,> ::capnp::traits::Imbue<'a> for Reader<'a,> { + fn imbue(&mut self, cap_table: &'a ::capnp::private::layout::CapTable) { + self.reader.imbue(::capnp::private::layout::CapTableReader::Plain(cap_table)) + } + } + + impl <'a,> Reader<'a,> { + pub fn reborrow(&self) -> Reader<'_,> { + Self { .. *self } + } + + pub fn total_size(&self) -> ::capnp::Result<::capnp::MessageSize> { + self.reader.total_size() + } + #[inline] + pub fn get_name(self) -> ::capnp::Result<::capnp::text::Reader<'a>> { + ::capnp::traits::FromPointerReader::get_from_pointer(&self.reader.get_pointer_field(0), ::core::option::Option::None) + } + #[inline] + pub fn has_name(&self) -> bool { + !self.reader.get_pointer_field(0).is_null() + } + #[inline] + pub fn get_value_name(self) -> ::capnp::Result<::capnp::text::Reader<'a>> { + ::capnp::traits::FromPointerReader::get_from_pointer(&self.reader.get_pointer_field(1), ::core::option::Option::None) + } + #[inline] + pub fn has_value_name(&self) -> bool { + !self.reader.get_pointer_field(1).is_null() + } + } + + pub struct Builder<'a> { builder: ::capnp::private::layout::StructBuilder<'a> } + impl <> ::capnp::traits::HasStructSize for Builder<'_,> { + const STRUCT_SIZE: ::capnp::private::layout::StructSize = ::capnp::private::layout::StructSize { data: 0, pointers: 2 }; + } + impl <> ::capnp::traits::HasTypeId for Builder<'_,> { + const TYPE_ID: u64 = _private::TYPE_ID; + } + impl <'a,> ::core::convert::From<::capnp::private::layout::StructBuilder<'a>> for Builder<'a,> { + fn from(builder: ::capnp::private::layout::StructBuilder<'a>) -> Self { + Self { builder, } + } + } + + impl <'a,> ::core::convert::From> for ::capnp::dynamic_value::Builder<'a> { + fn from(builder: Builder<'a,>) -> Self { + Self::Struct(::capnp::dynamic_struct::Builder::new(builder.builder, ::capnp::schema::StructSchema::new(::capnp::introspect::RawBrandedStructSchema { generic: &_private::RAW_SCHEMA, field_types: _private::get_field_types::<>, annotation_types: _private::get_annotation_types::<>}))) + } + } + + impl <'a,> ::capnp::traits::ImbueMut<'a> for Builder<'a,> { + fn imbue_mut(&mut self, cap_table: &'a mut ::capnp::private::layout::CapTable) { + self.builder.imbue(::capnp::private::layout::CapTableBuilder::Plain(cap_table)) + } + } + + impl <'a,> ::capnp::traits::FromPointerBuilder<'a> for Builder<'a,> { + fn init_pointer(builder: ::capnp::private::layout::PointerBuilder<'a>, _size: u32) -> Self { + builder.init_struct(::STRUCT_SIZE).into() + } + fn get_from_pointer(builder: ::capnp::private::layout::PointerBuilder<'a>, default: ::core::option::Option<&'a [::capnp::Word]>) -> ::capnp::Result { + ::core::result::Result::Ok(builder.get_struct(::STRUCT_SIZE, default)?.into()) + } + } + + impl <> ::capnp::traits::SetterInput> for Reader<'_,> { + fn set_pointer_builder(mut pointer: ::capnp::private::layout::PointerBuilder<'_>, value: Self, canonicalize: bool) -> ::capnp::Result<()> { pointer.set_struct(&value.reader, canonicalize) } + } + + impl <'a,> Builder<'a,> { + pub fn into_reader(self) -> Reader<'a,> { + self.builder.into_reader().into() + } + pub fn reborrow(&mut self) -> Builder<'_,> { + Builder { builder: self.builder.reborrow() } + } + pub fn reborrow_as_reader(&self) -> Reader<'_,> { + self.builder.as_reader().into() + } + + pub fn total_size(&self) -> ::capnp::Result<::capnp::MessageSize> { + self.builder.as_reader().total_size() + } + #[inline] + pub fn get_name(self) -> ::capnp::Result<::capnp::text::Builder<'a>> { + ::capnp::traits::FromPointerBuilder::get_from_pointer(self.builder.get_pointer_field(0), ::core::option::Option::None) + } + #[inline] + pub fn set_name(&mut self, value: impl ::capnp::traits::SetterInput<::capnp::text::Owned>) { + ::capnp::traits::SetterInput::set_pointer_builder(self.builder.reborrow().get_pointer_field(0), value, false).unwrap() + } + #[inline] + pub fn init_name(self, size: u32) -> ::capnp::text::Builder<'a> { + self.builder.get_pointer_field(0).init_text(size) + } + #[inline] + pub fn has_name(&self) -> bool { + !self.builder.is_pointer_field_null(0) + } + #[inline] + pub fn get_value_name(self) -> ::capnp::Result<::capnp::text::Builder<'a>> { + ::capnp::traits::FromPointerBuilder::get_from_pointer(self.builder.get_pointer_field(1), ::core::option::Option::None) + } + #[inline] + pub fn set_value_name(&mut self, value: impl ::capnp::traits::SetterInput<::capnp::text::Owned>) { + ::capnp::traits::SetterInput::set_pointer_builder(self.builder.reborrow().get_pointer_field(1), value, false).unwrap() + } + #[inline] + pub fn init_value_name(self, size: u32) -> ::capnp::text::Builder<'a> { + self.builder.get_pointer_field(1).init_text(size) + } + #[inline] + pub fn has_value_name(&self) -> bool { + !self.builder.is_pointer_field_null(1) + } + } + + pub struct Pipeline { _typeless: ::capnp::any_pointer::Pipeline } + impl ::capnp::capability::FromTypelessPipeline for Pipeline { + fn new(typeless: ::capnp::any_pointer::Pipeline) -> Self { + Self { _typeless: typeless, } + } + } + impl Pipeline { + } + mod _private { + pub static ENCODED_NODE: [::capnp::Word; 50] = [ + ::capnp::word(0, 0, 0, 0, 6, 0, 6, 0), + ::capnp::word(25, 83, 62, 41, 12, 194, 248, 194), + ::capnp::word(11, 0, 0, 0, 1, 0, 0, 0), + ::capnp::word(52, 94, 58, 164, 151, 146, 249, 142), + ::capnp::word(2, 0, 7, 0, 0, 0, 0, 0), + ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(187, 17, 0, 0, 184, 19, 0, 0), + ::capnp::word(21, 0, 0, 0, 2, 1, 0, 0), + ::capnp::word(33, 0, 0, 0, 7, 0, 0, 0), + ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(29, 0, 0, 0, 119, 0, 0, 0), + ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(106, 115, 111, 110, 46, 99, 97, 112), + ::capnp::word(110, 112, 58, 68, 105, 115, 99, 114), + ::capnp::word(105, 109, 105, 110, 97, 116, 111, 114), + ::capnp::word(79, 112, 116, 105, 111, 110, 115, 0), + ::capnp::word(0, 0, 0, 0, 1, 0, 1, 0), + ::capnp::word(8, 0, 0, 0, 3, 0, 4, 0), + ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(0, 0, 1, 0, 0, 0, 0, 0), + ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(41, 0, 0, 0, 42, 0, 0, 0), + ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(36, 0, 0, 0, 3, 0, 1, 0), + ::capnp::word(48, 0, 0, 0, 2, 0, 1, 0), + ::capnp::word(1, 0, 0, 0, 1, 0, 0, 0), + ::capnp::word(0, 0, 1, 0, 1, 0, 0, 0), + ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(45, 0, 0, 0, 82, 0, 0, 0), + ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(44, 0, 0, 0, 3, 0, 1, 0), + ::capnp::word(56, 0, 0, 0, 2, 0, 1, 0), + ::capnp::word(110, 97, 109, 101, 0, 0, 0, 0), + ::capnp::word(12, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(12, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(118, 97, 108, 117, 101, 78, 97, 109), + ::capnp::word(101, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(12, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(12, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), + ]; + pub fn get_field_types(index: u16) -> ::capnp::introspect::Type { + match index { + 0 => <::capnp::text::Owned as ::capnp::introspect::Introspect>::introspect(), + 1 => <::capnp::text::Owned as ::capnp::introspect::Introspect>::introspect(), + _ => ::capnp::introspect::panic_invalid_field_index(index), + } + } + pub fn get_annotation_types(child_index: Option, index: u32) -> ::capnp::introspect::Type { + ::capnp::introspect::panic_invalid_annotation_indices(child_index, index) + } + pub static RAW_SCHEMA: ::capnp::introspect::RawStructSchema = ::capnp::introspect::RawStructSchema { + encoded_node: &ENCODED_NODE, + nonunion_members: NONUNION_MEMBERS, + members_by_discriminant: MEMBERS_BY_DISCRIMINANT, + members_by_name: MEMBERS_BY_NAME, + }; + pub static NONUNION_MEMBERS : &[u16] = &[0,1]; + pub static MEMBERS_BY_DISCRIMINANT : &[u16] = &[]; + pub static MEMBERS_BY_NAME : &[u16] = &[0,1]; + pub const TYPE_ID: u64 = 0xc2f8_c20c_293e_5319; + } +} +pub mod base64 { + pub const ID: u64 = 0xd7d879450a253e4b; + pub fn get_type() -> ::capnp::introspect::Type { <() as ::capnp::introspect::Introspect>::introspect() } +} +pub mod hex { + pub const ID: u64 = 0xf061e22f0ae5c7b5; + pub fn get_type() -> ::capnp::introspect::Type { <() as ::capnp::introspect::Introspect>::introspect() } +} +pub mod notification { + pub const ID: u64 = 0xa0a054dea32fd98c; + pub fn get_type() -> ::capnp::introspect::Type { <() as ::capnp::introspect::Introspect>::introspect() } +} diff --git a/capnp-json/src/lib.rs b/capnp-json/src/lib.rs new file mode 100644 index 000000000..5d14ac844 --- /dev/null +++ b/capnp-json/src/lib.rs @@ -0,0 +1,5 @@ +pub mod json; +pub mod json_capnp; + +pub use json::*; + diff --git a/capnp-json/test/Cargo.toml b/capnp-json/test/Cargo.toml new file mode 100644 index 000000000..051733a1f --- /dev/null +++ b/capnp-json/test/Cargo.toml @@ -0,0 +1,20 @@ +[package] + +name = "capnp-json-test" +version = "0.0.0" +authors = [ "David Renshaw ", "Ben Jackson " ] +build = "build.rs" +edition = "2021" + +[lib] +name = "capnp_json_test" +path = "json.rs" + +[build-dependencies] +capnpc = { path = "../../capnpc" } + +[dependencies] +capnp = { path = "../../capnp" } +capnpc = { path = "../../capnpc" } +capnp-json = { path = "../" } +external-crate = { path = "../../capnpc/test/external-crate" } diff --git a/capnp-json/test/build.rs b/capnp-json/test/build.rs new file mode 100644 index 000000000..5a74494ad --- /dev/null +++ b/capnp-json/test/build.rs @@ -0,0 +1,9 @@ +fn main() { + capnpc::CompilerCommand::new() + .crate_provides("external_crate", [0xe6f94f52f7be8fe2]) + .crate_provides("capnp_json", [0x8ef99297a43a5e34]) // json.capnp + .file("test.capnp") + .file("json-test.capnp") + .run() + .expect("compiling schema"); +} diff --git a/capnpc/test/json-test.capnp b/capnp-json/test/json-test.capnp similarity index 100% rename from capnpc/test/json-test.capnp rename to capnp-json/test/json-test.capnp diff --git a/capnp-json/test/json.rs b/capnp-json/test/json.rs new file mode 100644 index 000000000..246af86aa --- /dev/null +++ b/capnp-json/test/json.rs @@ -0,0 +1,725 @@ +// Copyright (c) 2025 Ben Jackson [puremourning@gmail.com] and Cap'n Proto contributors +// Licensed under the MIT License: +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. + +capnp::generated_code!(pub mod test_capnp); +capnp::generated_code!(pub mod json_test_capnp); + +#[cfg(test)] +mod tests { + use crate::json_test_capnp::test_json_annotations; + use crate::test_capnp::{ + test_json_flatten_union, test_json_types, test_union, test_unnamed_union, TestEnum, + }; + use capnp::message; + use capnp_json as json; + + #[test] + fn test_encode_json_types_default() { + let mut builder = message::Builder::new_default(); + let root: test_json_types::Builder<'_> = builder.init_root(); + let expected = r#"{"voidField":null,"boolField":false,"int8Field":0,"int16Field":0,"int32Field":0,"int64Field":0,"uInt8Field":0,"uInt16Field":0,"uInt32Field":0,"uInt64Field":0,"float32Field":0,"float64Field":0,"enumField":"foo"}"#; + assert_eq!(expected, json::to_json(root.reborrow_as_reader()).unwrap()); + } + + #[test] + fn test_encode_all_json_types() { + let mut builder = message::Builder::new_default(); + let mut root: test_json_types::Builder<'_> = builder.init_root(); + root.set_int8_field(-8); + root.set_int16_field(-16); + root.set_int32_field(-32); + root.set_int64_field(-64); + root.set_u_int8_field(8); + root.set_u_int16_field(16); + root.set_u_int32_field(32); + root.set_u_int64_field(64); + root.set_bool_field(true); + root.set_void_field(()); + root.set_text_field("hello"); + root.set_float32_field(1.32); + root.set_float64_field(1.64); + root.set_data_field(&[0xde, 0xad, 0xbe, 0xef, 0xca, 0xfe, 0xba, 0xbe]); + root.set_base64_field(&[0xde, 0xad, 0xbe, 0xef, 0xca, 0xfe, 0xba, 0xbe]); + root.set_hex_field(&[0xde, 0xad, 0xbe, 0xef, 0xca, 0xfe, 0xba, 0xbe]); + { + let mut embedded = root.reborrow().init_struct_field(); + let mut text_list = embedded.reborrow().init_text_list(2); + text_list.set(0, "frist"); + text_list.set(1, "segund"); + embedded.set_text_field("inner"); + let mut hex_list = embedded.reborrow().init_hex_list(2); + hex_list.set(0, &[0xde, 0xad, 0xbe, 0xef]); + hex_list.set(1, &[0xba, 0xdf, 0x00, 0xd0]); + let mut based_list = embedded.reborrow().init_base64_list(2); + based_list.set(0, &[0xde, 0xad, 0xbe, 0xef]); + based_list.set(1, &[0xba, 0xdf, 0x00, 0xd0]); + } + root.set_enum_field(TestEnum::Quux); + { + let mut enum_list = root.reborrow().init_enum_list(3); + enum_list.set(0, TestEnum::Foo); + enum_list.set(1, TestEnum::Bar); + enum_list.set(2, TestEnum::Garply); + } + { + let mut floats = root.reborrow().init_float32_list(3); + floats.set(0, f32::NAN); + floats.set(1, f32::INFINITY); + floats.set(2, f32::NEG_INFINITY); + } + { + let mut floats = root.reborrow().init_float64_list(3); + floats.set(0, f64::NAN); + floats.set(1, f64::INFINITY); + floats.set(2, f64::NEG_INFINITY); + } + + let expected = concat!( + "{", + r#""voidField":null,"#, + r#""boolField":true,"#, + r#""int8Field":-8,"#, + r#""int16Field":-16,"#, + r#""int32Field":-32,"#, + r#""int64Field":-64,"#, + r#""uInt8Field":8,"#, + r#""uInt16Field":16,"#, + r#""uInt32Field":32,"#, + r#""uInt64Field":64,"#, + r#""float32Field":1.3200000524520874,"#, + r#""float64Field":1.64,"#, + r#""textField":"hello","#, + r#""dataField":[222,173,190,239,202,254,186,190],"#, + r#""base64Field":"3q2+78r+ur4=","#, + r#""hexField":"deadbeefcafebabe","#, + r#""structField":{"#, + r#""voidField":null,"#, + r#""boolField":false,"#, + r#""int8Field":0,"#, + r#""int16Field":0,"#, + r#""int32Field":0,"#, + r#""int64Field":0,"#, + r#""uInt8Field":0,"#, + r#""uInt16Field":0,"#, + r#""uInt32Field":0,"#, + r#""uInt64Field":0,"#, + r#""float32Field":0,"#, + r#""float64Field":0,"#, + r#""textField":"inner","#, + r#""enumField":"foo","#, + r#""textList":["frist","segund"],"#, + r#""base64List":["3q2+7w==","ut8A0A=="],"#, + r#""hexList":["deadbeef","badf00d0"]"#, + "},", + r#""enumField":"quux","#, + r#""float32List":["NaN","Infinity","-Infinity"],"#, + r#""float64List":["NaN","Infinity","-Infinity"],"#, + r#""enumList":["foo","bar","garply"]"#, + "}" + ); + assert_eq!(expected, json::to_json(root.reborrow_as_reader()).unwrap()); + } + + // Union encoding with flattening + + #[test] + fn test_named_union_non_flattened() { + let mut builder = message::Builder::new_default(); + let mut root: test_union::Builder<'_> = builder.init_root(); + root.set_bit0(true); + root.set_bit2(false); + root.set_bit3(true); + root.set_bit4(false); + root.set_bit5(true); + root.set_bit6(false); + root.set_bit7(true); + root.set_byte0(0xAA); + let mut union0 = root.reborrow().init_union0(); + union0.set_u0f0sp("not this one"); + union0.set_u0f0s16(-12345); + + let expected = concat!( + "{", + r#""union0":{"u0f0s16":-12345},"#, + r#""union1":{"u1f0s0":null},"#, + r#""union2":{"u2f0s1":false},"#, + r#""union3":{"u3f0s1":false},"#, + r#""bit0":true,"#, + r#""bit2":false,"#, + r#""bit3":true,"#, + r#""bit4":false,"#, + r#""bit5":true,"#, + r#""bit6":false,"#, + r#""bit7":true,"#, + r#""byte0":170"#, + "}", + ); + + assert_eq!(expected, json::to_json(root.reborrow_as_reader()).unwrap()); + } + + #[test] + fn test_unnamed_union() { + let mut builder = message::Builder::new_default(); + let mut root: test_unnamed_union::Builder<'_> = builder.init_root(); + root.set_before("before"); + root.set_middle(1234); + root.set_after("after"); + root.set_foo(16); + root.set_bar(32); + let expected = concat!( + "{", + r#""before":"before","#, + r#""middle":1234,"#, + r#""after":"after","#, + r#""bar":32"#, + "}", + ); + assert_eq!(expected, json::to_json(root.reborrow_as_reader()).unwrap()); + } + + #[test] + fn test_named_union_flattened() { + let mut builder = message::Builder::new_default(); + let mut root: test_json_flatten_union::Builder<'_> = builder.init_root(); + root.set_before("before"); + root.set_middle(1234); + root.set_after("after"); + let mut maybe = root.reborrow().init_maybe(); + maybe.set_foo(16); + maybe.set_bar(32); + + let expected = concat!( + "{", + r#""before":"before","#, + r#""maybe_bar":32,"#, + r#""middle":1234,"#, + r#""after":"after","#, + r#""foo":0,"#, + r#""bar":0,"#, + r#""nested_baz":0,"#, + r#""baz":0"#, + "}", + ); + assert_eq!(expected, json::to_json(root.reborrow_as_reader()).unwrap()); + } + + #[test] + fn test_discriminated_union() { + let mut builder = message::Builder::new_default(); + let mut root: test_json_annotations::Builder<'_> = builder.init_root(); + + let mut expected = String::from("{"); + + root.set_some_field("Some Field"); + expected.push_str(r#""names-can_contain!anything Really":"Some Field","#); + + { + let mut a_group = root.reborrow().init_a_group(); + // a_group is flattenned + a_group.set_flat_foo(0xF00); + expected.push_str(r#""flatFoo":3840,"#); + + a_group.set_flat_bar("0xBaa"); + expected.push_str(r#""flatBar":"0xBaa","#); + + a_group.reborrow().init_flat_baz().set_hello(true); + expected.push_str(r#""renamed-flatBaz":{"hello":true},"#); + + a_group.reborrow().init_double_flat().set_flat_qux("Qux"); + expected.push_str(r#""flatQux":"Qux","#); + } + + { + let mut prefixed_group = root.reborrow().init_prefixed_group(); + prefixed_group.set_foo("Foo"); + expected.push_str(r#""pfx.foo":"Foo","#); + + prefixed_group.set_bar(0xBAA); + expected.push_str(r#""pfx.renamed-bar":2986,"#); + + prefixed_group.reborrow().init_baz().set_hello(false); + expected.push_str(r#""pfx.baz":{"hello":false},"#); + + prefixed_group.reborrow().init_more_prefix().set_qux("Qux"); + expected.push_str(r#""pfx.xfp.qux":"Qux","#); + } + + { + let mut a_union_bar = root.reborrow().init_a_union().init_bar(); + expected.push_str(r#""union-type":"renamed-bar","#); + a_union_bar.set_bar_member(0xAAB); + expected.push_str(r#""barMember":2731,"#); + a_union_bar.set_multi_member("Member"); + expected.push_str(r#""multiMember":"Member","#); + } + + { + let mut dependency = root.reborrow().init_dependency(); + dependency.set_foo("dep-foo"); + expected.push_str(r#""dependency":{"renamed-foo":"dep-foo"},"#); + } + + { + let mut simple_group = root.reborrow().init_simple_group(); + simple_group.set_grault("grault"); + expected.push_str(r#""simpleGroup":{"renamed-grault":"grault"},"#); + } + + { + let mut e = root.reborrow().init_enums(4); + e.set(0, crate::json_test_capnp::TestJsonAnnotatedEnum::Foo); + e.set(1, crate::json_test_capnp::TestJsonAnnotatedEnum::Bar); + e.set(2, crate::json_test_capnp::TestJsonAnnotatedEnum::Baz); + e.set(3, crate::json_test_capnp::TestJsonAnnotatedEnum::Qux); + expected.push_str(r#""enums":["foo","renamed-bar","renamed-baz","qux"],"#); + } + + { + let mut b_union = root.reborrow().init_b_union(); + expected.push_str(r#""bUnion":"renamed-bar","#); + b_union.set_bar(100); + expected.push_str(r#""bValue":100,"#); + } + + { + let mut external_union = root.reborrow().init_external_union(); + external_union.reborrow().init_bar().set_value("Value"); + expected.push_str(r#""externalUnion":{"type":"bar","value":"Value"},"#); + } + + { + let mut union_with_void = root.reborrow().init_union_with_void(); + union_with_void.set_void_value(()); + expected.push_str(r#""unionWithVoid":{"type":"voidValue","voidValue":null},"#); + } + + expected.pop(); // Remove trailing comma + expected.push('}'); + + assert_eq!(expected, json::to_json(root.reborrow_as_reader()).unwrap()); + } + + #[test] + fn test_base64_union() { + let mut builder = message::Builder::new_default(); + let mut root: crate::json_test_capnp::test_base64_union::Builder<'_> = builder.init_root(); + + root.set_foo(&[0xde, 0xad, 0xbe, 0xef]); + assert_eq!( + r#"{"foo":"3q2+7w=="}"#, + json::to_json(root.reborrow_as_reader()).unwrap() + ); + } + + #[test] + fn test_string_encoding() { + let mut builder = message::Builder::new_default(); + let mut root: crate::json_test_capnp::test_flattened_struct::Builder<'_> = + builder.init_root(); + + root.set_value(""); + assert_eq!( + r#"{"value":""}"#, + json::to_json(root.reborrow_as_reader()).unwrap() + ); + + root.set_value("tab: \t, newline: \n, carriage return: \r, quote: \", backslash: \\"); + assert_eq!( + r#"{"value":"tab: \t, newline: \n, carriage return: \r, quote: \", backslash: \\"}"#, + json::to_json(root.reborrow_as_reader()).unwrap() + ); + + root.set_value("unicode: †eśt"); + assert_eq!( + r#"{"value":"unicode: †eśt"}"#, + json::to_json(root.reborrow_as_reader()).unwrap() + ); + + root.set_value("backspace: \u{0008}, formfeed: \u{000C}"); + assert_eq!( + r#"{"value":"backspace: \b, formfeed: \f"}"#, + json::to_json(root.reborrow_as_reader()).unwrap() + ); + + root.set_value("bell: \u{0007}, SOH: \u{0001}"); + assert_eq!( + r#"{"value":"bell: \u0007, SOH: \u0001"}"#, + json::to_json(root.reborrow_as_reader()).unwrap() + ); + } + + #[test] + fn test_nested_data_list() -> capnp::Result<()> { + let mut builder = message::Builder::new_default(); + let mut root = builder.init_root::>(); + let mut awd = root.reborrow().init_data_all_the_way_down(2); + let mut first = awd.reborrow().init(0, 2); + first.set(0, &[0xde, 0xad, 0xbe, 0xef]); + first.set(1, &[0xef, 0xbe, 0xad, 0xde]); + let mut second = awd.reborrow().init(1, 1); + second.set(0, &[0xba, 0xdf, 0x00, 0xd0]); + + assert_eq!( + r#"{"dataAllTheWayDown":[["deadbeef","efbeadde"],["badf00d0"]]}"#, + json::to_json(root.reborrow_as_reader())? + ); + + Ok(()) + } + + // Decode + + #[test] + fn test_decode_simple() -> capnp::Result<()> { + let mut builder = message::Builder::new_default(); + let mut root: test_json_types::Builder<'_> = builder.init_root(); + json::from_json( + r#" + { + "voidField": null, + "boolField": true, + "int8Field": -8, + "int16Field": -16, + "int32Field": -32, + "int64Field": -64, + "uInt8Field": 8, + "uInt16Field": 16, + "uInt32Field": 32, + "uInt64Field": 64, + "float32Field": 1.3200000524520874, + "float64Field": 0.164e2, + "textField": "hello", + "dataField": [ + 222, + 173 + + , + + 190, + 239, + 202, + 254, + 186, + 190 + ], + "base64Field": "3q2+78r+ur4=", + "hexField": "deadbeefcafebabe", + "structField": { + "voidField": null, + "boolField": false, + "int8Field": 0, + "int16Field": 0, + "int32Field": 0, + "int64Field": 0, + "uInt8Field": 0, + "uInt16Field" + : 0, + "uInt32Field": 0, + "uInt64Field": 0, + "float32Field": 0, + "float64Field": 0, + "textField": "inner", + "enumField": "foo", + "textList": [ + "frist", + "segund" + ], + "base64List": [ + "3q2+7w==", + "ut8A0A==" + ], + "hexList": [ + "deadbeef", + "badf00d0" + ] + }, + "enumField": "quux", + "float32List": [ + "NaN", + "Infinity", + "-Infinity" + ], + "float64List": [ + "NaN", + "Infinity" , + "-Infinity" + ], + "enumList": [ + "foo", + "bar", + "garply" + ], + "int64List": [ + 1, + 2, + 4, + 8 + ] + } + "#, + root.reborrow(), + )?; + + let reader = root.into_reader(); + assert_eq!((), reader.get_void_field()); + assert_eq!(true, reader.get_bool_field()); + assert_eq!(-8, reader.get_int8_field()); + assert_eq!(-16, reader.get_int16_field()); + assert_eq!(-32, reader.get_int32_field()); + assert_eq!(-64, reader.get_int64_field()); + assert_eq!(8, reader.get_u_int8_field()); + assert_eq!(16, reader.get_u_int16_field()); + assert_eq!(32, reader.get_u_int32_field()); + assert_eq!(64, reader.get_u_int64_field()); + assert_eq!(1.32, reader.get_float32_field()); + assert_eq!(16.4, reader.get_float64_field()); + assert_eq!("hello", reader.get_text_field()?.to_str()?); + assert_eq!( + [0xde, 0xad, 0xbe, 0xef, 0xca, 0xfe, 0xba, 0xbe], + reader.get_data_field()? + ); + assert_eq!( + [0xde, 0xad, 0xbe, 0xef, 0xca, 0xfe, 0xba, 0xbe], + reader.get_base64_field()? + ); + assert_eq!( + [0xde, 0xad, 0xbe, 0xef, 0xca, 0xfe, 0xba, 0xbe], + reader.get_hex_field()? + ); + + for i in 0..4 { + assert_eq!(1 << i, reader.get_int64_list()?.get(i as u32)); + } + + Ok(()) + } + + #[test] + fn test_encode_with_empty_flattened() -> capnp::Result<()> { + let mut builder = capnp::message::Builder::new_default(); + let root = + builder.init_root::>(); + + assert_eq!( + r#"{"flatFoo":0,"renamed-flatBaz":{"hello":false},"pfx.renamed-bar":0,"pfx.baz":{"hello":false},"union-type":"foo","multiMember":0,"simpleGroup":{},"unionWithVoid":{"type":"intValue","intValue":0}}"#, + json::to_json(root.reborrow_as_reader())? + ); + + Ok(()) + } + + #[test] + fn test_decode_flattened() -> capnp::Result<()> { + let j = r#" + { + "names-can_contain!anything Really": "Some Field", + "flatFoo": 1234, + "flatBar": "0xBaa", + "renamed-flatBaz": {"hello": true}, + "flatQux": "Qux", + "pfx.baz": {"hello": true}, + "union-type": "renamed-bar", + "barMember": 2731, + "multiMember": "Member", + "bUnion": "renamed-bar", + "bValue": 100 + } + "#; + let mut builder = capnp::message::Builder::new_default(); + let mut root = + builder.init_root::>(); + json::from_json(j, root.reborrow())?; + + let reader = root.into_reader(); + assert_eq!("Some Field", reader.get_some_field()?.to_str()?); + assert_eq!(1234, reader.get_a_group().get_flat_foo()); + assert_eq!("0xBaa", reader.get_a_group().get_flat_bar()?.to_str()?); + assert_eq!(true, reader.get_a_group().get_flat_baz().get_hello()); + assert_eq!( + "Qux", + reader + .get_a_group() + .get_double_flat() + .get_flat_qux()? + .to_str()? + ); + assert_eq!(true, reader.get_prefixed_group().get_baz().get_hello()); + assert!(matches!( + reader.get_a_union().which()?, + crate::json_test_capnp::test_json_annotations::a_union::Bar(_) + )); + { + let bar = match reader.get_a_union().which()? { + crate::json_test_capnp::test_json_annotations::a_union::Bar(b) => b, + _ => panic!("Expected Bar"), + }; + assert_eq!(2731, bar.get_bar_member()); + assert_eq!("Member", bar.get_multi_member()?.to_str()?); + } + assert!(matches!( + reader.get_b_union().which()?, + crate::json_test_capnp::test_json_annotations::b_union::Bar(_) + )); + { + let bar = match reader.get_b_union().which()? { + crate::json_test_capnp::test_json_annotations::b_union::Bar(b) => b, + _ => panic!("Expected Bar"), + }; + assert_eq!(100, bar); + } + + Ok(()) + } + + #[test] + fn test_decode_base64_union() -> capnp::Result<()> { + { + let j = r#" + { + "foo":"3q2+7w==" + } + "#; + let mut builder = capnp::message::Builder::new_default(); + let mut root = + builder.init_root::>(); + json::from_json(j, root.reborrow())?; + + let reader = root.into_reader(); + assert!(matches!( + reader.which()?, + crate::json_test_capnp::test_base64_union::Foo(_) + )); + { + let foo = match reader.which()? { + crate::json_test_capnp::test_base64_union::Foo(f) => f, + _ => panic!("Expected Foo"), + }?; + assert_eq!(&[0xde, 0xad, 0xbe, 0xef], foo); + } + } + + { + let j = r#" + { + "bar":"To the bar!" + } + "#; + let mut builder = capnp::message::Builder::new_default(); + let mut root = + builder.init_root::>(); + json::from_json(j, root.reborrow())?; + + let reader = root.into_reader(); + assert!(matches!( + reader.which()?, + crate::json_test_capnp::test_base64_union::Bar(_) + )); + { + let bar = match reader.which()? { + crate::json_test_capnp::test_base64_union::Bar(b) => b?, + _ => panic!("Expected Foo"), + }; + assert_eq!("To the bar!", bar.to_str()?); + } + } + + // When both variants are present, we pick the first one in the spec + { + let j = r#" + { + "bar":"To the bar!", + "foo":"3q2+7w==" + } + "#; + let mut builder = capnp::message::Builder::new_default(); + let mut root = + builder.init_root::>(); + json::from_json(j, root.reborrow())?; + + let reader = root.into_reader(); + assert!(matches!( + reader.which()?, + crate::json_test_capnp::test_base64_union::Foo(_) + )); + { + let foo = match reader.which()? { + crate::json_test_capnp::test_base64_union::Foo(f) => f, + _ => panic!("Expected Foo"), + }?; + assert_eq!(&[0xde, 0xad, 0xbe, 0xef], foo); + } + } + + { + let j = r#" + { + "bar":"To the bar!", + "foo":"3q2+7w==" + } + "#; + let mut builder = capnp::message::Builder::new_default(); + let mut root = + builder.init_root::>(); + json::from_json(j, root.reborrow())?; + + let reader = root.into_reader(); + assert!(matches!( + reader.which()?, + crate::json_test_capnp::test_renamed_anon_union::Bar(_) + )); + { + let bar = match reader.which()? { + crate::json_test_capnp::test_renamed_anon_union::Bar(b) => b?, + _ => panic!("Expected Foo"), + }; + assert_eq!("To the bar!", bar.to_str()?); + } + } + + { + let j = r#" + { + "bar":"To the bar!", + "renamed-foo":"3q2+7w==" + } + "#; + let mut builder = capnp::message::Builder::new_default(); + let mut root = + builder.init_root::>(); + json::from_json(j, root.reborrow())?; + + let reader = root.into_reader(); + assert!(matches!( + reader.which()?, + crate::json_test_capnp::test_renamed_anon_union::Foo(_) + )); + { + let foo = match reader.which()? { + crate::json_test_capnp::test_renamed_anon_union::Foo(f) => f, + _ => panic!("Expected Foo"), + }?; + assert_eq!(&[0xde, 0xad, 0xbe, 0xef], foo); + } + } + Ok(()) + } +} diff --git a/capnp-json/test/test.capnp b/capnp-json/test/test.capnp new file mode 100644 index 000000000..5e74480e9 --- /dev/null +++ b/capnp-json/test/test.capnp @@ -0,0 +1,863 @@ +# Copyright (c) 2013-2014 Sandstorm Development Group, Inc. and contributors +# Licensed under the MIT License: +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in +# all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +# THE SOFTWARE. +# + +@0x99d187209d25cee7; + +using Json = import "/capnp/compat/json.capnp"; + +struct FieldSubsetIndexesCorrectly { + common @2 :Text; + + union { + unset @0 :Void; + variant @1 :UInt8; + } +} + +struct TestPrimList { + uint8List @0 : List(UInt8); + int8List @1 : List(Int8); + uint16List @2 : List(UInt16); + int16List @3 : List(Int16); + uint32List @4 : List(UInt32); + int32List @5 : List(Int32); + uint64List @6 : List(UInt64); + int64List @7 : List(Int64); + float32List @8 : List(Float32); + boolList @9 : List(Bool); + voidList @10 : List(Void); +} + +struct TestStructList { + structList @0 : List(TestPrimList); +} + +struct TestBlob { + textField @0 : Text; + dataField @1 : Data; +} + +struct TestBigStruct { + voidField @0 : Void; + boolField @1 : Bool; + int8Field @2 : Int8; + int16Field @3 : Int16; + int32Field @4 : Int32; + int64Field @5 : Int64; + uint8Field @6 : UInt8; + uint16Field @7 : UInt16; + uint32Field @8 : UInt32; + uint64Field @9 : UInt64; + float32Field @10 : Float32; + float64Field @11 : Float64; + + structField @12 : Inner; + anotherStructField @13 : Inner; + + struct Inner { + uint32Field @0 : UInt32; + uint64Field @1 : UInt64; + float32Field @2 : Float32; + float64Field @3 : Float64; + boolFieldA @4 : Bool; + boolFieldB @5 : Bool; + boolFieldC @6 : Bool; + boolFieldD @7 : Bool; + } +} + +enum AnEnum { + foo @0; + bar @1; + baz @2; + qux @3; +} + +struct TestComplexList { + enumList @0 : List(AnEnum); + textList @1 : List(Text); + dataList @2 : List(Data); + primListList @3 : List(List(Int32)); + primListListList @4 : List(List(List(Int16))); + enumListList @5 : List(List(AnEnum)); + textListList @6 : List(List(Text)); + dataListList @7 : List(List(Data)); + structListList @8 : List(List(TestBigStruct)); +} + +enum TestEnum { + foo @0; + bar @1; + baz @2; + qux @3; + quux @4; + corge @5; + grault @6; + garply @7; +} + +enum TestEnumWithTrickyNames { + foo @0; + bar @1; + error @2; +} + +struct TestAllTypes { + voidField @0 : Void; + boolField @1 : Bool; + int8Field @2 : Int8; + int16Field @3 : Int16; + int32Field @4 : Int32; + int64Field @5 : Int64; + uInt8Field @6 : UInt8; + uInt16Field @7 : UInt16; + uInt32Field @8 : UInt32; + uInt64Field @9 : UInt64; + float32Field @10 : Float32; + float64Field @11 : Float64; + textField @12 : Text; + dataField @13 : Data; + structField @14 : TestAllTypes; + enumField @15 : TestEnum; + interfaceField @16 : EmptyInterface; + + voidList @17 : List(Void); + boolList @18 : List(Bool); + int8List @19 : List(Int8); + int16List @20 : List(Int16); + int32List @21 : List(Int32); + int64List @22 : List(Int64); + uInt8List @23 : List(UInt8); + uInt16List @24 : List(UInt16); + uInt32List @25 : List(UInt32); + uInt64List @26 : List(UInt64); + float32List @27 : List(Float32); + float64List @28 : List(Float64); + textList @29 : List(Text); + dataList @30 : List(Data); + structList @31 : List(TestAllTypes); + enumList @32 : List(TestEnum); + interfaceList @33 : List(EmptyInterface); +} + +struct TestDefaults { + voidField @0 :Void = void; + boolField @1 :Bool = true; + int8Field @2 :Int8 = -123; + int16Field @3 :Int16 = -12345; + int32Field @4 :Int32 = -12345678; + int64Field @5 :Int64 = -123456789012345; + uInt8Field @6 :UInt8 = 234; + uInt16Field @7 :UInt16 = 45678; + uInt32Field @8 :UInt32 = 3456789012; + uInt64Field @9 :UInt64 = 12345678901234567890; + float32Field @10 :Float32 = 1234.5; + float64Field @11 :Float64 = -123e45; + textField @12 :Text = "foo"; + dataField @13 :Data = 0x"62 61 72"; # "bar" + structField @14 : TestAllTypes = ( + voidField = void, + boolField = true, + int8Field = -12, + int16Field = 3456, + int32Field = -78901234, + int64Field = 56789012345678, + uInt8Field = 90, + uInt16Field = 1234, + uInt32Field = 56789012, + uInt64Field = 345678901234567890, + float32Field = -1.25e-10, + float64Field = 345, + textField = "baz", + dataField = "qux", + structField = ( + textField = "nested", + structField = (textField = "really nested")), + enumField = baz, + # interfaceField can't have a default + + voidList = [void, void, void], + boolList = [false, true, false, true, true], + int8List = [12, -34, -0x80, 0x7f], + int16List = [1234, -5678, -0x8000, 0x7fff], + int32List = [12345678, -90123456, -0x80000000, 0x7fffffff], + int64List = [123456789012345, -678901234567890, -0x8000000000000000, 0x7fffffffffffffff], + uInt8List = [12, 34, 0, 0xff], + uInt16List = [1234, 5678, 0, 0xffff], + uInt32List = [12345678, 90123456, 0, 0xffffffff], + uInt64List = [123456789012345, 678901234567890, 0, 0xffffffffffffffff], + float32List = [0, 1234567, 1e37, -1e37, 1e-37, -1e-37], + float64List = [0, 123456789012345, 1e306, -1e306, 1e-306, -1e-306], + textList = ["quux", "corge", "grault"], + dataList = ["garply", "waldo", "fred"], + structList = [ + (textField = "x structlist 1"), + (textField = "x structlist 2"), + (textField = "x structlist 3")], + enumList = [qux, bar, grault] + # interfaceList can't have a default + ); + + enumField @15 : TestEnum = corge; + interfaceField @16 : Void; # TODO + + voidList @17 : List(Void) = [void, void, void, void, void, void]; + boolList @18 : List(Bool) = [true, false, false, true]; + int8List @19 : List(Int8) = [111, -111]; + int16List @20 : List(Int16) = [11111, -11111]; + int32List @21 : List(Int32) = [111111111, -111111111]; + int64List @22 : List(Int64) = [1111111111111111111, -1111111111111111111]; + uInt8List @23 : List(UInt8) = [111, 222] ; + uInt16List @24 : List(UInt16) = [33333, 44444]; + uInt32List @25 : List(UInt32) = [3333333333]; + uInt64List @26 : List(UInt64) = [11111111111111111111]; + float32List @27 : List(Float32) = [5555.5, inf, -inf, nan]; + float64List @28 : List(Float64) = [7777.75, inf, -inf, nan]; + textList @29 : List(Text) = ["plugh", "xyzzy", "thud"]; + dataList @30 : List(Data) = ["oops", "exhausted", "rfc3092"]; + structList @31 : List(TestAllTypes) = [ + (textField = "structlist 1"), + (textField = "structlist 2"), + (textField = "structlist 3")]; + enumList @32 : List(TestEnum) = [foo, garply]; + interfaceList @33 : List(Void); # TODO +} + +struct TestAnyPointer { + anyPointerField @0 :AnyPointer; +} + +struct TestUnion { + union0 @0! :union { + # Pack union 0 under ideal conditions: there is no unused padding space prior to it. + u0f0s0 @4: Void; + u0f0s1 @5: Bool; + u0f0s8 @6: Int8; + u0f0s16 @7: Int16; + u0f0s32 @8: Int32; + u0f0s64 @9: Int64; + u0f0sp @10: Text; + + # Pack more stuff into union0 -- should go in same space. + u0f1s0 @11: Void; + u0f1s1 @12: Bool; + u0f1s8 @13: Int8; + u0f1s16 @14: Int16; + u0f1s32 @15: Int32; + u0f1s64 @16: Int64; + u0f1sp @17: Text; + } + + # Pack one bit in order to make pathological situation for union1. + bit0 @18: Bool; + + union1 @1! :union { + # Pack pathologically bad case. Each field takes up new space. + u1f0s0 @19: Void; + u1f0s1 @20: Bool; + u1f1s1 @21: Bool; + u1f0s8 @22: Int8; + u1f1s8 @23: Int8; + u1f0s16 @24: Int16; + u1f1s16 @25: Int16; + u1f0s32 @26: Int32; + u1f1s32 @27: Int32; + u1f0s64 @28: Int64; + u1f1s64 @29: Int64; + u1f0sp @30: Text; + u1f1sp @31: Text; + + # Pack more stuff into union1 -- each should go into the same space as corresponding u1f0s*. + u1f2s0 @32: Void; + u1f2s1 @33: Bool; + u1f2s8 @34: Int8; + u1f2s16 @35: Int16; + u1f2s32 @36: Int32; + u1f2s64 @37: Int64; + u1f2sp @38: Text; + } + + # Fill in the rest of that bitfield from earlier. + bit2 @39: Bool; + bit3 @40: Bool; + bit4 @41: Bool; + bit5 @42: Bool; + bit6 @43: Bool; + bit7 @44: Bool; + + # Interleave two unions to be really annoying. + # Also declare in reverse order to make sure union discriminant values are sorted by field number + # and not by declaration order. + union2 @2! :union { + u2f0s64 @54: Int64; + u2f0s32 @52: Int32; + u2f0s16 @50: Int16; + u2f0s8 @47: Int8; + u2f0s1 @45: Bool; + } + + union3 @3! :union { + u3f0s64 @55: Int64; + u3f0s32 @53: Int32; + u3f0s16 @51: Int16; + u3f0s8 @48: Int8; + u3f0s1 @46: Bool; + } + + byte0 @49: UInt8; +} + +struct TestUnnamedUnion { + before @0 :Text; + + union { + foo @1 :UInt16; + bar @3 :UInt32; + } + + middle @2 :UInt16; + + after @4 :Text; +} + +struct TestGroups { + groups :union { + foo :group { + corge @0 :Int32; + grault @2 :Int64; + garply @8 :Text; + } + bar :group { + corge @3 :Int32; + grault @4 :Text; + garply @5 :Int64; + } + baz :group { + corge @1 :Int32; + grault @6 :Text; + garply @7 :Text; + quz @9 :Float64; + anEnum @10 :TestEnum; + } + } +} + +struct TestUnionDefaults { + s16s8s64s8Set @0 :TestUnion = + (union0 = (u0f0s16 = 321), union1 = (u1f0s8 = 123), union2 = (u2f0s64 = 12345678901234567), + union3 = (u3f0s8 = 55)); + s0sps1s32Set @1 :TestUnion = + (union0 = (u0f1s0 = void), union1 = (u1f0sp = "foo"), union2 = (u2f0s1 = true), + union3 = (u3f0s32 = 12345678)); + + unnamed1 @2 :TestUnnamedUnion = (foo = 123); + unnamed2 @3 :TestUnnamedUnion = (bar = 321, before = "foo", after = "bar"); + + inner1 :union { + a @4 :UInt8 = 17; + b @5 :Text = "foobar"; + } + + inner2 :union { + c @6 :Text = "grault"; + d @7 :UInt8 = 19; + } +} + +struct TestLists { + struct Struct0 { f @0 :Void; } + struct Struct1 { f @0 :Bool; } + struct Struct8 { f @0 :UInt8; } + struct Struct16 { f @0 :UInt16; } + struct Struct32 { f @0 :UInt32; } + struct Struct64 { f @0 :UInt64; } + struct StructP { f @0 :Text; } + + struct Struct0c { f @0 :Void; pad @1 :Text; } + struct Struct1c { f @0 :Bool; pad @1 :Text; } + struct Struct8c { f @0 :UInt8; pad @1 :Text; } + struct Struct16c { f @0 :UInt16; pad @1 :Text; } + struct Struct32c { f @0 :UInt32; pad @1 :Text; } + struct Struct64c { f @0 :UInt64; pad @1 :Text; } + struct StructPc { f @0 :Text; pad @1 :UInt64; } + + list0 @0 :List(Struct0); + list1 @1 :List(Struct1); + list8 @2 :List(Struct8); + list16 @3 :List(Struct16); + list32 @4 :List(Struct32); + list64 @5 :List(Struct64); + listP @6 :List(StructP); + + int32ListList @7 :List(List(Int32)); + textListList @8 :List(List(Text)); + structListList @9 :List(List(TestAllTypes)); +} + +struct TestOldVersion { + # A subset of TestNewVersion. + old1 @0 :Int64; + old2 @1 :Text; + old3 @2 :TestOldVersion; + old4 @3 :List(Text); +} + +struct TestNewVersion { + # A superset of TestOldVersion. + old1 @0 :Int64; + old2 @1 :Text; + old3 @2 :TestNewVersion; + + struct UpgradedFromText { + textField @0 :Text; + int32Field @1 :Int32; + dataField @2 :Data; + } + old4 @3 :List(UpgradedFromText); + new1 @4 :Int64 = 987; + new2 @5 :Text = "baz"; + new3 @6 :TestDefaults; +} + +struct TestOldUnionVersion { + union { + a @0 :Void; + b @1 :UInt64; + } +} + +struct TestNewUnionVersion { + union { + a :union { + a0 @0 :Void; + a1 @2 :UInt64; + } + b @1 :UInt64; + } +} + +struct TestGenerics(Foo, Bar) { + foo @0 :Foo; + bar @1 :Bar; + rev @2 :TestGenerics(Bar, Foo); + dub @3 :TestGenerics(Text, List(UInt8)); + + struct Inner { + foo @0 :Foo; + bar @1 :Bar; + } + + struct Inner2(Baz) { + bar @0 :Bar; + baz @1 :Baz; + innerBound @2 :Inner; + innerUnbound @3 :TestGenerics.Inner; + + struct DeepNest(Qux) { + foo @0 :Foo; + bar @1 :Bar; + baz @2 :Baz; + qux @3 :Qux; + } + } + + interface Interface(Qux) { + call @0 Inner2(Text) -> (qux :Qux, gen :TestGenerics(TestAllTypes, TestAnyPointer)); + otherCall @1 Inner2(List(Text)) -> Inner2(List(Int16)); + } + + annotation ann(struct) :Foo; + + using AliasFoo = Foo; + using AliasInner = Inner; + using AliasInner2 = Inner2; + using AliasInner2Text = Inner2(Text); + using AliasRev = TestGenerics(Bar, Foo); + + struct UseAliases { + foo @0 :AliasFoo; + inner @1 :AliasInner; + inner2 @2 :AliasInner2; + inner2Bind @3 :AliasInner2(Text); + inner2Text @4 :AliasInner2Text; + revFoo @5 :AliasRev.AliasFoo; + } +} + +struct TestGenericsWrapper(Foo, Bar) { + value @0 :TestGenerics(Foo, Bar); +} + +struct TestGenericsWrapper2 { + value @0 :TestGenericsWrapper(Text, TestAllTypes); +} + +interface TestImplicitMethodParams { + call @0 [T, U] (foo :T, bar :U) -> TestGenerics(T, U); +} + +interface TestImplicitMethodParamsInGeneric(V) { + call @0 [T, U] (foo :T, bar :U) -> TestGenerics(T, U); + call1 @1 [T, U] TestGenerics(T, U) -> (foo :T, bar: U); + call2 @2 [T, U] TestGenerics(T, U) -> TestAllTypes; + call3 @3 [T, U] TestAllTypes -> TestAllTypes; + call4 @4 [T, U] TestGenerics(V, V) -> TestGenerics(V, AnyPointer); +} + +struct TestGenericsUnion(Foo, Bar) { + union { + foo1 @0 :Foo; + bar1 @1 :Bar; + foo2 @2 :Foo; + } +} + +struct TestGenericsGroups(T1, T2) { + foo @0 :T1; + bar :group { + baz @1 :T2; + } + + struct Inner(T3, T4) { + foo @0 :T3; + bar :union { + baz @1 :Void; + qux @2 :Int32; + } + } +} + +struct TestUseGenerics $TestGenerics(Text, Data).ann("foo") { + basic @0 :TestGenerics(TestAllTypes, TestAnyPointer); + inner @1 :TestGenerics(TestAllTypes, TestAnyPointer).Inner; + inner2 @2 :TestGenerics(TestAllTypes, TestAnyPointer).Inner2(Text); + unspecified @3 :TestGenerics; + unspecifiedInner @4 :TestGenerics.Inner2(Text); + wrapper @8 :TestGenericsWrapper(TestAllTypes, TestAnyPointer); + cap @18 :TestGenerics(TestInterface, Text); + + genericCap @19 :TestGenerics(TestAllTypes, List(UInt32)).Interface(Data); + + default @5 :TestGenerics(TestAllTypes, Text) = + (foo = (int16Field = 123), rev = (foo = "text", rev = (foo = (int16Field = 321)))); + defaultInner @6 :TestGenerics(TestAllTypes, Text).Inner = + (foo = (int16Field = 123), bar = "text"); + defaultUser @7 :TestUseGenerics = (basic = (foo = (int16Field = 123))); + defaultWrapper @9 :TestGenericsWrapper(Text, TestAllTypes) = + (value = (foo = "text", rev = (foo = (int16Field = 321)))); + defaultWrapper2 @10 :TestGenericsWrapper2 = + (value = (value = (foo = "text", rev = (foo = (int16Field = 321))))); + + aliasFoo @11 :TestGenerics(TestAllTypes, TestAnyPointer).AliasFoo = (int16Field = 123); + aliasInner @12 :TestGenerics(TestAllTypes, TestAnyPointer).AliasInner + = (foo = (int16Field = 123)); + aliasInner2 @13 :TestGenerics(TestAllTypes, TestAnyPointer).AliasInner2 + = (innerBound = (foo = (int16Field = 123))); + aliasInner2Bind @14 :TestGenerics(TestAllTypes, TestAnyPointer).AliasInner2(List(UInt32)) + = (baz = [12, 34], innerBound = (foo = (int16Field = 123))); + aliasInner2Text @15 :TestGenerics(TestAllTypes, TestAnyPointer).AliasInner2Text + = (baz = "text", innerBound = (foo = (int16Field = 123))); + aliasRev @16 :TestGenerics(TestAnyPointer, Text).AliasRev.AliasFoo = "text"; + + useAliases @17 :TestGenerics(TestAllTypes, List(UInt32)).UseAliases = ( + foo = (int16Field = 123), + inner = (foo = (int16Field = 123)), + inner2 = (innerBound = (foo = (int16Field = 123))), + inner2Bind = (baz = "text", innerBound = (foo = (int16Field = 123))), + inner2Text = (baz = "text", innerBound = (foo = (int16Field = 123)))); +} + +struct TestEmptyStruct {} + +struct TestConstants { + const voidConst :Void = void; + const boolConst :Bool = true; + const int8Const :Int8 = -123; + const int16Const :Int16 = -12345; + const int32Const :Int32 = -12345678; + const int64Const :Int64 = -123456789012345; + const uint8Const :UInt8 = 234; + const uint16Const :UInt16 = 45678; + const uint32Const :UInt32 = 3456789012; + const uint64Const :UInt64 = 12345678901234567890; + const float32Const :Float32 = 1234.5; + const float64Const :Float64 = -123e45; + const textConst :Text = "foo"; + const complexTextConst :Text = "foo\"☺\'$$$"; + const dataConst :Data = "bar"; + const structConst :TestAllTypes = ( + voidField = void, + boolField = true, + int8Field = -12, + int16Field = 3456, + int32Field = -78901234, + int64Field = 56789012345678, + uInt8Field = 90, + uInt16Field = 1234, + uInt32Field = 56789012, + uInt64Field = 345678901234567890, + float32Field = -1.25e-10, + float64Field = 345, + textField = "baz", + dataField = "qux", + structField = ( + textField = "nested", + structField = (textField = "really nested")), + enumField = baz, + + voidList = [void, void, void], + boolList = [false, true, false, true, true], + int8List = [12, -34, -0x80, 0x7f], + int16List = [1234, -5678, -0x8000, 0x7fff], + int32List = [12345678, -90123456, -0x80000000, 0x7fffffff], + int64List = [123456789012345, -678901234567890, -0x8000000000000000, 0x7fffffffffffffff], + uInt8List = [12, 34, 0, 0xff], + uInt16List = [1234, 5678, 0, 0xffff], + uInt32List = [12345678, 90123456, 0, 0xffffffff], + uInt64List = [123456789012345, 678901234567890, 0, 0xffffffffffffffff], + float32List = [0, 1234567, 1e37, -1e37, 1e-37, -1e-37], + float64List = [0, 123456789012345, 1e306, -1e306, 1e-306, -1e-306], + textList = ["quux", "corge", "grault"], + dataList = ["garply", "waldo", "fred"], + structList = [ + (textField = "x structlist 1"), + (textField = "x structlist 2"), + (textField = "x structlist 3")], + enumList = [qux, bar, grault] + ); + + const enumConst :TestEnum = corge; + + const voidListConst :List(Void) = [void, void, void, void, void, void]; + const boolListConst :List(Bool) = [true, false, false, true]; + const int8ListConst :List(Int8) = [111, -111]; + const int16ListConst :List(Int16) = [11111, -11111]; + const int32ListConst :List(Int32) = [111111111, -111111111]; + const int64ListConst :List(Int64) = [1111111111111111111, -1111111111111111111]; + const uint8ListConst :List(UInt8) = [111, 222] ; + const uint16ListConst :List(UInt16) = [33333, 44444]; + const uint32ListConst :List(UInt32) = [3333333333]; + const uint64ListConst :List(UInt64) = [11111111111111111111]; + const float32ListConst :List(Float32) = [5555.5, inf, -inf, nan]; + const float64ListConst :List(Float64) = [7777.75, inf, -inf, nan]; + const textListConst :List(Text) = ["plugh", "xyzzy", "thud"]; + const dataListConst :List(Data) = ["oops", "exhausted", "rfc3092"]; + const structListConst :List(TestAllTypes) = [ + (textField = "structlist 1"), + (textField = "structlist 2"), + (textField = "structlist 3")]; + const enumListConst :List(TestEnum) = [foo, garply]; +} + +const globalInt :UInt32 = 12345; + +struct TestFloatConsts { + const a :Float32 = inf; + const b :Float32 = -inf; + const c :Float32 = nan; + + const x :Float64 = inf; + const y :Float64 = -inf; + const z :Float64 = nan; + + const pi32 : Float32 = 3.14159265358979323846264338327950288; + const pi64 : Float64 = 3.14159265358979323846264338327950288; +} + +interface TestInterface { + foo @0 (i :UInt32, j :Bool) -> (x : Text); + bar @1 () -> (); + baz @2 (s : TestBigStruct); + bazz @3 (s : TestBigStruct) -> (r : TestBigStruct); +} + +interface TestExtends extends(TestInterface) { + qux @0 (); + corge @1 TestBigStruct -> (); + grault @2 () -> TestBigStruct; +} + +struct TestCapabilityList { + foo @0 :List(TestInterface); +} + +interface EmptyInterface {} + +struct TestKeywords { + struct As {} + struct Box {} + struct Break {} + struct Continue {} + struct Crate {} + struct Else {} + struct Enum {} + struct Extern {} + # ... + struct Struct{} + struct Super{} + struct True{} + struct Trait{} + struct Type{} + struct Unsafe{} + struct Use{} + struct While{} +} + +struct Issue77 { + data :union { + a @0 :UInt16; + b @1 :UInt8; + } + + text :union { + c @2 :Bool; + d @3 :Int32; + } + + layout :union { + e @4 :Void; + f @5 :Void; + } + + structList :union { + g @6 :Void; + h @7 :Void; + } + + enumList :union { + i @8 :Void; + j @9 :Void; + } + + primitiveList :union { + k @10 :Void; + l @11 :Void; + } + + dataList :union { + m @12 :Void; + n @13 :Void; + } + + textList :union { + o @14 :Void; + p @15 :Void; + } + + listList :union { + q @16 :Void; + r @17 :Void; + } +} + +struct GenericOnce(Foo) { + genericField @0 : Foo; +} + +struct BrandOnce { + brandedField @0 : GenericOnce(TestAllTypes); +} + +struct GenericTwice(Foo,Bar) { + fooField @0 : Foo; + barField @1 : Bar; +} + +struct BrandTwice { + bazField @0 : GenericTwice(Text, TestBlob); +} + +struct Map(Key, Value) { + entries @0 :List(Entry); + struct Entry { + key @0 :Key; + value @1 :Value; + } +} + +interface GenericBase(T) {} +interface GenericExtend extends(GenericBase(Data)) {} +interface GenericExtend2 extends (GenericBase(GenericBase(Data))) {} + +struct TestJsonTypes { + voidField @0 : Void; + boolField @1 : Bool; + int8Field @2 : Int8; + int16Field @3 : Int16; + int32Field @4 : Int32; + int64Field @5 : Int64; + uInt8Field @6 : UInt8; + uInt16Field @7 : UInt16; + uInt32Field @8 : UInt32; + uInt64Field @9 : UInt64; + float32Field @10 : Float32; + float64Field @11 : Float64; + textField @12 : Text; + dataField @13 : Data; + base64Field @14 : Data $Json.base64; + hexField @15 : Data $Json.hex; + structField @16 : TestJsonTypes; + enumField @17 : TestEnum; + + voidList @18 : List(Void); + boolList @19 : List(Bool); + int8List @20 : List(Int8); + int16List @21 : List(Int16); + int32List @22 : List(Int32); + int64List @23 : List(Int64); + uInt8List @24 : List(UInt8); + uInt16List @25 : List(UInt16); + uInt32List @26 : List(UInt32); + uInt64List @27 : List(UInt64); + float32List @28 : List(Float32); + float64List @29 : List(Float64); + textList @30 : List(Text); + dataList @31 : List(Data); + base64List @32 : List(Data) $Json.base64; + hexList @33 : List(Data) $Json.hex; + structList @34 : List(TestJsonTypes); + enumList @35 : List(TestEnum); +} + +struct TestJsonFlattenUnion { + before @0 :Text; + + maybe :union $Json.flatten("maybe_") { # field, group, union to test + foo @1 :UInt16; + bar @3 :UInt32; + } + + groupie :group $Json.flatten() { + foo @5 :UInt16; + bar @6 :UInt32; + prefixed :group $Json.flatten("nested_") { + baz @7 :UInt8; + } + nested :group $Json.flatten() { + baz @8 :UInt8; + } + } + + middle @2 :UInt16; + + after @4 :Text; +} diff --git a/capnp/src/json_capnp.rs b/capnp/src/json_capnp.rs deleted file mode 100644 index 4edcd7673..000000000 --- a/capnp/src/json_capnp.rs +++ /dev/null @@ -1,1521 +0,0 @@ -// @generated by the capnpc-rust plugin to the Cap'n Proto schema compiler. -// DO NOT EDIT. -// source: json.capnp - - -pub mod value { - pub use self::Which::{Null,Boolean,Number,String,Array,Object,Call,Raw}; - - #[derive(Copy, Clone)] - pub struct Owned(()); - impl crate::introspect::Introspect for Owned { fn introspect() -> crate::introspect::Type { crate::introspect::TypeVariant::Struct(crate::introspect::RawBrandedStructSchema { generic: &_private::RAW_SCHEMA, field_types: _private::get_field_types, annotation_types: _private::get_annotation_types }).into() } } - impl crate::traits::Owned for Owned { type Reader<'a> = Reader<'a>; type Builder<'a> = Builder<'a>; } - impl crate::traits::OwnedStruct for Owned { type Reader<'a> = Reader<'a>; type Builder<'a> = Builder<'a>; } - impl crate::traits::Pipelined for Owned { type Pipeline = Pipeline; } - - pub struct Reader<'a> { reader: crate::private::layout::StructReader<'a> } - impl <> ::core::marker::Copy for Reader<'_,> {} - impl <> ::core::clone::Clone for Reader<'_,> { - fn clone(&self) -> Self { *self } - } - - impl <> crate::traits::HasTypeId for Reader<'_,> { - const TYPE_ID: u64 = _private::TYPE_ID; - } - impl <'a,> ::core::convert::From> for Reader<'a,> { - fn from(reader: crate::private::layout::StructReader<'a>) -> Self { - Self { reader, } - } - } - - impl <'a,> ::core::convert::From> for crate::dynamic_value::Reader<'a> { - fn from(reader: Reader<'a,>) -> Self { - Self::Struct(crate::dynamic_struct::Reader::new(reader.reader, crate::schema::StructSchema::new(crate::introspect::RawBrandedStructSchema { generic: &_private::RAW_SCHEMA, field_types: _private::get_field_types::<>, annotation_types: _private::get_annotation_types::<>}))) - } - } - - impl <> ::core::fmt::Debug for Reader<'_,> { - fn fmt(&self, f: &mut ::core::fmt::Formatter<'_>) -> ::core::result::Result<(), ::core::fmt::Error> { - core::fmt::Debug::fmt(&::core::convert::Into::>::into(*self), f) - } - } - - impl <'a,> crate::traits::FromPointerReader<'a> for Reader<'a,> { - fn get_from_pointer(reader: &crate::private::layout::PointerReader<'a>, default: ::core::option::Option<&'a [crate::Word]>) -> crate::Result { - ::core::result::Result::Ok(reader.get_struct(default)?.into()) - } - } - - impl <'a,> crate::traits::IntoInternalStructReader<'a> for Reader<'a,> { - fn into_internal_struct_reader(self) -> crate::private::layout::StructReader<'a> { - self.reader - } - } - - impl <'a,> crate::traits::Imbue<'a> for Reader<'a,> { - fn imbue(&mut self, cap_table: &'a crate::private::layout::CapTable) { - self.reader.imbue(crate::private::layout::CapTableReader::Plain(cap_table)) - } - } - - impl <'a,> Reader<'a,> { - pub fn reborrow(&self) -> Reader<'_,> { - Self { .. *self } - } - - pub fn total_size(&self) -> crate::Result { - self.reader.total_size() - } - #[inline] - pub fn has_string(&self) -> bool { - if self.reader.get_data_field::(0) != 3 { return false; } - !self.reader.get_pointer_field(0).is_null() - } - #[inline] - pub fn has_array(&self) -> bool { - if self.reader.get_data_field::(0) != 4 { return false; } - !self.reader.get_pointer_field(0).is_null() - } - #[inline] - pub fn has_object(&self) -> bool { - if self.reader.get_data_field::(0) != 5 { return false; } - !self.reader.get_pointer_field(0).is_null() - } - #[inline] - pub fn has_call(&self) -> bool { - if self.reader.get_data_field::(0) != 6 { return false; } - !self.reader.get_pointer_field(0).is_null() - } - #[inline] - pub fn has_raw(&self) -> bool { - if self.reader.get_data_field::(0) != 7 { return false; } - !self.reader.get_pointer_field(0).is_null() - } - #[inline] - pub fn which(self) -> ::core::result::Result, crate::NotInSchema> { - match self.reader.get_data_field::(0) { - 0 => { - ::core::result::Result::Ok(Null( - () - )) - } - 1 => { - ::core::result::Result::Ok(Boolean( - self.reader.get_bool_field(16) - )) - } - 2 => { - ::core::result::Result::Ok(Number( - self.reader.get_data_field::(1) - )) - } - 3 => { - ::core::result::Result::Ok(String( - crate::traits::FromPointerReader::get_from_pointer(&self.reader.get_pointer_field(0), ::core::option::Option::None) - )) - } - 4 => { - ::core::result::Result::Ok(Array( - crate::traits::FromPointerReader::get_from_pointer(&self.reader.get_pointer_field(0), ::core::option::Option::None) - )) - } - 5 => { - ::core::result::Result::Ok(Object( - crate::traits::FromPointerReader::get_from_pointer(&self.reader.get_pointer_field(0), ::core::option::Option::None) - )) - } - 6 => { - ::core::result::Result::Ok(Call( - crate::traits::FromPointerReader::get_from_pointer(&self.reader.get_pointer_field(0), ::core::option::Option::None) - )) - } - 7 => { - ::core::result::Result::Ok(Raw( - crate::traits::FromPointerReader::get_from_pointer(&self.reader.get_pointer_field(0), ::core::option::Option::None) - )) - } - x => ::core::result::Result::Err(crate::NotInSchema(x)) - } - } - } - - pub struct Builder<'a> { builder: crate::private::layout::StructBuilder<'a> } - impl <> crate::traits::HasStructSize for Builder<'_,> { - const STRUCT_SIZE: crate::private::layout::StructSize = crate::private::layout::StructSize { data: 2, pointers: 1 }; - } - impl <> crate::traits::HasTypeId for Builder<'_,> { - const TYPE_ID: u64 = _private::TYPE_ID; - } - impl <'a,> ::core::convert::From> for Builder<'a,> { - fn from(builder: crate::private::layout::StructBuilder<'a>) -> Self { - Self { builder, } - } - } - - impl <'a,> ::core::convert::From> for crate::dynamic_value::Builder<'a> { - fn from(builder: Builder<'a,>) -> Self { - Self::Struct(crate::dynamic_struct::Builder::new(builder.builder, crate::schema::StructSchema::new(crate::introspect::RawBrandedStructSchema { generic: &_private::RAW_SCHEMA, field_types: _private::get_field_types::<>, annotation_types: _private::get_annotation_types::<>}))) - } - } - - impl <'a,> crate::traits::ImbueMut<'a> for Builder<'a,> { - fn imbue_mut(&mut self, cap_table: &'a mut crate::private::layout::CapTable) { - self.builder.imbue(crate::private::layout::CapTableBuilder::Plain(cap_table)) - } - } - - impl <'a,> crate::traits::FromPointerBuilder<'a> for Builder<'a,> { - fn init_pointer(builder: crate::private::layout::PointerBuilder<'a>, _size: u32) -> Self { - builder.init_struct(::STRUCT_SIZE).into() - } - fn get_from_pointer(builder: crate::private::layout::PointerBuilder<'a>, default: ::core::option::Option<&'a [crate::Word]>) -> crate::Result { - ::core::result::Result::Ok(builder.get_struct(::STRUCT_SIZE, default)?.into()) - } - } - - impl <> crate::traits::SetterInput> for Reader<'_,> { - fn set_pointer_builder(mut pointer: crate::private::layout::PointerBuilder<'_>, value: Self, canonicalize: bool) -> crate::Result<()> { pointer.set_struct(&value.reader, canonicalize) } - } - - impl <'a,> Builder<'a,> { - pub fn into_reader(self) -> Reader<'a,> { - self.builder.into_reader().into() - } - pub fn reborrow(&mut self) -> Builder<'_,> { - Builder { builder: self.builder.reborrow() } - } - pub fn reborrow_as_reader(&self) -> Reader<'_,> { - self.builder.as_reader().into() - } - - pub fn total_size(&self) -> crate::Result { - self.builder.as_reader().total_size() - } - #[inline] - pub fn set_null(&mut self, _value: ()) { - self.builder.set_data_field::(0, 0); - } - #[inline] - pub fn set_boolean(&mut self, value: bool) { - self.builder.set_data_field::(0, 1); - self.builder.set_bool_field(16, value); - } - #[inline] - pub fn set_number(&mut self, value: f64) { - self.builder.set_data_field::(0, 2); - self.builder.set_data_field::(1, value); - } - #[inline] - pub fn set_string(&mut self, value: impl crate::traits::SetterInput) { - self.builder.set_data_field::(0, 3); - crate::traits::SetterInput::set_pointer_builder(self.builder.reborrow().get_pointer_field(0), value, false).unwrap() - } - #[inline] - pub fn init_string(self, size: u32) -> crate::text::Builder<'a> { - self.builder.set_data_field::(0, 3); - self.builder.get_pointer_field(0).init_text(size) - } - #[inline] - pub fn has_string(&self) -> bool { - if self.builder.get_data_field::(0) != 3 { return false; } - !self.builder.is_pointer_field_null(0) - } - #[inline] - pub fn set_array(&mut self, value: crate::struct_list::Reader<'_,crate::json_capnp::value::Owned>) -> crate::Result<()> { - self.builder.set_data_field::(0, 4); - crate::traits::SetterInput::set_pointer_builder(self.builder.reborrow().get_pointer_field(0), value, false) - } - #[inline] - pub fn init_array(self, size: u32) -> crate::struct_list::Builder<'a,crate::json_capnp::value::Owned> { - self.builder.set_data_field::(0, 4); - crate::traits::FromPointerBuilder::init_pointer(self.builder.get_pointer_field(0), size) - } - #[inline] - pub fn has_array(&self) -> bool { - if self.builder.get_data_field::(0) != 4 { return false; } - !self.builder.is_pointer_field_null(0) - } - #[inline] - pub fn set_object(&mut self, value: crate::struct_list::Reader<'_,crate::json_capnp::value::field::Owned>) -> crate::Result<()> { - self.builder.set_data_field::(0, 5); - crate::traits::SetterInput::set_pointer_builder(self.builder.reborrow().get_pointer_field(0), value, false) - } - #[inline] - pub fn init_object(self, size: u32) -> crate::struct_list::Builder<'a,crate::json_capnp::value::field::Owned> { - self.builder.set_data_field::(0, 5); - crate::traits::FromPointerBuilder::init_pointer(self.builder.get_pointer_field(0), size) - } - #[inline] - pub fn has_object(&self) -> bool { - if self.builder.get_data_field::(0) != 5 { return false; } - !self.builder.is_pointer_field_null(0) - } - #[inline] - pub fn set_call(&mut self, value: crate::json_capnp::value::call::Reader<'_>) -> crate::Result<()> { - self.builder.set_data_field::(0, 6); - crate::traits::SetterInput::set_pointer_builder(self.builder.reborrow().get_pointer_field(0), value, false) - } - #[inline] - pub fn init_call(self, ) -> crate::json_capnp::value::call::Builder<'a> { - self.builder.set_data_field::(0, 6); - crate::traits::FromPointerBuilder::init_pointer(self.builder.get_pointer_field(0), 0) - } - #[inline] - pub fn has_call(&self) -> bool { - if self.builder.get_data_field::(0) != 6 { return false; } - !self.builder.is_pointer_field_null(0) - } - #[inline] - pub fn set_raw(&mut self, value: impl crate::traits::SetterInput) { - self.builder.set_data_field::(0, 7); - crate::traits::SetterInput::set_pointer_builder(self.builder.reborrow().get_pointer_field(0), value, false).unwrap() - } - #[inline] - pub fn init_raw(self, size: u32) -> crate::text::Builder<'a> { - self.builder.set_data_field::(0, 7); - self.builder.get_pointer_field(0).init_text(size) - } - #[inline] - pub fn has_raw(&self) -> bool { - if self.builder.get_data_field::(0) != 7 { return false; } - !self.builder.is_pointer_field_null(0) - } - #[inline] - pub fn which(self) -> ::core::result::Result, crate::NotInSchema> { - match self.builder.get_data_field::(0) { - 0 => { - ::core::result::Result::Ok(Null( - () - )) - } - 1 => { - ::core::result::Result::Ok(Boolean( - self.builder.get_bool_field(16) - )) - } - 2 => { - ::core::result::Result::Ok(Number( - self.builder.get_data_field::(1) - )) - } - 3 => { - ::core::result::Result::Ok(String( - crate::traits::FromPointerBuilder::get_from_pointer(self.builder.get_pointer_field(0), ::core::option::Option::None) - )) - } - 4 => { - ::core::result::Result::Ok(Array( - crate::traits::FromPointerBuilder::get_from_pointer(self.builder.get_pointer_field(0), ::core::option::Option::None) - )) - } - 5 => { - ::core::result::Result::Ok(Object( - crate::traits::FromPointerBuilder::get_from_pointer(self.builder.get_pointer_field(0), ::core::option::Option::None) - )) - } - 6 => { - ::core::result::Result::Ok(Call( - crate::traits::FromPointerBuilder::get_from_pointer(self.builder.get_pointer_field(0), ::core::option::Option::None) - )) - } - 7 => { - ::core::result::Result::Ok(Raw( - crate::traits::FromPointerBuilder::get_from_pointer(self.builder.get_pointer_field(0), ::core::option::Option::None) - )) - } - x => ::core::result::Result::Err(crate::NotInSchema(x)) - } - } - } - - pub struct Pipeline { _typeless: crate::any_pointer::Pipeline } - impl crate::capability::FromTypelessPipeline for Pipeline { - fn new(typeless: crate::any_pointer::Pipeline) -> Self { - Self { _typeless: typeless, } - } - } - impl Pipeline { - } - mod _private { - pub static ENCODED_NODE: [crate::Word; 152] = [ - crate::word(0, 0, 0, 0, 6, 0, 6, 0), - crate::word(131, 221, 25, 249, 69, 120, 250, 163), - crate::word(11, 0, 0, 0, 1, 0, 2, 0), - crate::word(52, 94, 58, 164, 151, 146, 249, 142), - crate::word(1, 0, 7, 0, 0, 0, 8, 0), - crate::word(0, 0, 0, 0, 0, 0, 0, 0), - crate::word(216, 4, 0, 0, 47, 11, 0, 0), - crate::word(21, 0, 0, 0, 138, 0, 0, 0), - crate::word(29, 0, 0, 0, 39, 0, 0, 0), - crate::word(0, 0, 0, 0, 0, 0, 0, 0), - crate::word(49, 0, 0, 0, 199, 1, 0, 0), - crate::word(0, 0, 0, 0, 0, 0, 0, 0), - crate::word(0, 0, 0, 0, 0, 0, 0, 0), - crate::word(106, 115, 111, 110, 46, 99, 97, 112), - crate::word(110, 112, 58, 86, 97, 108, 117, 101), - crate::word(0, 0, 0, 0, 0, 0, 0, 0), - crate::word(8, 0, 0, 0, 1, 0, 1, 0), - crate::word(223, 157, 214, 53, 231, 38, 16, 227), - crate::word(9, 0, 0, 0, 50, 0, 0, 0), - crate::word(72, 61, 201, 161, 236, 246, 217, 160), - crate::word(5, 0, 0, 0, 42, 0, 0, 0), - crate::word(70, 105, 101, 108, 100, 0, 0, 0), - crate::word(67, 97, 108, 108, 0, 0, 0, 0), - crate::word(32, 0, 0, 0, 3, 0, 4, 0), - crate::word(0, 0, 255, 255, 0, 0, 0, 0), - crate::word(0, 0, 1, 0, 0, 0, 0, 0), - crate::word(0, 0, 0, 0, 0, 0, 0, 0), - crate::word(209, 0, 0, 0, 42, 0, 0, 0), - crate::word(0, 0, 0, 0, 0, 0, 0, 0), - crate::word(204, 0, 0, 0, 3, 0, 1, 0), - crate::word(216, 0, 0, 0, 2, 0, 1, 0), - crate::word(1, 0, 254, 255, 16, 0, 0, 0), - crate::word(0, 0, 1, 0, 1, 0, 0, 0), - crate::word(0, 0, 0, 0, 0, 0, 0, 0), - crate::word(213, 0, 0, 0, 66, 0, 0, 0), - crate::word(0, 0, 0, 0, 0, 0, 0, 0), - crate::word(208, 0, 0, 0, 3, 0, 1, 0), - crate::word(220, 0, 0, 0, 2, 0, 1, 0), - crate::word(2, 0, 253, 255, 1, 0, 0, 0), - crate::word(0, 0, 1, 0, 2, 0, 0, 0), - crate::word(0, 0, 0, 0, 0, 0, 0, 0), - crate::word(217, 0, 0, 0, 58, 0, 0, 0), - crate::word(0, 0, 0, 0, 0, 0, 0, 0), - crate::word(212, 0, 0, 0, 3, 0, 1, 0), - crate::word(224, 0, 0, 0, 2, 0, 1, 0), - crate::word(3, 0, 252, 255, 0, 0, 0, 0), - crate::word(0, 0, 1, 0, 3, 0, 0, 0), - crate::word(0, 0, 0, 0, 0, 0, 0, 0), - crate::word(221, 0, 0, 0, 58, 0, 0, 0), - crate::word(0, 0, 0, 0, 0, 0, 0, 0), - crate::word(216, 0, 0, 0, 3, 0, 1, 0), - crate::word(228, 0, 0, 0, 2, 0, 1, 0), - crate::word(4, 0, 251, 255, 0, 0, 0, 0), - crate::word(0, 0, 1, 0, 4, 0, 0, 0), - crate::word(0, 0, 0, 0, 0, 0, 0, 0), - crate::word(225, 0, 0, 0, 50, 0, 0, 0), - crate::word(0, 0, 0, 0, 0, 0, 0, 0), - crate::word(220, 0, 0, 0, 3, 0, 1, 0), - crate::word(248, 0, 0, 0, 2, 0, 1, 0), - crate::word(5, 0, 250, 255, 0, 0, 0, 0), - crate::word(0, 0, 1, 0, 5, 0, 0, 0), - crate::word(0, 0, 0, 0, 0, 0, 0, 0), - crate::word(245, 0, 0, 0, 58, 0, 0, 0), - crate::word(0, 0, 0, 0, 0, 0, 0, 0), - crate::word(240, 0, 0, 0, 3, 0, 1, 0), - crate::word(12, 1, 0, 0, 2, 0, 1, 0), - crate::word(6, 0, 249, 255, 0, 0, 0, 0), - crate::word(0, 0, 1, 0, 6, 0, 0, 0), - crate::word(0, 0, 0, 0, 0, 0, 0, 0), - crate::word(9, 1, 0, 0, 42, 0, 0, 0), - crate::word(0, 0, 0, 0, 0, 0, 0, 0), - crate::word(4, 1, 0, 0, 3, 0, 1, 0), - crate::word(16, 1, 0, 0, 2, 0, 1, 0), - crate::word(7, 0, 248, 255, 0, 0, 0, 0), - crate::word(0, 0, 1, 0, 7, 0, 0, 0), - crate::word(0, 0, 0, 0, 0, 0, 0, 0), - crate::word(13, 1, 0, 0, 34, 0, 0, 0), - crate::word(0, 0, 0, 0, 0, 0, 0, 0), - crate::word(8, 1, 0, 0, 3, 0, 1, 0), - crate::word(20, 1, 0, 0, 2, 0, 1, 0), - crate::word(110, 117, 108, 108, 0, 0, 0, 0), - crate::word(0, 0, 0, 0, 0, 0, 0, 0), - crate::word(0, 0, 0, 0, 0, 0, 0, 0), - crate::word(0, 0, 0, 0, 0, 0, 0, 0), - crate::word(0, 0, 0, 0, 0, 0, 0, 0), - crate::word(0, 0, 0, 0, 0, 0, 0, 0), - crate::word(0, 0, 0, 0, 0, 0, 0, 0), - crate::word(0, 0, 0, 0, 0, 0, 0, 0), - crate::word(98, 111, 111, 108, 101, 97, 110, 0), - crate::word(1, 0, 0, 0, 0, 0, 0, 0), - crate::word(0, 0, 0, 0, 0, 0, 0, 0), - crate::word(0, 0, 0, 0, 0, 0, 0, 0), - crate::word(0, 0, 0, 0, 0, 0, 0, 0), - crate::word(1, 0, 0, 0, 0, 0, 0, 0), - crate::word(0, 0, 0, 0, 0, 0, 0, 0), - crate::word(0, 0, 0, 0, 0, 0, 0, 0), - crate::word(110, 117, 109, 98, 101, 114, 0, 0), - crate::word(11, 0, 0, 0, 0, 0, 0, 0), - crate::word(0, 0, 0, 0, 0, 0, 0, 0), - crate::word(0, 0, 0, 0, 0, 0, 0, 0), - crate::word(0, 0, 0, 0, 0, 0, 0, 0), - crate::word(11, 0, 0, 0, 0, 0, 0, 0), - crate::word(0, 0, 0, 0, 0, 0, 0, 0), - crate::word(0, 0, 0, 0, 0, 0, 0, 0), - crate::word(115, 116, 114, 105, 110, 103, 0, 0), - crate::word(12, 0, 0, 0, 0, 0, 0, 0), - crate::word(0, 0, 0, 0, 0, 0, 0, 0), - crate::word(0, 0, 0, 0, 0, 0, 0, 0), - crate::word(0, 0, 0, 0, 0, 0, 0, 0), - crate::word(12, 0, 0, 0, 0, 0, 0, 0), - crate::word(0, 0, 0, 0, 0, 0, 0, 0), - crate::word(0, 0, 0, 0, 0, 0, 0, 0), - crate::word(97, 114, 114, 97, 121, 0, 0, 0), - crate::word(14, 0, 0, 0, 0, 0, 0, 0), - crate::word(0, 0, 0, 0, 0, 0, 0, 0), - crate::word(0, 0, 0, 0, 0, 0, 0, 0), - crate::word(0, 0, 0, 0, 3, 0, 1, 0), - crate::word(16, 0, 0, 0, 0, 0, 0, 0), - crate::word(131, 221, 25, 249, 69, 120, 250, 163), - crate::word(0, 0, 0, 0, 0, 0, 0, 0), - crate::word(0, 0, 0, 0, 0, 0, 0, 0), - crate::word(14, 0, 0, 0, 0, 0, 0, 0), - crate::word(0, 0, 0, 0, 0, 0, 0, 0), - crate::word(0, 0, 0, 0, 0, 0, 0, 0), - crate::word(111, 98, 106, 101, 99, 116, 0, 0), - crate::word(14, 0, 0, 0, 0, 0, 0, 0), - crate::word(0, 0, 0, 0, 0, 0, 0, 0), - crate::word(0, 0, 0, 0, 0, 0, 0, 0), - crate::word(0, 0, 0, 0, 3, 0, 1, 0), - crate::word(16, 0, 0, 0, 0, 0, 0, 0), - crate::word(223, 157, 214, 53, 231, 38, 16, 227), - crate::word(0, 0, 0, 0, 0, 0, 0, 0), - crate::word(0, 0, 0, 0, 0, 0, 0, 0), - crate::word(14, 0, 0, 0, 0, 0, 0, 0), - crate::word(0, 0, 0, 0, 0, 0, 0, 0), - crate::word(0, 0, 0, 0, 0, 0, 0, 0), - crate::word(99, 97, 108, 108, 0, 0, 0, 0), - crate::word(16, 0, 0, 0, 0, 0, 0, 0), - crate::word(72, 61, 201, 161, 236, 246, 217, 160), - crate::word(0, 0, 0, 0, 0, 0, 0, 0), - crate::word(0, 0, 0, 0, 0, 0, 0, 0), - crate::word(16, 0, 0, 0, 0, 0, 0, 0), - crate::word(0, 0, 0, 0, 0, 0, 0, 0), - crate::word(0, 0, 0, 0, 0, 0, 0, 0), - crate::word(114, 97, 119, 0, 0, 0, 0, 0), - crate::word(12, 0, 0, 0, 0, 0, 0, 0), - crate::word(0, 0, 0, 0, 0, 0, 0, 0), - crate::word(0, 0, 0, 0, 0, 0, 0, 0), - crate::word(0, 0, 0, 0, 0, 0, 0, 0), - crate::word(12, 0, 0, 0, 0, 0, 0, 0), - crate::word(0, 0, 0, 0, 0, 0, 0, 0), - crate::word(0, 0, 0, 0, 0, 0, 0, 0), - ]; - pub fn get_field_types(index: u16) -> crate::introspect::Type { - match index { - 0 => <() as crate::introspect::Introspect>::introspect(), - 1 => ::introspect(), - 2 => ::introspect(), - 3 => ::introspect(), - 4 => as crate::introspect::Introspect>::introspect(), - 5 => as crate::introspect::Introspect>::introspect(), - 6 => ::introspect(), - 7 => ::introspect(), - _ => crate::introspect::panic_invalid_field_index(index), - } - } - pub fn get_annotation_types(child_index: Option, index: u32) -> crate::introspect::Type { - crate::introspect::panic_invalid_annotation_indices(child_index, index) - } - pub static RAW_SCHEMA: crate::introspect::RawStructSchema = crate::introspect::RawStructSchema { - encoded_node: &ENCODED_NODE, - nonunion_members: NONUNION_MEMBERS, - members_by_discriminant: MEMBERS_BY_DISCRIMINANT, - members_by_name: MEMBERS_BY_NAME, - }; - pub static NONUNION_MEMBERS : &[u16] = &[]; - pub static MEMBERS_BY_DISCRIMINANT : &[u16] = &[0,1,2,3,4,5,6,7]; - pub static MEMBERS_BY_NAME : &[u16] = &[4,1,6,0,2,5,7,3]; - pub const TYPE_ID: u64 = 0xa3fa_7845_f919_dd83; - } - pub enum Which { - Null(()), - Boolean(bool), - Number(f64), - String(A0), - Array(A1), - Object(A2), - Call(A3), - Raw(A4), - } - pub type WhichReader<'a,> = Which>,crate::Result>,crate::Result>,crate::Result>,crate::Result>>; - pub type WhichBuilder<'a,> = Which>,crate::Result>,crate::Result>,crate::Result>,crate::Result>>; - - pub mod field { - #[derive(Copy, Clone)] - pub struct Owned(()); - impl crate::introspect::Introspect for Owned { fn introspect() -> crate::introspect::Type { crate::introspect::TypeVariant::Struct(crate::introspect::RawBrandedStructSchema { generic: &_private::RAW_SCHEMA, field_types: _private::get_field_types, annotation_types: _private::get_annotation_types }).into() } } - impl crate::traits::Owned for Owned { type Reader<'a> = Reader<'a>; type Builder<'a> = Builder<'a>; } - impl crate::traits::OwnedStruct for Owned { type Reader<'a> = Reader<'a>; type Builder<'a> = Builder<'a>; } - impl crate::traits::Pipelined for Owned { type Pipeline = Pipeline; } - - pub struct Reader<'a> { reader: crate::private::layout::StructReader<'a> } - impl <> ::core::marker::Copy for Reader<'_,> {} - impl <> ::core::clone::Clone for Reader<'_,> { - fn clone(&self) -> Self { *self } - } - - impl <> crate::traits::HasTypeId for Reader<'_,> { - const TYPE_ID: u64 = _private::TYPE_ID; - } - impl <'a,> ::core::convert::From> for Reader<'a,> { - fn from(reader: crate::private::layout::StructReader<'a>) -> Self { - Self { reader, } - } - } - - impl <'a,> ::core::convert::From> for crate::dynamic_value::Reader<'a> { - fn from(reader: Reader<'a,>) -> Self { - Self::Struct(crate::dynamic_struct::Reader::new(reader.reader, crate::schema::StructSchema::new(crate::introspect::RawBrandedStructSchema { generic: &_private::RAW_SCHEMA, field_types: _private::get_field_types::<>, annotation_types: _private::get_annotation_types::<>}))) - } - } - - impl <> ::core::fmt::Debug for Reader<'_,> { - fn fmt(&self, f: &mut ::core::fmt::Formatter<'_>) -> ::core::result::Result<(), ::core::fmt::Error> { - core::fmt::Debug::fmt(&::core::convert::Into::>::into(*self), f) - } - } - - impl <'a,> crate::traits::FromPointerReader<'a> for Reader<'a,> { - fn get_from_pointer(reader: &crate::private::layout::PointerReader<'a>, default: ::core::option::Option<&'a [crate::Word]>) -> crate::Result { - ::core::result::Result::Ok(reader.get_struct(default)?.into()) - } - } - - impl <'a,> crate::traits::IntoInternalStructReader<'a> for Reader<'a,> { - fn into_internal_struct_reader(self) -> crate::private::layout::StructReader<'a> { - self.reader - } - } - - impl <'a,> crate::traits::Imbue<'a> for Reader<'a,> { - fn imbue(&mut self, cap_table: &'a crate::private::layout::CapTable) { - self.reader.imbue(crate::private::layout::CapTableReader::Plain(cap_table)) - } - } - - impl <'a,> Reader<'a,> { - pub fn reborrow(&self) -> Reader<'_,> { - Self { .. *self } - } - - pub fn total_size(&self) -> crate::Result { - self.reader.total_size() - } - #[inline] - pub fn get_name(self) -> crate::Result> { - crate::traits::FromPointerReader::get_from_pointer(&self.reader.get_pointer_field(0), ::core::option::Option::None) - } - #[inline] - pub fn has_name(&self) -> bool { - !self.reader.get_pointer_field(0).is_null() - } - #[inline] - pub fn get_value(self) -> crate::Result> { - crate::traits::FromPointerReader::get_from_pointer(&self.reader.get_pointer_field(1), ::core::option::Option::None) - } - #[inline] - pub fn has_value(&self) -> bool { - !self.reader.get_pointer_field(1).is_null() - } - } - - pub struct Builder<'a> { builder: crate::private::layout::StructBuilder<'a> } - impl <> crate::traits::HasStructSize for Builder<'_,> { - const STRUCT_SIZE: crate::private::layout::StructSize = crate::private::layout::StructSize { data: 0, pointers: 2 }; - } - impl <> crate::traits::HasTypeId for Builder<'_,> { - const TYPE_ID: u64 = _private::TYPE_ID; - } - impl <'a,> ::core::convert::From> for Builder<'a,> { - fn from(builder: crate::private::layout::StructBuilder<'a>) -> Self { - Self { builder, } - } - } - - impl <'a,> ::core::convert::From> for crate::dynamic_value::Builder<'a> { - fn from(builder: Builder<'a,>) -> Self { - Self::Struct(crate::dynamic_struct::Builder::new(builder.builder, crate::schema::StructSchema::new(crate::introspect::RawBrandedStructSchema { generic: &_private::RAW_SCHEMA, field_types: _private::get_field_types::<>, annotation_types: _private::get_annotation_types::<>}))) - } - } - - impl <'a,> crate::traits::ImbueMut<'a> for Builder<'a,> { - fn imbue_mut(&mut self, cap_table: &'a mut crate::private::layout::CapTable) { - self.builder.imbue(crate::private::layout::CapTableBuilder::Plain(cap_table)) - } - } - - impl <'a,> crate::traits::FromPointerBuilder<'a> for Builder<'a,> { - fn init_pointer(builder: crate::private::layout::PointerBuilder<'a>, _size: u32) -> Self { - builder.init_struct(::STRUCT_SIZE).into() - } - fn get_from_pointer(builder: crate::private::layout::PointerBuilder<'a>, default: ::core::option::Option<&'a [crate::Word]>) -> crate::Result { - ::core::result::Result::Ok(builder.get_struct(::STRUCT_SIZE, default)?.into()) - } - } - - impl <> crate::traits::SetterInput> for Reader<'_,> { - fn set_pointer_builder(mut pointer: crate::private::layout::PointerBuilder<'_>, value: Self, canonicalize: bool) -> crate::Result<()> { pointer.set_struct(&value.reader, canonicalize) } - } - - impl <'a,> Builder<'a,> { - pub fn into_reader(self) -> Reader<'a,> { - self.builder.into_reader().into() - } - pub fn reborrow(&mut self) -> Builder<'_,> { - Builder { builder: self.builder.reborrow() } - } - pub fn reborrow_as_reader(&self) -> Reader<'_,> { - self.builder.as_reader().into() - } - - pub fn total_size(&self) -> crate::Result { - self.builder.as_reader().total_size() - } - #[inline] - pub fn get_name(self) -> crate::Result> { - crate::traits::FromPointerBuilder::get_from_pointer(self.builder.get_pointer_field(0), ::core::option::Option::None) - } - #[inline] - pub fn set_name(&mut self, value: impl crate::traits::SetterInput) { - crate::traits::SetterInput::set_pointer_builder(self.builder.reborrow().get_pointer_field(0), value, false).unwrap() - } - #[inline] - pub fn init_name(self, size: u32) -> crate::text::Builder<'a> { - self.builder.get_pointer_field(0).init_text(size) - } - #[inline] - pub fn has_name(&self) -> bool { - !self.builder.is_pointer_field_null(0) - } - #[inline] - pub fn get_value(self) -> crate::Result> { - crate::traits::FromPointerBuilder::get_from_pointer(self.builder.get_pointer_field(1), ::core::option::Option::None) - } - #[inline] - pub fn set_value(&mut self, value: crate::json_capnp::value::Reader<'_>) -> crate::Result<()> { - crate::traits::SetterInput::set_pointer_builder(self.builder.reborrow().get_pointer_field(1), value, false) - } - #[inline] - pub fn init_value(self, ) -> crate::json_capnp::value::Builder<'a> { - crate::traits::FromPointerBuilder::init_pointer(self.builder.get_pointer_field(1), 0) - } - #[inline] - pub fn has_value(&self) -> bool { - !self.builder.is_pointer_field_null(1) - } - } - - pub struct Pipeline { _typeless: crate::any_pointer::Pipeline } - impl crate::capability::FromTypelessPipeline for Pipeline { - fn new(typeless: crate::any_pointer::Pipeline) -> Self { - Self { _typeless: typeless, } - } - } - impl Pipeline { - pub fn get_value(&self) -> crate::json_capnp::value::Pipeline { - crate::capability::FromTypelessPipeline::new(self._typeless.get_pointer_field(1)) - } - } - mod _private { - pub static ENCODED_NODE: [crate::Word; 48] = [ - crate::word(0, 0, 0, 0, 6, 0, 6, 0), - crate::word(223, 157, 214, 53, 231, 38, 16, 227), - crate::word(17, 0, 0, 0, 1, 0, 0, 0), - crate::word(131, 221, 25, 249, 69, 120, 250, 163), - crate::word(2, 0, 7, 0, 0, 0, 0, 0), - crate::word(0, 0, 0, 0, 0, 0, 0, 0), - crate::word(171, 10, 0, 0, 229, 10, 0, 0), - crate::word(21, 0, 0, 0, 186, 0, 0, 0), - crate::word(29, 0, 0, 0, 7, 0, 0, 0), - crate::word(0, 0, 0, 0, 0, 0, 0, 0), - crate::word(25, 0, 0, 0, 119, 0, 0, 0), - crate::word(0, 0, 0, 0, 0, 0, 0, 0), - crate::word(0, 0, 0, 0, 0, 0, 0, 0), - crate::word(106, 115, 111, 110, 46, 99, 97, 112), - crate::word(110, 112, 58, 86, 97, 108, 117, 101), - crate::word(46, 70, 105, 101, 108, 100, 0, 0), - crate::word(0, 0, 0, 0, 1, 0, 1, 0), - crate::word(8, 0, 0, 0, 3, 0, 4, 0), - crate::word(0, 0, 0, 0, 0, 0, 0, 0), - crate::word(0, 0, 1, 0, 0, 0, 0, 0), - crate::word(0, 0, 0, 0, 0, 0, 0, 0), - crate::word(41, 0, 0, 0, 42, 0, 0, 0), - crate::word(0, 0, 0, 0, 0, 0, 0, 0), - crate::word(36, 0, 0, 0, 3, 0, 1, 0), - crate::word(48, 0, 0, 0, 2, 0, 1, 0), - crate::word(1, 0, 0, 0, 1, 0, 0, 0), - crate::word(0, 0, 1, 0, 1, 0, 0, 0), - crate::word(0, 0, 0, 0, 0, 0, 0, 0), - crate::word(45, 0, 0, 0, 50, 0, 0, 0), - crate::word(0, 0, 0, 0, 0, 0, 0, 0), - crate::word(40, 0, 0, 0, 3, 0, 1, 0), - crate::word(52, 0, 0, 0, 2, 0, 1, 0), - crate::word(110, 97, 109, 101, 0, 0, 0, 0), - crate::word(12, 0, 0, 0, 0, 0, 0, 0), - crate::word(0, 0, 0, 0, 0, 0, 0, 0), - crate::word(0, 0, 0, 0, 0, 0, 0, 0), - crate::word(0, 0, 0, 0, 0, 0, 0, 0), - crate::word(12, 0, 0, 0, 0, 0, 0, 0), - crate::word(0, 0, 0, 0, 0, 0, 0, 0), - crate::word(0, 0, 0, 0, 0, 0, 0, 0), - crate::word(118, 97, 108, 117, 101, 0, 0, 0), - crate::word(16, 0, 0, 0, 0, 0, 0, 0), - crate::word(131, 221, 25, 249, 69, 120, 250, 163), - crate::word(0, 0, 0, 0, 0, 0, 0, 0), - crate::word(0, 0, 0, 0, 0, 0, 0, 0), - crate::word(16, 0, 0, 0, 0, 0, 0, 0), - crate::word(0, 0, 0, 0, 0, 0, 0, 0), - crate::word(0, 0, 0, 0, 0, 0, 0, 0), - ]; - pub fn get_field_types(index: u16) -> crate::introspect::Type { - match index { - 0 => ::introspect(), - 1 => ::introspect(), - _ => crate::introspect::panic_invalid_field_index(index), - } - } - pub fn get_annotation_types(child_index: Option, index: u32) -> crate::introspect::Type { - crate::introspect::panic_invalid_annotation_indices(child_index, index) - } - pub static RAW_SCHEMA: crate::introspect::RawStructSchema = crate::introspect::RawStructSchema { - encoded_node: &ENCODED_NODE, - nonunion_members: NONUNION_MEMBERS, - members_by_discriminant: MEMBERS_BY_DISCRIMINANT, - members_by_name: MEMBERS_BY_NAME, - }; - pub static NONUNION_MEMBERS : &[u16] = &[0,1]; - pub static MEMBERS_BY_DISCRIMINANT : &[u16] = &[]; - pub static MEMBERS_BY_NAME : &[u16] = &[0,1]; - pub const TYPE_ID: u64 = 0xe310_26e7_35d6_9ddf; - } - } - - pub mod call { - #[derive(Copy, Clone)] - pub struct Owned(()); - impl crate::introspect::Introspect for Owned { fn introspect() -> crate::introspect::Type { crate::introspect::TypeVariant::Struct(crate::introspect::RawBrandedStructSchema { generic: &_private::RAW_SCHEMA, field_types: _private::get_field_types, annotation_types: _private::get_annotation_types }).into() } } - impl crate::traits::Owned for Owned { type Reader<'a> = Reader<'a>; type Builder<'a> = Builder<'a>; } - impl crate::traits::OwnedStruct for Owned { type Reader<'a> = Reader<'a>; type Builder<'a> = Builder<'a>; } - impl crate::traits::Pipelined for Owned { type Pipeline = Pipeline; } - - pub struct Reader<'a> { reader: crate::private::layout::StructReader<'a> } - impl <> ::core::marker::Copy for Reader<'_,> {} - impl <> ::core::clone::Clone for Reader<'_,> { - fn clone(&self) -> Self { *self } - } - - impl <> crate::traits::HasTypeId for Reader<'_,> { - const TYPE_ID: u64 = _private::TYPE_ID; - } - impl <'a,> ::core::convert::From> for Reader<'a,> { - fn from(reader: crate::private::layout::StructReader<'a>) -> Self { - Self { reader, } - } - } - - impl <'a,> ::core::convert::From> for crate::dynamic_value::Reader<'a> { - fn from(reader: Reader<'a,>) -> Self { - Self::Struct(crate::dynamic_struct::Reader::new(reader.reader, crate::schema::StructSchema::new(crate::introspect::RawBrandedStructSchema { generic: &_private::RAW_SCHEMA, field_types: _private::get_field_types::<>, annotation_types: _private::get_annotation_types::<>}))) - } - } - - impl <> ::core::fmt::Debug for Reader<'_,> { - fn fmt(&self, f: &mut ::core::fmt::Formatter<'_>) -> ::core::result::Result<(), ::core::fmt::Error> { - core::fmt::Debug::fmt(&::core::convert::Into::>::into(*self), f) - } - } - - impl <'a,> crate::traits::FromPointerReader<'a> for Reader<'a,> { - fn get_from_pointer(reader: &crate::private::layout::PointerReader<'a>, default: ::core::option::Option<&'a [crate::Word]>) -> crate::Result { - ::core::result::Result::Ok(reader.get_struct(default)?.into()) - } - } - - impl <'a,> crate::traits::IntoInternalStructReader<'a> for Reader<'a,> { - fn into_internal_struct_reader(self) -> crate::private::layout::StructReader<'a> { - self.reader - } - } - - impl <'a,> crate::traits::Imbue<'a> for Reader<'a,> { - fn imbue(&mut self, cap_table: &'a crate::private::layout::CapTable) { - self.reader.imbue(crate::private::layout::CapTableReader::Plain(cap_table)) - } - } - - impl <'a,> Reader<'a,> { - pub fn reborrow(&self) -> Reader<'_,> { - Self { .. *self } - } - - pub fn total_size(&self) -> crate::Result { - self.reader.total_size() - } - #[inline] - pub fn get_function(self) -> crate::Result> { - crate::traits::FromPointerReader::get_from_pointer(&self.reader.get_pointer_field(0), ::core::option::Option::None) - } - #[inline] - pub fn has_function(&self) -> bool { - !self.reader.get_pointer_field(0).is_null() - } - #[inline] - pub fn get_params(self) -> crate::Result> { - crate::traits::FromPointerReader::get_from_pointer(&self.reader.get_pointer_field(1), ::core::option::Option::None) - } - #[inline] - pub fn has_params(&self) -> bool { - !self.reader.get_pointer_field(1).is_null() - } - } - - pub struct Builder<'a> { builder: crate::private::layout::StructBuilder<'a> } - impl <> crate::traits::HasStructSize for Builder<'_,> { - const STRUCT_SIZE: crate::private::layout::StructSize = crate::private::layout::StructSize { data: 0, pointers: 2 }; - } - impl <> crate::traits::HasTypeId for Builder<'_,> { - const TYPE_ID: u64 = _private::TYPE_ID; - } - impl <'a,> ::core::convert::From> for Builder<'a,> { - fn from(builder: crate::private::layout::StructBuilder<'a>) -> Self { - Self { builder, } - } - } - - impl <'a,> ::core::convert::From> for crate::dynamic_value::Builder<'a> { - fn from(builder: Builder<'a,>) -> Self { - Self::Struct(crate::dynamic_struct::Builder::new(builder.builder, crate::schema::StructSchema::new(crate::introspect::RawBrandedStructSchema { generic: &_private::RAW_SCHEMA, field_types: _private::get_field_types::<>, annotation_types: _private::get_annotation_types::<>}))) - } - } - - impl <'a,> crate::traits::ImbueMut<'a> for Builder<'a,> { - fn imbue_mut(&mut self, cap_table: &'a mut crate::private::layout::CapTable) { - self.builder.imbue(crate::private::layout::CapTableBuilder::Plain(cap_table)) - } - } - - impl <'a,> crate::traits::FromPointerBuilder<'a> for Builder<'a,> { - fn init_pointer(builder: crate::private::layout::PointerBuilder<'a>, _size: u32) -> Self { - builder.init_struct(::STRUCT_SIZE).into() - } - fn get_from_pointer(builder: crate::private::layout::PointerBuilder<'a>, default: ::core::option::Option<&'a [crate::Word]>) -> crate::Result { - ::core::result::Result::Ok(builder.get_struct(::STRUCT_SIZE, default)?.into()) - } - } - - impl <> crate::traits::SetterInput> for Reader<'_,> { - fn set_pointer_builder(mut pointer: crate::private::layout::PointerBuilder<'_>, value: Self, canonicalize: bool) -> crate::Result<()> { pointer.set_struct(&value.reader, canonicalize) } - } - - impl <'a,> Builder<'a,> { - pub fn into_reader(self) -> Reader<'a,> { - self.builder.into_reader().into() - } - pub fn reborrow(&mut self) -> Builder<'_,> { - Builder { builder: self.builder.reborrow() } - } - pub fn reborrow_as_reader(&self) -> Reader<'_,> { - self.builder.as_reader().into() - } - - pub fn total_size(&self) -> crate::Result { - self.builder.as_reader().total_size() - } - #[inline] - pub fn get_function(self) -> crate::Result> { - crate::traits::FromPointerBuilder::get_from_pointer(self.builder.get_pointer_field(0), ::core::option::Option::None) - } - #[inline] - pub fn set_function(&mut self, value: impl crate::traits::SetterInput) { - crate::traits::SetterInput::set_pointer_builder(self.builder.reborrow().get_pointer_field(0), value, false).unwrap() - } - #[inline] - pub fn init_function(self, size: u32) -> crate::text::Builder<'a> { - self.builder.get_pointer_field(0).init_text(size) - } - #[inline] - pub fn has_function(&self) -> bool { - !self.builder.is_pointer_field_null(0) - } - #[inline] - pub fn get_params(self) -> crate::Result> { - crate::traits::FromPointerBuilder::get_from_pointer(self.builder.get_pointer_field(1), ::core::option::Option::None) - } - #[inline] - pub fn set_params(&mut self, value: crate::struct_list::Reader<'_,crate::json_capnp::value::Owned>) -> crate::Result<()> { - crate::traits::SetterInput::set_pointer_builder(self.builder.reborrow().get_pointer_field(1), value, false) - } - #[inline] - pub fn init_params(self, size: u32) -> crate::struct_list::Builder<'a,crate::json_capnp::value::Owned> { - crate::traits::FromPointerBuilder::init_pointer(self.builder.get_pointer_field(1), size) - } - #[inline] - pub fn has_params(&self) -> bool { - !self.builder.is_pointer_field_null(1) - } - } - - pub struct Pipeline { _typeless: crate::any_pointer::Pipeline } - impl crate::capability::FromTypelessPipeline for Pipeline { - fn new(typeless: crate::any_pointer::Pipeline) -> Self { - Self { _typeless: typeless, } - } - } - impl Pipeline { - } - mod _private { - pub static ENCODED_NODE: [crate::Word; 53] = [ - crate::word(0, 0, 0, 0, 6, 0, 6, 0), - crate::word(72, 61, 201, 161, 236, 246, 217, 160), - crate::word(17, 0, 0, 0, 1, 0, 0, 0), - crate::word(131, 221, 25, 249, 69, 120, 250, 163), - crate::word(2, 0, 7, 0, 0, 0, 0, 0), - crate::word(0, 0, 0, 0, 0, 0, 0, 0), - crate::word(233, 10, 0, 0, 45, 11, 0, 0), - crate::word(21, 0, 0, 0, 178, 0, 0, 0), - crate::word(29, 0, 0, 0, 7, 0, 0, 0), - crate::word(0, 0, 0, 0, 0, 0, 0, 0), - crate::word(25, 0, 0, 0, 119, 0, 0, 0), - crate::word(0, 0, 0, 0, 0, 0, 0, 0), - crate::word(0, 0, 0, 0, 0, 0, 0, 0), - crate::word(106, 115, 111, 110, 46, 99, 97, 112), - crate::word(110, 112, 58, 86, 97, 108, 117, 101), - crate::word(46, 67, 97, 108, 108, 0, 0, 0), - crate::word(0, 0, 0, 0, 1, 0, 1, 0), - crate::word(8, 0, 0, 0, 3, 0, 4, 0), - crate::word(0, 0, 0, 0, 0, 0, 0, 0), - crate::word(0, 0, 1, 0, 0, 0, 0, 0), - crate::word(0, 0, 0, 0, 0, 0, 0, 0), - crate::word(41, 0, 0, 0, 74, 0, 0, 0), - crate::word(0, 0, 0, 0, 0, 0, 0, 0), - crate::word(40, 0, 0, 0, 3, 0, 1, 0), - crate::word(52, 0, 0, 0, 2, 0, 1, 0), - crate::word(1, 0, 0, 0, 1, 0, 0, 0), - crate::word(0, 0, 1, 0, 1, 0, 0, 0), - crate::word(0, 0, 0, 0, 0, 0, 0, 0), - crate::word(49, 0, 0, 0, 58, 0, 0, 0), - crate::word(0, 0, 0, 0, 0, 0, 0, 0), - crate::word(44, 0, 0, 0, 3, 0, 1, 0), - crate::word(72, 0, 0, 0, 2, 0, 1, 0), - crate::word(102, 117, 110, 99, 116, 105, 111, 110), - crate::word(0, 0, 0, 0, 0, 0, 0, 0), - crate::word(12, 0, 0, 0, 0, 0, 0, 0), - crate::word(0, 0, 0, 0, 0, 0, 0, 0), - crate::word(0, 0, 0, 0, 0, 0, 0, 0), - crate::word(0, 0, 0, 0, 0, 0, 0, 0), - crate::word(12, 0, 0, 0, 0, 0, 0, 0), - crate::word(0, 0, 0, 0, 0, 0, 0, 0), - crate::word(0, 0, 0, 0, 0, 0, 0, 0), - crate::word(112, 97, 114, 97, 109, 115, 0, 0), - crate::word(14, 0, 0, 0, 0, 0, 0, 0), - crate::word(0, 0, 0, 0, 0, 0, 0, 0), - crate::word(0, 0, 0, 0, 0, 0, 0, 0), - crate::word(0, 0, 0, 0, 3, 0, 1, 0), - crate::word(16, 0, 0, 0, 0, 0, 0, 0), - crate::word(131, 221, 25, 249, 69, 120, 250, 163), - crate::word(0, 0, 0, 0, 0, 0, 0, 0), - crate::word(0, 0, 0, 0, 0, 0, 0, 0), - crate::word(14, 0, 0, 0, 0, 0, 0, 0), - crate::word(0, 0, 0, 0, 0, 0, 0, 0), - crate::word(0, 0, 0, 0, 0, 0, 0, 0), - ]; - pub fn get_field_types(index: u16) -> crate::introspect::Type { - match index { - 0 => ::introspect(), - 1 => as crate::introspect::Introspect>::introspect(), - _ => crate::introspect::panic_invalid_field_index(index), - } - } - pub fn get_annotation_types(child_index: Option, index: u32) -> crate::introspect::Type { - crate::introspect::panic_invalid_annotation_indices(child_index, index) - } - pub static RAW_SCHEMA: crate::introspect::RawStructSchema = crate::introspect::RawStructSchema { - encoded_node: &ENCODED_NODE, - nonunion_members: NONUNION_MEMBERS, - members_by_discriminant: MEMBERS_BY_DISCRIMINANT, - members_by_name: MEMBERS_BY_NAME, - }; - pub static NONUNION_MEMBERS : &[u16] = &[0,1]; - pub static MEMBERS_BY_DISCRIMINANT : &[u16] = &[]; - pub static MEMBERS_BY_NAME : &[u16] = &[0,1]; - pub const TYPE_ID: u64 = 0xa0d9_f6ec_a1c9_3d48; - } - } -} -pub mod name { - pub const ID: u64 = 0xfa5b1fd61c2e7c3d; - pub fn get_type() -> crate::introspect::Type { ::introspect() } -} -pub mod flatten { - pub const ID: u64 = 0x82d3e852af0336bf; - pub fn get_type() -> crate::introspect::Type { ::introspect() } -} - -pub mod flatten_options { - #[derive(Copy, Clone)] - pub struct Owned(()); - impl crate::introspect::Introspect for Owned { fn introspect() -> crate::introspect::Type { crate::introspect::TypeVariant::Struct(crate::introspect::RawBrandedStructSchema { generic: &_private::RAW_SCHEMA, field_types: _private::get_field_types, annotation_types: _private::get_annotation_types }).into() } } - impl crate::traits::Owned for Owned { type Reader<'a> = Reader<'a>; type Builder<'a> = Builder<'a>; } - impl crate::traits::OwnedStruct for Owned { type Reader<'a> = Reader<'a>; type Builder<'a> = Builder<'a>; } - impl crate::traits::Pipelined for Owned { type Pipeline = Pipeline; } - - pub struct Reader<'a> { reader: crate::private::layout::StructReader<'a> } - impl <> ::core::marker::Copy for Reader<'_,> {} - impl <> ::core::clone::Clone for Reader<'_,> { - fn clone(&self) -> Self { *self } - } - - impl <> crate::traits::HasTypeId for Reader<'_,> { - const TYPE_ID: u64 = _private::TYPE_ID; - } - impl <'a,> ::core::convert::From> for Reader<'a,> { - fn from(reader: crate::private::layout::StructReader<'a>) -> Self { - Self { reader, } - } - } - - impl <'a,> ::core::convert::From> for crate::dynamic_value::Reader<'a> { - fn from(reader: Reader<'a,>) -> Self { - Self::Struct(crate::dynamic_struct::Reader::new(reader.reader, crate::schema::StructSchema::new(crate::introspect::RawBrandedStructSchema { generic: &_private::RAW_SCHEMA, field_types: _private::get_field_types::<>, annotation_types: _private::get_annotation_types::<>}))) - } - } - - impl <> ::core::fmt::Debug for Reader<'_,> { - fn fmt(&self, f: &mut ::core::fmt::Formatter<'_>) -> ::core::result::Result<(), ::core::fmt::Error> { - core::fmt::Debug::fmt(&::core::convert::Into::>::into(*self), f) - } - } - - impl <'a,> crate::traits::FromPointerReader<'a> for Reader<'a,> { - fn get_from_pointer(reader: &crate::private::layout::PointerReader<'a>, default: ::core::option::Option<&'a [crate::Word]>) -> crate::Result { - ::core::result::Result::Ok(reader.get_struct(default)?.into()) - } - } - - impl <'a,> crate::traits::IntoInternalStructReader<'a> for Reader<'a,> { - fn into_internal_struct_reader(self) -> crate::private::layout::StructReader<'a> { - self.reader - } - } - - impl <'a,> crate::traits::Imbue<'a> for Reader<'a,> { - fn imbue(&mut self, cap_table: &'a crate::private::layout::CapTable) { - self.reader.imbue(crate::private::layout::CapTableReader::Plain(cap_table)) - } - } - - impl <'a,> Reader<'a,> { - pub fn reborrow(&self) -> Reader<'_,> { - Self { .. *self } - } - - pub fn total_size(&self) -> crate::Result { - self.reader.total_size() - } - #[inline] - pub fn get_prefix(self) -> crate::Result> { - crate::traits::FromPointerReader::get_from_pointer(&self.reader.get_pointer_field(0), ::core::option::Option::Some(&_private::DEFAULT_PREFIX[..])) - } - #[inline] - pub fn has_prefix(&self) -> bool { - !self.reader.get_pointer_field(0).is_null() - } - } - - pub struct Builder<'a> { builder: crate::private::layout::StructBuilder<'a> } - impl <> crate::traits::HasStructSize for Builder<'_,> { - const STRUCT_SIZE: crate::private::layout::StructSize = crate::private::layout::StructSize { data: 0, pointers: 1 }; - } - impl <> crate::traits::HasTypeId for Builder<'_,> { - const TYPE_ID: u64 = _private::TYPE_ID; - } - impl <'a,> ::core::convert::From> for Builder<'a,> { - fn from(builder: crate::private::layout::StructBuilder<'a>) -> Self { - Self { builder, } - } - } - - impl <'a,> ::core::convert::From> for crate::dynamic_value::Builder<'a> { - fn from(builder: Builder<'a,>) -> Self { - Self::Struct(crate::dynamic_struct::Builder::new(builder.builder, crate::schema::StructSchema::new(crate::introspect::RawBrandedStructSchema { generic: &_private::RAW_SCHEMA, field_types: _private::get_field_types::<>, annotation_types: _private::get_annotation_types::<>}))) - } - } - - impl <'a,> crate::traits::ImbueMut<'a> for Builder<'a,> { - fn imbue_mut(&mut self, cap_table: &'a mut crate::private::layout::CapTable) { - self.builder.imbue(crate::private::layout::CapTableBuilder::Plain(cap_table)) - } - } - - impl <'a,> crate::traits::FromPointerBuilder<'a> for Builder<'a,> { - fn init_pointer(builder: crate::private::layout::PointerBuilder<'a>, _size: u32) -> Self { - builder.init_struct(::STRUCT_SIZE).into() - } - fn get_from_pointer(builder: crate::private::layout::PointerBuilder<'a>, default: ::core::option::Option<&'a [crate::Word]>) -> crate::Result { - ::core::result::Result::Ok(builder.get_struct(::STRUCT_SIZE, default)?.into()) - } - } - - impl <> crate::traits::SetterInput> for Reader<'_,> { - fn set_pointer_builder(mut pointer: crate::private::layout::PointerBuilder<'_>, value: Self, canonicalize: bool) -> crate::Result<()> { pointer.set_struct(&value.reader, canonicalize) } - } - - impl <'a,> Builder<'a,> { - pub fn into_reader(self) -> Reader<'a,> { - self.builder.into_reader().into() - } - pub fn reborrow(&mut self) -> Builder<'_,> { - Builder { builder: self.builder.reborrow() } - } - pub fn reborrow_as_reader(&self) -> Reader<'_,> { - self.builder.as_reader().into() - } - - pub fn total_size(&self) -> crate::Result { - self.builder.as_reader().total_size() - } - #[inline] - pub fn get_prefix(self) -> crate::Result> { - crate::traits::FromPointerBuilder::get_from_pointer(self.builder.get_pointer_field(0), ::core::option::Option::Some(&_private::DEFAULT_PREFIX[..])) - } - #[inline] - pub fn set_prefix(&mut self, value: impl crate::traits::SetterInput) { - crate::traits::SetterInput::set_pointer_builder(self.builder.reborrow().get_pointer_field(0), value, false).unwrap() - } - #[inline] - pub fn init_prefix(self, size: u32) -> crate::text::Builder<'a> { - self.builder.get_pointer_field(0).init_text(size) - } - #[inline] - pub fn has_prefix(&self) -> bool { - !self.builder.is_pointer_field_null(0) - } - } - - pub struct Pipeline { _typeless: crate::any_pointer::Pipeline } - impl crate::capability::FromTypelessPipeline for Pipeline { - fn new(typeless: crate::any_pointer::Pipeline) -> Self { - Self { _typeless: typeless, } - } - } - impl Pipeline { - } - mod _private { - pub static ENCODED_NODE: [crate::Word; 35] = [ - crate::word(0, 0, 0, 0, 6, 0, 6, 0), - crate::word(97, 234, 194, 123, 37, 19, 223, 196), - crate::word(11, 0, 0, 0, 1, 0, 0, 0), - crate::word(52, 94, 58, 164, 151, 146, 249, 142), - crate::word(1, 0, 7, 0, 0, 0, 0, 0), - crate::word(0, 0, 0, 0, 0, 0, 0, 0), - crate::word(180, 15, 0, 0, 35, 16, 0, 0), - crate::word(21, 0, 0, 0, 210, 0, 0, 0), - crate::word(33, 0, 0, 0, 7, 0, 0, 0), - crate::word(0, 0, 0, 0, 0, 0, 0, 0), - crate::word(29, 0, 0, 0, 63, 0, 0, 0), - crate::word(0, 0, 0, 0, 0, 0, 0, 0), - crate::word(0, 0, 0, 0, 0, 0, 0, 0), - crate::word(106, 115, 111, 110, 46, 99, 97, 112), - crate::word(110, 112, 58, 70, 108, 97, 116, 116), - crate::word(101, 110, 79, 112, 116, 105, 111, 110), - crate::word(115, 0, 0, 0, 0, 0, 0, 0), - crate::word(0, 0, 0, 0, 1, 0, 1, 0), - crate::word(4, 0, 0, 0, 3, 0, 4, 0), - crate::word(0, 0, 0, 0, 0, 0, 0, 0), - crate::word(0, 0, 1, 0, 0, 0, 0, 0), - crate::word(1, 0, 0, 0, 0, 0, 0, 0), - crate::word(13, 0, 0, 0, 58, 0, 0, 0), - crate::word(0, 0, 0, 0, 0, 0, 0, 0), - crate::word(8, 0, 0, 0, 3, 0, 1, 0), - crate::word(20, 0, 0, 0, 2, 0, 1, 0), - crate::word(112, 114, 101, 102, 105, 120, 0, 0), - crate::word(12, 0, 0, 0, 0, 0, 0, 0), - crate::word(0, 0, 0, 0, 0, 0, 0, 0), - crate::word(0, 0, 0, 0, 0, 0, 0, 0), - crate::word(0, 0, 0, 0, 0, 0, 0, 0), - crate::word(12, 0, 0, 0, 0, 0, 0, 0), - crate::word(0, 0, 0, 0, 0, 0, 0, 0), - crate::word(1, 0, 0, 0, 10, 0, 0, 0), - crate::word(0, 0, 0, 0, 0, 0, 0, 0), - ]; - pub fn get_field_types(index: u16) -> crate::introspect::Type { - match index { - 0 => ::introspect(), - _ => crate::introspect::panic_invalid_field_index(index), - } - } - pub fn get_annotation_types(child_index: Option, index: u32) -> crate::introspect::Type { - crate::introspect::panic_invalid_annotation_indices(child_index, index) - } - pub static RAW_SCHEMA: crate::introspect::RawStructSchema = crate::introspect::RawStructSchema { - encoded_node: &ENCODED_NODE, - nonunion_members: NONUNION_MEMBERS, - members_by_discriminant: MEMBERS_BY_DISCRIMINANT, - members_by_name: MEMBERS_BY_NAME, - }; - pub static NONUNION_MEMBERS : &[u16] = &[0]; - pub static MEMBERS_BY_DISCRIMINANT : &[u16] = &[]; - pub static MEMBERS_BY_NAME : &[u16] = &[0]; - pub static DEFAULT_PREFIX: [crate::Word; 2] = [ - crate::word(1, 0, 0, 0, 10, 0, 0, 0), - crate::word(0, 0, 0, 0, 0, 0, 0, 0), - ]; - pub const TYPE_ID: u64 = 0xc4df_1325_7bc2_ea61; - } -} -pub mod discriminator { - pub const ID: u64 = 0xcfa794e8d19a0162; - pub fn get_type() -> crate::introspect::Type { ::introspect() } -} - -pub mod discriminator_options { - #[derive(Copy, Clone)] - pub struct Owned(()); - impl crate::introspect::Introspect for Owned { fn introspect() -> crate::introspect::Type { crate::introspect::TypeVariant::Struct(crate::introspect::RawBrandedStructSchema { generic: &_private::RAW_SCHEMA, field_types: _private::get_field_types, annotation_types: _private::get_annotation_types }).into() } } - impl crate::traits::Owned for Owned { type Reader<'a> = Reader<'a>; type Builder<'a> = Builder<'a>; } - impl crate::traits::OwnedStruct for Owned { type Reader<'a> = Reader<'a>; type Builder<'a> = Builder<'a>; } - impl crate::traits::Pipelined for Owned { type Pipeline = Pipeline; } - - pub struct Reader<'a> { reader: crate::private::layout::StructReader<'a> } - impl <> ::core::marker::Copy for Reader<'_,> {} - impl <> ::core::clone::Clone for Reader<'_,> { - fn clone(&self) -> Self { *self } - } - - impl <> crate::traits::HasTypeId for Reader<'_,> { - const TYPE_ID: u64 = _private::TYPE_ID; - } - impl <'a,> ::core::convert::From> for Reader<'a,> { - fn from(reader: crate::private::layout::StructReader<'a>) -> Self { - Self { reader, } - } - } - - impl <'a,> ::core::convert::From> for crate::dynamic_value::Reader<'a> { - fn from(reader: Reader<'a,>) -> Self { - Self::Struct(crate::dynamic_struct::Reader::new(reader.reader, crate::schema::StructSchema::new(crate::introspect::RawBrandedStructSchema { generic: &_private::RAW_SCHEMA, field_types: _private::get_field_types::<>, annotation_types: _private::get_annotation_types::<>}))) - } - } - - impl <> ::core::fmt::Debug for Reader<'_,> { - fn fmt(&self, f: &mut ::core::fmt::Formatter<'_>) -> ::core::result::Result<(), ::core::fmt::Error> { - core::fmt::Debug::fmt(&::core::convert::Into::>::into(*self), f) - } - } - - impl <'a,> crate::traits::FromPointerReader<'a> for Reader<'a,> { - fn get_from_pointer(reader: &crate::private::layout::PointerReader<'a>, default: ::core::option::Option<&'a [crate::Word]>) -> crate::Result { - ::core::result::Result::Ok(reader.get_struct(default)?.into()) - } - } - - impl <'a,> crate::traits::IntoInternalStructReader<'a> for Reader<'a,> { - fn into_internal_struct_reader(self) -> crate::private::layout::StructReader<'a> { - self.reader - } - } - - impl <'a,> crate::traits::Imbue<'a> for Reader<'a,> { - fn imbue(&mut self, cap_table: &'a crate::private::layout::CapTable) { - self.reader.imbue(crate::private::layout::CapTableReader::Plain(cap_table)) - } - } - - impl <'a,> Reader<'a,> { - pub fn reborrow(&self) -> Reader<'_,> { - Self { .. *self } - } - - pub fn total_size(&self) -> crate::Result { - self.reader.total_size() - } - #[inline] - pub fn get_name(self) -> crate::Result> { - crate::traits::FromPointerReader::get_from_pointer(&self.reader.get_pointer_field(0), ::core::option::Option::None) - } - #[inline] - pub fn has_name(&self) -> bool { - !self.reader.get_pointer_field(0).is_null() - } - #[inline] - pub fn get_value_name(self) -> crate::Result> { - crate::traits::FromPointerReader::get_from_pointer(&self.reader.get_pointer_field(1), ::core::option::Option::None) - } - #[inline] - pub fn has_value_name(&self) -> bool { - !self.reader.get_pointer_field(1).is_null() - } - } - - pub struct Builder<'a> { builder: crate::private::layout::StructBuilder<'a> } - impl <> crate::traits::HasStructSize for Builder<'_,> { - const STRUCT_SIZE: crate::private::layout::StructSize = crate::private::layout::StructSize { data: 0, pointers: 2 }; - } - impl <> crate::traits::HasTypeId for Builder<'_,> { - const TYPE_ID: u64 = _private::TYPE_ID; - } - impl <'a,> ::core::convert::From> for Builder<'a,> { - fn from(builder: crate::private::layout::StructBuilder<'a>) -> Self { - Self { builder, } - } - } - - impl <'a,> ::core::convert::From> for crate::dynamic_value::Builder<'a> { - fn from(builder: Builder<'a,>) -> Self { - Self::Struct(crate::dynamic_struct::Builder::new(builder.builder, crate::schema::StructSchema::new(crate::introspect::RawBrandedStructSchema { generic: &_private::RAW_SCHEMA, field_types: _private::get_field_types::<>, annotation_types: _private::get_annotation_types::<>}))) - } - } - - impl <'a,> crate::traits::ImbueMut<'a> for Builder<'a,> { - fn imbue_mut(&mut self, cap_table: &'a mut crate::private::layout::CapTable) { - self.builder.imbue(crate::private::layout::CapTableBuilder::Plain(cap_table)) - } - } - - impl <'a,> crate::traits::FromPointerBuilder<'a> for Builder<'a,> { - fn init_pointer(builder: crate::private::layout::PointerBuilder<'a>, _size: u32) -> Self { - builder.init_struct(::STRUCT_SIZE).into() - } - fn get_from_pointer(builder: crate::private::layout::PointerBuilder<'a>, default: ::core::option::Option<&'a [crate::Word]>) -> crate::Result { - ::core::result::Result::Ok(builder.get_struct(::STRUCT_SIZE, default)?.into()) - } - } - - impl <> crate::traits::SetterInput> for Reader<'_,> { - fn set_pointer_builder(mut pointer: crate::private::layout::PointerBuilder<'_>, value: Self, canonicalize: bool) -> crate::Result<()> { pointer.set_struct(&value.reader, canonicalize) } - } - - impl <'a,> Builder<'a,> { - pub fn into_reader(self) -> Reader<'a,> { - self.builder.into_reader().into() - } - pub fn reborrow(&mut self) -> Builder<'_,> { - Builder { builder: self.builder.reborrow() } - } - pub fn reborrow_as_reader(&self) -> Reader<'_,> { - self.builder.as_reader().into() - } - - pub fn total_size(&self) -> crate::Result { - self.builder.as_reader().total_size() - } - #[inline] - pub fn get_name(self) -> crate::Result> { - crate::traits::FromPointerBuilder::get_from_pointer(self.builder.get_pointer_field(0), ::core::option::Option::None) - } - #[inline] - pub fn set_name(&mut self, value: impl crate::traits::SetterInput) { - crate::traits::SetterInput::set_pointer_builder(self.builder.reborrow().get_pointer_field(0), value, false).unwrap() - } - #[inline] - pub fn init_name(self, size: u32) -> crate::text::Builder<'a> { - self.builder.get_pointer_field(0).init_text(size) - } - #[inline] - pub fn has_name(&self) -> bool { - !self.builder.is_pointer_field_null(0) - } - #[inline] - pub fn get_value_name(self) -> crate::Result> { - crate::traits::FromPointerBuilder::get_from_pointer(self.builder.get_pointer_field(1), ::core::option::Option::None) - } - #[inline] - pub fn set_value_name(&mut self, value: impl crate::traits::SetterInput) { - crate::traits::SetterInput::set_pointer_builder(self.builder.reborrow().get_pointer_field(1), value, false).unwrap() - } - #[inline] - pub fn init_value_name(self, size: u32) -> crate::text::Builder<'a> { - self.builder.get_pointer_field(1).init_text(size) - } - #[inline] - pub fn has_value_name(&self) -> bool { - !self.builder.is_pointer_field_null(1) - } - } - - pub struct Pipeline { _typeless: crate::any_pointer::Pipeline } - impl crate::capability::FromTypelessPipeline for Pipeline { - fn new(typeless: crate::any_pointer::Pipeline) -> Self { - Self { _typeless: typeless, } - } - } - impl Pipeline { - } - mod _private { - pub static ENCODED_NODE: [crate::Word; 50] = [ - crate::word(0, 0, 0, 0, 6, 0, 6, 0), - crate::word(25, 83, 62, 41, 12, 194, 248, 194), - crate::word(11, 0, 0, 0, 1, 0, 0, 0), - crate::word(52, 94, 58, 164, 151, 146, 249, 142), - crate::word(2, 0, 7, 0, 0, 0, 0, 0), - crate::word(0, 0, 0, 0, 0, 0, 0, 0), - crate::word(187, 17, 0, 0, 184, 19, 0, 0), - crate::word(21, 0, 0, 0, 2, 1, 0, 0), - crate::word(33, 0, 0, 0, 7, 0, 0, 0), - crate::word(0, 0, 0, 0, 0, 0, 0, 0), - crate::word(29, 0, 0, 0, 119, 0, 0, 0), - crate::word(0, 0, 0, 0, 0, 0, 0, 0), - crate::word(0, 0, 0, 0, 0, 0, 0, 0), - crate::word(106, 115, 111, 110, 46, 99, 97, 112), - crate::word(110, 112, 58, 68, 105, 115, 99, 114), - crate::word(105, 109, 105, 110, 97, 116, 111, 114), - crate::word(79, 112, 116, 105, 111, 110, 115, 0), - crate::word(0, 0, 0, 0, 1, 0, 1, 0), - crate::word(8, 0, 0, 0, 3, 0, 4, 0), - crate::word(0, 0, 0, 0, 0, 0, 0, 0), - crate::word(0, 0, 1, 0, 0, 0, 0, 0), - crate::word(0, 0, 0, 0, 0, 0, 0, 0), - crate::word(41, 0, 0, 0, 42, 0, 0, 0), - crate::word(0, 0, 0, 0, 0, 0, 0, 0), - crate::word(36, 0, 0, 0, 3, 0, 1, 0), - crate::word(48, 0, 0, 0, 2, 0, 1, 0), - crate::word(1, 0, 0, 0, 1, 0, 0, 0), - crate::word(0, 0, 1, 0, 1, 0, 0, 0), - crate::word(0, 0, 0, 0, 0, 0, 0, 0), - crate::word(45, 0, 0, 0, 82, 0, 0, 0), - crate::word(0, 0, 0, 0, 0, 0, 0, 0), - crate::word(44, 0, 0, 0, 3, 0, 1, 0), - crate::word(56, 0, 0, 0, 2, 0, 1, 0), - crate::word(110, 97, 109, 101, 0, 0, 0, 0), - crate::word(12, 0, 0, 0, 0, 0, 0, 0), - crate::word(0, 0, 0, 0, 0, 0, 0, 0), - crate::word(0, 0, 0, 0, 0, 0, 0, 0), - crate::word(0, 0, 0, 0, 0, 0, 0, 0), - crate::word(12, 0, 0, 0, 0, 0, 0, 0), - crate::word(0, 0, 0, 0, 0, 0, 0, 0), - crate::word(0, 0, 0, 0, 0, 0, 0, 0), - crate::word(118, 97, 108, 117, 101, 78, 97, 109), - crate::word(101, 0, 0, 0, 0, 0, 0, 0), - crate::word(12, 0, 0, 0, 0, 0, 0, 0), - crate::word(0, 0, 0, 0, 0, 0, 0, 0), - crate::word(0, 0, 0, 0, 0, 0, 0, 0), - crate::word(0, 0, 0, 0, 0, 0, 0, 0), - crate::word(12, 0, 0, 0, 0, 0, 0, 0), - crate::word(0, 0, 0, 0, 0, 0, 0, 0), - crate::word(0, 0, 0, 0, 0, 0, 0, 0), - ]; - pub fn get_field_types(index: u16) -> crate::introspect::Type { - match index { - 0 => ::introspect(), - 1 => ::introspect(), - _ => crate::introspect::panic_invalid_field_index(index), - } - } - pub fn get_annotation_types(child_index: Option, index: u32) -> crate::introspect::Type { - crate::introspect::panic_invalid_annotation_indices(child_index, index) - } - pub static RAW_SCHEMA: crate::introspect::RawStructSchema = crate::introspect::RawStructSchema { - encoded_node: &ENCODED_NODE, - nonunion_members: NONUNION_MEMBERS, - members_by_discriminant: MEMBERS_BY_DISCRIMINANT, - members_by_name: MEMBERS_BY_NAME, - }; - pub static NONUNION_MEMBERS : &[u16] = &[0,1]; - pub static MEMBERS_BY_DISCRIMINANT : &[u16] = &[]; - pub static MEMBERS_BY_NAME : &[u16] = &[0,1]; - pub const TYPE_ID: u64 = 0xc2f8_c20c_293e_5319; - } -} -pub mod base64 { - pub const ID: u64 = 0xd7d879450a253e4b; - pub fn get_type() -> crate::introspect::Type { <() as crate::introspect::Introspect>::introspect() } -} -pub mod hex { - pub const ID: u64 = 0xf061e22f0ae5c7b5; - pub fn get_type() -> crate::introspect::Type { <() as crate::introspect::Introspect>::introspect() } -} -pub mod notification { - pub const ID: u64 = 0xa0a054dea32fd98c; - pub fn get_type() -> crate::introspect::Type { <() as crate::introspect::Introspect>::introspect() } -} diff --git a/capnp/src/lib.rs b/capnp/src/lib.rs index 67a0d6738..9a21f8fb4 100644 --- a/capnp/src/lib.rs +++ b/capnp/src/lib.rs @@ -37,8 +37,6 @@ extern crate alloc; /// [schema.capnp](https://github.com/capnproto/capnproto/blob/master/c%2B%2B/src/capnp/schema.capnp). pub mod schema_capnp; -pub mod json_capnp; - pub mod any_pointer; pub mod any_pointer_list; pub mod capability; @@ -52,7 +50,6 @@ pub mod dynamic_value; pub mod enum_list; pub mod introspect; pub mod io; -pub mod json; pub mod list_list; pub mod message; pub mod primitive_list; diff --git a/capnpc/test-edition-2015/Cargo.toml b/capnpc/test-edition-2015/Cargo.toml index 5953f8e06..ab3946511 100644 --- a/capnpc/test-edition-2015/Cargo.toml +++ b/capnpc/test-edition-2015/Cargo.toml @@ -16,4 +16,4 @@ capnpc = { path = "../" } [dependencies] capnp = { path = "../../capnp" } capnpc = { path = "../" } -external-crate = { path = "../test/external-crate" } \ No newline at end of file +external-crate = { path = "../test/external-crate" } diff --git a/capnpc/test-edition-2018/Cargo.toml b/capnpc/test-edition-2018/Cargo.toml index cff029364..eefe87fcf 100644 --- a/capnpc/test-edition-2018/Cargo.toml +++ b/capnpc/test-edition-2018/Cargo.toml @@ -16,4 +16,4 @@ capnpc = { path = "../" } [dependencies] capnp = { path = "../../capnp" } capnpc = { path = "../" } -external-crate = { path = "../test/external-crate" } \ No newline at end of file +external-crate = { path = "../test/external-crate" } diff --git a/capnpc/test/build.rs b/capnpc/test/build.rs index 37e1250a9..d40690898 100644 --- a/capnpc/test/build.rs +++ b/capnpc/test/build.rs @@ -1,9 +1,7 @@ fn main() { capnpc::CompilerCommand::new() .crate_provides("external_crate", [0xe6f94f52f7be8fe2]) - .crate_provides("capnp", [0x8ef99297a43a5e34]) // json.capnp .file("test.capnp") - .file("json-test.capnp") .file("in-submodule.capnp") .file("in-other-submodule.capnp") .file("schema/test-in-dir.capnp") diff --git a/capnpc/test/json.rs b/capnpc/test/json.rs deleted file mode 100644 index bb50ed82c..000000000 --- a/capnpc/test/json.rs +++ /dev/null @@ -1,718 +0,0 @@ -// Copyright (c) 2025 Ben Jackson [puremourning@gmail.com] and Cap'n Proto contributors -// Licensed under the MIT License: -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in -// all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -// THE SOFTWARE. - -use crate::json_test_capnp::test_json_annotations; -use crate::test_capnp::{ - test_json_flatten_union, test_json_types, test_union, test_unnamed_union, TestEnum, -}; -use capnp::json::{self}; -use capnp::message::{self}; - -#[test] -fn test_encode_json_types_default() { - let mut builder = message::Builder::new_default(); - let root: test_json_types::Builder<'_> = builder.init_root(); - let expected = r#"{"voidField":null,"boolField":false,"int8Field":0,"int16Field":0,"int32Field":0,"int64Field":0,"uInt8Field":0,"uInt16Field":0,"uInt32Field":0,"uInt64Field":0,"float32Field":0,"float64Field":0,"enumField":"foo"}"#; - assert_eq!(expected, json::to_json(root.reborrow_as_reader()).unwrap()); -} - -#[test] -fn test_encode_all_json_types() { - let mut builder = message::Builder::new_default(); - let mut root: test_json_types::Builder<'_> = builder.init_root(); - root.set_int8_field(-8); - root.set_int16_field(-16); - root.set_int32_field(-32); - root.set_int64_field(-64); - root.set_u_int8_field(8); - root.set_u_int16_field(16); - root.set_u_int32_field(32); - root.set_u_int64_field(64); - root.set_bool_field(true); - root.set_void_field(()); - root.set_text_field("hello"); - root.set_float32_field(1.32); - root.set_float64_field(1.64); - root.set_data_field(&[0xde, 0xad, 0xbe, 0xef, 0xca, 0xfe, 0xba, 0xbe]); - root.set_base64_field(&[0xde, 0xad, 0xbe, 0xef, 0xca, 0xfe, 0xba, 0xbe]); - root.set_hex_field(&[0xde, 0xad, 0xbe, 0xef, 0xca, 0xfe, 0xba, 0xbe]); - { - let mut embedded = root.reborrow().init_struct_field(); - let mut text_list = embedded.reborrow().init_text_list(2); - text_list.set(0, "frist"); - text_list.set(1, "segund"); - embedded.set_text_field("inner"); - let mut hex_list = embedded.reborrow().init_hex_list(2); - hex_list.set(0, &[0xde, 0xad, 0xbe, 0xef]); - hex_list.set(1, &[0xba, 0xdf, 0x00, 0xd0]); - let mut based_list = embedded.reborrow().init_base64_list(2); - based_list.set(0, &[0xde, 0xad, 0xbe, 0xef]); - based_list.set(1, &[0xba, 0xdf, 0x00, 0xd0]); - } - root.set_enum_field(TestEnum::Quux); - { - let mut enum_list = root.reborrow().init_enum_list(3); - enum_list.set(0, TestEnum::Foo); - enum_list.set(1, TestEnum::Bar); - enum_list.set(2, TestEnum::Garply); - } - { - let mut floats = root.reborrow().init_float32_list(3); - floats.set(0, f32::NAN); - floats.set(1, f32::INFINITY); - floats.set(2, f32::NEG_INFINITY); - } - { - let mut floats = root.reborrow().init_float64_list(3); - floats.set(0, f64::NAN); - floats.set(1, f64::INFINITY); - floats.set(2, f64::NEG_INFINITY); - } - - let expected = concat!( - "{", - r#""voidField":null,"#, - r#""boolField":true,"#, - r#""int8Field":-8,"#, - r#""int16Field":-16,"#, - r#""int32Field":-32,"#, - r#""int64Field":-64,"#, - r#""uInt8Field":8,"#, - r#""uInt16Field":16,"#, - r#""uInt32Field":32,"#, - r#""uInt64Field":64,"#, - r#""float32Field":1.3200000524520874,"#, - r#""float64Field":1.64,"#, - r#""textField":"hello","#, - r#""dataField":[222,173,190,239,202,254,186,190],"#, - r#""base64Field":"3q2+78r+ur4=","#, - r#""hexField":"deadbeefcafebabe","#, - r#""structField":{"#, - r#""voidField":null,"#, - r#""boolField":false,"#, - r#""int8Field":0,"#, - r#""int16Field":0,"#, - r#""int32Field":0,"#, - r#""int64Field":0,"#, - r#""uInt8Field":0,"#, - r#""uInt16Field":0,"#, - r#""uInt32Field":0,"#, - r#""uInt64Field":0,"#, - r#""float32Field":0,"#, - r#""float64Field":0,"#, - r#""textField":"inner","#, - r#""enumField":"foo","#, - r#""textList":["frist","segund"],"#, - r#""base64List":["3q2+7w==","ut8A0A=="],"#, - r#""hexList":["deadbeef","badf00d0"]"#, - "},", - r#""enumField":"quux","#, - r#""float32List":["NaN","Infinity","-Infinity"],"#, - r#""float64List":["NaN","Infinity","-Infinity"],"#, - r#""enumList":["foo","bar","garply"]"#, - "}" - ); - assert_eq!(expected, json::to_json(root.reborrow_as_reader()).unwrap()); -} - -// Union encoding with flattening - -#[test] -fn test_named_union_non_flattened() { - let mut builder = message::Builder::new_default(); - let mut root: test_union::Builder<'_> = builder.init_root(); - root.set_bit0(true); - root.set_bit2(false); - root.set_bit3(true); - root.set_bit4(false); - root.set_bit5(true); - root.set_bit6(false); - root.set_bit7(true); - root.set_byte0(0xAA); - let mut union0 = root.reborrow().init_union0(); - union0.set_u0f0sp("not this one"); - union0.set_u0f0s16(-12345); - - let expected = concat!( - "{", - r#""union0":{"u0f0s16":-12345},"#, - r#""union1":{"u1f0s0":null},"#, - r#""union2":{"u2f0s1":false},"#, - r#""union3":{"u3f0s1":false},"#, - r#""bit0":true,"#, - r#""bit2":false,"#, - r#""bit3":true,"#, - r#""bit4":false,"#, - r#""bit5":true,"#, - r#""bit6":false,"#, - r#""bit7":true,"#, - r#""byte0":170"#, - "}", - ); - - assert_eq!(expected, json::to_json(root.reborrow_as_reader()).unwrap()); -} - -#[test] -fn test_unnamed_union() { - let mut builder = message::Builder::new_default(); - let mut root: test_unnamed_union::Builder<'_> = builder.init_root(); - root.set_before("before"); - root.set_middle(1234); - root.set_after("after"); - root.set_foo(16); - root.set_bar(32); - let expected = concat!( - "{", - r#""before":"before","#, - r#""middle":1234,"#, - r#""after":"after","#, - r#""bar":32"#, - "}", - ); - assert_eq!(expected, json::to_json(root.reborrow_as_reader()).unwrap()); -} - -#[test] -fn test_named_union_flattened() { - let mut builder = message::Builder::new_default(); - let mut root: test_json_flatten_union::Builder<'_> = builder.init_root(); - root.set_before("before"); - root.set_middle(1234); - root.set_after("after"); - let mut maybe = root.reborrow().init_maybe(); - maybe.set_foo(16); - maybe.set_bar(32); - - let expected = concat!( - "{", - r#""before":"before","#, - r#""maybe_bar":32,"#, - r#""middle":1234,"#, - r#""after":"after","#, - r#""foo":0,"#, - r#""bar":0,"#, - r#""nested_baz":0,"#, - r#""baz":0"#, - "}", - ); - assert_eq!(expected, json::to_json(root.reborrow_as_reader()).unwrap()); -} - -#[test] -fn test_discriminated_union() { - let mut builder = message::Builder::new_default(); - let mut root: test_json_annotations::Builder<'_> = builder.init_root(); - - let mut expected = String::from("{"); - - root.set_some_field("Some Field"); - expected.push_str(r#""names-can_contain!anything Really":"Some Field","#); - - { - let mut a_group = root.reborrow().init_a_group(); - // a_group is flattenned - a_group.set_flat_foo(0xF00); - expected.push_str(r#""flatFoo":3840,"#); - - a_group.set_flat_bar("0xBaa"); - expected.push_str(r#""flatBar":"0xBaa","#); - - a_group.reborrow().init_flat_baz().set_hello(true); - expected.push_str(r#""renamed-flatBaz":{"hello":true},"#); - - a_group.reborrow().init_double_flat().set_flat_qux("Qux"); - expected.push_str(r#""flatQux":"Qux","#); - } - - { - let mut prefixed_group = root.reborrow().init_prefixed_group(); - prefixed_group.set_foo("Foo"); - expected.push_str(r#""pfx.foo":"Foo","#); - - prefixed_group.set_bar(0xBAA); - expected.push_str(r#""pfx.renamed-bar":2986,"#); - - prefixed_group.reborrow().init_baz().set_hello(false); - expected.push_str(r#""pfx.baz":{"hello":false},"#); - - prefixed_group.reborrow().init_more_prefix().set_qux("Qux"); - expected.push_str(r#""pfx.xfp.qux":"Qux","#); - } - - { - let mut a_union_bar = root.reborrow().init_a_union().init_bar(); - expected.push_str(r#""union-type":"renamed-bar","#); - a_union_bar.set_bar_member(0xAAB); - expected.push_str(r#""barMember":2731,"#); - a_union_bar.set_multi_member("Member"); - expected.push_str(r#""multiMember":"Member","#); - } - - { - let mut dependency = root.reborrow().init_dependency(); - dependency.set_foo("dep-foo"); - expected.push_str(r#""dependency":{"renamed-foo":"dep-foo"},"#); - } - - { - let mut simple_group = root.reborrow().init_simple_group(); - simple_group.set_grault("grault"); - expected.push_str(r#""simpleGroup":{"renamed-grault":"grault"},"#); - } - - { - let mut e = root.reborrow().init_enums(4); - e.set(0, crate::json_test_capnp::TestJsonAnnotatedEnum::Foo); - e.set(1, crate::json_test_capnp::TestJsonAnnotatedEnum::Bar); - e.set(2, crate::json_test_capnp::TestJsonAnnotatedEnum::Baz); - e.set(3, crate::json_test_capnp::TestJsonAnnotatedEnum::Qux); - expected.push_str(r#""enums":["foo","renamed-bar","renamed-baz","qux"],"#); - } - - { - let mut b_union = root.reborrow().init_b_union(); - expected.push_str(r#""bUnion":"renamed-bar","#); - b_union.set_bar(100); - expected.push_str(r#""bValue":100,"#); - } - - { - let mut external_union = root.reborrow().init_external_union(); - external_union.reborrow().init_bar().set_value("Value"); - expected.push_str(r#""externalUnion":{"type":"bar","value":"Value"},"#); - } - - { - let mut union_with_void = root.reborrow().init_union_with_void(); - union_with_void.set_void_value(()); - expected.push_str(r#""unionWithVoid":{"type":"voidValue","voidValue":null},"#); - } - - expected.pop(); // Remove trailing comma - expected.push('}'); - - assert_eq!(expected, json::to_json(root.reborrow_as_reader()).unwrap()); -} - -#[test] -fn test_base64_union() { - let mut builder = message::Builder::new_default(); - let mut root: crate::json_test_capnp::test_base64_union::Builder<'_> = builder.init_root(); - - root.set_foo(&[0xde, 0xad, 0xbe, 0xef]); - assert_eq!( - r#"{"foo":"3q2+7w=="}"#, - json::to_json(root.reborrow_as_reader()).unwrap() - ); -} - -#[test] -fn test_string_encoding() { - let mut builder = message::Builder::new_default(); - let mut root: crate::json_test_capnp::test_flattened_struct::Builder<'_> = builder.init_root(); - - root.set_value(""); - assert_eq!( - r#"{"value":""}"#, - json::to_json(root.reborrow_as_reader()).unwrap() - ); - - root.set_value("tab: \t, newline: \n, carriage return: \r, quote: \", backslash: \\"); - assert_eq!( - r#"{"value":"tab: \t, newline: \n, carriage return: \r, quote: \", backslash: \\"}"#, - json::to_json(root.reborrow_as_reader()).unwrap() - ); - - root.set_value("unicode: †eśt"); - assert_eq!( - r#"{"value":"unicode: †eśt"}"#, - json::to_json(root.reborrow_as_reader()).unwrap() - ); - - root.set_value("backspace: \u{0008}, formfeed: \u{000C}"); - assert_eq!( - r#"{"value":"backspace: \b, formfeed: \f"}"#, - json::to_json(root.reborrow_as_reader()).unwrap() - ); - - root.set_value("bell: \u{0007}, SOH: \u{0001}"); - assert_eq!( - r#"{"value":"bell: \u0007, SOH: \u0001"}"#, - json::to_json(root.reborrow_as_reader()).unwrap() - ); -} - -#[test] -fn test_nested_data_list() -> capnp::Result<()> { - let mut builder = message::Builder::new_default(); - let mut root = builder.init_root::>(); - let mut awd = root.reborrow().init_data_all_the_way_down(2); - let mut first = awd.reborrow().init(0, 2); - first.set(0, &[0xde, 0xad, 0xbe, 0xef]); - first.set(1, &[0xef, 0xbe, 0xad, 0xde]); - let mut second = awd.reborrow().init(1, 1); - second.set(0, &[0xba, 0xdf, 0x00, 0xd0]); - - assert_eq!( - r#"{"dataAllTheWayDown":[["deadbeef","efbeadde"],["badf00d0"]]}"#, - json::to_json(root.reborrow_as_reader())? - ); - - Ok(()) -} - -// Decode - -#[test] -fn test_decode_simple() -> capnp::Result<()> { - let mut builder = message::Builder::new_default(); - let mut root: test_json_types::Builder<'_> = builder.init_root(); - json::from_json( - r#" - { - "voidField": null, - "boolField": true, - "int8Field": -8, - "int16Field": -16, - "int32Field": -32, - "int64Field": -64, - "uInt8Field": 8, - "uInt16Field": 16, - "uInt32Field": 32, - "uInt64Field": 64, - "float32Field": 1.3200000524520874, - "float64Field": 0.164e2, - "textField": "hello", - "dataField": [ - 222, - 173 - - , - - 190, - 239, - 202, - 254, - 186, - 190 - ], - "base64Field": "3q2+78r+ur4=", - "hexField": "deadbeefcafebabe", - "structField": { - "voidField": null, - "boolField": false, - "int8Field": 0, - "int16Field": 0, - "int32Field": 0, - "int64Field": 0, - "uInt8Field": 0, - "uInt16Field" - : 0, - "uInt32Field": 0, - "uInt64Field": 0, - "float32Field": 0, - "float64Field": 0, - "textField": "inner", - "enumField": "foo", - "textList": [ - "frist", - "segund" - ], - "base64List": [ - "3q2+7w==", - "ut8A0A==" - ], - "hexList": [ - "deadbeef", - "badf00d0" - ] - }, - "enumField": "quux", - "float32List": [ - "NaN", - "Infinity", - "-Infinity" - ], - "float64List": [ - "NaN", - "Infinity" , - "-Infinity" - ], - "enumList": [ - "foo", - "bar", - "garply" - ], - "int64List": [ - 1, - 2, - 4, - 8 - ] - } - "#, - root.reborrow(), - )?; - - let reader = root.into_reader(); - assert_eq!((), reader.get_void_field()); - assert_eq!(true, reader.get_bool_field()); - assert_eq!(-8, reader.get_int8_field()); - assert_eq!(-16, reader.get_int16_field()); - assert_eq!(-32, reader.get_int32_field()); - assert_eq!(-64, reader.get_int64_field()); - assert_eq!(8, reader.get_u_int8_field()); - assert_eq!(16, reader.get_u_int16_field()); - assert_eq!(32, reader.get_u_int32_field()); - assert_eq!(64, reader.get_u_int64_field()); - assert_eq!(1.32, reader.get_float32_field()); - assert_eq!(16.4, reader.get_float64_field()); - assert_eq!("hello", reader.get_text_field()?.to_str()?); - assert_eq!( - [0xde, 0xad, 0xbe, 0xef, 0xca, 0xfe, 0xba, 0xbe], - reader.get_data_field()? - ); - assert_eq!( - [0xde, 0xad, 0xbe, 0xef, 0xca, 0xfe, 0xba, 0xbe], - reader.get_base64_field()? - ); - assert_eq!( - [0xde, 0xad, 0xbe, 0xef, 0xca, 0xfe, 0xba, 0xbe], - reader.get_hex_field()? - ); - - for i in 0..4 { - assert_eq!(1 << i, reader.get_int64_list()?.get(i as u32)); - } - - Ok(()) -} - -#[test] -fn test_encode_with_empty_flattened() -> capnp::Result<()> { - let mut builder = capnp::message::Builder::new_default(); - let root = builder.init_root::>(); - - assert_eq!( - r#"{"flatFoo":0,"renamed-flatBaz":{"hello":false},"pfx.renamed-bar":0,"pfx.baz":{"hello":false},"union-type":"foo","multiMember":0,"simpleGroup":{},"unionWithVoid":{"type":"intValue","intValue":0}}"#, - json::to_json(root.reborrow_as_reader())? - ); - - Ok(()) -} - -#[test] -fn test_decode_flattened() -> capnp::Result<()> { - let j = r#" - { - "names-can_contain!anything Really": "Some Field", - "flatFoo": 1234, - "flatBar": "0xBaa", - "renamed-flatBaz": {"hello": true}, - "flatQux": "Qux", - "pfx.baz": {"hello": true}, - "union-type": "renamed-bar", - "barMember": 2731, - "multiMember": "Member", - "bUnion": "renamed-bar", - "bValue": 100 - } - "#; - let mut builder = capnp::message::Builder::new_default(); - let mut root = - builder.init_root::>(); - json::from_json(j, root.reborrow())?; - - let reader = root.into_reader(); - assert_eq!("Some Field", reader.get_some_field()?.to_str()?); - assert_eq!(1234, reader.get_a_group().get_flat_foo()); - assert_eq!("0xBaa", reader.get_a_group().get_flat_bar()?.to_str()?); - assert_eq!(true, reader.get_a_group().get_flat_baz().get_hello()); - assert_eq!( - "Qux", - reader - .get_a_group() - .get_double_flat() - .get_flat_qux()? - .to_str()? - ); - assert_eq!(true, reader.get_prefixed_group().get_baz().get_hello()); - assert!(matches!( - reader.get_a_union().which()?, - crate::json_test_capnp::test_json_annotations::a_union::Bar(_) - )); - { - let bar = match reader.get_a_union().which()? { - crate::json_test_capnp::test_json_annotations::a_union::Bar(b) => b, - _ => panic!("Expected Bar"), - }; - assert_eq!(2731, bar.get_bar_member()); - assert_eq!("Member", bar.get_multi_member()?.to_str()?); - } - assert!(matches!( - reader.get_b_union().which()?, - crate::json_test_capnp::test_json_annotations::b_union::Bar(_) - )); - { - let bar = match reader.get_b_union().which()? { - crate::json_test_capnp::test_json_annotations::b_union::Bar(b) => b, - _ => panic!("Expected Bar"), - }; - assert_eq!(100, bar); - } - - Ok(()) -} - -#[test] -fn test_decode_base64_union() -> capnp::Result<()> { - { - let j = r#" - { - "foo":"3q2+7w==" - } - "#; - let mut builder = capnp::message::Builder::new_default(); - let mut root = - builder.init_root::>(); - json::from_json(j, root.reborrow())?; - - let reader = root.into_reader(); - assert!(matches!( - reader.which()?, - crate::json_test_capnp::test_base64_union::Foo(_) - )); - { - let foo = match reader.which()? { - crate::json_test_capnp::test_base64_union::Foo(f) => f, - _ => panic!("Expected Foo"), - }?; - assert_eq!(&[0xde, 0xad, 0xbe, 0xef], foo); - } - } - - { - let j = r#" - { - "bar":"To the bar!" - } - "#; - let mut builder = capnp::message::Builder::new_default(); - let mut root = - builder.init_root::>(); - json::from_json(j, root.reborrow())?; - - let reader = root.into_reader(); - assert!(matches!( - reader.which()?, - crate::json_test_capnp::test_base64_union::Bar(_) - )); - { - let bar = match reader.which()? { - crate::json_test_capnp::test_base64_union::Bar(b) => b?, - _ => panic!("Expected Foo"), - }; - assert_eq!("To the bar!", bar.to_str()?); - } - } - - // When both variants are present, we pick the first one in the spec - { - let j = r#" - { - "bar":"To the bar!", - "foo":"3q2+7w==" - } - "#; - let mut builder = capnp::message::Builder::new_default(); - let mut root = - builder.init_root::>(); - json::from_json(j, root.reborrow())?; - - let reader = root.into_reader(); - assert!(matches!( - reader.which()?, - crate::json_test_capnp::test_base64_union::Foo(_) - )); - { - let foo = match reader.which()? { - crate::json_test_capnp::test_base64_union::Foo(f) => f, - _ => panic!("Expected Foo"), - }?; - assert_eq!(&[0xde, 0xad, 0xbe, 0xef], foo); - } - } - - { - let j = r#" - { - "bar":"To the bar!", - "foo":"3q2+7w==" - } - "#; - let mut builder = capnp::message::Builder::new_default(); - let mut root = - builder.init_root::>(); - json::from_json(j, root.reborrow())?; - - let reader = root.into_reader(); - assert!(matches!( - reader.which()?, - crate::json_test_capnp::test_renamed_anon_union::Bar(_) - )); - { - let bar = match reader.which()? { - crate::json_test_capnp::test_renamed_anon_union::Bar(b) => b?, - _ => panic!("Expected Foo"), - }; - assert_eq!("To the bar!", bar.to_str()?); - } - } - - { - let j = r#" - { - "bar":"To the bar!", - "renamed-foo":"3q2+7w==" - } - "#; - let mut builder = capnp::message::Builder::new_default(); - let mut root = - builder.init_root::>(); - json::from_json(j, root.reborrow())?; - - let reader = root.into_reader(); - assert!(matches!( - reader.which()?, - crate::json_test_capnp::test_renamed_anon_union::Foo(_) - )); - { - let foo = match reader.which()? { - crate::json_test_capnp::test_renamed_anon_union::Foo(f) => f, - _ => panic!("Expected Foo"), - }?; - assert_eq!(&[0xde, 0xad, 0xbe, 0xef], foo); - } - } - Ok(()) -} - diff --git a/capnpc/test/test.capnp b/capnpc/test/test.capnp index 0ce26d52f..d8840052a 100644 --- a/capnpc/test/test.capnp +++ b/capnpc/test/test.capnp @@ -24,7 +24,6 @@ using Rust = import "rust.capnp"; using External = import "./external-crate/external.capnp"; -using Json = import "/capnp/compat/json.capnp"; # The test case is that this builds. This ensure we're able to refer to a struct # (external_capnp::opts) in the generated code. @@ -866,67 +865,3 @@ struct Issue260(T, Q) { interface TestStream { send @0 (data : Data) -> stream; } - -struct TestJsonTypes { - voidField @0 : Void; - boolField @1 : Bool; - int8Field @2 : Int8; - int16Field @3 : Int16; - int32Field @4 : Int32; - int64Field @5 : Int64; - uInt8Field @6 : UInt8; - uInt16Field @7 : UInt16; - uInt32Field @8 : UInt32; - uInt64Field @9 : UInt64; - float32Field @10 : Float32; - float64Field @11 : Float64; - textField @12 : Text; - dataField @13 : Data; - base64Field @14 : Data $Json.base64; - hexField @15 : Data $Json.hex; - structField @16 : TestJsonTypes; - enumField @17 : TestEnum; - - voidList @18 : List(Void); - boolList @19 : List(Bool); - int8List @20 : List(Int8); - int16List @21 : List(Int16); - int32List @22 : List(Int32); - int64List @23 : List(Int64); - uInt8List @24 : List(UInt8); - uInt16List @25 : List(UInt16); - uInt32List @26 : List(UInt32); - uInt64List @27 : List(UInt64); - float32List @28 : List(Float32); - float64List @29 : List(Float64); - textList @30 : List(Text); - dataList @31 : List(Data); - base64List @32 : List(Data) $Json.base64; - hexList @33 : List(Data) $Json.hex; - structList @34 : List(TestJsonTypes); - enumList @35 : List(TestEnum); -} - -struct TestJsonFlattenUnion { - before @0 :Text; - - maybe :union $Json.flatten("maybe_") { # field, group, union to test - foo @1 :UInt16; - bar @3 :UInt32; - } - - groupie :group $Json.flatten() { - foo @5 :UInt16; - bar @6 :UInt32; - prefixed :group $Json.flatten("nested_") { - baz @7 :UInt8; - } - nested :group $Json.flatten() { - baz @8 :UInt8; - } - } - - middle @2 :UInt16; - - after @4 :Text; -} diff --git a/capnpc/test/test.rs b/capnpc/test/test.rs index 368ce5fd7..26ace4153 100644 --- a/capnpc/test/test.rs +++ b/capnpc/test/test.rs @@ -24,7 +24,6 @@ #![allow(clippy::bool_assert_comparison, clippy::approx_constant)] capnp::generated_code!(pub mod test_capnp); -capnp::generated_code!(pub mod json_test_capnp); pub mod foo { pub mod bar { @@ -60,9 +59,6 @@ mod test_util; #[cfg(test)] mod dynamic; -#[cfg(test)] -mod json; - #[cfg(test)] mod tests { use crate::test_util::{init_test_message, CheckTestMessage}; From e53551b5d4ed19f65e35609f555376d8e459f2ea Mon Sep 17 00:00:00 2001 From: Ben Jackson Date: Wed, 3 Dec 2025 22:00:58 +0000 Subject: [PATCH 15/29] Split into more files because people like files --- capnp-json/src/data.rs | 120 ++++ capnp-json/src/decode.rs | 738 ++++++++++++++++++++++ capnp-json/src/encode.rs | 283 +++++++++ capnp-json/src/json.rs | 1287 -------------------------------------- capnp-json/src/lib.rs | 111 +++- 5 files changed, 1250 insertions(+), 1289 deletions(-) create mode 100644 capnp-json/src/data.rs create mode 100644 capnp-json/src/decode.rs create mode 100644 capnp-json/src/encode.rs delete mode 100644 capnp-json/src/json.rs diff --git a/capnp-json/src/data.rs b/capnp-json/src/data.rs new file mode 100644 index 000000000..2805d4b36 --- /dev/null +++ b/capnp-json/src/data.rs @@ -0,0 +1,120 @@ +// We don't want to pull in base64 crate just for this. So hand-rolling a +// base64 codec. +pub mod base64 { + const BASE64_CHARS: &[u8; 64] = + b"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; + + pub fn encode(data: &[u8]) -> String { + let mut encoded = String::with_capacity(data.len().div_ceil(3) * 4); + for chunk in data.chunks(3) { + #[allow(clippy::get_first)] + let b0 = chunk.get(0).copied().unwrap_or(0); + let b1 = chunk.get(1).copied().unwrap_or(0); + let b2 = chunk.get(2).copied().unwrap_or(0); + let n = ((b0 as u32) << 16) | ((b1 as u32) << 8) | (b2 as u32); + let c0 = BASE64_CHARS[((n >> 18) & 0x3F) as usize]; + let c1 = BASE64_CHARS[((n >> 12) & 0x3F) as usize]; + let c2 = if chunk.len() > 1 { + BASE64_CHARS[((n >> 6) & 0x3F) as usize] + } else { + b'=' + }; + let c3 = if chunk.len() > 2 { + BASE64_CHARS[(n & 0x3F) as usize] + } else { + b'=' + }; + encoded.push(c0 as char); + encoded.push(c1 as char); + encoded.push(c2 as char); + encoded.push(c3 as char); + } + encoded + } + + pub fn decode(data: &str) -> capnp::Result> { + let bytes = data.as_bytes(); + if !bytes.len().is_multiple_of(4) { + return Err(capnp::Error::failed( + "Base64 string length must be a multiple of 4".into(), + )); + } + let mut decoded = Vec::with_capacity(bytes.len() / 4 * 3); + for chunk in bytes.chunks(4) { + let mut n: u32 = 0; + let mut padding = 0; + for &c in chunk { + n <<= 6; + match c { + b'A'..=b'Z' => n |= (c - b'A') as u32, + b'a'..=b'z' => n |= (c - b'a' + 26) as u32, + b'0'..=b'9' => n |= (c - b'0' + 52) as u32, + b'+' => n |= 62, + b'/' => n |= 63, + b'=' => { + n |= 0; + padding += 1; + } + _ => { + return Err(capnp::Error::failed(format!( + "Invalid base64 character: {}", + c as char + ))); + } + } + } + decoded.push(((n >> 16) & 0xFF) as u8); + if padding < 2 { + decoded.push(((n >> 8) & 0xFF) as u8); + } + if padding < 1 { + decoded.push((n & 0xFF) as u8); + } + } + Ok(decoded) + } +} + +// We don't want to pull in hex crate just for this. So hand-rolling a +// hex codec. +pub mod hex { + const HEX_CHARS: &[u8; 16] = b"0123456789abcdef"; + fn hex_char_to_value(c: u8) -> capnp::Result { + match c { + b'0'..=b'9' => Ok(c - b'0'), + b'a'..=b'f' => Ok(c - b'a' + 10), + b'A'..=b'F' => Ok(c - b'A' + 10), + _ => Err(capnp::Error::failed(format!( + "Invalid hex character: {}", + c as char + ))), + } + } + + pub fn encode(data: &[u8]) -> String { + let mut encoded = String::with_capacity(data.len() * 2); + for &byte in data { + let high = HEX_CHARS[(byte >> 4) as usize]; + let low = HEX_CHARS[(byte & 0x0F) as usize]; + encoded.push(high as char); + encoded.push(low as char); + } + encoded + } + + pub fn decode(data: &str) -> capnp::Result> { + if !data.len().is_multiple_of(2) { + return Err(capnp::Error::failed( + "Hex string must have even length".into(), + )); + } + let mut decoded = Vec::with_capacity(data.len() / 2); + let bytes = data.as_bytes(); + for i in (0..data.len()).step_by(2) { + let high = hex_char_to_value(bytes[i])?; + let low = hex_char_to_value(bytes[i + 1])?; + decoded.push((high << 4) | low); + } + Ok(decoded) + } +} diff --git a/capnp-json/src/decode.rs b/capnp-json/src/decode.rs new file mode 100644 index 000000000..15b6d0cb9 --- /dev/null +++ b/capnp-json/src/decode.rs @@ -0,0 +1,738 @@ +// Deserialisation +use super::data::{base64, hex}; +use super::json_capnp; +use super::{DataEncoding, EncodingOptions}; + +enum ParseError { + UnexpectedEndOfInput, + InvalidToken(char), + Other(String), +} + +impl From for capnp::Error { + fn from(err: ParseError) -> Self { + match err { + ParseError::UnexpectedEndOfInput => { + capnp::Error::failed("Unexpected end of input while parsing JSON".into()) + } + ParseError::InvalidToken(c) => { + capnp::Error::failed(format!("Invalid token '{c}' while parsing JSON")) + } + // TODO: Use better values here? + ParseError::Other(msg) => capnp::Error::failed(msg), + } + } +} + +use std::collections::HashMap; + +// FIXME: The String valued below could be Cow<'input, str> as they only really +// need to be allocated if the input contains escaped characters. That would be +// a little more tricky lower down, but not by a lot. +enum JsonValue { + Null, + Boolean(bool), + Number(f64), + String(String), + Array(Vec), + Object(HashMap), + + DataBuffer(Vec), // HACK: This is so we have somewhere to store the data + // temporarily when we are decoding data fields into + // Readers +} + +struct Parser +where + I: Iterator, +{ + // FIXME: By using an iter over char here, we restrict ourselves to not + // being able to use string slices for must of the parsing. THis is piggy. + // It would be better to just have a &str and an index probably. + input_iter: std::iter::Peekable>, +} + +impl Parser +where + I: Iterator, +{ + fn new(iter: I) -> Self { + Self { + input_iter: iter.fuse().peekable(), + } + } + + /// Advance past any whitespace and peek at next value + fn peek_next(&mut self) -> Option { + self.discard_whitespace(); + self.peek() + } + + /// Peek at the current value + fn peek(&mut self) -> Option { + self.input_iter.peek().copied() + } + + /// Consume the current value + fn advance(&mut self) -> capnp::Result { + self.input_iter + .next() + .ok_or(ParseError::UnexpectedEndOfInput.into()) + } + + /// Consume the current value if it matches `c`, otherwise error + fn consume(&mut self, c: char) -> capnp::Result { + match self.advance()? { + p if p == c => Ok(p), + p => Err(ParseError::InvalidToken(p).into()), + } + } + + /// Advance past any whitespace and consume the current value if it matches `c`, otherwise error + fn consume_next(&mut self, c: char) -> capnp::Result { + self.discard_whitespace(); + match self.advance()? { + p if p == c => Ok(p), + p => Err(ParseError::InvalidToken(p).into()), + } + } + + fn discard_whitespace(&mut self) { + while let Some(c) = self.peek() { + if c.is_whitespace() { + self.advance().ok(); + } else { + break; + } + } + } + + fn parse_value(&mut self) -> capnp::Result { + match self.peek_next() { + None => Err(ParseError::UnexpectedEndOfInput.into()), + Some('n') => { + self.advance()?; + self.consume('u')?; + self.consume('l')?; + self.consume('l')?; + Ok(JsonValue::Null) + } + Some('t') => { + self.advance()?; + self.consume('r')?; + self.consume('u')?; + self.consume('e')?; + Ok(JsonValue::Boolean(true)) + } + Some('f') => { + self.advance()?; + self.consume('a')?; + self.consume('l')?; + self.consume('s')?; + self.consume('e')?; + Ok(JsonValue::Boolean(false)) + } + Some('\"') => Ok(JsonValue::String(self.parse_string()?)), + Some('0'..='9') | Some('-') => { + let num_str = self.parse_number()?; + let num = num_str + .parse::() + .map_err(|e| ParseError::Other(format!("Invalid number format: {}", e)))?; + Ok(JsonValue::Number(num)) + } + Some('[') => { + self.advance()?; + let mut items = Vec::new(); + let mut require_comma = false; + while self.peek_next().is_some_and(|c| c != ']') { + if require_comma { + self.consume(',')?; + } + require_comma = true; + let item = self.parse_value()?; + items.push(item); + } + self.consume_next(']')?; + Ok(JsonValue::Array(items)) + } + Some('{') => { + self.advance()?; + let mut members = HashMap::new(); + let mut require_comma = false; + while self.peek_next().is_some_and(|c| c != '}') { + if require_comma { + self.consume(',')?; + } + require_comma = true; + let key = self.parse_string()?; + self.consume_next(':')?; + let value = self.parse_value()?; + if members.insert(key.clone(), value).is_some() { + return Err( + ParseError::Other(format!("Duplicate key in object: {}", key)).into(), + ); + } + } + self.consume_next('}')?; + Ok(JsonValue::Object(members)) + } + Some(c) => Err(ParseError::InvalidToken(c).into()), + } + } + + fn parse_string(&mut self) -> capnp::Result { + self.consume_next('\"')?; + let mut result = String::new(); + loop { + let c = self.advance()?; + match c { + '\"' => return Ok(result), + '\\' => { + let escaped = self.advance()?; + match escaped { + '\"' => result.push('\"'), + '\\' => result.push('\\'), + '/' => result.push('/'), + 'b' => result.push('\u{08}'), + 'f' => result.push('\u{0C}'), + 'n' => result.push('\n'), + 'r' => result.push('\r'), + 't' => result.push('\t'), + 'u' => { + let mut hex = String::new(); + for _ in 0..4 { + hex.push(self.advance()?); + } + let code_point = u16::from_str_radix(&hex, 16).map_err(|_| { + ParseError::Other(format!("Invalid unicode escape: \\u{}", hex)) + })?; + if let Some(ch) = std::char::from_u32(code_point as u32) { + result.push(ch); + } else { + return Err(ParseError::Other(format!( + "Invalid unicode code point: \\u{}", + hex + )) + .into()); + } + } + other => { + return Err(ParseError::Other(format!( + "Invalid escape character: \\{}", + other + )) + .into()); + } + } + } + other => result.push(other), + } + } + } + + fn parse_number(&mut self) -> capnp::Result { + let mut num_str = String::new(); + if self.peek_next().is_some_and(|c| c == '-') { + num_str.push(self.advance()?); + } + while self.peek().is_some_and(|c| c.is_ascii_digit()) { + num_str.push(self.advance()?); + } + if self.peek().is_some_and(|c| c == '.') { + num_str.push(self.advance()?); + while self.peek().is_some_and(|c| c.is_ascii_digit()) { + num_str.push(self.advance()?); + } + } + if self.peek().is_some_and(|c| c == 'e' || c == 'E') { + num_str.push(self.advance()?); + if self.peek().is_some_and(|c| c == '+' || c == '-') { + num_str.push(self.advance()?); + } + while self.peek().is_some_and(|c| c.is_ascii_digit()) { + num_str.push(self.advance()?); + } + } + Ok(num_str) + } +} + +pub fn parse(json: &str, builder: capnp::dynamic_struct::Builder<'_>) -> capnp::Result<()> { + let mut parser = Parser::new(json.chars()); + let value = parser.parse_value()?; + let meta = EncodingOptions { + prefix: &std::borrow::Cow::Borrowed(""), + name: "", + flatten: None, + discriminator: None, + data_encoding: DataEncoding::Default, + }; + let JsonValue::Object(mut value) = value else { + return Err(capnp::Error::failed( + "Top-level JSON value must be an object".into(), + )); + }; + decode_struct(&mut value, builder, &meta) +} + +fn decode_primitive<'json, 'meta>( + field_value: &'json mut JsonValue, + field_type: &'meta capnp::introspect::Type, + field_meta: &'meta EncodingOptions, +) -> capnp::Result> { + match field_type.which() { + capnp::introspect::TypeVariant::Void => { + if !matches!(field_value, JsonValue::Null) { + Err(capnp::Error::failed(format!( + "Expected null for void field {}", + field_meta.name + ))) + } else { + Ok(capnp::dynamic_value::Reader::Void) + } + } + capnp::introspect::TypeVariant::Bool => { + let JsonValue::Boolean(field_value) = field_value else { + return Err(capnp::Error::failed(format!( + "Expected boolean for field {}", + field_meta.name + ))); + }; + Ok((*field_value).into()) + } + capnp::introspect::TypeVariant::Int8 => { + let JsonValue::Number(field_value) = field_value else { + return Err(capnp::Error::failed(format!( + "Expected number for field {}", + field_meta.name + ))); + }; + Ok((*field_value as i8).into()) + } + capnp::introspect::TypeVariant::Int16 => { + let JsonValue::Number(field_value) = field_value else { + return Err(capnp::Error::failed(format!( + "Expected number for field {}", + field_meta.name + ))); + }; + Ok((*field_value as i16).into()) + } + capnp::introspect::TypeVariant::Int32 => { + let JsonValue::Number(field_value) = field_value else { + return Err(capnp::Error::failed(format!( + "Expected number for field {}", + field_meta.name + ))); + }; + Ok((*field_value as i32).into()) + } + capnp::introspect::TypeVariant::Int64 => { + let JsonValue::Number(field_value) = field_value else { + return Err(capnp::Error::failed(format!( + "Expected number for field {}", + field_meta.name + ))); + }; + Ok((*field_value as i64).into()) + } + capnp::introspect::TypeVariant::UInt8 => { + let JsonValue::Number(field_value) = field_value else { + return Err(capnp::Error::failed(format!( + "Expected number for field {}", + field_meta.name + ))); + }; + Ok((*field_value as u8).into()) + } + capnp::introspect::TypeVariant::UInt16 => { + let JsonValue::Number(field_value) = field_value else { + return Err(capnp::Error::failed(format!( + "Expected number for field {}", + field_meta.name + ))); + }; + Ok((*field_value as u16).into()) + } + capnp::introspect::TypeVariant::UInt32 => { + let JsonValue::Number(field_value) = field_value else { + return Err(capnp::Error::failed(format!( + "Expected number for field {}", + field_meta.name + ))); + }; + Ok((*field_value as u32).into()) + } + capnp::introspect::TypeVariant::UInt64 => { + let JsonValue::Number(field_value) = field_value else { + return Err(capnp::Error::failed(format!( + "Expected number for field {}", + field_meta.name + ))); + }; + Ok((*field_value as u64).into()) + } + capnp::introspect::TypeVariant::Float32 => { + let field_value = match field_value { + JsonValue::Number(field_value) => *field_value as f32, + JsonValue::String(field_value) => match field_value.as_str() { + "NaN" => f32::NAN, + "Infinity" => f32::INFINITY, + "-Infinity" => f32::NEG_INFINITY, + _ => { + return Err(capnp::Error::failed(format!( + "Expected number for field {}", + field_meta.name + ))); + } + }, + _ => { + return Err(capnp::Error::failed(format!( + "Expected number for field {}", + field_meta.name + ))); + } + }; + Ok(field_value.into()) + } + capnp::introspect::TypeVariant::Float64 => { + let field_value = match field_value { + JsonValue::Number(field_value) => *field_value, + JsonValue::String(field_value) => match field_value.as_str() { + "NaN" => f64::NAN, + "Infinity" => f64::INFINITY, + "-Infinity" => f64::NEG_INFINITY, + _ => { + return Err(capnp::Error::failed(format!( + "Expected number for field {}", + field_meta.name + ))); + } + }, + _ => { + return Err(capnp::Error::failed(format!( + "Expected number for field {}", + field_meta.name + ))); + } + }; + Ok(field_value.into()) + } + capnp::introspect::TypeVariant::Text => { + let JsonValue::String(field_value) = field_value else { + return Err(capnp::Error::failed(format!( + "Expected string for field {}", + field_meta.name + ))); + }; + Ok((*field_value.as_str()).into()) + } + capnp::introspect::TypeVariant::Enum(enum_schema) => match field_value { + JsonValue::String(field_value) => { + let enum_schema = capnp::schema::EnumSchema::new(enum_schema); + let Some(enum_value) = enum_schema.get_enumerants()?.iter().find(|e| { + e.get_proto() + .get_name() + .ok() + .and_then(|n| n.to_str().ok()) + .is_some_and(|s| s == field_value) + }) else { + return Err(capnp::Error::failed(format!( + "Invalid enum value '{}' for field {}", + field_value, field_meta.name + ))); + }; + + Ok(capnp::dynamic_value::Reader::Enum( + capnp::dynamic_value::Enum::new( + enum_value.get_ordinal(), + enum_value.get_containing_enum(), + ), + )) + } + JsonValue::Number(enum_value) => { + let enum_schema = capnp::schema::EnumSchema::new(enum_schema); + Ok(capnp::dynamic_value::Reader::Enum( + capnp::dynamic_value::Enum::new(*enum_value as u16, enum_schema), + )) + } + _ => Err(capnp::Error::failed(format!( + "Expected string or number for enum field {}", + field_meta.name + ))), + }, + capnp::introspect::TypeVariant::Data => match field_meta.data_encoding { + // The reason we have this ugly DataBuffer hack is to ensure that we + // can return a Reader from this function whose lifetime is tied to + // the field_value, as there is no other buffer we can use. We don't + // currently support Orphans, but if we did, most of this Reader + // dance could probably be avoided. + DataEncoding::Default => { + let JsonValue::Array(data_value) = field_value else { + return Err(capnp::Error::failed(format!( + "Expected array for data field {}", + field_meta.name + ))); + }; + let mut data = Vec::with_capacity(data_value.len()); + for byte_value in data_value.drain(..) { + let JsonValue::Number(byte_value) = byte_value else { + return Err(capnp::Error::failed(format!( + "Expected number for data byte in field {}", + field_meta.name + ))); + }; + data.push(byte_value as u8); + } + *field_value = JsonValue::DataBuffer(data); + Ok(capnp::dynamic_value::Reader::Data(match field_value { + JsonValue::DataBuffer(ref data) => data.as_slice(), + _ => unreachable!(), + })) + } + DataEncoding::Base64 => { + let JsonValue::String(data_value) = field_value else { + return Err(capnp::Error::failed(format!( + "Expected string for base64 data field {}", + field_meta.name + ))); + }; + *field_value = JsonValue::DataBuffer(base64::decode(data_value)?); + Ok(capnp::dynamic_value::Reader::Data(match field_value { + JsonValue::DataBuffer(ref data) => data.as_slice(), + _ => unreachable!(), + })) + } + DataEncoding::Hex => { + let JsonValue::String(data_value) = field_value else { + return Err(capnp::Error::failed(format!( + "Expected string for hex data field {}", + field_meta.name + ))); + }; + *field_value = JsonValue::DataBuffer(hex::decode(data_value)?); + Ok(capnp::dynamic_value::Reader::Data(match field_value { + JsonValue::DataBuffer(ref data) => data.as_slice(), + _ => unreachable!(), + })) + } + }, + _ => Err(capnp::Error::failed(format!( + "Unsupported primitive type for field {}", + field_meta.name + ))), + } +} + +fn decode_list( + mut field_values: Vec, + mut list_builder: capnp::dynamic_list::Builder, + field_meta: &EncodingOptions, +) -> capnp::Result<()> { + match list_builder.element_type().which() { + capnp::introspect::TypeVariant::Struct(_sub_element_schema) => { + for (i, item_value) in field_values.drain(..).enumerate() { + let JsonValue::Object(mut item_value) = item_value else { + return Err(capnp::Error::failed(format!( + "Expected object for struct list field {}", + field_meta.name + ))); + }; + let struct_builder = list_builder + .reborrow() + .get(i as u32)? + .downcast::(); + decode_struct(&mut item_value, struct_builder, field_meta)?; + } + Ok(()) + } + capnp::introspect::TypeVariant::List(_sub_element_type) => { + for (i, item_value) in field_values.drain(..).enumerate() { + let JsonValue::Array(item_value) = item_value else { + return Err(capnp::Error::failed(format!( + "Expected array for list field {}", + field_meta.name + ))); + }; + let sub_element_builder = list_builder + .reborrow() + .init(i as u32, item_value.len() as u32)? + .downcast::(); + decode_list(item_value, sub_element_builder, field_meta)?; + } + Ok(()) + } + _ => { + for (i, mut item_value) in field_values.drain(..).enumerate() { + list_builder.set( + i as u32, + decode_primitive(&mut item_value, &list_builder.element_type(), field_meta)?, + )?; + } + Ok(()) + } + } +} + +fn decode_struct( + value: &mut HashMap, + mut builder: capnp::dynamic_struct::Builder<'_>, + meta: &EncodingOptions, +) -> capnp::Result<()> { + let field_prefix = if let Some(flatten_options) = &meta.flatten { + std::borrow::Cow::Owned(format!( + "{}{}", + meta.prefix, + flatten_options.get_prefix()?.to_str()? + )) + } else { + std::borrow::Cow::Borrowed("") + }; + + fn decode_member( + mut builder: capnp::dynamic_struct::Builder<'_>, + field: capnp::schema::Field, + field_meta: &EncodingOptions, + value: &mut HashMap, + value_name: &str, + ) -> capnp::Result<()> { + match field.get_type().which() { + capnp::introspect::TypeVariant::Struct(_struct_schema) => { + let struct_builder = builder + .reborrow() + .init(field)? + .downcast::(); + if field_meta.flatten.is_none() { + let field_value = match value.remove(value_name) { + Some(v) => v, + None => return Ok(()), + }; + + let JsonValue::Object(mut field_value) = field_value else { + return Err(capnp::Error::failed(format!( + "Expected object for field {}", + field_meta.name + ))); + }; + decode_struct(&mut field_value, struct_builder, field_meta)?; + } else { + // Flattened struct; pass the JsonValue at this level down + decode_struct(value, struct_builder, field_meta)?; + } + } + capnp::introspect::TypeVariant::List(_element_type) => { + let Some(field_value) = value.remove(value_name) else { + return Ok(()); + }; + + let JsonValue::Array(field_value) = field_value else { + return Err(capnp::Error::failed(format!( + "Expected array for field {}", + field_meta.name + ))); + }; + let list_builder = builder + .reborrow() + .initn(field, field_value.len() as u32)? + .downcast::(); + decode_list(field_value, list_builder, field_meta)?; + } + + capnp::introspect::TypeVariant::AnyPointer => { + return Err(capnp::Error::unimplemented( + "AnyPointer cannot be represented in JSON".into(), + )) + } + capnp::introspect::TypeVariant::Capability => { + return Err(capnp::Error::unimplemented( + "Capability cannot be represented in JSON".into(), + )) + } + + _ => { + let Some(mut field_value) = value.remove(value_name) else { + return Ok(()); + }; + + builder.set( + field, + decode_primitive(&mut field_value, &field.get_type(), field_meta)?, + )?; + } + } + Ok(()) + } + + for field in builder.get_schema().get_non_union_fields()? { + let field_meta = EncodingOptions::from_field(meta.prefix, &field)?; + let field_name = format!("{}{}", field_prefix, field_meta.name); + + decode_member(builder.reborrow(), field, &field_meta, value, &field_name)?; + } + + let struct_discriminator = builder + .get_schema() + .get_annotations()? + .iter() + .find(|a| a.get_id() == json_capnp::discriminator::ID) + .and_then(|annotation| { + annotation + .get_value() + .ok() + .map(|v| v.downcast_struct::()) + }); + let discriminator = meta.discriminator.or(struct_discriminator); + + // FIXME: refactor this to only loop through union memberes once; each + // iteration check if it matches the discriminant, *or* the requisite + // named field is present, then decode and break; + let discriminant = match discriminator { + Some(discriminator) => { + let discriminator_name = if discriminator.has_name() { + discriminator.get_name()?.to_str()? + } else { + meta.name + }; + let field_name = format!("{}{}", field_prefix, discriminator_name); + if let Some(JsonValue::String(discriminant)) = value.remove(&field_name) { + Some(discriminant) + } else { + None + } + } + None => { + // find the first field that exists matching a union field? + let mut discriminant = None; + for field in builder.get_schema().get_union_fields()? { + let field_meta = EncodingOptions::from_field(meta.prefix, &field)?; + let field_name = format!("{}{}", field_prefix, field_meta.name); + if value.contains_key(&field_name) { + discriminant = Some(field_meta.name.to_string()); + break; + } + } + discriminant + } + }; + if let Some(discriminant) = discriminant { + for field in builder.get_schema().get_union_fields()? { + let field_meta = EncodingOptions::from_field(meta.prefix, &field)?; + if field_meta.name != discriminant { + continue; + } + let value_name = if let Some(discriminator) = discriminator { + if discriminator.has_value_name() { + discriminator.get_value_name()?.to_str()? + } else { + field_meta.name + } + } else { + field_meta.name + }; + decode_member(builder.reborrow(), field, &field_meta, value, value_name)?; + break; + } + } + + Ok(()) +} diff --git a/capnp-json/src/encode.rs b/capnp-json/src/encode.rs new file mode 100644 index 000000000..fb6193449 --- /dev/null +++ b/capnp-json/src/encode.rs @@ -0,0 +1,283 @@ +use super::data::{base64, hex}; +use super::json_capnp; +use super::{DataEncoding, EncodingOptions}; + +pub fn serialize_json_to<'reader, W>( + writer: &mut W, + reader: impl Into>, +) -> capnp::Result<()> +where + W: std::io::Write, +{ + let meta = EncodingOptions { + prefix: &std::borrow::Cow::Borrowed(""), + name: "", + flatten: None, + discriminator: None, + data_encoding: DataEncoding::Default, + }; + serialize_value_to(writer, reader.into(), &meta, &mut true) +} + +fn serialize_value_to( + writer: &mut W, + reader: capnp::dynamic_value::Reader<'_>, + meta: &EncodingOptions<'_, '_>, + first: &mut bool, +) -> capnp::Result<()> +where + W: std::io::Write, +{ + match reader { + capnp::dynamic_value::Reader::Void => write!(writer, "null").map_err(|e| e.into()), + capnp::dynamic_value::Reader::Bool(value) => if value { + write!(writer, "true") + } else { + write!(writer, "false") + } + .map_err(|e| e.into()), + capnp::dynamic_value::Reader::Int8(value) => write_signed_number(writer, value as i64), + capnp::dynamic_value::Reader::Int16(value) => write_signed_number(writer, value as i64), + capnp::dynamic_value::Reader::Int32(value) => write_signed_number(writer, value as i64), + capnp::dynamic_value::Reader::Int64(value) => write_signed_number(writer, value), + capnp::dynamic_value::Reader::UInt8(value) => write_unsigned_number(writer, value as u64), + capnp::dynamic_value::Reader::UInt16(value) => write_unsigned_number(writer, value as u64), + capnp::dynamic_value::Reader::UInt32(value) => write_unsigned_number(writer, value as u64), + capnp::dynamic_value::Reader::UInt64(value) => write_unsigned_number(writer, value), + capnp::dynamic_value::Reader::Float32(value) => write_float_number(writer, value as f64), + capnp::dynamic_value::Reader::Float64(value) => write_float_number(writer, value), + capnp::dynamic_value::Reader::Enum(value) => { + if let Some(enumerant) = value.get_enumerant()? { + let value = enumerant + .get_annotations()? + .iter() + .find(|a| a.get_id() == json_capnp::name::ID) + .and_then(|a| { + a.get_value() + .ok() + .map(|v| v.downcast::().to_str()) + }) + .unwrap_or(enumerant.get_proto().get_name()?.to_str()); + write_string(writer, value?) + } else { + write_unsigned_number(writer, value.get_value() as u64) + } + } + capnp::dynamic_value::Reader::Text(reader) => write_string(writer, reader.to_str()?), + capnp::dynamic_value::Reader::Data(data) => write_data(writer, data, meta.data_encoding), + capnp::dynamic_value::Reader::Struct(reader) => write_object(writer, reader, meta, first), + capnp::dynamic_value::Reader::List(reader) => write_array(writer, reader.iter(), meta), + capnp::dynamic_value::Reader::AnyPointer(_) => Err(capnp::Error::unimplemented( + "AnyPointer cannot be represented in JSON".into(), + )), + capnp::dynamic_value::Reader::Capability(_) => Err(capnp::Error::unimplemented( + "Capability cannot be represented in JSON".into(), + )), + } +} + +// TODO: use capnp::io::Write ? +fn write_unsigned_number(writer: &mut W, value: u64) -> capnp::Result<()> { + write!(writer, "{}", value)?; + Ok(()) +} +fn write_signed_number(writer: &mut W, value: i64) -> capnp::Result<()> { + write!(writer, "{}", value)?; + Ok(()) +} + +fn write_float_number(writer: &mut W, value: f64) -> capnp::Result<()> { + // From the C++ codec comments: + // Inf, -inf and NaN are not allowed in the JSON spec. Storing into string. + + if value.is_finite() { + write!(writer, "{}", value)?; + } else if value.is_nan() { + write_string(writer, "NaN")?; + } else if value.is_infinite() { + if value.is_sign_positive() { + write_string(writer, "Infinity")?; + } else { + write_string(writer, "-Infinity")?; + } + } + Ok(()) +} + +fn write_string(writer: &mut W, value: &str) -> capnp::Result<()> { + write!(writer, "\"")?; + for c in value.chars() { + match c { + '\"' => write!(writer, "\\\"")?, + '\\' => write!(writer, "\\\\")?, + '\n' => write!(writer, "\\n")?, + '\r' => write!(writer, "\\r")?, + '\t' => write!(writer, "\\t")?, + '\u{08}' => write!(writer, "\\b")?, + '\u{0C}' => write!(writer, "\\f")?, + c if c.is_control() => write!(writer, "\\u{:04x}", c as u32)?, + c => write!(writer, "{}", c)?, + } + } + write!(writer, "\"")?; + Ok(()) +} + +fn write_array<'reader, W: std::io::Write, I>( + writer: &mut W, + items: I, + meta: &EncodingOptions, +) -> capnp::Result<()> +where + I: Iterator>>, +{ + write!(writer, "[")?; + let mut first = true; + for item in items { + if !first { + write!(writer, ",")?; + } + first = false; + serialize_value_to(writer, item?, meta, &mut true)?; + } + write!(writer, "]")?; + Ok(()) +} + +fn write_object<'reader, W: std::io::Write>( + writer: &mut W, + reader: capnp::dynamic_struct::Reader<'reader>, + meta: &EncodingOptions<'_, '_>, + first: &mut bool, +) -> capnp::Result<()> { + let (flatten, field_prefix) = if let Some(flatten_options) = &meta.flatten { + ( + true, + std::borrow::Cow::Owned(format!( + "{}{}", + meta.prefix, + flatten_options.get_prefix()?.to_str()? + )), + ) + } else { + (false, std::borrow::Cow::Borrowed("")) + }; + + let mut my_first = true; + + let first = if !flatten { + write!(writer, "{{")?; + &mut my_first + } else { + first + }; + for field in reader.get_schema().get_non_union_fields()? { + if !reader.has(field)? { + continue; + } + let field_meta = EncodingOptions::from_field(&field_prefix, &field)?; + if field_meta.flatten.is_none() { + if !*first { + write!(writer, ",")?; + } + *first = false; + write_string( + writer, + format!("{}{}", field_prefix, field_meta.name).as_str(), + )?; + write!(writer, ":")?; + } + let field_value = reader.get(field)?; + serialize_value_to(writer, field_value, &field_meta, first)?; + } + + // Comment copied verbatim from the Cap'n Proto C++ implementation: + // There are two cases of unions: + // * Named unions, which are special cases of named groups. In this case, the union may be + // annotated by annotating the field. In this case, we receive a non-null `discriminator` + // as a constructor parameter, and schemaProto.getAnnotations() must be empty because + // it's not possible to annotate a group's type (because the type is anonymous). + // * Unnamed unions, of which there can only be one in any particular scope. In this case, + // the parent struct type itself is annotated. + // So if we received `null` as the constructor parameter, check for annotations on the struct + // type. + let struct_discriminator = reader + .get_schema() + .get_annotations()? + .iter() + .find(|a| a.get_id() == json_capnp::discriminator::ID) + .and_then(|annotation| { + annotation + .get_value() + .ok() + .map(|v| v.downcast_struct::()) + }); + let discriminator = meta.discriminator.or(struct_discriminator); + + if let Some(active_union_member) = reader.which()? { + let active_union_member_meta = + EncodingOptions::from_field(&field_prefix, &active_union_member)?; + if reader.has(active_union_member)? { + let mut value_name = active_union_member_meta.name; + if let Some(discriminator) = discriminator { + if !*first { + write!(writer, ",")?; + } + *first = false; + let discriminator_name = if discriminator.has_name() { + discriminator.get_name()?.to_str()? + } else { + meta.name + }; + if discriminator.has_value_name() { + value_name = discriminator.get_value_name()?.to_str()?; + } + + write_string( + writer, + format!("{}{}", field_prefix, discriminator_name).as_str(), + )?; + write!(writer, ":")?; + write_string(writer, active_union_member_meta.name)?; + } + if active_union_member_meta.flatten.is_none() { + if !*first { + write!(writer, ",")?; + } + *first = false; + write_string(writer, format!("{}{}", field_prefix, value_name).as_str())?; + write!(writer, ":")?; + } + let field_value = reader.get(active_union_member)?; + serialize_value_to(writer, field_value, &active_union_member_meta, first)?; + } + } + if !flatten { + write!(writer, "}}")?; + } + Ok(()) +} + +fn write_data( + writer: &mut W, + data: capnp::data::Reader<'_>, + encoding: DataEncoding, +) -> capnp::Result<()> { + match encoding { + DataEncoding::Default => { + write!(writer, "[")?; + let mut first = true; + for byte in data.iter() { + if !first { + write!(writer, ",")?; + } + first = false; + write!(writer, "{}", byte)?; + } + write!(writer, "]")?; + Ok(()) + } + DataEncoding::Base64 => write_string(writer, base64::encode(data).as_str()), + DataEncoding::Hex => write_string(writer, hex::encode(data).as_str()), + } +} diff --git a/capnp-json/src/json.rs b/capnp-json/src/json.rs deleted file mode 100644 index c11e87807..000000000 --- a/capnp-json/src/json.rs +++ /dev/null @@ -1,1287 +0,0 @@ -// TODO: Turn these write_* into an encoding trait that can be implemented for -// different Reader types, in particular for particualr Reader types? -// In particular, encoding Data as an array of bytes is compatible with upstream -// encoder, but still dumb as bricks, probably. -// -// e.g. -// impl ToJson for capnp::dynamic_value::Reader<'_> { ... } -// impl ToJson for mycapnp::my_capnp::my_struct::Reader<'_> { ... } // more specific -// -// does that work in rust without specdialization? -// - -pub fn to_json<'reader>( - reader: impl Into>, -) -> capnp::Result { - let mut writer = std::io::Cursor::new(Vec::with_capacity(4096)); - encode::serialize_json_to(&mut writer, reader)?; - String::from_utf8(writer.into_inner()).map_err(|e| e.into()) -} - -pub fn from_json<'segments>( - json: &str, - builder: impl Into>, -) -> capnp::Result<()> { - let capnp::dynamic_value::Builder::Struct(builder) = builder.into() else { - return Err(capnp::Error::failed( - "Top-level JSON value must be an object".into(), - )); - }; - decode::parse(json, builder) -} - -use crate::json_capnp; - -#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)] -enum DataEncoding { - #[default] - Default, - Base64, - Hex, -} - -#[derive(Debug)] -struct EncodingOptions<'schema, 'prefix> { - prefix: &'prefix std::borrow::Cow<'schema, str>, - name: &'schema str, - flatten: Option>, - discriminator: Option>, - data_encoding: DataEncoding, -} - -impl<'schema, 'prefix> EncodingOptions<'schema, 'prefix> { - fn from_field( - prefix: &'prefix std::borrow::Cow<'schema, str>, - field: &capnp::schema::Field, - ) -> capnp::Result { - let mut options = Self { - prefix, - name: field.get_proto().get_name()?.to_str()?, - flatten: None, - discriminator: None, - data_encoding: DataEncoding::Default, - }; - - for anno in field.get_annotations()?.iter() { - match anno.get_id() { - json_capnp::name::ID => { - options.name = anno - .get_value()? - .downcast::() - .to_str()?; - } - json_capnp::base64::ID => { - if options.data_encoding != DataEncoding::Default { - return Err(capnp::Error::failed( - "Cannot specify both base64 and hex annotations on the same field" - .into(), - )); - } - options.data_encoding = DataEncoding::Base64; - } - json_capnp::hex::ID => { - if options.data_encoding != DataEncoding::Default { - return Err(capnp::Error::failed( - "Cannot specify both base64 and hex annotations on the same field" - .into(), - )); - } - options.data_encoding = DataEncoding::Hex; - } - json_capnp::flatten::ID => { - options.flatten = Some( - anno.get_value()? - .downcast_struct::(), - ); - } - json_capnp::discriminator::ID => { - options.discriminator = Some( - anno.get_value()? - .downcast_struct::(), - ); - } - _ => {} - } - } - if options.data_encoding != DataEncoding::Default { - let mut element_type = field.get_type(); - while let capnp::introspect::TypeVariant::List(sub_element_type) = element_type.which() - { - element_type = sub_element_type; - } - if !matches!(element_type.which(), capnp::introspect::TypeVariant::Data) { - return Err(capnp::Error::failed( - "base64/hex annotation can only be applied to Data fields".into(), - )); - } - } - Ok(options) - } -} - -// Serialisation - -pub mod encode { - use super::*; - - pub fn serialize_json_to<'reader, W>( - writer: &mut W, - reader: impl Into>, - ) -> capnp::Result<()> - where - W: std::io::Write, - { - let meta = EncodingOptions { - prefix: &std::borrow::Cow::Borrowed(""), - name: "", - flatten: None, - discriminator: None, - data_encoding: DataEncoding::Default, - }; - serialize_value_to(writer, reader.into(), &meta, &mut true) - } - - fn serialize_value_to( - writer: &mut W, - reader: capnp::dynamic_value::Reader<'_>, - meta: &EncodingOptions<'_, '_>, - first: &mut bool, - ) -> capnp::Result<()> - where - W: std::io::Write, - { - match reader { - capnp::dynamic_value::Reader::Void => write!(writer, "null").map_err(|e| e.into()), - capnp::dynamic_value::Reader::Bool(value) => if value { - write!(writer, "true") - } else { - write!(writer, "false") - } - .map_err(|e| e.into()), - capnp::dynamic_value::Reader::Int8(value) => write_signed_number(writer, value as i64), - capnp::dynamic_value::Reader::Int16(value) => write_signed_number(writer, value as i64), - capnp::dynamic_value::Reader::Int32(value) => write_signed_number(writer, value as i64), - capnp::dynamic_value::Reader::Int64(value) => write_signed_number(writer, value), - capnp::dynamic_value::Reader::UInt8(value) => { - write_unsigned_number(writer, value as u64) - } - capnp::dynamic_value::Reader::UInt16(value) => { - write_unsigned_number(writer, value as u64) - } - capnp::dynamic_value::Reader::UInt32(value) => { - write_unsigned_number(writer, value as u64) - } - capnp::dynamic_value::Reader::UInt64(value) => write_unsigned_number(writer, value), - capnp::dynamic_value::Reader::Float32(value) => { - write_float_number(writer, value as f64) - } - capnp::dynamic_value::Reader::Float64(value) => write_float_number(writer, value), - capnp::dynamic_value::Reader::Enum(value) => { - if let Some(enumerant) = value.get_enumerant()? { - let value = enumerant - .get_annotations()? - .iter() - .find(|a| a.get_id() == json_capnp::name::ID) - .and_then(|a| { - a.get_value() - .ok() - .map(|v| v.downcast::().to_str()) - }) - .unwrap_or(enumerant.get_proto().get_name()?.to_str()); - write_string(writer, value?) - } else { - write_unsigned_number(writer, value.get_value() as u64) - } - } - capnp::dynamic_value::Reader::Text(reader) => write_string(writer, reader.to_str()?), - capnp::dynamic_value::Reader::Data(data) => { - write_data(writer, data, meta.data_encoding) - } - capnp::dynamic_value::Reader::Struct(reader) => { - write_object(writer, reader, meta, first) - } - capnp::dynamic_value::Reader::List(reader) => write_array(writer, reader.iter(), meta), - capnp::dynamic_value::Reader::AnyPointer(_) => Err(capnp::Error::unimplemented( - "AnyPointer cannot be represented in JSON".into(), - )), - capnp::dynamic_value::Reader::Capability(_) => Err(capnp::Error::unimplemented( - "Capability cannot be represented in JSON".into(), - )), - } - } - - // TODO: use capnp::io::Write ? - fn write_unsigned_number(writer: &mut W, value: u64) -> capnp::Result<()> { - write!(writer, "{}", value)?; - Ok(()) - } - fn write_signed_number(writer: &mut W, value: i64) -> capnp::Result<()> { - write!(writer, "{}", value)?; - Ok(()) - } - - fn write_float_number(writer: &mut W, value: f64) -> capnp::Result<()> { - // From the C++ codec comments: - // Inf, -inf and NaN are not allowed in the JSON spec. Storing into string. - - if value.is_finite() { - write!(writer, "{}", value)?; - } else if value.is_nan() { - write_string(writer, "NaN")?; - } else if value.is_infinite() { - if value.is_sign_positive() { - write_string(writer, "Infinity")?; - } else { - write_string(writer, "-Infinity")?; - } - } - Ok(()) - } - - fn write_string(writer: &mut W, value: &str) -> capnp::Result<()> { - write!(writer, "\"")?; - for c in value.chars() { - match c { - '\"' => write!(writer, "\\\"")?, - '\\' => write!(writer, "\\\\")?, - '\n' => write!(writer, "\\n")?, - '\r' => write!(writer, "\\r")?, - '\t' => write!(writer, "\\t")?, - '\u{08}' => write!(writer, "\\b")?, - '\u{0C}' => write!(writer, "\\f")?, - c if c.is_control() => write!(writer, "\\u{:04x}", c as u32)?, - c => write!(writer, "{}", c)?, - } - } - write!(writer, "\"")?; - Ok(()) - } - - fn write_array<'reader, W: std::io::Write, I>( - writer: &mut W, - items: I, - meta: &EncodingOptions, - ) -> capnp::Result<()> - where - I: Iterator>>, - { - write!(writer, "[")?; - let mut first = true; - for item in items { - if !first { - write!(writer, ",")?; - } - first = false; - serialize_value_to(writer, item?, meta, &mut true)?; - } - write!(writer, "]")?; - Ok(()) - } - - fn write_object<'reader, W: std::io::Write>( - writer: &mut W, - reader: capnp::dynamic_struct::Reader<'reader>, - meta: &EncodingOptions<'_, '_>, - first: &mut bool, - ) -> capnp::Result<()> { - let (flatten, field_prefix) = if let Some(flatten_options) = &meta.flatten { - ( - true, - std::borrow::Cow::Owned(format!( - "{}{}", - meta.prefix, - flatten_options.get_prefix()?.to_str()? - )), - ) - } else { - (false, std::borrow::Cow::Borrowed("")) - }; - - let mut my_first = true; - - let first = if !flatten { - write!(writer, "{{")?; - &mut my_first - } else { - first - }; - for field in reader.get_schema().get_non_union_fields()? { - if !reader.has(field)? { - continue; - } - let field_meta = EncodingOptions::from_field(&field_prefix, &field)?; - if field_meta.flatten.is_none() { - if !*first { - write!(writer, ",")?; - } - *first = false; - write_string( - writer, - format!("{}{}", field_prefix, field_meta.name).as_str(), - )?; - write!(writer, ":")?; - } - let field_value = reader.get(field)?; - serialize_value_to(writer, field_value, &field_meta, first)?; - } - - // Comment copied verbatim from the Cap'n Proto C++ implementation: - // There are two cases of unions: - // * Named unions, which are special cases of named groups. In this case, the union may be - // annotated by annotating the field. In this case, we receive a non-null `discriminator` - // as a constructor parameter, and schemaProto.getAnnotations() must be empty because - // it's not possible to annotate a group's type (because the type is anonymous). - // * Unnamed unions, of which there can only be one in any particular scope. In this case, - // the parent struct type itself is annotated. - // So if we received `null` as the constructor parameter, check for annotations on the struct - // type. - let struct_discriminator = reader - .get_schema() - .get_annotations()? - .iter() - .find(|a| a.get_id() == json_capnp::discriminator::ID) - .and_then(|annotation| { - annotation - .get_value() - .ok() - .map(|v| v.downcast_struct::()) - }); - let discriminator = meta.discriminator.or(struct_discriminator); - - if let Some(active_union_member) = reader.which()? { - let active_union_member_meta = - EncodingOptions::from_field(&field_prefix, &active_union_member)?; - if reader.has(active_union_member)? { - let mut value_name = active_union_member_meta.name; - if let Some(discriminator) = discriminator { - // write out the discriminator - if !*first { - write!(writer, ",")?; - } - *first = false; - let discriminator_name = if discriminator.has_name() { - discriminator.get_name()?.to_str()? - } else { - meta.name - }; - if discriminator.has_value_name() { - value_name = discriminator.get_value_name()?.to_str()?; - } - - write_string( - writer, - format!("{}{}", field_prefix, discriminator_name).as_str(), - )?; - write!(writer, ":")?; - write_string(writer, active_union_member_meta.name)?; - } - if active_union_member_meta.flatten.is_none() { - if !*first { - write!(writer, ",")?; - } - *first = false; - write_string(writer, format!("{}{}", field_prefix, value_name).as_str())?; - write!(writer, ":")?; - } - let field_value = reader.get(active_union_member)?; - serialize_value_to(writer, field_value, &active_union_member_meta, first)?; - } - } - if !flatten { - write!(writer, "}}")?; - } - Ok(()) - } - - fn write_data( - writer: &mut W, - data: capnp::data::Reader<'_>, - encoding: DataEncoding, - ) -> capnp::Result<()> { - match encoding { - DataEncoding::Default => { - write!(writer, "[")?; - let mut first = true; - for byte in data.iter() { - if !first { - write!(writer, ",")?; - } - first = false; - write!(writer, "{}", byte)?; - } - write!(writer, "]")?; - Ok(()) - } - DataEncoding::Base64 => write_string(writer, base64::encode(data).as_str()), - DataEncoding::Hex => write_string(writer, hex::encode(data).as_str()), - } - } -} - -// Deserialisation - -pub mod decode { - use super::*; - - enum ParseError { - UnexpectedEndOfInput, - InvalidToken(char), - Other(String), - } - - impl From for capnp::Error { - fn from(err: ParseError) -> Self { - match err { - ParseError::UnexpectedEndOfInput => { - capnp::Error::failed("Unexpected end of input while parsing JSON".into()) - } - ParseError::InvalidToken(c) => { - capnp::Error::failed(format!("Invalid token '{c}' while parsing JSON")) - } - // TODO: Use better values here? - ParseError::Other(msg) => capnp::Error::failed(msg), - } - } - } - - use std::collections::HashMap; - - // FIXME: The String valued below could be Cow<'input, str> as they only really - // need to be allocated if the input contains escaped characters. That would be - // a little more tricky lower down, but not by a lot. - enum JsonValue { - Null, - Boolean(bool), - Number(f64), - String(String), - Array(Vec), - Object(HashMap), - - DataBuffer(Vec), // HACK: This is so we have somewhere to store the data - // temporarily when we are decoding data fields into - // Readers - } - - struct Parser - where - I: Iterator, - { - // FIXME: By using an iter over char here, we restrict ourselves to not - // being able to use string slices for must of the parsing. THis is piggy. - // It would be better to just have a &str and an index probably. - input_iter: std::iter::Peekable>, - } - - impl Parser - where - I: Iterator, - { - fn new(iter: I) -> Self { - Self { - input_iter: iter.fuse().peekable(), - } - } - - /// Advance past any whitespace and peek at next value - fn peek_next(&mut self) -> Option { - self.discard_whitespace(); - self.peek() - } - - /// Peek at the current value - fn peek(&mut self) -> Option { - self.input_iter.peek().copied() - } - - /// Consume the current value - fn advance(&mut self) -> capnp::Result { - self.input_iter - .next() - .ok_or(ParseError::UnexpectedEndOfInput.into()) - } - - /// Consume the current value if it matches `c`, otherwise error - fn consume(&mut self, c: char) -> capnp::Result { - match self.advance()? { - p if p == c => Ok(p), - p => Err(ParseError::InvalidToken(p).into()), - } - } - - /// Advance past any whitespace and consume the current value if it matches `c`, otherwise error - fn consume_next(&mut self, c: char) -> capnp::Result { - self.discard_whitespace(); - match self.advance()? { - p if p == c => Ok(p), - p => Err(ParseError::InvalidToken(p).into()), - } - } - - fn discard_whitespace(&mut self) { - while let Some(c) = self.peek() { - if c.is_whitespace() { - self.advance().ok(); - } else { - break; - } - } - } - - fn parse_value(&mut self) -> capnp::Result { - match self.peek_next() { - None => Err(ParseError::UnexpectedEndOfInput.into()), - Some('n') => { - self.advance()?; - self.consume('u')?; - self.consume('l')?; - self.consume('l')?; - Ok(JsonValue::Null) - } - Some('t') => { - self.advance()?; - self.consume('r')?; - self.consume('u')?; - self.consume('e')?; - Ok(JsonValue::Boolean(true)) - } - Some('f') => { - self.advance()?; - self.consume('a')?; - self.consume('l')?; - self.consume('s')?; - self.consume('e')?; - Ok(JsonValue::Boolean(false)) - } - Some('\"') => Ok(JsonValue::String(self.parse_string()?)), - Some('0'..='9') | Some('-') => { - let num_str = self.parse_number()?; - let num = num_str - .parse::() - .map_err(|e| ParseError::Other(format!("Invalid number format: {}", e)))?; - Ok(JsonValue::Number(num)) - } - Some('[') => { - self.advance()?; - let mut items = Vec::new(); - let mut require_comma = false; - while self.peek_next().is_some_and(|c| c != ']') { - if require_comma { - self.consume(',')?; - } - require_comma = true; - let item = self.parse_value()?; - items.push(item); - } - self.consume_next(']')?; - Ok(JsonValue::Array(items)) - } - Some('{') => { - self.advance()?; - let mut members = HashMap::new(); - let mut require_comma = false; - while self.peek_next().is_some_and(|c| c != '}') { - if require_comma { - self.consume(',')?; - } - require_comma = true; - let key = self.parse_string()?; - self.consume_next(':')?; - let value = self.parse_value()?; - if members.insert(key.clone(), value).is_some() { - return Err(ParseError::Other(format!( - "Duplicate key in object: {}", - key - )) - .into()); - } - } - self.consume_next('}')?; - Ok(JsonValue::Object(members)) - } - Some(c) => Err(ParseError::InvalidToken(c).into()), - } - } - - fn parse_string(&mut self) -> capnp::Result { - self.consume_next('\"')?; - let mut result = String::new(); - loop { - let c = self.advance()?; - match c { - '\"' => return Ok(result), - '\\' => { - let escaped = self.advance()?; - match escaped { - '\"' => result.push('\"'), - '\\' => result.push('\\'), - '/' => result.push('/'), - 'b' => result.push('\u{08}'), - 'f' => result.push('\u{0C}'), - 'n' => result.push('\n'), - 'r' => result.push('\r'), - 't' => result.push('\t'), - 'u' => { - let mut hex = String::new(); - for _ in 0..4 { - hex.push(self.advance()?); - } - let code_point = u16::from_str_radix(&hex, 16).map_err(|_| { - ParseError::Other(format!("Invalid unicode escape: \\u{}", hex)) - })?; - if let Some(ch) = std::char::from_u32(code_point as u32) { - result.push(ch); - } else { - return Err(ParseError::Other(format!( - "Invalid unicode code point: \\u{}", - hex - )) - .into()); - } - } - other => { - return Err(ParseError::Other(format!( - "Invalid escape character: \\{}", - other - )) - .into()); - } - } - } - other => result.push(other), - } - } - } - - fn parse_number(&mut self) -> capnp::Result { - let mut num_str = String::new(); - if self.peek_next().is_some_and(|c| c == '-') { - num_str.push(self.advance()?); - } - while self.peek().is_some_and(|c| c.is_ascii_digit()) { - num_str.push(self.advance()?); - } - if self.peek().is_some_and(|c| c == '.') { - num_str.push(self.advance()?); - while self.peek().is_some_and(|c| c.is_ascii_digit()) { - num_str.push(self.advance()?); - } - } - if self.peek().is_some_and(|c| c == 'e' || c == 'E') { - num_str.push(self.advance()?); - if self.peek().is_some_and(|c| c == '+' || c == '-') { - num_str.push(self.advance()?); - } - while self.peek().is_some_and(|c| c.is_ascii_digit()) { - num_str.push(self.advance()?); - } - } - Ok(num_str) - } - } - - pub fn parse(json: &str, builder: capnp::dynamic_struct::Builder<'_>) -> capnp::Result<()> { - let mut parser = Parser::new(json.chars()); - let value = parser.parse_value()?; - let meta = EncodingOptions { - prefix: &std::borrow::Cow::Borrowed(""), - name: "", - flatten: None, - discriminator: None, - data_encoding: DataEncoding::Default, - }; - let JsonValue::Object(mut value) = value else { - return Err(capnp::Error::failed( - "Top-level JSON value must be an object".into(), - )); - }; - decode_struct(&mut value, builder, &meta) - } - - fn decode_primitive<'json, 'meta>( - field_value: &'json mut JsonValue, - field_type: &'meta capnp::introspect::Type, - field_meta: &'meta EncodingOptions, - ) -> capnp::Result> { - match field_type.which() { - capnp::introspect::TypeVariant::Void => { - if !matches!(field_value, JsonValue::Null) { - Err(capnp::Error::failed(format!( - "Expected null for void field {}", - field_meta.name - ))) - } else { - Ok(capnp::dynamic_value::Reader::Void) - } - } - capnp::introspect::TypeVariant::Bool => { - let JsonValue::Boolean(field_value) = field_value else { - return Err(capnp::Error::failed(format!( - "Expected boolean for field {}", - field_meta.name - ))); - }; - Ok((*field_value).into()) - } - capnp::introspect::TypeVariant::Int8 => { - let JsonValue::Number(field_value) = field_value else { - return Err(capnp::Error::failed(format!( - "Expected number for field {}", - field_meta.name - ))); - }; - Ok((*field_value as i8).into()) - } - capnp::introspect::TypeVariant::Int16 => { - let JsonValue::Number(field_value) = field_value else { - return Err(capnp::Error::failed(format!( - "Expected number for field {}", - field_meta.name - ))); - }; - Ok((*field_value as i16).into()) - } - capnp::introspect::TypeVariant::Int32 => { - let JsonValue::Number(field_value) = field_value else { - return Err(capnp::Error::failed(format!( - "Expected number for field {}", - field_meta.name - ))); - }; - Ok((*field_value as i32).into()) - } - capnp::introspect::TypeVariant::Int64 => { - let JsonValue::Number(field_value) = field_value else { - return Err(capnp::Error::failed(format!( - "Expected number for field {}", - field_meta.name - ))); - }; - Ok((*field_value as i64).into()) - } - capnp::introspect::TypeVariant::UInt8 => { - let JsonValue::Number(field_value) = field_value else { - return Err(capnp::Error::failed(format!( - "Expected number for field {}", - field_meta.name - ))); - }; - Ok((*field_value as u8).into()) - } - capnp::introspect::TypeVariant::UInt16 => { - let JsonValue::Number(field_value) = field_value else { - return Err(capnp::Error::failed(format!( - "Expected number for field {}", - field_meta.name - ))); - }; - Ok((*field_value as u16).into()) - } - capnp::introspect::TypeVariant::UInt32 => { - let JsonValue::Number(field_value) = field_value else { - return Err(capnp::Error::failed(format!( - "Expected number for field {}", - field_meta.name - ))); - }; - Ok((*field_value as u32).into()) - } - capnp::introspect::TypeVariant::UInt64 => { - let JsonValue::Number(field_value) = field_value else { - return Err(capnp::Error::failed(format!( - "Expected number for field {}", - field_meta.name - ))); - }; - Ok((*field_value as u64).into()) - } - capnp::introspect::TypeVariant::Float32 => { - let field_value = match field_value { - JsonValue::Number(field_value) => *field_value as f32, - JsonValue::String(field_value) => match field_value.as_str() { - "NaN" => f32::NAN, - "Infinity" => f32::INFINITY, - "-Infinity" => f32::NEG_INFINITY, - _ => { - return Err(capnp::Error::failed(format!( - "Expected number for field {}", - field_meta.name - ))); - } - }, - _ => { - return Err(capnp::Error::failed(format!( - "Expected number for field {}", - field_meta.name - ))); - } - }; - Ok(field_value.into()) - } - capnp::introspect::TypeVariant::Float64 => { - let field_value = match field_value { - JsonValue::Number(field_value) => *field_value, - JsonValue::String(field_value) => match field_value.as_str() { - "NaN" => f64::NAN, - "Infinity" => f64::INFINITY, - "-Infinity" => f64::NEG_INFINITY, - _ => { - return Err(capnp::Error::failed(format!( - "Expected number for field {}", - field_meta.name - ))); - } - }, - _ => { - return Err(capnp::Error::failed(format!( - "Expected number for field {}", - field_meta.name - ))); - } - }; - Ok(field_value.into()) - } - capnp::introspect::TypeVariant::Text => { - let JsonValue::String(field_value) = field_value else { - return Err(capnp::Error::failed(format!( - "Expected string for field {}", - field_meta.name - ))); - }; - Ok((*field_value.as_str()).into()) - } - capnp::introspect::TypeVariant::Enum(enum_schema) => match field_value { - JsonValue::String(field_value) => { - let enum_schema = capnp::schema::EnumSchema::new(enum_schema); - let Some(enum_value) = enum_schema.get_enumerants()?.iter().find(|e| { - e.get_proto() - .get_name() - .ok() - .and_then(|n| n.to_str().ok()) - .is_some_and(|s| s == field_value) - }) else { - return Err(capnp::Error::failed(format!( - "Invalid enum value '{}' for field {}", - field_value, field_meta.name - ))); - }; - - Ok(capnp::dynamic_value::Reader::Enum( - capnp::dynamic_value::Enum::new( - enum_value.get_ordinal(), - enum_value.get_containing_enum(), - ), - )) - } - JsonValue::Number(enum_value) => { - let enum_schema = capnp::schema::EnumSchema::new(enum_schema); - Ok(capnp::dynamic_value::Reader::Enum( - capnp::dynamic_value::Enum::new(*enum_value as u16, enum_schema), - )) - } - _ => Err(capnp::Error::failed(format!( - "Expected string or number for enum field {}", - field_meta.name - ))), - }, - capnp::introspect::TypeVariant::Data => match field_meta.data_encoding { - // The reason we have this ugly DataBuffer hack is to ensure that we - // can return a Reader from this function whose lifetime is tied to - // the field_value, as there is no other buffer we can use. We don't - // currently support Orphans, but if we did, most of this Reader - // dance could probably be avoided. - DataEncoding::Default => { - let JsonValue::Array(data_value) = field_value else { - return Err(capnp::Error::failed(format!( - "Expected array for data field {}", - field_meta.name - ))); - }; - let mut data = Vec::with_capacity(data_value.len()); - for byte_value in data_value.drain(..) { - let JsonValue::Number(byte_value) = byte_value else { - return Err(capnp::Error::failed(format!( - "Expected number for data byte in field {}", - field_meta.name - ))); - }; - data.push(byte_value as u8); - } - *field_value = JsonValue::DataBuffer(data); - Ok(capnp::dynamic_value::Reader::Data(match field_value { - JsonValue::DataBuffer(ref data) => data.as_slice(), - _ => unreachable!(), - })) - } - DataEncoding::Base64 => { - let JsonValue::String(data_value) = field_value else { - return Err(capnp::Error::failed(format!( - "Expected string for base64 data field {}", - field_meta.name - ))); - }; - *field_value = JsonValue::DataBuffer(base64::decode(data_value)?); - Ok(capnp::dynamic_value::Reader::Data(match field_value { - JsonValue::DataBuffer(ref data) => data.as_slice(), - _ => unreachable!(), - })) - } - DataEncoding::Hex => { - let JsonValue::String(data_value) = field_value else { - return Err(capnp::Error::failed(format!( - "Expected string for hex data field {}", - field_meta.name - ))); - }; - *field_value = JsonValue::DataBuffer(hex::decode(data_value)?); - Ok(capnp::dynamic_value::Reader::Data(match field_value { - JsonValue::DataBuffer(ref data) => data.as_slice(), - _ => unreachable!(), - })) - } - }, - _ => Err(capnp::Error::failed(format!( - "Unsupported primitive type for field {}", - field_meta.name - ))), - } - } - - fn decode_list( - mut field_values: Vec, - mut list_builder: capnp::dynamic_list::Builder, - field_meta: &EncodingOptions, - ) -> capnp::Result<()> { - match list_builder.element_type().which() { - capnp::introspect::TypeVariant::Struct(_sub_element_schema) => { - for (i, item_value) in field_values.drain(..).enumerate() { - let JsonValue::Object(mut item_value) = item_value else { - return Err(capnp::Error::failed(format!( - "Expected object for struct list field {}", - field_meta.name - ))); - }; - let struct_builder = list_builder - .reborrow() - .get(i as u32)? - .downcast::(); - decode_struct(&mut item_value, struct_builder, field_meta)?; - } - Ok(()) - } - capnp::introspect::TypeVariant::List(_sub_element_type) => { - for (i, item_value) in field_values.drain(..).enumerate() { - let JsonValue::Array(item_value) = item_value else { - return Err(capnp::Error::failed(format!( - "Expected array for list field {}", - field_meta.name - ))); - }; - let sub_element_builder = list_builder - .reborrow() - .init(i as u32, item_value.len() as u32)? - .downcast::(); - decode_list(item_value, sub_element_builder, field_meta)?; - } - Ok(()) - } - _ => { - for (i, mut item_value) in field_values.drain(..).enumerate() { - list_builder.set( - i as u32, - decode_primitive( - &mut item_value, - &list_builder.element_type(), - field_meta, - )?, - )?; - } - Ok(()) - } - } - } - - fn decode_struct( - value: &mut HashMap, - mut builder: capnp::dynamic_struct::Builder<'_>, - meta: &EncodingOptions, - ) -> capnp::Result<()> { - let field_prefix = if let Some(flatten_options) = &meta.flatten { - std::borrow::Cow::Owned(format!( - "{}{}", - meta.prefix, - flatten_options.get_prefix()?.to_str()? - )) - } else { - std::borrow::Cow::Borrowed("") - }; - - fn decode_member( - mut builder: capnp::dynamic_struct::Builder<'_>, - field: capnp::schema::Field, - field_meta: &EncodingOptions, - value: &mut HashMap, - value_name: &str, - ) -> capnp::Result<()> { - match field.get_type().which() { - capnp::introspect::TypeVariant::Struct(_struct_schema) => { - let struct_builder = builder - .reborrow() - .init(field)? - .downcast::(); - if field_meta.flatten.is_none() { - let field_value = match value.remove(value_name) { - Some(v) => v, - None => return Ok(()), - }; - - let JsonValue::Object(mut field_value) = field_value else { - return Err(capnp::Error::failed(format!( - "Expected object for field {}", - field_meta.name - ))); - }; - decode_struct(&mut field_value, struct_builder, field_meta)?; - } else { - // Flattened struct; pass the JsonValue at this level down - decode_struct(value, struct_builder, field_meta)?; - } - } - capnp::introspect::TypeVariant::List(_element_type) => { - let Some(field_value) = value.remove(value_name) else { - return Ok(()); - }; - - let JsonValue::Array(field_value) = field_value else { - return Err(capnp::Error::failed(format!( - "Expected array for field {}", - field_meta.name - ))); - }; - let list_builder = builder - .reborrow() - .initn(field, field_value.len() as u32)? - .downcast::(); - decode_list(field_value, list_builder, field_meta)?; - } - - capnp::introspect::TypeVariant::AnyPointer => { - return Err(capnp::Error::unimplemented( - "AnyPointer cannot be represented in JSON".into(), - )) - } - capnp::introspect::TypeVariant::Capability => { - return Err(capnp::Error::unimplemented( - "Capability cannot be represented in JSON".into(), - )) - } - - _ => { - let Some(mut field_value) = value.remove(value_name) else { - return Ok(()); - }; - - builder.set( - field, - decode_primitive(&mut field_value, &field.get_type(), field_meta)?, - )?; - } - } - Ok(()) - } - - for field in builder.get_schema().get_non_union_fields()? { - let field_meta = EncodingOptions::from_field(meta.prefix, &field)?; - let field_name = format!("{}{}", field_prefix, field_meta.name); - - decode_member(builder.reborrow(), field, &field_meta, value, &field_name)?; - } - - let struct_discriminator = builder - .get_schema() - .get_annotations()? - .iter() - .find(|a| a.get_id() == json_capnp::discriminator::ID) - .and_then(|annotation| { - annotation - .get_value() - .ok() - .map(|v| v.downcast_struct::()) - }); - let discriminator = meta.discriminator.or(struct_discriminator); - - // FIXME: refactor this to only loop through union memberes once; each - // iteration check if it matches the discriminant, *or* the requisite - // named field is present, then decode and break; - let discriminant = match discriminator { - Some(discriminator) => { - let discriminator_name = if discriminator.has_name() { - discriminator.get_name()?.to_str()? - } else { - meta.name - }; - let field_name = format!("{}{}", field_prefix, discriminator_name); - if let Some(JsonValue::String(discriminant)) = value.remove(&field_name) { - Some(discriminant) - } else { - None - } - } - None => { - // find the first field that exists matching a union field? - let mut discriminant = None; - for field in builder.get_schema().get_union_fields()? { - let field_meta = EncodingOptions::from_field(meta.prefix, &field)?; - let field_name = format!("{}{}", field_prefix, field_meta.name); - if value.contains_key(&field_name) { - discriminant = Some(field_meta.name.to_string()); - break; - } - } - discriminant - } - }; - if let Some(discriminant) = discriminant { - for field in builder.get_schema().get_union_fields()? { - let field_meta = EncodingOptions::from_field(meta.prefix, &field)?; - if field_meta.name != discriminant { - continue; - } - let value_name = if let Some(discriminator) = discriminator { - if discriminator.has_value_name() { - discriminator.get_value_name()?.to_str()? - } else { - field_meta.name - } - } else { - field_meta.name - }; - decode_member(builder.reborrow(), field, &field_meta, value, value_name)?; - break; - } - } - - Ok(()) - } -} - -// We don't want to pull in base64 crate just for this. So hand-rolling a -// base64 codec. -mod base64 { - const BASE64_CHARS: &[u8; 64] = - b"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; - - pub fn encode(data: &[u8]) -> String { - let mut encoded = String::with_capacity(data.len().div_ceil(3) * 4); - for chunk in data.chunks(3) { - #[allow(clippy::get_first)] - let b0 = chunk.get(0).copied().unwrap_or(0); - let b1 = chunk.get(1).copied().unwrap_or(0); - let b2 = chunk.get(2).copied().unwrap_or(0); - let n = ((b0 as u32) << 16) | ((b1 as u32) << 8) | (b2 as u32); - let c0 = BASE64_CHARS[((n >> 18) & 0x3F) as usize]; - let c1 = BASE64_CHARS[((n >> 12) & 0x3F) as usize]; - let c2 = if chunk.len() > 1 { - BASE64_CHARS[((n >> 6) & 0x3F) as usize] - } else { - b'=' - }; - let c3 = if chunk.len() > 2 { - BASE64_CHARS[(n & 0x3F) as usize] - } else { - b'=' - }; - encoded.push(c0 as char); - encoded.push(c1 as char); - encoded.push(c2 as char); - encoded.push(c3 as char); - } - encoded - } - - pub fn decode(data: &str) -> capnp::Result> { - let bytes = data.as_bytes(); - if !bytes.len().is_multiple_of(4) { - return Err(capnp::Error::failed( - "Base64 string length must be a multiple of 4".into(), - )); - } - let mut decoded = Vec::with_capacity(bytes.len() / 4 * 3); - for chunk in bytes.chunks(4) { - let mut n: u32 = 0; - let mut padding = 0; - for &c in chunk { - n <<= 6; - match c { - b'A'..=b'Z' => n |= (c - b'A') as u32, - b'a'..=b'z' => n |= (c - b'a' + 26) as u32, - b'0'..=b'9' => n |= (c - b'0' + 52) as u32, - b'+' => n |= 62, - b'/' => n |= 63, - b'=' => { - n |= 0; - padding += 1; - } - _ => { - return Err(capnp::Error::failed(format!( - "Invalid base64 character: {}", - c as char - ))); - } - } - } - decoded.push(((n >> 16) & 0xFF) as u8); - if padding < 2 { - decoded.push(((n >> 8) & 0xFF) as u8); - } - if padding < 1 { - decoded.push((n & 0xFF) as u8); - } - } - Ok(decoded) - } -} - -// We don't want to pull in hex crate just for this. So hand-rolling a -// hex codec. -mod hex { - const HEX_CHARS: &[u8; 16] = b"0123456789abcdef"; - fn hex_char_to_value(c: u8) -> capnp::Result { - match c { - b'0'..=b'9' => Ok(c - b'0'), - b'a'..=b'f' => Ok(c - b'a' + 10), - b'A'..=b'F' => Ok(c - b'A' + 10), - _ => Err(capnp::Error::failed(format!( - "Invalid hex character: {}", - c as char - ))), - } - } - - pub fn encode(data: &[u8]) -> String { - let mut encoded = String::with_capacity(data.len() * 2); - for &byte in data { - let high = HEX_CHARS[(byte >> 4) as usize]; - let low = HEX_CHARS[(byte & 0x0F) as usize]; - encoded.push(high as char); - encoded.push(low as char); - } - encoded - } - - pub fn decode(data: &str) -> capnp::Result> { - if !data.len().is_multiple_of(2) { - return Err(capnp::Error::failed( - "Hex string must have even length".into(), - )); - } - let mut decoded = Vec::with_capacity(data.len() / 2); - let bytes = data.as_bytes(); - for i in (0..data.len()).step_by(2) { - let high = hex_char_to_value(bytes[i])?; - let low = hex_char_to_value(bytes[i + 1])?; - decoded.push((high << 4) | low); - } - Ok(decoded) - } -} - diff --git a/capnp-json/src/lib.rs b/capnp-json/src/lib.rs index 5d14ac844..7d128dfd2 100644 --- a/capnp-json/src/lib.rs +++ b/capnp-json/src/lib.rs @@ -1,5 +1,112 @@ -pub mod json; +mod data; +mod decode; +mod encode; + pub mod json_capnp; -pub use json::*; +#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)] +enum DataEncoding { + #[default] + Default, + Base64, + Hex, +} + +#[derive(Debug)] +struct EncodingOptions<'schema, 'prefix> { + prefix: &'prefix std::borrow::Cow<'schema, str>, + name: &'schema str, + flatten: Option>, + discriminator: Option>, + data_encoding: DataEncoding, +} + +impl<'schema, 'prefix> EncodingOptions<'schema, 'prefix> { + fn from_field( + prefix: &'prefix std::borrow::Cow<'schema, str>, + field: &capnp::schema::Field, + ) -> capnp::Result { + let mut options = Self { + prefix, + name: field.get_proto().get_name()?.to_str()?, + flatten: None, + discriminator: None, + data_encoding: DataEncoding::Default, + }; + + for anno in field.get_annotations()?.iter() { + match anno.get_id() { + json_capnp::name::ID => { + options.name = anno + .get_value()? + .downcast::() + .to_str()?; + } + json_capnp::base64::ID => { + if options.data_encoding != DataEncoding::Default { + return Err(capnp::Error::failed( + "Cannot specify both base64 and hex annotations on the same field" + .into(), + )); + } + options.data_encoding = DataEncoding::Base64; + } + json_capnp::hex::ID => { + if options.data_encoding != DataEncoding::Default { + return Err(capnp::Error::failed( + "Cannot specify both base64 and hex annotations on the same field" + .into(), + )); + } + options.data_encoding = DataEncoding::Hex; + } + json_capnp::flatten::ID => { + options.flatten = Some( + anno.get_value()? + .downcast_struct::(), + ); + } + json_capnp::discriminator::ID => { + options.discriminator = Some( + anno.get_value()? + .downcast_struct::(), + ); + } + _ => {} + } + } + if options.data_encoding != DataEncoding::Default { + let mut element_type = field.get_type(); + while let capnp::introspect::TypeVariant::List(sub_element_type) = element_type.which() + { + element_type = sub_element_type; + } + if !matches!(element_type.which(), capnp::introspect::TypeVariant::Data) { + return Err(capnp::Error::failed( + "base64/hex annotation can only be applied to Data fields".into(), + )); + } + } + Ok(options) + } +} + +pub fn to_json<'reader>( + reader: impl Into>, +) -> capnp::Result { + let mut writer = std::io::Cursor::new(Vec::with_capacity(4096)); + encode::serialize_json_to(&mut writer, reader)?; + String::from_utf8(writer.into_inner()).map_err(|e| e.into()) +} +pub fn from_json<'segments>( + json: &str, + builder: impl Into>, +) -> capnp::Result<()> { + let capnp::dynamic_value::Builder::Struct(builder) = builder.into() else { + return Err(capnp::Error::failed( + "Top-level JSON value must be an object".into(), + )); + }; + decode::parse(json, builder) +} From 5a795af10bd962def8bab7f3751267773bd4b1bc Mon Sep 17 00:00:00 2001 From: Ben Jackson Date: Sun, 7 Dec 2025 18:16:22 +0000 Subject: [PATCH 16/29] Better test coverage --- capnp-json/src/decode.rs | 41 ++++++++++++++++++++++++++++++++++++++++ capnp-json/test/json.rs | 24 +++++++++++++++++++++++ 2 files changed, 65 insertions(+) diff --git a/capnp-json/src/decode.rs b/capnp-json/src/decode.rs index 15b6d0cb9..2b1e64f72 100644 --- a/capnp-json/src/decode.rs +++ b/capnp-json/src/decode.rs @@ -736,3 +736,44 @@ fn decode_struct( Ok(()) } + +#[cfg(test)] +mod test { + use super::*; + #[test] + fn test_parse_string() -> capnp::Result<()> { + let json = r#""Hello, World!""#; + + let mut parser = Parser::new(json.chars()); + let value = parser.parse_value()?; + + assert!(matches!(value, JsonValue::String(s) if s == "Hello, World!")); + Ok(()) + } + + #[test] + fn test_parse_string_with_special_chars() -> capnp::Result<()> { + let json = r#""Hełło,\nWorld!\"†ęś†: \u0007""#; + + let mut parser = Parser::new(json.chars()); + let value = parser.parse_value()?; + + assert!(matches!(value, JsonValue::String(s) if s == "Hełło,\nWorld!\"†ęś†: \u{0007}")); + + let json = + r#"{"value":"tab: \t, newline: \n, carriage return: \r, quote: \", backslash: \\"}"#; + let mut parser = Parser::new(json.chars()); + let value = parser.parse_value()?; + let JsonValue::Object(map) = value else { + panic!("Expected object at top level"); + }; + let Some(JsonValue::String(s)) = map.get("value") else { + panic!("Expected string value for 'value' key"); + }; + assert_eq!( + s, + "tab: \t, newline: \n, carriage return: \r, quote: \", backslash: \\" + ); + Ok(()) + } +} diff --git a/capnp-json/test/json.rs b/capnp-json/test/json.rs index 246af86aa..11143f987 100644 --- a/capnp-json/test/json.rs +++ b/capnp-json/test/json.rs @@ -722,4 +722,28 @@ mod tests { } Ok(()) } + + #[test] + fn test_decode_nested_data_list() -> capnp::Result<()> { + let json = r#"{"dataAllTheWayDown":[["deadbeef","efbeadde"],["badf00d0"]]}"#; + let mut builder = message::Builder::new_default(); + let mut root = builder.init_root::>(); + json::from_json(json, root.reborrow())?; + + let reader = root.into_reader(); + + { + let awd = reader.get_data_all_the_way_down()?; + let first = awd.get(0)?; + assert_eq!(2, first.len()); + assert_eq!(&[0xde, 0xad, 0xbe, 0xef], first.get(0)?); + assert_eq!(&[0xef, 0xbe, 0xad, 0xde], first.get(1)?); + let second = awd.get(1)?; + assert_eq!(1, second.len()); + assert_eq!(&[0xba, 0xdf, 0x00, 0xd0], second.get(0)?); + } + + Ok(()) + } } + From df79246bd68f4245c638169133e029da11322f60 Mon Sep 17 00:00:00 2001 From: Ben Jackson Date: Sun, 7 Dec 2025 18:16:40 +0000 Subject: [PATCH 17/29] cargo fmt --all --- capnp-json/src/json_capnp.rs | 3365 ++++++++++++++++++++-------------- capnp-json/test/json.rs | 1 - 2 files changed, 1981 insertions(+), 1385 deletions(-) diff --git a/capnp-json/src/json_capnp.rs b/capnp-json/src/json_capnp.rs index 9c35a896f..d1d574aaa 100644 --- a/capnp-json/src/json_capnp.rs +++ b/capnp-json/src/json_capnp.rs @@ -2,1520 +2,2117 @@ // DO NOT EDIT. // source: json.capnp - pub mod value { - pub use self::Which::{Null,Boolean,Number,String,Array,Object,Call,Raw}; - - #[derive(Copy, Clone)] - pub struct Owned(()); - impl ::capnp::introspect::Introspect for Owned { fn introspect() -> ::capnp::introspect::Type { ::capnp::introspect::TypeVariant::Struct(::capnp::introspect::RawBrandedStructSchema { generic: &_private::RAW_SCHEMA, field_types: _private::get_field_types, annotation_types: _private::get_annotation_types }).into() } } - impl ::capnp::traits::Owned for Owned { type Reader<'a> = Reader<'a>; type Builder<'a> = Builder<'a>; } - impl ::capnp::traits::OwnedStruct for Owned { type Reader<'a> = Reader<'a>; type Builder<'a> = Builder<'a>; } - impl ::capnp::traits::Pipelined for Owned { type Pipeline = Pipeline; } - - pub struct Reader<'a> { reader: ::capnp::private::layout::StructReader<'a> } - impl <> ::core::marker::Copy for Reader<'_,> {} - impl <> ::core::clone::Clone for Reader<'_,> { - fn clone(&self) -> Self { *self } - } + pub use self::Which::{Array, Boolean, Call, Null, Number, Object, Raw, String}; - impl <> ::capnp::traits::HasTypeId for Reader<'_,> { - const TYPE_ID: u64 = _private::TYPE_ID; - } - impl <'a,> ::core::convert::From<::capnp::private::layout::StructReader<'a>> for Reader<'a,> { - fn from(reader: ::capnp::private::layout::StructReader<'a>) -> Self { - Self { reader, } - } - } - - impl <'a,> ::core::convert::From> for ::capnp::dynamic_value::Reader<'a> { - fn from(reader: Reader<'a,>) -> Self { - Self::Struct(::capnp::dynamic_struct::Reader::new(reader.reader, ::capnp::schema::StructSchema::new(::capnp::introspect::RawBrandedStructSchema { generic: &_private::RAW_SCHEMA, field_types: _private::get_field_types::<>, annotation_types: _private::get_annotation_types::<>}))) - } - } - - impl <> ::core::fmt::Debug for Reader<'_,> { - fn fmt(&self, f: &mut ::core::fmt::Formatter<'_>) -> ::core::result::Result<(), ::core::fmt::Error> { - core::fmt::Debug::fmt(&::core::convert::Into::<::capnp::dynamic_value::Reader<'_>>::into(*self), f) - } - } - - impl <'a,> ::capnp::traits::FromPointerReader<'a> for Reader<'a,> { - fn get_from_pointer(reader: &::capnp::private::layout::PointerReader<'a>, default: ::core::option::Option<&'a [::capnp::Word]>) -> ::capnp::Result { - ::core::result::Result::Ok(reader.get_struct(default)?.into()) - } - } - - impl <'a,> ::capnp::traits::IntoInternalStructReader<'a> for Reader<'a,> { - fn into_internal_struct_reader(self) -> ::capnp::private::layout::StructReader<'a> { - self.reader - } - } - - impl <'a,> ::capnp::traits::Imbue<'a> for Reader<'a,> { - fn imbue(&mut self, cap_table: &'a ::capnp::private::layout::CapTable) { - self.reader.imbue(::capnp::private::layout::CapTableReader::Plain(cap_table)) - } - } - - impl <'a,> Reader<'a,> { - pub fn reborrow(&self) -> Reader<'_,> { - Self { .. *self } - } - - pub fn total_size(&self) -> ::capnp::Result<::capnp::MessageSize> { - self.reader.total_size() - } - #[inline] - pub fn has_string(&self) -> bool { - if self.reader.get_data_field::(0) != 3 { return false; } - !self.reader.get_pointer_field(0).is_null() - } - #[inline] - pub fn has_array(&self) -> bool { - if self.reader.get_data_field::(0) != 4 { return false; } - !self.reader.get_pointer_field(0).is_null() - } - #[inline] - pub fn has_object(&self) -> bool { - if self.reader.get_data_field::(0) != 5 { return false; } - !self.reader.get_pointer_field(0).is_null() - } - #[inline] - pub fn has_call(&self) -> bool { - if self.reader.get_data_field::(0) != 6 { return false; } - !self.reader.get_pointer_field(0).is_null() - } - #[inline] - pub fn has_raw(&self) -> bool { - if self.reader.get_data_field::(0) != 7 { return false; } - !self.reader.get_pointer_field(0).is_null() - } - #[inline] - pub fn which(self) -> ::core::result::Result, ::capnp::NotInSchema> { - match self.reader.get_data_field::(0) { - 0 => { - ::core::result::Result::Ok(Null( - () - )) - } - 1 => { - ::core::result::Result::Ok(Boolean( - self.reader.get_bool_field(16) - )) - } - 2 => { - ::core::result::Result::Ok(Number( - self.reader.get_data_field::(1) - )) - } - 3 => { - ::core::result::Result::Ok(String( - ::capnp::traits::FromPointerReader::get_from_pointer(&self.reader.get_pointer_field(0), ::core::option::Option::None) - )) - } - 4 => { - ::core::result::Result::Ok(Array( - ::capnp::traits::FromPointerReader::get_from_pointer(&self.reader.get_pointer_field(0), ::core::option::Option::None) - )) - } - 5 => { - ::core::result::Result::Ok(Object( - ::capnp::traits::FromPointerReader::get_from_pointer(&self.reader.get_pointer_field(0), ::core::option::Option::None) - )) - } - 6 => { - ::core::result::Result::Ok(Call( - ::capnp::traits::FromPointerReader::get_from_pointer(&self.reader.get_pointer_field(0), ::core::option::Option::None) - )) - } - 7 => { - ::core::result::Result::Ok(Raw( - ::capnp::traits::FromPointerReader::get_from_pointer(&self.reader.get_pointer_field(0), ::core::option::Option::None) - )) + #[derive(Copy, Clone)] + pub struct Owned(()); + impl ::capnp::introspect::Introspect for Owned { + fn introspect() -> ::capnp::introspect::Type { + ::capnp::introspect::TypeVariant::Struct(::capnp::introspect::RawBrandedStructSchema { + generic: &_private::RAW_SCHEMA, + field_types: _private::get_field_types, + annotation_types: _private::get_annotation_types, + }) + .into() } - x => ::core::result::Result::Err(::capnp::NotInSchema(x)) - } - } - } - - pub struct Builder<'a> { builder: ::capnp::private::layout::StructBuilder<'a> } - impl <> ::capnp::traits::HasStructSize for Builder<'_,> { - const STRUCT_SIZE: ::capnp::private::layout::StructSize = ::capnp::private::layout::StructSize { data: 2, pointers: 1 }; - } - impl <> ::capnp::traits::HasTypeId for Builder<'_,> { - const TYPE_ID: u64 = _private::TYPE_ID; - } - impl <'a,> ::core::convert::From<::capnp::private::layout::StructBuilder<'a>> for Builder<'a,> { - fn from(builder: ::capnp::private::layout::StructBuilder<'a>) -> Self { - Self { builder, } } - } - - impl <'a,> ::core::convert::From> for ::capnp::dynamic_value::Builder<'a> { - fn from(builder: Builder<'a,>) -> Self { - Self::Struct(::capnp::dynamic_struct::Builder::new(builder.builder, ::capnp::schema::StructSchema::new(::capnp::introspect::RawBrandedStructSchema { generic: &_private::RAW_SCHEMA, field_types: _private::get_field_types::<>, annotation_types: _private::get_annotation_types::<>}))) + impl ::capnp::traits::Owned for Owned { + type Reader<'a> = Reader<'a>; + type Builder<'a> = Builder<'a>; } - } - - impl <'a,> ::capnp::traits::ImbueMut<'a> for Builder<'a,> { - fn imbue_mut(&mut self, cap_table: &'a mut ::capnp::private::layout::CapTable) { - self.builder.imbue(::capnp::private::layout::CapTableBuilder::Plain(cap_table)) + impl ::capnp::traits::OwnedStruct for Owned { + type Reader<'a> = Reader<'a>; + type Builder<'a> = Builder<'a>; } - } - - impl <'a,> ::capnp::traits::FromPointerBuilder<'a> for Builder<'a,> { - fn init_pointer(builder: ::capnp::private::layout::PointerBuilder<'a>, _size: u32) -> Self { - builder.init_struct(::STRUCT_SIZE).into() - } - fn get_from_pointer(builder: ::capnp::private::layout::PointerBuilder<'a>, default: ::core::option::Option<&'a [::capnp::Word]>) -> ::capnp::Result { - ::core::result::Result::Ok(builder.get_struct(::STRUCT_SIZE, default)?.into()) - } - } - - impl <> ::capnp::traits::SetterInput> for Reader<'_,> { - fn set_pointer_builder(mut pointer: ::capnp::private::layout::PointerBuilder<'_>, value: Self, canonicalize: bool) -> ::capnp::Result<()> { pointer.set_struct(&value.reader, canonicalize) } - } - - impl <'a,> Builder<'a,> { - pub fn into_reader(self) -> Reader<'a,> { - self.builder.into_reader().into() - } - pub fn reborrow(&mut self) -> Builder<'_,> { - Builder { builder: self.builder.reborrow() } - } - pub fn reborrow_as_reader(&self) -> Reader<'_,> { - self.builder.as_reader().into() - } - - pub fn total_size(&self) -> ::capnp::Result<::capnp::MessageSize> { - self.builder.as_reader().total_size() - } - #[inline] - pub fn set_null(&mut self, _value: ()) { - self.builder.set_data_field::(0, 0); - } - #[inline] - pub fn set_boolean(&mut self, value: bool) { - self.builder.set_data_field::(0, 1); - self.builder.set_bool_field(16, value); - } - #[inline] - pub fn set_number(&mut self, value: f64) { - self.builder.set_data_field::(0, 2); - self.builder.set_data_field::(1, value); - } - #[inline] - pub fn set_string(&mut self, value: impl ::capnp::traits::SetterInput<::capnp::text::Owned>) { - self.builder.set_data_field::(0, 3); - ::capnp::traits::SetterInput::set_pointer_builder(self.builder.reborrow().get_pointer_field(0), value, false).unwrap() - } - #[inline] - pub fn init_string(self, size: u32) -> ::capnp::text::Builder<'a> { - self.builder.set_data_field::(0, 3); - self.builder.get_pointer_field(0).init_text(size) - } - #[inline] - pub fn has_string(&self) -> bool { - if self.builder.get_data_field::(0) != 3 { return false; } - !self.builder.is_pointer_field_null(0) - } - #[inline] - pub fn set_array(&mut self, value: ::capnp::struct_list::Reader<'_,crate::json_capnp::value::Owned>) -> ::capnp::Result<()> { - self.builder.set_data_field::(0, 4); - ::capnp::traits::SetterInput::set_pointer_builder(self.builder.reborrow().get_pointer_field(0), value, false) - } - #[inline] - pub fn init_array(self, size: u32) -> ::capnp::struct_list::Builder<'a,crate::json_capnp::value::Owned> { - self.builder.set_data_field::(0, 4); - ::capnp::traits::FromPointerBuilder::init_pointer(self.builder.get_pointer_field(0), size) - } - #[inline] - pub fn has_array(&self) -> bool { - if self.builder.get_data_field::(0) != 4 { return false; } - !self.builder.is_pointer_field_null(0) - } - #[inline] - pub fn set_object(&mut self, value: ::capnp::struct_list::Reader<'_,crate::json_capnp::value::field::Owned>) -> ::capnp::Result<()> { - self.builder.set_data_field::(0, 5); - ::capnp::traits::SetterInput::set_pointer_builder(self.builder.reborrow().get_pointer_field(0), value, false) - } - #[inline] - pub fn init_object(self, size: u32) -> ::capnp::struct_list::Builder<'a,crate::json_capnp::value::field::Owned> { - self.builder.set_data_field::(0, 5); - ::capnp::traits::FromPointerBuilder::init_pointer(self.builder.get_pointer_field(0), size) - } - #[inline] - pub fn has_object(&self) -> bool { - if self.builder.get_data_field::(0) != 5 { return false; } - !self.builder.is_pointer_field_null(0) - } - #[inline] - pub fn set_call(&mut self, value: crate::json_capnp::value::call::Reader<'_>) -> ::capnp::Result<()> { - self.builder.set_data_field::(0, 6); - ::capnp::traits::SetterInput::set_pointer_builder(self.builder.reborrow().get_pointer_field(0), value, false) - } - #[inline] - pub fn init_call(self, ) -> crate::json_capnp::value::call::Builder<'a> { - self.builder.set_data_field::(0, 6); - ::capnp::traits::FromPointerBuilder::init_pointer(self.builder.get_pointer_field(0), 0) - } - #[inline] - pub fn has_call(&self) -> bool { - if self.builder.get_data_field::(0) != 6 { return false; } - !self.builder.is_pointer_field_null(0) - } - #[inline] - pub fn set_raw(&mut self, value: impl ::capnp::traits::SetterInput<::capnp::text::Owned>) { - self.builder.set_data_field::(0, 7); - ::capnp::traits::SetterInput::set_pointer_builder(self.builder.reborrow().get_pointer_field(0), value, false).unwrap() - } - #[inline] - pub fn init_raw(self, size: u32) -> ::capnp::text::Builder<'a> { - self.builder.set_data_field::(0, 7); - self.builder.get_pointer_field(0).init_text(size) - } - #[inline] - pub fn has_raw(&self) -> bool { - if self.builder.get_data_field::(0) != 7 { return false; } - !self.builder.is_pointer_field_null(0) - } - #[inline] - pub fn which(self) -> ::core::result::Result, ::capnp::NotInSchema> { - match self.builder.get_data_field::(0) { - 0 => { - ::core::result::Result::Ok(Null( - () - )) - } - 1 => { - ::core::result::Result::Ok(Boolean( - self.builder.get_bool_field(16) - )) - } - 2 => { - ::core::result::Result::Ok(Number( - self.builder.get_data_field::(1) - )) - } - 3 => { - ::core::result::Result::Ok(String( - ::capnp::traits::FromPointerBuilder::get_from_pointer(self.builder.get_pointer_field(0), ::core::option::Option::None) - )) - } - 4 => { - ::core::result::Result::Ok(Array( - ::capnp::traits::FromPointerBuilder::get_from_pointer(self.builder.get_pointer_field(0), ::core::option::Option::None) - )) - } - 5 => { - ::core::result::Result::Ok(Object( - ::capnp::traits::FromPointerBuilder::get_from_pointer(self.builder.get_pointer_field(0), ::core::option::Option::None) - )) - } - 6 => { - ::core::result::Result::Ok(Call( - ::capnp::traits::FromPointerBuilder::get_from_pointer(self.builder.get_pointer_field(0), ::core::option::Option::None) - )) - } - 7 => { - ::core::result::Result::Ok(Raw( - ::capnp::traits::FromPointerBuilder::get_from_pointer(self.builder.get_pointer_field(0), ::core::option::Option::None) - )) - } - x => ::core::result::Result::Err(::capnp::NotInSchema(x)) - } - } - } - - pub struct Pipeline { _typeless: ::capnp::any_pointer::Pipeline } - impl ::capnp::capability::FromTypelessPipeline for Pipeline { - fn new(typeless: ::capnp::any_pointer::Pipeline) -> Self { - Self { _typeless: typeless, } - } - } - impl Pipeline { - } - mod _private { - pub static ENCODED_NODE: [::capnp::Word; 152] = [ - ::capnp::word(0, 0, 0, 0, 6, 0, 6, 0), - ::capnp::word(131, 221, 25, 249, 69, 120, 250, 163), - ::capnp::word(11, 0, 0, 0, 1, 0, 2, 0), - ::capnp::word(52, 94, 58, 164, 151, 146, 249, 142), - ::capnp::word(1, 0, 7, 0, 0, 0, 8, 0), - ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), - ::capnp::word(216, 4, 0, 0, 47, 11, 0, 0), - ::capnp::word(21, 0, 0, 0, 138, 0, 0, 0), - ::capnp::word(29, 0, 0, 0, 39, 0, 0, 0), - ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), - ::capnp::word(49, 0, 0, 0, 199, 1, 0, 0), - ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), - ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), - ::capnp::word(106, 115, 111, 110, 46, 99, 97, 112), - ::capnp::word(110, 112, 58, 86, 97, 108, 117, 101), - ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), - ::capnp::word(8, 0, 0, 0, 1, 0, 1, 0), - ::capnp::word(223, 157, 214, 53, 231, 38, 16, 227), - ::capnp::word(9, 0, 0, 0, 50, 0, 0, 0), - ::capnp::word(72, 61, 201, 161, 236, 246, 217, 160), - ::capnp::word(5, 0, 0, 0, 42, 0, 0, 0), - ::capnp::word(70, 105, 101, 108, 100, 0, 0, 0), - ::capnp::word(67, 97, 108, 108, 0, 0, 0, 0), - ::capnp::word(32, 0, 0, 0, 3, 0, 4, 0), - ::capnp::word(0, 0, 255, 255, 0, 0, 0, 0), - ::capnp::word(0, 0, 1, 0, 0, 0, 0, 0), - ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), - ::capnp::word(209, 0, 0, 0, 42, 0, 0, 0), - ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), - ::capnp::word(204, 0, 0, 0, 3, 0, 1, 0), - ::capnp::word(216, 0, 0, 0, 2, 0, 1, 0), - ::capnp::word(1, 0, 254, 255, 16, 0, 0, 0), - ::capnp::word(0, 0, 1, 0, 1, 0, 0, 0), - ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), - ::capnp::word(213, 0, 0, 0, 66, 0, 0, 0), - ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), - ::capnp::word(208, 0, 0, 0, 3, 0, 1, 0), - ::capnp::word(220, 0, 0, 0, 2, 0, 1, 0), - ::capnp::word(2, 0, 253, 255, 1, 0, 0, 0), - ::capnp::word(0, 0, 1, 0, 2, 0, 0, 0), - ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), - ::capnp::word(217, 0, 0, 0, 58, 0, 0, 0), - ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), - ::capnp::word(212, 0, 0, 0, 3, 0, 1, 0), - ::capnp::word(224, 0, 0, 0, 2, 0, 1, 0), - ::capnp::word(3, 0, 252, 255, 0, 0, 0, 0), - ::capnp::word(0, 0, 1, 0, 3, 0, 0, 0), - ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), - ::capnp::word(221, 0, 0, 0, 58, 0, 0, 0), - ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), - ::capnp::word(216, 0, 0, 0, 3, 0, 1, 0), - ::capnp::word(228, 0, 0, 0, 2, 0, 1, 0), - ::capnp::word(4, 0, 251, 255, 0, 0, 0, 0), - ::capnp::word(0, 0, 1, 0, 4, 0, 0, 0), - ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), - ::capnp::word(225, 0, 0, 0, 50, 0, 0, 0), - ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), - ::capnp::word(220, 0, 0, 0, 3, 0, 1, 0), - ::capnp::word(248, 0, 0, 0, 2, 0, 1, 0), - ::capnp::word(5, 0, 250, 255, 0, 0, 0, 0), - ::capnp::word(0, 0, 1, 0, 5, 0, 0, 0), - ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), - ::capnp::word(245, 0, 0, 0, 58, 0, 0, 0), - ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), - ::capnp::word(240, 0, 0, 0, 3, 0, 1, 0), - ::capnp::word(12, 1, 0, 0, 2, 0, 1, 0), - ::capnp::word(6, 0, 249, 255, 0, 0, 0, 0), - ::capnp::word(0, 0, 1, 0, 6, 0, 0, 0), - ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), - ::capnp::word(9, 1, 0, 0, 42, 0, 0, 0), - ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), - ::capnp::word(4, 1, 0, 0, 3, 0, 1, 0), - ::capnp::word(16, 1, 0, 0, 2, 0, 1, 0), - ::capnp::word(7, 0, 248, 255, 0, 0, 0, 0), - ::capnp::word(0, 0, 1, 0, 7, 0, 0, 0), - ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), - ::capnp::word(13, 1, 0, 0, 34, 0, 0, 0), - ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), - ::capnp::word(8, 1, 0, 0, 3, 0, 1, 0), - ::capnp::word(20, 1, 0, 0, 2, 0, 1, 0), - ::capnp::word(110, 117, 108, 108, 0, 0, 0, 0), - ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), - ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), - ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), - ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), - ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), - ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), - ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), - ::capnp::word(98, 111, 111, 108, 101, 97, 110, 0), - ::capnp::word(1, 0, 0, 0, 0, 0, 0, 0), - ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), - ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), - ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), - ::capnp::word(1, 0, 0, 0, 0, 0, 0, 0), - ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), - ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), - ::capnp::word(110, 117, 109, 98, 101, 114, 0, 0), - ::capnp::word(11, 0, 0, 0, 0, 0, 0, 0), - ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), - ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), - ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), - ::capnp::word(11, 0, 0, 0, 0, 0, 0, 0), - ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), - ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), - ::capnp::word(115, 116, 114, 105, 110, 103, 0, 0), - ::capnp::word(12, 0, 0, 0, 0, 0, 0, 0), - ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), - ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), - ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), - ::capnp::word(12, 0, 0, 0, 0, 0, 0, 0), - ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), - ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), - ::capnp::word(97, 114, 114, 97, 121, 0, 0, 0), - ::capnp::word(14, 0, 0, 0, 0, 0, 0, 0), - ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), - ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), - ::capnp::word(0, 0, 0, 0, 3, 0, 1, 0), - ::capnp::word(16, 0, 0, 0, 0, 0, 0, 0), - ::capnp::word(131, 221, 25, 249, 69, 120, 250, 163), - ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), - ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), - ::capnp::word(14, 0, 0, 0, 0, 0, 0, 0), - ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), - ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), - ::capnp::word(111, 98, 106, 101, 99, 116, 0, 0), - ::capnp::word(14, 0, 0, 0, 0, 0, 0, 0), - ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), - ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), - ::capnp::word(0, 0, 0, 0, 3, 0, 1, 0), - ::capnp::word(16, 0, 0, 0, 0, 0, 0, 0), - ::capnp::word(223, 157, 214, 53, 231, 38, 16, 227), - ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), - ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), - ::capnp::word(14, 0, 0, 0, 0, 0, 0, 0), - ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), - ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), - ::capnp::word(99, 97, 108, 108, 0, 0, 0, 0), - ::capnp::word(16, 0, 0, 0, 0, 0, 0, 0), - ::capnp::word(72, 61, 201, 161, 236, 246, 217, 160), - ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), - ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), - ::capnp::word(16, 0, 0, 0, 0, 0, 0, 0), - ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), - ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), - ::capnp::word(114, 97, 119, 0, 0, 0, 0, 0), - ::capnp::word(12, 0, 0, 0, 0, 0, 0, 0), - ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), - ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), - ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), - ::capnp::word(12, 0, 0, 0, 0, 0, 0, 0), - ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), - ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), - ]; - pub fn get_field_types(index: u16) -> ::capnp::introspect::Type { - match index { - 0 => <() as ::capnp::introspect::Introspect>::introspect(), - 1 => ::introspect(), - 2 => ::introspect(), - 3 => <::capnp::text::Owned as ::capnp::introspect::Introspect>::introspect(), - 4 => <::capnp::struct_list::Owned as ::capnp::introspect::Introspect>::introspect(), - 5 => <::capnp::struct_list::Owned as ::capnp::introspect::Introspect>::introspect(), - 6 => ::introspect(), - 7 => <::capnp::text::Owned as ::capnp::introspect::Introspect>::introspect(), - _ => ::capnp::introspect::panic_invalid_field_index(index), - } + impl ::capnp::traits::Pipelined for Owned { + type Pipeline = Pipeline; } - pub fn get_annotation_types(child_index: Option, index: u32) -> ::capnp::introspect::Type { - ::capnp::introspect::panic_invalid_annotation_indices(child_index, index) - } - pub static RAW_SCHEMA: ::capnp::introspect::RawStructSchema = ::capnp::introspect::RawStructSchema { - encoded_node: &ENCODED_NODE, - nonunion_members: NONUNION_MEMBERS, - members_by_discriminant: MEMBERS_BY_DISCRIMINANT, - members_by_name: MEMBERS_BY_NAME, - }; - pub static NONUNION_MEMBERS : &[u16] = &[]; - pub static MEMBERS_BY_DISCRIMINANT : &[u16] = &[0,1,2,3,4,5,6,7]; - pub static MEMBERS_BY_NAME : &[u16] = &[4,1,6,0,2,5,7,3]; - pub const TYPE_ID: u64 = 0xa3fa_7845_f919_dd83; - } - pub enum Which { - Null(()), - Boolean(bool), - Number(f64), - String(A0), - Array(A1), - Object(A2), - Call(A3), - Raw(A4), - } - pub type WhichReader<'a,> = Which<::capnp::Result<::capnp::text::Reader<'a>>,::capnp::Result<::capnp::struct_list::Reader<'a,crate::json_capnp::value::Owned>>,::capnp::Result<::capnp::struct_list::Reader<'a,crate::json_capnp::value::field::Owned>>,::capnp::Result>,::capnp::Result<::capnp::text::Reader<'a>>>; - pub type WhichBuilder<'a,> = Which<::capnp::Result<::capnp::text::Builder<'a>>,::capnp::Result<::capnp::struct_list::Builder<'a,crate::json_capnp::value::Owned>>,::capnp::Result<::capnp::struct_list::Builder<'a,crate::json_capnp::value::field::Owned>>,::capnp::Result>,::capnp::Result<::capnp::text::Builder<'a>>>; - - pub mod field { - #[derive(Copy, Clone)] - pub struct Owned(()); - impl ::capnp::introspect::Introspect for Owned { fn introspect() -> ::capnp::introspect::Type { ::capnp::introspect::TypeVariant::Struct(::capnp::introspect::RawBrandedStructSchema { generic: &_private::RAW_SCHEMA, field_types: _private::get_field_types, annotation_types: _private::get_annotation_types }).into() } } - impl ::capnp::traits::Owned for Owned { type Reader<'a> = Reader<'a>; type Builder<'a> = Builder<'a>; } - impl ::capnp::traits::OwnedStruct for Owned { type Reader<'a> = Reader<'a>; type Builder<'a> = Builder<'a>; } - impl ::capnp::traits::Pipelined for Owned { type Pipeline = Pipeline; } - pub struct Reader<'a> { reader: ::capnp::private::layout::StructReader<'a> } - impl <> ::core::marker::Copy for Reader<'_,> {} - impl <> ::core::clone::Clone for Reader<'_,> { - fn clone(&self) -> Self { *self } + pub struct Reader<'a> { + reader: ::capnp::private::layout::StructReader<'a>, + } + impl ::core::marker::Copy for Reader<'_> {} + impl ::core::clone::Clone for Reader<'_> { + fn clone(&self) -> Self { + *self + } } - impl <> ::capnp::traits::HasTypeId for Reader<'_,> { - const TYPE_ID: u64 = _private::TYPE_ID; + impl ::capnp::traits::HasTypeId for Reader<'_> { + const TYPE_ID: u64 = _private::TYPE_ID; } - impl <'a,> ::core::convert::From<::capnp::private::layout::StructReader<'a>> for Reader<'a,> { - fn from(reader: ::capnp::private::layout::StructReader<'a>) -> Self { - Self { reader, } - } + impl<'a> ::core::convert::From<::capnp::private::layout::StructReader<'a>> for Reader<'a> { + fn from(reader: ::capnp::private::layout::StructReader<'a>) -> Self { + Self { reader } + } } - impl <'a,> ::core::convert::From> for ::capnp::dynamic_value::Reader<'a> { - fn from(reader: Reader<'a,>) -> Self { - Self::Struct(::capnp::dynamic_struct::Reader::new(reader.reader, ::capnp::schema::StructSchema::new(::capnp::introspect::RawBrandedStructSchema { generic: &_private::RAW_SCHEMA, field_types: _private::get_field_types::<>, annotation_types: _private::get_annotation_types::<>}))) - } + impl<'a> ::core::convert::From> for ::capnp::dynamic_value::Reader<'a> { + fn from(reader: Reader<'a>) -> Self { + Self::Struct(::capnp::dynamic_struct::Reader::new( + reader.reader, + ::capnp::schema::StructSchema::new(::capnp::introspect::RawBrandedStructSchema { + generic: &_private::RAW_SCHEMA, + field_types: _private::get_field_types, + annotation_types: _private::get_annotation_types, + }), + )) + } } - impl <> ::core::fmt::Debug for Reader<'_,> { - fn fmt(&self, f: &mut ::core::fmt::Formatter<'_>) -> ::core::result::Result<(), ::core::fmt::Error> { - core::fmt::Debug::fmt(&::core::convert::Into::<::capnp::dynamic_value::Reader<'_>>::into(*self), f) - } + impl ::core::fmt::Debug for Reader<'_> { + fn fmt( + &self, + f: &mut ::core::fmt::Formatter<'_>, + ) -> ::core::result::Result<(), ::core::fmt::Error> { + core::fmt::Debug::fmt( + &::core::convert::Into::<::capnp::dynamic_value::Reader<'_>>::into(*self), + f, + ) + } } - impl <'a,> ::capnp::traits::FromPointerReader<'a> for Reader<'a,> { - fn get_from_pointer(reader: &::capnp::private::layout::PointerReader<'a>, default: ::core::option::Option<&'a [::capnp::Word]>) -> ::capnp::Result { - ::core::result::Result::Ok(reader.get_struct(default)?.into()) - } + impl<'a> ::capnp::traits::FromPointerReader<'a> for Reader<'a> { + fn get_from_pointer( + reader: &::capnp::private::layout::PointerReader<'a>, + default: ::core::option::Option<&'a [::capnp::Word]>, + ) -> ::capnp::Result { + ::core::result::Result::Ok(reader.get_struct(default)?.into()) + } } - impl <'a,> ::capnp::traits::IntoInternalStructReader<'a> for Reader<'a,> { - fn into_internal_struct_reader(self) -> ::capnp::private::layout::StructReader<'a> { - self.reader - } + impl<'a> ::capnp::traits::IntoInternalStructReader<'a> for Reader<'a> { + fn into_internal_struct_reader(self) -> ::capnp::private::layout::StructReader<'a> { + self.reader + } } - impl <'a,> ::capnp::traits::Imbue<'a> for Reader<'a,> { - fn imbue(&mut self, cap_table: &'a ::capnp::private::layout::CapTable) { - self.reader.imbue(::capnp::private::layout::CapTableReader::Plain(cap_table)) - } + impl<'a> ::capnp::traits::Imbue<'a> for Reader<'a> { + fn imbue(&mut self, cap_table: &'a ::capnp::private::layout::CapTable) { + self.reader + .imbue(::capnp::private::layout::CapTableReader::Plain(cap_table)) + } } - impl <'a,> Reader<'a,> { - pub fn reborrow(&self) -> Reader<'_,> { - Self { .. *self } - } + impl<'a> Reader<'a> { + pub fn reborrow(&self) -> Reader<'_> { + Self { ..*self } + } - pub fn total_size(&self) -> ::capnp::Result<::capnp::MessageSize> { - self.reader.total_size() - } - #[inline] - pub fn get_name(self) -> ::capnp::Result<::capnp::text::Reader<'a>> { - ::capnp::traits::FromPointerReader::get_from_pointer(&self.reader.get_pointer_field(0), ::core::option::Option::None) - } - #[inline] - pub fn has_name(&self) -> bool { - !self.reader.get_pointer_field(0).is_null() - } - #[inline] - pub fn get_value(self) -> ::capnp::Result> { - ::capnp::traits::FromPointerReader::get_from_pointer(&self.reader.get_pointer_field(1), ::core::option::Option::None) - } - #[inline] - pub fn has_value(&self) -> bool { - !self.reader.get_pointer_field(1).is_null() - } + pub fn total_size(&self) -> ::capnp::Result<::capnp::MessageSize> { + self.reader.total_size() + } + #[inline] + pub fn has_string(&self) -> bool { + if self.reader.get_data_field::(0) != 3 { + return false; + } + !self.reader.get_pointer_field(0).is_null() + } + #[inline] + pub fn has_array(&self) -> bool { + if self.reader.get_data_field::(0) != 4 { + return false; + } + !self.reader.get_pointer_field(0).is_null() + } + #[inline] + pub fn has_object(&self) -> bool { + if self.reader.get_data_field::(0) != 5 { + return false; + } + !self.reader.get_pointer_field(0).is_null() + } + #[inline] + pub fn has_call(&self) -> bool { + if self.reader.get_data_field::(0) != 6 { + return false; + } + !self.reader.get_pointer_field(0).is_null() + } + #[inline] + pub fn has_raw(&self) -> bool { + if self.reader.get_data_field::(0) != 7 { + return false; + } + !self.reader.get_pointer_field(0).is_null() + } + #[inline] + pub fn which(self) -> ::core::result::Result, ::capnp::NotInSchema> { + match self.reader.get_data_field::(0) { + 0 => ::core::result::Result::Ok(Null(())), + 1 => ::core::result::Result::Ok(Boolean(self.reader.get_bool_field(16))), + 2 => ::core::result::Result::Ok(Number(self.reader.get_data_field::(1))), + 3 => ::core::result::Result::Ok(String( + ::capnp::traits::FromPointerReader::get_from_pointer( + &self.reader.get_pointer_field(0), + ::core::option::Option::None, + ), + )), + 4 => ::core::result::Result::Ok(Array( + ::capnp::traits::FromPointerReader::get_from_pointer( + &self.reader.get_pointer_field(0), + ::core::option::Option::None, + ), + )), + 5 => ::core::result::Result::Ok(Object( + ::capnp::traits::FromPointerReader::get_from_pointer( + &self.reader.get_pointer_field(0), + ::core::option::Option::None, + ), + )), + 6 => ::core::result::Result::Ok(Call( + ::capnp::traits::FromPointerReader::get_from_pointer( + &self.reader.get_pointer_field(0), + ::core::option::Option::None, + ), + )), + 7 => ::core::result::Result::Ok(Raw( + ::capnp::traits::FromPointerReader::get_from_pointer( + &self.reader.get_pointer_field(0), + ::core::option::Option::None, + ), + )), + x => ::core::result::Result::Err(::capnp::NotInSchema(x)), + } + } } - pub struct Builder<'a> { builder: ::capnp::private::layout::StructBuilder<'a> } - impl <> ::capnp::traits::HasStructSize for Builder<'_,> { - const STRUCT_SIZE: ::capnp::private::layout::StructSize = ::capnp::private::layout::StructSize { data: 0, pointers: 2 }; + pub struct Builder<'a> { + builder: ::capnp::private::layout::StructBuilder<'a>, } - impl <> ::capnp::traits::HasTypeId for Builder<'_,> { - const TYPE_ID: u64 = _private::TYPE_ID; + impl ::capnp::traits::HasStructSize for Builder<'_> { + const STRUCT_SIZE: ::capnp::private::layout::StructSize = + ::capnp::private::layout::StructSize { + data: 2, + pointers: 1, + }; } - impl <'a,> ::core::convert::From<::capnp::private::layout::StructBuilder<'a>> for Builder<'a,> { - fn from(builder: ::capnp::private::layout::StructBuilder<'a>) -> Self { - Self { builder, } - } + impl ::capnp::traits::HasTypeId for Builder<'_> { + const TYPE_ID: u64 = _private::TYPE_ID; + } + impl<'a> ::core::convert::From<::capnp::private::layout::StructBuilder<'a>> for Builder<'a> { + fn from(builder: ::capnp::private::layout::StructBuilder<'a>) -> Self { + Self { builder } + } } - impl <'a,> ::core::convert::From> for ::capnp::dynamic_value::Builder<'a> { - fn from(builder: Builder<'a,>) -> Self { - Self::Struct(::capnp::dynamic_struct::Builder::new(builder.builder, ::capnp::schema::StructSchema::new(::capnp::introspect::RawBrandedStructSchema { generic: &_private::RAW_SCHEMA, field_types: _private::get_field_types::<>, annotation_types: _private::get_annotation_types::<>}))) - } + impl<'a> ::core::convert::From> for ::capnp::dynamic_value::Builder<'a> { + fn from(builder: Builder<'a>) -> Self { + Self::Struct(::capnp::dynamic_struct::Builder::new( + builder.builder, + ::capnp::schema::StructSchema::new(::capnp::introspect::RawBrandedStructSchema { + generic: &_private::RAW_SCHEMA, + field_types: _private::get_field_types, + annotation_types: _private::get_annotation_types, + }), + )) + } } - impl <'a,> ::capnp::traits::ImbueMut<'a> for Builder<'a,> { - fn imbue_mut(&mut self, cap_table: &'a mut ::capnp::private::layout::CapTable) { - self.builder.imbue(::capnp::private::layout::CapTableBuilder::Plain(cap_table)) - } + impl<'a> ::capnp::traits::ImbueMut<'a> for Builder<'a> { + fn imbue_mut(&mut self, cap_table: &'a mut ::capnp::private::layout::CapTable) { + self.builder + .imbue(::capnp::private::layout::CapTableBuilder::Plain(cap_table)) + } } - impl <'a,> ::capnp::traits::FromPointerBuilder<'a> for Builder<'a,> { - fn init_pointer(builder: ::capnp::private::layout::PointerBuilder<'a>, _size: u32) -> Self { - builder.init_struct(::STRUCT_SIZE).into() - } - fn get_from_pointer(builder: ::capnp::private::layout::PointerBuilder<'a>, default: ::core::option::Option<&'a [::capnp::Word]>) -> ::capnp::Result { - ::core::result::Result::Ok(builder.get_struct(::STRUCT_SIZE, default)?.into()) - } + impl<'a> ::capnp::traits::FromPointerBuilder<'a> for Builder<'a> { + fn init_pointer(builder: ::capnp::private::layout::PointerBuilder<'a>, _size: u32) -> Self { + builder + .init_struct(::STRUCT_SIZE) + .into() + } + fn get_from_pointer( + builder: ::capnp::private::layout::PointerBuilder<'a>, + default: ::core::option::Option<&'a [::capnp::Word]>, + ) -> ::capnp::Result { + ::core::result::Result::Ok( + builder + .get_struct( + ::STRUCT_SIZE, + default, + )? + .into(), + ) + } } - impl <> ::capnp::traits::SetterInput> for Reader<'_,> { - fn set_pointer_builder(mut pointer: ::capnp::private::layout::PointerBuilder<'_>, value: Self, canonicalize: bool) -> ::capnp::Result<()> { pointer.set_struct(&value.reader, canonicalize) } + impl ::capnp::traits::SetterInput for Reader<'_> { + fn set_pointer_builder( + mut pointer: ::capnp::private::layout::PointerBuilder<'_>, + value: Self, + canonicalize: bool, + ) -> ::capnp::Result<()> { + pointer.set_struct(&value.reader, canonicalize) + } } - impl <'a,> Builder<'a,> { - pub fn into_reader(self) -> Reader<'a,> { - self.builder.into_reader().into() - } - pub fn reborrow(&mut self) -> Builder<'_,> { - Builder { builder: self.builder.reborrow() } - } - pub fn reborrow_as_reader(&self) -> Reader<'_,> { - self.builder.as_reader().into() - } + impl<'a> Builder<'a> { + pub fn into_reader(self) -> Reader<'a> { + self.builder.into_reader().into() + } + pub fn reborrow(&mut self) -> Builder<'_> { + Builder { + builder: self.builder.reborrow(), + } + } + pub fn reborrow_as_reader(&self) -> Reader<'_> { + self.builder.as_reader().into() + } - pub fn total_size(&self) -> ::capnp::Result<::capnp::MessageSize> { - self.builder.as_reader().total_size() - } - #[inline] - pub fn get_name(self) -> ::capnp::Result<::capnp::text::Builder<'a>> { - ::capnp::traits::FromPointerBuilder::get_from_pointer(self.builder.get_pointer_field(0), ::core::option::Option::None) - } - #[inline] - pub fn set_name(&mut self, value: impl ::capnp::traits::SetterInput<::capnp::text::Owned>) { - ::capnp::traits::SetterInput::set_pointer_builder(self.builder.reborrow().get_pointer_field(0), value, false).unwrap() - } - #[inline] - pub fn init_name(self, size: u32) -> ::capnp::text::Builder<'a> { - self.builder.get_pointer_field(0).init_text(size) - } - #[inline] - pub fn has_name(&self) -> bool { - !self.builder.is_pointer_field_null(0) - } - #[inline] - pub fn get_value(self) -> ::capnp::Result> { - ::capnp::traits::FromPointerBuilder::get_from_pointer(self.builder.get_pointer_field(1), ::core::option::Option::None) - } - #[inline] - pub fn set_value(&mut self, value: crate::json_capnp::value::Reader<'_>) -> ::capnp::Result<()> { - ::capnp::traits::SetterInput::set_pointer_builder(self.builder.reborrow().get_pointer_field(1), value, false) - } - #[inline] - pub fn init_value(self, ) -> crate::json_capnp::value::Builder<'a> { - ::capnp::traits::FromPointerBuilder::init_pointer(self.builder.get_pointer_field(1), 0) - } - #[inline] - pub fn has_value(&self) -> bool { - !self.builder.is_pointer_field_null(1) - } + pub fn total_size(&self) -> ::capnp::Result<::capnp::MessageSize> { + self.builder.as_reader().total_size() + } + #[inline] + pub fn set_null(&mut self, _value: ()) { + self.builder.set_data_field::(0, 0); + } + #[inline] + pub fn set_boolean(&mut self, value: bool) { + self.builder.set_data_field::(0, 1); + self.builder.set_bool_field(16, value); + } + #[inline] + pub fn set_number(&mut self, value: f64) { + self.builder.set_data_field::(0, 2); + self.builder.set_data_field::(1, value); + } + #[inline] + pub fn set_string( + &mut self, + value: impl ::capnp::traits::SetterInput<::capnp::text::Owned>, + ) { + self.builder.set_data_field::(0, 3); + ::capnp::traits::SetterInput::set_pointer_builder( + self.builder.reborrow().get_pointer_field(0), + value, + false, + ) + .unwrap() + } + #[inline] + pub fn init_string(self, size: u32) -> ::capnp::text::Builder<'a> { + self.builder.set_data_field::(0, 3); + self.builder.get_pointer_field(0).init_text(size) + } + #[inline] + pub fn has_string(&self) -> bool { + if self.builder.get_data_field::(0) != 3 { + return false; + } + !self.builder.is_pointer_field_null(0) + } + #[inline] + pub fn set_array( + &mut self, + value: ::capnp::struct_list::Reader<'_, crate::json_capnp::value::Owned>, + ) -> ::capnp::Result<()> { + self.builder.set_data_field::(0, 4); + ::capnp::traits::SetterInput::set_pointer_builder( + self.builder.reborrow().get_pointer_field(0), + value, + false, + ) + } + #[inline] + pub fn init_array( + self, + size: u32, + ) -> ::capnp::struct_list::Builder<'a, crate::json_capnp::value::Owned> { + self.builder.set_data_field::(0, 4); + ::capnp::traits::FromPointerBuilder::init_pointer( + self.builder.get_pointer_field(0), + size, + ) + } + #[inline] + pub fn has_array(&self) -> bool { + if self.builder.get_data_field::(0) != 4 { + return false; + } + !self.builder.is_pointer_field_null(0) + } + #[inline] + pub fn set_object( + &mut self, + value: ::capnp::struct_list::Reader<'_, crate::json_capnp::value::field::Owned>, + ) -> ::capnp::Result<()> { + self.builder.set_data_field::(0, 5); + ::capnp::traits::SetterInput::set_pointer_builder( + self.builder.reborrow().get_pointer_field(0), + value, + false, + ) + } + #[inline] + pub fn init_object( + self, + size: u32, + ) -> ::capnp::struct_list::Builder<'a, crate::json_capnp::value::field::Owned> { + self.builder.set_data_field::(0, 5); + ::capnp::traits::FromPointerBuilder::init_pointer( + self.builder.get_pointer_field(0), + size, + ) + } + #[inline] + pub fn has_object(&self) -> bool { + if self.builder.get_data_field::(0) != 5 { + return false; + } + !self.builder.is_pointer_field_null(0) + } + #[inline] + pub fn set_call( + &mut self, + value: crate::json_capnp::value::call::Reader<'_>, + ) -> ::capnp::Result<()> { + self.builder.set_data_field::(0, 6); + ::capnp::traits::SetterInput::set_pointer_builder( + self.builder.reborrow().get_pointer_field(0), + value, + false, + ) + } + #[inline] + pub fn init_call(self) -> crate::json_capnp::value::call::Builder<'a> { + self.builder.set_data_field::(0, 6); + ::capnp::traits::FromPointerBuilder::init_pointer(self.builder.get_pointer_field(0), 0) + } + #[inline] + pub fn has_call(&self) -> bool { + if self.builder.get_data_field::(0) != 6 { + return false; + } + !self.builder.is_pointer_field_null(0) + } + #[inline] + pub fn set_raw(&mut self, value: impl ::capnp::traits::SetterInput<::capnp::text::Owned>) { + self.builder.set_data_field::(0, 7); + ::capnp::traits::SetterInput::set_pointer_builder( + self.builder.reborrow().get_pointer_field(0), + value, + false, + ) + .unwrap() + } + #[inline] + pub fn init_raw(self, size: u32) -> ::capnp::text::Builder<'a> { + self.builder.set_data_field::(0, 7); + self.builder.get_pointer_field(0).init_text(size) + } + #[inline] + pub fn has_raw(&self) -> bool { + if self.builder.get_data_field::(0) != 7 { + return false; + } + !self.builder.is_pointer_field_null(0) + } + #[inline] + pub fn which(self) -> ::core::result::Result, ::capnp::NotInSchema> { + match self.builder.get_data_field::(0) { + 0 => ::core::result::Result::Ok(Null(())), + 1 => ::core::result::Result::Ok(Boolean(self.builder.get_bool_field(16))), + 2 => ::core::result::Result::Ok(Number(self.builder.get_data_field::(1))), + 3 => ::core::result::Result::Ok(String( + ::capnp::traits::FromPointerBuilder::get_from_pointer( + self.builder.get_pointer_field(0), + ::core::option::Option::None, + ), + )), + 4 => ::core::result::Result::Ok(Array( + ::capnp::traits::FromPointerBuilder::get_from_pointer( + self.builder.get_pointer_field(0), + ::core::option::Option::None, + ), + )), + 5 => ::core::result::Result::Ok(Object( + ::capnp::traits::FromPointerBuilder::get_from_pointer( + self.builder.get_pointer_field(0), + ::core::option::Option::None, + ), + )), + 6 => ::core::result::Result::Ok(Call( + ::capnp::traits::FromPointerBuilder::get_from_pointer( + self.builder.get_pointer_field(0), + ::core::option::Option::None, + ), + )), + 7 => ::core::result::Result::Ok(Raw( + ::capnp::traits::FromPointerBuilder::get_from_pointer( + self.builder.get_pointer_field(0), + ::core::option::Option::None, + ), + )), + x => ::core::result::Result::Err(::capnp::NotInSchema(x)), + } + } } - pub struct Pipeline { _typeless: ::capnp::any_pointer::Pipeline } - impl ::capnp::capability::FromTypelessPipeline for Pipeline { - fn new(typeless: ::capnp::any_pointer::Pipeline) -> Self { - Self { _typeless: typeless, } - } + pub struct Pipeline { + _typeless: ::capnp::any_pointer::Pipeline, } - impl Pipeline { - pub fn get_value(&self) -> crate::json_capnp::value::Pipeline { - ::capnp::capability::FromTypelessPipeline::new(self._typeless.get_pointer_field(1)) - } + impl ::capnp::capability::FromTypelessPipeline for Pipeline { + fn new(typeless: ::capnp::any_pointer::Pipeline) -> Self { + Self { + _typeless: typeless, + } + } } + impl Pipeline {} mod _private { - pub static ENCODED_NODE: [::capnp::Word; 48] = [ - ::capnp::word(0, 0, 0, 0, 6, 0, 6, 0), - ::capnp::word(223, 157, 214, 53, 231, 38, 16, 227), - ::capnp::word(17, 0, 0, 0, 1, 0, 0, 0), - ::capnp::word(131, 221, 25, 249, 69, 120, 250, 163), - ::capnp::word(2, 0, 7, 0, 0, 0, 0, 0), - ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), - ::capnp::word(171, 10, 0, 0, 229, 10, 0, 0), - ::capnp::word(21, 0, 0, 0, 186, 0, 0, 0), - ::capnp::word(29, 0, 0, 0, 7, 0, 0, 0), - ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), - ::capnp::word(25, 0, 0, 0, 119, 0, 0, 0), - ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), - ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), - ::capnp::word(106, 115, 111, 110, 46, 99, 97, 112), - ::capnp::word(110, 112, 58, 86, 97, 108, 117, 101), - ::capnp::word(46, 70, 105, 101, 108, 100, 0, 0), - ::capnp::word(0, 0, 0, 0, 1, 0, 1, 0), - ::capnp::word(8, 0, 0, 0, 3, 0, 4, 0), - ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), - ::capnp::word(0, 0, 1, 0, 0, 0, 0, 0), - ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), - ::capnp::word(41, 0, 0, 0, 42, 0, 0, 0), - ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), - ::capnp::word(36, 0, 0, 0, 3, 0, 1, 0), - ::capnp::word(48, 0, 0, 0, 2, 0, 1, 0), - ::capnp::word(1, 0, 0, 0, 1, 0, 0, 0), - ::capnp::word(0, 0, 1, 0, 1, 0, 0, 0), - ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), - ::capnp::word(45, 0, 0, 0, 50, 0, 0, 0), - ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), - ::capnp::word(40, 0, 0, 0, 3, 0, 1, 0), - ::capnp::word(52, 0, 0, 0, 2, 0, 1, 0), - ::capnp::word(110, 97, 109, 101, 0, 0, 0, 0), - ::capnp::word(12, 0, 0, 0, 0, 0, 0, 0), - ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), - ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), - ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), - ::capnp::word(12, 0, 0, 0, 0, 0, 0, 0), - ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), - ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), - ::capnp::word(118, 97, 108, 117, 101, 0, 0, 0), - ::capnp::word(16, 0, 0, 0, 0, 0, 0, 0), - ::capnp::word(131, 221, 25, 249, 69, 120, 250, 163), - ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), - ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), - ::capnp::word(16, 0, 0, 0, 0, 0, 0, 0), - ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), - ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), - ]; - pub fn get_field_types(index: u16) -> ::capnp::introspect::Type { - match index { + pub static ENCODED_NODE: [::capnp::Word; 152] = [ + ::capnp::word(0, 0, 0, 0, 6, 0, 6, 0), + ::capnp::word(131, 221, 25, 249, 69, 120, 250, 163), + ::capnp::word(11, 0, 0, 0, 1, 0, 2, 0), + ::capnp::word(52, 94, 58, 164, 151, 146, 249, 142), + ::capnp::word(1, 0, 7, 0, 0, 0, 8, 0), + ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(216, 4, 0, 0, 47, 11, 0, 0), + ::capnp::word(21, 0, 0, 0, 138, 0, 0, 0), + ::capnp::word(29, 0, 0, 0, 39, 0, 0, 0), + ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(49, 0, 0, 0, 199, 1, 0, 0), + ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(106, 115, 111, 110, 46, 99, 97, 112), + ::capnp::word(110, 112, 58, 86, 97, 108, 117, 101), + ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(8, 0, 0, 0, 1, 0, 1, 0), + ::capnp::word(223, 157, 214, 53, 231, 38, 16, 227), + ::capnp::word(9, 0, 0, 0, 50, 0, 0, 0), + ::capnp::word(72, 61, 201, 161, 236, 246, 217, 160), + ::capnp::word(5, 0, 0, 0, 42, 0, 0, 0), + ::capnp::word(70, 105, 101, 108, 100, 0, 0, 0), + ::capnp::word(67, 97, 108, 108, 0, 0, 0, 0), + ::capnp::word(32, 0, 0, 0, 3, 0, 4, 0), + ::capnp::word(0, 0, 255, 255, 0, 0, 0, 0), + ::capnp::word(0, 0, 1, 0, 0, 0, 0, 0), + ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(209, 0, 0, 0, 42, 0, 0, 0), + ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(204, 0, 0, 0, 3, 0, 1, 0), + ::capnp::word(216, 0, 0, 0, 2, 0, 1, 0), + ::capnp::word(1, 0, 254, 255, 16, 0, 0, 0), + ::capnp::word(0, 0, 1, 0, 1, 0, 0, 0), + ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(213, 0, 0, 0, 66, 0, 0, 0), + ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(208, 0, 0, 0, 3, 0, 1, 0), + ::capnp::word(220, 0, 0, 0, 2, 0, 1, 0), + ::capnp::word(2, 0, 253, 255, 1, 0, 0, 0), + ::capnp::word(0, 0, 1, 0, 2, 0, 0, 0), + ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(217, 0, 0, 0, 58, 0, 0, 0), + ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(212, 0, 0, 0, 3, 0, 1, 0), + ::capnp::word(224, 0, 0, 0, 2, 0, 1, 0), + ::capnp::word(3, 0, 252, 255, 0, 0, 0, 0), + ::capnp::word(0, 0, 1, 0, 3, 0, 0, 0), + ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(221, 0, 0, 0, 58, 0, 0, 0), + ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(216, 0, 0, 0, 3, 0, 1, 0), + ::capnp::word(228, 0, 0, 0, 2, 0, 1, 0), + ::capnp::word(4, 0, 251, 255, 0, 0, 0, 0), + ::capnp::word(0, 0, 1, 0, 4, 0, 0, 0), + ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(225, 0, 0, 0, 50, 0, 0, 0), + ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(220, 0, 0, 0, 3, 0, 1, 0), + ::capnp::word(248, 0, 0, 0, 2, 0, 1, 0), + ::capnp::word(5, 0, 250, 255, 0, 0, 0, 0), + ::capnp::word(0, 0, 1, 0, 5, 0, 0, 0), + ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(245, 0, 0, 0, 58, 0, 0, 0), + ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(240, 0, 0, 0, 3, 0, 1, 0), + ::capnp::word(12, 1, 0, 0, 2, 0, 1, 0), + ::capnp::word(6, 0, 249, 255, 0, 0, 0, 0), + ::capnp::word(0, 0, 1, 0, 6, 0, 0, 0), + ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(9, 1, 0, 0, 42, 0, 0, 0), + ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(4, 1, 0, 0, 3, 0, 1, 0), + ::capnp::word(16, 1, 0, 0, 2, 0, 1, 0), + ::capnp::word(7, 0, 248, 255, 0, 0, 0, 0), + ::capnp::word(0, 0, 1, 0, 7, 0, 0, 0), + ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(13, 1, 0, 0, 34, 0, 0, 0), + ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(8, 1, 0, 0, 3, 0, 1, 0), + ::capnp::word(20, 1, 0, 0, 2, 0, 1, 0), + ::capnp::word(110, 117, 108, 108, 0, 0, 0, 0), + ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(98, 111, 111, 108, 101, 97, 110, 0), + ::capnp::word(1, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(1, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(110, 117, 109, 98, 101, 114, 0, 0), + ::capnp::word(11, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(11, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(115, 116, 114, 105, 110, 103, 0, 0), + ::capnp::word(12, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(12, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(97, 114, 114, 97, 121, 0, 0, 0), + ::capnp::word(14, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(0, 0, 0, 0, 3, 0, 1, 0), + ::capnp::word(16, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(131, 221, 25, 249, 69, 120, 250, 163), + ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(14, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(111, 98, 106, 101, 99, 116, 0, 0), + ::capnp::word(14, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(0, 0, 0, 0, 3, 0, 1, 0), + ::capnp::word(16, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(223, 157, 214, 53, 231, 38, 16, 227), + ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(14, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(99, 97, 108, 108, 0, 0, 0, 0), + ::capnp::word(16, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(72, 61, 201, 161, 236, 246, 217, 160), + ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(16, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(114, 97, 119, 0, 0, 0, 0, 0), + ::capnp::word(12, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(12, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), + ]; + pub fn get_field_types(index: u16) -> ::capnp::introspect::Type { + match index { + 0 => <() as ::capnp::introspect::Introspect>::introspect(), + 1 => ::introspect(), + 2 => ::introspect(), + 3 => <::capnp::text::Owned as ::capnp::introspect::Introspect>::introspect(), + 4 => <::capnp::struct_list::Owned as ::capnp::introspect::Introspect>::introspect(), + 5 => <::capnp::struct_list::Owned as ::capnp::introspect::Introspect>::introspect(), + 6 => ::introspect(), + 7 => <::capnp::text::Owned as ::capnp::introspect::Introspect>::introspect(), + _ => ::capnp::introspect::panic_invalid_field_index(index), + } + } + pub fn get_annotation_types( + child_index: Option, + index: u32, + ) -> ::capnp::introspect::Type { + ::capnp::introspect::panic_invalid_annotation_indices(child_index, index) + } + pub static RAW_SCHEMA: ::capnp::introspect::RawStructSchema = + ::capnp::introspect::RawStructSchema { + encoded_node: &ENCODED_NODE, + nonunion_members: NONUNION_MEMBERS, + members_by_discriminant: MEMBERS_BY_DISCRIMINANT, + members_by_name: MEMBERS_BY_NAME, + }; + pub static NONUNION_MEMBERS: &[u16] = &[]; + pub static MEMBERS_BY_DISCRIMINANT: &[u16] = &[0, 1, 2, 3, 4, 5, 6, 7]; + pub static MEMBERS_BY_NAME: &[u16] = &[4, 1, 6, 0, 2, 5, 7, 3]; + pub const TYPE_ID: u64 = 0xa3fa_7845_f919_dd83; + } + pub enum Which { + Null(()), + Boolean(bool), + Number(f64), + String(A0), + Array(A1), + Object(A2), + Call(A3), + Raw(A4), + } + pub type WhichReader<'a> = Which< + ::capnp::Result<::capnp::text::Reader<'a>>, + ::capnp::Result<::capnp::struct_list::Reader<'a, crate::json_capnp::value::Owned>>, + ::capnp::Result<::capnp::struct_list::Reader<'a, crate::json_capnp::value::field::Owned>>, + ::capnp::Result>, + ::capnp::Result<::capnp::text::Reader<'a>>, + >; + pub type WhichBuilder<'a> = Which< + ::capnp::Result<::capnp::text::Builder<'a>>, + ::capnp::Result<::capnp::struct_list::Builder<'a, crate::json_capnp::value::Owned>>, + ::capnp::Result<::capnp::struct_list::Builder<'a, crate::json_capnp::value::field::Owned>>, + ::capnp::Result>, + ::capnp::Result<::capnp::text::Builder<'a>>, + >; + + pub mod field { + #[derive(Copy, Clone)] + pub struct Owned(()); + impl ::capnp::introspect::Introspect for Owned { + fn introspect() -> ::capnp::introspect::Type { + ::capnp::introspect::TypeVariant::Struct( + ::capnp::introspect::RawBrandedStructSchema { + generic: &_private::RAW_SCHEMA, + field_types: _private::get_field_types, + annotation_types: _private::get_annotation_types, + }, + ) + .into() + } + } + impl ::capnp::traits::Owned for Owned { + type Reader<'a> = Reader<'a>; + type Builder<'a> = Builder<'a>; + } + impl ::capnp::traits::OwnedStruct for Owned { + type Reader<'a> = Reader<'a>; + type Builder<'a> = Builder<'a>; + } + impl ::capnp::traits::Pipelined for Owned { + type Pipeline = Pipeline; + } + + pub struct Reader<'a> { + reader: ::capnp::private::layout::StructReader<'a>, + } + impl ::core::marker::Copy for Reader<'_> {} + impl ::core::clone::Clone for Reader<'_> { + fn clone(&self) -> Self { + *self + } + } + + impl ::capnp::traits::HasTypeId for Reader<'_> { + const TYPE_ID: u64 = _private::TYPE_ID; + } + impl<'a> ::core::convert::From<::capnp::private::layout::StructReader<'a>> for Reader<'a> { + fn from(reader: ::capnp::private::layout::StructReader<'a>) -> Self { + Self { reader } + } + } + + impl<'a> ::core::convert::From> for ::capnp::dynamic_value::Reader<'a> { + fn from(reader: Reader<'a>) -> Self { + Self::Struct(::capnp::dynamic_struct::Reader::new( + reader.reader, + ::capnp::schema::StructSchema::new( + ::capnp::introspect::RawBrandedStructSchema { + generic: &_private::RAW_SCHEMA, + field_types: _private::get_field_types, + annotation_types: _private::get_annotation_types, + }, + ), + )) + } + } + + impl ::core::fmt::Debug for Reader<'_> { + fn fmt( + &self, + f: &mut ::core::fmt::Formatter<'_>, + ) -> ::core::result::Result<(), ::core::fmt::Error> { + core::fmt::Debug::fmt( + &::core::convert::Into::<::capnp::dynamic_value::Reader<'_>>::into(*self), + f, + ) + } + } + + impl<'a> ::capnp::traits::FromPointerReader<'a> for Reader<'a> { + fn get_from_pointer( + reader: &::capnp::private::layout::PointerReader<'a>, + default: ::core::option::Option<&'a [::capnp::Word]>, + ) -> ::capnp::Result { + ::core::result::Result::Ok(reader.get_struct(default)?.into()) + } + } + + impl<'a> ::capnp::traits::IntoInternalStructReader<'a> for Reader<'a> { + fn into_internal_struct_reader(self) -> ::capnp::private::layout::StructReader<'a> { + self.reader + } + } + + impl<'a> ::capnp::traits::Imbue<'a> for Reader<'a> { + fn imbue(&mut self, cap_table: &'a ::capnp::private::layout::CapTable) { + self.reader + .imbue(::capnp::private::layout::CapTableReader::Plain(cap_table)) + } + } + + impl<'a> Reader<'a> { + pub fn reborrow(&self) -> Reader<'_> { + Self { ..*self } + } + + pub fn total_size(&self) -> ::capnp::Result<::capnp::MessageSize> { + self.reader.total_size() + } + #[inline] + pub fn get_name(self) -> ::capnp::Result<::capnp::text::Reader<'a>> { + ::capnp::traits::FromPointerReader::get_from_pointer( + &self.reader.get_pointer_field(0), + ::core::option::Option::None, + ) + } + #[inline] + pub fn has_name(&self) -> bool { + !self.reader.get_pointer_field(0).is_null() + } + #[inline] + pub fn get_value(self) -> ::capnp::Result> { + ::capnp::traits::FromPointerReader::get_from_pointer( + &self.reader.get_pointer_field(1), + ::core::option::Option::None, + ) + } + #[inline] + pub fn has_value(&self) -> bool { + !self.reader.get_pointer_field(1).is_null() + } + } + + pub struct Builder<'a> { + builder: ::capnp::private::layout::StructBuilder<'a>, + } + impl ::capnp::traits::HasStructSize for Builder<'_> { + const STRUCT_SIZE: ::capnp::private::layout::StructSize = + ::capnp::private::layout::StructSize { + data: 0, + pointers: 2, + }; + } + impl ::capnp::traits::HasTypeId for Builder<'_> { + const TYPE_ID: u64 = _private::TYPE_ID; + } + impl<'a> ::core::convert::From<::capnp::private::layout::StructBuilder<'a>> for Builder<'a> { + fn from(builder: ::capnp::private::layout::StructBuilder<'a>) -> Self { + Self { builder } + } + } + + impl<'a> ::core::convert::From> for ::capnp::dynamic_value::Builder<'a> { + fn from(builder: Builder<'a>) -> Self { + Self::Struct(::capnp::dynamic_struct::Builder::new( + builder.builder, + ::capnp::schema::StructSchema::new( + ::capnp::introspect::RawBrandedStructSchema { + generic: &_private::RAW_SCHEMA, + field_types: _private::get_field_types, + annotation_types: _private::get_annotation_types, + }, + ), + )) + } + } + + impl<'a> ::capnp::traits::ImbueMut<'a> for Builder<'a> { + fn imbue_mut(&mut self, cap_table: &'a mut ::capnp::private::layout::CapTable) { + self.builder + .imbue(::capnp::private::layout::CapTableBuilder::Plain(cap_table)) + } + } + + impl<'a> ::capnp::traits::FromPointerBuilder<'a> for Builder<'a> { + fn init_pointer( + builder: ::capnp::private::layout::PointerBuilder<'a>, + _size: u32, + ) -> Self { + builder + .init_struct(::STRUCT_SIZE) + .into() + } + fn get_from_pointer( + builder: ::capnp::private::layout::PointerBuilder<'a>, + default: ::core::option::Option<&'a [::capnp::Word]>, + ) -> ::capnp::Result { + ::core::result::Result::Ok( + builder + .get_struct( + ::STRUCT_SIZE, + default, + )? + .into(), + ) + } + } + + impl ::capnp::traits::SetterInput for Reader<'_> { + fn set_pointer_builder( + mut pointer: ::capnp::private::layout::PointerBuilder<'_>, + value: Self, + canonicalize: bool, + ) -> ::capnp::Result<()> { + pointer.set_struct(&value.reader, canonicalize) + } + } + + impl<'a> Builder<'a> { + pub fn into_reader(self) -> Reader<'a> { + self.builder.into_reader().into() + } + pub fn reborrow(&mut self) -> Builder<'_> { + Builder { + builder: self.builder.reborrow(), + } + } + pub fn reborrow_as_reader(&self) -> Reader<'_> { + self.builder.as_reader().into() + } + + pub fn total_size(&self) -> ::capnp::Result<::capnp::MessageSize> { + self.builder.as_reader().total_size() + } + #[inline] + pub fn get_name(self) -> ::capnp::Result<::capnp::text::Builder<'a>> { + ::capnp::traits::FromPointerBuilder::get_from_pointer( + self.builder.get_pointer_field(0), + ::core::option::Option::None, + ) + } + #[inline] + pub fn set_name( + &mut self, + value: impl ::capnp::traits::SetterInput<::capnp::text::Owned>, + ) { + ::capnp::traits::SetterInput::set_pointer_builder( + self.builder.reborrow().get_pointer_field(0), + value, + false, + ) + .unwrap() + } + #[inline] + pub fn init_name(self, size: u32) -> ::capnp::text::Builder<'a> { + self.builder.get_pointer_field(0).init_text(size) + } + #[inline] + pub fn has_name(&self) -> bool { + !self.builder.is_pointer_field_null(0) + } + #[inline] + pub fn get_value(self) -> ::capnp::Result> { + ::capnp::traits::FromPointerBuilder::get_from_pointer( + self.builder.get_pointer_field(1), + ::core::option::Option::None, + ) + } + #[inline] + pub fn set_value( + &mut self, + value: crate::json_capnp::value::Reader<'_>, + ) -> ::capnp::Result<()> { + ::capnp::traits::SetterInput::set_pointer_builder( + self.builder.reborrow().get_pointer_field(1), + value, + false, + ) + } + #[inline] + pub fn init_value(self) -> crate::json_capnp::value::Builder<'a> { + ::capnp::traits::FromPointerBuilder::init_pointer( + self.builder.get_pointer_field(1), + 0, + ) + } + #[inline] + pub fn has_value(&self) -> bool { + !self.builder.is_pointer_field_null(1) + } + } + + pub struct Pipeline { + _typeless: ::capnp::any_pointer::Pipeline, + } + impl ::capnp::capability::FromTypelessPipeline for Pipeline { + fn new(typeless: ::capnp::any_pointer::Pipeline) -> Self { + Self { + _typeless: typeless, + } + } + } + impl Pipeline { + pub fn get_value(&self) -> crate::json_capnp::value::Pipeline { + ::capnp::capability::FromTypelessPipeline::new(self._typeless.get_pointer_field(1)) + } + } + mod _private { + pub static ENCODED_NODE: [::capnp::Word; 48] = [ + ::capnp::word(0, 0, 0, 0, 6, 0, 6, 0), + ::capnp::word(223, 157, 214, 53, 231, 38, 16, 227), + ::capnp::word(17, 0, 0, 0, 1, 0, 0, 0), + ::capnp::word(131, 221, 25, 249, 69, 120, 250, 163), + ::capnp::word(2, 0, 7, 0, 0, 0, 0, 0), + ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(171, 10, 0, 0, 229, 10, 0, 0), + ::capnp::word(21, 0, 0, 0, 186, 0, 0, 0), + ::capnp::word(29, 0, 0, 0, 7, 0, 0, 0), + ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(25, 0, 0, 0, 119, 0, 0, 0), + ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(106, 115, 111, 110, 46, 99, 97, 112), + ::capnp::word(110, 112, 58, 86, 97, 108, 117, 101), + ::capnp::word(46, 70, 105, 101, 108, 100, 0, 0), + ::capnp::word(0, 0, 0, 0, 1, 0, 1, 0), + ::capnp::word(8, 0, 0, 0, 3, 0, 4, 0), + ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(0, 0, 1, 0, 0, 0, 0, 0), + ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(41, 0, 0, 0, 42, 0, 0, 0), + ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(36, 0, 0, 0, 3, 0, 1, 0), + ::capnp::word(48, 0, 0, 0, 2, 0, 1, 0), + ::capnp::word(1, 0, 0, 0, 1, 0, 0, 0), + ::capnp::word(0, 0, 1, 0, 1, 0, 0, 0), + ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(45, 0, 0, 0, 50, 0, 0, 0), + ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(40, 0, 0, 0, 3, 0, 1, 0), + ::capnp::word(52, 0, 0, 0, 2, 0, 1, 0), + ::capnp::word(110, 97, 109, 101, 0, 0, 0, 0), + ::capnp::word(12, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(12, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(118, 97, 108, 117, 101, 0, 0, 0), + ::capnp::word(16, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(131, 221, 25, 249, 69, 120, 250, 163), + ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(16, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), + ]; + pub fn get_field_types(index: u16) -> ::capnp::introspect::Type { + match index { 0 => <::capnp::text::Owned as ::capnp::introspect::Introspect>::introspect(), 1 => ::introspect(), _ => ::capnp::introspect::panic_invalid_field_index(index), } - } - pub fn get_annotation_types(child_index: Option, index: u32) -> ::capnp::introspect::Type { - ::capnp::introspect::panic_invalid_annotation_indices(child_index, index) - } - pub static RAW_SCHEMA: ::capnp::introspect::RawStructSchema = ::capnp::introspect::RawStructSchema { - encoded_node: &ENCODED_NODE, - nonunion_members: NONUNION_MEMBERS, - members_by_discriminant: MEMBERS_BY_DISCRIMINANT, - members_by_name: MEMBERS_BY_NAME, - }; - pub static NONUNION_MEMBERS : &[u16] = &[0,1]; - pub static MEMBERS_BY_DISCRIMINANT : &[u16] = &[]; - pub static MEMBERS_BY_NAME : &[u16] = &[0,1]; - pub const TYPE_ID: u64 = 0xe310_26e7_35d6_9ddf; - } - } - - pub mod call { + } + pub fn get_annotation_types( + child_index: Option, + index: u32, + ) -> ::capnp::introspect::Type { + ::capnp::introspect::panic_invalid_annotation_indices(child_index, index) + } + pub static RAW_SCHEMA: ::capnp::introspect::RawStructSchema = + ::capnp::introspect::RawStructSchema { + encoded_node: &ENCODED_NODE, + nonunion_members: NONUNION_MEMBERS, + members_by_discriminant: MEMBERS_BY_DISCRIMINANT, + members_by_name: MEMBERS_BY_NAME, + }; + pub static NONUNION_MEMBERS: &[u16] = &[0, 1]; + pub static MEMBERS_BY_DISCRIMINANT: &[u16] = &[]; + pub static MEMBERS_BY_NAME: &[u16] = &[0, 1]; + pub const TYPE_ID: u64 = 0xe310_26e7_35d6_9ddf; + } + } + + pub mod call { + #[derive(Copy, Clone)] + pub struct Owned(()); + impl ::capnp::introspect::Introspect for Owned { + fn introspect() -> ::capnp::introspect::Type { + ::capnp::introspect::TypeVariant::Struct( + ::capnp::introspect::RawBrandedStructSchema { + generic: &_private::RAW_SCHEMA, + field_types: _private::get_field_types, + annotation_types: _private::get_annotation_types, + }, + ) + .into() + } + } + impl ::capnp::traits::Owned for Owned { + type Reader<'a> = Reader<'a>; + type Builder<'a> = Builder<'a>; + } + impl ::capnp::traits::OwnedStruct for Owned { + type Reader<'a> = Reader<'a>; + type Builder<'a> = Builder<'a>; + } + impl ::capnp::traits::Pipelined for Owned { + type Pipeline = Pipeline; + } + + pub struct Reader<'a> { + reader: ::capnp::private::layout::StructReader<'a>, + } + impl ::core::marker::Copy for Reader<'_> {} + impl ::core::clone::Clone for Reader<'_> { + fn clone(&self) -> Self { + *self + } + } + + impl ::capnp::traits::HasTypeId for Reader<'_> { + const TYPE_ID: u64 = _private::TYPE_ID; + } + impl<'a> ::core::convert::From<::capnp::private::layout::StructReader<'a>> for Reader<'a> { + fn from(reader: ::capnp::private::layout::StructReader<'a>) -> Self { + Self { reader } + } + } + + impl<'a> ::core::convert::From> for ::capnp::dynamic_value::Reader<'a> { + fn from(reader: Reader<'a>) -> Self { + Self::Struct(::capnp::dynamic_struct::Reader::new( + reader.reader, + ::capnp::schema::StructSchema::new( + ::capnp::introspect::RawBrandedStructSchema { + generic: &_private::RAW_SCHEMA, + field_types: _private::get_field_types, + annotation_types: _private::get_annotation_types, + }, + ), + )) + } + } + + impl ::core::fmt::Debug for Reader<'_> { + fn fmt( + &self, + f: &mut ::core::fmt::Formatter<'_>, + ) -> ::core::result::Result<(), ::core::fmt::Error> { + core::fmt::Debug::fmt( + &::core::convert::Into::<::capnp::dynamic_value::Reader<'_>>::into(*self), + f, + ) + } + } + + impl<'a> ::capnp::traits::FromPointerReader<'a> for Reader<'a> { + fn get_from_pointer( + reader: &::capnp::private::layout::PointerReader<'a>, + default: ::core::option::Option<&'a [::capnp::Word]>, + ) -> ::capnp::Result { + ::core::result::Result::Ok(reader.get_struct(default)?.into()) + } + } + + impl<'a> ::capnp::traits::IntoInternalStructReader<'a> for Reader<'a> { + fn into_internal_struct_reader(self) -> ::capnp::private::layout::StructReader<'a> { + self.reader + } + } + + impl<'a> ::capnp::traits::Imbue<'a> for Reader<'a> { + fn imbue(&mut self, cap_table: &'a ::capnp::private::layout::CapTable) { + self.reader + .imbue(::capnp::private::layout::CapTableReader::Plain(cap_table)) + } + } + + impl<'a> Reader<'a> { + pub fn reborrow(&self) -> Reader<'_> { + Self { ..*self } + } + + pub fn total_size(&self) -> ::capnp::Result<::capnp::MessageSize> { + self.reader.total_size() + } + #[inline] + pub fn get_function(self) -> ::capnp::Result<::capnp::text::Reader<'a>> { + ::capnp::traits::FromPointerReader::get_from_pointer( + &self.reader.get_pointer_field(0), + ::core::option::Option::None, + ) + } + #[inline] + pub fn has_function(&self) -> bool { + !self.reader.get_pointer_field(0).is_null() + } + #[inline] + pub fn get_params( + self, + ) -> ::capnp::Result<::capnp::struct_list::Reader<'a, crate::json_capnp::value::Owned>> + { + ::capnp::traits::FromPointerReader::get_from_pointer( + &self.reader.get_pointer_field(1), + ::core::option::Option::None, + ) + } + #[inline] + pub fn has_params(&self) -> bool { + !self.reader.get_pointer_field(1).is_null() + } + } + + pub struct Builder<'a> { + builder: ::capnp::private::layout::StructBuilder<'a>, + } + impl ::capnp::traits::HasStructSize for Builder<'_> { + const STRUCT_SIZE: ::capnp::private::layout::StructSize = + ::capnp::private::layout::StructSize { + data: 0, + pointers: 2, + }; + } + impl ::capnp::traits::HasTypeId for Builder<'_> { + const TYPE_ID: u64 = _private::TYPE_ID; + } + impl<'a> ::core::convert::From<::capnp::private::layout::StructBuilder<'a>> for Builder<'a> { + fn from(builder: ::capnp::private::layout::StructBuilder<'a>) -> Self { + Self { builder } + } + } + + impl<'a> ::core::convert::From> for ::capnp::dynamic_value::Builder<'a> { + fn from(builder: Builder<'a>) -> Self { + Self::Struct(::capnp::dynamic_struct::Builder::new( + builder.builder, + ::capnp::schema::StructSchema::new( + ::capnp::introspect::RawBrandedStructSchema { + generic: &_private::RAW_SCHEMA, + field_types: _private::get_field_types, + annotation_types: _private::get_annotation_types, + }, + ), + )) + } + } + + impl<'a> ::capnp::traits::ImbueMut<'a> for Builder<'a> { + fn imbue_mut(&mut self, cap_table: &'a mut ::capnp::private::layout::CapTable) { + self.builder + .imbue(::capnp::private::layout::CapTableBuilder::Plain(cap_table)) + } + } + + impl<'a> ::capnp::traits::FromPointerBuilder<'a> for Builder<'a> { + fn init_pointer( + builder: ::capnp::private::layout::PointerBuilder<'a>, + _size: u32, + ) -> Self { + builder + .init_struct(::STRUCT_SIZE) + .into() + } + fn get_from_pointer( + builder: ::capnp::private::layout::PointerBuilder<'a>, + default: ::core::option::Option<&'a [::capnp::Word]>, + ) -> ::capnp::Result { + ::core::result::Result::Ok( + builder + .get_struct( + ::STRUCT_SIZE, + default, + )? + .into(), + ) + } + } + + impl ::capnp::traits::SetterInput for Reader<'_> { + fn set_pointer_builder( + mut pointer: ::capnp::private::layout::PointerBuilder<'_>, + value: Self, + canonicalize: bool, + ) -> ::capnp::Result<()> { + pointer.set_struct(&value.reader, canonicalize) + } + } + + impl<'a> Builder<'a> { + pub fn into_reader(self) -> Reader<'a> { + self.builder.into_reader().into() + } + pub fn reborrow(&mut self) -> Builder<'_> { + Builder { + builder: self.builder.reborrow(), + } + } + pub fn reborrow_as_reader(&self) -> Reader<'_> { + self.builder.as_reader().into() + } + + pub fn total_size(&self) -> ::capnp::Result<::capnp::MessageSize> { + self.builder.as_reader().total_size() + } + #[inline] + pub fn get_function(self) -> ::capnp::Result<::capnp::text::Builder<'a>> { + ::capnp::traits::FromPointerBuilder::get_from_pointer( + self.builder.get_pointer_field(0), + ::core::option::Option::None, + ) + } + #[inline] + pub fn set_function( + &mut self, + value: impl ::capnp::traits::SetterInput<::capnp::text::Owned>, + ) { + ::capnp::traits::SetterInput::set_pointer_builder( + self.builder.reborrow().get_pointer_field(0), + value, + false, + ) + .unwrap() + } + #[inline] + pub fn init_function(self, size: u32) -> ::capnp::text::Builder<'a> { + self.builder.get_pointer_field(0).init_text(size) + } + #[inline] + pub fn has_function(&self) -> bool { + !self.builder.is_pointer_field_null(0) + } + #[inline] + pub fn get_params( + self, + ) -> ::capnp::Result<::capnp::struct_list::Builder<'a, crate::json_capnp::value::Owned>> + { + ::capnp::traits::FromPointerBuilder::get_from_pointer( + self.builder.get_pointer_field(1), + ::core::option::Option::None, + ) + } + #[inline] + pub fn set_params( + &mut self, + value: ::capnp::struct_list::Reader<'_, crate::json_capnp::value::Owned>, + ) -> ::capnp::Result<()> { + ::capnp::traits::SetterInput::set_pointer_builder( + self.builder.reborrow().get_pointer_field(1), + value, + false, + ) + } + #[inline] + pub fn init_params( + self, + size: u32, + ) -> ::capnp::struct_list::Builder<'a, crate::json_capnp::value::Owned> { + ::capnp::traits::FromPointerBuilder::init_pointer( + self.builder.get_pointer_field(1), + size, + ) + } + #[inline] + pub fn has_params(&self) -> bool { + !self.builder.is_pointer_field_null(1) + } + } + + pub struct Pipeline { + _typeless: ::capnp::any_pointer::Pipeline, + } + impl ::capnp::capability::FromTypelessPipeline for Pipeline { + fn new(typeless: ::capnp::any_pointer::Pipeline) -> Self { + Self { + _typeless: typeless, + } + } + } + impl Pipeline {} + mod _private { + pub static ENCODED_NODE: [::capnp::Word; 53] = [ + ::capnp::word(0, 0, 0, 0, 6, 0, 6, 0), + ::capnp::word(72, 61, 201, 161, 236, 246, 217, 160), + ::capnp::word(17, 0, 0, 0, 1, 0, 0, 0), + ::capnp::word(131, 221, 25, 249, 69, 120, 250, 163), + ::capnp::word(2, 0, 7, 0, 0, 0, 0, 0), + ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(233, 10, 0, 0, 45, 11, 0, 0), + ::capnp::word(21, 0, 0, 0, 178, 0, 0, 0), + ::capnp::word(29, 0, 0, 0, 7, 0, 0, 0), + ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(25, 0, 0, 0, 119, 0, 0, 0), + ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(106, 115, 111, 110, 46, 99, 97, 112), + ::capnp::word(110, 112, 58, 86, 97, 108, 117, 101), + ::capnp::word(46, 67, 97, 108, 108, 0, 0, 0), + ::capnp::word(0, 0, 0, 0, 1, 0, 1, 0), + ::capnp::word(8, 0, 0, 0, 3, 0, 4, 0), + ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(0, 0, 1, 0, 0, 0, 0, 0), + ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(41, 0, 0, 0, 74, 0, 0, 0), + ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(40, 0, 0, 0, 3, 0, 1, 0), + ::capnp::word(52, 0, 0, 0, 2, 0, 1, 0), + ::capnp::word(1, 0, 0, 0, 1, 0, 0, 0), + ::capnp::word(0, 0, 1, 0, 1, 0, 0, 0), + ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(49, 0, 0, 0, 58, 0, 0, 0), + ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(44, 0, 0, 0, 3, 0, 1, 0), + ::capnp::word(72, 0, 0, 0, 2, 0, 1, 0), + ::capnp::word(102, 117, 110, 99, 116, 105, 111, 110), + ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(12, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(12, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(112, 97, 114, 97, 109, 115, 0, 0), + ::capnp::word(14, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(0, 0, 0, 0, 3, 0, 1, 0), + ::capnp::word(16, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(131, 221, 25, 249, 69, 120, 250, 163), + ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(14, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), + ]; + pub fn get_field_types(index: u16) -> ::capnp::introspect::Type { + match index { + 0 => <::capnp::text::Owned as ::capnp::introspect::Introspect>::introspect(), + 1 => <::capnp::struct_list::Owned as ::capnp::introspect::Introspect>::introspect(), + _ => ::capnp::introspect::panic_invalid_field_index(index), + } + } + pub fn get_annotation_types( + child_index: Option, + index: u32, + ) -> ::capnp::introspect::Type { + ::capnp::introspect::panic_invalid_annotation_indices(child_index, index) + } + pub static RAW_SCHEMA: ::capnp::introspect::RawStructSchema = + ::capnp::introspect::RawStructSchema { + encoded_node: &ENCODED_NODE, + nonunion_members: NONUNION_MEMBERS, + members_by_discriminant: MEMBERS_BY_DISCRIMINANT, + members_by_name: MEMBERS_BY_NAME, + }; + pub static NONUNION_MEMBERS: &[u16] = &[0, 1]; + pub static MEMBERS_BY_DISCRIMINANT: &[u16] = &[]; + pub static MEMBERS_BY_NAME: &[u16] = &[0, 1]; + pub const TYPE_ID: u64 = 0xa0d9_f6ec_a1c9_3d48; + } + } +} +pub mod name { + pub const ID: u64 = 0xfa5b1fd61c2e7c3d; + pub fn get_type() -> ::capnp::introspect::Type { + <::capnp::text::Owned as ::capnp::introspect::Introspect>::introspect() + } +} +pub mod flatten { + pub const ID: u64 = 0x82d3e852af0336bf; + pub fn get_type() -> ::capnp::introspect::Type { + ::introspect() + } +} + +pub mod flatten_options { #[derive(Copy, Clone)] pub struct Owned(()); - impl ::capnp::introspect::Introspect for Owned { fn introspect() -> ::capnp::introspect::Type { ::capnp::introspect::TypeVariant::Struct(::capnp::introspect::RawBrandedStructSchema { generic: &_private::RAW_SCHEMA, field_types: _private::get_field_types, annotation_types: _private::get_annotation_types }).into() } } - impl ::capnp::traits::Owned for Owned { type Reader<'a> = Reader<'a>; type Builder<'a> = Builder<'a>; } - impl ::capnp::traits::OwnedStruct for Owned { type Reader<'a> = Reader<'a>; type Builder<'a> = Builder<'a>; } - impl ::capnp::traits::Pipelined for Owned { type Pipeline = Pipeline; } + impl ::capnp::introspect::Introspect for Owned { + fn introspect() -> ::capnp::introspect::Type { + ::capnp::introspect::TypeVariant::Struct(::capnp::introspect::RawBrandedStructSchema { + generic: &_private::RAW_SCHEMA, + field_types: _private::get_field_types, + annotation_types: _private::get_annotation_types, + }) + .into() + } + } + impl ::capnp::traits::Owned for Owned { + type Reader<'a> = Reader<'a>; + type Builder<'a> = Builder<'a>; + } + impl ::capnp::traits::OwnedStruct for Owned { + type Reader<'a> = Reader<'a>; + type Builder<'a> = Builder<'a>; + } + impl ::capnp::traits::Pipelined for Owned { + type Pipeline = Pipeline; + } - pub struct Reader<'a> { reader: ::capnp::private::layout::StructReader<'a> } - impl <> ::core::marker::Copy for Reader<'_,> {} - impl <> ::core::clone::Clone for Reader<'_,> { - fn clone(&self) -> Self { *self } + pub struct Reader<'a> { + reader: ::capnp::private::layout::StructReader<'a>, + } + impl ::core::marker::Copy for Reader<'_> {} + impl ::core::clone::Clone for Reader<'_> { + fn clone(&self) -> Self { + *self + } } - impl <> ::capnp::traits::HasTypeId for Reader<'_,> { - const TYPE_ID: u64 = _private::TYPE_ID; + impl ::capnp::traits::HasTypeId for Reader<'_> { + const TYPE_ID: u64 = _private::TYPE_ID; } - impl <'a,> ::core::convert::From<::capnp::private::layout::StructReader<'a>> for Reader<'a,> { - fn from(reader: ::capnp::private::layout::StructReader<'a>) -> Self { - Self { reader, } - } + impl<'a> ::core::convert::From<::capnp::private::layout::StructReader<'a>> for Reader<'a> { + fn from(reader: ::capnp::private::layout::StructReader<'a>) -> Self { + Self { reader } + } } - impl <'a,> ::core::convert::From> for ::capnp::dynamic_value::Reader<'a> { - fn from(reader: Reader<'a,>) -> Self { - Self::Struct(::capnp::dynamic_struct::Reader::new(reader.reader, ::capnp::schema::StructSchema::new(::capnp::introspect::RawBrandedStructSchema { generic: &_private::RAW_SCHEMA, field_types: _private::get_field_types::<>, annotation_types: _private::get_annotation_types::<>}))) - } + impl<'a> ::core::convert::From> for ::capnp::dynamic_value::Reader<'a> { + fn from(reader: Reader<'a>) -> Self { + Self::Struct(::capnp::dynamic_struct::Reader::new( + reader.reader, + ::capnp::schema::StructSchema::new(::capnp::introspect::RawBrandedStructSchema { + generic: &_private::RAW_SCHEMA, + field_types: _private::get_field_types, + annotation_types: _private::get_annotation_types, + }), + )) + } } - impl <> ::core::fmt::Debug for Reader<'_,> { - fn fmt(&self, f: &mut ::core::fmt::Formatter<'_>) -> ::core::result::Result<(), ::core::fmt::Error> { - core::fmt::Debug::fmt(&::core::convert::Into::<::capnp::dynamic_value::Reader<'_>>::into(*self), f) - } + impl ::core::fmt::Debug for Reader<'_> { + fn fmt( + &self, + f: &mut ::core::fmt::Formatter<'_>, + ) -> ::core::result::Result<(), ::core::fmt::Error> { + core::fmt::Debug::fmt( + &::core::convert::Into::<::capnp::dynamic_value::Reader<'_>>::into(*self), + f, + ) + } } - impl <'a,> ::capnp::traits::FromPointerReader<'a> for Reader<'a,> { - fn get_from_pointer(reader: &::capnp::private::layout::PointerReader<'a>, default: ::core::option::Option<&'a [::capnp::Word]>) -> ::capnp::Result { - ::core::result::Result::Ok(reader.get_struct(default)?.into()) - } + impl<'a> ::capnp::traits::FromPointerReader<'a> for Reader<'a> { + fn get_from_pointer( + reader: &::capnp::private::layout::PointerReader<'a>, + default: ::core::option::Option<&'a [::capnp::Word]>, + ) -> ::capnp::Result { + ::core::result::Result::Ok(reader.get_struct(default)?.into()) + } } - impl <'a,> ::capnp::traits::IntoInternalStructReader<'a> for Reader<'a,> { - fn into_internal_struct_reader(self) -> ::capnp::private::layout::StructReader<'a> { - self.reader - } + impl<'a> ::capnp::traits::IntoInternalStructReader<'a> for Reader<'a> { + fn into_internal_struct_reader(self) -> ::capnp::private::layout::StructReader<'a> { + self.reader + } } - impl <'a,> ::capnp::traits::Imbue<'a> for Reader<'a,> { - fn imbue(&mut self, cap_table: &'a ::capnp::private::layout::CapTable) { - self.reader.imbue(::capnp::private::layout::CapTableReader::Plain(cap_table)) - } + impl<'a> ::capnp::traits::Imbue<'a> for Reader<'a> { + fn imbue(&mut self, cap_table: &'a ::capnp::private::layout::CapTable) { + self.reader + .imbue(::capnp::private::layout::CapTableReader::Plain(cap_table)) + } } - impl <'a,> Reader<'a,> { - pub fn reborrow(&self) -> Reader<'_,> { - Self { .. *self } - } + impl<'a> Reader<'a> { + pub fn reborrow(&self) -> Reader<'_> { + Self { ..*self } + } - pub fn total_size(&self) -> ::capnp::Result<::capnp::MessageSize> { - self.reader.total_size() - } - #[inline] - pub fn get_function(self) -> ::capnp::Result<::capnp::text::Reader<'a>> { - ::capnp::traits::FromPointerReader::get_from_pointer(&self.reader.get_pointer_field(0), ::core::option::Option::None) - } - #[inline] - pub fn has_function(&self) -> bool { - !self.reader.get_pointer_field(0).is_null() - } - #[inline] - pub fn get_params(self) -> ::capnp::Result<::capnp::struct_list::Reader<'a,crate::json_capnp::value::Owned>> { - ::capnp::traits::FromPointerReader::get_from_pointer(&self.reader.get_pointer_field(1), ::core::option::Option::None) - } - #[inline] - pub fn has_params(&self) -> bool { - !self.reader.get_pointer_field(1).is_null() - } + pub fn total_size(&self) -> ::capnp::Result<::capnp::MessageSize> { + self.reader.total_size() + } + #[inline] + pub fn get_prefix(self) -> ::capnp::Result<::capnp::text::Reader<'a>> { + ::capnp::traits::FromPointerReader::get_from_pointer( + &self.reader.get_pointer_field(0), + ::core::option::Option::Some(&_private::DEFAULT_PREFIX[..]), + ) + } + #[inline] + pub fn has_prefix(&self) -> bool { + !self.reader.get_pointer_field(0).is_null() + } } - pub struct Builder<'a> { builder: ::capnp::private::layout::StructBuilder<'a> } - impl <> ::capnp::traits::HasStructSize for Builder<'_,> { - const STRUCT_SIZE: ::capnp::private::layout::StructSize = ::capnp::private::layout::StructSize { data: 0, pointers: 2 }; + pub struct Builder<'a> { + builder: ::capnp::private::layout::StructBuilder<'a>, } - impl <> ::capnp::traits::HasTypeId for Builder<'_,> { - const TYPE_ID: u64 = _private::TYPE_ID; + impl ::capnp::traits::HasStructSize for Builder<'_> { + const STRUCT_SIZE: ::capnp::private::layout::StructSize = + ::capnp::private::layout::StructSize { + data: 0, + pointers: 1, + }; } - impl <'a,> ::core::convert::From<::capnp::private::layout::StructBuilder<'a>> for Builder<'a,> { - fn from(builder: ::capnp::private::layout::StructBuilder<'a>) -> Self { - Self { builder, } - } + impl ::capnp::traits::HasTypeId for Builder<'_> { + const TYPE_ID: u64 = _private::TYPE_ID; + } + impl<'a> ::core::convert::From<::capnp::private::layout::StructBuilder<'a>> for Builder<'a> { + fn from(builder: ::capnp::private::layout::StructBuilder<'a>) -> Self { + Self { builder } + } } - impl <'a,> ::core::convert::From> for ::capnp::dynamic_value::Builder<'a> { - fn from(builder: Builder<'a,>) -> Self { - Self::Struct(::capnp::dynamic_struct::Builder::new(builder.builder, ::capnp::schema::StructSchema::new(::capnp::introspect::RawBrandedStructSchema { generic: &_private::RAW_SCHEMA, field_types: _private::get_field_types::<>, annotation_types: _private::get_annotation_types::<>}))) - } + impl<'a> ::core::convert::From> for ::capnp::dynamic_value::Builder<'a> { + fn from(builder: Builder<'a>) -> Self { + Self::Struct(::capnp::dynamic_struct::Builder::new( + builder.builder, + ::capnp::schema::StructSchema::new(::capnp::introspect::RawBrandedStructSchema { + generic: &_private::RAW_SCHEMA, + field_types: _private::get_field_types, + annotation_types: _private::get_annotation_types, + }), + )) + } } - impl <'a,> ::capnp::traits::ImbueMut<'a> for Builder<'a,> { - fn imbue_mut(&mut self, cap_table: &'a mut ::capnp::private::layout::CapTable) { - self.builder.imbue(::capnp::private::layout::CapTableBuilder::Plain(cap_table)) - } + impl<'a> ::capnp::traits::ImbueMut<'a> for Builder<'a> { + fn imbue_mut(&mut self, cap_table: &'a mut ::capnp::private::layout::CapTable) { + self.builder + .imbue(::capnp::private::layout::CapTableBuilder::Plain(cap_table)) + } } - impl <'a,> ::capnp::traits::FromPointerBuilder<'a> for Builder<'a,> { - fn init_pointer(builder: ::capnp::private::layout::PointerBuilder<'a>, _size: u32) -> Self { - builder.init_struct(::STRUCT_SIZE).into() - } - fn get_from_pointer(builder: ::capnp::private::layout::PointerBuilder<'a>, default: ::core::option::Option<&'a [::capnp::Word]>) -> ::capnp::Result { - ::core::result::Result::Ok(builder.get_struct(::STRUCT_SIZE, default)?.into()) - } + impl<'a> ::capnp::traits::FromPointerBuilder<'a> for Builder<'a> { + fn init_pointer(builder: ::capnp::private::layout::PointerBuilder<'a>, _size: u32) -> Self { + builder + .init_struct(::STRUCT_SIZE) + .into() + } + fn get_from_pointer( + builder: ::capnp::private::layout::PointerBuilder<'a>, + default: ::core::option::Option<&'a [::capnp::Word]>, + ) -> ::capnp::Result { + ::core::result::Result::Ok( + builder + .get_struct( + ::STRUCT_SIZE, + default, + )? + .into(), + ) + } } - impl <> ::capnp::traits::SetterInput> for Reader<'_,> { - fn set_pointer_builder(mut pointer: ::capnp::private::layout::PointerBuilder<'_>, value: Self, canonicalize: bool) -> ::capnp::Result<()> { pointer.set_struct(&value.reader, canonicalize) } + impl ::capnp::traits::SetterInput for Reader<'_> { + fn set_pointer_builder( + mut pointer: ::capnp::private::layout::PointerBuilder<'_>, + value: Self, + canonicalize: bool, + ) -> ::capnp::Result<()> { + pointer.set_struct(&value.reader, canonicalize) + } } - impl <'a,> Builder<'a,> { - pub fn into_reader(self) -> Reader<'a,> { - self.builder.into_reader().into() - } - pub fn reborrow(&mut self) -> Builder<'_,> { - Builder { builder: self.builder.reborrow() } - } - pub fn reborrow_as_reader(&self) -> Reader<'_,> { - self.builder.as_reader().into() - } + impl<'a> Builder<'a> { + pub fn into_reader(self) -> Reader<'a> { + self.builder.into_reader().into() + } + pub fn reborrow(&mut self) -> Builder<'_> { + Builder { + builder: self.builder.reborrow(), + } + } + pub fn reborrow_as_reader(&self) -> Reader<'_> { + self.builder.as_reader().into() + } - pub fn total_size(&self) -> ::capnp::Result<::capnp::MessageSize> { - self.builder.as_reader().total_size() - } - #[inline] - pub fn get_function(self) -> ::capnp::Result<::capnp::text::Builder<'a>> { - ::capnp::traits::FromPointerBuilder::get_from_pointer(self.builder.get_pointer_field(0), ::core::option::Option::None) - } - #[inline] - pub fn set_function(&mut self, value: impl ::capnp::traits::SetterInput<::capnp::text::Owned>) { - ::capnp::traits::SetterInput::set_pointer_builder(self.builder.reborrow().get_pointer_field(0), value, false).unwrap() - } - #[inline] - pub fn init_function(self, size: u32) -> ::capnp::text::Builder<'a> { - self.builder.get_pointer_field(0).init_text(size) - } - #[inline] - pub fn has_function(&self) -> bool { - !self.builder.is_pointer_field_null(0) - } - #[inline] - pub fn get_params(self) -> ::capnp::Result<::capnp::struct_list::Builder<'a,crate::json_capnp::value::Owned>> { - ::capnp::traits::FromPointerBuilder::get_from_pointer(self.builder.get_pointer_field(1), ::core::option::Option::None) - } - #[inline] - pub fn set_params(&mut self, value: ::capnp::struct_list::Reader<'_,crate::json_capnp::value::Owned>) -> ::capnp::Result<()> { - ::capnp::traits::SetterInput::set_pointer_builder(self.builder.reborrow().get_pointer_field(1), value, false) - } - #[inline] - pub fn init_params(self, size: u32) -> ::capnp::struct_list::Builder<'a,crate::json_capnp::value::Owned> { - ::capnp::traits::FromPointerBuilder::init_pointer(self.builder.get_pointer_field(1), size) - } - #[inline] - pub fn has_params(&self) -> bool { - !self.builder.is_pointer_field_null(1) - } + pub fn total_size(&self) -> ::capnp::Result<::capnp::MessageSize> { + self.builder.as_reader().total_size() + } + #[inline] + pub fn get_prefix(self) -> ::capnp::Result<::capnp::text::Builder<'a>> { + ::capnp::traits::FromPointerBuilder::get_from_pointer( + self.builder.get_pointer_field(0), + ::core::option::Option::Some(&_private::DEFAULT_PREFIX[..]), + ) + } + #[inline] + pub fn set_prefix( + &mut self, + value: impl ::capnp::traits::SetterInput<::capnp::text::Owned>, + ) { + ::capnp::traits::SetterInput::set_pointer_builder( + self.builder.reborrow().get_pointer_field(0), + value, + false, + ) + .unwrap() + } + #[inline] + pub fn init_prefix(self, size: u32) -> ::capnp::text::Builder<'a> { + self.builder.get_pointer_field(0).init_text(size) + } + #[inline] + pub fn has_prefix(&self) -> bool { + !self.builder.is_pointer_field_null(0) + } } - pub struct Pipeline { _typeless: ::capnp::any_pointer::Pipeline } - impl ::capnp::capability::FromTypelessPipeline for Pipeline { - fn new(typeless: ::capnp::any_pointer::Pipeline) -> Self { - Self { _typeless: typeless, } - } + pub struct Pipeline { + _typeless: ::capnp::any_pointer::Pipeline, } - impl Pipeline { + impl ::capnp::capability::FromTypelessPipeline for Pipeline { + fn new(typeless: ::capnp::any_pointer::Pipeline) -> Self { + Self { + _typeless: typeless, + } + } } + impl Pipeline {} mod _private { - pub static ENCODED_NODE: [::capnp::Word; 53] = [ - ::capnp::word(0, 0, 0, 0, 6, 0, 6, 0), - ::capnp::word(72, 61, 201, 161, 236, 246, 217, 160), - ::capnp::word(17, 0, 0, 0, 1, 0, 0, 0), - ::capnp::word(131, 221, 25, 249, 69, 120, 250, 163), - ::capnp::word(2, 0, 7, 0, 0, 0, 0, 0), - ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), - ::capnp::word(233, 10, 0, 0, 45, 11, 0, 0), - ::capnp::word(21, 0, 0, 0, 178, 0, 0, 0), - ::capnp::word(29, 0, 0, 0, 7, 0, 0, 0), - ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), - ::capnp::word(25, 0, 0, 0, 119, 0, 0, 0), - ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), - ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), - ::capnp::word(106, 115, 111, 110, 46, 99, 97, 112), - ::capnp::word(110, 112, 58, 86, 97, 108, 117, 101), - ::capnp::word(46, 67, 97, 108, 108, 0, 0, 0), - ::capnp::word(0, 0, 0, 0, 1, 0, 1, 0), - ::capnp::word(8, 0, 0, 0, 3, 0, 4, 0), - ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), - ::capnp::word(0, 0, 1, 0, 0, 0, 0, 0), - ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), - ::capnp::word(41, 0, 0, 0, 74, 0, 0, 0), - ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), - ::capnp::word(40, 0, 0, 0, 3, 0, 1, 0), - ::capnp::word(52, 0, 0, 0, 2, 0, 1, 0), - ::capnp::word(1, 0, 0, 0, 1, 0, 0, 0), - ::capnp::word(0, 0, 1, 0, 1, 0, 0, 0), - ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), - ::capnp::word(49, 0, 0, 0, 58, 0, 0, 0), - ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), - ::capnp::word(44, 0, 0, 0, 3, 0, 1, 0), - ::capnp::word(72, 0, 0, 0, 2, 0, 1, 0), - ::capnp::word(102, 117, 110, 99, 116, 105, 111, 110), - ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), - ::capnp::word(12, 0, 0, 0, 0, 0, 0, 0), - ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), - ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), - ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), - ::capnp::word(12, 0, 0, 0, 0, 0, 0, 0), - ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), - ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), - ::capnp::word(112, 97, 114, 97, 109, 115, 0, 0), - ::capnp::word(14, 0, 0, 0, 0, 0, 0, 0), - ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), - ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), - ::capnp::word(0, 0, 0, 0, 3, 0, 1, 0), - ::capnp::word(16, 0, 0, 0, 0, 0, 0, 0), - ::capnp::word(131, 221, 25, 249, 69, 120, 250, 163), - ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), - ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), - ::capnp::word(14, 0, 0, 0, 0, 0, 0, 0), - ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), - ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), - ]; - pub fn get_field_types(index: u16) -> ::capnp::introspect::Type { - match index { - 0 => <::capnp::text::Owned as ::capnp::introspect::Introspect>::introspect(), - 1 => <::capnp::struct_list::Owned as ::capnp::introspect::Introspect>::introspect(), - _ => ::capnp::introspect::panic_invalid_field_index(index), + pub static ENCODED_NODE: [::capnp::Word; 35] = [ + ::capnp::word(0, 0, 0, 0, 6, 0, 6, 0), + ::capnp::word(97, 234, 194, 123, 37, 19, 223, 196), + ::capnp::word(11, 0, 0, 0, 1, 0, 0, 0), + ::capnp::word(52, 94, 58, 164, 151, 146, 249, 142), + ::capnp::word(1, 0, 7, 0, 0, 0, 0, 0), + ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(180, 15, 0, 0, 35, 16, 0, 0), + ::capnp::word(21, 0, 0, 0, 210, 0, 0, 0), + ::capnp::word(33, 0, 0, 0, 7, 0, 0, 0), + ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(29, 0, 0, 0, 63, 0, 0, 0), + ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(106, 115, 111, 110, 46, 99, 97, 112), + ::capnp::word(110, 112, 58, 70, 108, 97, 116, 116), + ::capnp::word(101, 110, 79, 112, 116, 105, 111, 110), + ::capnp::word(115, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(0, 0, 0, 0, 1, 0, 1, 0), + ::capnp::word(4, 0, 0, 0, 3, 0, 4, 0), + ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(0, 0, 1, 0, 0, 0, 0, 0), + ::capnp::word(1, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(13, 0, 0, 0, 58, 0, 0, 0), + ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(8, 0, 0, 0, 3, 0, 1, 0), + ::capnp::word(20, 0, 0, 0, 2, 0, 1, 0), + ::capnp::word(112, 114, 101, 102, 105, 120, 0, 0), + ::capnp::word(12, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(12, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(1, 0, 0, 0, 10, 0, 0, 0), + ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), + ]; + pub fn get_field_types(index: u16) -> ::capnp::introspect::Type { + match index { + 0 => <::capnp::text::Owned as ::capnp::introspect::Introspect>::introspect(), + _ => ::capnp::introspect::panic_invalid_field_index(index), + } } - } - pub fn get_annotation_types(child_index: Option, index: u32) -> ::capnp::introspect::Type { - ::capnp::introspect::panic_invalid_annotation_indices(child_index, index) - } - pub static RAW_SCHEMA: ::capnp::introspect::RawStructSchema = ::capnp::introspect::RawStructSchema { - encoded_node: &ENCODED_NODE, - nonunion_members: NONUNION_MEMBERS, - members_by_discriminant: MEMBERS_BY_DISCRIMINANT, - members_by_name: MEMBERS_BY_NAME, - }; - pub static NONUNION_MEMBERS : &[u16] = &[0,1]; - pub static MEMBERS_BY_DISCRIMINANT : &[u16] = &[]; - pub static MEMBERS_BY_NAME : &[u16] = &[0,1]; - pub const TYPE_ID: u64 = 0xa0d9_f6ec_a1c9_3d48; - } - } -} -pub mod name { - pub const ID: u64 = 0xfa5b1fd61c2e7c3d; - pub fn get_type() -> ::capnp::introspect::Type { <::capnp::text::Owned as ::capnp::introspect::Introspect>::introspect() } + pub fn get_annotation_types( + child_index: Option, + index: u32, + ) -> ::capnp::introspect::Type { + ::capnp::introspect::panic_invalid_annotation_indices(child_index, index) + } + pub static RAW_SCHEMA: ::capnp::introspect::RawStructSchema = + ::capnp::introspect::RawStructSchema { + encoded_node: &ENCODED_NODE, + nonunion_members: NONUNION_MEMBERS, + members_by_discriminant: MEMBERS_BY_DISCRIMINANT, + members_by_name: MEMBERS_BY_NAME, + }; + pub static NONUNION_MEMBERS: &[u16] = &[0]; + pub static MEMBERS_BY_DISCRIMINANT: &[u16] = &[]; + pub static MEMBERS_BY_NAME: &[u16] = &[0]; + pub static DEFAULT_PREFIX: [::capnp::Word; 2] = [ + ::capnp::word(1, 0, 0, 0, 10, 0, 0, 0), + ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), + ]; + pub const TYPE_ID: u64 = 0xc4df_1325_7bc2_ea61; + } } -pub mod flatten { - pub const ID: u64 = 0x82d3e852af0336bf; - pub fn get_type() -> ::capnp::introspect::Type { ::introspect() } +pub mod discriminator { + pub const ID: u64 = 0xcfa794e8d19a0162; + pub fn get_type() -> ::capnp::introspect::Type { + ::introspect() + } } -pub mod flatten_options { - #[derive(Copy, Clone)] - pub struct Owned(()); - impl ::capnp::introspect::Introspect for Owned { fn introspect() -> ::capnp::introspect::Type { ::capnp::introspect::TypeVariant::Struct(::capnp::introspect::RawBrandedStructSchema { generic: &_private::RAW_SCHEMA, field_types: _private::get_field_types, annotation_types: _private::get_annotation_types }).into() } } - impl ::capnp::traits::Owned for Owned { type Reader<'a> = Reader<'a>; type Builder<'a> = Builder<'a>; } - impl ::capnp::traits::OwnedStruct for Owned { type Reader<'a> = Reader<'a>; type Builder<'a> = Builder<'a>; } - impl ::capnp::traits::Pipelined for Owned { type Pipeline = Pipeline; } +pub mod discriminator_options { + #[derive(Copy, Clone)] + pub struct Owned(()); + impl ::capnp::introspect::Introspect for Owned { + fn introspect() -> ::capnp::introspect::Type { + ::capnp::introspect::TypeVariant::Struct(::capnp::introspect::RawBrandedStructSchema { + generic: &_private::RAW_SCHEMA, + field_types: _private::get_field_types, + annotation_types: _private::get_annotation_types, + }) + .into() + } + } + impl ::capnp::traits::Owned for Owned { + type Reader<'a> = Reader<'a>; + type Builder<'a> = Builder<'a>; + } + impl ::capnp::traits::OwnedStruct for Owned { + type Reader<'a> = Reader<'a>; + type Builder<'a> = Builder<'a>; + } + impl ::capnp::traits::Pipelined for Owned { + type Pipeline = Pipeline; + } - pub struct Reader<'a> { reader: ::capnp::private::layout::StructReader<'a> } - impl <> ::core::marker::Copy for Reader<'_,> {} - impl <> ::core::clone::Clone for Reader<'_,> { - fn clone(&self) -> Self { *self } - } + pub struct Reader<'a> { + reader: ::capnp::private::layout::StructReader<'a>, + } + impl ::core::marker::Copy for Reader<'_> {} + impl ::core::clone::Clone for Reader<'_> { + fn clone(&self) -> Self { + *self + } + } - impl <> ::capnp::traits::HasTypeId for Reader<'_,> { - const TYPE_ID: u64 = _private::TYPE_ID; - } - impl <'a,> ::core::convert::From<::capnp::private::layout::StructReader<'a>> for Reader<'a,> { - fn from(reader: ::capnp::private::layout::StructReader<'a>) -> Self { - Self { reader, } + impl ::capnp::traits::HasTypeId for Reader<'_> { + const TYPE_ID: u64 = _private::TYPE_ID; + } + impl<'a> ::core::convert::From<::capnp::private::layout::StructReader<'a>> for Reader<'a> { + fn from(reader: ::capnp::private::layout::StructReader<'a>) -> Self { + Self { reader } + } } - } - impl <'a,> ::core::convert::From> for ::capnp::dynamic_value::Reader<'a> { - fn from(reader: Reader<'a,>) -> Self { - Self::Struct(::capnp::dynamic_struct::Reader::new(reader.reader, ::capnp::schema::StructSchema::new(::capnp::introspect::RawBrandedStructSchema { generic: &_private::RAW_SCHEMA, field_types: _private::get_field_types::<>, annotation_types: _private::get_annotation_types::<>}))) + impl<'a> ::core::convert::From> for ::capnp::dynamic_value::Reader<'a> { + fn from(reader: Reader<'a>) -> Self { + Self::Struct(::capnp::dynamic_struct::Reader::new( + reader.reader, + ::capnp::schema::StructSchema::new(::capnp::introspect::RawBrandedStructSchema { + generic: &_private::RAW_SCHEMA, + field_types: _private::get_field_types, + annotation_types: _private::get_annotation_types, + }), + )) + } } - } - impl <> ::core::fmt::Debug for Reader<'_,> { - fn fmt(&self, f: &mut ::core::fmt::Formatter<'_>) -> ::core::result::Result<(), ::core::fmt::Error> { - core::fmt::Debug::fmt(&::core::convert::Into::<::capnp::dynamic_value::Reader<'_>>::into(*self), f) + impl ::core::fmt::Debug for Reader<'_> { + fn fmt( + &self, + f: &mut ::core::fmt::Formatter<'_>, + ) -> ::core::result::Result<(), ::core::fmt::Error> { + core::fmt::Debug::fmt( + &::core::convert::Into::<::capnp::dynamic_value::Reader<'_>>::into(*self), + f, + ) + } } - } - impl <'a,> ::capnp::traits::FromPointerReader<'a> for Reader<'a,> { - fn get_from_pointer(reader: &::capnp::private::layout::PointerReader<'a>, default: ::core::option::Option<&'a [::capnp::Word]>) -> ::capnp::Result { - ::core::result::Result::Ok(reader.get_struct(default)?.into()) + impl<'a> ::capnp::traits::FromPointerReader<'a> for Reader<'a> { + fn get_from_pointer( + reader: &::capnp::private::layout::PointerReader<'a>, + default: ::core::option::Option<&'a [::capnp::Word]>, + ) -> ::capnp::Result { + ::core::result::Result::Ok(reader.get_struct(default)?.into()) + } } - } - impl <'a,> ::capnp::traits::IntoInternalStructReader<'a> for Reader<'a,> { - fn into_internal_struct_reader(self) -> ::capnp::private::layout::StructReader<'a> { - self.reader + impl<'a> ::capnp::traits::IntoInternalStructReader<'a> for Reader<'a> { + fn into_internal_struct_reader(self) -> ::capnp::private::layout::StructReader<'a> { + self.reader + } } - } - impl <'a,> ::capnp::traits::Imbue<'a> for Reader<'a,> { - fn imbue(&mut self, cap_table: &'a ::capnp::private::layout::CapTable) { - self.reader.imbue(::capnp::private::layout::CapTableReader::Plain(cap_table)) + impl<'a> ::capnp::traits::Imbue<'a> for Reader<'a> { + fn imbue(&mut self, cap_table: &'a ::capnp::private::layout::CapTable) { + self.reader + .imbue(::capnp::private::layout::CapTableReader::Plain(cap_table)) + } } - } - impl <'a,> Reader<'a,> { - pub fn reborrow(&self) -> Reader<'_,> { - Self { .. *self } + impl<'a> Reader<'a> { + pub fn reborrow(&self) -> Reader<'_> { + Self { ..*self } + } + + pub fn total_size(&self) -> ::capnp::Result<::capnp::MessageSize> { + self.reader.total_size() + } + #[inline] + pub fn get_name(self) -> ::capnp::Result<::capnp::text::Reader<'a>> { + ::capnp::traits::FromPointerReader::get_from_pointer( + &self.reader.get_pointer_field(0), + ::core::option::Option::None, + ) + } + #[inline] + pub fn has_name(&self) -> bool { + !self.reader.get_pointer_field(0).is_null() + } + #[inline] + pub fn get_value_name(self) -> ::capnp::Result<::capnp::text::Reader<'a>> { + ::capnp::traits::FromPointerReader::get_from_pointer( + &self.reader.get_pointer_field(1), + ::core::option::Option::None, + ) + } + #[inline] + pub fn has_value_name(&self) -> bool { + !self.reader.get_pointer_field(1).is_null() + } } - pub fn total_size(&self) -> ::capnp::Result<::capnp::MessageSize> { - self.reader.total_size() + pub struct Builder<'a> { + builder: ::capnp::private::layout::StructBuilder<'a>, } - #[inline] - pub fn get_prefix(self) -> ::capnp::Result<::capnp::text::Reader<'a>> { - ::capnp::traits::FromPointerReader::get_from_pointer(&self.reader.get_pointer_field(0), ::core::option::Option::Some(&_private::DEFAULT_PREFIX[..])) + impl ::capnp::traits::HasStructSize for Builder<'_> { + const STRUCT_SIZE: ::capnp::private::layout::StructSize = + ::capnp::private::layout::StructSize { + data: 0, + pointers: 2, + }; } - #[inline] - pub fn has_prefix(&self) -> bool { - !self.reader.get_pointer_field(0).is_null() - } - } - - pub struct Builder<'a> { builder: ::capnp::private::layout::StructBuilder<'a> } - impl <> ::capnp::traits::HasStructSize for Builder<'_,> { - const STRUCT_SIZE: ::capnp::private::layout::StructSize = ::capnp::private::layout::StructSize { data: 0, pointers: 1 }; - } - impl <> ::capnp::traits::HasTypeId for Builder<'_,> { - const TYPE_ID: u64 = _private::TYPE_ID; - } - impl <'a,> ::core::convert::From<::capnp::private::layout::StructBuilder<'a>> for Builder<'a,> { - fn from(builder: ::capnp::private::layout::StructBuilder<'a>) -> Self { - Self { builder, } - } - } - - impl <'a,> ::core::convert::From> for ::capnp::dynamic_value::Builder<'a> { - fn from(builder: Builder<'a,>) -> Self { - Self::Struct(::capnp::dynamic_struct::Builder::new(builder.builder, ::capnp::schema::StructSchema::new(::capnp::introspect::RawBrandedStructSchema { generic: &_private::RAW_SCHEMA, field_types: _private::get_field_types::<>, annotation_types: _private::get_annotation_types::<>}))) - } - } - - impl <'a,> ::capnp::traits::ImbueMut<'a> for Builder<'a,> { - fn imbue_mut(&mut self, cap_table: &'a mut ::capnp::private::layout::CapTable) { - self.builder.imbue(::capnp::private::layout::CapTableBuilder::Plain(cap_table)) - } - } - - impl <'a,> ::capnp::traits::FromPointerBuilder<'a> for Builder<'a,> { - fn init_pointer(builder: ::capnp::private::layout::PointerBuilder<'a>, _size: u32) -> Self { - builder.init_struct(::STRUCT_SIZE).into() - } - fn get_from_pointer(builder: ::capnp::private::layout::PointerBuilder<'a>, default: ::core::option::Option<&'a [::capnp::Word]>) -> ::capnp::Result { - ::core::result::Result::Ok(builder.get_struct(::STRUCT_SIZE, default)?.into()) - } - } - - impl <> ::capnp::traits::SetterInput> for Reader<'_,> { - fn set_pointer_builder(mut pointer: ::capnp::private::layout::PointerBuilder<'_>, value: Self, canonicalize: bool) -> ::capnp::Result<()> { pointer.set_struct(&value.reader, canonicalize) } - } - - impl <'a,> Builder<'a,> { - pub fn into_reader(self) -> Reader<'a,> { - self.builder.into_reader().into() - } - pub fn reborrow(&mut self) -> Builder<'_,> { - Builder { builder: self.builder.reborrow() } - } - pub fn reborrow_as_reader(&self) -> Reader<'_,> { - self.builder.as_reader().into() - } - - pub fn total_size(&self) -> ::capnp::Result<::capnp::MessageSize> { - self.builder.as_reader().total_size() - } - #[inline] - pub fn get_prefix(self) -> ::capnp::Result<::capnp::text::Builder<'a>> { - ::capnp::traits::FromPointerBuilder::get_from_pointer(self.builder.get_pointer_field(0), ::core::option::Option::Some(&_private::DEFAULT_PREFIX[..])) - } - #[inline] - pub fn set_prefix(&mut self, value: impl ::capnp::traits::SetterInput<::capnp::text::Owned>) { - ::capnp::traits::SetterInput::set_pointer_builder(self.builder.reborrow().get_pointer_field(0), value, false).unwrap() - } - #[inline] - pub fn init_prefix(self, size: u32) -> ::capnp::text::Builder<'a> { - self.builder.get_pointer_field(0).init_text(size) - } - #[inline] - pub fn has_prefix(&self) -> bool { - !self.builder.is_pointer_field_null(0) - } - } - - pub struct Pipeline { _typeless: ::capnp::any_pointer::Pipeline } - impl ::capnp::capability::FromTypelessPipeline for Pipeline { - fn new(typeless: ::capnp::any_pointer::Pipeline) -> Self { - Self { _typeless: typeless, } - } - } - impl Pipeline { - } - mod _private { - pub static ENCODED_NODE: [::capnp::Word; 35] = [ - ::capnp::word(0, 0, 0, 0, 6, 0, 6, 0), - ::capnp::word(97, 234, 194, 123, 37, 19, 223, 196), - ::capnp::word(11, 0, 0, 0, 1, 0, 0, 0), - ::capnp::word(52, 94, 58, 164, 151, 146, 249, 142), - ::capnp::word(1, 0, 7, 0, 0, 0, 0, 0), - ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), - ::capnp::word(180, 15, 0, 0, 35, 16, 0, 0), - ::capnp::word(21, 0, 0, 0, 210, 0, 0, 0), - ::capnp::word(33, 0, 0, 0, 7, 0, 0, 0), - ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), - ::capnp::word(29, 0, 0, 0, 63, 0, 0, 0), - ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), - ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), - ::capnp::word(106, 115, 111, 110, 46, 99, 97, 112), - ::capnp::word(110, 112, 58, 70, 108, 97, 116, 116), - ::capnp::word(101, 110, 79, 112, 116, 105, 111, 110), - ::capnp::word(115, 0, 0, 0, 0, 0, 0, 0), - ::capnp::word(0, 0, 0, 0, 1, 0, 1, 0), - ::capnp::word(4, 0, 0, 0, 3, 0, 4, 0), - ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), - ::capnp::word(0, 0, 1, 0, 0, 0, 0, 0), - ::capnp::word(1, 0, 0, 0, 0, 0, 0, 0), - ::capnp::word(13, 0, 0, 0, 58, 0, 0, 0), - ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), - ::capnp::word(8, 0, 0, 0, 3, 0, 1, 0), - ::capnp::word(20, 0, 0, 0, 2, 0, 1, 0), - ::capnp::word(112, 114, 101, 102, 105, 120, 0, 0), - ::capnp::word(12, 0, 0, 0, 0, 0, 0, 0), - ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), - ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), - ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), - ::capnp::word(12, 0, 0, 0, 0, 0, 0, 0), - ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), - ::capnp::word(1, 0, 0, 0, 10, 0, 0, 0), - ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), - ]; - pub fn get_field_types(index: u16) -> ::capnp::introspect::Type { - match index { - 0 => <::capnp::text::Owned as ::capnp::introspect::Introspect>::introspect(), - _ => ::capnp::introspect::panic_invalid_field_index(index), - } + impl ::capnp::traits::HasTypeId for Builder<'_> { + const TYPE_ID: u64 = _private::TYPE_ID; } - pub fn get_annotation_types(child_index: Option, index: u32) -> ::capnp::introspect::Type { - ::capnp::introspect::panic_invalid_annotation_indices(child_index, index) - } - pub static RAW_SCHEMA: ::capnp::introspect::RawStructSchema = ::capnp::introspect::RawStructSchema { - encoded_node: &ENCODED_NODE, - nonunion_members: NONUNION_MEMBERS, - members_by_discriminant: MEMBERS_BY_DISCRIMINANT, - members_by_name: MEMBERS_BY_NAME, - }; - pub static NONUNION_MEMBERS : &[u16] = &[0]; - pub static MEMBERS_BY_DISCRIMINANT : &[u16] = &[]; - pub static MEMBERS_BY_NAME : &[u16] = &[0]; - pub static DEFAULT_PREFIX: [::capnp::Word; 2] = [ - ::capnp::word(1, 0, 0, 0, 10, 0, 0, 0), - ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), - ]; - pub const TYPE_ID: u64 = 0xc4df_1325_7bc2_ea61; - } -} -pub mod discriminator { - pub const ID: u64 = 0xcfa794e8d19a0162; - pub fn get_type() -> ::capnp::introspect::Type { ::introspect() } -} - -pub mod discriminator_options { - #[derive(Copy, Clone)] - pub struct Owned(()); - impl ::capnp::introspect::Introspect for Owned { fn introspect() -> ::capnp::introspect::Type { ::capnp::introspect::TypeVariant::Struct(::capnp::introspect::RawBrandedStructSchema { generic: &_private::RAW_SCHEMA, field_types: _private::get_field_types, annotation_types: _private::get_annotation_types }).into() } } - impl ::capnp::traits::Owned for Owned { type Reader<'a> = Reader<'a>; type Builder<'a> = Builder<'a>; } - impl ::capnp::traits::OwnedStruct for Owned { type Reader<'a> = Reader<'a>; type Builder<'a> = Builder<'a>; } - impl ::capnp::traits::Pipelined for Owned { type Pipeline = Pipeline; } - - pub struct Reader<'a> { reader: ::capnp::private::layout::StructReader<'a> } - impl <> ::core::marker::Copy for Reader<'_,> {} - impl <> ::core::clone::Clone for Reader<'_,> { - fn clone(&self) -> Self { *self } - } - - impl <> ::capnp::traits::HasTypeId for Reader<'_,> { - const TYPE_ID: u64 = _private::TYPE_ID; - } - impl <'a,> ::core::convert::From<::capnp::private::layout::StructReader<'a>> for Reader<'a,> { - fn from(reader: ::capnp::private::layout::StructReader<'a>) -> Self { - Self { reader, } + impl<'a> ::core::convert::From<::capnp::private::layout::StructBuilder<'a>> for Builder<'a> { + fn from(builder: ::capnp::private::layout::StructBuilder<'a>) -> Self { + Self { builder } + } } - } - impl <'a,> ::core::convert::From> for ::capnp::dynamic_value::Reader<'a> { - fn from(reader: Reader<'a,>) -> Self { - Self::Struct(::capnp::dynamic_struct::Reader::new(reader.reader, ::capnp::schema::StructSchema::new(::capnp::introspect::RawBrandedStructSchema { generic: &_private::RAW_SCHEMA, field_types: _private::get_field_types::<>, annotation_types: _private::get_annotation_types::<>}))) + impl<'a> ::core::convert::From> for ::capnp::dynamic_value::Builder<'a> { + fn from(builder: Builder<'a>) -> Self { + Self::Struct(::capnp::dynamic_struct::Builder::new( + builder.builder, + ::capnp::schema::StructSchema::new(::capnp::introspect::RawBrandedStructSchema { + generic: &_private::RAW_SCHEMA, + field_types: _private::get_field_types, + annotation_types: _private::get_annotation_types, + }), + )) + } } - } - impl <> ::core::fmt::Debug for Reader<'_,> { - fn fmt(&self, f: &mut ::core::fmt::Formatter<'_>) -> ::core::result::Result<(), ::core::fmt::Error> { - core::fmt::Debug::fmt(&::core::convert::Into::<::capnp::dynamic_value::Reader<'_>>::into(*self), f) + impl<'a> ::capnp::traits::ImbueMut<'a> for Builder<'a> { + fn imbue_mut(&mut self, cap_table: &'a mut ::capnp::private::layout::CapTable) { + self.builder + .imbue(::capnp::private::layout::CapTableBuilder::Plain(cap_table)) + } } - } - impl <'a,> ::capnp::traits::FromPointerReader<'a> for Reader<'a,> { - fn get_from_pointer(reader: &::capnp::private::layout::PointerReader<'a>, default: ::core::option::Option<&'a [::capnp::Word]>) -> ::capnp::Result { - ::core::result::Result::Ok(reader.get_struct(default)?.into()) + impl<'a> ::capnp::traits::FromPointerBuilder<'a> for Builder<'a> { + fn init_pointer(builder: ::capnp::private::layout::PointerBuilder<'a>, _size: u32) -> Self { + builder + .init_struct(::STRUCT_SIZE) + .into() + } + fn get_from_pointer( + builder: ::capnp::private::layout::PointerBuilder<'a>, + default: ::core::option::Option<&'a [::capnp::Word]>, + ) -> ::capnp::Result { + ::core::result::Result::Ok( + builder + .get_struct( + ::STRUCT_SIZE, + default, + )? + .into(), + ) + } } - } - impl <'a,> ::capnp::traits::IntoInternalStructReader<'a> for Reader<'a,> { - fn into_internal_struct_reader(self) -> ::capnp::private::layout::StructReader<'a> { - self.reader + impl ::capnp::traits::SetterInput for Reader<'_> { + fn set_pointer_builder( + mut pointer: ::capnp::private::layout::PointerBuilder<'_>, + value: Self, + canonicalize: bool, + ) -> ::capnp::Result<()> { + pointer.set_struct(&value.reader, canonicalize) + } } - } - impl <'a,> ::capnp::traits::Imbue<'a> for Reader<'a,> { - fn imbue(&mut self, cap_table: &'a ::capnp::private::layout::CapTable) { - self.reader.imbue(::capnp::private::layout::CapTableReader::Plain(cap_table)) - } - } + impl<'a> Builder<'a> { + pub fn into_reader(self) -> Reader<'a> { + self.builder.into_reader().into() + } + pub fn reborrow(&mut self) -> Builder<'_> { + Builder { + builder: self.builder.reborrow(), + } + } + pub fn reborrow_as_reader(&self) -> Reader<'_> { + self.builder.as_reader().into() + } - impl <'a,> Reader<'a,> { - pub fn reborrow(&self) -> Reader<'_,> { - Self { .. *self } + pub fn total_size(&self) -> ::capnp::Result<::capnp::MessageSize> { + self.builder.as_reader().total_size() + } + #[inline] + pub fn get_name(self) -> ::capnp::Result<::capnp::text::Builder<'a>> { + ::capnp::traits::FromPointerBuilder::get_from_pointer( + self.builder.get_pointer_field(0), + ::core::option::Option::None, + ) + } + #[inline] + pub fn set_name(&mut self, value: impl ::capnp::traits::SetterInput<::capnp::text::Owned>) { + ::capnp::traits::SetterInput::set_pointer_builder( + self.builder.reborrow().get_pointer_field(0), + value, + false, + ) + .unwrap() + } + #[inline] + pub fn init_name(self, size: u32) -> ::capnp::text::Builder<'a> { + self.builder.get_pointer_field(0).init_text(size) + } + #[inline] + pub fn has_name(&self) -> bool { + !self.builder.is_pointer_field_null(0) + } + #[inline] + pub fn get_value_name(self) -> ::capnp::Result<::capnp::text::Builder<'a>> { + ::capnp::traits::FromPointerBuilder::get_from_pointer( + self.builder.get_pointer_field(1), + ::core::option::Option::None, + ) + } + #[inline] + pub fn set_value_name( + &mut self, + value: impl ::capnp::traits::SetterInput<::capnp::text::Owned>, + ) { + ::capnp::traits::SetterInput::set_pointer_builder( + self.builder.reborrow().get_pointer_field(1), + value, + false, + ) + .unwrap() + } + #[inline] + pub fn init_value_name(self, size: u32) -> ::capnp::text::Builder<'a> { + self.builder.get_pointer_field(1).init_text(size) + } + #[inline] + pub fn has_value_name(&self) -> bool { + !self.builder.is_pointer_field_null(1) + } } - pub fn total_size(&self) -> ::capnp::Result<::capnp::MessageSize> { - self.reader.total_size() + pub struct Pipeline { + _typeless: ::capnp::any_pointer::Pipeline, } - #[inline] - pub fn get_name(self) -> ::capnp::Result<::capnp::text::Reader<'a>> { - ::capnp::traits::FromPointerReader::get_from_pointer(&self.reader.get_pointer_field(0), ::core::option::Option::None) - } - #[inline] - pub fn has_name(&self) -> bool { - !self.reader.get_pointer_field(0).is_null() - } - #[inline] - pub fn get_value_name(self) -> ::capnp::Result<::capnp::text::Reader<'a>> { - ::capnp::traits::FromPointerReader::get_from_pointer(&self.reader.get_pointer_field(1), ::core::option::Option::None) - } - #[inline] - pub fn has_value_name(&self) -> bool { - !self.reader.get_pointer_field(1).is_null() - } - } - - pub struct Builder<'a> { builder: ::capnp::private::layout::StructBuilder<'a> } - impl <> ::capnp::traits::HasStructSize for Builder<'_,> { - const STRUCT_SIZE: ::capnp::private::layout::StructSize = ::capnp::private::layout::StructSize { data: 0, pointers: 2 }; - } - impl <> ::capnp::traits::HasTypeId for Builder<'_,> { - const TYPE_ID: u64 = _private::TYPE_ID; - } - impl <'a,> ::core::convert::From<::capnp::private::layout::StructBuilder<'a>> for Builder<'a,> { - fn from(builder: ::capnp::private::layout::StructBuilder<'a>) -> Self { - Self { builder, } + impl ::capnp::capability::FromTypelessPipeline for Pipeline { + fn new(typeless: ::capnp::any_pointer::Pipeline) -> Self { + Self { + _typeless: typeless, + } + } } - } - - impl <'a,> ::core::convert::From> for ::capnp::dynamic_value::Builder<'a> { - fn from(builder: Builder<'a,>) -> Self { - Self::Struct(::capnp::dynamic_struct::Builder::new(builder.builder, ::capnp::schema::StructSchema::new(::capnp::introspect::RawBrandedStructSchema { generic: &_private::RAW_SCHEMA, field_types: _private::get_field_types::<>, annotation_types: _private::get_annotation_types::<>}))) - } - } - - impl <'a,> ::capnp::traits::ImbueMut<'a> for Builder<'a,> { - fn imbue_mut(&mut self, cap_table: &'a mut ::capnp::private::layout::CapTable) { - self.builder.imbue(::capnp::private::layout::CapTableBuilder::Plain(cap_table)) - } - } - - impl <'a,> ::capnp::traits::FromPointerBuilder<'a> for Builder<'a,> { - fn init_pointer(builder: ::capnp::private::layout::PointerBuilder<'a>, _size: u32) -> Self { - builder.init_struct(::STRUCT_SIZE).into() - } - fn get_from_pointer(builder: ::capnp::private::layout::PointerBuilder<'a>, default: ::core::option::Option<&'a [::capnp::Word]>) -> ::capnp::Result { - ::core::result::Result::Ok(builder.get_struct(::STRUCT_SIZE, default)?.into()) - } - } - - impl <> ::capnp::traits::SetterInput> for Reader<'_,> { - fn set_pointer_builder(mut pointer: ::capnp::private::layout::PointerBuilder<'_>, value: Self, canonicalize: bool) -> ::capnp::Result<()> { pointer.set_struct(&value.reader, canonicalize) } - } - - impl <'a,> Builder<'a,> { - pub fn into_reader(self) -> Reader<'a,> { - self.builder.into_reader().into() - } - pub fn reborrow(&mut self) -> Builder<'_,> { - Builder { builder: self.builder.reborrow() } - } - pub fn reborrow_as_reader(&self) -> Reader<'_,> { - self.builder.as_reader().into() - } - - pub fn total_size(&self) -> ::capnp::Result<::capnp::MessageSize> { - self.builder.as_reader().total_size() - } - #[inline] - pub fn get_name(self) -> ::capnp::Result<::capnp::text::Builder<'a>> { - ::capnp::traits::FromPointerBuilder::get_from_pointer(self.builder.get_pointer_field(0), ::core::option::Option::None) - } - #[inline] - pub fn set_name(&mut self, value: impl ::capnp::traits::SetterInput<::capnp::text::Owned>) { - ::capnp::traits::SetterInput::set_pointer_builder(self.builder.reborrow().get_pointer_field(0), value, false).unwrap() - } - #[inline] - pub fn init_name(self, size: u32) -> ::capnp::text::Builder<'a> { - self.builder.get_pointer_field(0).init_text(size) - } - #[inline] - pub fn has_name(&self) -> bool { - !self.builder.is_pointer_field_null(0) - } - #[inline] - pub fn get_value_name(self) -> ::capnp::Result<::capnp::text::Builder<'a>> { - ::capnp::traits::FromPointerBuilder::get_from_pointer(self.builder.get_pointer_field(1), ::core::option::Option::None) - } - #[inline] - pub fn set_value_name(&mut self, value: impl ::capnp::traits::SetterInput<::capnp::text::Owned>) { - ::capnp::traits::SetterInput::set_pointer_builder(self.builder.reborrow().get_pointer_field(1), value, false).unwrap() - } - #[inline] - pub fn init_value_name(self, size: u32) -> ::capnp::text::Builder<'a> { - self.builder.get_pointer_field(1).init_text(size) - } - #[inline] - pub fn has_value_name(&self) -> bool { - !self.builder.is_pointer_field_null(1) - } - } - - pub struct Pipeline { _typeless: ::capnp::any_pointer::Pipeline } - impl ::capnp::capability::FromTypelessPipeline for Pipeline { - fn new(typeless: ::capnp::any_pointer::Pipeline) -> Self { - Self { _typeless: typeless, } - } - } - impl Pipeline { - } - mod _private { - pub static ENCODED_NODE: [::capnp::Word; 50] = [ - ::capnp::word(0, 0, 0, 0, 6, 0, 6, 0), - ::capnp::word(25, 83, 62, 41, 12, 194, 248, 194), - ::capnp::word(11, 0, 0, 0, 1, 0, 0, 0), - ::capnp::word(52, 94, 58, 164, 151, 146, 249, 142), - ::capnp::word(2, 0, 7, 0, 0, 0, 0, 0), - ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), - ::capnp::word(187, 17, 0, 0, 184, 19, 0, 0), - ::capnp::word(21, 0, 0, 0, 2, 1, 0, 0), - ::capnp::word(33, 0, 0, 0, 7, 0, 0, 0), - ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), - ::capnp::word(29, 0, 0, 0, 119, 0, 0, 0), - ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), - ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), - ::capnp::word(106, 115, 111, 110, 46, 99, 97, 112), - ::capnp::word(110, 112, 58, 68, 105, 115, 99, 114), - ::capnp::word(105, 109, 105, 110, 97, 116, 111, 114), - ::capnp::word(79, 112, 116, 105, 111, 110, 115, 0), - ::capnp::word(0, 0, 0, 0, 1, 0, 1, 0), - ::capnp::word(8, 0, 0, 0, 3, 0, 4, 0), - ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), - ::capnp::word(0, 0, 1, 0, 0, 0, 0, 0), - ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), - ::capnp::word(41, 0, 0, 0, 42, 0, 0, 0), - ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), - ::capnp::word(36, 0, 0, 0, 3, 0, 1, 0), - ::capnp::word(48, 0, 0, 0, 2, 0, 1, 0), - ::capnp::word(1, 0, 0, 0, 1, 0, 0, 0), - ::capnp::word(0, 0, 1, 0, 1, 0, 0, 0), - ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), - ::capnp::word(45, 0, 0, 0, 82, 0, 0, 0), - ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), - ::capnp::word(44, 0, 0, 0, 3, 0, 1, 0), - ::capnp::word(56, 0, 0, 0, 2, 0, 1, 0), - ::capnp::word(110, 97, 109, 101, 0, 0, 0, 0), - ::capnp::word(12, 0, 0, 0, 0, 0, 0, 0), - ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), - ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), - ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), - ::capnp::word(12, 0, 0, 0, 0, 0, 0, 0), - ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), - ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), - ::capnp::word(118, 97, 108, 117, 101, 78, 97, 109), - ::capnp::word(101, 0, 0, 0, 0, 0, 0, 0), - ::capnp::word(12, 0, 0, 0, 0, 0, 0, 0), - ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), - ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), - ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), - ::capnp::word(12, 0, 0, 0, 0, 0, 0, 0), - ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), - ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), - ]; - pub fn get_field_types(index: u16) -> ::capnp::introspect::Type { - match index { - 0 => <::capnp::text::Owned as ::capnp::introspect::Introspect>::introspect(), - 1 => <::capnp::text::Owned as ::capnp::introspect::Introspect>::introspect(), - _ => ::capnp::introspect::panic_invalid_field_index(index), - } + impl Pipeline {} + mod _private { + pub static ENCODED_NODE: [::capnp::Word; 50] = [ + ::capnp::word(0, 0, 0, 0, 6, 0, 6, 0), + ::capnp::word(25, 83, 62, 41, 12, 194, 248, 194), + ::capnp::word(11, 0, 0, 0, 1, 0, 0, 0), + ::capnp::word(52, 94, 58, 164, 151, 146, 249, 142), + ::capnp::word(2, 0, 7, 0, 0, 0, 0, 0), + ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(187, 17, 0, 0, 184, 19, 0, 0), + ::capnp::word(21, 0, 0, 0, 2, 1, 0, 0), + ::capnp::word(33, 0, 0, 0, 7, 0, 0, 0), + ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(29, 0, 0, 0, 119, 0, 0, 0), + ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(106, 115, 111, 110, 46, 99, 97, 112), + ::capnp::word(110, 112, 58, 68, 105, 115, 99, 114), + ::capnp::word(105, 109, 105, 110, 97, 116, 111, 114), + ::capnp::word(79, 112, 116, 105, 111, 110, 115, 0), + ::capnp::word(0, 0, 0, 0, 1, 0, 1, 0), + ::capnp::word(8, 0, 0, 0, 3, 0, 4, 0), + ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(0, 0, 1, 0, 0, 0, 0, 0), + ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(41, 0, 0, 0, 42, 0, 0, 0), + ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(36, 0, 0, 0, 3, 0, 1, 0), + ::capnp::word(48, 0, 0, 0, 2, 0, 1, 0), + ::capnp::word(1, 0, 0, 0, 1, 0, 0, 0), + ::capnp::word(0, 0, 1, 0, 1, 0, 0, 0), + ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(45, 0, 0, 0, 82, 0, 0, 0), + ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(44, 0, 0, 0, 3, 0, 1, 0), + ::capnp::word(56, 0, 0, 0, 2, 0, 1, 0), + ::capnp::word(110, 97, 109, 101, 0, 0, 0, 0), + ::capnp::word(12, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(12, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(118, 97, 108, 117, 101, 78, 97, 109), + ::capnp::word(101, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(12, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(12, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), + ::capnp::word(0, 0, 0, 0, 0, 0, 0, 0), + ]; + pub fn get_field_types(index: u16) -> ::capnp::introspect::Type { + match index { + 0 => <::capnp::text::Owned as ::capnp::introspect::Introspect>::introspect(), + 1 => <::capnp::text::Owned as ::capnp::introspect::Introspect>::introspect(), + _ => ::capnp::introspect::panic_invalid_field_index(index), + } + } + pub fn get_annotation_types( + child_index: Option, + index: u32, + ) -> ::capnp::introspect::Type { + ::capnp::introspect::panic_invalid_annotation_indices(child_index, index) + } + pub static RAW_SCHEMA: ::capnp::introspect::RawStructSchema = + ::capnp::introspect::RawStructSchema { + encoded_node: &ENCODED_NODE, + nonunion_members: NONUNION_MEMBERS, + members_by_discriminant: MEMBERS_BY_DISCRIMINANT, + members_by_name: MEMBERS_BY_NAME, + }; + pub static NONUNION_MEMBERS: &[u16] = &[0, 1]; + pub static MEMBERS_BY_DISCRIMINANT: &[u16] = &[]; + pub static MEMBERS_BY_NAME: &[u16] = &[0, 1]; + pub const TYPE_ID: u64 = 0xc2f8_c20c_293e_5319; } - pub fn get_annotation_types(child_index: Option, index: u32) -> ::capnp::introspect::Type { - ::capnp::introspect::panic_invalid_annotation_indices(child_index, index) - } - pub static RAW_SCHEMA: ::capnp::introspect::RawStructSchema = ::capnp::introspect::RawStructSchema { - encoded_node: &ENCODED_NODE, - nonunion_members: NONUNION_MEMBERS, - members_by_discriminant: MEMBERS_BY_DISCRIMINANT, - members_by_name: MEMBERS_BY_NAME, - }; - pub static NONUNION_MEMBERS : &[u16] = &[0,1]; - pub static MEMBERS_BY_DISCRIMINANT : &[u16] = &[]; - pub static MEMBERS_BY_NAME : &[u16] = &[0,1]; - pub const TYPE_ID: u64 = 0xc2f8_c20c_293e_5319; - } } pub mod base64 { - pub const ID: u64 = 0xd7d879450a253e4b; - pub fn get_type() -> ::capnp::introspect::Type { <() as ::capnp::introspect::Introspect>::introspect() } + pub const ID: u64 = 0xd7d879450a253e4b; + pub fn get_type() -> ::capnp::introspect::Type { + <() as ::capnp::introspect::Introspect>::introspect() + } } pub mod hex { - pub const ID: u64 = 0xf061e22f0ae5c7b5; - pub fn get_type() -> ::capnp::introspect::Type { <() as ::capnp::introspect::Introspect>::introspect() } + pub const ID: u64 = 0xf061e22f0ae5c7b5; + pub fn get_type() -> ::capnp::introspect::Type { + <() as ::capnp::introspect::Introspect>::introspect() + } } pub mod notification { - pub const ID: u64 = 0xa0a054dea32fd98c; - pub fn get_type() -> ::capnp::introspect::Type { <() as ::capnp::introspect::Introspect>::introspect() } + pub const ID: u64 = 0xa0a054dea32fd98c; + pub fn get_type() -> ::capnp::introspect::Type { + <() as ::capnp::introspect::Introspect>::introspect() + } } diff --git a/capnp-json/test/json.rs b/capnp-json/test/json.rs index 11143f987..d22382864 100644 --- a/capnp-json/test/json.rs +++ b/capnp-json/test/json.rs @@ -746,4 +746,3 @@ mod tests { Ok(()) } } - From 631b96ea2dc287d96ba3f56b9311e43ecb936c08 Mon Sep 17 00:00:00 2001 From: Ben Jackson Date: Sun, 7 Dec 2025 18:23:23 +0000 Subject: [PATCH 18/29] Remve a couple of lints --- capnp-json/test/json.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/capnp-json/test/json.rs b/capnp-json/test/json.rs index d22382864..7de70ee5b 100644 --- a/capnp-json/test/json.rs +++ b/capnp-json/test/json.rs @@ -481,7 +481,7 @@ mod tests { let reader = root.into_reader(); assert_eq!((), reader.get_void_field()); - assert_eq!(true, reader.get_bool_field()); + assert!(reader.get_bool_field()); assert_eq!(-8, reader.get_int8_field()); assert_eq!(-16, reader.get_int16_field()); assert_eq!(-32, reader.get_int32_field()); @@ -553,7 +553,7 @@ mod tests { assert_eq!("Some Field", reader.get_some_field()?.to_str()?); assert_eq!(1234, reader.get_a_group().get_flat_foo()); assert_eq!("0xBaa", reader.get_a_group().get_flat_bar()?.to_str()?); - assert_eq!(true, reader.get_a_group().get_flat_baz().get_hello()); + assert!(reader.get_a_group().get_flat_baz().get_hello()); assert_eq!( "Qux", reader @@ -562,7 +562,7 @@ mod tests { .get_flat_qux()? .to_str()? ); - assert_eq!(true, reader.get_prefixed_group().get_baz().get_hello()); + assert!(reader.get_prefixed_group().get_baz().get_hello()); assert!(matches!( reader.get_a_union().which()?, crate::json_test_capnp::test_json_annotations::a_union::Bar(_) From 3ecea6a70987890ddbe829f78d2313c3719e5e01 Mon Sep 17 00:00:00 2001 From: Ben Jackson Date: Mon, 8 Dec 2025 19:33:10 +0000 Subject: [PATCH 19/29] Cargo clippy --- capnp-json/src/decode.rs | 14 ++++++-------- capnp-json/src/encode.rs | 14 +++++++------- capnp-json/test/Cargo.toml | 5 +++++ 3 files changed, 18 insertions(+), 15 deletions(-) diff --git a/capnp-json/src/decode.rs b/capnp-json/src/decode.rs index 2b1e64f72..678e5fec0 100644 --- a/capnp-json/src/decode.rs +++ b/capnp-json/src/decode.rs @@ -137,7 +137,7 @@ where let num_str = self.parse_number()?; let num = num_str .parse::() - .map_err(|e| ParseError::Other(format!("Invalid number format: {}", e)))?; + .map_err(|e| ParseError::Other(format!("Invalid number format: {e}")))?; Ok(JsonValue::Number(num)) } Some('[') => { @@ -169,7 +169,7 @@ where let value = self.parse_value()?; if members.insert(key.clone(), value).is_some() { return Err( - ParseError::Other(format!("Duplicate key in object: {}", key)).into(), + ParseError::Other(format!("Duplicate key in object: {key}")).into() ); } } @@ -204,22 +204,20 @@ where hex.push(self.advance()?); } let code_point = u16::from_str_radix(&hex, 16).map_err(|_| { - ParseError::Other(format!("Invalid unicode escape: \\u{}", hex)) + ParseError::Other(format!("Invalid unicode escape: \\u{hex}")) })?; if let Some(ch) = std::char::from_u32(code_point as u32) { result.push(ch); } else { return Err(ParseError::Other(format!( - "Invalid unicode code point: \\u{}", - hex + "Invalid unicode code point: \\u{hex}" )) .into()); } } other => { return Err(ParseError::Other(format!( - "Invalid escape character: \\{}", - other + "Invalid escape character: \\{other}" )) .into()); } @@ -693,7 +691,7 @@ fn decode_struct( } else { meta.name }; - let field_name = format!("{}{}", field_prefix, discriminator_name); + let field_name = format!("{field_prefix}{discriminator_name}"); if let Some(JsonValue::String(discriminant)) = value.remove(&field_name) { Some(discriminant) } else { diff --git a/capnp-json/src/encode.rs b/capnp-json/src/encode.rs index fb6193449..e1348d3a7 100644 --- a/capnp-json/src/encode.rs +++ b/capnp-json/src/encode.rs @@ -78,11 +78,11 @@ where // TODO: use capnp::io::Write ? fn write_unsigned_number(writer: &mut W, value: u64) -> capnp::Result<()> { - write!(writer, "{}", value)?; + write!(writer, "{value}")?; Ok(()) } fn write_signed_number(writer: &mut W, value: i64) -> capnp::Result<()> { - write!(writer, "{}", value)?; + write!(writer, "{value}")?; Ok(()) } @@ -91,7 +91,7 @@ fn write_float_number(writer: &mut W, value: f64) -> capnp::R // Inf, -inf and NaN are not allowed in the JSON spec. Storing into string. if value.is_finite() { - write!(writer, "{}", value)?; + write!(writer, "{value}")?; } else if value.is_nan() { write_string(writer, "NaN")?; } else if value.is_infinite() { @@ -116,7 +116,7 @@ fn write_string(writer: &mut W, value: &str) -> capnp::Result '\u{08}' => write!(writer, "\\b")?, '\u{0C}' => write!(writer, "\\f")?, c if c.is_control() => write!(writer, "\\u{:04x}", c as u32)?, - c => write!(writer, "{}", c)?, + c => write!(writer, "{c}")?, } } write!(writer, "\"")?; @@ -235,7 +235,7 @@ fn write_object<'reader, W: std::io::Write>( write_string( writer, - format!("{}{}", field_prefix, discriminator_name).as_str(), + format!("{field_prefix}{discriminator_name}").as_str(), )?; write!(writer, ":")?; write_string(writer, active_union_member_meta.name)?; @@ -245,7 +245,7 @@ fn write_object<'reader, W: std::io::Write>( write!(writer, ",")?; } *first = false; - write_string(writer, format!("{}{}", field_prefix, value_name).as_str())?; + write_string(writer, format!("{field_prefix}{value_name}").as_str())?; write!(writer, ":")?; } let field_value = reader.get(active_union_member)?; @@ -272,7 +272,7 @@ fn write_data( write!(writer, ",")?; } first = false; - write!(writer, "{}", byte)?; + write!(writer, "{byte}")?; } write!(writer, "]")?; Ok(()) diff --git a/capnp-json/test/Cargo.toml b/capnp-json/test/Cargo.toml index 051733a1f..13dca1d1a 100644 --- a/capnp-json/test/Cargo.toml +++ b/capnp-json/test/Cargo.toml @@ -18,3 +18,8 @@ capnp = { path = "../../capnp" } capnpc = { path = "../../capnpc" } capnp-json = { path = "../" } external-crate = { path = "../../capnpc/test/external-crate" } + +[lints.clippy] +type_complexity = "allow" # this should be removed in future +extra_unused_type_parameters = "allow" +match_single_binding = "allow" From a3d65589efe8d78957eb33cacec8c4448fb3ee6f Mon Sep 17 00:00:00 2001 From: Ben Jackson Date: Mon, 8 Dec 2025 19:57:47 +0000 Subject: [PATCH 20/29] Remove trailing whitespace from test that breaks flaky rustfmt --- capnp-json/test/json.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/capnp-json/test/json.rs b/capnp-json/test/json.rs index 7de70ee5b..78b1ebd14 100644 --- a/capnp-json/test/json.rs +++ b/capnp-json/test/json.rs @@ -431,7 +431,7 @@ mod tests { "int32Field": 0, "int64Field": 0, "uInt8Field": 0, - "uInt16Field" + "uInt16Field" : 0, "uInt32Field": 0, "uInt64Field": 0, From 9b5ab3fa1b87366973d5ec1162514a3400a4a535 Mon Sep 17 00:00:00 2001 From: Ben Jackson Date: Mon, 8 Dec 2025 20:15:43 +0000 Subject: [PATCH 21/29] More clippy --- capnp-json/test/Cargo.toml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/capnp-json/test/Cargo.toml b/capnp-json/test/Cargo.toml index 13dca1d1a..ed3fa9bd4 100644 --- a/capnp-json/test/Cargo.toml +++ b/capnp-json/test/Cargo.toml @@ -20,6 +20,7 @@ capnp-json = { path = "../" } external-crate = { path = "../../capnpc/test/external-crate" } [lints.clippy] -type_complexity = "allow" # this should be removed in future +type_complexity = "allow" extra_unused_type_parameters = "allow" match_single_binding = "allow" +approx_constant = "allow" From d3e3d546c4bb17128e39481f5b2418cf418ca59b Mon Sep 17 00:00:00 2001 From: Ben Jackson Date: Thu, 11 Dec 2025 20:32:17 +0000 Subject: [PATCH 22/29] Don't encode Void/null values in discriminated unions --- capnp-json/src/decode.rs | 10 ++++++++++ capnp-json/src/encode.rs | 20 ++++++++++++-------- capnp-json/test/json.rs | 26 +++++++++++++++++++++++++- 3 files changed, 47 insertions(+), 9 deletions(-) diff --git a/capnp-json/src/decode.rs b/capnp-json/src/decode.rs index 678e5fec0..f88d4b940 100644 --- a/capnp-json/src/decode.rs +++ b/capnp-json/src/decode.rs @@ -727,6 +727,16 @@ fn decode_struct( } else { field_meta.name }; + if matches!( + field.get_type().which(), + capnp::introspect::TypeVariant::Void + ) { + // Void union member; just set the discriminant + builder + .reborrow() + .set(field, capnp::dynamic_value::Reader::Void)?; + break; + } decode_member(builder.reborrow(), field, &field_meta, value, value_name)?; break; } diff --git a/capnp-json/src/encode.rs b/capnp-json/src/encode.rs index e1348d3a7..78477f29c 100644 --- a/capnp-json/src/encode.rs +++ b/capnp-json/src/encode.rs @@ -219,7 +219,9 @@ fn write_object<'reader, W: std::io::Write>( EncodingOptions::from_field(&field_prefix, &active_union_member)?; if reader.has(active_union_member)? { let mut value_name = active_union_member_meta.name; + let mut suppress_void = false; if let Some(discriminator) = discriminator { + suppress_void = true; if !*first { write!(writer, ",")?; } @@ -240,16 +242,18 @@ fn write_object<'reader, W: std::io::Write>( write!(writer, ":")?; write_string(writer, active_union_member_meta.name)?; } - if active_union_member_meta.flatten.is_none() { - if !*first { - write!(writer, ",")?; + let field_value = reader.get(active_union_member)?; + if !suppress_void || !matches!(field_value, capnp::dynamic_value::Reader::Void) { + if active_union_member_meta.flatten.is_none() { + if !*first { + write!(writer, ",")?; + } + *first = false; + write_string(writer, format!("{field_prefix}{value_name}").as_str())?; + write!(writer, ":")?; } - *first = false; - write_string(writer, format!("{field_prefix}{value_name}").as_str())?; - write!(writer, ":")?; + serialize_value_to(writer, field_value, &active_union_member_meta, first)?; } - let field_value = reader.get(active_union_member)?; - serialize_value_to(writer, field_value, &active_union_member_meta, first)?; } } if !flatten { diff --git a/capnp-json/test/json.rs b/capnp-json/test/json.rs index 78b1ebd14..85f1143b4 100644 --- a/capnp-json/test/json.rs +++ b/capnp-json/test/json.rs @@ -309,7 +309,7 @@ mod tests { { let mut union_with_void = root.reborrow().init_union_with_void(); union_with_void.set_void_value(()); - expected.push_str(r#""unionWithVoid":{"type":"voidValue","voidValue":null},"#); + expected.push_str(r#""unionWithVoid":{"type":"voidValue"},"#); } expected.pop(); // Remove trailing comma @@ -745,4 +745,28 @@ mod tests { Ok(()) } + + #[test] + fn test_decode_union_with_void() -> capnp::Result<()> { + let json = r#" + { + "unionWithVoid": { + "type": "voidValue" + } + } + "#; + + let mut builder = capnp::message::Builder::new_default(); + let mut root = + builder.init_root::>(); + json::from_json(json, root.reborrow())?; + + let reader = root.into_reader(); + assert!(matches!( + reader.get_union_with_void().which()?, + crate::json_test_capnp::test_json_annotations::union_with_void::VoidValue(_) + )); + + Ok(()) + } } From 20339ea33af580d0b172a1266c12f6d8e5347dd3 Mon Sep 17 00:00:00 2001 From: Ben Jackson Date: Thu, 11 Dec 2025 22:49:21 +0000 Subject: [PATCH 23/29] Test for discriminator without a name --- capnp-json/test/json-test.capnp | 12 +++++++++++ capnp-json/test/json.rs | 36 +++++++++++++++++++++++++++++++++ 2 files changed, 48 insertions(+) diff --git a/capnp-json/test/json-test.capnp b/capnp-json/test/json-test.capnp index 58234942b..839ee0be2 100644 --- a/capnp-json/test/json-test.capnp +++ b/capnp-json/test/json-test.capnp @@ -132,3 +132,15 @@ struct TestRenamedAnonUnion { struct NestedHex { dataAllTheWayDown @0 : List(List(Data)) $Json.hex; } + +struct UnnamedDiscriminator { + baz: union $Json.discriminator() { + foo @0 :Text; + bar @1 :UInt32; + } + + sbaz: union $Json.discriminator() $Json.flatten() { + sfoo @2 :Text; + sbar @3 :UInt32; + } +} diff --git a/capnp-json/test/json.rs b/capnp-json/test/json.rs index 85f1143b4..15f0de436 100644 --- a/capnp-json/test/json.rs +++ b/capnp-json/test/json.rs @@ -769,4 +769,40 @@ mod tests { Ok(()) } + + #[test] + fn test_encode_decode_no_name_discriminator() -> capnp::Result<()> { + let mut builder = capnp::message::Builder::new_default(); + let mut root = + builder.init_root::>(); + root.reborrow().init_baz().set_bar(100); + root.reborrow().init_sbaz().set_sfoo("Hello"); + let json = json::to_json(root.reborrow_as_reader())?; + assert_eq!( + r#"{"baz":{"baz":"bar","bar":100},"sbaz":"sfoo","sfoo":"Hello"}"#, + json + ); + + let mut builder = capnp::message::Builder::new_default(); + let mut root = + builder.init_root::>(); + json::from_json(&json, root.reborrow())?; + let reader = root.into_reader(); + assert_eq!( + 100, + match reader.get_baz().which()? { + crate::json_test_capnp::unnamed_discriminator::baz::Bar(b) => b, + _ => panic!("Expected Bar"), + }, + ); + assert_eq!( + "Hello", + match reader.get_sbaz().which()? { + crate::json_test_capnp::unnamed_discriminator::sbaz::Sfoo(s) => s?.to_str()?, + _ => panic!("Expected Sfoo"), + } + ); + + Ok(()) + } } From 8516b735dd0245c8f078044115a5d067e085f812 Mon Sep 17 00:00:00 2001 From: Ben Jackson Date: Thu, 11 Dec 2025 22:59:55 +0000 Subject: [PATCH 24/29] Remove redundant argument --- capnp-json/test/build.rs | 1 - 1 file changed, 1 deletion(-) diff --git a/capnp-json/test/build.rs b/capnp-json/test/build.rs index 5a74494ad..2a2e39e8c 100644 --- a/capnp-json/test/build.rs +++ b/capnp-json/test/build.rs @@ -1,6 +1,5 @@ fn main() { capnpc::CompilerCommand::new() - .crate_provides("external_crate", [0xe6f94f52f7be8fe2]) .crate_provides("capnp_json", [0x8ef99297a43a5e34]) // json.capnp .file("test.capnp") .file("json-test.capnp") From f316fe4c576c764cd5c34c5f96d0903cba9fd3a8 Mon Sep 17 00:00:00 2001 From: Ben Jackson Date: Fri, 12 Dec 2025 00:23:37 +0000 Subject: [PATCH 25/29] Add tests that round trip data using 'capnp convert' to prove compatibility with the c++ implementation... and fix the resulting bugs found --- capnp-json/src/decode.rs | 23 ++- capnp-json/test/cppcompat.rs | 363 +++++++++++++++++++++++++++++++++++ capnp-json/test/json.rs | 2 + 3 files changed, 382 insertions(+), 6 deletions(-) create mode 100644 capnp-json/test/cppcompat.rs diff --git a/capnp-json/src/decode.rs b/capnp-json/src/decode.rs index f88d4b940..c7678bc86 100644 --- a/capnp-json/src/decode.rs +++ b/capnp-json/src/decode.rs @@ -429,11 +429,22 @@ fn decode_primitive<'json, 'meta>( JsonValue::String(field_value) => { let enum_schema = capnp::schema::EnumSchema::new(enum_schema); let Some(enum_value) = enum_schema.get_enumerants()?.iter().find(|e| { - e.get_proto() - .get_name() - .ok() - .and_then(|n| n.to_str().ok()) - .is_some_and(|s| s == field_value) + // FIXME: this is naive, enum values can be renamed using + // $Json.name so we need to handle that + + let annotations = e.get_annotations().ok(); + let value = annotations + .and_then(|anns| { + anns.iter() + .find(|a| a.get_id() == json_capnp::name::ID) + .and_then(|a| { + a.get_value() + .ok() + .map(|v| v.downcast::().to_str().ok()) + }) + }) + .unwrap_or(e.get_proto().get_name().ok().and_then(|n| n.to_str().ok())); + value.is_some_and(|s| s == field_value) }) else { return Err(capnp::Error::failed(format!( "Invalid enum value '{}' for field {}", @@ -662,7 +673,7 @@ fn decode_struct( } for field in builder.get_schema().get_non_union_fields()? { - let field_meta = EncodingOptions::from_field(meta.prefix, &field)?; + let field_meta = EncodingOptions::from_field(&field_prefix, &field)?; let field_name = format!("{}{}", field_prefix, field_meta.name); decode_member(builder.reborrow(), field, &field_meta, value, &field_name)?; diff --git a/capnp-json/test/cppcompat.rs b/capnp-json/test/cppcompat.rs new file mode 100644 index 000000000..b44534234 --- /dev/null +++ b/capnp-json/test/cppcompat.rs @@ -0,0 +1,363 @@ +#[cfg(test)] +mod tests { + use crate::json_test_capnp::test_json_annotations; + use std::io::Write; + + use capnp::message; + + fn cpp_binary_to_json(proto: &str, kind: &str, data: &[u8]) -> capnp::Result { + let output = std::process::Command::new("capnp") + .args(["convert", "binary:json", proto, kind]) + .stdin(std::process::Stdio::piped()) + .stdout(std::process::Stdio::piped()) + .spawn() + .and_then(|child| { + child.stdin.as_ref().map(|mut stdin| stdin.write_all(data)); + child.wait_with_output() + })?; + String::from_utf8(output.stdout).map_err(|e| e.into()) + } + + fn cpp_json_to_binary(proto: &str, kind: &str, data: &[u8]) -> capnp::Result> { + let output = std::process::Command::new("capnp") + .args(["convert", "json:binary", proto, kind]) + .stdin(std::process::Stdio::piped()) + .stdout(std::process::Stdio::piped()) + .spawn() + .and_then(|child| { + child.stdin.as_ref().map(|mut stdin| stdin.write_all(data)); + child.wait_with_output() + })?; + Ok(output.stdout) + } + + #[test] + fn read_json_from_cpp_encoder() -> capnp::Result<()> { + let mut builder = message::Builder::new_default(); + let mut root: test_json_annotations::Builder<'_> = builder.init_root(); + + root.set_some_field("Some Field"); + { + let mut a_group = root.reborrow().init_a_group(); + // a_group is flattenned + a_group.set_flat_foo(0xF00); + a_group.set_flat_bar("0xBaa"); + a_group.reborrow().init_flat_baz().set_hello(true); + a_group.reborrow().init_double_flat().set_flat_qux("Qux"); + } + + { + let mut prefixed_group = root.reborrow().init_prefixed_group(); + prefixed_group.set_foo("Foo"); + prefixed_group.set_bar(0xBAA); + prefixed_group.reborrow().init_baz().set_hello(false); + prefixed_group.reborrow().init_more_prefix().set_qux("Qux"); + } + + { + let mut a_union_bar = root.reborrow().init_a_union().init_bar(); + a_union_bar.set_bar_member(0xAAB); + a_union_bar.set_multi_member("Member"); + } + + { + let mut dependency = root.reborrow().init_dependency(); + dependency.set_foo("dep-foo"); + } + + { + let mut simple_group = root.reborrow().init_simple_group(); + simple_group.set_grault("grault"); + } + + { + let mut e = root.reborrow().init_enums(4); + e.set(0, crate::json_test_capnp::TestJsonAnnotatedEnum::Foo); + e.set(1, crate::json_test_capnp::TestJsonAnnotatedEnum::Bar); + e.set(2, crate::json_test_capnp::TestJsonAnnotatedEnum::Baz); + e.set(3, crate::json_test_capnp::TestJsonAnnotatedEnum::Qux); + } + + { + let mut b_union = root.reborrow().init_b_union(); + b_union.set_bar(100); + } + + { + let mut external_union = root.reborrow().init_external_union(); + external_union.reborrow().init_bar().set_value("Value"); + } + + { + let mut union_with_void = root.reborrow().init_union_with_void(); + union_with_void.set_void_value(()); + } + + let mut buf = vec![]; + capnp::serialize::write_message(&mut buf, &builder)?; + let cpp_json = cpp_binary_to_json("./json-test.capnp", "TestJsonAnnotations", &buf)?; + + let mut buidler = message::Builder::new_default(); + let mut root = buidler.init_root::>(); + eprintln!("CPP generated JSON: {}", cpp_json); + capnp_json::from_json(&cpp_json, root.reborrow())?; + + let reader = root.into_reader(); + assert_eq!(reader.get_some_field()?, "Some Field"); + + { + let a_group = reader.get_a_group(); + assert_eq!(a_group.get_flat_foo(), 0xF00); + assert_eq!(a_group.get_flat_bar()?, "0xBaa"); + assert!(a_group.get_flat_baz().get_hello()); + assert_eq!(a_group.get_double_flat().get_flat_qux()?, "Qux"); + } + + { + let prefixed_group = reader.get_prefixed_group(); + assert_eq!(prefixed_group.get_foo()?, "Foo"); + assert_eq!(prefixed_group.get_bar(), 0xBAA); + assert!(!prefixed_group.get_baz().get_hello()); + assert_eq!(prefixed_group.get_more_prefix().get_qux()?, "Qux"); + } + + { + let a_union = reader.get_a_union(); + match a_union.which()? { + crate::json_test_capnp::test_json_annotations::a_union::Bar(bar) => { + assert_eq!(bar.get_bar_member(), 0xAAB); + assert_eq!(bar.get_multi_member()?, "Member"); + } + _ => panic!("Expected Bar variant"), + } + } + + { + let dependency = reader.get_dependency()?; + assert_eq!(dependency.get_foo()?, "dep-foo"); + } + + { + let simple_group = reader.get_simple_group(); + assert_eq!(simple_group.get_grault()?, "grault"); + } + + { + let enums = reader.get_enums()?; + assert_eq!(enums.len(), 4); + assert_eq!( + enums.get(0)?, + crate::json_test_capnp::TestJsonAnnotatedEnum::Foo + ); + assert_eq!( + enums.get(1)?, + crate::json_test_capnp::TestJsonAnnotatedEnum::Bar + ); + assert_eq!( + enums.get(2)?, + crate::json_test_capnp::TestJsonAnnotatedEnum::Baz + ); + assert_eq!( + enums.get(3)?, + crate::json_test_capnp::TestJsonAnnotatedEnum::Qux + ); + } + + { + let b_union = reader.get_b_union(); + match b_union.which()? { + crate::json_test_capnp::test_json_annotations::b_union::Bar(value) => { + assert_eq!(value, 100); + } + _ => panic!("Expected Bar variant"), + } + } + + { + let external_union = reader.get_external_union()?; + match external_union.which()? { + crate::json_test_capnp::test_json_annotations3::Bar(bar) => { + assert_eq!(bar?.get_value()?, "Value"); + } + _ => panic!("Expected Bar variant"), + } + } + + { + let union_with_void = reader.get_union_with_void(); + match union_with_void.which()? { + crate::json_test_capnp::test_json_annotations::union_with_void::VoidValue(()) => { + // ok + } + _ => panic!("Expected VoidValue variant"), + } + } + Ok(()) + } + + #[test] + fn write_json_to_cpp() -> capnp::Result<()> { + let mut builder = message::Builder::new_default(); + let mut root: test_json_annotations::Builder<'_> = builder.init_root(); + + root.set_some_field("Some Field"); + { + let mut a_group = root.reborrow().init_a_group(); + // a_group is flattenned + a_group.set_flat_foo(0xF00); + a_group.set_flat_bar("0xBaa"); + a_group.reborrow().init_flat_baz().set_hello(true); + a_group.reborrow().init_double_flat().set_flat_qux("Qux"); + } + + { + let mut prefixed_group = root.reborrow().init_prefixed_group(); + prefixed_group.set_foo("Foo"); + prefixed_group.set_bar(0xBAA); + prefixed_group.reborrow().init_baz().set_hello(false); + prefixed_group.reborrow().init_more_prefix().set_qux("Qux"); + } + + { + let mut a_union_bar = root.reborrow().init_a_union().init_bar(); + a_union_bar.set_bar_member(0xAAB); + a_union_bar.set_multi_member("Member"); + } + + { + let mut dependency = root.reborrow().init_dependency(); + dependency.set_foo("dep-foo"); + } + + { + let mut simple_group = root.reborrow().init_simple_group(); + simple_group.set_grault("grault"); + } + + { + let mut e = root.reborrow().init_enums(4); + e.set(0, crate::json_test_capnp::TestJsonAnnotatedEnum::Foo); + e.set(1, crate::json_test_capnp::TestJsonAnnotatedEnum::Bar); + e.set(2, crate::json_test_capnp::TestJsonAnnotatedEnum::Baz); + e.set(3, crate::json_test_capnp::TestJsonAnnotatedEnum::Qux); + } + + { + let mut b_union = root.reborrow().init_b_union(); + b_union.set_bar(100); + } + + { + let mut external_union = root.reborrow().init_external_union(); + external_union.reborrow().init_bar().set_value("Value"); + } + + { + let mut union_with_void = root.reborrow().init_union_with_void(); + union_with_void.set_void_value(()); + } + + let json = capnp_json::to_json(root.into_reader())?; + eprintln!("Generated JSON: {}", json); + let cpp_binary = + cpp_json_to_binary("./json-test.capnp", "TestJsonAnnotations", json.as_bytes())?; + let mut cpp_binary = cpp_binary.as_slice(); + + let msg = capnp::serialize::read_message_from_flat_slice( + &mut cpp_binary, + capnp::message::ReaderOptions::default(), + )?; + + let reader = msg.get_root::>()?; + assert_eq!(reader.get_some_field()?, "Some Field"); + + { + let a_group = reader.get_a_group(); + assert_eq!(a_group.get_flat_foo(), 0xF00); + assert_eq!(a_group.get_flat_bar()?, "0xBaa"); + assert!(a_group.get_flat_baz().get_hello()); + assert_eq!(a_group.get_double_flat().get_flat_qux()?, "Qux"); + } + + { + let prefixed_group = reader.get_prefixed_group(); + assert_eq!(prefixed_group.get_foo()?, "Foo"); + assert_eq!(prefixed_group.get_bar(), 0xBAA); + assert!(!prefixed_group.get_baz().get_hello()); + assert_eq!(prefixed_group.get_more_prefix().get_qux()?, "Qux"); + } + + { + let a_union = reader.get_a_union(); + match a_union.which()? { + crate::json_test_capnp::test_json_annotations::a_union::Bar(bar) => { + assert_eq!(bar.get_bar_member(), 0xAAB); + assert_eq!(bar.get_multi_member()?, "Member"); + } + _ => panic!("Expected Bar variant"), + } + } + + { + let dependency = reader.get_dependency()?; + assert_eq!(dependency.get_foo()?, "dep-foo"); + } + + { + let simple_group = reader.get_simple_group(); + assert_eq!(simple_group.get_grault()?, "grault"); + } + + { + let enums = reader.get_enums()?; + assert_eq!(enums.len(), 4); + assert_eq!( + enums.get(0)?, + crate::json_test_capnp::TestJsonAnnotatedEnum::Foo + ); + assert_eq!( + enums.get(1)?, + crate::json_test_capnp::TestJsonAnnotatedEnum::Bar + ); + assert_eq!( + enums.get(2)?, + crate::json_test_capnp::TestJsonAnnotatedEnum::Baz + ); + assert_eq!( + enums.get(3)?, + crate::json_test_capnp::TestJsonAnnotatedEnum::Qux + ); + } + + { + let b_union = reader.get_b_union(); + match b_union.which()? { + crate::json_test_capnp::test_json_annotations::b_union::Bar(value) => { + assert_eq!(value, 100); + } + _ => panic!("Expected Bar variant"), + } + } + + { + let external_union = reader.get_external_union()?; + match external_union.which()? { + crate::json_test_capnp::test_json_annotations3::Bar(bar) => { + assert_eq!(bar?.get_value()?, "Value"); + } + _ => panic!("Expected Bar variant"), + } + } + + { + let union_with_void = reader.get_union_with_void(); + match union_with_void.which()? { + crate::json_test_capnp::test_json_annotations::union_with_void::VoidValue(()) => { + // ok + } + _ => panic!("Expected VoidValue variant"), + } + } + Ok(()) + } +} diff --git a/capnp-json/test/json.rs b/capnp-json/test/json.rs index 15f0de436..37f8cbb86 100644 --- a/capnp-json/test/json.rs +++ b/capnp-json/test/json.rs @@ -22,6 +22,8 @@ capnp::generated_code!(pub mod test_capnp); capnp::generated_code!(pub mod json_test_capnp); +mod cppcompat; + #[cfg(test)] mod tests { use crate::json_test_capnp::test_json_annotations; From be70432b3f83cf1104fe4272d6ead763cd962dea Mon Sep 17 00:00:00 2001 From: Ben Jackson Date: Fri, 12 Dec 2025 00:35:18 +0000 Subject: [PATCH 26/29] Reduce copy paste in the roundtrip test --- capnp-json/test/cppcompat.rs | 182 +++++------------------------------ 1 file changed, 22 insertions(+), 160 deletions(-) diff --git a/capnp-json/test/cppcompat.rs b/capnp-json/test/cppcompat.rs index b44534234..ab00309ce 100644 --- a/capnp-json/test/cppcompat.rs +++ b/capnp-json/test/cppcompat.rs @@ -31,9 +31,9 @@ mod tests { Ok(output.stdout) } - #[test] - fn read_json_from_cpp_encoder() -> capnp::Result<()> { - let mut builder = message::Builder::new_default(); + fn make_test_message( + builder: &mut message::Builder, + ) -> capnp::Result> { let mut root: test_json_annotations::Builder<'_> = builder.init_root(); root.set_some_field("Some Field"); @@ -93,16 +93,10 @@ mod tests { union_with_void.set_void_value(()); } - let mut buf = vec![]; - capnp::serialize::write_message(&mut buf, &builder)?; - let cpp_json = cpp_binary_to_json("./json-test.capnp", "TestJsonAnnotations", &buf)?; - - let mut buidler = message::Builder::new_default(); - let mut root = buidler.init_root::>(); - eprintln!("CPP generated JSON: {}", cpp_json); - capnp_json::from_json(&cpp_json, root.reborrow())?; + Ok(root) + } - let reader = root.into_reader(); + fn check_test_message(reader: test_json_annotations::Reader<'_>) -> capnp::Result<()> { assert_eq!(reader.get_some_field()?, "Some Field"); { @@ -196,67 +190,25 @@ mod tests { } #[test] - fn write_json_to_cpp() -> capnp::Result<()> { + fn read_json_from_cpp_encoder() -> capnp::Result<()> { let mut builder = message::Builder::new_default(); - let mut root: test_json_annotations::Builder<'_> = builder.init_root(); - - root.set_some_field("Some Field"); - { - let mut a_group = root.reborrow().init_a_group(); - // a_group is flattenned - a_group.set_flat_foo(0xF00); - a_group.set_flat_bar("0xBaa"); - a_group.reborrow().init_flat_baz().set_hello(true); - a_group.reborrow().init_double_flat().set_flat_qux("Qux"); - } - - { - let mut prefixed_group = root.reborrow().init_prefixed_group(); - prefixed_group.set_foo("Foo"); - prefixed_group.set_bar(0xBAA); - prefixed_group.reborrow().init_baz().set_hello(false); - prefixed_group.reborrow().init_more_prefix().set_qux("Qux"); - } - - { - let mut a_union_bar = root.reborrow().init_a_union().init_bar(); - a_union_bar.set_bar_member(0xAAB); - a_union_bar.set_multi_member("Member"); - } - - { - let mut dependency = root.reborrow().init_dependency(); - dependency.set_foo("dep-foo"); - } - - { - let mut simple_group = root.reborrow().init_simple_group(); - simple_group.set_grault("grault"); - } - - { - let mut e = root.reborrow().init_enums(4); - e.set(0, crate::json_test_capnp::TestJsonAnnotatedEnum::Foo); - e.set(1, crate::json_test_capnp::TestJsonAnnotatedEnum::Bar); - e.set(2, crate::json_test_capnp::TestJsonAnnotatedEnum::Baz); - e.set(3, crate::json_test_capnp::TestJsonAnnotatedEnum::Qux); - } - - { - let mut b_union = root.reborrow().init_b_union(); - b_union.set_bar(100); - } + make_test_message(&mut builder)?; + let mut buf = vec![]; + capnp::serialize::write_message(&mut buf, &builder)?; + let cpp_json = cpp_binary_to_json("./json-test.capnp", "TestJsonAnnotations", &buf)?; - { - let mut external_union = root.reborrow().init_external_union(); - external_union.reborrow().init_bar().set_value("Value"); - } + let mut buidler = message::Builder::new_default(); + let mut root = buidler.init_root::>(); + eprintln!("CPP generated JSON: {}", cpp_json); + capnp_json::from_json(&cpp_json, root.reborrow())?; - { - let mut union_with_void = root.reborrow().init_union_with_void(); - union_with_void.set_void_value(()); - } + check_test_message(root.into_reader()) + } + #[test] + fn write_json_to_cpp() -> capnp::Result<()> { + let mut builder = message::Builder::new_default(); + let root = make_test_message(&mut builder)?; let json = capnp_json::to_json(root.into_reader())?; eprintln!("Generated JSON: {}", json); let cpp_binary = @@ -268,96 +220,6 @@ mod tests { capnp::message::ReaderOptions::default(), )?; - let reader = msg.get_root::>()?; - assert_eq!(reader.get_some_field()?, "Some Field"); - - { - let a_group = reader.get_a_group(); - assert_eq!(a_group.get_flat_foo(), 0xF00); - assert_eq!(a_group.get_flat_bar()?, "0xBaa"); - assert!(a_group.get_flat_baz().get_hello()); - assert_eq!(a_group.get_double_flat().get_flat_qux()?, "Qux"); - } - - { - let prefixed_group = reader.get_prefixed_group(); - assert_eq!(prefixed_group.get_foo()?, "Foo"); - assert_eq!(prefixed_group.get_bar(), 0xBAA); - assert!(!prefixed_group.get_baz().get_hello()); - assert_eq!(prefixed_group.get_more_prefix().get_qux()?, "Qux"); - } - - { - let a_union = reader.get_a_union(); - match a_union.which()? { - crate::json_test_capnp::test_json_annotations::a_union::Bar(bar) => { - assert_eq!(bar.get_bar_member(), 0xAAB); - assert_eq!(bar.get_multi_member()?, "Member"); - } - _ => panic!("Expected Bar variant"), - } - } - - { - let dependency = reader.get_dependency()?; - assert_eq!(dependency.get_foo()?, "dep-foo"); - } - - { - let simple_group = reader.get_simple_group(); - assert_eq!(simple_group.get_grault()?, "grault"); - } - - { - let enums = reader.get_enums()?; - assert_eq!(enums.len(), 4); - assert_eq!( - enums.get(0)?, - crate::json_test_capnp::TestJsonAnnotatedEnum::Foo - ); - assert_eq!( - enums.get(1)?, - crate::json_test_capnp::TestJsonAnnotatedEnum::Bar - ); - assert_eq!( - enums.get(2)?, - crate::json_test_capnp::TestJsonAnnotatedEnum::Baz - ); - assert_eq!( - enums.get(3)?, - crate::json_test_capnp::TestJsonAnnotatedEnum::Qux - ); - } - - { - let b_union = reader.get_b_union(); - match b_union.which()? { - crate::json_test_capnp::test_json_annotations::b_union::Bar(value) => { - assert_eq!(value, 100); - } - _ => panic!("Expected Bar variant"), - } - } - - { - let external_union = reader.get_external_union()?; - match external_union.which()? { - crate::json_test_capnp::test_json_annotations3::Bar(bar) => { - assert_eq!(bar?.get_value()?, "Value"); - } - _ => panic!("Expected Bar variant"), - } - } - - { - let union_with_void = reader.get_union_with_void(); - match union_with_void.which()? { - crate::json_test_capnp::test_json_annotations::union_with_void::VoidValue(()) => { - // ok - } - _ => panic!("Expected VoidValue variant"), - } - } - Ok(()) + check_test_message(msg.get_root::>()?) } } From f99ddcd3cace92160926f6db8fb6eed413475e19 Mon Sep 17 00:00:00 2001 From: Ben Jackson Date: Fri, 12 Dec 2025 02:25:46 +0000 Subject: [PATCH 27/29] Add failing test showing difference in encoding for named union members with a discriminator --- capnp-json/test/cppcompat.rs | 139 ++++++++++++++++++++++++++++++++ capnp-json/test/json-test.capnp | 12 +++ 2 files changed, 151 insertions(+) diff --git a/capnp-json/test/cppcompat.rs b/capnp-json/test/cppcompat.rs index ab00309ce..0ec35bbde 100644 --- a/capnp-json/test/cppcompat.rs +++ b/capnp-json/test/cppcompat.rs @@ -222,4 +222,143 @@ mod tests { check_test_message(msg.get_root::>()?) } + + #[test] + fn roundtrip_unnamed_discriminator() -> capnp::Result<()> { + let mut builder = message::Builder::new_default(); + let mut root = + builder.init_root::(); + root.reborrow().init_baz().set_bar(100); + root.reborrow().init_sbaz().set_sfoo("Hello"); + + let rust_json = capnp_json::to_json(root.reborrow_as_reader())?; + eprintln!("Generated JSON: {}", rust_json); + + let mut buf = vec![]; + capnp::serialize::write_message(&mut buf, &builder)?; + let cpp_json = cpp_binary_to_json("./json-test.capnp", "UnnamedDiscriminator", &buf)?; + eprintln!("CPP generated JSON: {}", cpp_json); + + let mut read_json_builder = message::Builder::new_default(); + let mut read_json_root = + read_json_builder.init_root::(); + capnp_json::from_json(&cpp_json, read_json_root.reborrow())?; + let read_json_root = read_json_root.into_reader(); + + assert_eq!( + 100, + match read_json_root.get_baz().which()? { + crate::json_test_capnp::unnamed_discriminator::baz::Bar(bar) => bar, + _ => panic!("Expected Bar variant"), + }, + ); + assert_eq!( + "Hello", + match read_json_root.get_sbaz().which()? { + crate::json_test_capnp::unnamed_discriminator::sbaz::Sfoo(sfoo) => + sfoo?.to_str()?, + _ => panic!("Expected SFoo variant"), + }, + ); + + let cpp_binary = cpp_json_to_binary( + "./json-test.capnp", + "UnnamedDiscriminator", + rust_json.as_bytes(), + )?; + let mut cpp_binary = cpp_binary.as_slice(); + + let read_binary = capnp::serialize::read_message_from_flat_slice( + &mut cpp_binary, + capnp::message::ReaderOptions::default(), + )?; + let read_binary_root = + read_binary.get_root::>()?; + + assert_eq!( + 100, + match read_binary_root.get_baz().which()? { + crate::json_test_capnp::unnamed_discriminator::baz::Bar(bar) => bar, + _ => panic!("Expected Bar variant"), + }, + ); + assert_eq!( + "Hello", + match read_binary_root.get_sbaz().which()? { + crate::json_test_capnp::unnamed_discriminator::sbaz::Sfoo(sfoo) => + sfoo?.to_str()?, + _ => panic!("Expected SFoo variant"), + }, + ); + + Ok(()) + } + + #[test] + fn roundtrip_named_discriminator() -> capnp::Result<()> { + let mut builder = message::Builder::new_default(); + let mut root = builder.init_root::(); + root.reborrow().init_baz().set_bar(100); + root.reborrow().init_sbaz().set_sfoo("Hello"); + + let rust_json = capnp_json::to_json(root.reborrow_as_reader())?; + eprintln!("Generated JSON: {}", rust_json); + + let mut buf = vec![]; + capnp::serialize::write_message(&mut buf, &builder)?; + let cpp_json = cpp_binary_to_json("./json-test.capnp", "UnnamedDiscriminator", &buf)?; + eprintln!("CPP generated JSON: {}", cpp_json); + + let mut read_json_builder = message::Builder::new_default(); + let mut read_json_root = + read_json_builder.init_root::(); + capnp_json::from_json(&cpp_json, read_json_root.reborrow())?; + let read_json_root = read_json_root.into_reader(); + + assert_eq!( + 100, + match read_json_root.get_baz().which()? { + crate::json_test_capnp::named_discriminator::baz::Bar(bar) => bar, + _ => panic!("Expected Bar variant"), + }, + ); + assert_eq!( + "Hello", + match read_json_root.get_sbaz().which()? { + crate::json_test_capnp::named_discriminator::sbaz::Sfoo(sfoo) => sfoo?.to_str()?, + _ => panic!("Expected SFoo variant"), + }, + ); + + let cpp_binary = cpp_json_to_binary( + "./json-test.capnp", + "UnnamedDiscriminator", + rust_json.as_bytes(), + )?; + let mut cpp_binary = cpp_binary.as_slice(); + + let read_binary = capnp::serialize::read_message_from_flat_slice( + &mut cpp_binary, + capnp::message::ReaderOptions::default(), + )?; + let read_binary_root = + read_binary.get_root::>()?; + + assert_eq!( + 100, + match read_binary_root.get_baz().which()? { + crate::json_test_capnp::named_discriminator::baz::Bar(bar) => bar, + _ => panic!("Expected Bar variant"), + }, + ); + assert_eq!( + "Hello", + match read_binary_root.get_sbaz().which()? { + crate::json_test_capnp::named_discriminator::sbaz::Sfoo(sfoo) => sfoo?.to_str()?, + _ => panic!("Expected SFoo variant"), + }, + ); + + Ok(()) + } } diff --git a/capnp-json/test/json-test.capnp b/capnp-json/test/json-test.capnp index 839ee0be2..1455d8b83 100644 --- a/capnp-json/test/json-test.capnp +++ b/capnp-json/test/json-test.capnp @@ -144,3 +144,15 @@ struct UnnamedDiscriminator { sbar @3 :UInt32; } } + +struct NamedDiscriminator { + baz: union $Json.discriminator(name="baz_kind") { + foo @0 :Text; + bar @1 :UInt32; + } + + sbaz: union $Json.discriminator(name="sbaz_kind") $Json.flatten() { + sfoo @2 :Text; + sbar @3 :UInt32; + } +} From f7ecd7521b8037c30a855729f454702b9ecfabe1 Mon Sep 17 00:00:00 2001 From: Ben Jackson Date: Fri, 12 Dec 2025 19:10:51 +0000 Subject: [PATCH 28/29] Allow missing discriminator as this is required for c++ compat --- capnp-json/src/decode.rs | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/capnp-json/src/decode.rs b/capnp-json/src/decode.rs index c7678bc86..8149095a4 100644 --- a/capnp-json/src/decode.rs +++ b/capnp-json/src/decode.rs @@ -709,6 +709,11 @@ fn decode_struct( None } } + None => None, + }; + + let discriminant = match discriminant { + Some(discriminant) => Some(discriminant), None => { // find the first field that exists matching a union field? let mut discriminant = None; @@ -723,6 +728,7 @@ fn decode_struct( discriminant } }; + if let Some(discriminant) = discriminant { for field in builder.get_schema().get_union_fields()? { let field_meta = EncodingOptions::from_field(meta.prefix, &field)?; From 2cea57f75b443ac1a4eba49ea5728a7d7c4bd81f Mon Sep 17 00:00:00 2001 From: Ben Jackson Date: Tue, 16 Dec 2025 20:23:01 +0000 Subject: [PATCH 29/29] Don't output a discriminator for unflattened unnamed-discriminator union --- capnp-json/src/encode.rs | 35 ++++++++++++++++++++++------------- capnp-json/test/cppcompat.rs | 14 ++++++++------ capnp-json/test/json.rs | 5 +---- 3 files changed, 31 insertions(+), 23 deletions(-) diff --git a/capnp-json/src/encode.rs b/capnp-json/src/encode.rs index 78477f29c..bf643c694 100644 --- a/capnp-json/src/encode.rs +++ b/capnp-json/src/encode.rs @@ -221,26 +221,35 @@ fn write_object<'reader, W: std::io::Write>( let mut value_name = active_union_member_meta.name; let mut suppress_void = false; if let Some(discriminator) = discriminator { - suppress_void = true; - if !*first { - write!(writer, ",")?; - } - *first = false; let discriminator_name = if discriminator.has_name() { - discriminator.get_name()?.to_str()? + Some(discriminator.get_name()?.to_str()?) + } else if flatten { + Some(meta.name) } else { - meta.name + // https://github.com/capnproto/capnproto/issues/2461 + // The discriminator is not output even if the annoyation is + // present if: + // - it doesn't have an explicit name, and + // - the group is _not_ being flattened. + None }; if discriminator.has_value_name() { value_name = discriminator.get_value_name()?.to_str()?; } - write_string( - writer, - format!("{field_prefix}{discriminator_name}").as_str(), - )?; - write!(writer, ":")?; - write_string(writer, active_union_member_meta.name)?; + if let Some(discriminator_name) = discriminator_name { + if !*first { + write!(writer, ",")?; + } + *first = false; + suppress_void = true; + write_string( + writer, + format!("{field_prefix}{discriminator_name}").as_str(), + )?; + write!(writer, ":")?; + write_string(writer, active_union_member_meta.name)?; + } } let field_value = reader.get(active_union_member)?; if !suppress_void || !matches!(field_value, capnp::dynamic_value::Reader::Void) { diff --git a/capnp-json/test/cppcompat.rs b/capnp-json/test/cppcompat.rs index 0ec35bbde..b28820759 100644 --- a/capnp-json/test/cppcompat.rs +++ b/capnp-json/test/cppcompat.rs @@ -232,12 +232,13 @@ mod tests { root.reborrow().init_sbaz().set_sfoo("Hello"); let rust_json = capnp_json::to_json(root.reborrow_as_reader())?; - eprintln!("Generated JSON: {}", rust_json); + eprintln!("unnamed_discriminator Generated JSON: {}", rust_json); let mut buf = vec![]; capnp::serialize::write_message(&mut buf, &builder)?; + let cpp_json = cpp_binary_to_json("./json-test.capnp", "UnnamedDiscriminator", &buf)?; - eprintln!("CPP generated JSON: {}", cpp_json); + eprintln!("unnamed_discriminator CPP generated JSON: {}", cpp_json); let mut read_json_builder = message::Builder::new_default(); let mut read_json_root = @@ -302,12 +303,13 @@ mod tests { root.reborrow().init_sbaz().set_sfoo("Hello"); let rust_json = capnp_json::to_json(root.reborrow_as_reader())?; - eprintln!("Generated JSON: {}", rust_json); + eprintln!("named_discriminator Generated JSON: {}", rust_json); let mut buf = vec![]; capnp::serialize::write_message(&mut buf, &builder)?; - let cpp_json = cpp_binary_to_json("./json-test.capnp", "UnnamedDiscriminator", &buf)?; - eprintln!("CPP generated JSON: {}", cpp_json); + + let cpp_json = cpp_binary_to_json("./json-test.capnp", "NamedDiscriminator", &buf)?; + eprintln!("named_discriminator CPP generated JSON: {}", cpp_json); let mut read_json_builder = message::Builder::new_default(); let mut read_json_root = @@ -332,7 +334,7 @@ mod tests { let cpp_binary = cpp_json_to_binary( "./json-test.capnp", - "UnnamedDiscriminator", + "NamedDiscriminator", rust_json.as_bytes(), )?; let mut cpp_binary = cpp_binary.as_slice(); diff --git a/capnp-json/test/json.rs b/capnp-json/test/json.rs index 37f8cbb86..e1166f6c9 100644 --- a/capnp-json/test/json.rs +++ b/capnp-json/test/json.rs @@ -780,10 +780,7 @@ mod tests { root.reborrow().init_baz().set_bar(100); root.reborrow().init_sbaz().set_sfoo("Hello"); let json = json::to_json(root.reborrow_as_reader())?; - assert_eq!( - r#"{"baz":{"baz":"bar","bar":100},"sbaz":"sfoo","sfoo":"Hello"}"#, - json - ); + assert_eq!(r#"{"baz":{"bar":100},"sbaz":"sfoo","sfoo":"Hello"}"#, json); let mut builder = capnp::message::Builder::new_default(); let mut root =