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 field_newtype_ids(
2054 ctx: &GeneratorContext,
2055 field: schema_capnp::field::Reader,
2056) -> ::capnp::Result<Vec<u64>> {
2057 use capnp::schema_capnp::*;
2058 let mut id = field.get_type_id();
2059 if id == 0 {
2060 if let field::Slot(slot) = field.which()? {
2061 id = slot.get_type()?.get_type_id();
2062 }
2063 }
2064 let mut ids = Vec::new();
2065 while id != 0 && !ids.contains(&id) {
2068 ids.push(id);
2069 let Some(node) = ctx.node_map.get(&id) else {
2070 break;
2071 };
2072 let node::Type(Ok(t)) = node.which()? else {
2073 break;
2074 };
2075 id = t.get_type_id();
2076 }
2077 Ok(ids)
2078}
2079
2080fn generate_field_newtypes(
2084 ctx: &GeneratorContext,
2085 node_reader: schema_capnp::node::Reader,
2086) -> ::capnp::Result<Option<FormattedText>> {
2087 let schema_capnp::node::Struct(st) = node_reader.which()? else {
2088 return Err(Error::failed("not a struct".into()));
2089 };
2090 let mut any = false;
2091 let mut entries = Vec::new();
2092 for field in st.get_fields()? {
2093 let ids = field_newtype_ids(ctx, field)?;
2094 any |= !ids.is_empty();
2095 let ids: Vec<String> = ids.into_iter().map(format_u64).collect();
2096 entries.push(format!("&[{}]", ids.join(", ")));
2097 }
2098 if !any {
2099 return Ok(None);
2100 }
2101 Ok(Some(Line(format!(
2102 "pub(crate) static FIELD_NEWTYPES: &[&[u64]] = &[{}];",
2103 entries.join(", ")
2104 ))))
2105}
2106
2107fn get_ty_params_of_brand(
2110 ctx: &GeneratorContext,
2111 brand: schema_capnp::brand::Reader,
2112) -> ::capnp::Result<String> {
2113 let mut acc = HashSet::new();
2114 get_ty_params_of_brand_helper(ctx, &mut acc, brand)?;
2115 let mut result = String::new();
2116 for (scope_id, parameter_index) in acc.into_iter() {
2117 let node = ctx.node_map[&scope_id];
2118 let p = node.get_parameters()?.get(u32::from(parameter_index));
2119 result.push_str(p.get_name()?.to_str()?);
2120 result.push(',');
2121 }
2122
2123 Ok(result)
2124}
2125
2126fn get_ty_params_of_type_helper(
2127 ctx: &GeneratorContext,
2128 accumulator: &mut HashSet<(u64, u16)>,
2129 typ: schema_capnp::type_::Reader,
2130) -> ::capnp::Result<()> {
2131 use capnp::schema_capnp::type_;
2132 match typ.which()? {
2133 type_::Void(())
2134 | type_::Bool(())
2135 | type_::Int8(())
2136 | type_::Int16(())
2137 | type_::Int32(())
2138 | type_::Int64(())
2139 | type_::Uint8(())
2140 | type_::Uint16(())
2141 | type_::Uint32(())
2142 | type_::Uint64(())
2143 | type_::Float32(())
2144 | type_::Float64(())
2145 | type_::Text(_)
2146 | type_::Data(_) => {}
2147 type_::AnyPointer(p) => {
2148 match p.which()? {
2149 type_::any_pointer::Unconstrained(_) => (),
2150 type_::any_pointer::Parameter(p) => {
2151 accumulator.insert((p.get_scope_id(), p.get_parameter_index()));
2152 }
2153 type_::any_pointer::ImplicitMethodParameter(_) => {
2154 }
2156 }
2157 }
2158 type_::List(list) => {
2159 get_ty_params_of_type_helper(ctx, accumulator, list.get_element_type()?)?
2160 }
2161 type_::Enum(e) => {
2162 get_ty_params_of_brand_helper(ctx, accumulator, e.get_brand()?)?;
2163 }
2164 type_::Struct(s) => {
2165 get_ty_params_of_brand_helper(ctx, accumulator, s.get_brand()?)?;
2166 }
2167 type_::Interface(interf) => {
2168 get_ty_params_of_brand_helper(ctx, accumulator, interf.get_brand()?)?;
2169 }
2170 }
2171 Ok(())
2172}
2173
2174fn get_ty_params_of_brand_helper(
2175 ctx: &GeneratorContext,
2176 accumulator: &mut HashSet<(u64, u16)>,
2177 brand: schema_capnp::brand::Reader,
2178) -> ::capnp::Result<()> {
2179 for scope in brand.get_scopes()? {
2180 let scope_id = scope.get_scope_id();
2181 match scope.which()? {
2182 schema_capnp::brand::scope::Bind(bind) => {
2183 for binding in bind? {
2184 match binding.which()? {
2185 schema_capnp::brand::binding::Unbound(()) => {}
2186 schema_capnp::brand::binding::Type(t) => {
2187 get_ty_params_of_type_helper(ctx, accumulator, t?)?
2188 }
2189 }
2190 }
2191 }
2192 schema_capnp::brand::scope::Inherit(()) => {
2193 let parameters = ctx.node_map[&scope_id].get_parameters()?;
2194 for idx in 0..parameters.len() {
2195 accumulator.insert((scope_id, idx as u16));
2196 }
2197 }
2198 }
2199 }
2200 Ok(())
2201}
2202
2203fn newtype_template_id(ctx: &GeneratorContext, alias_id: u64) -> ::capnp::Result<Option<u64>> {
2209 use capnp::schema_capnp::*;
2210 let Some(alias) = ctx.node_map.get(&alias_id) else {
2211 return Ok(None);
2212 };
2213 let node::Type(Ok(t)) = alias.which()? else {
2214 return Ok(None);
2215 };
2216 let type_::Struct(st) = t.which()? else {
2217 return Ok(None); };
2219 let template_id = st.get_type_id();
2220 let Some(template) = ctx.node_map.get(&template_id) else {
2221 return Ok(None);
2222 };
2223 if template.get_scope_id() != alias_id {
2224 let aliased = t.get_type_id();
2227 if aliased != 0 {
2228 return newtype_template_id(ctx, aliased);
2229 }
2230 return Ok(None);
2231 }
2232 Ok(Some(template_id))
2233}
2234
2235fn inline_newtype_owner(ctx: &GeneratorContext, alias_id: u64) -> ::capnp::Result<Option<u64>> {
2238 Ok(newtype_template_id(ctx, alias_id)?.map(|t| ctx.node_map[&t].get_scope_id()))
2239}
2240
2241fn group_newtype_template_id(
2245 ctx: &GeneratorContext,
2246 alias_id: u64,
2247) -> ::capnp::Result<Option<u64>> {
2248 use capnp::schema_capnp::*;
2249 let Some(template_id) = newtype_template_id(ctx, alias_id)? else {
2250 return Ok(None);
2251 };
2252 let node::Struct(tmpl) = ctx.node_map[&template_id].which()? else {
2253 return Ok(None);
2254 };
2255 if tmpl.get_discriminant_count() > 0 {
2256 return Ok(None); }
2258 for field in tmpl.get_fields()? {
2259 if let field::Group(_) = field.which()? {
2260 if field.get_type_id() == 0 {
2261 return Ok(None); }
2263 }
2264 }
2265 Ok(Some(template_id))
2266}
2267
2268fn union_newtype_template_id(
2271 ctx: &GeneratorContext,
2272 alias_id: u64,
2273) -> ::capnp::Result<Option<u64>> {
2274 use capnp::schema_capnp::*;
2275 let Some(template_id) = newtype_template_id(ctx, alias_id)? else {
2276 return Ok(None);
2277 };
2278 let node::Struct(tmpl) = ctx.node_map[&template_id].which()? else {
2279 return Ok(None);
2280 };
2281 if tmpl.get_discriminant_count() == 0 {
2282 return Ok(None); }
2284 for field in tmpl.get_fields()? {
2285 if let field::Group(_) = field.which()? {
2286 if field.get_type_id() == 0 {
2287 return Ok(None); }
2289 }
2290 }
2291 Ok(Some(template_id))
2292}
2293
2294struct TraitMethod {
2298 signature: String,
2299 call_name: String,
2300 call_args: String,
2301 deref_self: bool,
2302}
2303
2304fn newtype_trait_methods(
2307 ctx: &GeneratorContext,
2308 field: &schema_capnp::field::Reader,
2309 is_reader: bool,
2310 include_getter: bool,
2311) -> ::capnp::Result<Vec<TraitMethod>> {
2312 use capnp::schema_capnp::*;
2313 let name = camel_to_snake_case(field.get_name()?.to_str()?);
2314 let is_pointer = match field.which()? {
2315 field::Slot(s) => s.get_type()?.is_pointer()?,
2316 field::Group(_) => false,
2317 };
2318 let mut methods = Vec::new();
2319
2320 if is_reader {
2323 if include_getter {
2324 let (ret, _, _) = getter_text(ctx, field, true, true)?;
2325 methods.push(TraitMethod {
2326 signature: format!("get_{name}(&self) {ret}"),
2327 call_name: format!("get_{name}"),
2328 call_args: String::new(),
2329 deref_self: true,
2330 });
2331 }
2332 } else {
2333 if include_getter {
2334 let (ret, _, _) = getter_text(ctx, field, false, true)?;
2337 methods.push(TraitMethod {
2338 signature: format!("get_{name}(self) {ret}"),
2339 call_name: format!("get_{name}"),
2340 call_args: String::new(),
2341 deref_self: false,
2342 });
2343 }
2344 for m in setter_methods(ctx, 0, &name, field)? {
2345 methods.push(TraitMethod {
2346 signature: m.signature(false),
2347 call_name: m.name,
2348 call_args: m.delegate_args,
2349 deref_self: false,
2350 });
2351 }
2352 }
2353 if is_pointer {
2354 methods.push(TraitMethod {
2355 signature: format!("has_{name}(&self) -> bool"),
2356 call_name: format!("has_{name}"),
2357 call_args: String::new(),
2358 deref_self: false,
2359 });
2360 }
2361 Ok(methods)
2362}
2363
2364fn newtype_type_id_line(node_id: u64) -> FormattedText {
2369 Line(format!("pub const TYPE_ID: u64 = {};", format_u64(node_id)))
2370}
2371
2372fn generate_newtype_trait(
2375 ctx: &GeneratorContext,
2376 node_id: u64,
2377 node_name: &str,
2378) -> ::capnp::Result<FormattedText> {
2379 if let Some(owner) = inline_newtype_owner(ctx, node_id)? {
2380 if owner != node_id {
2381 return Ok(Branch(vec![
2384 BlankLine,
2385 Line(format!("pub mod {} {{", module_name(node_name))),
2386 indent(Line(format!(
2387 "pub use {}::*;",
2388 ctx.get_qualified_module(owner)
2389 ))),
2390 indent(newtype_type_id_line(node_id)),
2391 line("}"),
2392 ]));
2393 }
2394 }
2395 Ok(Branch(vec![
2396 generate_group_newtype_trait(ctx, node_id, node_name)?,
2397 generate_union_newtype_trait(ctx, node_id, node_name)?,
2398 ]))
2399}
2400
2401fn count_newtype_leaves(ctx: &GeneratorContext, template_id: u64) -> ::capnp::Result<usize> {
2404 use capnp::schema_capnp::*;
2405 let node::Struct(tmpl) = ctx.node_map[&template_id].which()? else {
2406 return Ok(0);
2407 };
2408 let mut n = 0;
2409 for field in tmpl.get_fields()? {
2410 match field.which()? {
2411 field::Slot(_) => n += 1,
2412 field::Group(_) => {
2413 if let Some(nested) = newtype_template_id(ctx, field.get_type_id())? {
2414 n += count_newtype_leaves(ctx, nested)?;
2415 }
2416 }
2417 }
2418 }
2419 Ok(n)
2420}
2421
2422fn collect_leaf_offsets(
2426 ctx: &GeneratorContext,
2427 template_id: u64,
2428 instance_id: u64,
2429 out: &mut Vec<String>,
2430) -> ::capnp::Result<()> {
2431 use capnp::schema_capnp::*;
2432 let node::Struct(tmpl) = ctx.node_map[&template_id].which()? else {
2433 return Ok(());
2434 };
2435 let node::Struct(instance) = ctx.node_map[&instance_id].which()? else {
2436 return Ok(());
2437 };
2438 let mut inst_fields = ::std::collections::HashMap::new();
2439 for f in instance.get_fields()? {
2440 inst_fields.insert(f.get_name()?.to_str()?.to_string(), f);
2441 }
2442 for field in tmpl.get_fields()? {
2443 let raw = field.get_name()?.to_str()?;
2444 match field.which()? {
2445 field::Slot(_) => match inst_fields.get(raw).map(|f| f.which()) {
2446 Some(Ok(field::Slot(s))) => out.push(s.get_offset().to_string()),
2447 _ => out.push("0xffff_ffff".to_string()),
2448 },
2449 field::Group(_) => {
2450 let Some(nested_tmpl) = newtype_template_id(ctx, field.get_type_id())? else {
2451 continue;
2452 };
2453 match inst_fields.get(raw).map(|f| f.which()) {
2454 Some(Ok(field::Group(ig))) => {
2455 collect_leaf_offsets(ctx, nested_tmpl, ig.get_type_id(), out)?
2456 }
2457 _ => {
2458 for _ in 0..count_newtype_leaves(ctx, nested_tmpl)? {
2459 out.push("0xffff_ffff".to_string());
2460 }
2461 }
2462 }
2463 }
2464 }
2465 }
2466 Ok(())
2467}
2468
2469fn any_reader_items(
2475 ctx: &GeneratorContext,
2476 template_id: u64,
2477) -> ::capnp::Result<Vec<FormattedText>> {
2478 use capnp::schema_capnp::*;
2479 let node::Struct(tmpl) = ctx.node_map[&template_id].which()? else {
2480 return Ok(vec![]);
2481 };
2482 if tmpl.get_discriminant_count() > 0 {
2483 return Ok(vec![]); }
2485
2486 let mut inherent = Vec::new();
2487 let mut trait_methods = Vec::new();
2488 let mut defaults = Vec::new();
2489 let mut cursor = 0usize;
2490 for field in tmpl.get_fields()? {
2491 let name = camel_to_snake_case(field.get_name()?.to_str()?);
2492 if let field::Group(_) = field.which()? {
2493 let assoc = capitalize_first_letter(field.get_name()?.to_str()?);
2494 let nested_mod = ctx.get_qualified_module(field.get_type_id());
2495 let Some(nested_tmpl) = newtype_template_id(ctx, field.get_type_id())? else {
2496 return Ok(vec![]);
2497 };
2498 let count = count_newtype_leaves(ctx, nested_tmpl)?;
2499 let (start, end) = (cursor, cursor + count);
2500 inherent.push(Line(format!(
2501 "pub fn get_{name}(&self) -> {nested_mod}::AnyReader<'a> {{ {nested_mod}::AnyReader::new(self.reader, &self.offsets[{start}..{end}]) }}"
2502 )));
2503 trait_methods.push(Line(format!("type {assoc} = {nested_mod}::AnyReader<'a>;")));
2504 trait_methods.push(Line(format!(
2505 "fn get_{name}(&self) -> Self::{assoc} {{ self.get_{name}() }}"
2506 )));
2507 cursor += count;
2508 } else {
2509 let off = format!("self.offsets[{cursor}] as usize");
2510 let (ret, mut body, def) = getter_text_at(ctx, &field, true, true, Some(&off))?;
2511 if let Some(d) = def {
2512 defaults.push(d);
2513 }
2514 if is_scalar_data_field(&field)? {
2517 if let (field::Slot(s), FormattedText::Line(expr)) = (field.which()?, &body) {
2518 let expr = expr.clone();
2519 let dflt = prim_default_value(&s.get_default_value()?)?;
2520 body = Line(format!(
2521 "if self.offsets[{cursor}] == 0xffff_ffffu32 {{ {dflt} }} else {{ {expr} }}"
2522 ));
2523 }
2524 }
2525 inherent.push(Line(format!("pub fn get_{name}(&self) {ret} {{")));
2526 inherent.push(indent(body));
2527 inherent.push(line("}"));
2528 trait_methods.push(Line(format!(
2529 "fn get_{name}(&self) {ret} {{ self.get_{name}() }}"
2530 )));
2531 if let field::Slot(s) = field.which()? {
2532 if s.get_type()?.is_pointer()? {
2533 inherent.push(Line(format!(
2534 "pub fn has_{name}(&self) -> bool {{ !self.reader.get_pointer_field(self.offsets[{cursor}] as usize).is_null() }}"
2535 )));
2536 trait_methods.push(Line(format!(
2537 "fn has_{name}(&self) -> bool {{ self.has_{name}() }}"
2538 )));
2539 }
2540 }
2541 cursor += 1;
2542 }
2543 }
2544
2545 let sr = fmt!(ctx, "{capnp}::private::layout::StructReader<'a>");
2546 let mut items = vec![
2547 BlankLine,
2548 line("#[derive(Clone, Copy)]"),
2549 Line(format!(
2550 "pub struct AnyReader<'a> {{ reader: {sr}, offsets: &'a [u32] }}"
2551 )),
2552 line("impl<'a> AnyReader<'a> {"),
2553 indent(vec![
2554 Line(format!(
2555 "pub fn new(reader: {sr}, offsets: &'a [u32]) -> Self {{ AnyReader {{ reader, offsets }} }}"
2556 )),
2557 Branch(inherent),
2558 ]),
2559 line("}"),
2560 line("impl<'a> Reader<'a> for AnyReader<'a> {"),
2561 indent(trait_methods),
2562 line("}"),
2563 ];
2564 if !defaults.is_empty() {
2565 items.push(line("mod _private {"));
2566 items.push(indent(defaults));
2567 items.push(line("}"));
2568 }
2569 Ok(items)
2570}
2571
2572fn union_any_reader_items(
2577 ctx: &GeneratorContext,
2578 template_id: u64,
2579) -> ::capnp::Result<Vec<FormattedText>> {
2580 use capnp::schema_capnp::*;
2581 let node::Struct(tmpl) = ctx.node_map[&template_id].which()? else {
2582 return Ok(vec![]);
2583 };
2584 if tmpl.get_discriminant_count() == 0 {
2585 return Ok(vec![]);
2586 }
2587
2588 let mut arms = Vec::new();
2589 let mut assoc = Vec::new();
2590 let mut group_variants = Vec::new();
2591 let mut which_type_params = Vec::new();
2592 let mut has_inherent = Vec::new();
2593 let mut has_trait = Vec::new();
2594 let mut needs_lifetime = false;
2595 let mut cursor = 0usize;
2596 for field in tmpl.get_fields()? {
2597 let variant = capitalize_first_letter(field.get_name()?.to_str()?);
2598 let name = camel_to_snake_case(field.get_name()?.to_str()?);
2599 let dvalue = field.get_discriminant_value();
2600 if let field::Group(_) = field.which()? {
2601 let nested_mod = ctx.get_qualified_module(field.get_type_id());
2602 let Some(nested_tmpl) = newtype_template_id(ctx, field.get_type_id())? else {
2603 return Ok(vec![]);
2604 };
2605 let count = count_newtype_leaves(ctx, nested_tmpl)?;
2606 let (start, end) = (cursor, cursor + count);
2607 arms.push(Line(format!(
2608 "{dvalue} => ::core::result::Result::Ok(Which::{variant}({nested_mod}::AnyReader::new(self.reader, &self.offsets[{start}..{end}]))),"
2609 )));
2610 assoc.push(Line(format!(
2611 "type {variant} = {nested_mod}::AnyReader<'a>;"
2612 )));
2613 group_variants.push(variant.clone());
2614 which_type_params.push(format!("{nested_mod}::AnyReader<'a>"));
2615 cursor += count;
2616 } else {
2617 let off = format!("self.offsets[{cursor}] as usize");
2618 let (_, getter_code, _) = getter_text_at(ctx, &field, true, false, Some(&off))?;
2619 let FormattedText::Line(payload) = getter_code else {
2620 return Ok(vec![]); };
2622 arms.push(Line(format!(
2623 "{dvalue} => ::core::result::Result::Ok(Which::{variant}({payload})),"
2624 )));
2625 if let field::Slot(s) = field.which()? {
2626 if s.get_type()?.is_pointer()? {
2627 needs_lifetime = true;
2628 has_inherent.push(Line(format!(
2629 "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() }}"
2630 )));
2631 has_trait.push(Line(format!(
2632 "fn has_{name}(&self) -> bool {{ self.has_{name}() }}"
2633 )));
2634 }
2635 }
2636 cursor += 1;
2637 }
2638 }
2639 arms.push(line(
2640 "x => ::core::result::Result::Err(::capnp::NotInSchema(x)),",
2641 ));
2642
2643 let inherent_ret = union_which_generics(needs_lifetime, &which_type_params);
2644 let self_ret = union_which_generics(
2645 needs_lifetime,
2646 &group_variants
2647 .iter()
2648 .map(|v| format!("Self::{v}"))
2649 .collect::<Vec<_>>(),
2650 );
2651
2652 let sr = fmt!(ctx, "{capnp}::private::layout::StructReader<'a>");
2653 let which_method = Branch(vec![
2654 Line(format!(
2655 "pub fn which(&self) -> ::core::result::Result<Which{inherent_ret}, ::capnp::NotInSchema> {{"
2656 )),
2657 indent(vec![
2658 line("match self.reader.get_data_field::<u16>(self.disc_offset as usize) {"),
2659 indent(arms),
2660 line("}"),
2661 ]),
2662 line("}"),
2663 ]);
2664
2665 let mut trait_items = assoc;
2666 trait_items.push(Line(format!(
2667 "fn which(&self) -> ::core::result::Result<Which{self_ret}, ::capnp::NotInSchema> {{ self.which() }}"
2668 )));
2669 trait_items.extend(has_trait);
2670
2671 Ok(vec![
2672 BlankLine,
2673 line("#[derive(Clone, Copy)]"),
2674 Line(format!(
2675 "pub struct AnyReader<'a> {{ reader: {sr}, disc_offset: u32, offsets: &'a [u32] }}"
2676 )),
2677 line("impl<'a> AnyReader<'a> {"),
2678 indent(vec![
2679 Line(format!(
2680 "pub fn new(reader: {sr}, disc_offset: u32, offsets: &'a [u32]) -> Self {{ AnyReader {{ reader, disc_offset, offsets }} }}"
2681 )),
2682 which_method,
2683 Branch(has_inherent),
2684 ]),
2685 line("}"),
2686 line("impl<'a> Reader<'a> for AnyReader<'a> {"),
2687 indent(trait_items),
2688 line("}"),
2689 ])
2690}
2691
2692fn any_builder_items(
2696 ctx: &GeneratorContext,
2697 template_id: u64,
2698) -> ::capnp::Result<Vec<FormattedText>> {
2699 use capnp::schema_capnp::*;
2700 let node::Struct(tmpl) = ctx.node_map[&template_id].which()? else {
2701 return Ok(vec![]);
2702 };
2703 if tmpl.get_discriminant_count() > 0 {
2704 return Ok(vec![]); }
2706
2707 let mut inherent = Vec::new();
2708 let mut trait_methods = Vec::new();
2709 let mut cursor = 0usize;
2710 for field in tmpl.get_fields()? {
2711 let name = camel_to_snake_case(field.get_name()?.to_str()?);
2712 if let field::Group(_) = field.which()? {
2713 let assoc = capitalize_first_letter(field.get_name()?.to_str()?);
2714 let nested_mod = ctx.get_qualified_module(field.get_type_id());
2715 let Some(nested_tmpl) = newtype_template_id(ctx, field.get_type_id())? else {
2716 return Ok(vec![]);
2717 };
2718 let count = count_newtype_leaves(ctx, nested_tmpl)?;
2719 let (start, end) = (cursor, cursor + count);
2720 for verb in ["get", "init"] {
2721 inherent.push(Line(format!(
2722 "pub fn {verb}_{name}(self) -> {nested_mod}::AnyBuilder<'a> {{ {nested_mod}::AnyBuilder::new(self.builder, &self.offsets[{start}..{end}]) }}"
2723 )));
2724 }
2725 trait_methods.push(Line(format!(
2726 "type {assoc} = {nested_mod}::AnyBuilder<'a>;"
2727 )));
2728 trait_methods.push(Line(format!(
2729 "fn get_{name}(self) -> Self::{assoc} {{ self.get_{name}() }}"
2730 )));
2731 trait_methods.push(Line(format!(
2732 "fn init_{name}(self) -> Self::{assoc} {{ self.init_{name}() }}"
2733 )));
2734 cursor += count;
2735 } else {
2736 let off = format!("self.offsets[{cursor}] as usize");
2737 let guard = unmapped_panic(cursor, &name);
2738 let (ret, body, _) = getter_text_at(ctx, &field, false, true, Some(&off))?;
2741 let get_body = if is_scalar_data_field(&field)? {
2742 if let field::Slot(s) = field.which()? {
2743 if let FormattedText::Line(expr) = &body {
2744 let expr = expr.clone();
2745 let dflt = prim_default_value(&s.get_default_value()?)?;
2746 Line(format!(
2747 "if self.offsets[{cursor}] == 0xffff_ffffu32 {{ {dflt} }} else {{ {expr} }}"
2748 ))
2749 } else {
2750 body
2751 }
2752 } else {
2753 body
2754 }
2755 } else {
2756 Branch(vec![Line(guard.clone()), body])
2757 };
2758 inherent.push(Line(format!("pub fn get_{name}(self) {ret} {{")));
2759 inherent.push(indent(get_body));
2760 inherent.push(line("}"));
2761 trait_methods.push(Line(format!(
2762 "fn get_{name}(self) {ret} {{ self.get_{name}() }}"
2763 )));
2764 for m in setter_methods_at(ctx, "0", &name, &field, Some(&off))? {
2765 let sig_inherent = m.signature(true);
2766 let sig_trait = m.signature(false);
2767 let call = format!("self.{}({})", m.name, m.delegate_args);
2768 inherent.push(Line(format!("pub fn {sig_inherent} {{")));
2769 inherent.push(indent(Branch(vec![Line(guard.clone()), m.body])));
2770 inherent.push(line("}"));
2771 trait_methods.push(Line(format!("fn {sig_trait} {{ {call} }}")));
2772 }
2773 if let field::Slot(s) = field.which()? {
2774 if s.get_type()?.is_pointer()? {
2775 inherent.push(Line(format!(
2776 "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) }}"
2777 )));
2778 trait_methods.push(Line(format!(
2779 "fn has_{name}(&self) -> bool {{ self.has_{name}() }}"
2780 )));
2781 }
2782 }
2783 cursor += 1;
2784 }
2785 }
2786
2787 let sb = fmt!(ctx, "{capnp}::private::layout::StructBuilder<'a>");
2788 Ok(vec![
2789 BlankLine,
2790 Line(format!(
2791 "pub struct AnyBuilder<'a> {{ builder: {sb}, offsets: &'a [u32] }}"
2792 )),
2793 line("impl<'a> AnyBuilder<'a> {"),
2794 indent(vec![
2795 Line(format!(
2796 "pub fn new(builder: {sb}, offsets: &'a [u32]) -> Self {{ AnyBuilder {{ builder, offsets }} }}"
2797 )),
2798 Branch(inherent),
2799 ]),
2800 line("}"),
2801 line("impl<'a> Builder<'a> for AnyBuilder<'a> {"),
2802 indent(trait_methods),
2803 line("}"),
2804 ])
2805}
2806
2807fn union_any_builder_items(
2811 ctx: &GeneratorContext,
2812 template_id: u64,
2813) -> ::capnp::Result<Vec<FormattedText>> {
2814 use capnp::schema_capnp::*;
2815 let node::Struct(tmpl) = ctx.node_map[&template_id].which()? else {
2816 return Ok(vec![]);
2817 };
2818 if tmpl.get_discriminant_count() == 0 {
2819 return Ok(vec![]);
2820 }
2821
2822 let mut inherent = Vec::new();
2823 let mut assoc = Vec::new();
2824 let mut trait_methods = Vec::new();
2825 let mut cursor = 0usize;
2826 for field in tmpl.get_fields()? {
2827 let variant = capitalize_first_letter(field.get_name()?.to_str()?);
2828 let name = camel_to_snake_case(field.get_name()?.to_str()?);
2829 let dvalue = field.get_discriminant_value();
2830 if let field::Group(_) = field.which()? {
2831 let nested_mod = ctx.get_qualified_module(field.get_type_id());
2832 let Some(nested_tmpl) = newtype_template_id(ctx, field.get_type_id())? else {
2833 return Ok(vec![]);
2834 };
2835 let count = count_newtype_leaves(ctx, nested_tmpl)?;
2836 let (start, end) = (cursor, cursor + count);
2837 inherent.push(Line(format!(
2838 "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}]) }}"
2839 )));
2840 assoc.push(Line(format!(
2841 "type {variant} = {nested_mod}::AnyBuilder<'a>;"
2842 )));
2843 trait_methods.push(Line(format!(
2844 "fn init_{name}(self) -> Self::{variant} {{ self.init_{name}() }}"
2845 )));
2846 cursor += count;
2847 } else {
2848 let off = format!("self.offsets[{cursor}] as usize");
2849 let guard = unmapped_panic(cursor, &name);
2850 for m in setter_methods_at(ctx, "self.disc_offset as usize", &name, &field, Some(&off))?
2851 {
2852 let sig_inherent = m.signature(true);
2853 let sig_trait = m.signature(false);
2854 let call = format!("self.{}({})", m.name, m.delegate_args);
2855 inherent.push(Line(format!("pub fn {sig_inherent} {{")));
2856 inherent.push(indent(Branch(vec![Line(guard.clone()), m.body])));
2857 inherent.push(line("}"));
2858 trait_methods.push(Line(format!("fn {sig_trait} {{ {call} }}")));
2859 }
2860 if let field::Slot(s) = field.which()? {
2861 if s.get_type()?.is_pointer()? {
2862 inherent.push(Line(format!(
2863 "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) }}"
2864 )));
2865 trait_methods.push(Line(format!(
2866 "fn has_{name}(&self) -> bool {{ self.has_{name}() }}"
2867 )));
2868 }
2869 }
2870 cursor += 1;
2871 }
2872 }
2873
2874 let sb = fmt!(ctx, "{capnp}::private::layout::StructBuilder<'a>");
2875 let mut trait_items = assoc;
2876 trait_items.extend(trait_methods);
2877 Ok(vec![
2878 BlankLine,
2879 Line(format!(
2880 "pub struct AnyBuilder<'a> {{ builder: {sb}, disc_offset: u32, offsets: &'a [u32] }}"
2881 )),
2882 line("impl<'a> AnyBuilder<'a> {"),
2883 indent(vec![
2884 Line(format!(
2885 "pub fn new(builder: {sb}, disc_offset: u32, offsets: &'a [u32]) -> Self {{ AnyBuilder {{ builder, disc_offset, offsets }} }}"
2886 )),
2887 Branch(inherent),
2888 ]),
2889 line("}"),
2890 line("impl<'a> Builder<'a> for AnyBuilder<'a> {"),
2891 indent(trait_items),
2892 line("}"),
2893 ])
2894}
2895
2896fn any_downcast_impls(
2901 ctx: &GeneratorContext,
2902 template_id: u64,
2903 is_union: bool,
2904 has_reader: bool,
2905 has_builder: bool,
2906) -> ::capnp::Result<Vec<FormattedText>> {
2907 let leaves = count_newtype_leaves(ctx, template_id)?;
2908 let disc_arg = if is_union {
2910 "discriminant_offset, "
2911 } else {
2912 ""
2913 };
2914 let mut items = Vec::new();
2915 let mut emit = |kind: &str, raw: &str, value: &str, downcast: &str| {
2916 let ident = kind.to_ascii_lowercase();
2917 let unused = if is_union { "" } else { "_" };
2918 items.push(Line(fmt!(
2919 ctx,
2920 "impl<'a> {capnp}::traits::{kind}<'a> for {kind}<'a> {{"
2921 )));
2922 items.push(indent(vec![
2923 line("const TYPE_ID: u64 = TYPE_ID;"),
2924 Line(format!("const LEAF_COUNT: usize = {leaves};")),
2925 Line(fmt!(ctx,
2926 "fn from_use_site({ident}: {capnp}::private::layout::{raw}<'a>, offsets: &'a [u32], {unused}discriminant_offset: u32) -> Self {{ Self::new({ident}, {disc_arg}offsets) }}"
2927 )),
2928 ]));
2929 items.push(line("}"));
2930 items.push(Line(fmt!(
2931 ctx,
2932 "impl<'a> {capnp}::dynamic_value::Downcast{value}<'a> for {kind}<'a> {{"
2933 )));
2934 items.push(indent(Line(fmt!(ctx,
2935 "fn downcast_{value_lc}(v: {capnp}::dynamic_value::{value}<'a>) -> Self {{ {capnp}::dynamic_value::{downcast}(v) }}",
2936 value_lc = value.to_ascii_lowercase()
2937 ))));
2938 items.push(line("}"));
2939 };
2940 if has_reader {
2941 emit("AnyReader", "StructReader", "Reader", "downcast_any_reader");
2942 }
2943 if has_builder {
2944 emit(
2945 "AnyBuilder",
2946 "StructBuilder",
2947 "Builder",
2948 "downcast_any_builder",
2949 );
2950 }
2951 Ok(items)
2952}
2953
2954fn use_site_any_layout(
2960 ctx: &GeneratorContext,
2961 node: schema_capnp::node::Reader,
2962) -> ::capnp::Result<Option<String>> {
2963 use capnp::schema_capnp::*;
2964 let node::Struct(instance) = node.which()? else {
2965 return Ok(None);
2966 };
2967 if !instance.get_is_group() {
2968 return Ok(None);
2969 }
2970 let id = node.get_id();
2971 let Some(parent) = ctx.node_map.get(&node.get_scope_id()) else {
2972 return Ok(None);
2973 };
2974 let node::Struct(parent_struct) = parent.which()? else {
2975 return Ok(None);
2976 };
2977 for field in parent_struct.get_fields()? {
2978 let field::Group(group) = field.which()? else {
2979 continue;
2980 };
2981 if group.get_type_id() != id || field.get_type_id() == 0 {
2982 continue;
2983 }
2984 let alias_id = field.get_type_id();
2985 let is_newtype = group_newtype_template_id(ctx, alias_id)?.is_some()
2986 || union_newtype_template_id(ctx, alias_id)?.is_some();
2987 if !is_newtype {
2988 return Ok(None);
2989 }
2990 let ids: Vec<String> = field_newtype_ids(ctx, field)?
2991 .into_iter()
2992 .map(format_u64)
2993 .collect();
2994 let table = use_site_offsets_table(ctx, node.get_scope_id(), id)?;
2995 return Ok(Some(format!(
2996 ".with_any_layout(&[{}], &{table}, {})",
2997 ids.join(", "),
2998 instance.get_discriminant_offset()
2999 )));
3000 }
3001 Ok(None)
3002}
3003
3004fn use_site_offsets_table(
3007 ctx: &GeneratorContext,
3008 parent_id: u64,
3009 instance_id: u64,
3010) -> ::capnp::Result<String> {
3011 Ok(format!(
3012 "{}::{}",
3013 ctx.get_qualified_module(parent_id),
3014 use_site_offsets_name(ctx, instance_id)?
3015 ))
3016}
3017
3018fn use_site_offsets_name(ctx: &GeneratorContext, instance_id: u64) -> ::capnp::Result<String> {
3019 Ok(format!(
3020 "{}_OFFSETS",
3021 camel_to_snake_case(ctx.get_last_name(instance_id)?).to_ascii_uppercase()
3022 ))
3023}
3024
3025fn generate_group_newtype_trait(
3029 ctx: &GeneratorContext,
3030 node_id: u64,
3031 node_name: &str,
3032) -> ::capnp::Result<FormattedText> {
3033 use capnp::schema_capnp::*;
3034 let Some(template_id) = group_newtype_template_id(ctx, node_id)? else {
3035 return Ok(Branch(vec![]));
3036 };
3037 let node::Struct(tmpl) = ctx.node_map[&template_id].which()? else {
3038 return Ok(Branch(vec![]));
3039 };
3040
3041 let mut reader_items = Vec::new();
3042 let mut builder_items = Vec::new();
3043 for field in tmpl.get_fields()? {
3044 if let field::Group(_) = field.which()? {
3045 let name = camel_to_snake_case(field.get_name()?.to_str()?);
3048 let assoc = capitalize_first_letter(field.get_name()?.to_str()?);
3049 let nested = ctx.get_qualified_module(field.get_type_id());
3050 reader_items.push(Line(format!("type {assoc}: {nested}::Reader<'a>;")));
3051 reader_items.push(Line(format!("fn get_{name}(&self) -> Self::{assoc};")));
3052 builder_items.push(Line(format!("type {assoc}: {nested}::Builder<'a>;")));
3053 builder_items.push(Line(format!("fn get_{name}(self) -> Self::{assoc};")));
3054 builder_items.push(Line(format!("fn init_{name}(self) -> Self::{assoc};")));
3055 } else {
3056 for m in newtype_trait_methods(ctx, &field, true, true)? {
3057 reader_items.push(Line(format!("fn {};", m.signature)));
3058 }
3059 for m in newtype_trait_methods(ctx, &field, false, true)? {
3060 builder_items.push(Line(format!("fn {};", m.signature)));
3061 }
3062 }
3063 }
3064
3065 let mut module_items = vec![
3066 line("pub trait Reader<'a> {"),
3067 indent(reader_items),
3068 line("}"),
3069 line("pub trait Builder<'a> {"),
3070 indent(builder_items),
3071 line("}"),
3072 ];
3073 let any_reader = any_reader_items(ctx, template_id)?;
3074 let any_builder = any_builder_items(ctx, template_id)?;
3075 let downcasts = any_downcast_impls(
3076 ctx,
3077 template_id,
3078 false,
3079 !any_reader.is_empty(),
3080 !any_builder.is_empty(),
3081 )?;
3082 module_items.extend(any_reader);
3083 module_items.extend(any_builder);
3084 module_items.extend(downcasts);
3085
3086 Ok(Branch(vec![
3087 BlankLine,
3088 Line(format!("pub mod {} {{", module_name(node_name))),
3089 indent(newtype_type_id_line(node_id)),
3090 indent(module_items),
3091 line("}"),
3092 ]))
3093}
3094
3095fn generate_newtype_impl(
3100 ctx: &GeneratorContext,
3101 alias_id: u64,
3102 instance_id: u64,
3103) -> ::capnp::Result<FormattedText> {
3104 Ok(Branch(vec![
3105 generate_group_newtype_impl(ctx, alias_id, instance_id)?,
3106 generate_union_newtype_impl(ctx, alias_id, instance_id)?,
3107 ]))
3108}
3109
3110fn generate_group_newtype_impl(
3111 ctx: &GeneratorContext,
3112 alias_id: u64,
3113 instance_id: u64,
3114) -> ::capnp::Result<FormattedText> {
3115 use capnp::schema_capnp::*;
3116 let Some(template_id) = group_newtype_template_id(ctx, alias_id)? else {
3117 return Ok(Branch(vec![]));
3118 };
3119 let node::Struct(tmpl) = ctx.node_map[&template_id].which()? else {
3120 return Ok(Branch(vec![]));
3121 };
3122 let node::Struct(instance) = ctx.node_map[&instance_id].which()? else {
3123 return Ok(Branch(vec![]));
3124 };
3125
3126 let mut instance_fields = ::std::collections::HashMap::new();
3131 for field in instance.get_fields()? {
3132 instance_fields.insert(field.get_name()?.to_str()?.to_string(), field);
3133 }
3134
3135 let mut trait_ok = true;
3136 let mut reader_items = Vec::new();
3137 let mut builder_items = Vec::new();
3138 for field in tmpl.get_fields()? {
3139 let raw_name = field.get_name()?.to_str()?;
3140 let Some(inst_field) = instance_fields.get(raw_name) else {
3141 if is_scalar_data_field(&field)? {
3146 let field::Slot(s) = field.which()? else {
3147 trait_ok = false;
3148 continue;
3149 };
3150 let dflt = prim_default_value(&s.get_default_value()?)?;
3151 let not_mapped =
3152 format!("panic!(\"field '{raw_name}' is not mapped at this use site\")");
3153 for m in newtype_trait_methods(ctx, &field, true, true)? {
3154 reader_items.push(Line(format!("fn {} {{ {dflt} }}", m.signature)));
3155 }
3156 for m in newtype_trait_methods(ctx, &field, false, true)? {
3157 let body = if m.call_name.starts_with("get_") {
3158 dflt.clone()
3159 } else if m.call_args.is_empty() {
3160 not_mapped.clone()
3161 } else if m.call_args.contains(',') {
3162 format!("let _ = ({}); {not_mapped}", m.call_args)
3163 } else {
3164 format!("let _ = {}; {not_mapped}", m.call_args)
3166 };
3167 builder_items.push(Line(format!("fn {} {{ {body} }}", m.signature)));
3168 }
3169 } else {
3170 trait_ok = false;
3171 }
3172 continue;
3173 };
3174 if let field::Group(_) = field.which()? {
3177 let field::Group(inst_group) = inst_field.which()? else {
3178 return Ok(Branch(vec![]));
3179 };
3180 let name = camel_to_snake_case(raw_name);
3181 let assoc = capitalize_first_letter(raw_name);
3182 let inst_mod = ctx.get_qualified_module(inst_group.get_type_id());
3183 reader_items.push(Line(format!("type {assoc} = {inst_mod}::Reader<'a>;")));
3184 reader_items.push(Line(format!(
3185 "fn get_{name}(&self) -> Self::{assoc} {{ (*self).get_{name}() }}"
3186 )));
3187 builder_items.push(Line(format!("type {assoc} = {inst_mod}::Builder<'a>;")));
3188 builder_items.push(Line(format!(
3189 "fn get_{name}(self) -> Self::{assoc} {{ self.get_{name}() }}"
3190 )));
3191 builder_items.push(Line(format!(
3192 "fn init_{name}(self) -> Self::{assoc} {{ self.init_{name}() }}"
3193 )));
3194 } else {
3195 for m in newtype_trait_methods(ctx, &field, true, true)? {
3196 let recv = if m.deref_self { "(*self)" } else { "self" };
3197 reader_items.push(Line(format!(
3198 "fn {} {{ {recv}.{}({}) }}",
3199 m.signature, m.call_name, m.call_args
3200 )));
3201 }
3202 for m in newtype_trait_methods(ctx, &field, false, true)? {
3203 let recv = if m.deref_self { "(*self)" } else { "self" };
3204 builder_items.push(Line(format!(
3205 "fn {} {{ {recv}.{}({}) }}",
3206 m.signature, m.call_name, m.call_args
3207 )));
3208 }
3209 }
3210 }
3211
3212 let reader_methods = reader_items;
3213 let builder_methods = builder_items;
3214 let trait_path = ctx.get_qualified_module(alias_id);
3215 let concrete = ctx.get_qualified_module(instance_id);
3216
3217 let mut any_items = Vec::new();
3221 {
3222 let mut offsets = Vec::new();
3223 collect_leaf_offsets(ctx, template_id, instance_id, &mut offsets)?;
3224 let n = offsets.len();
3225 let table = use_site_offsets_name(ctx, instance_id)?;
3226 any_items.push(BlankLine);
3227 any_items.push(Line(format!(
3228 "static {table}: [u32; {n}] = [{}];",
3229 offsets.join(", ")
3230 )));
3231 any_items.push(Line(format!("impl<'a> {concrete}::Reader<'a> {{")));
3232 any_items.push(indent(Line(fmt!(ctx,
3233 "pub fn as_any(self) -> {trait_path}::AnyReader<'a> {{ {trait_path}::AnyReader::new({capnp}::traits::IntoInternalStructReader::into_internal_struct_reader(self), &{table}) }}"
3234 ))));
3235 any_items.push(line("}"));
3236 any_items.push(Line(format!("impl<'a> {concrete}::Builder<'a> {{")));
3237 any_items.push(indent(Line(fmt!(ctx,
3238 "pub fn as_any(self) -> {trait_path}::AnyBuilder<'a> {{ {trait_path}::AnyBuilder::new({capnp}::traits::IntoInternalStructBuilder::into_internal_struct_builder(self), &{table}) }}"
3239 ))));
3240 any_items.push(line("}"));
3241 }
3242
3243 let mut out = Vec::new();
3246 if trait_ok {
3247 out.push(BlankLine);
3248 out.push(Line(format!(
3249 "impl<'a> {trait_path}::Reader<'a> for {concrete}::Reader<'a> {{"
3250 )));
3251 out.push(indent(reader_methods));
3252 out.push(line("}"));
3253 out.push(BlankLine);
3254 out.push(Line(format!(
3255 "impl<'a> {trait_path}::Builder<'a> for {concrete}::Builder<'a> {{"
3256 )));
3257 out.push(indent(builder_methods));
3258 out.push(line("}"));
3259 }
3260 out.push(Branch(any_items));
3261 Ok(Branch(out))
3262}
3263
3264fn union_which_generics(needs_lifetime: bool, params: &[String]) -> String {
3270 let mut all = Vec::new();
3271 if needs_lifetime {
3272 all.push("'a".to_string());
3273 }
3274 all.extend(params.iter().cloned());
3275 if all.is_empty() {
3276 String::new()
3277 } else {
3278 format!("<{}>", all.join(", "))
3279 }
3280}
3281
3282fn generate_union_newtype_trait(
3286 ctx: &GeneratorContext,
3287 node_id: u64,
3288 node_name: &str,
3289) -> ::capnp::Result<FormattedText> {
3290 use capnp::schema_capnp::*;
3291 let Some(template_id) = union_newtype_template_id(ctx, node_id)? else {
3292 return Ok(Branch(vec![]));
3293 };
3294 let node::Struct(tmpl) = ctx.node_map[&template_id].which()? else {
3295 return Ok(Branch(vec![]));
3296 };
3297
3298 let mut variants = Vec::new();
3299 let mut group_params = Vec::new();
3300 let mut reader_assoc = Vec::new();
3301 let mut reader_methods = Vec::new();
3302 let mut builder_assoc = Vec::new();
3303 let mut builder_methods = Vec::new();
3304 let mut needs_lifetime = false;
3305 for field in tmpl.get_fields()? {
3306 let variant = capitalize_first_letter(field.get_name()?.to_str()?);
3307 let name = camel_to_snake_case(field.get_name()?.to_str()?);
3308 if let field::Group(_) = field.which()? {
3309 let nested = ctx.get_qualified_module(field.get_type_id());
3310 variants.push(Line(format!("{variant}({variant}),")));
3311 group_params.push(variant.clone());
3312 reader_assoc.push(Line(format!("type {variant}: {nested}::Reader<'a>;")));
3313 builder_assoc.push(Line(format!("type {variant}: {nested}::Builder<'a>;")));
3314 builder_methods.push(Line(format!("fn init_{name}(self) -> Self::{variant};")));
3315 } else {
3316 let (payload, _, _) = getter_text(ctx, &field, true, false)?;
3317 if let field::Slot(s) = field.which()? {
3318 if s.get_type()?.is_pointer()? {
3319 needs_lifetime = true;
3320 }
3321 }
3322 variants.push(Line(format!("{variant}({payload}),")));
3323 for m in newtype_trait_methods(ctx, &field, true, false)? {
3324 reader_methods.push(Line(format!("fn {};", m.signature)));
3325 }
3326 for m in newtype_trait_methods(ctx, &field, false, false)? {
3327 builder_methods.push(Line(format!("fn {};", m.signature)));
3328 }
3329 }
3330 }
3331
3332 let which_generics = union_which_generics(needs_lifetime, &group_params);
3333 let self_params: Vec<String> = group_params.iter().map(|p| format!("Self::{p}")).collect();
3334 let which_ret = union_which_generics(needs_lifetime, &self_params);
3335
3336 let mut reader_items = reader_assoc;
3337 reader_items.push(Line(format!(
3338 "fn which(&self) -> ::core::result::Result<Which{which_ret}, ::capnp::NotInSchema>;"
3339 )));
3340 reader_items.extend(reader_methods);
3341 let mut builder_items = builder_assoc;
3342 builder_items.extend(builder_methods);
3343
3344 let mut module_items = vec![
3345 Branch(vec![
3346 Line(format!("pub enum Which{which_generics} {{")),
3347 indent(variants),
3348 line("}"),
3349 ]),
3350 line("pub trait Reader<'a> {"),
3351 indent(reader_items),
3352 line("}"),
3353 line("pub trait Builder<'a> {"),
3354 indent(builder_items),
3355 line("}"),
3356 ];
3357 let any_reader = union_any_reader_items(ctx, template_id)?;
3358 let any_builder = union_any_builder_items(ctx, template_id)?;
3359 let downcasts = any_downcast_impls(
3360 ctx,
3361 template_id,
3362 true,
3363 !any_reader.is_empty(),
3364 !any_builder.is_empty(),
3365 )?;
3366 module_items.extend(any_reader);
3367 module_items.extend(any_builder);
3368 module_items.extend(downcasts);
3369
3370 Ok(Branch(vec![
3371 BlankLine,
3372 Line(format!("pub mod {} {{", module_name(node_name))),
3373 indent(newtype_type_id_line(node_id)),
3374 indent(module_items),
3375 line("}"),
3376 ]))
3377}
3378
3379fn generate_union_newtype_impl(
3383 ctx: &GeneratorContext,
3384 alias_id: u64,
3385 instance_id: u64,
3386) -> ::capnp::Result<FormattedText> {
3387 use capnp::schema_capnp::*;
3388 let Some(template_id) = union_newtype_template_id(ctx, alias_id)? else {
3389 return Ok(Branch(vec![]));
3390 };
3391 let node::Struct(tmpl) = ctx.node_map[&template_id].which()? else {
3392 return Ok(Branch(vec![]));
3393 };
3394 let node::Struct(instance) = ctx.node_map[&instance_id].which()? else {
3395 return Ok(Branch(vec![]));
3396 };
3397
3398 let mut instance_fields = ::std::collections::HashMap::new();
3399 for field in instance.get_fields()? {
3400 instance_fields.insert(field.get_name()?.to_str()?.to_string(), field);
3401 }
3402
3403 let trait_path = ctx.get_qualified_module(alias_id);
3404 let concrete = ctx.get_qualified_module(instance_id);
3405
3406 let mut which_arms = Vec::new();
3407 let mut group_params = Vec::new();
3408 let mut reader_assoc = Vec::new();
3409 let mut reader_methods = Vec::new();
3410 let mut builder_assoc = Vec::new();
3411 let mut builder_methods = Vec::new();
3412 let mut needs_lifetime = false;
3413 for field in tmpl.get_fields()? {
3414 let raw_name = field.get_name()?.to_str()?;
3415 let Some(inst_field) = instance_fields.get(raw_name) else {
3416 return Ok(Branch(vec![]));
3417 };
3418 let variant = capitalize_first_letter(raw_name);
3419 let name = camel_to_snake_case(raw_name);
3420 which_arms.push(Line(format!(
3421 "{concrete}::Which::{variant}(x) => {trait_path}::Which::{variant}(x),"
3422 )));
3423 if let field::Group(_) = field.which()? {
3424 let field::Group(inst_group) = inst_field.which()? else {
3425 return Ok(Branch(vec![]));
3426 };
3427 let inst_mod = ctx.get_qualified_module(inst_group.get_type_id());
3428 group_params.push(variant.clone());
3429 reader_assoc.push(Line(format!("type {variant} = {inst_mod}::Reader<'a>;")));
3430 builder_assoc.push(Line(format!("type {variant} = {inst_mod}::Builder<'a>;")));
3431 builder_methods.push(Line(format!(
3432 "fn init_{name}(self) -> Self::{variant} {{ self.init_{name}() }}"
3433 )));
3434 } else {
3435 if let field::Slot(s) = field.which()? {
3436 if s.get_type()?.is_pointer()? {
3437 needs_lifetime = true;
3438 }
3439 }
3440 for m in newtype_trait_methods(ctx, &field, true, false)? {
3441 let recv = if m.deref_self { "(*self)" } else { "self" };
3442 reader_methods.push(Line(format!(
3443 "fn {} {{ {recv}.{}({}) }}",
3444 m.signature, m.call_name, m.call_args
3445 )));
3446 }
3447 for m in newtype_trait_methods(ctx, &field, false, false)? {
3448 let recv = if m.deref_self { "(*self)" } else { "self" };
3449 builder_methods.push(Line(format!(
3450 "fn {} {{ {recv}.{}({}) }}",
3451 m.signature, m.call_name, m.call_args
3452 )));
3453 }
3454 }
3455 }
3456 let self_params: Vec<String> = group_params.iter().map(|p| format!("Self::{p}")).collect();
3457 let which_ret = union_which_generics(needs_lifetime, &self_params);
3458
3459 let which_method = Branch(vec![
3460 Line(format!(
3461 "fn which(&self) -> ::core::result::Result<{trait_path}::Which{which_ret}, ::capnp::NotInSchema> {{"
3462 )),
3463 indent(vec![
3464 line("::core::result::Result::Ok(match (*self).which()? {"),
3465 indent(which_arms),
3466 line("})"),
3467 ]),
3468 line("}"),
3469 ]);
3470
3471 let mut reader_items = reader_assoc;
3472 reader_items.push(which_method);
3473 reader_items.extend(reader_methods);
3474 let mut builder_items = builder_assoc;
3475 builder_items.extend(builder_methods);
3476
3477 let mut offsets = Vec::new();
3479 collect_leaf_offsets(ctx, template_id, instance_id, &mut offsets)?;
3480 let n = offsets.len();
3481 let disc = instance.get_discriminant_offset();
3482 let table = use_site_offsets_name(ctx, instance_id)?;
3483 let any_items = vec![
3484 BlankLine,
3485 Line(format!(
3486 "static {table}: [u32; {n}] = [{}];",
3487 offsets.join(", ")
3488 )),
3489 Line(format!("impl<'a> {concrete}::Reader<'a> {{")),
3490 indent(Line(fmt!(ctx,
3491 "pub fn as_any(self) -> {trait_path}::AnyReader<'a> {{ {trait_path}::AnyReader::new({capnp}::traits::IntoInternalStructReader::into_internal_struct_reader(self), {disc}, &{table}) }}"
3492 ))),
3493 line("}"),
3494 Line(format!("impl<'a> {concrete}::Builder<'a> {{")),
3495 indent(Line(fmt!(ctx,
3496 "pub fn as_any(self) -> {trait_path}::AnyBuilder<'a> {{ {trait_path}::AnyBuilder::new({capnp}::traits::IntoInternalStructBuilder::into_internal_struct_builder(self), {disc}, &{table}) }}"
3497 ))),
3498 line("}"),
3499 ];
3500
3501 Ok(Branch(vec![
3502 BlankLine,
3503 Line(format!(
3504 "impl<'a> {trait_path}::Reader<'a> for {concrete}::Reader<'a> {{"
3505 )),
3506 indent(reader_items),
3507 line("}"),
3508 BlankLine,
3509 Line(format!(
3510 "impl<'a> {trait_path}::Builder<'a> for {concrete}::Builder<'a> {{"
3511 )),
3512 indent(builder_items),
3513 line("}"),
3514 Branch(any_items),
3515 ]))
3516}
3517
3518fn generate_scalar_newtype_alias(
3523 ctx: &GeneratorContext,
3524 node_id: u64,
3525 node_name: &str,
3526 t: schema_capnp::type_::Reader,
3527) -> ::capnp::Result<FormattedText> {
3528 use capnp::schema_capnp::*;
3529 if newtype_template_id(ctx, node_id)?.is_some() {
3530 return Ok(Branch(vec![]));
3531 }
3532 if matches!(t.which()?, type_::Struct(_) | type_::Interface(_)) {
3533 return Ok(Branch(vec![]));
3534 }
3535 let module = module_name(node_name);
3536 let items = if t.is_pointer()? {
3537 vec![
3538 Line(format!(
3539 "pub type Reader<'a> = {};",
3540 t.type_string(ctx, Leaf::Reader("'a"))?
3541 )),
3542 Line(format!(
3543 "pub type Builder<'a> = {};",
3544 t.type_string(ctx, Leaf::Builder("'a"))?
3545 )),
3546 Line(format!(
3547 "pub type Owned = {};",
3548 t.type_string(ctx, Leaf::Owned)?
3549 )),
3550 ]
3551 } else {
3552 let v = t.type_string(ctx, Leaf::Reader(""))?;
3553 vec![
3554 Line(format!("pub type Reader = {v};")),
3555 Line(format!("pub type Builder = {v};")),
3556 Line(format!("pub type Owned = {v};")),
3557 ]
3558 };
3559 Ok(Branch(vec![
3560 BlankLine,
3561 Line(format!("pub mod {module} {{")),
3562 indent(newtype_type_id_line(node_id)),
3563 indent(items),
3564 line("}"),
3565 ]))
3566}
3567
3568fn generate_node(
3569 ctx: &GeneratorContext,
3570 node_id: u64,
3571 node_name: &str,
3572) -> ::capnp::Result<FormattedText> {
3573 use capnp::schema_capnp::*;
3574
3575 let mut output: Vec<FormattedText> = Vec::new();
3576 let mut nested_output: Vec<FormattedText> = Vec::new();
3577
3578 let node_reader = &ctx.node_map[&node_id];
3579 let nested_nodes = node_reader.get_nested_nodes()?;
3580 for nested_node in nested_nodes {
3581 let id = nested_node.get_id();
3582 nested_output.push(generate_node(ctx, id, ctx.get_last_name(id)?)?);
3583 }
3584
3585 match node_reader.which()? {
3586 node::Type(Ok(t)) => {
3587 output.push(generate_newtype_trait(ctx, node_id, node_name)?);
3588 output.push(generate_scalar_newtype_alias(ctx, node_id, node_name, t)?);
3589 }
3590 node::Type(Err(e)) => {
3591 return Err(Error::failed(format!("error reading node type: {e}")));
3592 }
3593 node::File(()) => {
3594 output.push(Branch(nested_output));
3595 }
3596 node::Struct(struct_reader) => {
3597 let params = node_reader.parameters_texts(ctx);
3598 output.push(BlankLine);
3599
3600 let is_generic = node_reader.get_is_generic();
3601 if is_generic {
3602 output.push(Line(format!(
3603 "pub mod {} {{ /* {} */",
3604 node_name,
3605 params.expanded_list.join(",")
3606 )));
3607 } else {
3608 output.push(Line(format!("pub mod {node_name} {{")));
3609 }
3610 let bracketed_params = if params.params.is_empty() {
3611 "".to_string()
3612 } else {
3613 format!("<{}>", params.params)
3614 };
3615
3616 let mut preamble = Vec::new();
3617 let mut builder_members = Vec::new();
3618 let mut reader_members = Vec::new();
3619 let mut union_fields = Vec::new();
3620 let mut which_enums = Vec::new();
3621 let mut pipeline_impl_interior = Vec::new();
3622 let mut private_mod_interior = Vec::new();
3623
3624 let data_size = struct_reader.get_data_word_count();
3625 let pointer_size = struct_reader.get_pointer_count();
3626 let discriminant_count = struct_reader.get_discriminant_count();
3627 let discriminant_offset = struct_reader.get_discriminant_offset();
3628
3629 private_mod_interior.push(crate::pointer_constants::node_word_array_declaration(
3630 ctx,
3631 "ENCODED_NODE",
3632 *node_reader,
3633 crate::pointer_constants::WordArrayDeclarationOptions { pub_crate: true },
3634 )?);
3635
3636 private_mod_interior.push(generate_get_field_types(ctx, *node_reader)?);
3637 private_mod_interior.push(generate_get_annotation_types(ctx, *node_reader)?);
3638
3639 let field_newtypes = generate_field_newtypes(ctx, *node_reader)?;
3642 let mut raw_schema_end = ")".to_string();
3643 if field_newtypes.is_some() {
3644 raw_schema_end += ".with_field_newtypes(FIELD_NEWTYPES)";
3645 }
3646 if let Some(any_layout) = use_site_any_layout(ctx, *node_reader)? {
3647 raw_schema_end += &any_layout;
3648 }
3649 raw_schema_end += ";";
3650 private_mod_interior.push(Branch(vec![
3651 Line(fmt!(ctx, "pub(crate) static ARENA: {capnp}::private::arena::GeneratedCodeArena = {capnp}::private::arena::GeneratedCodeArena::new(&ENCODED_NODE);")),
3652 Line(fmt!(ctx,"pub(crate) static RAW_SCHEMA: {capnp}::introspect::RawStructSchema = {capnp}::introspect::RawStructSchema::new(")),
3653 indent(vec![
3654 Line("&ARENA,".into()),
3655 Line("NONUNION_MEMBERS,".into()),
3656 Line("MEMBERS_BY_DISCRIMINANT,".into()),
3657 Line("MEMBERS_BY_NAME".into()),
3658 ]),
3659 Line(raw_schema_end),
3660 ]));
3661 if let Some(field_newtypes) = field_newtypes {
3662 private_mod_interior.push(field_newtypes);
3663 }
3664
3665 private_mod_interior.push(generate_members_by_discriminant(*node_reader)?);
3666 private_mod_interior.push(generate_members_by_name(*node_reader)?);
3667
3668 let mut has_pointer_field = false;
3669 let fields = struct_reader.get_fields()?;
3670 for field in fields {
3671 let name = get_field_name(field)?;
3672 let styled_name = camel_to_snake_case(name);
3673
3674 let discriminant_value = field.get_discriminant_value();
3675 let is_union_field = discriminant_value != field::NO_DISCRIMINANT;
3676
3677 match field.which()? {
3678 field::Slot(s) => match s.get_type()?.which()? {
3679 type_::Text(())
3680 | type_::Data(())
3681 | type_::List(_)
3682 | type_::Struct(_)
3683 | type_::Interface(_)
3684 | type_::AnyPointer(_) => has_pointer_field = true,
3685 _ => (),
3686 },
3687 field::Group(_) => has_pointer_field = true,
3688 }
3689
3690 if !is_union_field {
3691 pipeline_impl_interior.push(generate_pipeline_getter(ctx, field)?);
3692 let (ty, get, default_decl) = getter_text(ctx, &field, true, true)?;
3693 if let Some(default) = default_decl {
3694 private_mod_interior.push(default.clone());
3695 }
3696 reader_members.push(Branch(vec![
3697 line("#[inline]"),
3698 Line(format!("pub fn get_{styled_name}(self) {ty} {{")),
3699 indent(get),
3700 line("}"),
3701 ]));
3702
3703 let (ty_b, get_b, _) = getter_text(ctx, &field, false, true)?;
3704 builder_members.push(Branch(vec![
3705 line("#[inline]"),
3706 Line(format!("pub fn get_{styled_name}(self) {ty_b} {{")),
3707 indent(get_b),
3708 line("}"),
3709 ]));
3710 } else {
3711 union_fields.push(field);
3712 }
3713
3714 builder_members.push(generate_setter(
3715 ctx,
3716 discriminant_offset,
3717 &styled_name,
3718 &field,
3719 )?);
3720
3721 reader_members.push(generate_haser(
3722 discriminant_offset,
3723 &styled_name,
3724 &field,
3725 true,
3726 )?);
3727 builder_members.push(generate_haser(
3728 discriminant_offset,
3729 &styled_name,
3730 &field,
3731 false,
3732 )?);
3733
3734 if let Ok(field::Group(group)) = field.which() {
3735 let id = group.get_type_id();
3736 let text = generate_node(ctx, id, ctx.get_last_name(id)?)?;
3737 nested_output.push(text);
3738
3739 let alias_id = field.get_type_id();
3742 if alias_id != 0 {
3743 nested_output.push(generate_newtype_impl(ctx, alias_id, id)?);
3744 }
3745 }
3746 }
3747
3748 if discriminant_count > 0 {
3749 let (which_enums1, union_getter, typedef, mut default_decls) =
3750 generate_union(ctx, discriminant_offset, &union_fields, true, ¶ms)?;
3751 which_enums.push(which_enums1);
3752 which_enums.push(typedef);
3753 reader_members.push(union_getter);
3754
3755 private_mod_interior.append(&mut default_decls);
3756
3757 let (_, union_getter, typedef, _) =
3758 generate_union(ctx, discriminant_offset, &union_fields, false, ¶ms)?;
3759 which_enums.push(typedef);
3760 builder_members.push(union_getter);
3761
3762 let mut reexports = String::new();
3763 reexports.push_str("pub use self::Which::{");
3764 let mut whichs = Vec::new();
3765 for f in &union_fields {
3766 whichs.push(capitalize_first_letter(get_field_name(*f)?));
3767 }
3768 reexports.push_str(&whichs.join(","));
3769 reexports.push_str("};");
3770 preamble.push(Line(reexports));
3771 preamble.push(BlankLine);
3772 }
3773
3774 let builder_struct_size =
3775 Branch(vec![
3776 Line(fmt!(ctx,"impl <{0}> {capnp}::traits::HasStructSize for Builder<'_,{0}> {1} {{",
3777 params.params, params.where_clause)),
3778 indent(Line(
3779 fmt!(ctx,"const STRUCT_SIZE: {capnp}::private::layout::StructSize = {capnp}::private::layout::StructSize {{ data: {}, pointers: {} }};", data_size as usize, pointer_size as usize))),
3780 line("}")]);
3781
3782 private_mod_interior.push(Line(format!(
3783 "pub(crate) const TYPE_ID: u64 = {};",
3784 format_u64(node_id)
3785 )));
3786
3787 let from_pointer_builder_impl =
3788 Branch(vec![
3789 Line(fmt!(ctx,"impl <'a,{0}> {capnp}::traits::FromPointerBuilder<'a> for Builder<'a,{0}> {1} {{", params.params, params.where_clause)),
3790 indent(vec![
3791 Line(fmt!(ctx,"fn init_pointer(builder: {capnp}::private::layout::PointerBuilder<'a>, _size: u32) -> Self {{")),
3792 indent(Line(fmt!(ctx,"builder.init_struct(<Self as {capnp}::traits::HasStructSize>::STRUCT_SIZE).into()"))),
3793 line("}"),
3794 Line(fmt!(ctx,"fn get_from_pointer(builder: {capnp}::private::layout::PointerBuilder<'a>, default: ::core::option::Option<&'a [{capnp}::Word]>) -> {capnp}::Result<Self> {{")),
3795 indent(Line(fmt!(ctx,"::core::result::Result::Ok(builder.get_struct(<Self as {capnp}::traits::HasStructSize>::STRUCT_SIZE, default)?.into())"))),
3796 line("}")
3797 ]),
3798 line("}"),
3799 BlankLine]);
3800
3801 let accessors = vec![
3802 Branch(preamble),
3803 (if !is_generic {
3804 Branch(vec![
3805 Line("#[derive(Copy, Clone)]".into()),
3806 line("pub struct Owned(());"),
3807 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() }} }}")),
3808 Line(fmt!(ctx, "impl {capnp}::traits::Owned for Owned {{ type Reader<'a> = Reader<'a>; type Builder<'a> = Builder<'a>; }}")),
3809 Line(fmt!(ctx,"impl {capnp}::traits::OwnedStruct for Owned {{ type Reader<'a> = Reader<'a>; type Builder<'a> = Builder<'a>; }}")),
3810 Line(fmt!(ctx,"impl {capnp}::traits::Pipelined for Owned {{ type Pipeline = Pipeline; }}"))
3811 ])
3812 } else {
3813 Branch(vec![
3814 Line("#[derive(Copy, Clone)]".into()),
3815 Line(format!("pub struct Owned<{}> {{", params.params)),
3816 indent(Line(params.phantom_data_type.clone())),
3817 line("}"),
3818 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() }} }}",
3819 params.params, params.where_clause)),
3820 Line(fmt!(ctx,"impl <{0}> {capnp}::traits::Owned for Owned <{0}> {1} {{ type Reader<'a> = Reader<'a, {0}>; type Builder<'a> = Builder<'a, {0}>; }}",
3821 params.params, params.where_clause)),
3822 Line(fmt!(ctx,"impl <{0}> {capnp}::traits::OwnedStruct for Owned <{0}> {1} {{ type Reader<'a> = Reader<'a, {0}>; type Builder<'a> = Builder<'a, {0}>; }}",
3823 params.params, params.where_clause)),
3824 Line(fmt!(ctx,"impl <{0}> {capnp}::traits::Pipelined for Owned<{0}> {1} {{ type Pipeline = Pipeline{2}; }}",
3825 params.params, params.where_clause, bracketed_params)),
3826 ])
3827 }),
3828 BlankLine,
3829 (if !is_generic {
3830 Line(fmt!(ctx,"pub struct Reader<'a> {{ reader: {capnp}::private::layout::StructReader<'a> }}"))
3831 } else {
3832 Branch(vec![
3833 Line(format!("pub struct Reader<'a,{}> {} {{", params.params, params.where_clause)),
3834 indent(vec![
3835 Line(fmt!(ctx,"reader: {capnp}::private::layout::StructReader<'a>,")),
3836 Line(params.phantom_data_type.clone()),
3837 ]),
3838 line("}")
3839 ])
3840 }),
3841 Branch(vec![
3844 Line(format!("impl <{0}> ::core::marker::Copy for Reader<'_,{0}> {1} {{}}",
3845 params.params, params.where_clause)),
3846 Line(format!("impl <{0}> ::core::clone::Clone for Reader<'_,{0}> {1} {{",
3847 params.params, params.where_clause)),
3848 indent(Line("fn clone(&self) -> Self { *self }".into())),
3849 Line("}".into())]),
3850 BlankLine,
3851 Branch(vec![
3852 Line(fmt!(ctx,"impl <{0}> {capnp}::traits::HasTypeId for Reader<'_,{0}> {1} {{",
3853 params.params, params.where_clause)),
3854 indent(vec![line("const TYPE_ID: u64 = _private::TYPE_ID;")]),
3855 line("}")]),
3856 Line(fmt!(ctx,"impl <'a,{0}> ::core::convert::From<{capnp}::private::layout::StructReader<'a>> for Reader<'a,{0}> {1} {{",
3857 params.params, params.where_clause)),
3858 indent(vec![
3859 Line(fmt!(ctx,"fn from(reader: {capnp}::private::layout::StructReader<'a>) -> Self {{")),
3860 indent(Line(format!("Self {{ reader, {} }}", params.phantom_data_value))),
3861 line("}")
3862 ]),
3863 line("}"),
3864 BlankLine,
3865 Line(fmt!(ctx,"impl <'a,{0}> ::core::convert::From<Reader<'a,{0}>> for {capnp}::dynamic_value::Reader<'a> {1} {{",
3866 params.params, params.where_clause)),
3867 indent(vec![
3868 Line(format!("fn from(reader: Reader<'a,{0}>) -> Self {{", params.params)),
3869 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))),
3870 line("}")
3871 ]),
3872 line("}"),
3873 BlankLine,
3874 Line(format!("impl <{0}> ::core::fmt::Debug for Reader<'_,{0}> {1} {{",
3875 params.params, params.where_clause)),
3876 indent(vec![
3877 Line("fn fmt(&self, f: &mut ::core::fmt::Formatter<'_>) -> ::core::result::Result<(), ::core::fmt::Error> {".into()),
3878 indent(Line(fmt!(ctx,"core::fmt::Debug::fmt(&::core::convert::Into::<{capnp}::dynamic_value::Reader<'_>>::into(*self), f)"))),
3879 line("}")
3880 ]),
3881 line("}"),
3882
3883 BlankLine,
3884
3885 Line(fmt!(ctx,"impl <'a,{0}> {capnp}::traits::FromPointerReader<'a> for Reader<'a,{0}> {1} {{",
3886 params.params, params.where_clause)),
3887 indent(vec![
3888 Line(fmt!(ctx,"fn get_from_pointer(reader: &{capnp}::private::layout::PointerReader<'a>, default: ::core::option::Option<&'a [{capnp}::Word]>) -> {capnp}::Result<Self> {{")),
3889 indent(line("::core::result::Result::Ok(reader.get_struct(default)?.into())")),
3890 line("}")
3891 ]),
3892 line("}"),
3893 BlankLine,
3894 Line(fmt!(ctx,"impl <'a,{0}> {capnp}::traits::IntoInternalStructReader<'a> for Reader<'a,{0}> {1} {{",
3895 params.params, params.where_clause)),
3896 indent(vec![
3897 Line(fmt!(ctx,"fn into_internal_struct_reader(self) -> {capnp}::private::layout::StructReader<'a> {{")),
3898 indent(line("self.reader")),
3899 line("}")
3900 ]),
3901 line("}"),
3902 BlankLine,
3903 Line(fmt!(ctx,"impl <'a,{0}> {capnp}::traits::Imbue<'a> for Reader<'a,{0}> {1} {{",
3904 params.params, params.where_clause)),
3905 indent(vec![
3906 Line(fmt!(ctx,"fn imbue(&mut self, cap_table: &'a {capnp}::private::layout::CapTable) {{")),
3907 indent(Line(fmt!(ctx,"self.reader.imbue({capnp}::private::layout::CapTableReader::from_ref(cap_table))"))),
3908 line("}")
3909 ]),
3910 line("}"),
3911 BlankLine,
3912 if has_pointer_field { Line(format!("impl <'a,{0}> Reader<'a,{0}> {1} {{", params.params, params.where_clause))
3914 } else {
3915 Line(format!("impl <{0}> Reader<'_,{0}> {1} {{", params.params, params.where_clause))
3916 },
3917 indent(vec![
3918 Line(format!("pub fn reborrow(&self) -> Reader<'_,{}> {{",params.params)),
3919 indent(line("Self { .. *self }")),
3920 line("}"),
3921 BlankLine,
3922 Line(fmt!(ctx,"pub fn total_size(&self) -> {capnp}::Result<{capnp}::MessageSize> {{")),
3923 indent(line("self.reader.total_size()")),
3924 line("}")]),
3925 indent(reader_members),
3926 line("}"),
3927 BlankLine,
3928 (if !is_generic {
3929 Line(fmt!(ctx,"pub struct Builder<'a> {{ builder: {capnp}::private::layout::StructBuilder<'a> }}"))
3930 } else {
3931 Branch(vec![
3932 Line(format!("pub struct Builder<'a,{}> {} {{",
3933 params.params, params.where_clause)),
3934 indent(vec![
3935 Line(fmt!(ctx, "builder: {capnp}::private::layout::StructBuilder<'a>,")),
3936 Line(params.phantom_data_type.clone()),
3937 ]),
3938 line("}")
3939 ])
3940 }),
3941 builder_struct_size,
3942 Branch(vec![
3943 Line(fmt!(ctx,"impl <{0}> {capnp}::traits::HasTypeId for Builder<'_,{0}> {1} {{",
3944 params.params, params.where_clause)),
3945 indent(vec![
3946 line("const TYPE_ID: u64 = _private::TYPE_ID;")]),
3947 line("}")
3948 ]),
3949 Line(fmt!(ctx,
3950 "impl <'a,{0}> ::core::convert::From<{capnp}::private::layout::StructBuilder<'a>> for Builder<'a,{0}> {1} {{",
3951 params.params, params.where_clause)),
3952 indent(vec![
3953 Line(fmt!(ctx,"fn from(builder: {capnp}::private::layout::StructBuilder<'a>) -> Self {{")),
3954 indent(Line(format!("Self {{ builder, {} }}", params.phantom_data_value))),
3955 line("}")
3956 ]),
3957 line("}"),
3958 BlankLine,
3959 Line(fmt!(ctx,"impl <'a,{0}> {capnp}::traits::IntoInternalStructBuilder<'a> for Builder<'a,{0}> {1} {{",
3960 params.params, params.where_clause)),
3961 indent(vec![
3962 Line(fmt!(ctx,"fn into_internal_struct_builder(self) -> {capnp}::private::layout::StructBuilder<'a> {{")),
3963 indent(line("self.builder")),
3964 line("}")
3965 ]),
3966 line("}"),
3967 BlankLine,
3968 Line(fmt!(ctx,"impl <'a,{0}> ::core::convert::From<Builder<'a,{0}>> for {capnp}::dynamic_value::Builder<'a> {1} {{",
3969 params.params, params.where_clause)),
3970 indent(vec![
3971 Line(format!("fn from(builder: Builder<'a,{0}>) -> Self {{", params.params)),
3972 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))),
3973 line("}")
3974 ]),
3975 line("}"),
3976 BlankLine,
3977
3978 Line(fmt!(ctx,"impl <'a,{0}> {capnp}::traits::ImbueMut<'a> for Builder<'a,{0}> {1} {{",
3979 params.params, params.where_clause)),
3980 indent(vec![
3981 Line(fmt!(ctx,"fn imbue_mut(&mut self, cap_table: &'a mut {capnp}::private::layout::CapTable) {{")),
3982 indent(Line(fmt!(ctx,"self.builder.imbue({capnp}::private::layout::CapTableBuilder::from_ref(cap_table))"))),
3983 line("}")]),
3984 line("}"),
3985 BlankLine,
3986
3987 from_pointer_builder_impl,
3988 Line(fmt!(ctx,
3989 "impl <{0}> {capnp}::traits::SetterInput<Owned<{0}>> for Reader<'_,{0}> {1} {{",
3990 params.params, params.where_clause)),
3991 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) }}"))),
3992 line("}"),
3993 BlankLine,
3994 Line(format!("impl <'a,{0}> Builder<'a,{0}> {1} {{", params.params, params.where_clause)),
3995 indent(vec![
3996 Line(format!("pub fn into_reader(self) -> Reader<'a,{}> {{", params.params)),
3997 indent(line("self.builder.into_reader().into()")),
3998 line("}"),
3999 Line(format!("pub fn reborrow(&mut self) -> Builder<'_,{}> {{", params.params)),
4000 (if !is_generic {
4001 indent(line("Builder { builder: self.builder.reborrow() }"))
4002 } else {
4003 indent(line("Builder { builder: self.builder.reborrow(), ..*self }"))
4004 }),
4005 line("}"),
4006 Line(format!("pub fn reborrow_as_reader(&self) -> Reader<'_,{}> {{", params.params)),
4007 indent(line("self.builder.as_reader().into()")),
4008 line("}"),
4009
4010 BlankLine,
4011 Line(fmt!(ctx,"pub fn total_size(&self) -> {capnp}::Result<{capnp}::MessageSize> {{")),
4012 indent(line("self.builder.as_reader().total_size()")),
4013 line("}")
4014 ]),
4015 indent(builder_members),
4016 line("}"),
4017 BlankLine,
4018 (if is_generic {
4019 Branch(vec![
4020 Line(format!("pub struct Pipeline{bracketed_params} {{")),
4021 indent(vec![
4022 Line(fmt!(ctx,"_typeless: {capnp}::any_pointer::Pipeline,")),
4023 Line(params.phantom_data_type),
4024 ]),
4025 line("}")
4026 ])
4027 } else {
4028 Line(fmt!(ctx,"pub struct Pipeline {{ _typeless: {capnp}::any_pointer::Pipeline }}"))
4029 }),
4030 Line(fmt!(ctx,"impl{bracketed_params} {capnp}::capability::FromTypelessPipeline for Pipeline{bracketed_params} {{")),
4031 indent(vec![
4032 Line(fmt!(ctx,"fn new(typeless: {capnp}::any_pointer::Pipeline) -> Self {{")),
4033 indent(Line(format!("Self {{ _typeless: typeless, {} }}", params.phantom_data_value))),
4034 line("}")]),
4035 line("}"),
4036 Line(format!("impl{0} Pipeline{0} {1} {{", bracketed_params,
4037 params.pipeline_where_clause)),
4038 indent(pipeline_impl_interior),
4039 line("}"),
4040 line("mod _private {"),
4041 indent(private_mod_interior),
4042 line("}"),
4043 ];
4044
4045 output.push(indent(vec![
4046 Branch(accessors),
4047 Branch(which_enums),
4048 Branch(nested_output),
4049 ]));
4050 output.push(line("}"));
4051 }
4052
4053 node::Enum(enum_reader) => {
4054 let last_name = ctx.get_last_name(node_id)?;
4055 let name_as_mod = module_name(last_name);
4056 output.push(BlankLine);
4057
4058 let mut members = Vec::new();
4059 let mut match_branches = Vec::new();
4060 let enumerants = enum_reader.get_enumerants()?;
4061 for (ii, enumerant) in enumerants.into_iter().enumerate() {
4062 let enumerant = capitalize_first_letter(get_enumerant_name(enumerant)?);
4063 members.push(Line(format!("{enumerant} = {ii},")));
4064 match_branches.push(Line(format!(
4065 "{ii} => ::core::result::Result::Ok(Self::{enumerant}),"
4066 )));
4067 }
4068 match_branches.push(Line(fmt!(
4069 ctx,
4070 "n => ::core::result::Result::Err({capnp}::NotInSchema(n)),"
4071 )));
4072
4073 output.push(Branch(vec![
4074 line("#[repr(u16)]"),
4075 line("#[derive(Clone, Copy, Debug, PartialEq, Eq)]"),
4076 Line(format!("pub enum {last_name} {{")),
4077 indent(members),
4078 line("}"),
4079 ]));
4080
4081 output.push(BlankLine);
4082 output.push(Branch(vec![
4083 Line(fmt!(ctx,
4084 "impl {capnp}::introspect::Introspect for {last_name} {{"
4085 )),
4086 indent(Line(fmt!(ctx,
4087 "fn introspect() -> {capnp}::introspect::Type {{ {capnp}::introspect::TypeVariant::Enum({capnp}::introspect::RawEnumSchema::new(&{0}::ARENA, {0}::get_annotation_types)).into() }}", name_as_mod))),
4088 Line("}".into()),
4089 ]));
4090
4091 output.push(Branch(vec![
4092 Line(fmt!(ctx,"impl ::core::convert::From<{last_name}> for {capnp}::dynamic_value::Reader<'_> {{")),
4093 indent(Line(fmt!(ctx,
4094 "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 ))),
4095 Line("}".into())
4096 ]));
4097
4098 output.push(Branch(vec![
4099 Line(format!(
4100 "impl ::core::convert::TryFrom<u16> for {last_name} {{"
4101 )),
4102 indent(Line(
4103 fmt!(ctx,"type Error = {capnp}::NotInSchema;"),
4104 )),
4105 indent(vec![
4106 Line(
4107 format!("fn try_from(value: u16) -> ::core::result::Result<Self, <{last_name} as ::core::convert::TryFrom<u16>>::Error> {{")
4108 ),
4109 indent(vec![
4110 line("match value {"),
4111 indent(match_branches),
4112 line("}"),
4113 ]),
4114 line("}"),
4115 ]),
4116 line("}"),
4117 Line(format!("impl From<{last_name}> for u16 {{")),
4118 indent(line("#[inline]")),
4119 indent(Line(format!(
4120 "fn from(x: {last_name}) -> u16 {{ x as u16 }}"
4121 ))),
4122 line("}"),
4123 ]));
4124
4125 output.push(Branch(vec![
4126 Line(fmt!(
4127 ctx,
4128 "impl {capnp}::traits::HasTypeId for {last_name} {{"
4129 )),
4130 indent(Line(format!(
4131 "const TYPE_ID: u64 = {}u64;",
4132 format_u64(node_id)
4133 ))),
4134 line("}"),
4135 ]));
4136
4137 output.push(Branch(vec![
4138 Line(format!("mod {name_as_mod} {{")),
4139 Branch(vec![
4140 crate::pointer_constants::node_word_array_declaration(
4141 ctx,
4142 "ENCODED_NODE",
4143 *node_reader,
4144 crate::pointer_constants::WordArrayDeclarationOptions { pub_crate: true },
4145 )?,
4146 generate_get_annotation_types(ctx, *node_reader)?,
4147 Line(fmt!(ctx, "pub(crate) static ARENA: {capnp}::private::arena::GeneratedCodeArena = {capnp}::private::arena::GeneratedCodeArena::new(&ENCODED_NODE);")),
4148 ]),
4149 Line("}".into()),
4150 ]));
4151 }
4152
4153 node::Interface(interface) => {
4154 let params = node_reader.parameters_texts(ctx);
4155 output.push(BlankLine);
4156
4157 let is_generic = node_reader.get_is_generic();
4158
4159 let names = &ctx.scope_map[&node_id];
4160 let mut client_impl_interior = Vec::new();
4161 let mut server_interior = Vec::new();
4162 let mut mod_interior = Vec::new();
4163 let mut dispatch_arms = Vec::new();
4164 let mut private_mod_interior = Vec::new();
4165
4166 let bracketed_params = if params.params.is_empty() {
4167 "".to_string()
4168 } else {
4169 format!("<{}>", params.params)
4170 };
4171
4172 private_mod_interior.push(Line(format!(
4173 "pub(crate) const TYPE_ID: u64 = {};",
4174 format_u64(node_id)
4175 )));
4176
4177 mod_interior.push(line("#![allow(unused_variables)]"));
4178
4179 let methods = interface.get_methods()?;
4180 for (ordinal, method) in methods.into_iter().enumerate() {
4181 let name = method.get_name()?.to_str()?;
4182
4183 let param_id = method.get_param_struct_type();
4184 let param_node = &ctx.node_map[¶m_id];
4185 let (param_scopes, params_ty_params) = if param_node.get_scope_id() == 0 {
4186 let mut names = names.clone();
4187 let local_name = module_name(&format!("{name}Params"));
4188 nested_output.push(generate_node(ctx, param_id, &local_name)?);
4189 names.push(local_name);
4190 (names, params.params.clone())
4191 } else {
4192 (
4193 ctx.scope_map[¶m_node.get_id()].clone(),
4194 get_ty_params_of_brand(ctx, method.get_param_brand()?)?,
4195 )
4196 };
4197 let param_type = do_branding(
4198 ctx,
4199 param_id,
4200 method.get_param_brand()?,
4201 Leaf::Owned,
4202 ¶m_scopes.join("::"),
4203 )?;
4204
4205 mod_interior.push(Line(fmt!(
4206 ctx,
4207 "pub type {}Params<{}> = {capnp}::capability::Params<{}>;",
4208 capitalize_first_letter(name),
4209 params_ty_params,
4210 param_type
4211 )));
4212
4213 let result_id = method.get_result_struct_type();
4214 if result_id != STREAM_RESULT_ID {
4215 dispatch_arms.push(
4216 Line(fmt!(ctx,
4217 "{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),",
4218 module_name(name))));
4219
4220 let result_node = &ctx.node_map[&result_id];
4221 let (result_scopes, results_ty_params) = if result_node.get_scope_id() == 0 {
4222 let mut names = names.clone();
4223 let local_name = module_name(&format!("{name}Results"));
4224 nested_output.push(generate_node(ctx, result_id, &local_name)?);
4225 names.push(local_name);
4226 (names, params.params.clone())
4227 } else {
4228 (
4229 ctx.scope_map[&result_node.get_id()].clone(),
4230 get_ty_params_of_brand(ctx, method.get_result_brand()?)?,
4231 )
4232 };
4233 let result_type = do_branding(
4234 ctx,
4235 result_id,
4236 method.get_result_brand()?,
4237 Leaf::Owned,
4238 &result_scopes.join("::"),
4239 )?;
4240 mod_interior.push(Line(fmt!(
4241 ctx,
4242 "pub type {}Results<{}> = {capnp}::capability::Results<{}>;",
4243 capitalize_first_letter(name),
4244 results_ty_params,
4245 result_type
4246 )));
4247 server_interior.push(
4248 Line(fmt!(ctx,
4249 "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()))) }}",
4250 module_name(name),
4251 capitalize_first_letter(name), params_ty_params,
4252 capitalize_first_letter(name), results_ty_params,
4253 node_name, module_name(name)
4254 )));
4255
4256 client_impl_interior.push(Line(fmt!(
4257 ctx,
4258 "pub fn {}_request(&self) -> {capnp}::capability::Request<{},{}> {{",
4259 camel_to_snake_case(name),
4260 param_type,
4261 result_type
4262 )));
4263
4264 client_impl_interior.push(indent(Line(format!(
4265 "self.client.new_call(_private::TYPE_ID, {ordinal}, ::core::option::Option::None)"
4266 ))));
4267 client_impl_interior.push(line("}"));
4268 } else {
4269 dispatch_arms.push(
4271 Line(fmt!(ctx,
4272 "{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),",
4273
4274 module_name(name))));
4275
4276 server_interior.push(
4277 Line(fmt!(ctx,
4278 "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()))) }}",
4279 module_name(name),
4280 capitalize_first_letter(name), params_ty_params,
4281 node_name, module_name(name)
4282 )));
4283 client_impl_interior.push(Line(fmt!(
4284 ctx,
4285 "pub fn {}_request(&self) -> {capnp}::capability::StreamingRequest<{}> {{",
4286 camel_to_snake_case(name),
4287 param_type
4288 )));
4289 client_impl_interior.push(indent(Line(format!(
4290 "self.client.new_streaming_call(_private::TYPE_ID, {ordinal}, ::core::option::Option::None)"
4291 ))));
4292
4293 client_impl_interior.push(line("}"));
4294 }
4295
4296 method.get_annotations()?;
4297 }
4298
4299 let mut base_dispatch_arms = Vec::new();
4300
4301 let server_base = {
4302 let mut base_traits = Vec::new();
4303
4304 fn find_super_interfaces<'a>(
4305 interface: schema_capnp::node::interface::Reader<'a>,
4306 all_extends: &mut Vec<
4307 <schema_capnp::superclass::Owned as capnp::traits::OwnedStruct>::Reader<'a>,
4308 >,
4309 ctx: &GeneratorContext<'a>,
4310 ) -> ::capnp::Result<()> {
4311 let extends = interface.get_superclasses()?;
4312 for superclass in extends {
4313 if let node::Interface(interface) =
4314 ctx.node_map[&superclass.get_id()].which()?
4315 {
4316 find_super_interfaces(interface, all_extends, ctx)?;
4317 }
4318 all_extends.push(superclass);
4319 }
4320 Ok(())
4321 }
4322
4323 let mut extends = Vec::new();
4324 find_super_interfaces(interface, &mut extends, ctx)?;
4325 for interface in &extends {
4326 let type_id = interface.get_id();
4327 let brand = interface.get_brand()?;
4328 let the_mod = ctx.get_qualified_module(type_id);
4329
4330 base_dispatch_arms.push(Line(format!(
4331 "0x{type_id:x} => {}::dispatch_call_internal(self.server, method_id, params, results),",
4332 do_branding(
4333 ctx, type_id, brand, Leaf::ServerDispatch, &the_mod)?)));
4334 base_traits.push(do_branding(ctx, type_id, brand, Leaf::Server, &the_mod)?);
4335 }
4336
4337 if !extends.is_empty() {
4340 format!(": {} + 'static", base_traits.join(" + "))
4341 } else {
4342 ": 'static".to_string()
4343 }
4344 };
4345
4346 mod_interior.push(BlankLine);
4347 mod_interior.push(Line(format!("pub struct Client{bracketed_params} {{")));
4348 mod_interior.push(indent(Line(fmt!(
4349 ctx,
4350 "pub client: {capnp}::capability::Client,"
4351 ))));
4352 if is_generic {
4353 mod_interior.push(indent(Line(params.phantom_data_type.clone())));
4354 }
4355 mod_interior.push(line("}"));
4356 mod_interior.push(
4357 Branch(vec![
4358 Line(fmt!(ctx,"impl {bracketed_params} {capnp}::capability::FromClientHook for Client{bracketed_params} {{")),
4359 indent(Line(fmt!(ctx,"fn new(hook: Box<{capnp}::capability::DynClientHook>) -> Self {{"))),
4360 indent(indent(Line(fmt!(ctx,"Self {{ client: {capnp}::capability::Client::new(hook), {} }}", params.phantom_data_value)))),
4361 indent(line("}")),
4362 indent(Line(fmt!(ctx,"fn into_client_hook(self) -> Box<{capnp}::capability::DynClientHook> {{"))),
4363 indent(indent(line("self.client.hook"))),
4364 indent(line("}")),
4365 indent(Line(fmt!(ctx,"fn as_client_hook(&self) -> &{capnp}::capability::DynClientHook {{"))),
4366 indent(indent(line("&*self.client.hook"))),
4367 indent(line("}")),
4368 line("}")]));
4369
4370 mod_interior.push(if !is_generic {
4371 Branch(vec![
4372 Line("#[derive(Copy, Clone)]".into()),
4373 line("pub struct Owned(());"),
4374 Line(fmt!(ctx,"impl {capnp}::introspect::Introspect for Owned {{ fn introspect() -> {capnp}::introspect::Type {{ {capnp}::introspect::TypeVariant::Capability.into() }} }}")),
4375 Line(fmt!(ctx,"impl {capnp}::traits::Owned for Owned {{ type Reader<'a> = Client; type Builder<'a> = Client; }}")),
4376 Line(fmt!(ctx,"impl {capnp}::traits::Pipelined for Owned {{ type Pipeline = Client; }}"))])
4377 } else {
4378 Branch(vec![
4379 Line("#[derive(Copy, Clone)]".into()),
4380 Line(format!("pub struct Owned<{}> {} {{", params.params, params.where_clause)),
4381 indent(Line(params.phantom_data_type.clone())),
4382 line("}"),
4383 Line(fmt!(ctx,
4384 "impl <{0}> {capnp}::introspect::Introspect for Owned <{0}> {1} {{ fn introspect() -> {capnp}::introspect::Type {{ {capnp}::introspect::TypeVariant::Capability.into() }} }}",
4385 params.params, params.where_clause)),
4386 Line(fmt!(ctx,
4387 "impl <{0}> {capnp}::traits::Owned for Owned <{0}> {1} {{ type Reader<'a> = Client<{0}>; type Builder<'a> = Client<{0}>; }}",
4388 params.params, params.where_clause)),
4389 Line(fmt!(ctx,
4390 "impl <{0}> {capnp}::traits::Pipelined for Owned <{0}> {1} {{ type Pipeline = Client{2}; }}",
4391 params.params, params.where_clause, bracketed_params))])
4392 });
4393
4394 mod_interior.push(Branch(vec![
4395 Line(fmt!(ctx,"impl <'a,{0}> {capnp}::traits::FromPointerReader<'a> for Client<{0}> {1} {{",
4396 params.params, params.where_clause)),
4397 indent(vec![
4398 Line(fmt!(ctx,"fn get_from_pointer(reader: &{capnp}::private::layout::PointerReader<'a>, _default: ::core::option::Option<&'a [{capnp}::Word]>) -> {capnp}::Result<Self> {{")),
4399 indent(Line(fmt!(ctx,"::core::result::Result::Ok({capnp}::capability::FromClientHook::new(reader.get_capability()?))"))),
4400 line("}")]),
4401 line("}")]));
4402
4403 mod_interior.push(Branch(vec![
4404 Line(fmt!(ctx,"impl <'a,{0}> {capnp}::traits::FromPointerBuilder<'a> for Client<{0}> {1} {{",
4405 params.params, params.where_clause)),
4406 indent(vec![
4407 Line(fmt!(ctx,"fn init_pointer(_builder: {capnp}::private::layout::PointerBuilder<'a>, _size: u32) -> Self {{")),
4408 indent(line("unimplemented!()")),
4409 line("}"),
4410 Line(fmt!(ctx,"fn get_from_pointer(builder: {capnp}::private::layout::PointerBuilder<'a>, _default: ::core::option::Option<&'a [{capnp}::Word]>) -> {capnp}::Result<Self> {{")),
4411 indent(Line(fmt!(ctx,"::core::result::Result::Ok({capnp}::capability::FromClientHook::new(builder.get_capability()?))"))),
4412 line("}")]),
4413 line("}"),
4414 BlankLine]));
4415
4416 mod_interior.push(Branch(vec![
4417 Line(fmt!(ctx,
4418 "impl <{0}> {capnp}::traits::SetterInput<Owned<{0}>> for Client<{0}> {1} {{",
4419 params.params, params.where_clause)),
4420 indent(vec![
4421 Line(fmt!(ctx,"fn set_pointer_builder(mut pointer: {capnp}::private::layout::PointerBuilder<'_>, from: Self, _canonicalize: bool) -> {capnp}::Result<()> {{")),
4422 indent(Line("pointer.set_capability(from.client.hook);".to_string())),
4423 indent(Line("::core::result::Result::Ok(())".to_string())),
4424 line("}")
4425 ]
4426 ),
4427 line("}")]));
4428
4429 mod_interior.push(Branch(vec![
4430 Line(fmt!(ctx,
4431 "impl {bracketed_params} {capnp}::traits::HasTypeId for Client{bracketed_params} {{"
4432 )),
4433 indent(Line(
4434 "const TYPE_ID: u64 = _private::TYPE_ID;".to_string(),
4435 )),
4436 line("}"),
4437 ]));
4438
4439 mod_interior.push(Branch(vec![
4440 Line(format!(
4441 "impl {bracketed_params} Clone for Client{bracketed_params} {{"
4442 )),
4443 indent(line("fn clone(&self) -> Self {")),
4444 indent(indent(Line(format!(
4445 "Self {{ client: self.client.clone(), {} }}",
4446 params.phantom_data_value
4447 )))),
4448 indent(line("}")),
4449 line("}"),
4450 ]));
4451
4452 mod_interior.push(Branch(vec![
4453 Line(format!(
4454 "impl {bracketed_params} Client{bracketed_params} {{"
4455 )),
4456 indent(client_impl_interior),
4457 line("}"),
4458 ]));
4459
4460 mod_interior.push(Branch(vec![
4461 Line(format!(
4462 "pub trait Server<{}> {} {} {{",
4463 params.params, server_base, params.where_clause
4464 )),
4465 indent(server_interior),
4466 line("}"),
4467 ]));
4468
4469 mod_interior.push(Branch(vec![
4470 Line(format!(
4471 "pub struct ServerDispatch<_T,{}> {{",
4472 params.params
4473 )),
4474 indent(line(fmt!(ctx, "pub server: {capnp}::capability::Rc<_T>,"))),
4475 indent(if is_generic {
4476 vec![Line(params.phantom_data_type.clone())]
4477 } else {
4478 vec![]
4479 }),
4480 line("}"),
4481 ]));
4482
4483 mod_interior.push(Branch(vec![
4484 Line(
4485 fmt!(ctx,"impl <_S: Server{1} + 'static, {0}> {capnp}::capability::FromServer<_S> for Client{1} {2} {{",
4486 params.params, bracketed_params, params.where_clause)),
4487 indent(vec![
4488 Line(format!("type Dispatch = ServerDispatch<_S, {}>;", params.params)),
4489 Line(fmt!(ctx, "fn from_server(s: {capnp}::capability::Rc<_S>) -> ServerDispatch<_S, {}> {{", params.params)),
4490 indent(Line(format!("ServerDispatch {{ server: s, {} }}", params.phantom_data_value))),
4491 line("}"),
4492 ]),
4493 line("}"),
4494 ]));
4495
4496 mod_interior.push(
4497 Branch(vec![
4498 (if is_generic {
4499 Line(format!("impl <{}, _T: Server{}> ::core::ops::Deref for ServerDispatch<_T,{}> {} {{", params.params, bracketed_params, params.params, params.where_clause))
4500 } else {
4501 line("impl <_T: Server> ::core::ops::Deref for ServerDispatch<_T> {")
4502 }),
4503 indent(line("type Target = _T;")),
4504 indent(line("fn deref(&self) -> &_T { &self.server}")),
4505 line("}"),
4506 ]));
4507
4508 mod_interior.push(
4509 Branch(vec![
4510 (if is_generic {
4511 Line(format!("impl <{}, _T: Server{}> ::core::clone::Clone for ServerDispatch<_T,{}> {} {{", params.params, bracketed_params, params.params, params.where_clause))
4512 } else {
4513 line("impl <_T: Server> ::core::clone::Clone for ServerDispatch<_T> {")
4514 }),
4515 indent(line(
4516 format!("fn clone(&self) -> Self {{ Self {{ server: self.server.clone(), {} }} }}", params.phantom_data_value))),
4517 line("}"),
4518 ]));
4519
4520 mod_interior.push(
4521 Branch(vec![
4522 (if is_generic {
4523 Line(fmt!(ctx,"impl <{}, _T: Server{}> {capnp}::capability::Server for ServerDispatch<_T,{}> {} {{", params.params, bracketed_params, params.params, params.where_clause))
4524 } else {
4525 Line(fmt!(ctx,"impl <_T: Server> {capnp}::capability::Server for ServerDispatch<_T> {{"))
4526 }),
4527 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 {{"))),
4528 indent(indent(line("match interface_id {"))),
4529 indent(indent(indent(line("_private::TYPE_ID => Self::dispatch_call_internal(self.server, method_id, params, results),")))),
4530 indent(indent(indent(base_dispatch_arms))),
4531 indent(indent(indent(Line(fmt!(ctx,"_ => {{ {capnp}::capability::DispatchCallResult::new({capnp}::capability::Promise::err({capnp}::Error::unimplemented(\"Method not implemented.\".to_string())), false) }}"))))),
4532 indent(indent(line("}"))),
4533 indent(line("}")),
4534
4535 indent(Line(fmt!(ctx, "fn as_ptr(&self) -> usize {{ {capnp}::capability::Rc::as_ptr(&self.server) as usize }}"))),
4536
4537 line("}")]));
4538
4539 mod_interior.push(
4540 Branch(vec![
4541 (if is_generic {
4542 Line(format!("impl <{}, _T: Server{}> ServerDispatch<_T,{}> {} {{", params.params, bracketed_params, params.params, params.where_clause))
4543 } else {
4544 line("impl <_T :Server> ServerDispatch<_T> {")
4545 }),
4546
4547 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 {{"))),
4548 indent(indent(line("match method_id {"))),
4549 indent(indent(indent(dispatch_arms))),
4550 indent(indent(indent(Line(fmt!(ctx,"_ => {{ {capnp}::capability::DispatchCallResult::new({capnp}::capability::Promise::err({capnp}::Error::unimplemented(\"Method not implemented.\".to_string())), false) }}"))))),
4551 indent(indent(line("}"))),
4552 indent(line("}")),
4553 line("}")]));
4554
4555 mod_interior.push(Branch(vec![
4556 line("pub(crate) mod _private {"),
4557 indent(private_mod_interior),
4558 line("}"),
4559 ]));
4560
4561 mod_interior.push(Branch(vec![Branch(nested_output)]));
4562
4563 output.push(BlankLine);
4564 if is_generic {
4565 output.push(Line(format!(
4566 "pub mod {} {{ /* ({}) */",
4567 node_name,
4568 params.expanded_list.join(",")
4569 )));
4570 } else {
4571 output.push(Line(format!("pub mod {node_name} {{")));
4572 }
4573 output.push(indent(mod_interior));
4574 output.push(line("}"));
4575 }
4576
4577 node::Const(c) => {
4578 let styled_name = ctx.get_last_name(node_id)?.to_ascii_uppercase();
4579
4580 let typ = c.get_type()?;
4581 let formatted_text = match (typ.which()?, c.get_value()?.which()?) {
4582 (type_::Void(()), value::Void(())) => {
4583 Line(format!("pub const {styled_name}: () = ();"))
4584 }
4585 (type_::Bool(()), value::Bool(b)) => {
4586 Line(format!("pub const {styled_name}: bool = {b};"))
4587 }
4588 (type_::Int8(()), value::Int8(i)) => {
4589 Line(format!("pub const {styled_name}: i8 = {i};"))
4590 }
4591 (type_::Int16(()), value::Int16(i)) => {
4592 Line(format!("pub const {styled_name}: i16 = {i};"))
4593 }
4594 (type_::Int32(()), value::Int32(i)) => {
4595 Line(format!("pub const {styled_name}: i32 = {i};"))
4596 }
4597 (type_::Int64(()), value::Int64(i)) => {
4598 Line(format!("pub const {styled_name}: i64 = {i};"))
4599 }
4600 (type_::Uint8(()), value::Uint8(i)) => {
4601 Line(format!("pub const {styled_name}: u8 = {i};"))
4602 }
4603 (type_::Uint16(()), value::Uint16(i)) => {
4604 Line(format!("pub const {styled_name}: u16 = {i};"))
4605 }
4606 (type_::Uint32(()), value::Uint32(i)) => {
4607 Line(format!("pub const {styled_name}: u32 = {i};"))
4608 }
4609 (type_::Uint64(()), value::Uint64(i)) => {
4610 Line(format!("pub const {styled_name}: u64 = {i};"))
4611 }
4612
4613 (type_::Float32(()), value::Float32(f)) => {
4614 let literal = match f.classify() {
4615 std::num::FpCategory::Nan => "f32::NAN".into(),
4616 std::num::FpCategory::Infinite => {
4617 if f.is_sign_positive() {
4618 "f32::INFINITY".into()
4619 } else {
4620 "f32::NEG_INFINITY".into()
4621 }
4622 }
4623 _ => format!("{f:e}"),
4624 };
4625 Line(format!("pub const {styled_name}: f32 = {literal};"))
4626 }
4627
4628 (type_::Float64(()), value::Float64(f)) => {
4629 let literal = match f.classify() {
4630 std::num::FpCategory::Nan => "f64::NAN".into(),
4631 std::num::FpCategory::Infinite => {
4632 if f.is_sign_positive() {
4633 "f64::INFINITY".into()
4634 } else {
4635 "f64::NEG_INFINITY".into()
4636 }
4637 }
4638 _ => format!("{f:e}"),
4639 };
4640 Line(format!("pub const {styled_name}: f64 = {literal};"))
4641 }
4642
4643 (type_::Enum(e), value::Enum(v)) => {
4644 if let Some(node) = ctx.node_map.get(&e.get_type_id()) {
4645 match node.which()? {
4646 node::Enum(e) => {
4647 let enumerants = e.get_enumerants()?;
4648 if let Some(enumerant) = enumerants.try_get(u32::from(v)) {
4649 let variant =
4650 capitalize_first_letter(get_enumerant_name(enumerant)?);
4651 let type_string = typ.type_string(ctx, Leaf::Owned)?;
4652 Line(format!(
4653 "pub const {}: {} = {}::{};",
4654 styled_name, type_string, type_string, variant
4655 ))
4656 } else {
4657 return Err(Error::failed(format!(
4658 "enumerant out of range: {v}"
4659 )));
4660 }
4661 }
4662 _ => {
4663 return Err(Error::failed(format!(
4664 "bad enum type ID: {}",
4665 e.get_type_id()
4666 )));
4667 }
4668 }
4669 } else {
4670 return Err(Error::failed(format!(
4671 "bad enum type ID: {}",
4672 e.get_type_id()
4673 )));
4674 }
4675 }
4676
4677 (type_::Text(()), value::Text(t)) => Line(format!(
4678 "pub const {styled_name}: &str = {:?};",
4679 t?.to_str()?
4680 )),
4681 (type_::Data(()), value::Data(d)) => {
4682 Line(format!("pub const {styled_name}: &[u8] = &{:?};", d?))
4683 }
4684
4685 (type_::List(_), value::List(v)) => {
4686 generate_pointer_constant(ctx, &styled_name, typ, v)?
4687 }
4688 (type_::Struct(_), value::Struct(v)) => {
4689 generate_pointer_constant(ctx, &styled_name, typ, v)?
4690 }
4691
4692 (type_::Interface(_t), value::Interface(())) => {
4693 return Err(Error::unimplemented("interface constants".to_string()));
4694 }
4695 (type_::AnyPointer(_), value::AnyPointer(_pr)) => {
4696 return Err(Error::unimplemented("anypointer constants".to_string()));
4697 }
4698
4699 _ => {
4700 return Err(Error::failed("type does not match value".to_string()));
4701 }
4702 };
4703
4704 output.push(formatted_text);
4705 }
4706
4707 node::Annotation(annotation_reader) => {
4708 let is_generic = node_reader.get_is_generic();
4709 let params = node_reader.parameters_texts(ctx);
4710 let last_name = ctx.get_last_name(node_id)?;
4711 let mut interior = vec![];
4712 interior.push(Line(format!("pub const ID: u64 = 0x{node_id:x};")));
4713
4714 let ty = annotation_reader.get_type()?;
4715 if !is_generic {
4716 interior.push(Line(fmt!(ctx,
4717 "pub fn get_type() -> {capnp}::introspect::Type {{ <{} as {capnp}::introspect::Introspect>::introspect() }}", ty.type_string(ctx, Leaf::Owned)?)));
4718 } else {
4719 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)?)));
4720 }
4721 output.push(Branch(vec![
4722 Line(format!("pub mod {last_name} {{")),
4723 indent(interior),
4724 Line("}".into()),
4725 ]));
4726 }
4727 }
4728
4729 Ok(Branch(output))
4730}
4731
4732