1use std::collections;
23use std::collections::{HashMap, HashSet};
24use std::path::{Path, PathBuf};
25
26use capnp::schema_capnp;
27use capnp::Error;
28
29use self::FormattedText::{BlankLine, Branch, Indent, Line};
30use crate::codegen_types::{do_branding, Leaf, RustNodeInfo, RustTypeInfo, TypeParameterTexts};
31use crate::convert_io_err;
32use crate::pointer_constants::generate_pointer_constant;
33
34pub struct CodeGenerationCommand {
36 output_directory: PathBuf,
37 default_parent_module: Vec<String>,
38 raw_code_generator_request_path: Option<PathBuf>,
39 capnp_root: String,
40 crates_provide_map: HashMap<u64, String>,
41}
42
43impl Default for CodeGenerationCommand {
44 fn default() -> Self {
45 Self {
46 output_directory: PathBuf::new(),
47 default_parent_module: Vec::new(),
48 raw_code_generator_request_path: None,
49 capnp_root: "::capnp".into(),
50 crates_provide_map: HashMap::new(),
51 }
52 }
53}
54
55impl CodeGenerationCommand {
56 pub fn new() -> Self {
58 Self::default()
59 }
60
61 pub fn output_directory<P>(&mut self, path: P) -> &mut Self
63 where
64 P: AsRef<Path>,
65 {
66 self.output_directory = path.as_ref().to_path_buf();
67 self
68 }
69
70 pub fn default_parent_module(&mut self, default_parent_module: Vec<String>) -> &mut Self {
75 self.default_parent_module = default_parent_module;
76 self
77 }
78
79 pub fn capnp_root(&mut self, capnp_root: &str) -> &mut Self {
84 self.capnp_root = capnp_root.into();
85 self
86 }
87
88 pub fn raw_code_generator_request_path<P>(&mut self, path: P) -> &mut Self
90 where
91 P: AsRef<Path>,
92 {
93 self.raw_code_generator_request_path = Some(path.as_ref().to_path_buf());
94 self
95 }
96
97 pub fn crates_provide_map(&mut self, map: HashMap<u64, String>) -> &mut Self {
106 self.crates_provide_map = map;
107 self
108 }
109
110 pub fn run<T>(&mut self, inp: T) -> ::capnp::Result<()>
112 where
113 T: std::io::Read,
114 {
115 use capnp::serialize;
116 use std::io::Write;
117
118 let message = serialize::read_message(inp, capnp::message::ReaderOptions::new())?;
119
120 let ctx = GeneratorContext::new_from_code_generation_command(self, &message)?;
121
122 for requested_file in ctx.request.get_requested_files()? {
123 let id = requested_file.get_id();
124 let mut filepath = self.output_directory.to_path_buf();
125 let requested = ::std::path::PathBuf::from(requested_file.get_filename()?.to_str()?);
126 filepath.push(requested);
127 if let Some(parent) = filepath.parent() {
128 ::std::fs::create_dir_all(parent).map_err(convert_io_err)?;
129 }
130
131 let root_name = path_to_stem_string(&filepath)?.replace('-', "_");
132 filepath.set_file_name(format!("{root_name}_capnp.rs"));
133
134 let capnp_version = match ctx.request.get_capnp_version() {
135 Ok(version) => format!(
136 "{}.{}.{}",
137 version.get_major(),
138 version.get_minor(),
139 version.get_micro()
140 ),
141 Err(_) => "<unknown>".to_owned(),
142 };
143
144 let lines =
145 Branch(vec![
146 Line(
147 "// @generated by the capnpc-rust plugin to the Cap'n Proto schema compiler."
148 .to_string(),
149 ),
150 line("// DO NOT EDIT."),
151 Line(format!("// source: {}", requested_file.get_filename()?.to_str()?)),
152 Line(format!("// capnp binary version: {}", capnp_version)),
153 Line(format!("// capnpc crate version: {}", env!("CARGO_PKG_VERSION"))),
154 BlankLine,
155 generate_node(&ctx, id, &root_name)?,
156 ]);
157
158 let text = stringify(&lines);
159
160 let previous_text = ::std::fs::read(&filepath);
161 if previous_text.is_ok() && previous_text.unwrap() == text.as_bytes() {
162 continue;
167 }
168
169 match ::std::fs::File::create(&filepath) {
172 Ok(mut writer) => {
173 writer.write_all(text.as_bytes()).map_err(convert_io_err)?;
174 }
175 Err(e) => {
176 let _ = writeln!(
177 &mut ::std::io::stderr(),
178 "could not open file {filepath:?} for writing: {e}"
179 );
180 return Err(convert_io_err(e));
181 }
182 }
183 }
184
185 if let Some(raw_code_generator_request) = &self.raw_code_generator_request_path {
186 let raw_code_generator_request_file =
187 ::std::fs::File::create(raw_code_generator_request).map_err(convert_io_err)?;
188 serialize::write_message_segments(
189 raw_code_generator_request_file,
190 &message.into_segments(),
191 )?;
192 }
193
194 Ok(())
195 }
196}
197
198pub struct GeneratorContext<'a> {
199 pub request: schema_capnp::code_generator_request::Reader<'a>,
200 pub node_map: collections::hash_map::HashMap<u64, schema_capnp::node::Reader<'a>>,
201 pub scope_map: collections::hash_map::HashMap<u64, Vec<String>>,
202
203 pub node_parents: collections::hash_map::HashMap<u64, u64>,
207
208 pub capnp_root: String,
210}
211
212impl<'a> GeneratorContext<'a> {
213 pub fn new(
214 message: &'a capnp::message::Reader<capnp::serialize::OwnedSegments>,
215 ) -> ::capnp::Result<GeneratorContext<'a>> {
216 GeneratorContext::new_from_code_generation_command(&Default::default(), message)
217 }
218
219 fn new_from_code_generation_command(
220 code_generation_command: &CodeGenerationCommand,
221 message: &'a capnp::message::Reader<capnp::serialize::OwnedSegments>,
222 ) -> ::capnp::Result<GeneratorContext<'a>> {
223 let mut default_parent_module_scope = vec!["crate".to_string()];
224 default_parent_module_scope
225 .extend_from_slice(&code_generation_command.default_parent_module[..]);
226
227 let mut ctx = GeneratorContext {
228 request: message.get_root()?,
229 node_map: collections::hash_map::HashMap::<u64, schema_capnp::node::Reader<'a>>::new(),
230 scope_map: collections::hash_map::HashMap::<u64, Vec<String>>::new(),
231 node_parents: collections::hash_map::HashMap::new(),
232 capnp_root: code_generation_command.capnp_root.clone(),
233 };
234
235 let crates_provide = &code_generation_command.crates_provide_map;
236
237 for node in ctx.request.get_nodes()? {
238 ctx.node_map.insert(node.get_id(), node);
239 ctx.node_parents.insert(node.get_id(), node.get_scope_id());
240 }
241
242 for node in ctx.request.get_nodes()? {
244 if let Ok(schema_capnp::node::Interface(interface_reader)) = node.which() {
245 for method in interface_reader.get_methods()? {
246 let param_struct_type = method.get_param_struct_type();
247 if ctx.node_parents.get(¶m_struct_type) == Some(&0) {
248 ctx.node_parents.insert(param_struct_type, node.get_id());
249 }
250 let result_struct_type = method.get_result_struct_type();
251 if ctx.node_parents.get(&result_struct_type) == Some(&0) {
252 ctx.node_parents.insert(result_struct_type, node.get_id());
253 }
254 }
255 }
256 }
257
258 for requested_file in ctx.request.get_requested_files()? {
259 let id = requested_file.get_id();
260
261 for import in requested_file.get_imports()? {
262 let importpath = ::std::path::Path::new(import.get_name()?.to_str()?);
263 let root_name: String = format!(
264 "{}_capnp",
265 path_to_stem_string(importpath)?.replace('-', "_")
266 );
267 let parent_module_scope = if let Some(krate) = crates_provide.get(&import.get_id())
268 {
269 vec![format!("::{krate}")]
270 } else {
271 default_parent_module_scope.clone()
272 };
273
274 ctx.populate_scope_map(
275 parent_module_scope,
276 root_name,
277 NameKind::Verbatim,
278 import.get_id(),
279 )?;
280 }
281
282 let root_name = path_to_stem_string(requested_file.get_filename()?.to_str()?)?;
283 let root_mod = format!("{}_capnp", root_name.replace('-', "_"));
284 ctx.populate_scope_map(
285 default_parent_module_scope.clone(),
286 root_mod,
287 NameKind::Verbatim,
288 id,
289 )?;
290 }
291 Ok(ctx)
292 }
293
294 fn get_last_name(&self, id: u64) -> ::capnp::Result<&str> {
295 match self.scope_map.get(&id) {
296 None => Err(Error::failed(format!("node not found: {id}"))),
297 Some(v) => match v.last() {
298 None => Err(Error::failed(format!("node has no scope: {id}"))),
299 Some(n) => Ok(n),
300 },
301 }
302 }
303
304 fn populate_scope_map(
305 &mut self,
306 mut ancestor_scope_names: Vec<String>,
307 mut current_node_name: String,
308 current_name_kind: NameKind,
309 node_id: u64,
310 ) -> ::capnp::Result<()> {
311 let Some(&node_reader) = self.node_map.get(&node_id) else {
313 return Ok(());
314 };
315
316 for annotation in node_reader.get_annotations()? {
317 if annotation.get_id() == NAME_ANNOTATION_ID {
318 current_node_name = name_annotation_value(annotation)?.to_string();
319 } else if annotation.get_id() == PARENT_MODULE_ANNOTATION_ID {
320 let head = ancestor_scope_names[0].clone();
321 ancestor_scope_names.clear();
322 ancestor_scope_names.push(head);
323 ancestor_scope_names.append(&mut get_parent_module(annotation)?);
324 }
325 }
326
327 let mut scope_names = ancestor_scope_names;
328 scope_names.push(capnp_name_to_rust_name(
329 ¤t_node_name,
330 current_name_kind,
331 ));
332
333 self.scope_map.insert(node_id, scope_names.clone());
334
335 let nested_nodes = node_reader.get_nested_nodes()?;
336 for nested_node in nested_nodes {
337 let nested_node_id = nested_node.get_id();
338 match self.node_map.get(&nested_node_id) {
339 None => {}
340 Some(node_reader) => match node_reader.which() {
341 Ok(schema_capnp::node::Enum(_enum_reader)) => {
342 self.populate_scope_map(
343 scope_names.clone(),
344 nested_node.get_name()?.to_string()?,
345 NameKind::Verbatim,
346 nested_node_id,
347 )?;
348 }
349 _ => {
350 self.populate_scope_map(
351 scope_names.clone(),
352 nested_node.get_name()?.to_string()?,
353 NameKind::Module,
354 nested_node_id,
355 )?;
356 }
357 },
358 }
359 }
360
361 if let Ok(schema_capnp::node::Struct(struct_reader)) = node_reader.which() {
362 let fields = struct_reader.get_fields()?;
363 for field in fields {
364 if let Ok(schema_capnp::field::Group(group)) = field.which() {
365 self.populate_scope_map(
366 scope_names.clone(),
367 get_field_name(field)?.to_string(),
368 NameKind::Module,
369 group.get_type_id(),
370 )?;
371 }
372 }
373 }
374
375 Ok(())
376 }
377
378 pub fn get_qualified_module(&self, type_id: u64) -> String {
379 self.scope_map[&type_id].join("::")
380 }
381}
382
383macro_rules! fmt(
385 ($ctx:ident, $($arg:tt)*) => ( format!($($arg)*, capnp=$ctx.capnp_root) )
386);
387
388pub(crate) use fmt;
389
390fn path_to_stem_string<P: AsRef<::std::path::Path>>(path: P) -> ::capnp::Result<String> {
391 if let Some(stem) = path.as_ref().file_stem() {
392 stem.to_owned()
393 .into_string()
394 .map_err(|os_string| Error::failed(format!("bad filename: {os_string:?}")))
395 } else {
396 Err(Error::failed(format!(
397 "file has no stem: {:?}",
398 path.as_ref()
399 )))
400 }
401}
402
403fn camel_to_snake_case(s: &str) -> String {
404 let mut result_chars: Vec<char> = Vec::new();
405 let mut first_char = true;
406 for c in s.chars() {
407 if c.is_uppercase() && !first_char {
408 result_chars.push('_');
409 }
410 result_chars.push(c.to_ascii_lowercase());
411 first_char = false;
412 }
413 result_chars.into_iter().collect()
414}
415
416fn capitalize_first_letter(s: &str) -> String {
417 let mut result_chars: Vec<char> = Vec::new();
418 for c in s.chars() {
419 result_chars.push(c)
420 }
421 result_chars[0] = result_chars[0].to_ascii_uppercase();
422 result_chars.into_iter().collect()
423}
424
425fn format_u64(value: u64) -> String {
430 let hex = format!("{value:#x}");
431 let mut separated = hex[0..2].to_string();
432 let mut place = hex.len() - 2;
433 let mut later_loop = false;
434
435 for ch in hex[2..].chars() {
436 if later_loop && place % 4 == 0 {
437 separated.push('_');
438 }
439
440 separated.push(ch);
441 later_loop = true;
442 place -= 1;
443 }
444
445 separated
446}
447
448#[test]
449fn test_camel_to_snake_case() {
450 assert_eq!(camel_to_snake_case("fooBar"), "foo_bar".to_string());
451 assert_eq!(camel_to_snake_case("FooBar"), "foo_bar".to_string());
452 assert_eq!(camel_to_snake_case("fooBarBaz"), "foo_bar_baz".to_string());
453 assert_eq!(camel_to_snake_case("FooBarBaz"), "foo_bar_baz".to_string());
454 assert_eq!(camel_to_snake_case("helloWorld"), "hello_world".to_string());
455 assert_eq!(camel_to_snake_case("HelloWorld"), "hello_world".to_string());
456 assert_eq!(camel_to_snake_case("uint32Id"), "uint32_id".to_string());
457
458 assert_eq!(camel_to_snake_case("fooBar_"), "foo_bar_".to_string());
459}
460
461#[derive(PartialEq, Clone)]
462pub enum FormattedText {
463 Indent(Box<FormattedText>),
464 Branch(Vec<FormattedText>),
465 Line(String),
466 BlankLine,
467}
468
469impl From<Vec<FormattedText>> for FormattedText {
470 fn from(value: Vec<FormattedText>) -> Self {
471 Branch(value)
472 }
473}
474
475pub fn indent(inner: impl Into<FormattedText>) -> FormattedText {
476 Indent(Box::new(inner.into()))
477}
478
479pub fn line(inner: impl ToString) -> FormattedText {
480 Line(inner.to_string())
481}
482
483fn to_lines(ft: &FormattedText, indent: usize) -> Vec<String> {
484 match ft {
485 Indent(ft) => to_lines(ft, indent + 1),
486 Branch(fts) => fts.iter().flat_map(|ft| to_lines(ft, indent)).collect(),
487 Line(s) => {
488 let mut s1: String = " ".repeat(indent * 4);
489 s1.push_str(s);
490 vec![s1.to_string()]
491 }
492 BlankLine => vec!["".to_string()],
493 }
494}
495
496fn stringify(ft: &FormattedText) -> String {
497 let mut result = to_lines(ft, 0).join("\n");
498 result.push('\n');
499 result
500}
501
502const RUST_KEYWORDS: &[&str] = &[
503 "abstract", "alignof", "as", "be", "become", "box", "break", "const", "continue", "crate",
504 "do", "else", "enum", "extern", "false", "final", "fn", "for", "if", "impl", "in", "let",
505 "loop", "macro", "match", "mod", "move", "mut", "offsetof", "once", "override", "priv", "proc",
506 "pub", "pure", "ref", "return", "self", "sizeof", "static", "struct", "super", "trait", "true",
507 "type", "typeof", "unsafe", "unsized", "use", "virtual", "where", "while", "yield",
508];
509
510fn module_name(camel_case: &str) -> String {
511 let mut name = camel_to_snake_case(camel_case);
512 if RUST_KEYWORDS.contains(&&*name) {
513 name.push('_');
514 }
515 name
516}
517
518const NAME_ANNOTATION_ID: u64 = 0xc2fe4c6d100166d0;
520const PARENT_MODULE_ANNOTATION_ID: u64 = 0xabee386cd1450364;
521const OPTION_ANNOTATION_ID: u64 = 0xabfef22c4ee1964e;
522
523const STREAM_RESULT_ID: u64 = 0x995f9a3377c0b16e;
525
526fn name_annotation_value(annotation: schema_capnp::annotation::Reader<'_>) -> capnp::Result<&str> {
527 if let schema_capnp::value::Text(t) = annotation.get_value()?.which()? {
528 let name = t?.to_str()?;
529 for c in name.chars() {
530 if !(c == '_' || c.is_alphanumeric()) {
531 return Err(capnp::Error::failed(
532 "rust.name annotation value must only contain alphanumeric characters and '_'"
533 .to_string(),
534 ));
535 }
536 }
537 Ok(name)
538 } else {
539 Err(capnp::Error::failed(
540 "expected rust.name annotation value to be of type Text".to_string(),
541 ))
542 }
543}
544
545fn get_field_name(field: schema_capnp::field::Reader<'_>) -> capnp::Result<&str> {
546 for annotation in field.get_annotations()? {
547 if annotation.get_id() == NAME_ANNOTATION_ID {
548 return name_annotation_value(annotation);
549 }
550 }
551 Ok(field.get_name()?.to_str()?)
552}
553
554fn get_enumerant_name(enumerant: schema_capnp::enumerant::Reader<'_>) -> capnp::Result<&str> {
555 for annotation in enumerant.get_annotations()? {
556 if annotation.get_id() == NAME_ANNOTATION_ID {
557 return name_annotation_value(annotation);
558 }
559 }
560 Ok(enumerant.get_name()?.to_str()?)
561}
562
563fn get_parent_module(annotation: schema_capnp::annotation::Reader) -> capnp::Result<Vec<String>> {
564 if let schema_capnp::value::Text(t) = annotation.get_value()?.which()? {
565 let module = t?.to_str()?;
566 Ok(module.split("::").map(|x| x.to_string()).collect())
567 } else {
568 Err(capnp::Error::failed(
569 "expected rust.parentModule annotation value to be of type Text".to_string(),
570 ))
571 }
572}
573#[derive(Clone, Copy)]
574enum NameKind {
575 Module,
577
578 Verbatim,
580}
581
582fn capnp_name_to_rust_name(capnp_name: &str, name_kind: NameKind) -> String {
583 match name_kind {
584 NameKind::Module => module_name(capnp_name),
585 NameKind::Verbatim => capnp_name.to_string(),
586 }
587}
588
589fn is_option_field(field: schema_capnp::field::Reader) -> capnp::Result<bool> {
590 use capnp::schema_capnp::*;
591
592 let enabled = field
593 .get_annotations()?
594 .iter()
595 .any(|a| a.get_id() == OPTION_ANNOTATION_ID);
596
597 if enabled {
598 let supported = match field.which()? {
599 field::Which::Group(_) => false,
600 field::Which::Slot(field) => {
601 let ty = field.get_type()?;
602 ty.is_pointer()? && !matches!(ty.which()?, type_::Interface(_))
603 }
604 };
605 if !supported {
606 return Err(capnp::Error::failed(
607 "$Rust.option annotation only supported on pointer fields (support for optional interfaces isn't implemented yet)".to_string(),
608 ));
609 }
610 }
611
612 Ok(enabled)
613}
614
615fn prim_default(value: &schema_capnp::value::Reader) -> ::capnp::Result<Option<String>> {
616 use capnp::schema_capnp::value;
617 match value.which()? {
618 value::Bool(false)
619 | value::Int8(0)
620 | value::Int16(0)
621 | value::Int32(0)
622 | value::Int64(0)
623 | value::Uint8(0)
624 | value::Uint16(0)
625 | value::Uint32(0)
626 | value::Uint64(0) => Ok(None),
627
628 value::Bool(true) => Ok(Some("true".to_string())),
629 value::Int8(i) => Ok(Some(i.to_string())),
630 value::Int16(i) => Ok(Some(i.to_string())),
631 value::Int32(i) => Ok(Some(i.to_string())),
632 value::Int64(i) => Ok(Some(i.to_string())),
633 value::Uint8(i) => Ok(Some(i.to_string())),
634 value::Uint16(i) => Ok(Some(i.to_string())),
635 value::Uint32(i) => Ok(Some(i.to_string())),
636 value::Uint64(i) => Ok(Some(i.to_string())),
637 value::Float32(f) => match f.classify() {
638 ::std::num::FpCategory::Zero => Ok(None),
639 _ => Ok(Some(format!("{}u32", f.to_bits()))),
640 },
641 value::Float64(f) => match f.classify() {
642 ::std::num::FpCategory::Zero => Ok(None),
643 _ => Ok(Some(format!("{}u64", f.to_bits()))),
644 },
645 _ => Err(Error::failed(
646 "Non-primitive value found where primitive was expected.".to_string(),
647 )),
648 }
649}
650
651fn prim_default_value(value: &schema_capnp::value::Reader) -> ::capnp::Result<String> {
655 use capnp::schema_capnp::value;
656 Ok(match value.which()? {
657 value::Bool(b) => b.to_string(),
658 value::Int8(i) => i.to_string(),
659 value::Int16(i) => i.to_string(),
660 value::Int32(i) => i.to_string(),
661 value::Int64(i) => i.to_string(),
662 value::Uint8(i) => i.to_string(),
663 value::Uint16(i) => i.to_string(),
664 value::Uint32(i) => i.to_string(),
665 value::Uint64(i) => i.to_string(),
666 value::Float32(f) => format!("f32::from_bits({}u32)", f.to_bits()),
667 value::Float64(f) => format!("f64::from_bits({}u64)", f.to_bits()),
668 _ => {
669 return Err(Error::failed(
670 "expected a primitive default value".to_string(),
671 ))
672 }
673 })
674}
675
676fn is_scalar_data_field(field: &schema_capnp::field::Reader) -> ::capnp::Result<bool> {
681 use capnp::schema_capnp::*;
682 let field::Slot(s) = field.which()? else {
683 return Ok(false);
684 };
685 Ok(matches!(
686 s.get_type()?.which()?,
687 type_::Bool(())
688 | type_::Int8(())
689 | type_::Int16(())
690 | type_::Int32(())
691 | type_::Int64(())
692 | type_::Uint8(())
693 | type_::Uint16(())
694 | type_::Uint32(())
695 | type_::Uint64(())
696 | type_::Float32(())
697 | type_::Float64(())
698 ))
699}
700
701fn unmapped_panic(idx: usize, field_name: &str) -> String {
705 format!(
706 "if self.offsets[{idx}] == 0xffff_ffffu32 {{ panic!(\"field '{field_name}' is not mapped at this use site\"); }}"
707 )
708}
709
710fn get_params(ctx: &GeneratorContext, mut node_id: u64) -> ::capnp::Result<Vec<String>> {
712 let mut result = Vec::new();
713
714 while node_id != 0 {
715 let node = ctx.node_map[&node_id];
716 let parameters = node.get_parameters()?;
717
718 for parameter in parameters.into_iter().rev() {
719 result.push(parameter.get_name()?.to_str()?.into());
720 }
721
722 node_id = node.get_scope_id();
723 }
724
725 result.reverse();
726 Ok(result)
727}
728
729pub fn getter_text(
733 ctx: &GeneratorContext,
734 field: &schema_capnp::field::Reader,
735 is_reader: bool,
736 is_fn: bool,
737) -> ::capnp::Result<(String, FormattedText, Option<FormattedText>)> {
738 getter_text_at(ctx, field, is_reader, is_fn, None)
739}
740
741fn getter_text_at(
745 ctx: &GeneratorContext,
746 field: &schema_capnp::field::Reader,
747 is_reader: bool,
748 is_fn: bool,
749 offset_override: Option<&str>,
750) -> ::capnp::Result<(String, FormattedText, Option<FormattedText>)> {
751 use capnp::schema_capnp::*;
752
753 match field.which()? {
754 field::Group(group) => {
755 let params = get_params(ctx, group.get_type_id())?;
756 let params_string = if params.is_empty() {
757 "".to_string()
758 } else {
759 format!(",{}", params.join(","))
760 };
761
762 let the_mod = ctx.get_qualified_module(group.get_type_id());
763
764 let mut result_type = if is_reader {
765 format!("{the_mod}::Reader<'a{params_string}>")
766 } else {
767 format!("{the_mod}::Builder<'a{params_string}>")
768 };
769
770 if is_fn {
771 result_type = format!("-> {result_type}");
772 }
773
774 let getter_code = if is_reader {
775 line("self.reader.into()")
776 } else {
777 line("self.builder.into()")
778 };
779
780 Ok((result_type, getter_code, None))
781 }
782 field::Slot(reg_field) => {
783 let mut default_decl = None;
784 let offset: String = match offset_override {
785 Some(e) => e.to_string(),
786 None => (reg_field.get_offset() as usize).to_string(),
787 };
788 let module_string = if is_reader { "Reader" } else { "Builder" };
789 let module = if is_reader {
790 Leaf::Reader("'a")
791 } else {
792 Leaf::Builder("'a")
793 };
794 let member = camel_to_snake_case(module_string);
795
796 fn primitive_case<T: PartialEq + ::std::fmt::Display>(
797 typ: &str,
798 member: &str,
799 offset: &str,
800 default: T,
801 zero: T,
802 ) -> String {
803 if default == zero {
804 format!("self.{member}.get_data_field::<{typ}>({offset})")
805 } else {
806 format!("self.{member}.get_data_field_mask::<{typ}>({offset}, {default})")
807 }
808 }
809
810 let raw_type = reg_field.get_type()?;
811 let inner_type = raw_type.type_string(ctx, module)?;
812 let default_value = reg_field.get_default_value()?;
813 let default = default_value.which()?;
814 let default_name = format!(
815 "DEFAULT_{}",
816 camel_to_snake_case(get_field_name(*field)?).to_ascii_uppercase()
817 );
818 let should_get_option = is_option_field(*field)?;
819
820 let typ = if should_get_option {
821 format!("Option<{inner_type}>")
822 } else {
823 inner_type
824 };
825
826 let (is_fallible, mut result_type) = match raw_type.which()? {
827 type_::Enum(_) => (
828 true,
829 fmt!(ctx, "::core::result::Result<{typ},{capnp}::NotInSchema>"),
830 ),
831 type_::AnyPointer(_) if !raw_type.is_parameter()? => (false, typ.clone()),
832 type_::Interface(_) => (
833 true,
834 fmt!(
835 ctx,
836 "{capnp}::Result<{}>",
837 raw_type.type_string(ctx, Leaf::Client)?
838 ),
839 ),
840 _ if raw_type.is_prim()? => (false, typ.clone()),
841 _ => (true, fmt!(ctx, "{capnp}::Result<{typ}>")),
842 };
843
844 if is_fn {
845 result_type = if result_type == "()" {
846 "".to_string()
847 } else {
848 format!("-> {result_type}")
849 }
850 }
851
852 let getter_fragment = match (raw_type.which()?, default) {
853 (type_::Void(()), value::Void(())) => {
854 if is_fn {
855 "".to_string()
856 } else {
857 "()".to_string()
858 }
859 }
860 (type_::Bool(()), value::Bool(b)) => {
861 if b {
862 format!("self.{member}.get_bool_field_mask({offset}, true)")
863 } else {
864 format!("self.{member}.get_bool_field({offset})")
865 }
866 }
867 (type_::Int8(()), value::Int8(i)) => primitive_case(&typ, &member, &offset, i, 0),
868 (type_::Int16(()), value::Int16(i)) => primitive_case(&typ, &member, &offset, i, 0),
869 (type_::Int32(()), value::Int32(i)) => primitive_case(&typ, &member, &offset, i, 0),
870 (type_::Int64(()), value::Int64(i)) => primitive_case(&typ, &member, &offset, i, 0),
871 (type_::Uint8(()), value::Uint8(i)) => primitive_case(&typ, &member, &offset, i, 0),
872 (type_::Uint16(()), value::Uint16(i)) => {
873 primitive_case(&typ, &member, &offset, i, 0)
874 }
875 (type_::Uint32(()), value::Uint32(i)) => {
876 primitive_case(&typ, &member, &offset, i, 0)
877 }
878 (type_::Uint64(()), value::Uint64(i)) => {
879 primitive_case(&typ, &member, &offset, i, 0)
880 }
881 (type_::Float32(()), value::Float32(f)) => {
882 primitive_case(&typ, &member, &offset, f.to_bits(), 0)
883 }
884 (type_::Float64(()), value::Float64(f)) => {
885 primitive_case(&typ, &member, &offset, f.to_bits(), 0)
886 }
887 (type_::Enum(_), value::Enum(d)) => {
888 if d == 0 {
889 format!("::core::convert::TryFrom::try_from(self.{member}.get_data_field::<u16>({offset}))")
890 } else {
891 format!(
892 "::core::convert::TryFrom::try_from(self.{member}.get_data_field_mask::<u16>({offset}, {d}))")
893 }
894 }
895
896 (type_::Text(()), value::Text(_))
897 | (type_::Data(()), value::Data(_))
898 | (type_::List(_), value::List(_))
899 | (type_::Struct(_), value::Struct(_)) => {
900 let default = if reg_field.get_had_explicit_default() {
901 default_decl = Some(crate::pointer_constants::word_array_declaration(
902 ctx,
903 &default_name,
904 ::capnp::raw::get_struct_pointer_section(default_value).get(0),
905 crate::pointer_constants::WordArrayDeclarationOptions {
906 pub_crate: true,
907 },
908 )?);
909 format!("::core::option::Option::Some(&_private::{default_name}[..])")
910 } else {
911 "::core::option::Option::None".to_string()
912 };
913
914 if is_reader {
915 fmt!(ctx,
916 "{capnp}::traits::FromPointerReader::get_from_pointer(&self.{member}.get_pointer_field({offset}), {default})")
917 } else {
918 fmt!(ctx,"{capnp}::traits::FromPointerBuilder::get_from_pointer(self.{member}.get_pointer_field({offset}), {default})")
919 }
920 }
921
922 (type_::Interface(_), value::Interface(_)) => {
923 fmt!(ctx,"match self.{member}.get_pointer_field({offset}).get_capability() {{ ::core::result::Result::Ok(c) => ::core::result::Result::Ok({capnp}::capability::FromClientHook::new(c)), ::core::result::Result::Err(e) => ::core::result::Result::Err(e)}}")
924 }
925 (type_::AnyPointer(_), value::AnyPointer(_)) => {
926 if !raw_type.is_parameter()? {
927 fmt!(ctx,"{capnp}::any_pointer::{module_string}::new(self.{member}.get_pointer_field({offset}))")
928 } else if is_reader {
929 fmt!(ctx,"{capnp}::traits::FromPointerReader::get_from_pointer(&self.{member}.get_pointer_field({offset}), ::core::option::Option::None)")
930 } else {
931 fmt!(ctx,"{capnp}::traits::FromPointerBuilder::get_from_pointer(self.{member}.get_pointer_field({offset}), ::core::option::Option::None)")
932 }
933 }
934 _ => return Err(Error::failed("default value was of wrong type".to_string())),
935 };
936
937 let getter_code = if should_get_option {
938 Branch(vec![
939 Line(format!(
940 "if self.{member}.is_pointer_field_null({offset}) {{"
941 )),
942 indent(Line(
943 if is_fallible {
944 "core::result::Result::Ok(core::option::Option::None)"
945 } else {
946 "::core::option::Option::None"
947 }
948 .to_string(),
949 )),
950 Line("} else {".to_string()),
951 indent(Line(if is_fallible {
952 format!("{getter_fragment}.map(::core::option::Option::Some)")
953 } else {
954 format!("::core::option::Option::Some({getter_fragment})")
955 })),
956 Line("}".to_string()),
957 ])
958 } else {
959 Line(getter_fragment)
960 };
961
962 Ok((result_type, getter_code, default_decl))
963 }
964 }
965}
966
967fn zero_fields_of_group(
968 ctx: &GeneratorContext,
969 node_id: u64,
970 clear: &mut bool,
971) -> ::capnp::Result<FormattedText> {
972 use capnp::schema_capnp::{field, node, type_};
973 match ctx.node_map[&node_id].which()? {
974 node::Struct(st) => {
975 let mut result = Vec::new();
976 if st.get_discriminant_count() != 0 {
977 result.push(Line(format!(
978 "self.builder.set_data_field::<u16>({}, 0);",
979 st.get_discriminant_offset()
980 )));
981 }
982 let fields = st.get_fields()?;
983 for field in fields {
984 match field.which()? {
985 field::Group(group) => {
986 result.push(zero_fields_of_group(ctx, group.get_type_id(), clear)?);
987 }
988 field::Slot(slot) => {
989 let typ = slot.get_type()?.which()?;
990 match typ {
991 type_::Void(()) => {}
992 type_::Bool(()) => {
993 let line = Line(format!(
994 "self.builder.set_bool_field({}, false);",
995 slot.get_offset()
996 ));
997 if !result.contains(&line) {
999 result.push(line)
1000 }
1001 }
1002 type_::Int8(())
1003 | type_::Int16(())
1004 | type_::Int32(())
1005 | type_::Int64(())
1006 | type_::Uint8(())
1007 | type_::Uint16(())
1008 | type_::Uint32(())
1009 | type_::Uint64(())
1010 | type_::Float32(())
1011 | type_::Float64(()) => {
1012 let line = Line(format!(
1013 "self.builder.set_data_field::<{0}>({1}, 0{0});",
1014 slot.get_type()?.type_string(ctx, Leaf::Builder("'a"))?,
1015 slot.get_offset()
1016 ));
1017 if !result.contains(&line) {
1019 result.push(line)
1020 }
1021 }
1022 type_::Enum(_) => {
1023 let line = Line(format!(
1024 "self.builder.set_data_field::<u16>({}, 0u16);",
1025 slot.get_offset()
1026 ));
1027 if !result.contains(&line) {
1029 result.push(line)
1030 }
1031 }
1032 type_::Struct(_)
1033 | type_::List(_)
1034 | type_::Text(())
1035 | type_::Data(())
1036 | type_::AnyPointer(_)
1037 | type_::Interface(_) => {
1038 let line = Line(format!(
1040 "self.builder.reborrow().get_pointer_field({}).clear();",
1041 slot.get_offset()
1042 ));
1043 *clear = true;
1044 if !result.contains(&line) {
1046 result.push(line)
1047 }
1048 }
1049 }
1050 }
1051 }
1052 }
1053 Ok(Branch(result))
1054 }
1055 _ => Err(Error::failed(
1056 "zero_fields_of_group() expected a struct".to_string(),
1057 )),
1058 }
1059}
1060
1061struct SetterMethod {
1066 name: String,
1067 receiver: String,
1068 params: String,
1069 ret: String,
1070 body: FormattedText,
1071 delegate_args: String,
1072}
1073
1074impl SetterMethod {
1075 fn signature(&self, bind_mut: bool) -> String {
1079 let receiver = if bind_mut {
1080 self.receiver.clone()
1081 } else {
1082 self.receiver.trim_start_matches("mut ").to_string()
1083 };
1084 let args = if self.params.is_empty() {
1085 receiver
1086 } else {
1087 format!("{receiver}, {}", self.params)
1088 };
1089 let ret = if self.ret.is_empty() {
1090 String::new()
1091 } else {
1092 format!(" {}", self.ret)
1093 };
1094 format!("{}({args}){ret}", self.name)
1095 }
1096}
1097
1098fn setter_methods(
1099 ctx: &GeneratorContext,
1100 discriminant_offset: u32,
1101 styled_name: &str,
1102 field: &schema_capnp::field::Reader,
1103) -> ::capnp::Result<Vec<SetterMethod>> {
1104 setter_methods_at(
1105 ctx,
1106 &(discriminant_offset as usize).to_string(),
1107 styled_name,
1108 field,
1109 None,
1110 )
1111}
1112
1113fn setter_methods_at(
1117 ctx: &GeneratorContext,
1118 disc_offset: &str,
1119 styled_name: &str,
1120 field: &schema_capnp::field::Reader,
1121 offset_override: Option<&str>,
1122) -> ::capnp::Result<Vec<SetterMethod>> {
1123 use capnp::schema_capnp::*;
1124
1125 let mut setter_interior = Vec::new();
1126 let mut setter_param = "value".to_string();
1127 let mut initter_interior = Vec::new();
1128 let mut initter_mut = false;
1129 let mut initn_interior = Vec::new();
1130 let mut initter_params = Vec::new();
1131
1132 let discriminant_value = field.get_discriminant_value();
1133 if discriminant_value != field::NO_DISCRIMINANT {
1134 setter_interior.push(Line(format!(
1135 "self.builder.set_data_field::<u16>({}, {});",
1136 disc_offset, discriminant_value as usize
1137 )));
1138 let init_discrim = Line(format!(
1139 "self.builder.set_data_field::<u16>({}, {});",
1140 disc_offset, discriminant_value as usize
1141 ));
1142 initter_interior.push(init_discrim.clone());
1143 initn_interior.push(init_discrim);
1144 }
1145
1146 let mut return_result = false;
1147 let mut methods: Vec<SetterMethod> = Vec::new();
1148
1149 let (maybe_reader_type, maybe_builder_type): (Option<String>, Option<String>) = match field
1150 .which()?
1151 {
1152 field::Group(group) => {
1153 let params = get_params(ctx, group.get_type_id())?;
1154 let params_string = if params.is_empty() {
1155 "".to_string()
1156 } else {
1157 format!(",{}", params.join(","))
1158 };
1159
1160 let the_mod = ctx.get_qualified_module(group.get_type_id());
1161
1162 initter_interior.push(zero_fields_of_group(
1163 ctx,
1164 group.get_type_id(),
1165 &mut initter_mut,
1166 )?);
1167
1168 initter_interior.push(line("self.builder.into()"));
1169
1170 (None, Some(format!("{the_mod}::Builder<'a{params_string}>")))
1171 }
1172 field::Slot(reg_field) => {
1173 let offset: String = match offset_override {
1174 Some(e) => e.to_string(),
1175 None => (reg_field.get_offset() as usize).to_string(),
1176 };
1177 let typ = reg_field.get_type()?;
1178 match typ.which().expect("unrecognized type") {
1179 type_::Void(()) => {
1180 setter_param = "_value".to_string();
1181 (Some("()".to_string()), None)
1182 }
1183 type_::Bool(()) => {
1184 match prim_default(®_field.get_default_value()?)? {
1185 None => {
1186 setter_interior.push(Line(format!(
1187 "self.builder.set_bool_field({offset}, value);"
1188 )));
1189 }
1190 Some(s) => {
1191 setter_interior.push(Line(format!(
1192 "self.builder.set_bool_field_mask({offset}, value, {s});"
1193 )));
1194 }
1195 }
1196 (Some("bool".to_string()), None)
1197 }
1198 _ if typ.is_prim()? => {
1199 let tstr = typ.type_string(ctx, Leaf::Reader("'a"))?;
1200 match prim_default(®_field.get_default_value()?)? {
1201 None => {
1202 setter_interior.push(Line(format!(
1203 "self.builder.set_data_field::<{tstr}>({offset}, value);"
1204 )));
1205 }
1206 Some(s) => {
1207 setter_interior.push(Line(format!(
1208 "self.builder.set_data_field_mask::<{tstr}>({offset}, value, {s});"
1209 )));
1210 }
1211 };
1212 (Some(tstr), None)
1213 }
1214 type_::Text(()) => {
1215 setter_interior.push(Line(fmt!(ctx,
1217 "{capnp}::traits::SetterInput::set_pointer_builder(self.builder.reborrow().get_pointer_field({offset}), value, false).unwrap()"
1218 )));
1219 initter_interior.push(Line(format!(
1220 "self.builder.get_pointer_field({offset}).init_text(size)"
1221 )));
1222 initter_params.push("size: u32");
1223 (
1224 Some(fmt!(
1225 ctx,
1226 "impl {capnp}::traits::SetterInput<{capnp}::text::Owned>"
1227 )),
1228 Some(fmt!(ctx, "{capnp}::text::Builder<'a>")),
1229 )
1230 }
1231 type_::Data(()) => {
1232 setter_interior.push(Line(format!(
1233 "self.builder.reborrow().get_pointer_field({offset}).set_data(value);"
1234 )));
1235 initter_interior.push(Line(format!(
1236 "self.builder.get_pointer_field({offset}).init_data(size)"
1237 )));
1238 initter_params.push("size: u32");
1239 (
1240 Some(fmt!(ctx, "{capnp}::data::Reader<'_>")),
1241 Some(fmt!(ctx, "{capnp}::data::Builder<'a>")),
1242 )
1243 }
1244 type_::List(ls) => {
1245 let et = ls.get_element_type()?;
1246 return_result = true;
1247 setter_interior.push(
1248 Line(fmt!(ctx,"{capnp}::traits::SetterInput::set_pointer_builder(self.builder.reborrow().get_pointer_field({offset}), value, false)")));
1249
1250 initter_params.push("size: u32");
1251 initter_interior.push(
1252 Line(fmt!(ctx,"{capnp}::traits::FromPointerBuilder::init_pointer(self.builder.get_pointer_field({offset}), size)")));
1253
1254 let mr = match et.which()? {
1255 type_::Void(())
1256 | type_::Bool(())
1257 | type_::Int8(())
1258 | type_::Int16(())
1259 | type_::Int32(())
1260 | type_::Int64(())
1261 | type_::Uint8(())
1262 | type_::Uint16(())
1263 | type_::Uint32(())
1264 | type_::Uint64(())
1265 | type_::Float32(())
1266 | type_::Float64(())
1267 | type_::Enum(_)
1268 | type_::Text(()) => {
1269 fmt!(
1271 ctx,
1272 "impl {capnp}::traits::SetterInput<{}>",
1273 reg_field.get_type()?.type_string(ctx, Leaf::Owned)?
1274 )
1275 }
1276 _ => reg_field.get_type()?.type_string(ctx, Leaf::Reader("'_"))?,
1277 };
1278
1279 (
1280 Some(mr),
1281 Some(
1282 reg_field
1283 .get_type()?
1284 .type_string(ctx, Leaf::Builder("'a"))?,
1285 ),
1286 )
1287 }
1288 type_::Enum(e) => {
1289 let id = e.get_type_id();
1290 let the_mod = ctx.get_qualified_module(id);
1291 if !reg_field.get_had_explicit_default() {
1292 setter_interior.push(Line(format!(
1293 "self.builder.set_data_field::<u16>({offset}, value as u16);"
1294 )));
1295 } else {
1296 match reg_field.get_default_value()?.which()? {
1297 schema_capnp::value::Enum(d) => {
1298 setter_interior.push(Line(format!(
1299 "self.builder.set_data_field_mask::<u16>({offset}, value as u16, {d});"
1300 )));
1301 }
1302 _ => return Err(Error::failed("enum default not an Enum".to_string())),
1303 }
1304 };
1305 (Some(the_mod), None)
1306 }
1307 type_::Struct(_) => {
1308 return_result = true;
1309 initter_interior.push(
1310 Line(fmt!(ctx,"{capnp}::traits::FromPointerBuilder::init_pointer(self.builder.get_pointer_field({offset}), 0)")));
1311 setter_interior.push(
1312 Line(fmt!(ctx,"{capnp}::traits::SetterInput::set_pointer_builder(self.builder.reborrow().get_pointer_field({offset}), value, false)")));
1313
1314 (
1315 Some(typ.type_string(ctx, Leaf::Reader("'_"))?),
1316 Some(typ.type_string(ctx, Leaf::Builder("'a"))?),
1317 )
1318 }
1319 type_::Interface(_) => {
1320 setter_interior.push(Line(format!(
1321 "self.builder.reborrow().get_pointer_field({offset}).set_capability(value.client.hook);"
1322 )));
1323 (Some(typ.type_string(ctx, Leaf::Client)?), None)
1324 }
1325 type_::AnyPointer(_) => {
1326 if typ.is_parameter()? {
1327 initter_interior.push(Line(fmt!(ctx,"{capnp}::any_pointer::Builder::new(self.builder.get_pointer_field({offset})).init_as()")));
1328 setter_interior.push(Line(fmt!(ctx,"{capnp}::traits::SetterInput::set_pointer_builder(self.builder.reborrow().get_pointer_field({offset}), value, false)")));
1329 return_result = true;
1330
1331 let builder_type = typ.type_string(ctx, Leaf::Builder("'a"))?;
1332
1333 methods.push(SetterMethod {
1334 name: format!("initn_{styled_name}"),
1335 receiver: "self".into(),
1336 params: "length: u32".into(),
1337 ret: format!("-> {builder_type}"),
1338 body: Branch(vec![
1339 Branch(initn_interior),
1340 Line(fmt!(ctx,"{capnp}::any_pointer::Builder::new(self.builder.get_pointer_field({offset})).initn_as(length)")),
1341 ]),
1342 delegate_args: "length".into(),
1343 });
1344
1345 (
1346 Some(fmt!(
1347 ctx,
1348 "impl {capnp}::traits::SetterInput<{}>",
1349 typ.type_string(ctx, Leaf::Owned)?
1350 )),
1351 Some(builder_type),
1352 )
1353 } else {
1354 initter_interior.push(Line(fmt!(ctx,"let mut result = {capnp}::any_pointer::Builder::new(self.builder.get_pointer_field({offset}));")));
1355 initter_interior.push(line("result.clear();"));
1356 initter_interior.push(line("result"));
1357 (None, Some(fmt!(ctx, "{capnp}::any_pointer::Builder<'a>")))
1358 }
1359 }
1360 _ => return Err(Error::failed("unrecognized type".to_string())),
1361 }
1362 }
1363 };
1364 if let Some(reader_type) = maybe_reader_type {
1365 let ret = if return_result {
1366 fmt!(ctx, "-> {capnp}::Result<()>")
1367 } else {
1368 String::new()
1369 };
1370 methods.push(SetterMethod {
1371 name: format!("set_{styled_name}"),
1372 receiver: "&mut self".into(),
1373 params: format!("{setter_param}: {reader_type}"),
1374 ret,
1375 body: Branch(setter_interior),
1376 delegate_args: setter_param.clone(),
1377 });
1378 }
1379 if let Some(builder_type) = maybe_builder_type {
1380 let arg_names: Vec<&str> = initter_params
1381 .iter()
1382 .map(|p| p.split(':').next().unwrap_or("").trim())
1383 .collect();
1384 methods.push(SetterMethod {
1385 name: format!("init_{styled_name}"),
1386 receiver: if initter_mut { "mut self" } else { "self" }.into(),
1387 params: initter_params.join(", "),
1388 ret: format!("-> {builder_type}"),
1389 body: Branch(initter_interior),
1390 delegate_args: arg_names.join(", "),
1391 });
1392 }
1393 Ok(methods)
1394}
1395
1396fn generate_setter(
1398 ctx: &GeneratorContext,
1399 discriminant_offset: u32,
1400 styled_name: &str,
1401 field: &schema_capnp::field::Reader,
1402) -> ::capnp::Result<FormattedText> {
1403 let mut result = Vec::new();
1404 for m in setter_methods(ctx, discriminant_offset, styled_name, field)? {
1405 result.push(line("#[inline]"));
1406 result.push(Line(format!("pub fn {} {{", m.signature(true))));
1407 result.push(indent(m.body));
1408 result.push(line("}"));
1409 }
1410 Ok(Branch(result))
1411}
1412
1413fn used_params_of_group(
1414 ctx: &GeneratorContext,
1415 group_id: u64,
1416 used_params: &mut HashSet<String>,
1417) -> capnp::Result<()> {
1418 let node = ctx.node_map[&group_id];
1419 match node.which()? {
1420 schema_capnp::node::Struct(st) => {
1421 for field in st.get_fields()? {
1422 match field.which()? {
1423 schema_capnp::field::Group(group) => {
1424 used_params_of_group(ctx, group.get_type_id(), used_params)?;
1425 }
1426 schema_capnp::field::Slot(slot) => {
1427 used_params_of_type(ctx, slot.get_type()?, used_params)?;
1428 }
1429 }
1430 }
1431 Ok(())
1432 }
1433 _ => Err(Error::failed("not a group".to_string())),
1434 }
1435}
1436
1437fn used_params_of_type(
1438 ctx: &GeneratorContext,
1439 ty: schema_capnp::type_::Reader,
1440 used_params: &mut HashSet<String>,
1441) -> capnp::Result<()> {
1442 use capnp::schema_capnp::type_;
1443 match ty.which()? {
1444 type_::List(ls) => {
1445 let et = ls.get_element_type()?;
1446 used_params_of_type(ctx, et, used_params)?;
1447 }
1448 type_::Enum(e) => {
1449 let node_id = e.get_type_id();
1450 let brand = e.get_brand()?;
1451 used_params_of_brand(ctx, node_id, brand, used_params)?;
1452 }
1453 type_::Struct(s) => {
1454 let node_id = s.get_type_id();
1455 let brand = s.get_brand()?;
1456 used_params_of_brand(ctx, node_id, brand, used_params)?;
1457 }
1458 type_::Interface(i) => {
1459 let node_id = i.get_type_id();
1460 let brand = i.get_brand()?;
1461 used_params_of_brand(ctx, node_id, brand, used_params)?;
1462 }
1463
1464 type_::AnyPointer(ap) => {
1465 if let type_::any_pointer::Parameter(def) = ap.which()? {
1466 let the_struct = &ctx.node_map[&def.get_scope_id()];
1467 let parameters = the_struct.get_parameters()?;
1468 let parameter = parameters.get(u32::from(def.get_parameter_index()));
1469 let parameter_name = parameter.get_name()?.to_str()?;
1470 used_params.insert(parameter_name.to_string());
1471 }
1472 }
1473 _ => (),
1474 }
1475 Ok(())
1476}
1477
1478fn used_params_of_brand(
1479 ctx: &GeneratorContext,
1480 node_id: u64,
1481 brand: schema_capnp::brand::Reader,
1482 used_params: &mut HashSet<String>,
1483) -> capnp::Result<()> {
1484 use schema_capnp::brand;
1485 let scopes = brand.get_scopes()?;
1486 let mut brand_scopes = HashMap::new();
1487 for scope in scopes {
1488 brand_scopes.insert(scope.get_scope_id(), scope);
1489 }
1490 let brand_scopes = brand_scopes; let mut current_node_id = node_id;
1492 while let Some(current_node) = ctx.node_map.get(¤t_node_id) {
1493 let params = current_node.get_parameters()?;
1494 match brand_scopes.get(¤t_node_id) {
1495 None => (),
1496 Some(scope) => match scope.which()? {
1497 brand::scope::Inherit(()) => {
1498 for param in params {
1499 used_params.insert(param.get_name()?.to_string()?);
1500 }
1501 }
1502 brand::scope::Bind(bindings_list_opt) => {
1503 let bindings_list = bindings_list_opt?;
1504 assert_eq!(bindings_list.len(), params.len());
1505 for binding in bindings_list {
1506 match binding.which()? {
1507 brand::binding::Unbound(()) => (),
1508 brand::binding::Type(t) => {
1509 used_params_of_type(ctx, t?, used_params)?;
1510 }
1511 }
1512 }
1513 }
1514 },
1515 }
1516 current_node_id = current_node.get_scope_id();
1517 }
1518 Ok(())
1519}
1520
1521fn generate_union(
1523 ctx: &GeneratorContext,
1524 discriminant_offset: u32,
1525 fields: &[schema_capnp::field::Reader],
1526 is_reader: bool,
1527 params: &TypeParameterTexts,
1528) -> ::capnp::Result<(
1529 FormattedText,
1530 FormattedText,
1531 FormattedText,
1532 Vec<FormattedText>,
1533)> {
1534 use capnp::schema_capnp::*;
1535
1536 fn new_ty_param(ty_params: &mut Vec<String>) -> String {
1537 let result = format!("A{}", ty_params.len());
1538 ty_params.push(result.clone());
1539 result
1540 }
1541
1542 let mut getter_interior = Vec::new();
1543 let mut interior = Vec::new();
1544 let mut enum_interior = Vec::new();
1545 let mut default_decls = Vec::new();
1546
1547 let mut ty_params = Vec::new();
1548 let mut ty_args = Vec::new();
1549
1550 let mut used_params: HashSet<String> = HashSet::new();
1551
1552 let doffset = discriminant_offset as usize;
1553
1554 for field in fields {
1555 let dvalue = field.get_discriminant_value() as usize;
1556
1557 let field_name = get_field_name(*field)?;
1558 let enumerant_name = capitalize_first_letter(field_name);
1559
1560 let (ty, get, maybe_default_decl) = getter_text(ctx, field, is_reader, false)?;
1561 if let Some(default_decl) = maybe_default_decl {
1562 default_decls.push(default_decl)
1563 }
1564
1565 getter_interior.push(Branch(vec![
1566 Line(format!("{dvalue} => {{")),
1567 indent(Line(format!(
1568 "::core::result::Result::Ok({}(",
1569 enumerant_name.clone()
1570 ))),
1571 indent(indent(get)),
1572 indent(line("))")),
1573 line("}"),
1574 ]));
1575
1576 let ty1 = match field.which() {
1577 Ok(field::Group(group)) => {
1578 used_params_of_group(ctx, group.get_type_id(), &mut used_params)?;
1579 ty_args.push(ty);
1580 new_ty_param(&mut ty_params)
1581 }
1582 Ok(field::Slot(reg_field)) => {
1583 let fty = reg_field.get_type()?;
1584 used_params_of_type(ctx, fty, &mut used_params)?;
1585 match fty.which() {
1586 Ok(
1587 type_::Text(())
1588 | type_::Data(())
1589 | type_::List(_)
1590 | type_::Struct(_)
1591 | type_::AnyPointer(_),
1592 ) => {
1593 ty_args.push(ty);
1594 new_ty_param(&mut ty_params)
1595 }
1596 Ok(type_::Interface(_)) => ty,
1597 _ => ty,
1598 }
1599 }
1600 _ => ty,
1601 };
1602
1603 enum_interior.push(Line(format!("{enumerant_name}({ty1}),")));
1604 }
1605
1606 let enum_name = format!(
1607 "Which{}",
1608 if !ty_params.is_empty() {
1609 format!("<{}>", ty_params.join(","))
1610 } else {
1611 "".to_string()
1612 }
1613 );
1614
1615 getter_interior.push(Line(fmt!(
1616 ctx,
1617 "x => ::core::result::Result::Err({capnp}::NotInSchema(x))"
1618 )));
1619
1620 interior.push(Branch(vec![
1621 Line(format!("pub enum {enum_name} {{")),
1622 indent(enum_interior),
1623 line("}"),
1624 ]));
1625
1626 let result = Branch(interior);
1627
1628 let field_name = if is_reader { "reader" } else { "builder" };
1629
1630 let concrete_type = format!(
1631 "Which{}{}",
1632 if is_reader { "Reader" } else { "Builder" },
1633 if !ty_params.is_empty() {
1634 format!(
1635 "<'a,{}>",
1636 params
1637 .expanded_list
1638 .iter()
1639 .filter(|s: &&String| used_params.contains(*s))
1640 .cloned()
1641 .collect::<Vec<String>>()
1642 .join(",")
1643 )
1644 } else {
1645 "".to_string()
1646 }
1647 );
1648
1649 let typedef = Line(format!(
1650 "pub type {concrete_type} = Which{};",
1651 if !ty_args.is_empty() {
1652 format!("<{}>", ty_args.join(","))
1653 } else {
1654 "".to_string()
1655 }
1656 ));
1657
1658 let getter_result = Branch(vec![
1659 line("#[inline]"),
1660 Line(fmt!(ctx,
1661 "pub fn which(self) -> ::core::result::Result<{concrete_type}, {capnp}::NotInSchema> {{"
1662 )),
1663 indent(vec![
1664 Line(format!(
1665 "match self.{field_name}.get_data_field::<u16>({doffset}) {{"
1666 )),
1667 indent(getter_interior),
1668 line("}"),
1669 ]),
1670 line("}"),
1671 ]);
1672
1673 Ok((result, getter_result, typedef, default_decls))
1676}
1677
1678fn generate_haser(
1679 discriminant_offset: u32,
1680 styled_name: &str,
1681 field: &schema_capnp::field::Reader,
1682 is_reader: bool,
1683) -> ::capnp::Result<FormattedText> {
1684 use capnp::schema_capnp::*;
1685
1686 let mut result = Vec::new();
1687 let mut interior = Vec::new();
1688 let member = if is_reader { "reader" } else { "builder" };
1689
1690 let discriminant_value = field.get_discriminant_value();
1691 if discriminant_value != field::NO_DISCRIMINANT {
1692 interior.push(Line(format!(
1693 "if self.{}.get_data_field::<u16>({}) != {} {{ return false; }}",
1694 member, discriminant_offset as usize, discriminant_value as usize
1695 )));
1696 }
1697 match field.which() {
1698 Err(_) | Ok(field::Group(_)) => {}
1699 Ok(field::Slot(reg_field)) => match reg_field.get_type()?.which()? {
1700 type_::Text(())
1701 | type_::Data(())
1702 | type_::List(_)
1703 | type_::Struct(_)
1704 | type_::Interface(_)
1705 | type_::AnyPointer(_) => {
1706 if is_reader {
1707 interior.push(Line(format!(
1708 "!self.{member}.get_pointer_field({}).is_null()",
1709 reg_field.get_offset()
1710 )));
1711 } else {
1712 interior.push(Line(format!(
1713 "!self.{member}.is_pointer_field_null({})",
1714 reg_field.get_offset()
1715 )));
1716 }
1717 result.push(line("#[inline]"));
1718 result.push(Line(format!("pub fn has_{styled_name}(&self) -> bool {{")));
1719 result.push(indent(interior));
1720 result.push(line("}"));
1721 }
1722 _ => {}
1723 },
1724 }
1725
1726 Ok(Branch(result))
1727}
1728
1729fn generate_pipeline_getter(
1730 ctx: &GeneratorContext,
1731 field: schema_capnp::field::Reader,
1732) -> ::capnp::Result<FormattedText> {
1733 use capnp::schema_capnp::{field, type_};
1734
1735 let name = get_field_name(field)?;
1736
1737 match field.which()? {
1738 field::Group(group) => {
1739 let params = get_params(ctx, group.get_type_id())?;
1740 let params_string = if params.is_empty() {
1741 "".to_string()
1742 } else {
1743 format!("<{}>", params.join(","))
1744 };
1745
1746 let the_mod = ctx.get_qualified_module(group.get_type_id());
1747 Ok(Branch(vec![
1748 Line(format!(
1749 "pub fn get_{}(&self) -> {}::Pipeline{} {{",
1750 camel_to_snake_case(name),
1751 the_mod,
1752 params_string
1753 )),
1754 indent(Line(fmt!(
1755 ctx,
1756 "{capnp}::capability::FromTypelessPipeline::new(self._typeless.noop())"
1757 ))),
1758 line("}"),
1759 ]))
1760 }
1761 field::Slot(reg_field) => {
1762 let typ = reg_field.get_type()?;
1763 match typ.which()? {
1764 type_::Struct(_) | type_::AnyPointer(_) => {
1765 Ok(Branch(vec![
1766 Line(format!("pub fn get_{}(&self) -> {} {{", camel_to_snake_case(name), typ.type_string(ctx, Leaf::Pipeline)?)),
1767 indent(Line(fmt!(ctx,"{capnp}::capability::FromTypelessPipeline::new(self._typeless.get_pointer_field({}))", reg_field.get_offset()))),
1768 line("}")
1769 ]))
1770 }
1771 type_::Interface(_) => {
1772 Ok(Branch(vec![
1773 Line(format!("pub fn get_{}(&self) -> {} {{", camel_to_snake_case(name), typ.type_string(ctx, Leaf::Client)?)),
1774 indent(Line(fmt!(ctx,"{capnp}::capability::FromClientHook::new(self._typeless.get_pointer_field({}).as_cap())", reg_field.get_offset()))),
1775 line("}")
1776 ]))
1777 }
1778 _ => {
1779 Ok(Branch(Vec::new()))
1780 }
1781 }
1782 }
1783 }
1784}
1785
1786fn generate_get_field_types(
1787 ctx: &GeneratorContext,
1788 node_reader: schema_capnp::node::Reader,
1789) -> ::capnp::Result<FormattedText> {
1790 use capnp::schema_capnp::field;
1791 let st = match node_reader.which()? {
1792 schema_capnp::node::Struct(st) => st,
1793 _ => return Err(Error::failed("not a struct".into())),
1794 };
1795 let mut branches = vec![];
1796 for (index, field) in st.get_fields()?.iter().enumerate() {
1797 match field.which()? {
1798 field::Slot(slot) => {
1799 let raw_type = slot.get_type()?;
1800 let typ = raw_type.type_string(ctx, Leaf::Owned)?;
1801 branches.push(Line(fmt!(
1802 ctx,
1803 "{} => <{} as {capnp}::introspect::Introspect>::introspect(),",
1804 index,
1805 typ
1806 )));
1807 }
1808 field::Group(group) => {
1809 let params = get_params(ctx, group.get_type_id())?;
1810 let params_string = if params.is_empty() {
1811 "".to_string()
1812 } else {
1813 format!("<{}>", params.join(","))
1814 };
1815
1816 let the_mod = ctx.get_qualified_module(group.get_type_id());
1817
1818 let typ = format!("{the_mod}::Owned{params_string}");
1819 branches.push(Line(fmt!(
1820 ctx,
1821 "{} => <{} as {capnp}::introspect::Introspect>::introspect(),",
1822 index,
1823 typ
1824 )));
1825 }
1826 }
1827 }
1828 let body = if branches.is_empty() {
1829 Line(fmt!(
1830 ctx,
1831 "{capnp}::introspect::panic_invalid_field_index(index)"
1832 ))
1833 } else {
1834 branches.push(Line(fmt!(
1835 ctx,
1836 "_ => {capnp}::introspect::panic_invalid_field_index(index),"
1837 )));
1838 Branch(vec![
1839 Line("match index {".into()),
1840 indent(branches),
1841 Line("}".into()),
1842 ])
1843 };
1844 if !node_reader.get_is_generic() {
1845 Ok(Branch(vec![
1846 Line(fmt!(
1847 ctx,
1848 "pub(crate) fn get_field_types(index: u16) -> {capnp}::introspect::Type {{"
1849 )),
1850 indent(body),
1851 Line("}".into()),
1852 ]))
1853 } else {
1854 let params = node_reader.parameters_texts(ctx);
1855 Ok(Branch(vec![
1856 Line(fmt!(
1857 ctx,
1858 "pub(crate) fn get_field_types<{0}>(index: u16) -> {capnp}::introspect::Type {1} {{",
1859 params.params,
1860 params.where_clause
1861 )),
1862 indent(body),
1863 Line("}".into()),
1864 ]))
1865 }
1866}
1867
1868fn annotation_branch(
1869 ctx: &GeneratorContext,
1870 annotation: schema_capnp::annotation::Reader,
1871 child_index: Option<u16>,
1872 index: u32,
1873) -> ::capnp::Result<FormattedText> {
1874 use capnp::schema_capnp::node;
1875 let id = annotation.get_id();
1876 let annotation_decl = ctx.node_map[&id];
1877 let node::Annotation(a) = annotation_decl.which()? else {
1878 return Err(Error::failed("not an annotation node".into()));
1879 };
1880 if annotation_decl.get_is_generic() {
1881 let brand = annotation.get_brand()?;
1882 let the_mod = ctx.get_qualified_module(id);
1883 let func = do_branding(ctx, id, brand, Leaf::GetType, &the_mod)?;
1884 Ok(Line(format!("({child_index:?}, {index}) => {func}(),")))
1885 } else {
1886 let ty = a.get_type()?;
1890 Ok(Line(fmt!(
1891 ctx,
1892 "({child_index:?}, {index}) => <{} as {capnp}::introspect::Introspect>::introspect(),",
1893 ty.type_string(ctx, Leaf::Owned)?
1894 )))
1895 }
1896}
1897
1898fn generate_get_annotation_types(
1899 ctx: &GeneratorContext,
1900 node_reader: schema_capnp::node::Reader,
1901) -> ::capnp::Result<FormattedText> {
1902 use capnp::schema_capnp::node;
1903
1904 let mut branches = vec![];
1905
1906 for (idx, annotation) in node_reader.get_annotations()?.iter().enumerate() {
1907 branches.push(annotation_branch(ctx, annotation, None, idx as u32)?);
1908 }
1909
1910 match node_reader.which()? {
1911 node::Struct(s) => {
1912 for (fidx, field) in s.get_fields()?.iter().enumerate() {
1913 for (idx, annotation) in field.get_annotations()?.iter().enumerate() {
1914 branches.push(annotation_branch(
1915 ctx,
1916 annotation,
1917 Some(fidx as u16),
1918 idx as u32,
1919 )?);
1920 }
1921 }
1922 }
1923 node::Enum(e) => {
1924 for (fidx, enumerant) in e.get_enumerants()?.iter().enumerate() {
1925 for (idx, annotation) in enumerant.get_annotations()?.iter().enumerate() {
1926 branches.push(annotation_branch(
1927 ctx,
1928 annotation,
1929 Some(fidx as u16),
1930 idx as u32,
1931 )?);
1932 }
1933 }
1934 }
1935 _ => (),
1936 }
1937
1938 let body = if branches.is_empty() {
1939 Line(fmt!(
1940 ctx,
1941 "{capnp}::introspect::panic_invalid_annotation_indices(child_index, index)"
1942 ))
1943 } else {
1944 branches.push(Line(fmt!(
1945 ctx,
1946 "_ => {capnp}::introspect::panic_invalid_annotation_indices(child_index, index),"
1947 )));
1948 indent(vec![
1949 Line("match (child_index, index) {".into()),
1950 indent(branches),
1951 Line("}".into()),
1952 ])
1953 };
1954
1955 if !node_reader.get_is_generic() {
1956 Ok(Branch(vec![
1957 Line(fmt!(ctx,"pub(crate) fn get_annotation_types(child_index: Option<u16>, index: u32) -> {capnp}::introspect::Type {{")),
1958 indent(body),
1959 Line("}".into()),
1960 ]))
1961 } else {
1962 let params = node_reader.parameters_texts(ctx);
1963 Ok(Branch(vec![
1964 Line(fmt!(ctx,
1965 "pub(crate) fn get_annotation_types<{0}>(child_index: Option<u16>, index: u32) -> {capnp}::introspect::Type {1} {{",
1966 params.params, params.where_clause
1967 )),
1968 indent(body),
1969 Line("}".into()),
1970 ]))
1971 }
1972}
1973
1974fn generate_members_by_discriminant(
1975 node_reader: schema_capnp::node::Reader,
1976) -> ::capnp::Result<FormattedText> {
1977 use capnp::schema_capnp::field;
1978 let st = match node_reader.which()? {
1979 schema_capnp::node::Struct(st) => st,
1980 _ => return Err(Error::failed("not a struct".into())),
1981 };
1982
1983 let mut union_member_indexes = vec![];
1984 let mut nonunion_member_indexes = vec![];
1985 for (index, field) in st.get_fields()?.iter().enumerate() {
1986 let disc = field.get_discriminant_value();
1987 if disc == field::NO_DISCRIMINANT {
1988 nonunion_member_indexes.push(index);
1989 } else {
1990 union_member_indexes.push((disc, index));
1991 }
1992 }
1993 union_member_indexes.sort();
1994
1995 let mut nonunion_string: String = "pub(crate) static NONUNION_MEMBERS : &[u16] = &[".into();
1996 for idx in 0..nonunion_member_indexes.len() {
1997 nonunion_string += &format!("{}", nonunion_member_indexes[idx]);
1998 if idx + 1 < nonunion_member_indexes.len() {
1999 nonunion_string += ",";
2000 }
2001 }
2002 nonunion_string += "];";
2003
2004 let mut members_by_disc: String =
2005 "pub(crate) static MEMBERS_BY_DISCRIMINANT : &[u16] = &[".into();
2006 for idx in 0..union_member_indexes.len() {
2007 let (disc, index) = union_member_indexes[idx];
2008 assert_eq!(idx, disc as usize);
2009 members_by_disc += &format!("{index}");
2010 if idx + 1 < union_member_indexes.len() {
2011 members_by_disc += ",";
2012 }
2013 }
2014 members_by_disc += "];";
2015 Ok(Branch(vec![Line(nonunion_string), Line(members_by_disc)]))
2016}
2017
2018fn generate_members_by_name(
2019 node_reader: schema_capnp::node::Reader,
2020) -> ::capnp::Result<FormattedText> {
2021 let st = match node_reader.which()? {
2022 schema_capnp::node::Struct(st) => st,
2023 _ => return Err(Error::failed("not a struct".into())),
2024 };
2025
2026 let mut members_by_name = Vec::new();
2027 for (index, field) in st.get_fields()?.iter().enumerate() {
2028 if let Ok(name) = get_field_name(field) {
2029 members_by_name.push((name, index));
2030 }
2031 }
2032 members_by_name.sort_by_key(|k| k.0);
2033
2034 let mut members_by_name_string: String =
2035 "pub(crate) static MEMBERS_BY_NAME : &[u16] = &[".into();
2036 for (i, (_, index)) in members_by_name.iter().enumerate() {
2037 members_by_name_string += &format!("{}", *index);
2038 if i + 1 < members_by_name.len() {
2039 members_by_name_string += ",";
2040 }
2041 }
2042 members_by_name_string += "];";
2043
2044 Ok(Branch(vec![Line(members_by_name_string)]))
2045}
2046
2047fn get_ty_params_of_brand(
2050 ctx: &GeneratorContext,
2051 brand: schema_capnp::brand::Reader,
2052) -> ::capnp::Result<String> {
2053 let mut acc = HashSet::new();
2054 get_ty_params_of_brand_helper(ctx, &mut acc, brand)?;
2055 let mut result = String::new();
2056 for (scope_id, parameter_index) in acc.into_iter() {
2057 let node = ctx.node_map[&scope_id];
2058 let p = node.get_parameters()?.get(u32::from(parameter_index));
2059 result.push_str(p.get_name()?.to_str()?);
2060 result.push(',');
2061 }
2062
2063 Ok(result)
2064}
2065
2066fn get_ty_params_of_type_helper(
2067 ctx: &GeneratorContext,
2068 accumulator: &mut HashSet<(u64, u16)>,
2069 typ: schema_capnp::type_::Reader,
2070) -> ::capnp::Result<()> {
2071 use capnp::schema_capnp::type_;
2072 match typ.which()? {
2073 type_::Void(())
2074 | type_::Bool(())
2075 | type_::Int8(())
2076 | type_::Int16(())
2077 | type_::Int32(())
2078 | type_::Int64(())
2079 | type_::Uint8(())
2080 | type_::Uint16(())
2081 | type_::Uint32(())
2082 | type_::Uint64(())
2083 | type_::Float32(())
2084 | type_::Float64(())
2085 | type_::Text(_)
2086 | type_::Data(_) => {}
2087 type_::AnyPointer(p) => {
2088 match p.which()? {
2089 type_::any_pointer::Unconstrained(_) => (),
2090 type_::any_pointer::Parameter(p) => {
2091 accumulator.insert((p.get_scope_id(), p.get_parameter_index()));
2092 }
2093 type_::any_pointer::ImplicitMethodParameter(_) => {
2094 }
2096 }
2097 }
2098 type_::List(list) => {
2099 get_ty_params_of_type_helper(ctx, accumulator, list.get_element_type()?)?
2100 }
2101 type_::Enum(e) => {
2102 get_ty_params_of_brand_helper(ctx, accumulator, e.get_brand()?)?;
2103 }
2104 type_::Struct(s) => {
2105 get_ty_params_of_brand_helper(ctx, accumulator, s.get_brand()?)?;
2106 }
2107 type_::Interface(interf) => {
2108 get_ty_params_of_brand_helper(ctx, accumulator, interf.get_brand()?)?;
2109 }
2110 }
2111 Ok(())
2112}
2113
2114fn get_ty_params_of_brand_helper(
2115 ctx: &GeneratorContext,
2116 accumulator: &mut HashSet<(u64, u16)>,
2117 brand: schema_capnp::brand::Reader,
2118) -> ::capnp::Result<()> {
2119 for scope in brand.get_scopes()? {
2120 let scope_id = scope.get_scope_id();
2121 match scope.which()? {
2122 schema_capnp::brand::scope::Bind(bind) => {
2123 for binding in bind? {
2124 match binding.which()? {
2125 schema_capnp::brand::binding::Unbound(()) => {}
2126 schema_capnp::brand::binding::Type(t) => {
2127 get_ty_params_of_type_helper(ctx, accumulator, t?)?
2128 }
2129 }
2130 }
2131 }
2132 schema_capnp::brand::scope::Inherit(()) => {
2133 let parameters = ctx.node_map[&scope_id].get_parameters()?;
2134 for idx in 0..parameters.len() {
2135 accumulator.insert((scope_id, idx as u16));
2136 }
2137 }
2138 }
2139 }
2140 Ok(())
2141}
2142
2143fn newtype_template_id(
2149 ctx: &GeneratorContext,
2150 alias_id: u64,
2151) -> ::capnp::Result<Option<u64>> {
2152 use capnp::schema_capnp::*;
2153 let Some(alias) = ctx.node_map.get(&alias_id) else {
2154 return Ok(None);
2155 };
2156 let node::Type(Ok(t)) = alias.which()? else {
2157 return Ok(None);
2158 };
2159 let type_::Struct(st) = t.which()? else {
2160 return Ok(None); };
2162 let template_id = st.get_type_id();
2163 let Some(template) = ctx.node_map.get(&template_id) else {
2164 return Ok(None);
2165 };
2166 if template.get_scope_id() != alias_id {
2167 let aliased = t.get_type_id();
2170 if aliased != 0 {
2171 return newtype_template_id(ctx, aliased);
2172 }
2173 return Ok(None);
2174 }
2175 Ok(Some(template_id))
2176}
2177
2178fn inline_newtype_owner(ctx: &GeneratorContext, alias_id: u64) -> ::capnp::Result<Option<u64>> {
2181 Ok(newtype_template_id(ctx, alias_id)?.map(|t| ctx.node_map[&t].get_scope_id()))
2182}
2183
2184fn group_newtype_template_id(
2188 ctx: &GeneratorContext,
2189 alias_id: u64,
2190) -> ::capnp::Result<Option<u64>> {
2191 use capnp::schema_capnp::*;
2192 let Some(template_id) = newtype_template_id(ctx, alias_id)? else {
2193 return Ok(None);
2194 };
2195 let node::Struct(tmpl) = ctx.node_map[&template_id].which()? else {
2196 return Ok(None);
2197 };
2198 if tmpl.get_discriminant_count() > 0 {
2199 return Ok(None); }
2201 for field in tmpl.get_fields()? {
2202 if let field::Group(_) = field.which()? {
2203 if field.get_type_id() == 0 {
2204 return Ok(None); }
2206 }
2207 }
2208 Ok(Some(template_id))
2209}
2210
2211fn union_newtype_template_id(
2214 ctx: &GeneratorContext,
2215 alias_id: u64,
2216) -> ::capnp::Result<Option<u64>> {
2217 use capnp::schema_capnp::*;
2218 let Some(template_id) = newtype_template_id(ctx, alias_id)? else {
2219 return Ok(None);
2220 };
2221 let node::Struct(tmpl) = ctx.node_map[&template_id].which()? else {
2222 return Ok(None);
2223 };
2224 if tmpl.get_discriminant_count() == 0 {
2225 return Ok(None); }
2227 for field in tmpl.get_fields()? {
2228 if let field::Group(_) = field.which()? {
2229 if field.get_type_id() == 0 {
2230 return Ok(None); }
2232 }
2233 }
2234 Ok(Some(template_id))
2235}
2236
2237struct TraitMethod {
2241 signature: String,
2242 call_name: String,
2243 call_args: String,
2244 deref_self: bool,
2245}
2246
2247fn newtype_trait_methods(
2250 ctx: &GeneratorContext,
2251 field: &schema_capnp::field::Reader,
2252 is_reader: bool,
2253 include_getter: bool,
2254) -> ::capnp::Result<Vec<TraitMethod>> {
2255 use capnp::schema_capnp::*;
2256 let name = camel_to_snake_case(field.get_name()?.to_str()?);
2257 let is_pointer = match field.which()? {
2258 field::Slot(s) => s.get_type()?.is_pointer()?,
2259 field::Group(_) => false,
2260 };
2261 let mut methods = Vec::new();
2262
2263 if is_reader {
2266 if include_getter {
2267 let (ret, _, _) = getter_text(ctx, field, true, true)?;
2268 methods.push(TraitMethod {
2269 signature: format!("get_{name}(&self) {ret}"),
2270 call_name: format!("get_{name}"),
2271 call_args: String::new(),
2272 deref_self: true,
2273 });
2274 }
2275 } else {
2276 if include_getter {
2277 let (ret, _, _) = getter_text(ctx, field, false, true)?;
2280 methods.push(TraitMethod {
2281 signature: format!("get_{name}(self) {ret}"),
2282 call_name: format!("get_{name}"),
2283 call_args: String::new(),
2284 deref_self: false,
2285 });
2286 }
2287 for m in setter_methods(ctx, 0, &name, field)? {
2288 methods.push(TraitMethod {
2289 signature: m.signature(false),
2290 call_name: m.name,
2291 call_args: m.delegate_args,
2292 deref_self: false,
2293 });
2294 }
2295 }
2296 if is_pointer {
2297 methods.push(TraitMethod {
2298 signature: format!("has_{name}(&self) -> bool"),
2299 call_name: format!("has_{name}"),
2300 call_args: String::new(),
2301 deref_self: false,
2302 });
2303 }
2304 Ok(methods)
2305}
2306
2307fn generate_newtype_trait(
2310 ctx: &GeneratorContext,
2311 node_id: u64,
2312 node_name: &str,
2313) -> ::capnp::Result<FormattedText> {
2314 if let Some(owner) = inline_newtype_owner(ctx, node_id)? {
2315 if owner != node_id {
2316 return Ok(Branch(vec![
2319 BlankLine,
2320 Line(format!("pub mod {} {{", module_name(node_name))),
2321 indent(Line(format!("pub use {}::*;", ctx.get_qualified_module(owner)))),
2322 line("}"),
2323 ]));
2324 }
2325 }
2326 Ok(Branch(vec![
2327 generate_group_newtype_trait(ctx, node_id, node_name)?,
2328 generate_union_newtype_trait(ctx, node_id, node_name)?,
2329 ]))
2330}
2331
2332fn count_newtype_leaves(ctx: &GeneratorContext, template_id: u64) -> ::capnp::Result<usize> {
2335 use capnp::schema_capnp::*;
2336 let node::Struct(tmpl) = ctx.node_map[&template_id].which()? else {
2337 return Ok(0);
2338 };
2339 let mut n = 0;
2340 for field in tmpl.get_fields()? {
2341 match field.which()? {
2342 field::Slot(_) => n += 1,
2343 field::Group(_) => {
2344 if let Some(nested) = newtype_template_id(ctx, field.get_type_id())? {
2345 n += count_newtype_leaves(ctx, nested)?;
2346 }
2347 }
2348 }
2349 }
2350 Ok(n)
2351}
2352
2353fn collect_leaf_offsets(
2357 ctx: &GeneratorContext,
2358 template_id: u64,
2359 instance_id: u64,
2360 out: &mut Vec<String>,
2361) -> ::capnp::Result<()> {
2362 use capnp::schema_capnp::*;
2363 let node::Struct(tmpl) = ctx.node_map[&template_id].which()? else {
2364 return Ok(());
2365 };
2366 let node::Struct(instance) = ctx.node_map[&instance_id].which()? else {
2367 return Ok(());
2368 };
2369 let mut inst_fields = ::std::collections::HashMap::new();
2370 for f in instance.get_fields()? {
2371 inst_fields.insert(f.get_name()?.to_str()?.to_string(), f);
2372 }
2373 for field in tmpl.get_fields()? {
2374 let raw = field.get_name()?.to_str()?;
2375 match field.which()? {
2376 field::Slot(_) => match inst_fields.get(raw).map(|f| f.which()) {
2377 Some(Ok(field::Slot(s))) => out.push(s.get_offset().to_string()),
2378 _ => out.push("0xffff_ffff".to_string()),
2379 },
2380 field::Group(_) => {
2381 let Some(nested_tmpl) = newtype_template_id(ctx, field.get_type_id())? else {
2382 continue;
2383 };
2384 match inst_fields.get(raw).map(|f| f.which()) {
2385 Some(Ok(field::Group(ig))) => {
2386 collect_leaf_offsets(ctx, nested_tmpl, ig.get_type_id(), out)?
2387 }
2388 _ => {
2389 for _ in 0..count_newtype_leaves(ctx, nested_tmpl)? {
2390 out.push("0xffff_ffff".to_string());
2391 }
2392 }
2393 }
2394 }
2395 }
2396 }
2397 Ok(())
2398}
2399
2400fn any_reader_items(
2406 ctx: &GeneratorContext,
2407 template_id: u64,
2408) -> ::capnp::Result<Vec<FormattedText>> {
2409 use capnp::schema_capnp::*;
2410 let node::Struct(tmpl) = ctx.node_map[&template_id].which()? else {
2411 return Ok(vec![]);
2412 };
2413 if tmpl.get_discriminant_count() > 0 {
2414 return Ok(vec![]); }
2416
2417 let mut inherent = Vec::new();
2418 let mut trait_methods = Vec::new();
2419 let mut defaults = Vec::new();
2420 let mut cursor = 0usize;
2421 for field in tmpl.get_fields()? {
2422 let name = camel_to_snake_case(field.get_name()?.to_str()?);
2423 if let field::Group(_) = field.which()? {
2424 let assoc = capitalize_first_letter(field.get_name()?.to_str()?);
2425 let nested_mod = ctx.get_qualified_module(field.get_type_id());
2426 let Some(nested_tmpl) = newtype_template_id(ctx, field.get_type_id())? else {
2427 return Ok(vec![]);
2428 };
2429 let count = count_newtype_leaves(ctx, nested_tmpl)?;
2430 let (start, end) = (cursor, cursor + count);
2431 inherent.push(Line(format!(
2432 "pub fn get_{name}(&self) -> {nested_mod}::AnyReader<'a> {{ {nested_mod}::AnyReader::new(self.reader, &self.offsets[{start}..{end}]) }}"
2433 )));
2434 trait_methods.push(Line(format!("type {assoc} = {nested_mod}::AnyReader<'a>;")));
2435 trait_methods.push(Line(format!(
2436 "fn get_{name}(&self) -> Self::{assoc} {{ self.get_{name}() }}"
2437 )));
2438 cursor += count;
2439 } else {
2440 let off = format!("self.offsets[{cursor}] as usize");
2441 let (ret, mut body, def) = getter_text_at(ctx, &field, true, true, Some(&off))?;
2442 if let Some(d) = def {
2443 defaults.push(d);
2444 }
2445 if is_scalar_data_field(&field)? {
2448 if let (field::Slot(s), FormattedText::Line(expr)) = (field.which()?, &body) {
2449 let expr = expr.clone();
2450 let dflt = prim_default_value(&s.get_default_value()?)?;
2451 body = Line(format!(
2452 "if self.offsets[{cursor}] == 0xffff_ffffu32 {{ {dflt} }} else {{ {expr} }}"
2453 ));
2454 }
2455 }
2456 inherent.push(Line(format!("pub fn get_{name}(&self) {ret} {{")));
2457 inherent.push(indent(body));
2458 inherent.push(line("}"));
2459 trait_methods.push(Line(format!("fn get_{name}(&self) {ret} {{ self.get_{name}() }}")));
2460 if let field::Slot(s) = field.which()? {
2461 if s.get_type()?.is_pointer()? {
2462 inherent.push(Line(format!(
2463 "pub fn has_{name}(&self) -> bool {{ !self.reader.get_pointer_field(self.offsets[{cursor}] as usize).is_null() }}"
2464 )));
2465 trait_methods.push(Line(format!(
2466 "fn has_{name}(&self) -> bool {{ self.has_{name}() }}"
2467 )));
2468 }
2469 }
2470 cursor += 1;
2471 }
2472 }
2473
2474 let sr = fmt!(ctx, "{capnp}::private::layout::StructReader<'a>");
2475 let mut items = vec![
2476 BlankLine,
2477 line("#[derive(Clone, Copy)]"),
2478 Line(format!(
2479 "pub struct AnyReader<'a> {{ reader: {sr}, offsets: &'a [u32] }}"
2480 )),
2481 line("impl<'a> AnyReader<'a> {"),
2482 indent(vec![
2483 Line(format!(
2484 "pub fn new(reader: {sr}, offsets: &'a [u32]) -> Self {{ AnyReader {{ reader, offsets }} }}"
2485 )),
2486 Branch(inherent),
2487 ]),
2488 line("}"),
2489 line("impl<'a> Reader<'a> for AnyReader<'a> {"),
2490 indent(trait_methods),
2491 line("}"),
2492 ];
2493 if !defaults.is_empty() {
2494 items.push(line("mod _private {"));
2495 items.push(indent(defaults));
2496 items.push(line("}"));
2497 }
2498 Ok(items)
2499}
2500
2501fn union_any_reader_items(
2506 ctx: &GeneratorContext,
2507 template_id: u64,
2508) -> ::capnp::Result<Vec<FormattedText>> {
2509 use capnp::schema_capnp::*;
2510 let node::Struct(tmpl) = ctx.node_map[&template_id].which()? else {
2511 return Ok(vec![]);
2512 };
2513 if tmpl.get_discriminant_count() == 0 {
2514 return Ok(vec![]);
2515 }
2516
2517 let mut arms = Vec::new();
2518 let mut assoc = Vec::new();
2519 let mut group_variants = Vec::new();
2520 let mut which_type_params = Vec::new();
2521 let mut has_inherent = Vec::new();
2522 let mut has_trait = Vec::new();
2523 let mut needs_lifetime = false;
2524 let mut cursor = 0usize;
2525 for field in tmpl.get_fields()? {
2526 let variant = capitalize_first_letter(field.get_name()?.to_str()?);
2527 let name = camel_to_snake_case(field.get_name()?.to_str()?);
2528 let dvalue = field.get_discriminant_value();
2529 if let field::Group(_) = field.which()? {
2530 let nested_mod = ctx.get_qualified_module(field.get_type_id());
2531 let Some(nested_tmpl) = newtype_template_id(ctx, field.get_type_id())? else {
2532 return Ok(vec![]);
2533 };
2534 let count = count_newtype_leaves(ctx, nested_tmpl)?;
2535 let (start, end) = (cursor, cursor + count);
2536 arms.push(Line(format!(
2537 "{dvalue} => ::core::result::Result::Ok(Which::{variant}({nested_mod}::AnyReader::new(self.reader, &self.offsets[{start}..{end}]))),"
2538 )));
2539 assoc.push(Line(format!("type {variant} = {nested_mod}::AnyReader<'a>;")));
2540 group_variants.push(variant.clone());
2541 which_type_params.push(format!("{nested_mod}::AnyReader<'a>"));
2542 cursor += count;
2543 } else {
2544 let off = format!("self.offsets[{cursor}] as usize");
2545 let (_, getter_code, _) = getter_text_at(ctx, &field, true, false, Some(&off))?;
2546 let FormattedText::Line(payload) = getter_code else {
2547 return Ok(vec![]); };
2549 arms.push(Line(format!(
2550 "{dvalue} => ::core::result::Result::Ok(Which::{variant}({payload})),"
2551 )));
2552 if let field::Slot(s) = field.which()? {
2553 if s.get_type()?.is_pointer()? {
2554 needs_lifetime = true;
2555 has_inherent.push(Line(format!(
2556 "pub fn has_{name}(&self) -> bool {{ if self.reader.get_data_field::<u16>(self.disc_offset as usize) != {dvalue} {{ return false; }} !self.reader.get_pointer_field(self.offsets[{cursor}] as usize).is_null() }}"
2557 )));
2558 has_trait.push(Line(format!(
2559 "fn has_{name}(&self) -> bool {{ self.has_{name}() }}"
2560 )));
2561 }
2562 }
2563 cursor += 1;
2564 }
2565 }
2566 arms.push(line(
2567 "x => ::core::result::Result::Err(::capnp::NotInSchema(x)),",
2568 ));
2569
2570 let inherent_ret = union_which_generics(needs_lifetime, &which_type_params);
2571 let self_ret = union_which_generics(
2572 needs_lifetime,
2573 &group_variants
2574 .iter()
2575 .map(|v| format!("Self::{v}"))
2576 .collect::<Vec<_>>(),
2577 );
2578
2579 let sr = fmt!(ctx, "{capnp}::private::layout::StructReader<'a>");
2580 let which_method = Branch(vec![
2581 Line(format!(
2582 "pub fn which(&self) -> ::core::result::Result<Which{inherent_ret}, ::capnp::NotInSchema> {{"
2583 )),
2584 indent(vec![
2585 line("match self.reader.get_data_field::<u16>(self.disc_offset as usize) {"),
2586 indent(arms),
2587 line("}"),
2588 ]),
2589 line("}"),
2590 ]);
2591
2592 let mut trait_items = assoc;
2593 trait_items.push(Line(format!(
2594 "fn which(&self) -> ::core::result::Result<Which{self_ret}, ::capnp::NotInSchema> {{ self.which() }}"
2595 )));
2596 trait_items.extend(has_trait);
2597
2598 Ok(vec![
2599 BlankLine,
2600 line("#[derive(Clone, Copy)]"),
2601 Line(format!(
2602 "pub struct AnyReader<'a> {{ reader: {sr}, disc_offset: u32, offsets: &'a [u32] }}"
2603 )),
2604 line("impl<'a> AnyReader<'a> {"),
2605 indent(vec![
2606 Line(format!(
2607 "pub fn new(reader: {sr}, disc_offset: u32, offsets: &'a [u32]) -> Self {{ AnyReader {{ reader, disc_offset, offsets }} }}"
2608 )),
2609 which_method,
2610 Branch(has_inherent),
2611 ]),
2612 line("}"),
2613 line("impl<'a> Reader<'a> for AnyReader<'a> {"),
2614 indent(trait_items),
2615 line("}"),
2616 ])
2617}
2618
2619fn any_builder_items(
2623 ctx: &GeneratorContext,
2624 template_id: u64,
2625) -> ::capnp::Result<Vec<FormattedText>> {
2626 use capnp::schema_capnp::*;
2627 let node::Struct(tmpl) = ctx.node_map[&template_id].which()? else {
2628 return Ok(vec![]);
2629 };
2630 if tmpl.get_discriminant_count() > 0 {
2631 return Ok(vec![]); }
2633
2634 let mut inherent = Vec::new();
2635 let mut trait_methods = Vec::new();
2636 let mut cursor = 0usize;
2637 for field in tmpl.get_fields()? {
2638 let name = camel_to_snake_case(field.get_name()?.to_str()?);
2639 if let field::Group(_) = field.which()? {
2640 let assoc = capitalize_first_letter(field.get_name()?.to_str()?);
2641 let nested_mod = ctx.get_qualified_module(field.get_type_id());
2642 let Some(nested_tmpl) = newtype_template_id(ctx, field.get_type_id())? else {
2643 return Ok(vec![]);
2644 };
2645 let count = count_newtype_leaves(ctx, nested_tmpl)?;
2646 let (start, end) = (cursor, cursor + count);
2647 for verb in ["get", "init"] {
2648 inherent.push(Line(format!(
2649 "pub fn {verb}_{name}(self) -> {nested_mod}::AnyBuilder<'a> {{ {nested_mod}::AnyBuilder::new(self.builder, &self.offsets[{start}..{end}]) }}"
2650 )));
2651 }
2652 trait_methods.push(Line(format!("type {assoc} = {nested_mod}::AnyBuilder<'a>;")));
2653 trait_methods.push(Line(format!(
2654 "fn get_{name}(self) -> Self::{assoc} {{ self.get_{name}() }}"
2655 )));
2656 trait_methods.push(Line(format!(
2657 "fn init_{name}(self) -> Self::{assoc} {{ self.init_{name}() }}"
2658 )));
2659 cursor += count;
2660 } else {
2661 let off = format!("self.offsets[{cursor}] as usize");
2662 let guard = unmapped_panic(cursor, &name);
2663 let (ret, body, _) = getter_text_at(ctx, &field, false, true, Some(&off))?;
2666 let get_body = if is_scalar_data_field(&field)? {
2667 if let field::Slot(s) = field.which()? {
2668 if let FormattedText::Line(expr) = &body {
2669 let expr = expr.clone();
2670 let dflt = prim_default_value(&s.get_default_value()?)?;
2671 Line(format!(
2672 "if self.offsets[{cursor}] == 0xffff_ffffu32 {{ {dflt} }} else {{ {expr} }}"
2673 ))
2674 } else {
2675 body
2676 }
2677 } else {
2678 body
2679 }
2680 } else {
2681 Branch(vec![Line(guard.clone()), body])
2682 };
2683 inherent.push(Line(format!("pub fn get_{name}(self) {ret} {{")));
2684 inherent.push(indent(get_body));
2685 inherent.push(line("}"));
2686 trait_methods.push(Line(format!("fn get_{name}(self) {ret} {{ self.get_{name}() }}")));
2687 for m in setter_methods_at(ctx, "0", &name, &field, Some(&off))? {
2688 let sig_inherent = m.signature(true);
2689 let sig_trait = m.signature(false);
2690 let call = format!("self.{}({})", m.name, m.delegate_args);
2691 inherent.push(Line(format!("pub fn {sig_inherent} {{")));
2692 inherent.push(indent(Branch(vec![Line(guard.clone()), m.body])));
2693 inherent.push(line("}"));
2694 trait_methods.push(Line(format!("fn {sig_trait} {{ {call} }}")));
2695 }
2696 if let field::Slot(s) = field.which()? {
2697 if s.get_type()?.is_pointer()? {
2698 inherent.push(Line(format!(
2699 "pub fn has_{name}(&self) -> bool {{ if self.offsets[{cursor}] == 0xffff_ffffu32 {{ return false; }} !self.builder.is_pointer_field_null(self.offsets[{cursor}] as usize) }}"
2700 )));
2701 trait_methods.push(Line(format!(
2702 "fn has_{name}(&self) -> bool {{ self.has_{name}() }}"
2703 )));
2704 }
2705 }
2706 cursor += 1;
2707 }
2708 }
2709
2710 let sb = fmt!(ctx, "{capnp}::private::layout::StructBuilder<'a>");
2711 Ok(vec![
2712 BlankLine,
2713 Line(format!(
2714 "pub struct AnyBuilder<'a> {{ builder: {sb}, offsets: &'a [u32] }}"
2715 )),
2716 line("impl<'a> AnyBuilder<'a> {"),
2717 indent(vec![
2718 Line(format!(
2719 "pub fn new(builder: {sb}, offsets: &'a [u32]) -> Self {{ AnyBuilder {{ builder, offsets }} }}"
2720 )),
2721 Branch(inherent),
2722 ]),
2723 line("}"),
2724 line("impl<'a> Builder<'a> for AnyBuilder<'a> {"),
2725 indent(trait_methods),
2726 line("}"),
2727 ])
2728}
2729
2730fn union_any_builder_items(
2734 ctx: &GeneratorContext,
2735 template_id: u64,
2736) -> ::capnp::Result<Vec<FormattedText>> {
2737 use capnp::schema_capnp::*;
2738 let node::Struct(tmpl) = ctx.node_map[&template_id].which()? else {
2739 return Ok(vec![]);
2740 };
2741 if tmpl.get_discriminant_count() == 0 {
2742 return Ok(vec![]);
2743 }
2744
2745 let mut inherent = Vec::new();
2746 let mut assoc = Vec::new();
2747 let mut trait_methods = Vec::new();
2748 let mut cursor = 0usize;
2749 for field in tmpl.get_fields()? {
2750 let variant = capitalize_first_letter(field.get_name()?.to_str()?);
2751 let name = camel_to_snake_case(field.get_name()?.to_str()?);
2752 let dvalue = field.get_discriminant_value();
2753 if let field::Group(_) = field.which()? {
2754 let nested_mod = ctx.get_qualified_module(field.get_type_id());
2755 let Some(nested_tmpl) = newtype_template_id(ctx, field.get_type_id())? else {
2756 return Ok(vec![]);
2757 };
2758 let count = count_newtype_leaves(ctx, nested_tmpl)?;
2759 let (start, end) = (cursor, cursor + count);
2760 inherent.push(Line(format!(
2761 "pub fn init_{name}(self) -> {nested_mod}::AnyBuilder<'a> {{ let b = self.builder; b.set_data_field::<u16>(self.disc_offset as usize, {dvalue}); {nested_mod}::AnyBuilder::new(b, &self.offsets[{start}..{end}]) }}"
2762 )));
2763 assoc.push(Line(format!("type {variant} = {nested_mod}::AnyBuilder<'a>;")));
2764 trait_methods.push(Line(format!(
2765 "fn init_{name}(self) -> Self::{variant} {{ self.init_{name}() }}"
2766 )));
2767 cursor += count;
2768 } else {
2769 let off = format!("self.offsets[{cursor}] as usize");
2770 let guard = unmapped_panic(cursor, &name);
2771 for m in setter_methods_at(ctx, "self.disc_offset as usize", &name, &field, Some(&off))? {
2772 let sig_inherent = m.signature(true);
2773 let sig_trait = m.signature(false);
2774 let call = format!("self.{}({})", m.name, m.delegate_args);
2775 inherent.push(Line(format!("pub fn {sig_inherent} {{")));
2776 inherent.push(indent(Branch(vec![Line(guard.clone()), m.body])));
2777 inherent.push(line("}"));
2778 trait_methods.push(Line(format!("fn {sig_trait} {{ {call} }}")));
2779 }
2780 if let field::Slot(s) = field.which()? {
2781 if s.get_type()?.is_pointer()? {
2782 inherent.push(Line(format!(
2783 "pub fn has_{name}(&self) -> bool {{ if self.builder.get_data_field::<u16>(self.disc_offset as usize) != {dvalue} {{ return false; }} !self.builder.is_pointer_field_null(self.offsets[{cursor}] as usize) }}"
2784 )));
2785 trait_methods.push(Line(format!(
2786 "fn has_{name}(&self) -> bool {{ self.has_{name}() }}"
2787 )));
2788 }
2789 }
2790 cursor += 1;
2791 }
2792 }
2793
2794 let sb = fmt!(ctx, "{capnp}::private::layout::StructBuilder<'a>");
2795 let mut trait_items = assoc;
2796 trait_items.extend(trait_methods);
2797 Ok(vec![
2798 BlankLine,
2799 Line(format!(
2800 "pub struct AnyBuilder<'a> {{ builder: {sb}, disc_offset: u32, offsets: &'a [u32] }}"
2801 )),
2802 line("impl<'a> AnyBuilder<'a> {"),
2803 indent(vec![
2804 Line(format!(
2805 "pub fn new(builder: {sb}, disc_offset: u32, offsets: &'a [u32]) -> Self {{ AnyBuilder {{ builder, disc_offset, offsets }} }}"
2806 )),
2807 Branch(inherent),
2808 ]),
2809 line("}"),
2810 line("impl<'a> Builder<'a> for AnyBuilder<'a> {"),
2811 indent(trait_items),
2812 line("}"),
2813 ])
2814}
2815
2816fn generate_group_newtype_trait(
2820 ctx: &GeneratorContext,
2821 node_id: u64,
2822 node_name: &str,
2823) -> ::capnp::Result<FormattedText> {
2824 use capnp::schema_capnp::*;
2825 let Some(template_id) = group_newtype_template_id(ctx, node_id)? else {
2826 return Ok(Branch(vec![]));
2827 };
2828 let node::Struct(tmpl) = ctx.node_map[&template_id].which()? else {
2829 return Ok(Branch(vec![]));
2830 };
2831
2832 let mut reader_items = Vec::new();
2833 let mut builder_items = Vec::new();
2834 for field in tmpl.get_fields()? {
2835 if let field::Group(_) = field.which()? {
2836 let name = camel_to_snake_case(field.get_name()?.to_str()?);
2839 let assoc = capitalize_first_letter(field.get_name()?.to_str()?);
2840 let nested = ctx.get_qualified_module(field.get_type_id());
2841 reader_items.push(Line(format!("type {assoc}: {nested}::Reader<'a>;")));
2842 reader_items.push(Line(format!("fn get_{name}(&self) -> Self::{assoc};")));
2843 builder_items.push(Line(format!("type {assoc}: {nested}::Builder<'a>;")));
2844 builder_items.push(Line(format!("fn get_{name}(self) -> Self::{assoc};")));
2845 builder_items.push(Line(format!("fn init_{name}(self) -> Self::{assoc};")));
2846 } else {
2847 for m in newtype_trait_methods(ctx, &field, true, true)? {
2848 reader_items.push(Line(format!("fn {};", m.signature)));
2849 }
2850 for m in newtype_trait_methods(ctx, &field, false, true)? {
2851 builder_items.push(Line(format!("fn {};", m.signature)));
2852 }
2853 }
2854 }
2855
2856 let mut module_items = vec![
2857 line("pub trait Reader<'a> {"),
2858 indent(reader_items),
2859 line("}"),
2860 line("pub trait Builder<'a> {"),
2861 indent(builder_items),
2862 line("}"),
2863 ];
2864 module_items.extend(any_reader_items(ctx, template_id)?);
2865 module_items.extend(any_builder_items(ctx, template_id)?);
2866
2867 Ok(Branch(vec![
2868 BlankLine,
2869 Line(format!("pub mod {} {{", module_name(node_name))),
2870 indent(module_items),
2871 line("}"),
2872 ]))
2873}
2874
2875fn generate_newtype_impl(
2880 ctx: &GeneratorContext,
2881 alias_id: u64,
2882 instance_id: u64,
2883) -> ::capnp::Result<FormattedText> {
2884 Ok(Branch(vec![
2885 generate_group_newtype_impl(ctx, alias_id, instance_id)?,
2886 generate_union_newtype_impl(ctx, alias_id, instance_id)?,
2887 ]))
2888}
2889
2890fn generate_group_newtype_impl(
2891 ctx: &GeneratorContext,
2892 alias_id: u64,
2893 instance_id: u64,
2894) -> ::capnp::Result<FormattedText> {
2895 use capnp::schema_capnp::*;
2896 let Some(template_id) = group_newtype_template_id(ctx, alias_id)? else {
2897 return Ok(Branch(vec![]));
2898 };
2899 let node::Struct(tmpl) = ctx.node_map[&template_id].which()? else {
2900 return Ok(Branch(vec![]));
2901 };
2902 let node::Struct(instance) = ctx.node_map[&instance_id].which()? else {
2903 return Ok(Branch(vec![]));
2904 };
2905
2906 let mut instance_fields = ::std::collections::HashMap::new();
2911 for field in instance.get_fields()? {
2912 instance_fields.insert(field.get_name()?.to_str()?.to_string(), field);
2913 }
2914
2915 let mut trait_ok = true;
2916 let mut reader_items = Vec::new();
2917 let mut builder_items = Vec::new();
2918 for field in tmpl.get_fields()? {
2919 let raw_name = field.get_name()?.to_str()?;
2920 let Some(inst_field) = instance_fields.get(raw_name) else {
2921 if is_scalar_data_field(&field)? {
2926 let field::Slot(s) = field.which()? else {
2927 trait_ok = false;
2928 continue;
2929 };
2930 let dflt = prim_default_value(&s.get_default_value()?)?;
2931 let not_mapped =
2932 format!("panic!(\"field '{raw_name}' is not mapped at this use site\")");
2933 for m in newtype_trait_methods(ctx, &field, true, true)? {
2934 reader_items.push(Line(format!("fn {} {{ {dflt} }}", m.signature)));
2935 }
2936 for m in newtype_trait_methods(ctx, &field, false, true)? {
2937 let body = if m.call_name.starts_with("get_") {
2938 dflt.clone()
2939 } else if m.call_args.is_empty() {
2940 not_mapped.clone()
2941 } else if m.call_args.contains(',') {
2942 format!("let _ = ({}); {not_mapped}", m.call_args)
2943 } else {
2944 format!("let _ = {}; {not_mapped}", m.call_args)
2946 };
2947 builder_items.push(Line(format!("fn {} {{ {body} }}", m.signature)));
2948 }
2949 } else {
2950 trait_ok = false;
2951 }
2952 continue;
2953 };
2954 if let field::Group(_) = field.which()? {
2957 let field::Group(inst_group) = inst_field.which()? else {
2958 return Ok(Branch(vec![]));
2959 };
2960 let name = camel_to_snake_case(raw_name);
2961 let assoc = capitalize_first_letter(raw_name);
2962 let inst_mod = ctx.get_qualified_module(inst_group.get_type_id());
2963 reader_items.push(Line(format!("type {assoc} = {inst_mod}::Reader<'a>;")));
2964 reader_items.push(Line(format!(
2965 "fn get_{name}(&self) -> Self::{assoc} {{ (*self).get_{name}() }}"
2966 )));
2967 builder_items.push(Line(format!("type {assoc} = {inst_mod}::Builder<'a>;")));
2968 builder_items.push(Line(format!(
2969 "fn get_{name}(self) -> Self::{assoc} {{ self.get_{name}() }}"
2970 )));
2971 builder_items.push(Line(format!(
2972 "fn init_{name}(self) -> Self::{assoc} {{ self.init_{name}() }}"
2973 )));
2974 } else {
2975 for m in newtype_trait_methods(ctx, &field, true, true)? {
2976 let recv = if m.deref_self { "(*self)" } else { "self" };
2977 reader_items.push(Line(format!(
2978 "fn {} {{ {recv}.{}({}) }}",
2979 m.signature, m.call_name, m.call_args
2980 )));
2981 }
2982 for m in newtype_trait_methods(ctx, &field, false, true)? {
2983 let recv = if m.deref_self { "(*self)" } else { "self" };
2984 builder_items.push(Line(format!(
2985 "fn {} {{ {recv}.{}({}) }}",
2986 m.signature, m.call_name, m.call_args
2987 )));
2988 }
2989 }
2990 }
2991
2992 let reader_methods = reader_items;
2993 let builder_methods = builder_items;
2994 let trait_path = ctx.get_qualified_module(alias_id);
2995 let concrete = ctx.get_qualified_module(instance_id);
2996
2997 let mut any_items = Vec::new();
3001 {
3002 let mut offsets = Vec::new();
3003 collect_leaf_offsets(ctx, template_id, instance_id, &mut offsets)?;
3004 let n = offsets.len();
3005 let table = format!(
3006 "{}_OFFSETS",
3007 camel_to_snake_case(ctx.get_last_name(instance_id)?).to_ascii_uppercase()
3008 );
3009 any_items.push(BlankLine);
3010 any_items.push(Line(format!(
3011 "static {table}: [u32; {n}] = [{}];",
3012 offsets.join(", ")
3013 )));
3014 any_items.push(Line(format!("impl<'a> {concrete}::Reader<'a> {{")));
3015 any_items.push(indent(Line(fmt!(ctx,
3016 "pub fn as_any(self) -> {trait_path}::AnyReader<'a> {{ {trait_path}::AnyReader::new({capnp}::traits::IntoInternalStructReader::into_internal_struct_reader(self), &{table}) }}"
3017 ))));
3018 any_items.push(line("}"));
3019 any_items.push(Line(format!("impl<'a> {concrete}::Builder<'a> {{")));
3020 any_items.push(indent(Line(fmt!(ctx,
3021 "pub fn as_any(self) -> {trait_path}::AnyBuilder<'a> {{ {trait_path}::AnyBuilder::new({capnp}::traits::IntoInternalStructBuilder::into_internal_struct_builder(self), &{table}) }}"
3022 ))));
3023 any_items.push(line("}"));
3024 }
3025
3026 let mut out = Vec::new();
3029 if trait_ok {
3030 out.push(BlankLine);
3031 out.push(Line(format!(
3032 "impl<'a> {trait_path}::Reader<'a> for {concrete}::Reader<'a> {{"
3033 )));
3034 out.push(indent(reader_methods));
3035 out.push(line("}"));
3036 out.push(BlankLine);
3037 out.push(Line(format!(
3038 "impl<'a> {trait_path}::Builder<'a> for {concrete}::Builder<'a> {{"
3039 )));
3040 out.push(indent(builder_methods));
3041 out.push(line("}"));
3042 }
3043 out.push(Branch(any_items));
3044 Ok(Branch(out))
3045}
3046
3047fn union_which_generics(needs_lifetime: bool, params: &[String]) -> String {
3053 let mut all = Vec::new();
3054 if needs_lifetime {
3055 all.push("'a".to_string());
3056 }
3057 all.extend(params.iter().cloned());
3058 if all.is_empty() {
3059 String::new()
3060 } else {
3061 format!("<{}>", all.join(", "))
3062 }
3063}
3064
3065fn generate_union_newtype_trait(
3069 ctx: &GeneratorContext,
3070 node_id: u64,
3071 node_name: &str,
3072) -> ::capnp::Result<FormattedText> {
3073 use capnp::schema_capnp::*;
3074 let Some(template_id) = union_newtype_template_id(ctx, node_id)? else {
3075 return Ok(Branch(vec![]));
3076 };
3077 let node::Struct(tmpl) = ctx.node_map[&template_id].which()? else {
3078 return Ok(Branch(vec![]));
3079 };
3080
3081 let mut variants = Vec::new();
3082 let mut group_params = Vec::new();
3083 let mut reader_assoc = Vec::new();
3084 let mut reader_methods = Vec::new();
3085 let mut builder_assoc = Vec::new();
3086 let mut builder_methods = Vec::new();
3087 let mut needs_lifetime = false;
3088 for field in tmpl.get_fields()? {
3089 let variant = capitalize_first_letter(field.get_name()?.to_str()?);
3090 let name = camel_to_snake_case(field.get_name()?.to_str()?);
3091 if let field::Group(_) = field.which()? {
3092 let nested = ctx.get_qualified_module(field.get_type_id());
3093 variants.push(Line(format!("{variant}({variant}),")));
3094 group_params.push(variant.clone());
3095 reader_assoc.push(Line(format!("type {variant}: {nested}::Reader<'a>;")));
3096 builder_assoc.push(Line(format!("type {variant}: {nested}::Builder<'a>;")));
3097 builder_methods.push(Line(format!("fn init_{name}(self) -> Self::{variant};")));
3098 } else {
3099 let (payload, _, _) = getter_text(ctx, &field, true, false)?;
3100 if let field::Slot(s) = field.which()? {
3101 if s.get_type()?.is_pointer()? {
3102 needs_lifetime = true;
3103 }
3104 }
3105 variants.push(Line(format!("{variant}({payload}),")));
3106 for m in newtype_trait_methods(ctx, &field, true, false)? {
3107 reader_methods.push(Line(format!("fn {};", m.signature)));
3108 }
3109 for m in newtype_trait_methods(ctx, &field, false, false)? {
3110 builder_methods.push(Line(format!("fn {};", m.signature)));
3111 }
3112 }
3113 }
3114
3115 let which_generics = union_which_generics(needs_lifetime, &group_params);
3116 let self_params: Vec<String> = group_params.iter().map(|p| format!("Self::{p}")).collect();
3117 let which_ret = union_which_generics(needs_lifetime, &self_params);
3118
3119 let mut reader_items = reader_assoc;
3120 reader_items.push(Line(format!(
3121 "fn which(&self) -> ::core::result::Result<Which{which_ret}, ::capnp::NotInSchema>;"
3122 )));
3123 reader_items.extend(reader_methods);
3124 let mut builder_items = builder_assoc;
3125 builder_items.extend(builder_methods);
3126
3127 let mut module_items = vec![
3128 Branch(vec![
3129 Line(format!("pub enum Which{which_generics} {{")),
3130 indent(variants),
3131 line("}"),
3132 ]),
3133 line("pub trait Reader<'a> {"),
3134 indent(reader_items),
3135 line("}"),
3136 line("pub trait Builder<'a> {"),
3137 indent(builder_items),
3138 line("}"),
3139 ];
3140 module_items.extend(union_any_reader_items(ctx, template_id)?);
3141 module_items.extend(union_any_builder_items(ctx, template_id)?);
3142
3143 Ok(Branch(vec![
3144 BlankLine,
3145 Line(format!("pub mod {} {{", module_name(node_name))),
3146 indent(module_items),
3147 line("}"),
3148 ]))
3149}
3150
3151fn generate_union_newtype_impl(
3155 ctx: &GeneratorContext,
3156 alias_id: u64,
3157 instance_id: u64,
3158) -> ::capnp::Result<FormattedText> {
3159 use capnp::schema_capnp::*;
3160 let Some(template_id) = union_newtype_template_id(ctx, alias_id)? else {
3161 return Ok(Branch(vec![]));
3162 };
3163 let node::Struct(tmpl) = ctx.node_map[&template_id].which()? else {
3164 return Ok(Branch(vec![]));
3165 };
3166 let node::Struct(instance) = ctx.node_map[&instance_id].which()? else {
3167 return Ok(Branch(vec![]));
3168 };
3169
3170 let mut instance_fields = ::std::collections::HashMap::new();
3171 for field in instance.get_fields()? {
3172 instance_fields.insert(field.get_name()?.to_str()?.to_string(), field);
3173 }
3174
3175 let trait_path = ctx.get_qualified_module(alias_id);
3176 let concrete = ctx.get_qualified_module(instance_id);
3177
3178 let mut which_arms = Vec::new();
3179 let mut group_params = Vec::new();
3180 let mut reader_assoc = Vec::new();
3181 let mut reader_methods = Vec::new();
3182 let mut builder_assoc = Vec::new();
3183 let mut builder_methods = Vec::new();
3184 let mut needs_lifetime = false;
3185 for field in tmpl.get_fields()? {
3186 let raw_name = field.get_name()?.to_str()?;
3187 let Some(inst_field) = instance_fields.get(raw_name) else {
3188 return Ok(Branch(vec![]));
3189 };
3190 let variant = capitalize_first_letter(raw_name);
3191 let name = camel_to_snake_case(raw_name);
3192 which_arms.push(Line(format!(
3193 "{concrete}::Which::{variant}(x) => {trait_path}::Which::{variant}(x),"
3194 )));
3195 if let field::Group(_) = field.which()? {
3196 let field::Group(inst_group) = inst_field.which()? else {
3197 return Ok(Branch(vec![]));
3198 };
3199 let inst_mod = ctx.get_qualified_module(inst_group.get_type_id());
3200 group_params.push(variant.clone());
3201 reader_assoc.push(Line(format!("type {variant} = {inst_mod}::Reader<'a>;")));
3202 builder_assoc.push(Line(format!("type {variant} = {inst_mod}::Builder<'a>;")));
3203 builder_methods.push(Line(format!(
3204 "fn init_{name}(self) -> Self::{variant} {{ self.init_{name}() }}"
3205 )));
3206 } else {
3207 if let field::Slot(s) = field.which()? {
3208 if s.get_type()?.is_pointer()? {
3209 needs_lifetime = true;
3210 }
3211 }
3212 for m in newtype_trait_methods(ctx, &field, true, false)? {
3213 let recv = if m.deref_self { "(*self)" } else { "self" };
3214 reader_methods.push(Line(format!(
3215 "fn {} {{ {recv}.{}({}) }}",
3216 m.signature, m.call_name, m.call_args
3217 )));
3218 }
3219 for m in newtype_trait_methods(ctx, &field, false, false)? {
3220 let recv = if m.deref_self { "(*self)" } else { "self" };
3221 builder_methods.push(Line(format!(
3222 "fn {} {{ {recv}.{}({}) }}",
3223 m.signature, m.call_name, m.call_args
3224 )));
3225 }
3226 }
3227 }
3228 let self_params: Vec<String> = group_params.iter().map(|p| format!("Self::{p}")).collect();
3229 let which_ret = union_which_generics(needs_lifetime, &self_params);
3230
3231 let which_method = Branch(vec![
3232 Line(format!(
3233 "fn which(&self) -> ::core::result::Result<{trait_path}::Which{which_ret}, ::capnp::NotInSchema> {{"
3234 )),
3235 indent(vec![
3236 line("::core::result::Result::Ok(match (*self).which()? {"),
3237 indent(which_arms),
3238 line("})"),
3239 ]),
3240 line("}"),
3241 ]);
3242
3243 let mut reader_items = reader_assoc;
3244 reader_items.push(which_method);
3245 reader_items.extend(reader_methods);
3246 let mut builder_items = builder_assoc;
3247 builder_items.extend(builder_methods);
3248
3249 let mut offsets = Vec::new();
3251 collect_leaf_offsets(ctx, template_id, instance_id, &mut offsets)?;
3252 let n = offsets.len();
3253 let disc = instance.get_discriminant_offset();
3254 let table = format!(
3255 "{}_OFFSETS",
3256 camel_to_snake_case(ctx.get_last_name(instance_id)?).to_ascii_uppercase()
3257 );
3258 let any_items = vec![
3259 BlankLine,
3260 Line(format!(
3261 "static {table}: [u32; {n}] = [{}];",
3262 offsets.join(", ")
3263 )),
3264 Line(format!("impl<'a> {concrete}::Reader<'a> {{")),
3265 indent(Line(fmt!(ctx,
3266 "pub fn as_any(self) -> {trait_path}::AnyReader<'a> {{ {trait_path}::AnyReader::new({capnp}::traits::IntoInternalStructReader::into_internal_struct_reader(self), {disc}, &{table}) }}"
3267 ))),
3268 line("}"),
3269 Line(format!("impl<'a> {concrete}::Builder<'a> {{")),
3270 indent(Line(fmt!(ctx,
3271 "pub fn as_any(self) -> {trait_path}::AnyBuilder<'a> {{ {trait_path}::AnyBuilder::new({capnp}::traits::IntoInternalStructBuilder::into_internal_struct_builder(self), {disc}, &{table}) }}"
3272 ))),
3273 line("}"),
3274 ];
3275
3276 Ok(Branch(vec![
3277 BlankLine,
3278 Line(format!(
3279 "impl<'a> {trait_path}::Reader<'a> for {concrete}::Reader<'a> {{"
3280 )),
3281 indent(reader_items),
3282 line("}"),
3283 BlankLine,
3284 Line(format!(
3285 "impl<'a> {trait_path}::Builder<'a> for {concrete}::Builder<'a> {{"
3286 )),
3287 indent(builder_items),
3288 line("}"),
3289 Branch(any_items),
3290 ]))
3291}
3292
3293fn generate_scalar_newtype_alias(
3298 ctx: &GeneratorContext,
3299 node_id: u64,
3300 node_name: &str,
3301 t: schema_capnp::type_::Reader,
3302) -> ::capnp::Result<FormattedText> {
3303 use capnp::schema_capnp::*;
3304 if newtype_template_id(ctx, node_id)?.is_some() {
3305 return Ok(Branch(vec![]));
3306 }
3307 if matches!(t.which()?, type_::Struct(_) | type_::Interface(_)) {
3308 return Ok(Branch(vec![]));
3309 }
3310 let module = module_name(node_name);
3311 let items = if t.is_pointer()? {
3312 vec![
3313 Line(format!(
3314 "pub type Reader<'a> = {};",
3315 t.type_string(ctx, Leaf::Reader("'a"))?
3316 )),
3317 Line(format!(
3318 "pub type Builder<'a> = {};",
3319 t.type_string(ctx, Leaf::Builder("'a"))?
3320 )),
3321 Line(format!(
3322 "pub type Owned = {};",
3323 t.type_string(ctx, Leaf::Owned)?
3324 )),
3325 ]
3326 } else {
3327 let v = t.type_string(ctx, Leaf::Reader(""))?;
3328 vec![
3329 Line(format!("pub type Reader = {v};")),
3330 Line(format!("pub type Builder = {v};")),
3331 Line(format!("pub type Owned = {v};")),
3332 ]
3333 };
3334 Ok(Branch(vec![
3335 BlankLine,
3336 Line(format!("pub mod {module} {{")),
3337 indent(items),
3338 line("}"),
3339 ]))
3340}
3341
3342fn generate_node(
3343 ctx: &GeneratorContext,
3344 node_id: u64,
3345 node_name: &str,
3346) -> ::capnp::Result<FormattedText> {
3347 use capnp::schema_capnp::*;
3348
3349 let mut output: Vec<FormattedText> = Vec::new();
3350 let mut nested_output: Vec<FormattedText> = Vec::new();
3351
3352 let node_reader = &ctx.node_map[&node_id];
3353 let nested_nodes = node_reader.get_nested_nodes()?;
3354 for nested_node in nested_nodes {
3355 let id = nested_node.get_id();
3356 nested_output.push(generate_node(ctx, id, ctx.get_last_name(id)?)?);
3357 }
3358
3359 match node_reader.which()? {
3360 node::Type(Ok(t)) => {
3361 output.push(generate_newtype_trait(ctx, node_id, node_name)?);
3362 output.push(generate_scalar_newtype_alias(ctx, node_id, node_name, t)?);
3363 }
3364 node::Type(Err(e)) => {
3365 return Err(Error::failed(format!("error reading node type: {e}")));
3366 }
3367 node::File(()) => {
3368 output.push(Branch(nested_output));
3369 }
3370 node::Struct(struct_reader) => {
3371 let params = node_reader.parameters_texts(ctx);
3372 output.push(BlankLine);
3373
3374 let is_generic = node_reader.get_is_generic();
3375 if is_generic {
3376 output.push(Line(format!(
3377 "pub mod {} {{ /* {} */",
3378 node_name,
3379 params.expanded_list.join(",")
3380 )));
3381 } else {
3382 output.push(Line(format!("pub mod {node_name} {{")));
3383 }
3384 let bracketed_params = if params.params.is_empty() {
3385 "".to_string()
3386 } else {
3387 format!("<{}>", params.params)
3388 };
3389
3390 let mut preamble = Vec::new();
3391 let mut builder_members = Vec::new();
3392 let mut reader_members = Vec::new();
3393 let mut union_fields = Vec::new();
3394 let mut which_enums = Vec::new();
3395 let mut pipeline_impl_interior = Vec::new();
3396 let mut private_mod_interior = Vec::new();
3397
3398 let data_size = struct_reader.get_data_word_count();
3399 let pointer_size = struct_reader.get_pointer_count();
3400 let discriminant_count = struct_reader.get_discriminant_count();
3401 let discriminant_offset = struct_reader.get_discriminant_offset();
3402
3403 private_mod_interior.push(crate::pointer_constants::node_word_array_declaration(
3404 ctx,
3405 "ENCODED_NODE",
3406 *node_reader,
3407 crate::pointer_constants::WordArrayDeclarationOptions { pub_crate: true },
3408 )?);
3409
3410 private_mod_interior.push(generate_get_field_types(ctx, *node_reader)?);
3411 private_mod_interior.push(generate_get_annotation_types(ctx, *node_reader)?);
3412
3413 private_mod_interior.push(Branch(vec![
3416 Line(fmt!(ctx, "pub(crate) static ARENA: {capnp}::private::arena::GeneratedCodeArena = {capnp}::private::arena::GeneratedCodeArena::new(&ENCODED_NODE);")),
3417 Line(fmt!(ctx,"pub(crate) static RAW_SCHEMA: {capnp}::introspect::RawStructSchema = {capnp}::introspect::RawStructSchema::new(")),
3418 indent(vec![
3419 Line("&ARENA,".into()),
3420 Line("NONUNION_MEMBERS,".into()),
3421 Line("MEMBERS_BY_DISCRIMINANT,".into()),
3422 Line("MEMBERS_BY_NAME".into()),
3423 ]),
3424 Line(");".into()),
3425 ]));
3426
3427 private_mod_interior.push(generate_members_by_discriminant(*node_reader)?);
3428 private_mod_interior.push(generate_members_by_name(*node_reader)?);
3429
3430 let mut has_pointer_field = false;
3431 let fields = struct_reader.get_fields()?;
3432 for field in fields {
3433 let name = get_field_name(field)?;
3434 let styled_name = camel_to_snake_case(name);
3435
3436 let discriminant_value = field.get_discriminant_value();
3437 let is_union_field = discriminant_value != field::NO_DISCRIMINANT;
3438
3439 match field.which()? {
3440 field::Slot(s) => match s.get_type()?.which()? {
3441 type_::Text(())
3442 | type_::Data(())
3443 | type_::List(_)
3444 | type_::Struct(_)
3445 | type_::Interface(_)
3446 | type_::AnyPointer(_) => has_pointer_field = true,
3447 _ => (),
3448 },
3449 field::Group(_) => has_pointer_field = true,
3450 }
3451
3452 if !is_union_field {
3453 pipeline_impl_interior.push(generate_pipeline_getter(ctx, field)?);
3454 let (ty, get, default_decl) = getter_text(ctx, &field, true, true)?;
3455 if let Some(default) = default_decl {
3456 private_mod_interior.push(default.clone());
3457 }
3458 reader_members.push(Branch(vec![
3459 line("#[inline]"),
3460 Line(format!("pub fn get_{styled_name}(self) {ty} {{")),
3461 indent(get),
3462 line("}"),
3463 ]));
3464
3465 let (ty_b, get_b, _) = getter_text(ctx, &field, false, true)?;
3466 builder_members.push(Branch(vec![
3467 line("#[inline]"),
3468 Line(format!("pub fn get_{styled_name}(self) {ty_b} {{")),
3469 indent(get_b),
3470 line("}"),
3471 ]));
3472 } else {
3473 union_fields.push(field);
3474 }
3475
3476 builder_members.push(generate_setter(
3477 ctx,
3478 discriminant_offset,
3479 &styled_name,
3480 &field,
3481 )?);
3482
3483 reader_members.push(generate_haser(
3484 discriminant_offset,
3485 &styled_name,
3486 &field,
3487 true,
3488 )?);
3489 builder_members.push(generate_haser(
3490 discriminant_offset,
3491 &styled_name,
3492 &field,
3493 false,
3494 )?);
3495
3496 if let Ok(field::Group(group)) = field.which() {
3497 let id = group.get_type_id();
3498 let text = generate_node(ctx, id, ctx.get_last_name(id)?)?;
3499 nested_output.push(text);
3500
3501 let alias_id = field.get_type_id();
3504 if alias_id != 0 {
3505 nested_output.push(generate_newtype_impl(ctx, alias_id, id)?);
3506 }
3507 }
3508 }
3509
3510 if discriminant_count > 0 {
3511 let (which_enums1, union_getter, typedef, mut default_decls) =
3512 generate_union(ctx, discriminant_offset, &union_fields, true, ¶ms)?;
3513 which_enums.push(which_enums1);
3514 which_enums.push(typedef);
3515 reader_members.push(union_getter);
3516
3517 private_mod_interior.append(&mut default_decls);
3518
3519 let (_, union_getter, typedef, _) =
3520 generate_union(ctx, discriminant_offset, &union_fields, false, ¶ms)?;
3521 which_enums.push(typedef);
3522 builder_members.push(union_getter);
3523
3524 let mut reexports = String::new();
3525 reexports.push_str("pub use self::Which::{");
3526 let mut whichs = Vec::new();
3527 for f in &union_fields {
3528 whichs.push(capitalize_first_letter(get_field_name(*f)?));
3529 }
3530 reexports.push_str(&whichs.join(","));
3531 reexports.push_str("};");
3532 preamble.push(Line(reexports));
3533 preamble.push(BlankLine);
3534 }
3535
3536 let builder_struct_size =
3537 Branch(vec![
3538 Line(fmt!(ctx,"impl <{0}> {capnp}::traits::HasStructSize for Builder<'_,{0}> {1} {{",
3539 params.params, params.where_clause)),
3540 indent(Line(
3541 fmt!(ctx,"const STRUCT_SIZE: {capnp}::private::layout::StructSize = {capnp}::private::layout::StructSize {{ data: {}, pointers: {} }};", data_size as usize, pointer_size as usize))),
3542 line("}")]);
3543
3544 private_mod_interior.push(Line(format!(
3545 "pub(crate) const TYPE_ID: u64 = {};",
3546 format_u64(node_id)
3547 )));
3548
3549 let from_pointer_builder_impl =
3550 Branch(vec![
3551 Line(fmt!(ctx,"impl <'a,{0}> {capnp}::traits::FromPointerBuilder<'a> for Builder<'a,{0}> {1} {{", params.params, params.where_clause)),
3552 indent(vec![
3553 Line(fmt!(ctx,"fn init_pointer(builder: {capnp}::private::layout::PointerBuilder<'a>, _size: u32) -> Self {{")),
3554 indent(Line(fmt!(ctx,"builder.init_struct(<Self as {capnp}::traits::HasStructSize>::STRUCT_SIZE).into()"))),
3555 line("}"),
3556 Line(fmt!(ctx,"fn get_from_pointer(builder: {capnp}::private::layout::PointerBuilder<'a>, default: ::core::option::Option<&'a [{capnp}::Word]>) -> {capnp}::Result<Self> {{")),
3557 indent(Line(fmt!(ctx,"::core::result::Result::Ok(builder.get_struct(<Self as {capnp}::traits::HasStructSize>::STRUCT_SIZE, default)?.into())"))),
3558 line("}")
3559 ]),
3560 line("}"),
3561 BlankLine]);
3562
3563 let accessors = vec![
3564 Branch(preamble),
3565 (if !is_generic {
3566 Branch(vec![
3567 Line("#[derive(Copy, Clone)]".into()),
3568 line("pub struct Owned(());"),
3569 Line(fmt!(ctx,"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, type_id: ::core::any::TypeId::of::<Owned>() }}).into() }} }}")),
3570 Line(fmt!(ctx, "impl {capnp}::traits::Owned for Owned {{ type Reader<'a> = Reader<'a>; type Builder<'a> = Builder<'a>; }}")),
3571 Line(fmt!(ctx,"impl {capnp}::traits::OwnedStruct for Owned {{ type Reader<'a> = Reader<'a>; type Builder<'a> = Builder<'a>; }}")),
3572 Line(fmt!(ctx,"impl {capnp}::traits::Pipelined for Owned {{ type Pipeline = Pipeline; }}"))
3573 ])
3574 } else {
3575 Branch(vec![
3576 Line("#[derive(Copy, Clone)]".into()),
3577 Line(format!("pub struct Owned<{}> {{", params.params)),
3578 indent(Line(params.phantom_data_type.clone())),
3579 line("}"),
3580 Line(fmt!(ctx,"impl <{0}> {capnp}::introspect::Introspect for Owned <{0}> {1} {{ fn introspect() -> {capnp}::introspect::Type {{ {capnp}::introspect::TypeVariant::Struct({capnp}::introspect::RawBrandedStructSchema {{ generic: &_private::RAW_SCHEMA, field_types: _private::get_field_types::<{0}>, annotation_types: _private::get_annotation_types::<{0}>, type_id: ::core::any::TypeId::of::<Owned<{0}>>() }}).into() }} }}",
3581 params.params, params.where_clause)),
3582 Line(fmt!(ctx,"impl <{0}> {capnp}::traits::Owned for Owned <{0}> {1} {{ type Reader<'a> = Reader<'a, {0}>; type Builder<'a> = Builder<'a, {0}>; }}",
3583 params.params, params.where_clause)),
3584 Line(fmt!(ctx,"impl <{0}> {capnp}::traits::OwnedStruct for Owned <{0}> {1} {{ type Reader<'a> = Reader<'a, {0}>; type Builder<'a> = Builder<'a, {0}>; }}",
3585 params.params, params.where_clause)),
3586 Line(fmt!(ctx,"impl <{0}> {capnp}::traits::Pipelined for Owned<{0}> {1} {{ type Pipeline = Pipeline{2}; }}",
3587 params.params, params.where_clause, bracketed_params)),
3588 ])
3589 }),
3590 BlankLine,
3591 (if !is_generic {
3592 Line(fmt!(ctx,"pub struct Reader<'a> {{ reader: {capnp}::private::layout::StructReader<'a> }}"))
3593 } else {
3594 Branch(vec![
3595 Line(format!("pub struct Reader<'a,{}> {} {{", params.params, params.where_clause)),
3596 indent(vec![
3597 Line(fmt!(ctx,"reader: {capnp}::private::layout::StructReader<'a>,")),
3598 Line(params.phantom_data_type.clone()),
3599 ]),
3600 line("}")
3601 ])
3602 }),
3603 Branch(vec![
3606 Line(format!("impl <{0}> ::core::marker::Copy for Reader<'_,{0}> {1} {{}}",
3607 params.params, params.where_clause)),
3608 Line(format!("impl <{0}> ::core::clone::Clone for Reader<'_,{0}> {1} {{",
3609 params.params, params.where_clause)),
3610 indent(Line("fn clone(&self) -> Self { *self }".into())),
3611 Line("}".into())]),
3612 BlankLine,
3613 Branch(vec![
3614 Line(fmt!(ctx,"impl <{0}> {capnp}::traits::HasTypeId for Reader<'_,{0}> {1} {{",
3615 params.params, params.where_clause)),
3616 indent(vec![line("const TYPE_ID: u64 = _private::TYPE_ID;")]),
3617 line("}")]),
3618 Line(fmt!(ctx,"impl <'a,{0}> ::core::convert::From<{capnp}::private::layout::StructReader<'a>> for Reader<'a,{0}> {1} {{",
3619 params.params, params.where_clause)),
3620 indent(vec![
3621 Line(fmt!(ctx,"fn from(reader: {capnp}::private::layout::StructReader<'a>) -> Self {{")),
3622 indent(Line(format!("Self {{ reader, {} }}", params.phantom_data_value))),
3623 line("}")
3624 ]),
3625 line("}"),
3626 BlankLine,
3627 Line(fmt!(ctx,"impl <'a,{0}> ::core::convert::From<Reader<'a,{0}>> for {capnp}::dynamic_value::Reader<'a> {1} {{",
3628 params.params, params.where_clause)),
3629 indent(vec![
3630 Line(format!("fn from(reader: Reader<'a,{0}>) -> Self {{", params.params)),
3631 indent(Line(fmt!(ctx,"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::<{0}>, annotation_types: _private::get_annotation_types::<{0}>, type_id: ::core::any::TypeId::of::<Owned<{0}>>()}})))", params.params))),
3632 line("}")
3633 ]),
3634 line("}"),
3635 BlankLine,
3636 Line(format!("impl <{0}> ::core::fmt::Debug for Reader<'_,{0}> {1} {{",
3637 params.params, params.where_clause)),
3638 indent(vec![
3639 Line("fn fmt(&self, f: &mut ::core::fmt::Formatter<'_>) -> ::core::result::Result<(), ::core::fmt::Error> {".into()),
3640 indent(Line(fmt!(ctx,"core::fmt::Debug::fmt(&::core::convert::Into::<{capnp}::dynamic_value::Reader<'_>>::into(*self), f)"))),
3641 line("}")
3642 ]),
3643 line("}"),
3644
3645 BlankLine,
3646
3647 Line(fmt!(ctx,"impl <'a,{0}> {capnp}::traits::FromPointerReader<'a> for Reader<'a,{0}> {1} {{",
3648 params.params, params.where_clause)),
3649 indent(vec![
3650 Line(fmt!(ctx,"fn get_from_pointer(reader: &{capnp}::private::layout::PointerReader<'a>, default: ::core::option::Option<&'a [{capnp}::Word]>) -> {capnp}::Result<Self> {{")),
3651 indent(line("::core::result::Result::Ok(reader.get_struct(default)?.into())")),
3652 line("}")
3653 ]),
3654 line("}"),
3655 BlankLine,
3656 Line(fmt!(ctx,"impl <'a,{0}> {capnp}::traits::IntoInternalStructReader<'a> for Reader<'a,{0}> {1} {{",
3657 params.params, params.where_clause)),
3658 indent(vec![
3659 Line(fmt!(ctx,"fn into_internal_struct_reader(self) -> {capnp}::private::layout::StructReader<'a> {{")),
3660 indent(line("self.reader")),
3661 line("}")
3662 ]),
3663 line("}"),
3664 BlankLine,
3665 Line(fmt!(ctx,"impl <'a,{0}> {capnp}::traits::Imbue<'a> for Reader<'a,{0}> {1} {{",
3666 params.params, params.where_clause)),
3667 indent(vec![
3668 Line(fmt!(ctx,"fn imbue(&mut self, cap_table: &'a {capnp}::private::layout::CapTable) {{")),
3669 indent(Line(fmt!(ctx,"self.reader.imbue({capnp}::private::layout::CapTableReader::from_ref(cap_table))"))),
3670 line("}")
3671 ]),
3672 line("}"),
3673 BlankLine,
3674 if has_pointer_field { Line(format!("impl <'a,{0}> Reader<'a,{0}> {1} {{", params.params, params.where_clause))
3676 } else {
3677 Line(format!("impl <{0}> Reader<'_,{0}> {1} {{", params.params, params.where_clause))
3678 },
3679 indent(vec![
3680 Line(format!("pub fn reborrow(&self) -> Reader<'_,{}> {{",params.params)),
3681 indent(line("Self { .. *self }")),
3682 line("}"),
3683 BlankLine,
3684 Line(fmt!(ctx,"pub fn total_size(&self) -> {capnp}::Result<{capnp}::MessageSize> {{")),
3685 indent(line("self.reader.total_size()")),
3686 line("}")]),
3687 indent(reader_members),
3688 line("}"),
3689 BlankLine,
3690 (if !is_generic {
3691 Line(fmt!(ctx,"pub struct Builder<'a> {{ builder: {capnp}::private::layout::StructBuilder<'a> }}"))
3692 } else {
3693 Branch(vec![
3694 Line(format!("pub struct Builder<'a,{}> {} {{",
3695 params.params, params.where_clause)),
3696 indent(vec![
3697 Line(fmt!(ctx, "builder: {capnp}::private::layout::StructBuilder<'a>,")),
3698 Line(params.phantom_data_type.clone()),
3699 ]),
3700 line("}")
3701 ])
3702 }),
3703 builder_struct_size,
3704 Branch(vec![
3705 Line(fmt!(ctx,"impl <{0}> {capnp}::traits::HasTypeId for Builder<'_,{0}> {1} {{",
3706 params.params, params.where_clause)),
3707 indent(vec![
3708 line("const TYPE_ID: u64 = _private::TYPE_ID;")]),
3709 line("}")
3710 ]),
3711 Line(fmt!(ctx,
3712 "impl <'a,{0}> ::core::convert::From<{capnp}::private::layout::StructBuilder<'a>> for Builder<'a,{0}> {1} {{",
3713 params.params, params.where_clause)),
3714 indent(vec![
3715 Line(fmt!(ctx,"fn from(builder: {capnp}::private::layout::StructBuilder<'a>) -> Self {{")),
3716 indent(Line(format!("Self {{ builder, {} }}", params.phantom_data_value))),
3717 line("}")
3718 ]),
3719 line("}"),
3720 BlankLine,
3721 Line(fmt!(ctx,"impl <'a,{0}> {capnp}::traits::IntoInternalStructBuilder<'a> for Builder<'a,{0}> {1} {{",
3722 params.params, params.where_clause)),
3723 indent(vec![
3724 Line(fmt!(ctx,"fn into_internal_struct_builder(self) -> {capnp}::private::layout::StructBuilder<'a> {{")),
3725 indent(line("self.builder")),
3726 line("}")
3727 ]),
3728 line("}"),
3729 BlankLine,
3730 Line(fmt!(ctx,"impl <'a,{0}> ::core::convert::From<Builder<'a,{0}>> for {capnp}::dynamic_value::Builder<'a> {1} {{",
3731 params.params, params.where_clause)),
3732 indent(vec![
3733 Line(format!("fn from(builder: Builder<'a,{0}>) -> Self {{", params.params)),
3734 indent(Line(fmt!(ctx,"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::<{0}>, annotation_types: _private::get_annotation_types::<{0}>, type_id: ::core::any::TypeId::of::<Owned<{0}>>()}})))", params.params))),
3735 line("}")
3736 ]),
3737 line("}"),
3738 BlankLine,
3739
3740 Line(fmt!(ctx,"impl <'a,{0}> {capnp}::traits::ImbueMut<'a> for Builder<'a,{0}> {1} {{",
3741 params.params, params.where_clause)),
3742 indent(vec![
3743 Line(fmt!(ctx,"fn imbue_mut(&mut self, cap_table: &'a mut {capnp}::private::layout::CapTable) {{")),
3744 indent(Line(fmt!(ctx,"self.builder.imbue({capnp}::private::layout::CapTableBuilder::from_ref(cap_table))"))),
3745 line("}")]),
3746 line("}"),
3747 BlankLine,
3748
3749 from_pointer_builder_impl,
3750 Line(fmt!(ctx,
3751 "impl <{0}> {capnp}::traits::SetterInput<Owned<{0}>> for Reader<'_,{0}> {1} {{",
3752 params.params, params.where_clause)),
3753 indent(Line(fmt!(ctx,"fn set_pointer_builder(mut pointer: {capnp}::private::layout::PointerBuilder<'_>, value: Self, canonicalize: bool) -> {capnp}::Result<()> {{ pointer.set_struct(&value.reader, canonicalize) }}"))),
3754 line("}"),
3755 BlankLine,
3756 Line(format!("impl <'a,{0}> Builder<'a,{0}> {1} {{", params.params, params.where_clause)),
3757 indent(vec![
3758 Line(format!("pub fn into_reader(self) -> Reader<'a,{}> {{", params.params)),
3759 indent(line("self.builder.into_reader().into()")),
3760 line("}"),
3761 Line(format!("pub fn reborrow(&mut self) -> Builder<'_,{}> {{", params.params)),
3762 (if !is_generic {
3763 indent(line("Builder { builder: self.builder.reborrow() }"))
3764 } else {
3765 indent(line("Builder { builder: self.builder.reborrow(), ..*self }"))
3766 }),
3767 line("}"),
3768 Line(format!("pub fn reborrow_as_reader(&self) -> Reader<'_,{}> {{", params.params)),
3769 indent(line("self.builder.as_reader().into()")),
3770 line("}"),
3771
3772 BlankLine,
3773 Line(fmt!(ctx,"pub fn total_size(&self) -> {capnp}::Result<{capnp}::MessageSize> {{")),
3774 indent(line("self.builder.as_reader().total_size()")),
3775 line("}")
3776 ]),
3777 indent(builder_members),
3778 line("}"),
3779 BlankLine,
3780 (if is_generic {
3781 Branch(vec![
3782 Line(format!("pub struct Pipeline{bracketed_params} {{")),
3783 indent(vec![
3784 Line(fmt!(ctx,"_typeless: {capnp}::any_pointer::Pipeline,")),
3785 Line(params.phantom_data_type),
3786 ]),
3787 line("}")
3788 ])
3789 } else {
3790 Line(fmt!(ctx,"pub struct Pipeline {{ _typeless: {capnp}::any_pointer::Pipeline }}"))
3791 }),
3792 Line(fmt!(ctx,"impl{bracketed_params} {capnp}::capability::FromTypelessPipeline for Pipeline{bracketed_params} {{")),
3793 indent(vec![
3794 Line(fmt!(ctx,"fn new(typeless: {capnp}::any_pointer::Pipeline) -> Self {{")),
3795 indent(Line(format!("Self {{ _typeless: typeless, {} }}", params.phantom_data_value))),
3796 line("}")]),
3797 line("}"),
3798 Line(format!("impl{0} Pipeline{0} {1} {{", bracketed_params,
3799 params.pipeline_where_clause)),
3800 indent(pipeline_impl_interior),
3801 line("}"),
3802 line("mod _private {"),
3803 indent(private_mod_interior),
3804 line("}"),
3805 ];
3806
3807 output.push(indent(vec![
3808 Branch(accessors),
3809 Branch(which_enums),
3810 Branch(nested_output),
3811 ]));
3812 output.push(line("}"));
3813 }
3814
3815 node::Enum(enum_reader) => {
3816 let last_name = ctx.get_last_name(node_id)?;
3817 let name_as_mod = module_name(last_name);
3818 output.push(BlankLine);
3819
3820 let mut members = Vec::new();
3821 let mut match_branches = Vec::new();
3822 let enumerants = enum_reader.get_enumerants()?;
3823 for (ii, enumerant) in enumerants.into_iter().enumerate() {
3824 let enumerant = capitalize_first_letter(get_enumerant_name(enumerant)?);
3825 members.push(Line(format!("{enumerant} = {ii},")));
3826 match_branches.push(Line(format!(
3827 "{ii} => ::core::result::Result::Ok(Self::{enumerant}),"
3828 )));
3829 }
3830 match_branches.push(Line(fmt!(
3831 ctx,
3832 "n => ::core::result::Result::Err({capnp}::NotInSchema(n)),"
3833 )));
3834
3835 output.push(Branch(vec![
3836 line("#[repr(u16)]"),
3837 line("#[derive(Clone, Copy, Debug, PartialEq, Eq)]"),
3838 Line(format!("pub enum {last_name} {{")),
3839 indent(members),
3840 line("}"),
3841 ]));
3842
3843 output.push(BlankLine);
3844 output.push(Branch(vec![
3845 Line(fmt!(ctx,
3846 "impl {capnp}::introspect::Introspect for {last_name} {{"
3847 )),
3848 indent(Line(fmt!(ctx,
3849 "fn introspect() -> {capnp}::introspect::Type {{ {capnp}::introspect::TypeVariant::Enum({capnp}::introspect::RawEnumSchema::new(&{0}::ARENA, {0}::get_annotation_types)).into() }}", name_as_mod))),
3850 Line("}".into()),
3851 ]));
3852
3853 output.push(Branch(vec![
3854 Line(fmt!(ctx,"impl ::core::convert::From<{last_name}> for {capnp}::dynamic_value::Reader<'_> {{")),
3855 indent(Line(fmt!(ctx,
3856 "fn from(e: {last_name}) -> Self {{ {capnp}::dynamic_value::Enum::new(e.into(), {capnp}::introspect::RawEnumSchema::new(&{0}::ARENA, {0}::get_annotation_types).into()).into() }}", name_as_mod ))),
3857 Line("}".into())
3858 ]));
3859
3860 output.push(Branch(vec![
3861 Line(format!(
3862 "impl ::core::convert::TryFrom<u16> for {last_name} {{"
3863 )),
3864 indent(Line(
3865 fmt!(ctx,"type Error = {capnp}::NotInSchema;"),
3866 )),
3867 indent(vec![
3868 Line(
3869 format!("fn try_from(value: u16) -> ::core::result::Result<Self, <{last_name} as ::core::convert::TryFrom<u16>>::Error> {{")
3870 ),
3871 indent(vec![
3872 line("match value {"),
3873 indent(match_branches),
3874 line("}"),
3875 ]),
3876 line("}"),
3877 ]),
3878 line("}"),
3879 Line(format!("impl From<{last_name}> for u16 {{")),
3880 indent(line("#[inline]")),
3881 indent(Line(format!(
3882 "fn from(x: {last_name}) -> u16 {{ x as u16 }}"
3883 ))),
3884 line("}"),
3885 ]));
3886
3887 output.push(Branch(vec![
3888 Line(fmt!(
3889 ctx,
3890 "impl {capnp}::traits::HasTypeId for {last_name} {{"
3891 )),
3892 indent(Line(format!(
3893 "const TYPE_ID: u64 = {}u64;",
3894 format_u64(node_id)
3895 ))),
3896 line("}"),
3897 ]));
3898
3899 output.push(Branch(vec![
3900 Line(format!("mod {name_as_mod} {{")),
3901 Branch(vec![
3902 crate::pointer_constants::node_word_array_declaration(
3903 ctx,
3904 "ENCODED_NODE",
3905 *node_reader,
3906 crate::pointer_constants::WordArrayDeclarationOptions { pub_crate: true },
3907 )?,
3908 generate_get_annotation_types(ctx, *node_reader)?,
3909 Line(fmt!(ctx, "pub(crate) static ARENA: {capnp}::private::arena::GeneratedCodeArena = {capnp}::private::arena::GeneratedCodeArena::new(&ENCODED_NODE);")),
3910 ]),
3911 Line("}".into()),
3912 ]));
3913 }
3914
3915 node::Interface(interface) => {
3916 let params = node_reader.parameters_texts(ctx);
3917 output.push(BlankLine);
3918
3919 let is_generic = node_reader.get_is_generic();
3920
3921 let names = &ctx.scope_map[&node_id];
3922 let mut client_impl_interior = Vec::new();
3923 let mut server_interior = Vec::new();
3924 let mut mod_interior = Vec::new();
3925 let mut dispatch_arms = Vec::new();
3926 let mut private_mod_interior = Vec::new();
3927
3928 let bracketed_params = if params.params.is_empty() {
3929 "".to_string()
3930 } else {
3931 format!("<{}>", params.params)
3932 };
3933
3934 private_mod_interior.push(Line(format!(
3935 "pub(crate) const TYPE_ID: u64 = {};",
3936 format_u64(node_id)
3937 )));
3938
3939 mod_interior.push(line("#![allow(unused_variables)]"));
3940
3941 let methods = interface.get_methods()?;
3942 for (ordinal, method) in methods.into_iter().enumerate() {
3943 let name = method.get_name()?.to_str()?;
3944
3945 let param_id = method.get_param_struct_type();
3946 let param_node = &ctx.node_map[¶m_id];
3947 let (param_scopes, params_ty_params) = if param_node.get_scope_id() == 0 {
3948 let mut names = names.clone();
3949 let local_name = module_name(&format!("{name}Params"));
3950 nested_output.push(generate_node(ctx, param_id, &local_name)?);
3951 names.push(local_name);
3952 (names, params.params.clone())
3953 } else {
3954 (
3955 ctx.scope_map[¶m_node.get_id()].clone(),
3956 get_ty_params_of_brand(ctx, method.get_param_brand()?)?,
3957 )
3958 };
3959 let param_type = do_branding(
3960 ctx,
3961 param_id,
3962 method.get_param_brand()?,
3963 Leaf::Owned,
3964 ¶m_scopes.join("::"),
3965 )?;
3966
3967 mod_interior.push(Line(fmt!(
3968 ctx,
3969 "pub type {}Params<{}> = {capnp}::capability::Params<{}>;",
3970 capitalize_first_letter(name),
3971 params_ty_params,
3972 param_type
3973 )));
3974
3975 let result_id = method.get_result_struct_type();
3976 if result_id != STREAM_RESULT_ID {
3977 dispatch_arms.push(
3978 Line(fmt!(ctx,
3979 "{ordinal} => {capnp}::capability::DispatchCallResult::new({capnp}::capability::Promise::from_future(<_T as Server{bracketed_params}>::{}(this, {capnp}::private::capability::internal_get_typed_params(params), {capnp}::private::capability::internal_get_typed_results(results))), false),",
3980 module_name(name))));
3981
3982 let result_node = &ctx.node_map[&result_id];
3983 let (result_scopes, results_ty_params) = if result_node.get_scope_id() == 0 {
3984 let mut names = names.clone();
3985 let local_name = module_name(&format!("{name}Results"));
3986 nested_output.push(generate_node(ctx, result_id, &local_name)?);
3987 names.push(local_name);
3988 (names, params.params.clone())
3989 } else {
3990 (
3991 ctx.scope_map[&result_node.get_id()].clone(),
3992 get_ty_params_of_brand(ctx, method.get_result_brand()?)?,
3993 )
3994 };
3995 let result_type = do_branding(
3996 ctx,
3997 result_id,
3998 method.get_result_brand()?,
3999 Leaf::Owned,
4000 &result_scopes.join("::"),
4001 )?;
4002 mod_interior.push(Line(fmt!(
4003 ctx,
4004 "pub type {}Results<{}> = {capnp}::capability::Results<{}>;",
4005 capitalize_first_letter(name),
4006 results_ty_params,
4007 result_type
4008 )));
4009 server_interior.push(
4010 Line(fmt!(ctx,
4011 "fn {}(self: {capnp}::capability::Rc<Self>, _: {}Params<{}>, _: {}Results<{}>) -> impl ::core::future::Future<Output = Result<(), {capnp}::Error>> + 'static {{ ::core::future::ready(Err({capnp}::Error::unimplemented(\"method {}::Server::{} not implemented\".to_string()))) }}",
4012 module_name(name),
4013 capitalize_first_letter(name), params_ty_params,
4014 capitalize_first_letter(name), results_ty_params,
4015 node_name, module_name(name)
4016 )));
4017
4018 client_impl_interior.push(Line(fmt!(
4019 ctx,
4020 "pub fn {}_request(&self) -> {capnp}::capability::Request<{},{}> {{",
4021 camel_to_snake_case(name),
4022 param_type,
4023 result_type
4024 )));
4025
4026 client_impl_interior.push(indent(Line(format!(
4027 "self.client.new_call(_private::TYPE_ID, {ordinal}, ::core::option::Option::None)"
4028 ))));
4029 client_impl_interior.push(line("}"));
4030 } else {
4031 dispatch_arms.push(
4033 Line(fmt!(ctx,
4034 "{ordinal} => {capnp}::capability::DispatchCallResult::new({capnp}::capability::Promise::from_future(<_T as Server{bracketed_params}>::{}(this, {capnp}::private::capability::internal_get_typed_params(params))), true),",
4035
4036 module_name(name))));
4037
4038 server_interior.push(
4039 Line(fmt!(ctx,
4040 "fn {}(self: {capnp}::capability::Rc<Self>, _: {}Params<{}>) -> impl ::core::future::Future<Output = Result<(), {capnp}::Error>> + 'static {{ ::core::future::ready(Err({capnp}::Error::unimplemented(\"method {}::Server::{} not implemented\".to_string()))) }}",
4041 module_name(name),
4042 capitalize_first_letter(name), params_ty_params,
4043 node_name, module_name(name)
4044 )));
4045 client_impl_interior.push(Line(fmt!(
4046 ctx,
4047 "pub fn {}_request(&self) -> {capnp}::capability::StreamingRequest<{}> {{",
4048 camel_to_snake_case(name),
4049 param_type
4050 )));
4051 client_impl_interior.push(indent(Line(format!(
4052 "self.client.new_streaming_call(_private::TYPE_ID, {ordinal}, ::core::option::Option::None)"
4053 ))));
4054
4055 client_impl_interior.push(line("}"));
4056 }
4057
4058 method.get_annotations()?;
4059 }
4060
4061 let mut base_dispatch_arms = Vec::new();
4062
4063 let server_base = {
4064 let mut base_traits = Vec::new();
4065
4066 fn find_super_interfaces<'a>(
4067 interface: schema_capnp::node::interface::Reader<'a>,
4068 all_extends: &mut Vec<
4069 <schema_capnp::superclass::Owned as capnp::traits::OwnedStruct>::Reader<'a>,
4070 >,
4071 ctx: &GeneratorContext<'a>,
4072 ) -> ::capnp::Result<()> {
4073 let extends = interface.get_superclasses()?;
4074 for superclass in extends {
4075 if let node::Interface(interface) =
4076 ctx.node_map[&superclass.get_id()].which()?
4077 {
4078 find_super_interfaces(interface, all_extends, ctx)?;
4079 }
4080 all_extends.push(superclass);
4081 }
4082 Ok(())
4083 }
4084
4085 let mut extends = Vec::new();
4086 find_super_interfaces(interface, &mut extends, ctx)?;
4087 for interface in &extends {
4088 let type_id = interface.get_id();
4089 let brand = interface.get_brand()?;
4090 let the_mod = ctx.get_qualified_module(type_id);
4091
4092 base_dispatch_arms.push(Line(format!(
4093 "0x{type_id:x} => {}::dispatch_call_internal(self.server, method_id, params, results),",
4094 do_branding(
4095 ctx, type_id, brand, Leaf::ServerDispatch, &the_mod)?)));
4096 base_traits.push(do_branding(ctx, type_id, brand, Leaf::Server, &the_mod)?);
4097 }
4098
4099 if !extends.is_empty() {
4102 format!(": {} + 'static", base_traits.join(" + "))
4103 } else {
4104 ": 'static".to_string()
4105 }
4106 };
4107
4108 mod_interior.push(BlankLine);
4109 mod_interior.push(Line(format!("pub struct Client{bracketed_params} {{")));
4110 mod_interior.push(indent(Line(fmt!(
4111 ctx,
4112 "pub client: {capnp}::capability::Client,"
4113 ))));
4114 if is_generic {
4115 mod_interior.push(indent(Line(params.phantom_data_type.clone())));
4116 }
4117 mod_interior.push(line("}"));
4118 mod_interior.push(
4119 Branch(vec![
4120 Line(fmt!(ctx,"impl {bracketed_params} {capnp}::capability::FromClientHook for Client{bracketed_params} {{")),
4121 indent(Line(fmt!(ctx,"fn new(hook: Box<{capnp}::capability::DynClientHook>) -> Self {{"))),
4122 indent(indent(Line(fmt!(ctx,"Self {{ client: {capnp}::capability::Client::new(hook), {} }}", params.phantom_data_value)))),
4123 indent(line("}")),
4124 indent(Line(fmt!(ctx,"fn into_client_hook(self) -> Box<{capnp}::capability::DynClientHook> {{"))),
4125 indent(indent(line("self.client.hook"))),
4126 indent(line("}")),
4127 indent(Line(fmt!(ctx,"fn as_client_hook(&self) -> &{capnp}::capability::DynClientHook {{"))),
4128 indent(indent(line("&*self.client.hook"))),
4129 indent(line("}")),
4130 line("}")]));
4131
4132 mod_interior.push(if !is_generic {
4133 Branch(vec![
4134 Line("#[derive(Copy, Clone)]".into()),
4135 line("pub struct Owned(());"),
4136 Line(fmt!(ctx,"impl {capnp}::introspect::Introspect for Owned {{ fn introspect() -> {capnp}::introspect::Type {{ {capnp}::introspect::TypeVariant::Capability.into() }} }}")),
4137 Line(fmt!(ctx,"impl {capnp}::traits::Owned for Owned {{ type Reader<'a> = Client; type Builder<'a> = Client; }}")),
4138 Line(fmt!(ctx,"impl {capnp}::traits::Pipelined for Owned {{ type Pipeline = Client; }}"))])
4139 } else {
4140 Branch(vec![
4141 Line("#[derive(Copy, Clone)]".into()),
4142 Line(format!("pub struct Owned<{}> {} {{", params.params, params.where_clause)),
4143 indent(Line(params.phantom_data_type.clone())),
4144 line("}"),
4145 Line(fmt!(ctx,
4146 "impl <{0}> {capnp}::introspect::Introspect for Owned <{0}> {1} {{ fn introspect() -> {capnp}::introspect::Type {{ {capnp}::introspect::TypeVariant::Capability.into() }} }}",
4147 params.params, params.where_clause)),
4148 Line(fmt!(ctx,
4149 "impl <{0}> {capnp}::traits::Owned for Owned <{0}> {1} {{ type Reader<'a> = Client<{0}>; type Builder<'a> = Client<{0}>; }}",
4150 params.params, params.where_clause)),
4151 Line(fmt!(ctx,
4152 "impl <{0}> {capnp}::traits::Pipelined for Owned <{0}> {1} {{ type Pipeline = Client{2}; }}",
4153 params.params, params.where_clause, bracketed_params))])
4154 });
4155
4156 mod_interior.push(Branch(vec![
4157 Line(fmt!(ctx,"impl <'a,{0}> {capnp}::traits::FromPointerReader<'a> for Client<{0}> {1} {{",
4158 params.params, params.where_clause)),
4159 indent(vec![
4160 Line(fmt!(ctx,"fn get_from_pointer(reader: &{capnp}::private::layout::PointerReader<'a>, _default: ::core::option::Option<&'a [{capnp}::Word]>) -> {capnp}::Result<Self> {{")),
4161 indent(Line(fmt!(ctx,"::core::result::Result::Ok({capnp}::capability::FromClientHook::new(reader.get_capability()?))"))),
4162 line("}")]),
4163 line("}")]));
4164
4165 mod_interior.push(Branch(vec![
4166 Line(fmt!(ctx,"impl <'a,{0}> {capnp}::traits::FromPointerBuilder<'a> for Client<{0}> {1} {{",
4167 params.params, params.where_clause)),
4168 indent(vec![
4169 Line(fmt!(ctx,"fn init_pointer(_builder: {capnp}::private::layout::PointerBuilder<'a>, _size: u32) -> Self {{")),
4170 indent(line("unimplemented!()")),
4171 line("}"),
4172 Line(fmt!(ctx,"fn get_from_pointer(builder: {capnp}::private::layout::PointerBuilder<'a>, _default: ::core::option::Option<&'a [{capnp}::Word]>) -> {capnp}::Result<Self> {{")),
4173 indent(Line(fmt!(ctx,"::core::result::Result::Ok({capnp}::capability::FromClientHook::new(builder.get_capability()?))"))),
4174 line("}")]),
4175 line("}"),
4176 BlankLine]));
4177
4178 mod_interior.push(Branch(vec![
4179 Line(fmt!(ctx,
4180 "impl <{0}> {capnp}::traits::SetterInput<Owned<{0}>> for Client<{0}> {1} {{",
4181 params.params, params.where_clause)),
4182 indent(vec![
4183 Line(fmt!(ctx,"fn set_pointer_builder(mut pointer: {capnp}::private::layout::PointerBuilder<'_>, from: Self, _canonicalize: bool) -> {capnp}::Result<()> {{")),
4184 indent(Line("pointer.set_capability(from.client.hook);".to_string())),
4185 indent(Line("::core::result::Result::Ok(())".to_string())),
4186 line("}")
4187 ]
4188 ),
4189 line("}")]));
4190
4191 mod_interior.push(Branch(vec![
4192 Line(fmt!(ctx,
4193 "impl {bracketed_params} {capnp}::traits::HasTypeId for Client{bracketed_params} {{"
4194 )),
4195 indent(Line(
4196 "const TYPE_ID: u64 = _private::TYPE_ID;".to_string(),
4197 )),
4198 line("}"),
4199 ]));
4200
4201 mod_interior.push(Branch(vec![
4202 Line(format!(
4203 "impl {bracketed_params} Clone for Client{bracketed_params} {{"
4204 )),
4205 indent(line("fn clone(&self) -> Self {")),
4206 indent(indent(Line(format!(
4207 "Self {{ client: self.client.clone(), {} }}",
4208 params.phantom_data_value
4209 )))),
4210 indent(line("}")),
4211 line("}"),
4212 ]));
4213
4214 mod_interior.push(Branch(vec![
4215 Line(format!(
4216 "impl {bracketed_params} Client{bracketed_params} {{"
4217 )),
4218 indent(client_impl_interior),
4219 line("}"),
4220 ]));
4221
4222 mod_interior.push(Branch(vec![
4223 Line(format!(
4224 "pub trait Server<{}> {} {} {{",
4225 params.params, server_base, params.where_clause
4226 )),
4227 indent(server_interior),
4228 line("}"),
4229 ]));
4230
4231 mod_interior.push(Branch(vec![
4232 Line(format!(
4233 "pub struct ServerDispatch<_T,{}> {{",
4234 params.params
4235 )),
4236 indent(line(fmt!(ctx, "pub server: {capnp}::capability::Rc<_T>,"))),
4237 indent(if is_generic {
4238 vec![Line(params.phantom_data_type.clone())]
4239 } else {
4240 vec![]
4241 }),
4242 line("}"),
4243 ]));
4244
4245 mod_interior.push(Branch(vec![
4246 Line(
4247 fmt!(ctx,"impl <_S: Server{1} + 'static, {0}> {capnp}::capability::FromServer<_S> for Client{1} {2} {{",
4248 params.params, bracketed_params, params.where_clause)),
4249 indent(vec![
4250 Line(format!("type Dispatch = ServerDispatch<_S, {}>;", params.params)),
4251 Line(fmt!(ctx, "fn from_server(s: {capnp}::capability::Rc<_S>) -> ServerDispatch<_S, {}> {{", params.params)),
4252 indent(Line(format!("ServerDispatch {{ server: s, {} }}", params.phantom_data_value))),
4253 line("}"),
4254 ]),
4255 line("}"),
4256 ]));
4257
4258 mod_interior.push(
4259 Branch(vec![
4260 (if is_generic {
4261 Line(format!("impl <{}, _T: Server{}> ::core::ops::Deref for ServerDispatch<_T,{}> {} {{", params.params, bracketed_params, params.params, params.where_clause))
4262 } else {
4263 line("impl <_T: Server> ::core::ops::Deref for ServerDispatch<_T> {")
4264 }),
4265 indent(line("type Target = _T;")),
4266 indent(line("fn deref(&self) -> &_T { &self.server}")),
4267 line("}"),
4268 ]));
4269
4270 mod_interior.push(
4271 Branch(vec![
4272 (if is_generic {
4273 Line(format!("impl <{}, _T: Server{}> ::core::clone::Clone for ServerDispatch<_T,{}> {} {{", params.params, bracketed_params, params.params, params.where_clause))
4274 } else {
4275 line("impl <_T: Server> ::core::clone::Clone for ServerDispatch<_T> {")
4276 }),
4277 indent(line(
4278 format!("fn clone(&self) -> Self {{ Self {{ server: self.server.clone(), {} }} }}", params.phantom_data_value))),
4279 line("}"),
4280 ]));
4281
4282 mod_interior.push(
4283 Branch(vec![
4284 (if is_generic {
4285 Line(fmt!(ctx,"impl <{}, _T: Server{}> {capnp}::capability::Server for ServerDispatch<_T,{}> {} {{", params.params, bracketed_params, params.params, params.where_clause))
4286 } else {
4287 Line(fmt!(ctx,"impl <_T: Server> {capnp}::capability::Server for ServerDispatch<_T> {{"))
4288 }),
4289 indent(Line(fmt!(ctx,"fn dispatch_call(self, interface_id: u64, method_id: u16, params: {capnp}::capability::Params<{capnp}::any_pointer::Owned>, results: {capnp}::capability::Results<{capnp}::any_pointer::Owned>) -> {capnp}::capability::DispatchCallResult {{"))),
4290 indent(indent(line("match interface_id {"))),
4291 indent(indent(indent(line("_private::TYPE_ID => Self::dispatch_call_internal(self.server, method_id, params, results),")))),
4292 indent(indent(indent(base_dispatch_arms))),
4293 indent(indent(indent(Line(fmt!(ctx,"_ => {{ {capnp}::capability::DispatchCallResult::new({capnp}::capability::Promise::err({capnp}::Error::unimplemented(\"Method not implemented.\".to_string())), false) }}"))))),
4294 indent(indent(line("}"))),
4295 indent(line("}")),
4296
4297 indent(Line(fmt!(ctx, "fn as_ptr(&self) -> usize {{ {capnp}::capability::Rc::as_ptr(&self.server) as usize }}"))),
4298
4299 line("}")]));
4300
4301 mod_interior.push(
4302 Branch(vec![
4303 (if is_generic {
4304 Line(format!("impl <{}, _T: Server{}> ServerDispatch<_T,{}> {} {{", params.params, bracketed_params, params.params, params.where_clause))
4305 } else {
4306 line("impl <_T :Server> ServerDispatch<_T> {")
4307 }),
4308
4309 indent(Line(fmt!(ctx,"pub fn dispatch_call_internal(this: {capnp}::capability::Rc<_T>, method_id: u16, params: {capnp}::capability::Params<{capnp}::any_pointer::Owned>, results: {capnp}::capability::Results<{capnp}::any_pointer::Owned>) -> {capnp}::capability::DispatchCallResult {{"))),
4310 indent(indent(line("match method_id {"))),
4311 indent(indent(indent(dispatch_arms))),
4312 indent(indent(indent(Line(fmt!(ctx,"_ => {{ {capnp}::capability::DispatchCallResult::new({capnp}::capability::Promise::err({capnp}::Error::unimplemented(\"Method not implemented.\".to_string())), false) }}"))))),
4313 indent(indent(line("}"))),
4314 indent(line("}")),
4315 line("}")]));
4316
4317 mod_interior.push(Branch(vec![
4318 line("pub(crate) mod _private {"),
4319 indent(private_mod_interior),
4320 line("}"),
4321 ]));
4322
4323 mod_interior.push(Branch(vec![Branch(nested_output)]));
4324
4325 output.push(BlankLine);
4326 if is_generic {
4327 output.push(Line(format!(
4328 "pub mod {} {{ /* ({}) */",
4329 node_name,
4330 params.expanded_list.join(",")
4331 )));
4332 } else {
4333 output.push(Line(format!("pub mod {node_name} {{")));
4334 }
4335 output.push(indent(mod_interior));
4336 output.push(line("}"));
4337 }
4338
4339 node::Const(c) => {
4340 let styled_name = ctx.get_last_name(node_id)?.to_ascii_uppercase();
4341
4342 let typ = c.get_type()?;
4343 let formatted_text = match (typ.which()?, c.get_value()?.which()?) {
4344 (type_::Void(()), value::Void(())) => {
4345 Line(format!("pub const {styled_name}: () = ();"))
4346 }
4347 (type_::Bool(()), value::Bool(b)) => {
4348 Line(format!("pub const {styled_name}: bool = {b};"))
4349 }
4350 (type_::Int8(()), value::Int8(i)) => {
4351 Line(format!("pub const {styled_name}: i8 = {i};"))
4352 }
4353 (type_::Int16(()), value::Int16(i)) => {
4354 Line(format!("pub const {styled_name}: i16 = {i};"))
4355 }
4356 (type_::Int32(()), value::Int32(i)) => {
4357 Line(format!("pub const {styled_name}: i32 = {i};"))
4358 }
4359 (type_::Int64(()), value::Int64(i)) => {
4360 Line(format!("pub const {styled_name}: i64 = {i};"))
4361 }
4362 (type_::Uint8(()), value::Uint8(i)) => {
4363 Line(format!("pub const {styled_name}: u8 = {i};"))
4364 }
4365 (type_::Uint16(()), value::Uint16(i)) => {
4366 Line(format!("pub const {styled_name}: u16 = {i};"))
4367 }
4368 (type_::Uint32(()), value::Uint32(i)) => {
4369 Line(format!("pub const {styled_name}: u32 = {i};"))
4370 }
4371 (type_::Uint64(()), value::Uint64(i)) => {
4372 Line(format!("pub const {styled_name}: u64 = {i};"))
4373 }
4374
4375 (type_::Float32(()), value::Float32(f)) => {
4376 let literal = match f.classify() {
4377 std::num::FpCategory::Nan => "f32::NAN".into(),
4378 std::num::FpCategory::Infinite => {
4379 if f.is_sign_positive() {
4380 "f32::INFINITY".into()
4381 } else {
4382 "f32::NEG_INFINITY".into()
4383 }
4384 }
4385 _ => format!("{f:e}"),
4386 };
4387 Line(format!("pub const {styled_name}: f32 = {literal};"))
4388 }
4389
4390 (type_::Float64(()), value::Float64(f)) => {
4391 let literal = match f.classify() {
4392 std::num::FpCategory::Nan => "f64::NAN".into(),
4393 std::num::FpCategory::Infinite => {
4394 if f.is_sign_positive() {
4395 "f64::INFINITY".into()
4396 } else {
4397 "f64::NEG_INFINITY".into()
4398 }
4399 }
4400 _ => format!("{f:e}"),
4401 };
4402 Line(format!("pub const {styled_name}: f64 = {literal};"))
4403 }
4404
4405 (type_::Enum(e), value::Enum(v)) => {
4406 if let Some(node) = ctx.node_map.get(&e.get_type_id()) {
4407 match node.which()? {
4408 node::Enum(e) => {
4409 let enumerants = e.get_enumerants()?;
4410 if let Some(enumerant) = enumerants.try_get(u32::from(v)) {
4411 let variant =
4412 capitalize_first_letter(get_enumerant_name(enumerant)?);
4413 let type_string = typ.type_string(ctx, Leaf::Owned)?;
4414 Line(format!(
4415 "pub const {}: {} = {}::{};",
4416 styled_name, type_string, type_string, variant
4417 ))
4418 } else {
4419 return Err(Error::failed(format!(
4420 "enumerant out of range: {v}"
4421 )));
4422 }
4423 }
4424 _ => {
4425 return Err(Error::failed(format!(
4426 "bad enum type ID: {}",
4427 e.get_type_id()
4428 )));
4429 }
4430 }
4431 } else {
4432 return Err(Error::failed(format!(
4433 "bad enum type ID: {}",
4434 e.get_type_id()
4435 )));
4436 }
4437 }
4438
4439 (type_::Text(()), value::Text(t)) => Line(format!(
4440 "pub const {styled_name}: &str = {:?};",
4441 t?.to_str()?
4442 )),
4443 (type_::Data(()), value::Data(d)) => {
4444 Line(format!("pub const {styled_name}: &[u8] = &{:?};", d?))
4445 }
4446
4447 (type_::List(_), value::List(v)) => {
4448 generate_pointer_constant(ctx, &styled_name, typ, v)?
4449 }
4450 (type_::Struct(_), value::Struct(v)) => {
4451 generate_pointer_constant(ctx, &styled_name, typ, v)?
4452 }
4453
4454 (type_::Interface(_t), value::Interface(())) => {
4455 return Err(Error::unimplemented("interface constants".to_string()));
4456 }
4457 (type_::AnyPointer(_), value::AnyPointer(_pr)) => {
4458 return Err(Error::unimplemented("anypointer constants".to_string()));
4459 }
4460
4461 _ => {
4462 return Err(Error::failed("type does not match value".to_string()));
4463 }
4464 };
4465
4466 output.push(formatted_text);
4467 }
4468
4469 node::Annotation(annotation_reader) => {
4470 let is_generic = node_reader.get_is_generic();
4471 let params = node_reader.parameters_texts(ctx);
4472 let last_name = ctx.get_last_name(node_id)?;
4473 let mut interior = vec![];
4474 interior.push(Line(format!("pub const ID: u64 = 0x{node_id:x};")));
4475
4476 let ty = annotation_reader.get_type()?;
4477 if !is_generic {
4478 interior.push(Line(fmt!(ctx,
4479 "pub fn get_type() -> {capnp}::introspect::Type {{ <{} as {capnp}::introspect::Introspect>::introspect() }}", ty.type_string(ctx, Leaf::Owned)?)));
4480 } else {
4481 interior.push(Line(fmt!(ctx,"pub fn get_type<{0}>() -> {capnp}::introspect::Type {1} {{ <{2} as {capnp}::introspect::Introspect>::introspect() }}", params.params, params.where_clause, ty.type_string(ctx, Leaf::Owned)?)));
4482 }
4483 output.push(Branch(vec![
4484 Line(format!("pub mod {last_name} {{")),
4485 indent(interior),
4486 Line("}".into()),
4487 ]));
4488 }
4489 }
4490
4491 Ok(Branch(output))
4492}
4493
4494