From 27073728b083886868f4694f19bc6506707c0352 Mon Sep 17 00:00:00 2001 From: Antoine Cordelle Date: Tue, 22 Aug 2023 16:27:52 +0100 Subject: [PATCH] Add codegen to expose getter as bytes for text fields Exposes as getter as bytes for text fields in the codegen. This is a secondary getter that is for now only populating anything for text fields for readers. I have duplicated the method and trimmed it only for texts instead of complexifying the already existent getter_text function for the sake of clarity. This also regenerates the corresponding rpc_capnp and schema_capnp rust files. --- capnp-rpc/src/rpc_capnp.rs | 18 ++++++ capnp/src/schema_capnp.rs | 90 ++++++++++++++++++++++++++ capnpc/src/codegen.rs | 129 ++++++++++++++++++++++++++++++------- 3 files changed, 215 insertions(+), 22 deletions(-) diff --git a/capnp-rpc/src/rpc_capnp.rs b/capnp-rpc/src/rpc_capnp.rs index ff302a020..8e95ecb76 100644 --- a/capnp-rpc/src/rpc_capnp.rs +++ b/capnp-rpc/src/rpc_capnp.rs @@ -8008,6 +8008,15 @@ pub mod exception { } } #[inline] + pub fn get_reason_as_bytes(self) -> ::capnp::Result<&'a [u8]> { + ::core::result::Result::Ok(::capnp::text::Reader::as_bytes( + ::capnp::traits::FromPointerReader::get_from_pointer( + &self.reader.get_pointer_field(0), + ::core::option::Option::None, + )?, + )) + } + #[inline] pub fn has_reason(&self) -> bool { !self.reader.get_pointer_field(0).is_null() } @@ -8037,6 +8046,15 @@ pub mod exception { } } #[inline] + pub fn get_trace_as_bytes(self) -> ::capnp::Result<&'a [u8]> { + ::core::result::Result::Ok(::capnp::text::Reader::as_bytes( + ::capnp::traits::FromPointerReader::get_from_pointer( + &self.reader.get_pointer_field(1), + ::core::option::Option::None, + )?, + )) + } + #[inline] pub fn has_trace(&self) -> bool { !self.reader.get_pointer_field(1).is_null() } diff --git a/capnp/src/schema_capnp.rs b/capnp/src/schema_capnp.rs index 4a1964ca6..67264377c 100644 --- a/capnp/src/schema_capnp.rs +++ b/capnp/src/schema_capnp.rs @@ -118,6 +118,15 @@ pub mod node { } } #[inline] + pub fn get_display_name_as_bytes(self) -> crate::Result<&'a [u8]> { + ::core::result::Result::Ok(crate::text::Reader::as_bytes( + crate::traits::FromPointerReader::get_from_pointer( + &self.reader.get_pointer_field(0), + ::core::option::Option::None, + )?, + )) + } + #[inline] pub fn has_display_name(&self) -> bool { !self.reader.get_pointer_field(0).is_null() } @@ -899,6 +908,15 @@ pub mod node { } } #[inline] + pub fn get_name_as_bytes(self) -> crate::Result<&'a [u8]> { + ::core::result::Result::Ok(crate::text::Reader::as_bytes( + 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() } @@ -1192,6 +1210,15 @@ pub mod node { } } #[inline] + pub fn get_name_as_bytes(self) -> crate::Result<&'a [u8]> { + ::core::result::Result::Ok(crate::text::Reader::as_bytes( + 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() } @@ -1517,6 +1544,15 @@ pub mod node { } } #[inline] + pub fn get_doc_comment_as_bytes(self) -> crate::Result<&'a [u8]> { + ::core::result::Result::Ok(crate::text::Reader::as_bytes( + crate::traits::FromPointerReader::get_from_pointer( + &self.reader.get_pointer_field(0), + ::core::option::Option::None, + )?, + )) + } + #[inline] pub fn has_doc_comment(&self) -> bool { !self.reader.get_pointer_field(0).is_null() } @@ -1926,6 +1962,15 @@ pub mod node { } } #[inline] + pub fn get_doc_comment_as_bytes(self) -> crate::Result<&'a [u8]> { + ::core::result::Result::Ok(crate::text::Reader::as_bytes( + crate::traits::FromPointerReader::get_from_pointer( + &self.reader.get_pointer_field(0), + ::core::option::Option::None, + )?, + )) + } + #[inline] pub fn has_doc_comment(&self) -> bool { !self.reader.get_pointer_field(0).is_null() } @@ -4436,6 +4481,15 @@ pub mod field { } } #[inline] + pub fn get_name_as_bytes(self) -> crate::Result<&'a [u8]> { + ::core::result::Result::Ok(crate::text::Reader::as_bytes( + 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() } @@ -5951,6 +6005,15 @@ pub mod enumerant { } } #[inline] + pub fn get_name_as_bytes(self) -> crate::Result<&'a [u8]> { + ::core::result::Result::Ok(crate::text::Reader::as_bytes( + 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() } @@ -6664,6 +6727,15 @@ pub mod method { } } #[inline] + pub fn get_name_as_bytes(self) -> crate::Result<&'a [u8]> { + ::core::result::Result::Ok(crate::text::Reader::as_bytes( + 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() } @@ -13848,6 +13920,15 @@ pub mod code_generator_request { } } #[inline] + pub fn get_filename_as_bytes(self) -> crate::Result<&'a [u8]> { + ::core::result::Result::Ok(crate::text::Reader::as_bytes( + crate::traits::FromPointerReader::get_from_pointer( + &self.reader.get_pointer_field(0), + ::core::option::Option::None, + )?, + )) + } + #[inline] pub fn has_filename(&self) -> bool { !self.reader.get_pointer_field(0).is_null() } @@ -14263,6 +14344,15 @@ pub mod code_generator_request { } } #[inline] + pub fn get_name_as_bytes(self) -> crate::Result<&'a [u8]> { + ::core::result::Result::Ok(crate::text::Reader::as_bytes( + 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() } diff --git a/capnpc/src/codegen.rs b/capnpc/src/codegen.rs index 75855e78e..207d54938 100644 --- a/capnpc/src/codegen.rs +++ b/capnpc/src/codegen.rs @@ -673,6 +673,28 @@ fn get_params(ctx: &GeneratorContext, mut node_id: u64) -> ::capnp::Result, + ctx: &GeneratorContext, + default_name: String, + default_value: schema_capnp::value::Reader, +) -> ::capnp::Result { + if reg_field.get_had_explicit_default() { + *default_decl = Some(crate::pointer_constants::word_array_declaration( + ctx, + &default_name, + ::capnp::raw::get_struct_pointer_section(default_value).get(0), + crate::pointer_constants::WordArrayDeclarationOptions { public: true }, + )?); + Ok(format!( + "::core::option::Option::Some(&_private::{default_name}[..])" + )) + } else { + Ok("::core::option::Option::None".to_string()) + } +} + // // Returns (type, getter body, default_decl) // @@ -784,28 +806,6 @@ pub fn getter_text( } } - fn set_default( - reg_field: slot::Reader, - default_decl: &mut Option, - ctx: &GeneratorContext, - default_name: String, - default_value: value::Reader, - ) -> ::capnp::Result { - if reg_field.get_had_explicit_default() { - *default_decl = Some(crate::pointer_constants::word_array_declaration( - ctx, - &default_name, - ::capnp::raw::get_struct_pointer_section(default_value).get(0), - crate::pointer_constants::WordArrayDeclarationOptions { public: true }, - )?); - Ok(format!( - "::core::option::Option::Some(&_private::{default_name}[..])" - )) - } else { - Ok("::core::option::Option::None".to_string()) - } - } - let getter_fragment = match (module_type, default) { (type_::Void(()), value::Void(())) => { if is_fn { @@ -931,6 +931,80 @@ pub fn getter_text( } } +// +// Returns (type, getter body, default_decl) +// Currently only required for reader text fields. +// +pub fn secondary_getter_text( + ctx: &GeneratorContext, + field: &schema_capnp::field::Reader, +) -> ::capnp::Result> { + use capnp::schema_capnp::*; + + match field.which()? { + field::Group(_) => Ok(None), + field::Slot(reg_field) => { + let raw_type = reg_field.get_type()?; + let default_value = reg_field.get_default_value()?; + let default = default_value.which()?; + let module_type = raw_type.which()?; + + if let (type_::Text(()), value::Text(_)) = (module_type, default) { + let mut default_decl = None; + let offset = reg_field.get_offset() as usize; + let module_string = "Reader"; + let member = camel_to_snake_case(module_string); + + let default_name = format!( + "DEFAULT_{}", + snake_to_upper_case(&camel_to_snake_case(get_field_name(*field)?)) + ); + let should_get_option = is_option_field(*field)?; + + let result_type = if should_get_option { + fmt!(ctx, "-> {capnp}::Result>") + } else { + fmt!(ctx, "-> {capnp}::Result<&'a [u8]>") + }; + + let default = set_default( + reg_field, + &mut default_decl, + ctx, + default_name, + default_value, + )?; + + let getter_fragment = fmt!(ctx, "::core::result::Result::Ok({capnp}::text::Reader::as_bytes({capnp}::traits::FromPointerReader::get_from_pointer(&self.{member}.get_pointer_field({offset}),{default})?))"); + + let getter_code = if should_get_option { + Branch(vec![ + Line(format!( + "if self.{member}.is_pointer_field_null({offset}) {{" + )), + indent(Line( + "core::result::Result::Ok(core::option::Option::None)".to_string(), + )), + Line("} else {".to_string()), + indent(Line(format!( + "{getter_fragment}.map(::core::option::Option::Some)" + ))), + Line("}".to_string()), + ]) + } else { + Line(getter_fragment) + }; + + let getter_suffix = "as_bytes".to_string(); + + Ok(Some((result_type, getter_code, getter_suffix))) + } else { + Ok(None) + } + } + } +} + fn zero_fields_of_group( ctx: &GeneratorContext, node_id: u64, @@ -2078,6 +2152,17 @@ fn generate_node( line("}"), ])); + if let Some((ty, get, getter_suffix)) = secondary_getter_text(ctx, &field)? { + reader_members.push(Branch(vec![ + line("#[inline]"), + Line(format!( + "pub fn get_{styled_name}_{getter_suffix}(self) {ty} {{" + )), + indent(get), + line("}"), + ])); + } + let (ty_b, get_b, _) = getter_text(ctx, &field, false, true)?; builder_members.push(Branch(vec![ line("#[inline]"),