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 snake_to_upper_case(s: &str) -> String {
404 let mut result_chars: Vec<char> = Vec::new();
405 for c in s.chars() {
406 if c == '_' {
407 result_chars.push('_');
408 } else {
409 result_chars.push(c.to_ascii_uppercase());
410 }
411 }
412 result_chars.into_iter().collect()
413}
414
415fn camel_to_snake_case(s: &str) -> String {
416 let mut result_chars: Vec<char> = Vec::new();
417 let mut first_char = true;
418 for c in s.chars() {
419 if c.is_uppercase() && !first_char {
420 result_chars.push('_');
421 }
422 result_chars.push(c.to_ascii_lowercase());
423 first_char = false;
424 }
425 result_chars.into_iter().collect()
426}
427
428fn capitalize_first_letter(s: &str) -> String {
429 let mut result_chars: Vec<char> = Vec::new();
430 for c in s.chars() {
431 result_chars.push(c)
432 }
433 result_chars[0] = result_chars[0].to_ascii_uppercase();
434 result_chars.into_iter().collect()
435}
436
437fn format_u64(value: u64) -> String {
442 let hex = format!("{value:#x}");
443 let mut separated = hex[0..2].to_string();
444 let mut place = hex.len() - 2;
445 let mut later_loop = false;
446
447 for ch in hex[2..].chars() {
448 if later_loop && place % 4 == 0 {
449 separated.push('_');
450 }
451
452 separated.push(ch);
453 later_loop = true;
454 place -= 1;
455 }
456
457 separated
458}
459
460#[test]
461fn test_camel_to_snake_case() {
462 assert_eq!(camel_to_snake_case("fooBar"), "foo_bar".to_string());
463 assert_eq!(camel_to_snake_case("FooBar"), "foo_bar".to_string());
464 assert_eq!(camel_to_snake_case("fooBarBaz"), "foo_bar_baz".to_string());
465 assert_eq!(camel_to_snake_case("FooBarBaz"), "foo_bar_baz".to_string());
466 assert_eq!(camel_to_snake_case("helloWorld"), "hello_world".to_string());
467 assert_eq!(camel_to_snake_case("HelloWorld"), "hello_world".to_string());
468 assert_eq!(camel_to_snake_case("uint32Id"), "uint32_id".to_string());
469
470 assert_eq!(camel_to_snake_case("fooBar_"), "foo_bar_".to_string());
471}
472
473#[derive(PartialEq, Clone)]
474pub enum FormattedText {
475 Indent(Box<FormattedText>),
476 Branch(Vec<FormattedText>),
477 Line(String),
478 BlankLine,
479}
480
481impl From<Vec<FormattedText>> for FormattedText {
482 fn from(value: Vec<FormattedText>) -> Self {
483 Branch(value)
484 }
485}
486
487pub fn indent(inner: impl Into<FormattedText>) -> FormattedText {
488 Indent(Box::new(inner.into()))
489}
490
491pub fn line(inner: impl ToString) -> FormattedText {
492 Line(inner.to_string())
493}
494
495fn to_lines(ft: &FormattedText, indent: usize) -> Vec<String> {
496 match ft {
497 Indent(ft) => to_lines(ft, indent + 1),
498 Branch(fts) => fts.iter().flat_map(|ft| to_lines(ft, indent)).collect(),
499 Line(s) => {
500 let mut s1: String = " ".repeat(indent * 4);
501 s1.push_str(s);
502 vec![s1.to_string()]
503 }
504 BlankLine => vec!["".to_string()],
505 }
506}
507
508fn stringify(ft: &FormattedText) -> String {
509 let mut result = to_lines(ft, 0).join("\n");
510 result.push('\n');
511 result
512}
513
514const RUST_KEYWORDS: &[&str] = &[
515 "abstract", "alignof", "as", "be", "become", "box", "break", "const", "continue", "crate",
516 "do", "else", "enum", "extern", "false", "final", "fn", "for", "if", "impl", "in", "let",
517 "loop", "macro", "match", "mod", "move", "mut", "offsetof", "once", "override", "priv", "proc",
518 "pub", "pure", "ref", "return", "self", "sizeof", "static", "struct", "super", "trait", "true",
519 "type", "typeof", "unsafe", "unsized", "use", "virtual", "where", "while", "yield",
520];
521
522fn module_name(camel_case: &str) -> String {
523 let mut name = camel_to_snake_case(camel_case);
524 if RUST_KEYWORDS.contains(&&*name) {
525 name.push('_');
526 }
527 name
528}
529
530const NAME_ANNOTATION_ID: u64 = 0xc2fe4c6d100166d0;
532const PARENT_MODULE_ANNOTATION_ID: u64 = 0xabee386cd1450364;
533const OPTION_ANNOTATION_ID: u64 = 0xabfef22c4ee1964e;
534
535const STREAM_RESULT_ID: u64 = 0x995f9a3377c0b16e;
537
538fn name_annotation_value(annotation: schema_capnp::annotation::Reader<'_>) -> capnp::Result<&str> {
539 if let schema_capnp::value::Text(t) = annotation.get_value()?.which()? {
540 let name = t?.to_str()?;
541 for c in name.chars() {
542 if !(c == '_' || c.is_alphanumeric()) {
543 return Err(capnp::Error::failed(
544 "rust.name annotation value must only contain alphanumeric characters and '_'"
545 .to_string(),
546 ));
547 }
548 }
549 Ok(name)
550 } else {
551 Err(capnp::Error::failed(
552 "expected rust.name annotation value to be of type Text".to_string(),
553 ))
554 }
555}
556
557fn get_field_name(field: schema_capnp::field::Reader<'_>) -> capnp::Result<&str> {
558 for annotation in field.get_annotations()? {
559 if annotation.get_id() == NAME_ANNOTATION_ID {
560 return name_annotation_value(annotation);
561 }
562 }
563 Ok(field.get_name()?.to_str()?)
564}
565
566fn get_enumerant_name(enumerant: schema_capnp::enumerant::Reader<'_>) -> capnp::Result<&str> {
567 for annotation in enumerant.get_annotations()? {
568 if annotation.get_id() == NAME_ANNOTATION_ID {
569 return name_annotation_value(annotation);
570 }
571 }
572 Ok(enumerant.get_name()?.to_str()?)
573}
574
575fn get_parent_module(annotation: schema_capnp::annotation::Reader) -> capnp::Result<Vec<String>> {
576 if let schema_capnp::value::Text(t) = annotation.get_value()?.which()? {
577 let module = t?.to_str()?;
578 Ok(module.split("::").map(|x| x.to_string()).collect())
579 } else {
580 Err(capnp::Error::failed(
581 "expected rust.parentModule annotation value to be of type Text".to_string(),
582 ))
583 }
584}
585#[derive(Clone, Copy)]
586enum NameKind {
587 Module,
589
590 Verbatim,
592}
593
594fn capnp_name_to_rust_name(capnp_name: &str, name_kind: NameKind) -> String {
595 match name_kind {
596 NameKind::Module => module_name(capnp_name),
597 NameKind::Verbatim => capnp_name.to_string(),
598 }
599}
600
601fn is_option_field(field: schema_capnp::field::Reader) -> capnp::Result<bool> {
602 use capnp::schema_capnp::*;
603
604 let enabled = field
605 .get_annotations()?
606 .iter()
607 .any(|a| a.get_id() == OPTION_ANNOTATION_ID);
608
609 if enabled {
610 let supported = match field.which()? {
611 field::Which::Group(_) => false,
612 field::Which::Slot(field) => {
613 let ty = field.get_type()?;
614 ty.is_pointer()? && !matches!(ty.which()?, type_::Interface(_))
615 }
616 };
617 if !supported {
618 return Err(capnp::Error::failed(
619 "$Rust.option annotation only supported on pointer fields (support for optional interfaces isn't implemented yet)".to_string(),
620 ));
621 }
622 }
623
624 Ok(enabled)
625}
626
627fn prim_default(value: &schema_capnp::value::Reader) -> ::capnp::Result<Option<String>> {
628 use capnp::schema_capnp::value;
629 match value.which()? {
630 value::Bool(false)
631 | value::Int8(0)
632 | value::Int16(0)
633 | value::Int32(0)
634 | value::Int64(0)
635 | value::Uint8(0)
636 | value::Uint16(0)
637 | value::Uint32(0)
638 | value::Uint64(0) => Ok(None),
639
640 value::Bool(true) => Ok(Some("true".to_string())),
641 value::Int8(i) => Ok(Some(i.to_string())),
642 value::Int16(i) => Ok(Some(i.to_string())),
643 value::Int32(i) => Ok(Some(i.to_string())),
644 value::Int64(i) => Ok(Some(i.to_string())),
645 value::Uint8(i) => Ok(Some(i.to_string())),
646 value::Uint16(i) => Ok(Some(i.to_string())),
647 value::Uint32(i) => Ok(Some(i.to_string())),
648 value::Uint64(i) => Ok(Some(i.to_string())),
649 value::Float32(f) => match f.classify() {
650 ::std::num::FpCategory::Zero => Ok(None),
651 _ => Ok(Some(format!("{}u32", f.to_bits()))),
652 },
653 value::Float64(f) => match f.classify() {
654 ::std::num::FpCategory::Zero => Ok(None),
655 _ => Ok(Some(format!("{}u64", f.to_bits()))),
656 },
657 _ => Err(Error::failed(
658 "Non-primitive value found where primitive was expected.".to_string(),
659 )),
660 }
661}
662
663fn get_params(ctx: &GeneratorContext, mut node_id: u64) -> ::capnp::Result<Vec<String>> {
665 let mut result = Vec::new();
666
667 while node_id != 0 {
668 let node = ctx.node_map[&node_id];
669 let parameters = node.get_parameters()?;
670
671 for parameter in parameters.into_iter().rev() {
672 result.push(parameter.get_name()?.to_str()?.into());
673 }
674
675 node_id = node.get_scope_id();
676 }
677
678 result.reverse();
679 Ok(result)
680}
681
682pub fn getter_text(
686 ctx: &GeneratorContext,
687 field: &schema_capnp::field::Reader,
688 is_reader: bool,
689 is_fn: bool,
690) -> ::capnp::Result<(String, FormattedText, Option<FormattedText>)> {
691 use capnp::schema_capnp::*;
692
693 match field.which()? {
694 field::Group(group) => {
695 let params = get_params(ctx, group.get_type_id())?;
696 let params_string = if params.is_empty() {
697 "".to_string()
698 } else {
699 format!(",{}", params.join(","))
700 };
701
702 let the_mod = ctx.get_qualified_module(group.get_type_id());
703
704 let mut result_type = if is_reader {
705 format!("{the_mod}::Reader<'a{params_string}>")
706 } else {
707 format!("{the_mod}::Builder<'a{params_string}>")
708 };
709
710 if is_fn {
711 result_type = format!("-> {result_type}");
712 }
713
714 let getter_code = if is_reader {
715 line("self.reader.into()")
716 } else {
717 line("self.builder.into()")
718 };
719
720 Ok((result_type, getter_code, None))
721 }
722 field::Slot(reg_field) => {
723 let mut default_decl = None;
724 let offset = reg_field.get_offset() as usize;
725 let module_string = if is_reader { "Reader" } else { "Builder" };
726 let module = if is_reader {
727 Leaf::Reader("'a")
728 } else {
729 Leaf::Builder("'a")
730 };
731 let member = camel_to_snake_case(module_string);
732
733 fn primitive_case<T: PartialEq + ::std::fmt::Display>(
734 typ: &str,
735 member: &str,
736 offset: usize,
737 default: T,
738 zero: T,
739 ) -> String {
740 if default == zero {
741 format!("self.{member}.get_data_field::<{typ}>({offset})")
742 } else {
743 format!("self.{member}.get_data_field_mask::<{typ}>({offset}, {default})")
744 }
745 }
746
747 let raw_type = reg_field.get_type()?;
748 let inner_type = raw_type.type_string(ctx, module)?;
749 let default_value = reg_field.get_default_value()?;
750 let default = default_value.which()?;
751 let default_name = format!(
752 "DEFAULT_{}",
753 snake_to_upper_case(&camel_to_snake_case(get_field_name(*field)?))
754 );
755 let should_get_option = is_option_field(*field)?;
756
757 let typ = if should_get_option {
758 format!("Option<{inner_type}>")
759 } else {
760 inner_type
761 };
762
763 let (is_fallible, mut result_type) = match raw_type.which()? {
764 type_::Enum(_) => (
765 true,
766 fmt!(ctx, "::core::result::Result<{typ},{capnp}::NotInSchema>"),
767 ),
768 type_::AnyPointer(_) if !raw_type.is_parameter()? => (false, typ.clone()),
769 type_::Interface(_) => (
770 true,
771 fmt!(
772 ctx,
773 "{capnp}::Result<{}>",
774 raw_type.type_string(ctx, Leaf::Client)?
775 ),
776 ),
777 _ if raw_type.is_prim()? => (false, typ.clone()),
778 _ => (true, fmt!(ctx, "{capnp}::Result<{typ}>")),
779 };
780
781 if is_fn {
782 result_type = if result_type == "()" {
783 "".to_string()
784 } else {
785 format!("-> {result_type}")
786 }
787 }
788
789 let getter_fragment = match (raw_type.which()?, default) {
790 (type_::Void(()), value::Void(())) => {
791 if is_fn {
792 "".to_string()
793 } else {
794 "()".to_string()
795 }
796 }
797 (type_::Bool(()), value::Bool(b)) => {
798 if b {
799 format!("self.{member}.get_bool_field_mask({offset}, true)")
800 } else {
801 format!("self.{member}.get_bool_field({offset})")
802 }
803 }
804 (type_::Int8(()), value::Int8(i)) => primitive_case(&typ, &member, offset, i, 0),
805 (type_::Int16(()), value::Int16(i)) => primitive_case(&typ, &member, offset, i, 0),
806 (type_::Int32(()), value::Int32(i)) => primitive_case(&typ, &member, offset, i, 0),
807 (type_::Int64(()), value::Int64(i)) => primitive_case(&typ, &member, offset, i, 0),
808 (type_::Uint8(()), value::Uint8(i)) => primitive_case(&typ, &member, offset, i, 0),
809 (type_::Uint16(()), value::Uint16(i)) => {
810 primitive_case(&typ, &member, offset, i, 0)
811 }
812 (type_::Uint32(()), value::Uint32(i)) => {
813 primitive_case(&typ, &member, offset, i, 0)
814 }
815 (type_::Uint64(()), value::Uint64(i)) => {
816 primitive_case(&typ, &member, offset, i, 0)
817 }
818 (type_::Float32(()), value::Float32(f)) => {
819 primitive_case(&typ, &member, offset, f.to_bits(), 0)
820 }
821 (type_::Float64(()), value::Float64(f)) => {
822 primitive_case(&typ, &member, offset, f.to_bits(), 0)
823 }
824 (type_::Enum(_), value::Enum(d)) => {
825 if d == 0 {
826 format!("::core::convert::TryFrom::try_from(self.{member}.get_data_field::<u16>({offset}))")
827 } else {
828 format!(
829 "::core::convert::TryFrom::try_from(self.{member}.get_data_field_mask::<u16>({offset}, {d}))")
830 }
831 }
832
833 (type_::Text(()), value::Text(_))
834 | (type_::Data(()), value::Data(_))
835 | (type_::List(_), value::List(_))
836 | (type_::Struct(_), value::Struct(_)) => {
837 let default = if reg_field.get_had_explicit_default() {
838 default_decl = Some(crate::pointer_constants::word_array_declaration(
839 ctx,
840 &default_name,
841 ::capnp::raw::get_struct_pointer_section(default_value).get(0),
842 crate::pointer_constants::WordArrayDeclarationOptions { public: true },
843 )?);
844 format!("::core::option::Option::Some(&_private::{default_name}[..])")
845 } else {
846 "::core::option::Option::None".to_string()
847 };
848
849 if is_reader {
850 fmt!(ctx,
851 "{capnp}::traits::FromPointerReader::get_from_pointer(&self.{member}.get_pointer_field({offset}), {default})")
852 } else {
853 fmt!(ctx,"{capnp}::traits::FromPointerBuilder::get_from_pointer(self.{member}.get_pointer_field({offset}), {default})")
854 }
855 }
856
857 (type_::Interface(_), value::Interface(_)) => {
858 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)}}")
859 }
860 (type_::AnyPointer(_), value::AnyPointer(_)) => {
861 if !raw_type.is_parameter()? {
862 fmt!(ctx,"{capnp}::any_pointer::{module_string}::new(self.{member}.get_pointer_field({offset}))")
863 } else if is_reader {
864 fmt!(ctx,"{capnp}::traits::FromPointerReader::get_from_pointer(&self.{member}.get_pointer_field({offset}), ::core::option::Option::None)")
865 } else {
866 fmt!(ctx,"{capnp}::traits::FromPointerBuilder::get_from_pointer(self.{member}.get_pointer_field({offset}), ::core::option::Option::None)")
867 }
868 }
869 _ => return Err(Error::failed("default value was of wrong type".to_string())),
870 };
871
872 let getter_code = if should_get_option {
873 Branch(vec![
874 Line(format!(
875 "if self.{member}.is_pointer_field_null({offset}) {{"
876 )),
877 indent(Line(
878 if is_fallible {
879 "core::result::Result::Ok(core::option::Option::None)"
880 } else {
881 "::core::option::Option::None"
882 }
883 .to_string(),
884 )),
885 Line("} else {".to_string()),
886 indent(Line(if is_fallible {
887 format!("{getter_fragment}.map(::core::option::Option::Some)")
888 } else {
889 format!("::core::option::Option::Some({getter_fragment})")
890 })),
891 Line("}".to_string()),
892 ])
893 } else {
894 Line(getter_fragment)
895 };
896
897 Ok((result_type, getter_code, default_decl))
898 }
899 }
900}
901
902fn zero_fields_of_group(
903 ctx: &GeneratorContext,
904 node_id: u64,
905 clear: &mut bool,
906) -> ::capnp::Result<FormattedText> {
907 use capnp::schema_capnp::{field, node, type_};
908 match ctx.node_map[&node_id].which()? {
909 node::Struct(st) => {
910 let mut result = Vec::new();
911 if st.get_discriminant_count() != 0 {
912 result.push(Line(format!(
913 "self.builder.set_data_field::<u16>({}, 0);",
914 st.get_discriminant_offset()
915 )));
916 }
917 let fields = st.get_fields()?;
918 for field in fields {
919 match field.which()? {
920 field::Group(group) => {
921 result.push(zero_fields_of_group(ctx, group.get_type_id(), clear)?);
922 }
923 field::Slot(slot) => {
924 let typ = slot.get_type()?.which()?;
925 match typ {
926 type_::Void(()) => {}
927 type_::Bool(()) => {
928 let line = Line(format!(
929 "self.builder.set_bool_field({}, false);",
930 slot.get_offset()
931 ));
932 if !result.contains(&line) {
934 result.push(line)
935 }
936 }
937 type_::Int8(())
938 | type_::Int16(())
939 | type_::Int32(())
940 | type_::Int64(())
941 | type_::Uint8(())
942 | type_::Uint16(())
943 | type_::Uint32(())
944 | type_::Uint64(())
945 | type_::Float32(())
946 | type_::Float64(()) => {
947 let line = Line(format!(
948 "self.builder.set_data_field::<{0}>({1}, 0{0});",
949 slot.get_type()?.type_string(ctx, Leaf::Builder("'a"))?,
950 slot.get_offset()
951 ));
952 if !result.contains(&line) {
954 result.push(line)
955 }
956 }
957 type_::Enum(_) => {
958 let line = Line(format!(
959 "self.builder.set_data_field::<u16>({}, 0u16);",
960 slot.get_offset()
961 ));
962 if !result.contains(&line) {
964 result.push(line)
965 }
966 }
967 type_::Struct(_)
968 | type_::List(_)
969 | type_::Text(())
970 | type_::Data(())
971 | type_::AnyPointer(_)
972 | type_::Interface(_) => {
973 let line = Line(format!(
975 "self.builder.reborrow().get_pointer_field({}).clear();",
976 slot.get_offset()
977 ));
978 *clear = true;
979 if !result.contains(&line) {
981 result.push(line)
982 }
983 }
984 }
985 }
986 }
987 }
988 Ok(Branch(result))
989 }
990 _ => Err(Error::failed(
991 "zero_fields_of_group() expected a struct".to_string(),
992 )),
993 }
994}
995
996fn generate_setter(
997 ctx: &GeneratorContext,
998 discriminant_offset: u32,
999 styled_name: &str,
1000 field: &schema_capnp::field::Reader,
1001) -> ::capnp::Result<FormattedText> {
1002 use capnp::schema_capnp::*;
1003
1004 let mut setter_interior = Vec::new();
1005 let mut setter_param = "value".to_string();
1006 let mut initter_interior = Vec::new();
1007 let mut initter_mut = false;
1008 let mut initn_interior = Vec::new();
1009 let mut initter_params = Vec::new();
1010
1011 let discriminant_value = field.get_discriminant_value();
1012 if discriminant_value != field::NO_DISCRIMINANT {
1013 setter_interior.push(Line(format!(
1014 "self.builder.set_data_field::<u16>({}, {});",
1015 discriminant_offset as usize, discriminant_value as usize
1016 )));
1017 let init_discrim = Line(format!(
1018 "self.builder.set_data_field::<u16>({}, {});",
1019 discriminant_offset as usize, discriminant_value as usize
1020 ));
1021 initter_interior.push(init_discrim.clone());
1022 initn_interior.push(init_discrim);
1023 }
1024
1025 let mut return_result = false;
1026 let mut result = Vec::new();
1027
1028 let (maybe_reader_type, maybe_builder_type): (Option<String>, Option<String>) = match field
1029 .which()?
1030 {
1031 field::Group(group) => {
1032 let params = get_params(ctx, group.get_type_id())?;
1033 let params_string = if params.is_empty() {
1034 "".to_string()
1035 } else {
1036 format!(",{}", params.join(","))
1037 };
1038
1039 let the_mod = ctx.get_qualified_module(group.get_type_id());
1040
1041 initter_interior.push(zero_fields_of_group(
1042 ctx,
1043 group.get_type_id(),
1044 &mut initter_mut,
1045 )?);
1046
1047 initter_interior.push(line("self.builder.into()"));
1048
1049 (None, Some(format!("{the_mod}::Builder<'a{params_string}>")))
1050 }
1051 field::Slot(reg_field) => {
1052 let offset = reg_field.get_offset() as usize;
1053 let typ = reg_field.get_type()?;
1054 match typ.which().expect("unrecognized type") {
1055 type_::Void(()) => {
1056 setter_param = "_value".to_string();
1057 (Some("()".to_string()), None)
1058 }
1059 type_::Bool(()) => {
1060 match prim_default(®_field.get_default_value()?)? {
1061 None => {
1062 setter_interior.push(Line(format!(
1063 "self.builder.set_bool_field({offset}, value);"
1064 )));
1065 }
1066 Some(s) => {
1067 setter_interior.push(Line(format!(
1068 "self.builder.set_bool_field_mask({offset}, value, {s});"
1069 )));
1070 }
1071 }
1072 (Some("bool".to_string()), None)
1073 }
1074 _ if typ.is_prim()? => {
1075 let tstr = typ.type_string(ctx, Leaf::Reader("'a"))?;
1076 match prim_default(®_field.get_default_value()?)? {
1077 None => {
1078 setter_interior.push(Line(format!(
1079 "self.builder.set_data_field::<{tstr}>({offset}, value);"
1080 )));
1081 }
1082 Some(s) => {
1083 setter_interior.push(Line(format!(
1084 "self.builder.set_data_field_mask::<{tstr}>({offset}, value, {s});"
1085 )));
1086 }
1087 };
1088 (Some(tstr), None)
1089 }
1090 type_::Text(()) => {
1091 setter_interior.push(Line(fmt!(ctx,
1093 "{capnp}::traits::SetterInput::set_pointer_builder(self.builder.reborrow().get_pointer_field({offset}), value, false).unwrap()"
1094 )));
1095 initter_interior.push(Line(format!(
1096 "self.builder.get_pointer_field({offset}).init_text(size)"
1097 )));
1098 initter_params.push("size: u32");
1099 (
1100 Some(fmt!(
1101 ctx,
1102 "impl {capnp}::traits::SetterInput<{capnp}::text::Owned>"
1103 )),
1104 Some(fmt!(ctx, "{capnp}::text::Builder<'a>")),
1105 )
1106 }
1107 type_::Data(()) => {
1108 setter_interior.push(Line(format!(
1109 "self.builder.reborrow().get_pointer_field({offset}).set_data(value);"
1110 )));
1111 initter_interior.push(Line(format!(
1112 "self.builder.get_pointer_field({offset}).init_data(size)"
1113 )));
1114 initter_params.push("size: u32");
1115 (
1116 Some(fmt!(ctx, "{capnp}::data::Reader<'_>")),
1117 Some(fmt!(ctx, "{capnp}::data::Builder<'a>")),
1118 )
1119 }
1120 type_::List(ls) => {
1121 let et = ls.get_element_type()?;
1122 return_result = true;
1123 setter_interior.push(
1124 Line(fmt!(ctx,"{capnp}::traits::SetterInput::set_pointer_builder(self.builder.reborrow().get_pointer_field({offset}), value, false)")));
1125
1126 initter_params.push("size: u32");
1127 initter_interior.push(
1128 Line(fmt!(ctx,"{capnp}::traits::FromPointerBuilder::init_pointer(self.builder.get_pointer_field({offset}), size)")));
1129
1130 let mr = match et.which()? {
1131 type_::Void(())
1132 | type_::Bool(())
1133 | type_::Int8(())
1134 | type_::Int16(())
1135 | type_::Int32(())
1136 | type_::Int64(())
1137 | type_::Uint8(())
1138 | type_::Uint16(())
1139 | type_::Uint32(())
1140 | type_::Uint64(())
1141 | type_::Float32(())
1142 | type_::Float64(())
1143 | type_::Enum(_)
1144 | type_::Text(()) => {
1145 fmt!(
1147 ctx,
1148 "impl {capnp}::traits::SetterInput<{}>",
1149 reg_field.get_type()?.type_string(ctx, Leaf::Owned)?
1150 )
1151 }
1152 _ => reg_field.get_type()?.type_string(ctx, Leaf::Reader("'_"))?,
1153 };
1154
1155 (
1156 Some(mr),
1157 Some(
1158 reg_field
1159 .get_type()?
1160 .type_string(ctx, Leaf::Builder("'a"))?,
1161 ),
1162 )
1163 }
1164 type_::Enum(e) => {
1165 let id = e.get_type_id();
1166 let the_mod = ctx.get_qualified_module(id);
1167 if !reg_field.get_had_explicit_default() {
1168 setter_interior.push(Line(format!(
1169 "self.builder.set_data_field::<u16>({offset}, value as u16);"
1170 )));
1171 } else {
1172 match reg_field.get_default_value()?.which()? {
1173 schema_capnp::value::Enum(d) => {
1174 setter_interior.push(Line(format!(
1175 "self.builder.set_data_field_mask::<u16>({offset}, value as u16, {d});"
1176 )));
1177 }
1178 _ => return Err(Error::failed("enum default not an Enum".to_string())),
1179 }
1180 };
1181 (Some(the_mod), None)
1182 }
1183 type_::Struct(_) => {
1184 return_result = true;
1185 initter_interior.push(
1186 Line(fmt!(ctx,"{capnp}::traits::FromPointerBuilder::init_pointer(self.builder.get_pointer_field({offset}), 0)")));
1187 setter_interior.push(
1188 Line(fmt!(ctx,"{capnp}::traits::SetterInput::set_pointer_builder(self.builder.reborrow().get_pointer_field({offset}), value, false)")));
1189
1190 (
1191 Some(typ.type_string(ctx, Leaf::Reader("'_"))?),
1192 Some(typ.type_string(ctx, Leaf::Builder("'a"))?),
1193 )
1194 }
1195 type_::Interface(_) => {
1196 setter_interior.push(Line(format!(
1197 "self.builder.reborrow().get_pointer_field({offset}).set_capability(value.client.hook);"
1198 )));
1199 (Some(typ.type_string(ctx, Leaf::Client)?), None)
1200 }
1201 type_::AnyPointer(_) => {
1202 if typ.is_parameter()? {
1203 initter_interior.push(Line(fmt!(ctx,"{capnp}::any_pointer::Builder::new(self.builder.get_pointer_field({offset})).init_as()")));
1204 setter_interior.push(Line(fmt!(ctx,"{capnp}::traits::SetterInput::set_pointer_builder(self.builder.reborrow().get_pointer_field({offset}), value, false)")));
1205 return_result = true;
1206
1207 let builder_type = typ.type_string(ctx, Leaf::Builder("'a"))?;
1208
1209 result.push(line("#[inline]"));
1210 result.push(Line(format!(
1211 "pub fn initn_{styled_name}(self, length: u32) -> {builder_type} {{"
1212 )));
1213 result.push(indent(initn_interior));
1214 result.push(indent(
1215 Line(fmt!(ctx,"{capnp}::any_pointer::Builder::new(self.builder.get_pointer_field({offset})).initn_as(length)")))
1216 );
1217 result.push(line("}"));
1218
1219 (
1220 Some(fmt!(
1221 ctx,
1222 "impl {capnp}::traits::SetterInput<{}>",
1223 typ.type_string(ctx, Leaf::Owned)?
1224 )),
1225 Some(builder_type),
1226 )
1227 } else {
1228 initter_interior.push(Line(fmt!(ctx,"let mut result = {capnp}::any_pointer::Builder::new(self.builder.get_pointer_field({offset}));")));
1229 initter_interior.push(line("result.clear();"));
1230 initter_interior.push(line("result"));
1231 (None, Some(fmt!(ctx, "{capnp}::any_pointer::Builder<'a>")))
1232 }
1233 }
1234 _ => return Err(Error::failed("unrecognized type".to_string())),
1235 }
1236 }
1237 };
1238 if let Some(reader_type) = maybe_reader_type {
1239 let return_type = if return_result {
1240 fmt!(ctx, "-> {capnp}::Result<()>")
1241 } else {
1242 "".into()
1243 };
1244 result.push(line("#[inline]"));
1245 result.push(Line(format!(
1246 "pub fn set_{styled_name}(&mut self, {setter_param}: {reader_type}) {return_type} {{"
1247 )));
1248 result.push(indent(setter_interior));
1249 result.push(line("}"));
1250 }
1251 if let Some(builder_type) = maybe_builder_type {
1252 result.push(line("#[inline]"));
1253 let args = initter_params.join(", ");
1254 let mutable = if initter_mut { "mut " } else { "" };
1255 result.push(Line(format!(
1256 "pub fn init_{styled_name}({mutable}self, {args}) -> {builder_type} {{"
1257 )));
1258 result.push(indent(initter_interior));
1259 result.push(line("}"));
1260 }
1261 Ok(Branch(result))
1262}
1263
1264fn used_params_of_group(
1265 ctx: &GeneratorContext,
1266 group_id: u64,
1267 used_params: &mut HashSet<String>,
1268) -> capnp::Result<()> {
1269 let node = ctx.node_map[&group_id];
1270 match node.which()? {
1271 schema_capnp::node::Struct(st) => {
1272 for field in st.get_fields()? {
1273 match field.which()? {
1274 schema_capnp::field::Group(group) => {
1275 used_params_of_group(ctx, group.get_type_id(), used_params)?;
1276 }
1277 schema_capnp::field::Slot(slot) => {
1278 used_params_of_type(ctx, slot.get_type()?, used_params)?;
1279 }
1280 }
1281 }
1282 Ok(())
1283 }
1284 _ => Err(Error::failed("not a group".to_string())),
1285 }
1286}
1287
1288fn used_params_of_type(
1289 ctx: &GeneratorContext,
1290 ty: schema_capnp::type_::Reader,
1291 used_params: &mut HashSet<String>,
1292) -> capnp::Result<()> {
1293 use capnp::schema_capnp::type_;
1294 match ty.which()? {
1295 type_::List(ls) => {
1296 let et = ls.get_element_type()?;
1297 used_params_of_type(ctx, et, used_params)?;
1298 }
1299 type_::Enum(e) => {
1300 let node_id = e.get_type_id();
1301 let brand = e.get_brand()?;
1302 used_params_of_brand(ctx, node_id, brand, used_params)?;
1303 }
1304 type_::Struct(s) => {
1305 let node_id = s.get_type_id();
1306 let brand = s.get_brand()?;
1307 used_params_of_brand(ctx, node_id, brand, used_params)?;
1308 }
1309 type_::Interface(i) => {
1310 let node_id = i.get_type_id();
1311 let brand = i.get_brand()?;
1312 used_params_of_brand(ctx, node_id, brand, used_params)?;
1313 }
1314
1315 type_::AnyPointer(ap) => {
1316 if let type_::any_pointer::Parameter(def) = ap.which()? {
1317 let the_struct = &ctx.node_map[&def.get_scope_id()];
1318 let parameters = the_struct.get_parameters()?;
1319 let parameter = parameters.get(u32::from(def.get_parameter_index()));
1320 let parameter_name = parameter.get_name()?.to_str()?;
1321 used_params.insert(parameter_name.to_string());
1322 }
1323 }
1324 _ => (),
1325 }
1326 Ok(())
1327}
1328
1329fn used_params_of_brand(
1330 ctx: &GeneratorContext,
1331 node_id: u64,
1332 brand: schema_capnp::brand::Reader,
1333 used_params: &mut HashSet<String>,
1334) -> capnp::Result<()> {
1335 use schema_capnp::brand;
1336 let scopes = brand.get_scopes()?;
1337 let mut brand_scopes = HashMap::new();
1338 for scope in scopes {
1339 brand_scopes.insert(scope.get_scope_id(), scope);
1340 }
1341 let brand_scopes = brand_scopes; let mut current_node_id = node_id;
1343 loop {
1344 let Some(current_node) = ctx.node_map.get(¤t_node_id) else {
1345 break;
1346 };
1347 let params = current_node.get_parameters()?;
1348 match brand_scopes.get(¤t_node_id) {
1349 None => (),
1350 Some(scope) => match scope.which()? {
1351 brand::scope::Inherit(()) => {
1352 for param in params {
1353 used_params.insert(param.get_name()?.to_string()?);
1354 }
1355 }
1356 brand::scope::Bind(bindings_list_opt) => {
1357 let bindings_list = bindings_list_opt?;
1358 assert_eq!(bindings_list.len(), params.len());
1359 for binding in bindings_list {
1360 match binding.which()? {
1361 brand::binding::Unbound(()) => (),
1362 brand::binding::Type(t) => {
1363 used_params_of_type(ctx, t?, used_params)?;
1364 }
1365 }
1366 }
1367 }
1368 },
1369 }
1370 current_node_id = current_node.get_scope_id();
1371 }
1372 Ok(())
1373}
1374
1375fn generate_union(
1377 ctx: &GeneratorContext,
1378 discriminant_offset: u32,
1379 fields: &[schema_capnp::field::Reader],
1380 is_reader: bool,
1381 params: &TypeParameterTexts,
1382) -> ::capnp::Result<(
1383 FormattedText,
1384 FormattedText,
1385 FormattedText,
1386 Vec<FormattedText>,
1387)> {
1388 use capnp::schema_capnp::*;
1389
1390 fn new_ty_param(ty_params: &mut Vec<String>) -> String {
1391 let result = format!("A{}", ty_params.len());
1392 ty_params.push(result.clone());
1393 result
1394 }
1395
1396 let mut getter_interior = Vec::new();
1397 let mut interior = Vec::new();
1398 let mut enum_interior = Vec::new();
1399 let mut default_decls = Vec::new();
1400
1401 let mut ty_params = Vec::new();
1402 let mut ty_args = Vec::new();
1403
1404 let mut used_params: HashSet<String> = HashSet::new();
1405
1406 let doffset = discriminant_offset as usize;
1407
1408 for field in fields {
1409 let dvalue = field.get_discriminant_value() as usize;
1410
1411 let field_name = get_field_name(*field)?;
1412 let enumerant_name = capitalize_first_letter(field_name);
1413
1414 let (ty, get, maybe_default_decl) = getter_text(ctx, field, is_reader, false)?;
1415 if let Some(default_decl) = maybe_default_decl {
1416 default_decls.push(default_decl)
1417 }
1418
1419 getter_interior.push(Branch(vec![
1420 Line(format!("{dvalue} => {{")),
1421 indent(Line(format!(
1422 "::core::result::Result::Ok({}(",
1423 enumerant_name.clone()
1424 ))),
1425 indent(indent(get)),
1426 indent(line("))")),
1427 line("}"),
1428 ]));
1429
1430 let ty1 = match field.which() {
1431 Ok(field::Group(group)) => {
1432 used_params_of_group(ctx, group.get_type_id(), &mut used_params)?;
1433 ty_args.push(ty);
1434 new_ty_param(&mut ty_params)
1435 }
1436 Ok(field::Slot(reg_field)) => {
1437 let fty = reg_field.get_type()?;
1438 used_params_of_type(ctx, fty, &mut used_params)?;
1439 match fty.which() {
1440 Ok(
1441 type_::Text(())
1442 | type_::Data(())
1443 | type_::List(_)
1444 | type_::Struct(_)
1445 | type_::AnyPointer(_),
1446 ) => {
1447 ty_args.push(ty);
1448 new_ty_param(&mut ty_params)
1449 }
1450 Ok(type_::Interface(_)) => ty,
1451 _ => ty,
1452 }
1453 }
1454 _ => ty,
1455 };
1456
1457 enum_interior.push(Line(format!("{enumerant_name}({ty1}),")));
1458 }
1459
1460 let enum_name = format!(
1461 "Which{}",
1462 if !ty_params.is_empty() {
1463 format!("<{}>", ty_params.join(","))
1464 } else {
1465 "".to_string()
1466 }
1467 );
1468
1469 getter_interior.push(Line(fmt!(
1470 ctx,
1471 "x => ::core::result::Result::Err({capnp}::NotInSchema(x))"
1472 )));
1473
1474 interior.push(Branch(vec![
1475 Line(format!("pub enum {enum_name} {{")),
1476 indent(enum_interior),
1477 line("}"),
1478 ]));
1479
1480 let result = Branch(interior);
1481
1482 let field_name = if is_reader { "reader" } else { "builder" };
1483
1484 let concrete_type = format!(
1485 "Which{}{}",
1486 if is_reader { "Reader" } else { "Builder" },
1487 if !ty_params.is_empty() {
1488 format!(
1489 "<'a,{}>",
1490 params
1491 .expanded_list
1492 .iter()
1493 .filter(|s: &&String| used_params.contains(*s))
1494 .cloned()
1495 .collect::<Vec<String>>()
1496 .join(",")
1497 )
1498 } else {
1499 "".to_string()
1500 }
1501 );
1502
1503 let typedef = Line(format!(
1504 "pub type {concrete_type} = Which{};",
1505 if !ty_args.is_empty() {
1506 format!("<{}>", ty_args.join(","))
1507 } else {
1508 "".to_string()
1509 }
1510 ));
1511
1512 let getter_result = Branch(vec![
1513 line("#[inline]"),
1514 Line(fmt!(ctx,
1515 "pub fn which(self) -> ::core::result::Result<{concrete_type}, {capnp}::NotInSchema> {{"
1516 )),
1517 indent(vec![
1518 Line(format!(
1519 "match self.{field_name}.get_data_field::<u16>({doffset}) {{"
1520 )),
1521 indent(getter_interior),
1522 line("}"),
1523 ]),
1524 line("}"),
1525 ]);
1526
1527 Ok((result, getter_result, typedef, default_decls))
1530}
1531
1532fn generate_haser(
1533 discriminant_offset: u32,
1534 styled_name: &str,
1535 field: &schema_capnp::field::Reader,
1536 is_reader: bool,
1537) -> ::capnp::Result<FormattedText> {
1538 use capnp::schema_capnp::*;
1539
1540 let mut result = Vec::new();
1541 let mut interior = Vec::new();
1542 let member = if is_reader { "reader" } else { "builder" };
1543
1544 let discriminant_value = field.get_discriminant_value();
1545 if discriminant_value != field::NO_DISCRIMINANT {
1546 interior.push(Line(format!(
1547 "if self.{}.get_data_field::<u16>({}) != {} {{ return false; }}",
1548 member, discriminant_offset as usize, discriminant_value as usize
1549 )));
1550 }
1551 match field.which() {
1552 Err(_) | Ok(field::Group(_)) => {}
1553 Ok(field::Slot(reg_field)) => match reg_field.get_type()?.which()? {
1554 type_::Text(())
1555 | type_::Data(())
1556 | type_::List(_)
1557 | type_::Struct(_)
1558 | type_::Interface(_)
1559 | type_::AnyPointer(_) => {
1560 if is_reader {
1561 interior.push(Line(format!(
1562 "!self.{member}.get_pointer_field({}).is_null()",
1563 reg_field.get_offset()
1564 )));
1565 } else {
1566 interior.push(Line(format!(
1567 "!self.{member}.is_pointer_field_null({})",
1568 reg_field.get_offset()
1569 )));
1570 }
1571 result.push(line("#[inline]"));
1572 result.push(Line(format!("pub fn has_{styled_name}(&self) -> bool {{")));
1573 result.push(indent(interior));
1574 result.push(line("}"));
1575 }
1576 _ => {}
1577 },
1578 }
1579
1580 Ok(Branch(result))
1581}
1582
1583fn generate_pipeline_getter(
1584 ctx: &GeneratorContext,
1585 field: schema_capnp::field::Reader,
1586) -> ::capnp::Result<FormattedText> {
1587 use capnp::schema_capnp::{field, type_};
1588
1589 let name = get_field_name(field)?;
1590
1591 match field.which()? {
1592 field::Group(group) => {
1593 let params = get_params(ctx, group.get_type_id())?;
1594 let params_string = if params.is_empty() {
1595 "".to_string()
1596 } else {
1597 format!("<{}>", params.join(","))
1598 };
1599
1600 let the_mod = ctx.get_qualified_module(group.get_type_id());
1601 Ok(Branch(vec![
1602 Line(format!(
1603 "pub fn get_{}(&self) -> {}::Pipeline{} {{",
1604 camel_to_snake_case(name),
1605 the_mod,
1606 params_string
1607 )),
1608 indent(Line(fmt!(
1609 ctx,
1610 "{capnp}::capability::FromTypelessPipeline::new(self._typeless.noop())"
1611 ))),
1612 line("}"),
1613 ]))
1614 }
1615 field::Slot(reg_field) => {
1616 let typ = reg_field.get_type()?;
1617 match typ.which()? {
1618 type_::Struct(_) | type_::AnyPointer(_) => {
1619 Ok(Branch(vec![
1620 Line(format!("pub fn get_{}(&self) -> {} {{", camel_to_snake_case(name), typ.type_string(ctx, Leaf::Pipeline)?)),
1621 indent(Line(fmt!(ctx,"{capnp}::capability::FromTypelessPipeline::new(self._typeless.get_pointer_field({}))", reg_field.get_offset()))),
1622 line("}")
1623 ]))
1624 }
1625 type_::Interface(_) => {
1626 Ok(Branch(vec![
1627 Line(format!("pub fn get_{}(&self) -> {} {{", camel_to_snake_case(name), typ.type_string(ctx, Leaf::Client)?)),
1628 indent(Line(fmt!(ctx,"{capnp}::capability::FromClientHook::new(self._typeless.get_pointer_field({}).as_cap())", reg_field.get_offset()))),
1629 line("}")
1630 ]))
1631 }
1632 _ => {
1633 Ok(Branch(Vec::new()))
1634 }
1635 }
1636 }
1637 }
1638}
1639
1640fn generate_get_field_types(
1641 ctx: &GeneratorContext,
1642 node_reader: schema_capnp::node::Reader,
1643) -> ::capnp::Result<FormattedText> {
1644 use capnp::schema_capnp::field;
1645 let st = match node_reader.which()? {
1646 schema_capnp::node::Struct(st) => st,
1647 _ => return Err(Error::failed("not a struct".into())),
1648 };
1649 let mut branches = vec![];
1650 for (index, field) in st.get_fields()?.iter().enumerate() {
1651 match field.which()? {
1652 field::Slot(slot) => {
1653 let raw_type = slot.get_type()?;
1654 let typ = raw_type.type_string(ctx, Leaf::Owned)?;
1655 branches.push(Line(fmt!(
1656 ctx,
1657 "{} => <{} as {capnp}::introspect::Introspect>::introspect(),",
1658 index,
1659 typ
1660 )));
1661 }
1662 field::Group(group) => {
1663 let params = get_params(ctx, group.get_type_id())?;
1664 let params_string = if params.is_empty() {
1665 "".to_string()
1666 } else {
1667 format!("<{}>", params.join(","))
1668 };
1669
1670 let the_mod = ctx.get_qualified_module(group.get_type_id());
1671
1672 let typ = format!("{the_mod}::Owned{params_string}");
1673 branches.push(Line(fmt!(
1674 ctx,
1675 "{} => <{} as {capnp}::introspect::Introspect>::introspect(),",
1676 index,
1677 typ
1678 )));
1679 }
1680 }
1681 }
1682 let body = if branches.is_empty() {
1683 Line(fmt!(
1684 ctx,
1685 "{capnp}::introspect::panic_invalid_field_index(index)"
1686 ))
1687 } else {
1688 branches.push(Line(fmt!(
1689 ctx,
1690 "_ => {capnp}::introspect::panic_invalid_field_index(index),"
1691 )));
1692 Branch(vec![
1693 Line("match index {".into()),
1694 indent(branches),
1695 Line("}".into()),
1696 ])
1697 };
1698 if !node_reader.get_is_generic() {
1699 Ok(Branch(vec![
1700 Line(fmt!(
1701 ctx,
1702 "pub fn get_field_types(index: u16) -> {capnp}::introspect::Type {{"
1703 )),
1704 indent(body),
1705 Line("}".into()),
1706 ]))
1707 } else {
1708 let params = node_reader.parameters_texts(ctx);
1709 Ok(Branch(vec![
1710 Line(fmt!(
1711 ctx,
1712 "pub fn get_field_types<{0}>(index: u16) -> {capnp}::introspect::Type {1} {{",
1713 params.params,
1714 params.where_clause
1715 )),
1716 indent(body),
1717 Line("}".into()),
1718 ]))
1719 }
1720}
1721
1722fn annotation_branch(
1723 ctx: &GeneratorContext,
1724 annotation: schema_capnp::annotation::Reader,
1725 child_index: Option<u16>,
1726 index: u32,
1727) -> ::capnp::Result<FormattedText> {
1728 use capnp::schema_capnp::node;
1729 let id = annotation.get_id();
1730 let annotation_decl = ctx.node_map[&id];
1731 let node::Annotation(a) = annotation_decl.which()? else {
1732 return Err(Error::failed("not an annotation node".into()));
1733 };
1734 if annotation_decl.get_is_generic() {
1735 let brand = annotation.get_brand()?;
1736 let the_mod = ctx.get_qualified_module(id);
1737 let func = do_branding(ctx, id, brand, Leaf::GetType, &the_mod)?;
1738 Ok(Line(format!("({child_index:?}, {index}) => {func}(),")))
1739 } else {
1740 let ty = a.get_type()?;
1744 Ok(Line(fmt!(
1745 ctx,
1746 "({child_index:?}, {index}) => <{} as {capnp}::introspect::Introspect>::introspect(),",
1747 ty.type_string(ctx, Leaf::Owned)?
1748 )))
1749 }
1750}
1751
1752fn generate_get_annotation_types(
1753 ctx: &GeneratorContext,
1754 node_reader: schema_capnp::node::Reader,
1755) -> ::capnp::Result<FormattedText> {
1756 use capnp::schema_capnp::node;
1757
1758 let mut branches = vec![];
1759
1760 for (idx, annotation) in node_reader.get_annotations()?.iter().enumerate() {
1761 branches.push(annotation_branch(ctx, annotation, None, idx as u32)?);
1762 }
1763
1764 match node_reader.which()? {
1765 node::Struct(s) => {
1766 for (fidx, field) in s.get_fields()?.iter().enumerate() {
1767 for (idx, annotation) in field.get_annotations()?.iter().enumerate() {
1768 branches.push(annotation_branch(
1769 ctx,
1770 annotation,
1771 Some(fidx as u16),
1772 idx as u32,
1773 )?);
1774 }
1775 }
1776 }
1777 node::Enum(e) => {
1778 for (fidx, enumerant) in e.get_enumerants()?.iter().enumerate() {
1779 for (idx, annotation) in enumerant.get_annotations()?.iter().enumerate() {
1780 branches.push(annotation_branch(
1781 ctx,
1782 annotation,
1783 Some(fidx as u16),
1784 idx as u32,
1785 )?);
1786 }
1787 }
1788 }
1789 _ => (),
1790 }
1791
1792 let body = if branches.is_empty() {
1793 Line(fmt!(
1794 ctx,
1795 "{capnp}::introspect::panic_invalid_annotation_indices(child_index, index)"
1796 ))
1797 } else {
1798 branches.push(Line(fmt!(
1799 ctx,
1800 "_ => {capnp}::introspect::panic_invalid_annotation_indices(child_index, index),"
1801 )));
1802 indent(vec![
1803 Line("match (child_index, index) {".into()),
1804 indent(branches),
1805 Line("}".into()),
1806 ])
1807 };
1808
1809 if !node_reader.get_is_generic() {
1810 Ok(Branch(vec![
1811 Line(fmt!(ctx,"pub fn get_annotation_types(child_index: Option<u16>, index: u32) -> {capnp}::introspect::Type {{")),
1812 indent(body),
1813 Line("}".into()),
1814 ]))
1815 } else {
1816 let params = node_reader.parameters_texts(ctx);
1817 Ok(Branch(vec![
1818 Line(fmt!(ctx,
1819 "pub fn get_annotation_types<{0}>(child_index: Option<u16>, index: u32) -> {capnp}::introspect::Type {1} {{",
1820 params.params, params.where_clause
1821 )),
1822 indent(body),
1823 Line("}".into()),
1824 ]))
1825 }
1826}
1827
1828fn generate_members_by_discriminant(
1829 node_reader: schema_capnp::node::Reader,
1830) -> ::capnp::Result<FormattedText> {
1831 use capnp::schema_capnp::field;
1832 let st = match node_reader.which()? {
1833 schema_capnp::node::Struct(st) => st,
1834 _ => return Err(Error::failed("not a struct".into())),
1835 };
1836
1837 let mut union_member_indexes = vec![];
1838 let mut nonunion_member_indexes = vec![];
1839 for (index, field) in st.get_fields()?.iter().enumerate() {
1840 let disc = field.get_discriminant_value();
1841 if disc == field::NO_DISCRIMINANT {
1842 nonunion_member_indexes.push(index);
1843 } else {
1844 union_member_indexes.push((disc, index));
1845 }
1846 }
1847 union_member_indexes.sort();
1848
1849 let mut nonunion_string: String = "pub static NONUNION_MEMBERS : &[u16] = &[".into();
1850 for idx in 0..nonunion_member_indexes.len() {
1851 nonunion_string += &format!("{}", nonunion_member_indexes[idx]);
1852 if idx + 1 < nonunion_member_indexes.len() {
1853 nonunion_string += ",";
1854 }
1855 }
1856 nonunion_string += "];";
1857
1858 let mut members_by_disc: String = "pub static MEMBERS_BY_DISCRIMINANT : &[u16] = &[".into();
1859 for idx in 0..union_member_indexes.len() {
1860 let (disc, index) = union_member_indexes[idx];
1861 assert_eq!(idx, disc as usize);
1862 members_by_disc += &format!("{index}");
1863 if idx + 1 < union_member_indexes.len() {
1864 members_by_disc += ",";
1865 }
1866 }
1867 members_by_disc += "];";
1868 Ok(Branch(vec![Line(nonunion_string), Line(members_by_disc)]))
1869}
1870
1871fn generate_members_by_name(
1872 node_reader: schema_capnp::node::Reader,
1873) -> ::capnp::Result<FormattedText> {
1874 let st = match node_reader.which()? {
1875 schema_capnp::node::Struct(st) => st,
1876 _ => return Err(Error::failed("not a struct".into())),
1877 };
1878
1879 let mut members_by_name = Vec::new();
1880 for (index, field) in st.get_fields()?.iter().enumerate() {
1881 if let Ok(name) = get_field_name(field) {
1882 members_by_name.push((name, index));
1883 }
1884 }
1885 members_by_name.sort_by_key(|k| k.0);
1886
1887 let mut members_by_name_string: String = "pub static MEMBERS_BY_NAME : &[u16] = &[".into();
1888 for (i, (_, index)) in members_by_name.iter().enumerate() {
1889 members_by_name_string += &format!("{}", *index);
1890 if i + 1 < members_by_name.len() {
1891 members_by_name_string += ",";
1892 }
1893 }
1894 members_by_name_string += "];";
1895
1896 Ok(Branch(vec![Line(members_by_name_string)]))
1897}
1898
1899fn get_ty_params_of_brand(
1902 ctx: &GeneratorContext,
1903 brand: schema_capnp::brand::Reader,
1904) -> ::capnp::Result<String> {
1905 let mut acc = HashSet::new();
1906 get_ty_params_of_brand_helper(ctx, &mut acc, brand)?;
1907 let mut result = String::new();
1908 for (scope_id, parameter_index) in acc.into_iter() {
1909 let node = ctx.node_map[&scope_id];
1910 let p = node.get_parameters()?.get(u32::from(parameter_index));
1911 result.push_str(p.get_name()?.to_str()?);
1912 result.push(',');
1913 }
1914
1915 Ok(result)
1916}
1917
1918fn get_ty_params_of_type_helper(
1919 ctx: &GeneratorContext,
1920 accumulator: &mut HashSet<(u64, u16)>,
1921 typ: schema_capnp::type_::Reader,
1922) -> ::capnp::Result<()> {
1923 use capnp::schema_capnp::type_;
1924 match typ.which()? {
1925 type_::Void(())
1926 | type_::Bool(())
1927 | type_::Int8(())
1928 | type_::Int16(())
1929 | type_::Int32(())
1930 | type_::Int64(())
1931 | type_::Uint8(())
1932 | type_::Uint16(())
1933 | type_::Uint32(())
1934 | type_::Uint64(())
1935 | type_::Float32(())
1936 | type_::Float64(())
1937 | type_::Text(_)
1938 | type_::Data(_) => {}
1939 type_::AnyPointer(p) => {
1940 match p.which()? {
1941 type_::any_pointer::Unconstrained(_) => (),
1942 type_::any_pointer::Parameter(p) => {
1943 accumulator.insert((p.get_scope_id(), p.get_parameter_index()));
1944 }
1945 type_::any_pointer::ImplicitMethodParameter(_) => {
1946 }
1948 }
1949 }
1950 type_::List(list) => {
1951 get_ty_params_of_type_helper(ctx, accumulator, list.get_element_type()?)?
1952 }
1953 type_::Enum(e) => {
1954 get_ty_params_of_brand_helper(ctx, accumulator, e.get_brand()?)?;
1955 }
1956 type_::Struct(s) => {
1957 get_ty_params_of_brand_helper(ctx, accumulator, s.get_brand()?)?;
1958 }
1959 type_::Interface(interf) => {
1960 get_ty_params_of_brand_helper(ctx, accumulator, interf.get_brand()?)?;
1961 }
1962 }
1963 Ok(())
1964}
1965
1966fn get_ty_params_of_brand_helper(
1967 ctx: &GeneratorContext,
1968 accumulator: &mut HashSet<(u64, u16)>,
1969 brand: schema_capnp::brand::Reader,
1970) -> ::capnp::Result<()> {
1971 for scope in brand.get_scopes()? {
1972 let scope_id = scope.get_scope_id();
1973 match scope.which()? {
1974 schema_capnp::brand::scope::Bind(bind) => {
1975 for binding in bind? {
1976 match binding.which()? {
1977 schema_capnp::brand::binding::Unbound(()) => {}
1978 schema_capnp::brand::binding::Type(t) => {
1979 get_ty_params_of_type_helper(ctx, accumulator, t?)?
1980 }
1981 }
1982 }
1983 }
1984 schema_capnp::brand::scope::Inherit(()) => {
1985 let parameters = ctx.node_map[&scope_id].get_parameters()?;
1986 for idx in 0..parameters.len() {
1987 accumulator.insert((scope_id, idx as u16));
1988 }
1989 }
1990 }
1991 }
1992 Ok(())
1993}
1994
1995fn generate_node(
1996 ctx: &GeneratorContext,
1997 node_id: u64,
1998 node_name: &str,
1999) -> ::capnp::Result<FormattedText> {
2000 use capnp::schema_capnp::*;
2001
2002 let mut output: Vec<FormattedText> = Vec::new();
2003 let mut nested_output: Vec<FormattedText> = Vec::new();
2004
2005 let node_reader = &ctx.node_map[&node_id];
2006 let nested_nodes = node_reader.get_nested_nodes()?;
2007 for nested_node in nested_nodes {
2008 let id = nested_node.get_id();
2009 nested_output.push(generate_node(ctx, id, ctx.get_last_name(id)?)?);
2010 }
2011
2012 match node_reader.which()? {
2013 node::File(()) => {
2014 output.push(Branch(nested_output));
2015 }
2016 node::Struct(struct_reader) => {
2017 let params = node_reader.parameters_texts(ctx);
2018 output.push(BlankLine);
2019
2020 let is_generic = node_reader.get_is_generic();
2021 if is_generic {
2022 output.push(Line(format!(
2023 "pub mod {} {{ /* {} */",
2024 node_name,
2025 params.expanded_list.join(",")
2026 )));
2027 } else {
2028 output.push(Line(format!("pub mod {node_name} {{")));
2029 }
2030 let bracketed_params = if params.params.is_empty() {
2031 "".to_string()
2032 } else {
2033 format!("<{}>", params.params)
2034 };
2035
2036 let mut preamble = Vec::new();
2037 let mut builder_members = Vec::new();
2038 let mut reader_members = Vec::new();
2039 let mut union_fields = Vec::new();
2040 let mut which_enums = Vec::new();
2041 let mut pipeline_impl_interior = Vec::new();
2042 let mut private_mod_interior = Vec::new();
2043
2044 let data_size = struct_reader.get_data_word_count();
2045 let pointer_size = struct_reader.get_pointer_count();
2046 let discriminant_count = struct_reader.get_discriminant_count();
2047 let discriminant_offset = struct_reader.get_discriminant_offset();
2048
2049 private_mod_interior.push(crate::pointer_constants::node_word_array_declaration(
2050 ctx,
2051 "ENCODED_NODE",
2052 *node_reader,
2053 crate::pointer_constants::WordArrayDeclarationOptions { public: true },
2054 )?);
2055
2056 private_mod_interior.push(generate_get_field_types(ctx, *node_reader)?);
2057 private_mod_interior.push(generate_get_annotation_types(ctx, *node_reader)?);
2058
2059 private_mod_interior.push(Branch(vec![
2062 Line(fmt!(ctx, "pub static ARENA: {capnp}::private::arena::GeneratedCodeArena = {capnp}::private::arena::GeneratedCodeArena::new(&ENCODED_NODE);")),
2063 Line(fmt!(ctx,"pub static RAW_SCHEMA: {capnp}::introspect::RawStructSchema = {capnp}::introspect::RawStructSchema::new(")),
2064 indent(vec![
2065 Line("&ARENA,".into()),
2066 Line("NONUNION_MEMBERS,".into()),
2067 Line("MEMBERS_BY_DISCRIMINANT,".into()),
2068 Line("MEMBERS_BY_NAME".into()),
2069 ]),
2070 Line(");".into()),
2071 ]));
2072
2073 private_mod_interior.push(generate_members_by_discriminant(*node_reader)?);
2074 private_mod_interior.push(generate_members_by_name(*node_reader)?);
2075
2076 let mut has_pointer_field = false;
2077 let fields = struct_reader.get_fields()?;
2078 for field in fields {
2079 let name = get_field_name(field)?;
2080 let styled_name = camel_to_snake_case(name);
2081
2082 let discriminant_value = field.get_discriminant_value();
2083 let is_union_field = discriminant_value != field::NO_DISCRIMINANT;
2084
2085 match field.which()? {
2086 field::Slot(s) => match s.get_type()?.which()? {
2087 type_::Text(())
2088 | type_::Data(())
2089 | type_::List(_)
2090 | type_::Struct(_)
2091 | type_::Interface(_)
2092 | type_::AnyPointer(_) => has_pointer_field = true,
2093 _ => (),
2094 },
2095 field::Group(_) => has_pointer_field = true,
2096 }
2097
2098 if !is_union_field {
2099 pipeline_impl_interior.push(generate_pipeline_getter(ctx, field)?);
2100 let (ty, get, default_decl) = getter_text(ctx, &field, true, true)?;
2101 if let Some(default) = default_decl {
2102 private_mod_interior.push(default.clone());
2103 }
2104 reader_members.push(Branch(vec![
2105 line("#[inline]"),
2106 Line(format!("pub fn get_{styled_name}(self) {ty} {{")),
2107 indent(get),
2108 line("}"),
2109 ]));
2110
2111 let (ty_b, get_b, _) = getter_text(ctx, &field, false, true)?;
2112 builder_members.push(Branch(vec![
2113 line("#[inline]"),
2114 Line(format!("pub fn get_{styled_name}(self) {ty_b} {{")),
2115 indent(get_b),
2116 line("}"),
2117 ]));
2118 } else {
2119 union_fields.push(field);
2120 }
2121
2122 builder_members.push(generate_setter(
2123 ctx,
2124 discriminant_offset,
2125 &styled_name,
2126 &field,
2127 )?);
2128
2129 reader_members.push(generate_haser(
2130 discriminant_offset,
2131 &styled_name,
2132 &field,
2133 true,
2134 )?);
2135 builder_members.push(generate_haser(
2136 discriminant_offset,
2137 &styled_name,
2138 &field,
2139 false,
2140 )?);
2141
2142 if let Ok(field::Group(group)) = field.which() {
2143 let id = group.get_type_id();
2144 let text = generate_node(ctx, id, ctx.get_last_name(id)?)?;
2145 nested_output.push(text);
2146 }
2147 }
2148
2149 if discriminant_count > 0 {
2150 let (which_enums1, union_getter, typedef, mut default_decls) =
2151 generate_union(ctx, discriminant_offset, &union_fields, true, ¶ms)?;
2152 which_enums.push(which_enums1);
2153 which_enums.push(typedef);
2154 reader_members.push(union_getter);
2155
2156 private_mod_interior.append(&mut default_decls);
2157
2158 let (_, union_getter, typedef, _) =
2159 generate_union(ctx, discriminant_offset, &union_fields, false, ¶ms)?;
2160 which_enums.push(typedef);
2161 builder_members.push(union_getter);
2162
2163 let mut reexports = String::new();
2164 reexports.push_str("pub use self::Which::{");
2165 let mut whichs = Vec::new();
2166 for f in &union_fields {
2167 whichs.push(capitalize_first_letter(get_field_name(*f)?));
2168 }
2169 reexports.push_str(&whichs.join(","));
2170 reexports.push_str("};");
2171 preamble.push(Line(reexports));
2172 preamble.push(BlankLine);
2173 }
2174
2175 let builder_struct_size =
2176 Branch(vec![
2177 Line(fmt!(ctx,"impl <{0}> {capnp}::traits::HasStructSize for Builder<'_,{0}> {1} {{",
2178 params.params, params.where_clause)),
2179 indent(Line(
2180 fmt!(ctx,"const STRUCT_SIZE: {capnp}::private::layout::StructSize = {capnp}::private::layout::StructSize {{ data: {}, pointers: {} }};", data_size as usize, pointer_size as usize))),
2181 line("}")]);
2182
2183 private_mod_interior.push(Line(format!(
2184 "pub const TYPE_ID: u64 = {};",
2185 format_u64(node_id)
2186 )));
2187
2188 let from_pointer_builder_impl =
2189 Branch(vec![
2190 Line(fmt!(ctx,"impl <'a,{0}> {capnp}::traits::FromPointerBuilder<'a> for Builder<'a,{0}> {1} {{", params.params, params.where_clause)),
2191 indent(vec![
2192 Line(fmt!(ctx,"fn init_pointer(builder: {capnp}::private::layout::PointerBuilder<'a>, _size: u32) -> Self {{")),
2193 indent(Line(fmt!(ctx,"builder.init_struct(<Self as {capnp}::traits::HasStructSize>::STRUCT_SIZE).into()"))),
2194 line("}"),
2195 Line(fmt!(ctx,"fn get_from_pointer(builder: {capnp}::private::layout::PointerBuilder<'a>, default: ::core::option::Option<&'a [{capnp}::Word]>) -> {capnp}::Result<Self> {{")),
2196 indent(Line(fmt!(ctx,"::core::result::Result::Ok(builder.get_struct(<Self as {capnp}::traits::HasStructSize>::STRUCT_SIZE, default)?.into())"))),
2197 line("}")
2198 ]),
2199 line("}"),
2200 BlankLine]);
2201
2202 let accessors = vec![
2203 Branch(preamble),
2204 (if !is_generic {
2205 Branch(vec![
2206 Line("#[derive(Copy, Clone)]".into()),
2207 line("pub struct Owned(());"),
2208 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 }}).into() }} }}")),
2209 Line(fmt!(ctx, "impl {capnp}::traits::Owned for Owned {{ type Reader<'a> = Reader<'a>; type Builder<'a> = Builder<'a>; }}")),
2210 Line(fmt!(ctx,"impl {capnp}::traits::OwnedStruct for Owned {{ type Reader<'a> = Reader<'a>; type Builder<'a> = Builder<'a>; }}")),
2211 Line(fmt!(ctx,"impl {capnp}::traits::Pipelined for Owned {{ type Pipeline = Pipeline; }}"))
2212 ])
2213 } else {
2214 Branch(vec![
2215 Line("#[derive(Copy, Clone)]".into()),
2216 Line(format!("pub struct Owned<{}> {{", params.params)),
2217 indent(Line(params.phantom_data_type.clone())),
2218 line("}"),
2219 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}> }}).into() }} }}",
2220 params.params, params.where_clause)),
2221 Line(fmt!(ctx,"impl <{0}> {capnp}::traits::Owned for Owned <{0}> {1} {{ type Reader<'a> = Reader<'a, {0}>; type Builder<'a> = Builder<'a, {0}>; }}",
2222 params.params, params.where_clause)),
2223 Line(fmt!(ctx,"impl <{0}> {capnp}::traits::OwnedStruct for Owned <{0}> {1} {{ type Reader<'a> = Reader<'a, {0}>; type Builder<'a> = Builder<'a, {0}>; }}",
2224 params.params, params.where_clause)),
2225 Line(fmt!(ctx,"impl <{0}> {capnp}::traits::Pipelined for Owned<{0}> {1} {{ type Pipeline = Pipeline{2}; }}",
2226 params.params, params.where_clause, bracketed_params)),
2227 ])
2228 }),
2229 BlankLine,
2230 (if !is_generic {
2231 Line(fmt!(ctx,"pub struct Reader<'a> {{ reader: {capnp}::private::layout::StructReader<'a> }}"))
2232 } else {
2233 Branch(vec![
2234 Line(format!("pub struct Reader<'a,{}> {} {{", params.params, params.where_clause)),
2235 indent(vec![
2236 Line(fmt!(ctx,"reader: {capnp}::private::layout::StructReader<'a>,")),
2237 Line(params.phantom_data_type.clone()),
2238 ]),
2239 line("}")
2240 ])
2241 }),
2242 Branch(vec![
2245 Line(format!("impl <{0}> ::core::marker::Copy for Reader<'_,{0}> {1} {{}}",
2246 params.params, params.where_clause)),
2247 Line(format!("impl <{0}> ::core::clone::Clone for Reader<'_,{0}> {1} {{",
2248 params.params, params.where_clause)),
2249 indent(Line("fn clone(&self) -> Self { *self }".into())),
2250 Line("}".into())]),
2251 BlankLine,
2252 Branch(vec![
2253 Line(fmt!(ctx,"impl <{0}> {capnp}::traits::HasTypeId for Reader<'_,{0}> {1} {{",
2254 params.params, params.where_clause)),
2255 indent(vec![line("const TYPE_ID: u64 = _private::TYPE_ID;")]),
2256 line("}")]),
2257 Line(fmt!(ctx,"impl <'a,{0}> ::core::convert::From<{capnp}::private::layout::StructReader<'a>> for Reader<'a,{0}> {1} {{",
2258 params.params, params.where_clause)),
2259 indent(vec![
2260 Line(fmt!(ctx,"fn from(reader: {capnp}::private::layout::StructReader<'a>) -> Self {{")),
2261 indent(Line(format!("Self {{ reader, {} }}", params.phantom_data_value))),
2262 line("}")
2263 ]),
2264 line("}"),
2265 BlankLine,
2266 Line(fmt!(ctx,"impl <'a,{0}> ::core::convert::From<Reader<'a,{0}>> for {capnp}::dynamic_value::Reader<'a> {1} {{",
2267 params.params, params.where_clause)),
2268 indent(vec![
2269 Line(format!("fn from(reader: Reader<'a,{0}>) -> Self {{", params.params)),
2270 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}>}})))", params.params))),
2271 line("}")
2272 ]),
2273 line("}"),
2274 BlankLine,
2275 Line(format!("impl <{0}> ::core::fmt::Debug for Reader<'_,{0}> {1} {{",
2276 params.params, params.where_clause)),
2277 indent(vec![
2278 Line("fn fmt(&self, f: &mut ::core::fmt::Formatter<'_>) -> ::core::result::Result<(), ::core::fmt::Error> {".into()),
2279 indent(Line(fmt!(ctx,"core::fmt::Debug::fmt(&::core::convert::Into::<{capnp}::dynamic_value::Reader<'_>>::into(*self), f)"))),
2280 line("}")
2281 ]),
2282 line("}"),
2283
2284 BlankLine,
2285
2286 Line(fmt!(ctx,"impl <'a,{0}> {capnp}::traits::FromPointerReader<'a> for Reader<'a,{0}> {1} {{",
2287 params.params, params.where_clause)),
2288 indent(vec![
2289 Line(fmt!(ctx,"fn get_from_pointer(reader: &{capnp}::private::layout::PointerReader<'a>, default: ::core::option::Option<&'a [{capnp}::Word]>) -> {capnp}::Result<Self> {{")),
2290 indent(line("::core::result::Result::Ok(reader.get_struct(default)?.into())")),
2291 line("}")
2292 ]),
2293 line("}"),
2294 BlankLine,
2295 Line(fmt!(ctx,"impl <'a,{0}> {capnp}::traits::IntoInternalStructReader<'a> for Reader<'a,{0}> {1} {{",
2296 params.params, params.where_clause)),
2297 indent(vec![
2298 Line(fmt!(ctx,"fn into_internal_struct_reader(self) -> {capnp}::private::layout::StructReader<'a> {{")),
2299 indent(line("self.reader")),
2300 line("}")
2301 ]),
2302 line("}"),
2303 BlankLine,
2304 Line(fmt!(ctx,"impl <'a,{0}> {capnp}::traits::Imbue<'a> for Reader<'a,{0}> {1} {{",
2305 params.params, params.where_clause)),
2306 indent(vec![
2307 Line(fmt!(ctx,"fn imbue(&mut self, cap_table: &'a {capnp}::private::layout::CapTable) {{")),
2308 indent(Line(fmt!(ctx,"self.reader.imbue({capnp}::private::layout::CapTableReader::Plain(cap_table))"))),
2309 line("}")
2310 ]),
2311 line("}"),
2312 BlankLine,
2313 if has_pointer_field { Line(format!("impl <'a,{0}> Reader<'a,{0}> {1} {{", params.params, params.where_clause))
2315 } else {
2316 Line(format!("impl <{0}> Reader<'_,{0}> {1} {{", params.params, params.where_clause))
2317 },
2318 indent(vec![
2319 Line(format!("pub fn reborrow(&self) -> Reader<'_,{}> {{",params.params)),
2320 indent(line("Self { .. *self }")),
2321 line("}"),
2322 BlankLine,
2323 Line(fmt!(ctx,"pub fn total_size(&self) -> {capnp}::Result<{capnp}::MessageSize> {{")),
2324 indent(line("self.reader.total_size()")),
2325 line("}")]),
2326 indent(reader_members),
2327 line("}"),
2328 BlankLine,
2329 (if !is_generic {
2330 Line(fmt!(ctx,"pub struct Builder<'a> {{ builder: {capnp}::private::layout::StructBuilder<'a> }}"))
2331 } else {
2332 Branch(vec![
2333 Line(format!("pub struct Builder<'a,{}> {} {{",
2334 params.params, params.where_clause)),
2335 indent(vec![
2336 Line(fmt!(ctx, "builder: {capnp}::private::layout::StructBuilder<'a>,")),
2337 Line(params.phantom_data_type.clone()),
2338 ]),
2339 line("}")
2340 ])
2341 }),
2342 builder_struct_size,
2343 Branch(vec![
2344 Line(fmt!(ctx,"impl <{0}> {capnp}::traits::HasTypeId for Builder<'_,{0}> {1} {{",
2345 params.params, params.where_clause)),
2346 indent(vec![
2347 line("const TYPE_ID: u64 = _private::TYPE_ID;")]),
2348 line("}")
2349 ]),
2350 Line(fmt!(ctx,
2351 "impl <'a,{0}> ::core::convert::From<{capnp}::private::layout::StructBuilder<'a>> for Builder<'a,{0}> {1} {{",
2352 params.params, params.where_clause)),
2353 indent(vec![
2354 Line(fmt!(ctx,"fn from(builder: {capnp}::private::layout::StructBuilder<'a>) -> Self {{")),
2355 indent(Line(format!("Self {{ builder, {} }}", params.phantom_data_value))),
2356 line("}")
2357 ]),
2358 line("}"),
2359 BlankLine,
2360 Line(fmt!(ctx,"impl <'a,{0}> ::core::convert::From<Builder<'a,{0}>> for {capnp}::dynamic_value::Builder<'a> {1} {{",
2361 params.params, params.where_clause)),
2362 indent(vec![
2363 Line(format!("fn from(builder: Builder<'a,{0}>) -> Self {{", params.params)),
2364 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}>}})))", params.params))),
2365 line("}")
2366 ]),
2367 line("}"),
2368 BlankLine,
2369
2370 Line(fmt!(ctx,"impl <'a,{0}> {capnp}::traits::ImbueMut<'a> for Builder<'a,{0}> {1} {{",
2371 params.params, params.where_clause)),
2372 indent(vec![
2373 Line(fmt!(ctx,"fn imbue_mut(&mut self, cap_table: &'a mut {capnp}::private::layout::CapTable) {{")),
2374 indent(Line(fmt!(ctx,"self.builder.imbue({capnp}::private::layout::CapTableBuilder::Plain(cap_table))"))),
2375 line("}")]),
2376 line("}"),
2377 BlankLine,
2378
2379 from_pointer_builder_impl,
2380 Line(fmt!(ctx,
2381 "impl <{0}> {capnp}::traits::SetterInput<Owned<{0}>> for Reader<'_,{0}> {1} {{",
2382 params.params, params.where_clause)),
2383 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) }}"))),
2384 line("}"),
2385 BlankLine,
2386 Line(format!("impl <'a,{0}> Builder<'a,{0}> {1} {{", params.params, params.where_clause)),
2387 indent(vec![
2388 Line(format!("pub fn into_reader(self) -> Reader<'a,{}> {{", params.params)),
2389 indent(line("self.builder.into_reader().into()")),
2390 line("}"),
2391 Line(format!("pub fn reborrow(&mut self) -> Builder<'_,{}> {{", params.params)),
2392 (if !is_generic {
2393 indent(line("Builder { builder: self.builder.reborrow() }"))
2394 } else {
2395 indent(line("Builder { builder: self.builder.reborrow(), ..*self }"))
2396 }),
2397 line("}"),
2398 Line(format!("pub fn reborrow_as_reader(&self) -> Reader<'_,{}> {{", params.params)),
2399 indent(line("self.builder.as_reader().into()")),
2400 line("}"),
2401
2402 BlankLine,
2403 Line(fmt!(ctx,"pub fn total_size(&self) -> {capnp}::Result<{capnp}::MessageSize> {{")),
2404 indent(line("self.builder.as_reader().total_size()")),
2405 line("}")
2406 ]),
2407 indent(builder_members),
2408 line("}"),
2409 BlankLine,
2410 (if is_generic {
2411 Branch(vec![
2412 Line(format!("pub struct Pipeline{bracketed_params} {{")),
2413 indent(vec![
2414 Line(fmt!(ctx,"_typeless: {capnp}::any_pointer::Pipeline,")),
2415 Line(params.phantom_data_type),
2416 ]),
2417 line("}")
2418 ])
2419 } else {
2420 Line(fmt!(ctx,"pub struct Pipeline {{ _typeless: {capnp}::any_pointer::Pipeline }}"))
2421 }),
2422 Line(fmt!(ctx,"impl{bracketed_params} {capnp}::capability::FromTypelessPipeline for Pipeline{bracketed_params} {{")),
2423 indent(vec![
2424 Line(fmt!(ctx,"fn new(typeless: {capnp}::any_pointer::Pipeline) -> Self {{")),
2425 indent(Line(format!("Self {{ _typeless: typeless, {} }}", params.phantom_data_value))),
2426 line("}")]),
2427 line("}"),
2428 Line(format!("impl{0} Pipeline{0} {1} {{", bracketed_params,
2429 params.pipeline_where_clause)),
2430 indent(pipeline_impl_interior),
2431 line("}"),
2432 line("mod _private {"),
2433 indent(private_mod_interior),
2434 line("}"),
2435 ];
2436
2437 output.push(indent(vec![
2438 Branch(accessors),
2439 Branch(which_enums),
2440 Branch(nested_output),
2441 ]));
2442 output.push(line("}"));
2443 }
2444
2445 node::Enum(enum_reader) => {
2446 let last_name = ctx.get_last_name(node_id)?;
2447 let name_as_mod = module_name(last_name);
2448 output.push(BlankLine);
2449
2450 let mut members = Vec::new();
2451 let mut match_branches = Vec::new();
2452 let enumerants = enum_reader.get_enumerants()?;
2453 for (ii, enumerant) in enumerants.into_iter().enumerate() {
2454 let enumerant = capitalize_first_letter(get_enumerant_name(enumerant)?);
2455 members.push(Line(format!("{enumerant} = {ii},")));
2456 match_branches.push(Line(format!(
2457 "{ii} => ::core::result::Result::Ok(Self::{enumerant}),"
2458 )));
2459 }
2460 match_branches.push(Line(fmt!(
2461 ctx,
2462 "n => ::core::result::Result::Err({capnp}::NotInSchema(n)),"
2463 )));
2464
2465 output.push(Branch(vec![
2466 line("#[repr(u16)]"),
2467 line("#[derive(Clone, Copy, Debug, PartialEq, Eq)]"),
2468 Line(format!("pub enum {last_name} {{")),
2469 indent(members),
2470 line("}"),
2471 ]));
2472
2473 output.push(BlankLine);
2474 output.push(Branch(vec![
2475 Line(fmt!(ctx,
2476 "impl {capnp}::introspect::Introspect for {last_name} {{"
2477 )),
2478 indent(Line(fmt!(ctx,
2479 "fn introspect() -> {capnp}::introspect::Type {{ {capnp}::introspect::TypeVariant::Enum({capnp}::introspect::RawEnumSchema {{ encoded_node: &{0}::ENCODED_NODE, annotation_types: {0}::get_annotation_types }}).into() }}", name_as_mod))),
2480 Line("}".into()),
2481 ]));
2482
2483 output.push(Branch(vec![
2484 Line(fmt!(ctx,"impl ::core::convert::From<{last_name}> for {capnp}::dynamic_value::Reader<'_> {{")),
2485 indent(Line(fmt!(ctx,
2486 "fn from(e: {last_name}) -> Self {{ {capnp}::dynamic_value::Enum::new(e.into(), {capnp}::introspect::RawEnumSchema {{ encoded_node: &{0}::ENCODED_NODE, annotation_types: {0}::get_annotation_types }}.into()).into() }}", name_as_mod ))),
2487 Line("}".into())
2488 ]));
2489
2490 output.push(Branch(vec![
2491 Line(format!(
2492 "impl ::core::convert::TryFrom<u16> for {last_name} {{"
2493 )),
2494 indent(Line(
2495 fmt!(ctx,"type Error = {capnp}::NotInSchema;"),
2496 )),
2497 indent(vec![
2498 Line(
2499 format!("fn try_from(value: u16) -> ::core::result::Result<Self, <{last_name} as ::core::convert::TryFrom<u16>>::Error> {{")
2500 ),
2501 indent(vec![
2502 line("match value {"),
2503 indent(match_branches),
2504 line("}"),
2505 ]),
2506 line("}"),
2507 ]),
2508 line("}"),
2509 Line(format!("impl From<{last_name}> for u16 {{")),
2510 indent(line("#[inline]")),
2511 indent(Line(format!(
2512 "fn from(x: {last_name}) -> u16 {{ x as u16 }}"
2513 ))),
2514 line("}"),
2515 ]));
2516
2517 output.push(Branch(vec![
2518 Line(fmt!(
2519 ctx,
2520 "impl {capnp}::traits::HasTypeId for {last_name} {{"
2521 )),
2522 indent(Line(format!(
2523 "const TYPE_ID: u64 = {}u64;",
2524 format_u64(node_id)
2525 ))),
2526 line("}"),
2527 ]));
2528
2529 output.push(Branch(vec![
2530 Line(format!("mod {name_as_mod} {{")),
2531 Branch(vec![
2532 crate::pointer_constants::node_word_array_declaration(
2533 ctx,
2534 "ENCODED_NODE",
2535 *node_reader,
2536 crate::pointer_constants::WordArrayDeclarationOptions { public: true },
2537 )?,
2538 generate_get_annotation_types(ctx, *node_reader)?,
2539 ]),
2540 Line("}".into()),
2541 ]));
2542 }
2543
2544 node::Interface(interface) => {
2545 let params = node_reader.parameters_texts(ctx);
2546 output.push(BlankLine);
2547
2548 let is_generic = node_reader.get_is_generic();
2549
2550 let names = &ctx.scope_map[&node_id];
2551 let mut client_impl_interior = Vec::new();
2552 let mut server_interior = Vec::new();
2553 let mut mod_interior = Vec::new();
2554 let mut dispatch_arms = Vec::new();
2555 let mut private_mod_interior = Vec::new();
2556
2557 let bracketed_params = if params.params.is_empty() {
2558 "".to_string()
2559 } else {
2560 format!("<{}>", params.params)
2561 };
2562
2563 private_mod_interior.push(Line(format!(
2564 "pub const TYPE_ID: u64 = {};",
2565 format_u64(node_id)
2566 )));
2567
2568 mod_interior.push(line("#![allow(unused_variables)]"));
2569
2570 let methods = interface.get_methods()?;
2571 for (ordinal, method) in methods.into_iter().enumerate() {
2572 let name = method.get_name()?.to_str()?;
2573
2574 let param_id = method.get_param_struct_type();
2575 let param_node = &ctx.node_map[¶m_id];
2576 let (param_scopes, params_ty_params) = if param_node.get_scope_id() == 0 {
2577 let mut names = names.clone();
2578 let local_name = module_name(&format!("{name}Params"));
2579 nested_output.push(generate_node(ctx, param_id, &local_name)?);
2580 names.push(local_name);
2581 (names, params.params.clone())
2582 } else {
2583 (
2584 ctx.scope_map[¶m_node.get_id()].clone(),
2585 get_ty_params_of_brand(ctx, method.get_param_brand()?)?,
2586 )
2587 };
2588 let param_type = do_branding(
2589 ctx,
2590 param_id,
2591 method.get_param_brand()?,
2592 Leaf::Owned,
2593 ¶m_scopes.join("::"),
2594 )?;
2595
2596 mod_interior.push(Line(fmt!(
2597 ctx,
2598 "pub type {}Params<{}> = {capnp}::capability::Params<{}>;",
2599 capitalize_first_letter(name),
2600 params_ty_params,
2601 param_type
2602 )));
2603
2604 let result_id = method.get_result_struct_type();
2605 if result_id != STREAM_RESULT_ID {
2606 dispatch_arms.push(
2607 Line(fmt!(ctx,
2608 "{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),",
2609 module_name(name))));
2610
2611 let result_node = &ctx.node_map[&result_id];
2612 let (result_scopes, results_ty_params) = if result_node.get_scope_id() == 0 {
2613 let mut names = names.clone();
2614 let local_name = module_name(&format!("{name}Results"));
2615 nested_output.push(generate_node(ctx, result_id, &local_name)?);
2616 names.push(local_name);
2617 (names, params.params.clone())
2618 } else {
2619 (
2620 ctx.scope_map[&result_node.get_id()].clone(),
2621 get_ty_params_of_brand(ctx, method.get_result_brand()?)?,
2622 )
2623 };
2624 let result_type = do_branding(
2625 ctx,
2626 result_id,
2627 method.get_result_brand()?,
2628 Leaf::Owned,
2629 &result_scopes.join("::"),
2630 )?;
2631 mod_interior.push(Line(fmt!(
2632 ctx,
2633 "pub type {}Results<{}> = {capnp}::capability::Results<{}>;",
2634 capitalize_first_letter(name),
2635 results_ty_params,
2636 result_type
2637 )));
2638 server_interior.push(
2639 Line(fmt!(ctx,
2640 "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()))) }}",
2641 module_name(name),
2642 capitalize_first_letter(name), params_ty_params,
2643 capitalize_first_letter(name), results_ty_params,
2644 node_name, module_name(name)
2645 )));
2646
2647 client_impl_interior.push(Line(fmt!(
2648 ctx,
2649 "pub fn {}_request(&self) -> {capnp}::capability::Request<{},{}> {{",
2650 camel_to_snake_case(name),
2651 param_type,
2652 result_type
2653 )));
2654
2655 client_impl_interior.push(indent(Line(format!(
2656 "self.client.new_call(_private::TYPE_ID, {ordinal}, ::core::option::Option::None)"
2657 ))));
2658 client_impl_interior.push(line("}"));
2659 } else {
2660 dispatch_arms.push(
2662 Line(fmt!(ctx,
2663 "{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),",
2664
2665 module_name(name))));
2666
2667 server_interior.push(
2668 Line(fmt!(ctx,
2669 "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()))) }}",
2670 module_name(name),
2671 capitalize_first_letter(name), params_ty_params,
2672 node_name, module_name(name)
2673 )));
2674 client_impl_interior.push(Line(fmt!(
2675 ctx,
2676 "pub fn {}_request(&self) -> {capnp}::capability::StreamingRequest<{}> {{",
2677 camel_to_snake_case(name),
2678 param_type
2679 )));
2680 client_impl_interior.push(indent(Line(format!(
2681 "self.client.new_streaming_call(_private::TYPE_ID, {ordinal}, ::core::option::Option::None)"
2682 ))));
2683
2684 client_impl_interior.push(line("}"));
2685 }
2686
2687 method.get_annotations()?;
2688 }
2689
2690 let mut base_dispatch_arms = Vec::new();
2691
2692 let server_base = {
2693 let mut base_traits = Vec::new();
2694
2695 fn find_super_interfaces<'a>(
2696 interface: schema_capnp::node::interface::Reader<'a>,
2697 all_extends: &mut Vec<
2698 <schema_capnp::superclass::Owned as capnp::traits::OwnedStruct>::Reader<'a>,
2699 >,
2700 ctx: &GeneratorContext<'a>,
2701 ) -> ::capnp::Result<()> {
2702 let extends = interface.get_superclasses()?;
2703 for superclass in extends {
2704 if let node::Interface(interface) =
2705 ctx.node_map[&superclass.get_id()].which()?
2706 {
2707 find_super_interfaces(interface, all_extends, ctx)?;
2708 }
2709 all_extends.push(superclass);
2710 }
2711 Ok(())
2712 }
2713
2714 let mut extends = Vec::new();
2715 find_super_interfaces(interface, &mut extends, ctx)?;
2716 for interface in &extends {
2717 let type_id = interface.get_id();
2718 let brand = interface.get_brand()?;
2719 let the_mod = ctx.get_qualified_module(type_id);
2720
2721 base_dispatch_arms.push(Line(format!(
2722 "0x{type_id:x} => {}::dispatch_call_internal(self.server, method_id, params, results),",
2723 do_branding(
2724 ctx, type_id, brand, Leaf::ServerDispatch, &the_mod)?)));
2725 base_traits.push(do_branding(ctx, type_id, brand, Leaf::Server, &the_mod)?);
2726 }
2727
2728 if !extends.is_empty() {
2731 format!(": {} + 'static", base_traits.join(" + "))
2732 } else {
2733 ": 'static".to_string()
2734 }
2735 };
2736
2737 mod_interior.push(BlankLine);
2738 mod_interior.push(Line(format!("pub struct Client{bracketed_params} {{")));
2739 mod_interior.push(indent(Line(fmt!(
2740 ctx,
2741 "pub client: {capnp}::capability::Client,"
2742 ))));
2743 if is_generic {
2744 mod_interior.push(indent(Line(params.phantom_data_type.clone())));
2745 }
2746 mod_interior.push(line("}"));
2747 mod_interior.push(
2748 Branch(vec![
2749 Line(fmt!(ctx,"impl {bracketed_params} {capnp}::capability::FromClientHook for Client{bracketed_params} {{")),
2750 indent(Line(fmt!(ctx,"fn new(hook: Box<{capnp}::capability::DynClientHook>) -> Self {{"))),
2751 indent(indent(Line(fmt!(ctx,"Self {{ client: {capnp}::capability::Client::new(hook), {} }}", params.phantom_data_value)))),
2752 indent(line("}")),
2753 indent(Line(fmt!(ctx,"fn into_client_hook(self) -> Box<{capnp}::capability::DynClientHook> {{"))),
2754 indent(indent(line("self.client.hook"))),
2755 indent(line("}")),
2756 indent(Line(fmt!(ctx,"fn as_client_hook(&self) -> &{capnp}::capability::DynClientHook {{"))),
2757 indent(indent(line("&*self.client.hook"))),
2758 indent(line("}")),
2759 line("}")]));
2760
2761 mod_interior.push(if !is_generic {
2762 Branch(vec![
2763 Line("#[derive(Copy, Clone)]".into()),
2764 line("pub struct Owned(());"),
2765 Line(fmt!(ctx,"impl {capnp}::introspect::Introspect for Owned {{ fn introspect() -> {capnp}::introspect::Type {{ {capnp}::introspect::TypeVariant::Capability.into() }} }}")),
2766 line("impl ::capnp::traits::Owned for Owned { type Reader<'a> = Client; type Builder<'a> = Client; }"),
2767 Line(fmt!(ctx,"impl {capnp}::traits::Pipelined for Owned {{ type Pipeline = Client; }}"))])
2768 } else {
2769 Branch(vec![
2770 Line("#[derive(Copy, Clone)]".into()),
2771 Line(format!("pub struct Owned<{}> {} {{", params.params, params.where_clause)),
2772 indent(Line(params.phantom_data_type.clone())),
2773 line("}"),
2774 Line(fmt!(ctx,
2775 "impl <{0}> {capnp}::introspect::Introspect for Owned <{0}> {1} {{ fn introspect() -> {capnp}::introspect::Type {{ {capnp}::introspect::TypeVariant::Capability.into() }} }}",
2776 params.params, params.where_clause)),
2777 Line(fmt!(ctx,
2778 "impl <{0}> {capnp}::traits::Owned for Owned <{0}> {1} {{ type Reader<'a> = Client<{0}>; type Builder<'a> = Client<{0}>; }}",
2779 params.params, params.where_clause)),
2780 Line(fmt!(ctx,
2781 "impl <{0}> {capnp}::traits::Pipelined for Owned <{0}> {1} {{ type Pipeline = Client{2}; }}",
2782 params.params, params.where_clause, bracketed_params))])
2783 });
2784
2785 mod_interior.push(Branch(vec![
2786 Line(fmt!(ctx,"impl <'a,{0}> {capnp}::traits::FromPointerReader<'a> for Client<{0}> {1} {{",
2787 params.params, params.where_clause)),
2788 indent(vec![
2789 Line(fmt!(ctx,"fn get_from_pointer(reader: &{capnp}::private::layout::PointerReader<'a>, _default: ::core::option::Option<&'a [{capnp}::Word]>) -> {capnp}::Result<Self> {{")),
2790 indent(Line(fmt!(ctx,"::core::result::Result::Ok({capnp}::capability::FromClientHook::new(reader.get_capability()?))"))),
2791 line("}")]),
2792 line("}")]));
2793
2794 mod_interior.push(Branch(vec![
2795 Line(fmt!(ctx,"impl <'a,{0}> {capnp}::traits::FromPointerBuilder<'a> for Client<{0}> {1} {{",
2796 params.params, params.where_clause)),
2797 indent(vec![
2798 Line(fmt!(ctx,"fn init_pointer(_builder: {capnp}::private::layout::PointerBuilder<'a>, _size: u32) -> Self {{")),
2799 indent(line("unimplemented!()")),
2800 line("}"),
2801 Line(fmt!(ctx,"fn get_from_pointer(builder: {capnp}::private::layout::PointerBuilder<'a>, _default: ::core::option::Option<&'a [{capnp}::Word]>) -> {capnp}::Result<Self> {{")),
2802 indent(Line(fmt!(ctx,"::core::result::Result::Ok({capnp}::capability::FromClientHook::new(builder.get_capability()?))"))),
2803 line("}")]),
2804 line("}"),
2805 BlankLine]));
2806
2807 mod_interior.push(Branch(vec![
2808 Line(fmt!(ctx,
2809 "impl <{0}> {capnp}::traits::SetterInput<Owned<{0}>> for Client<{0}> {1} {{",
2810 params.params, params.where_clause)),
2811 indent(vec![
2812 Line(fmt!(ctx,"fn set_pointer_builder(mut pointer: {capnp}::private::layout::PointerBuilder<'_>, from: Self, _canonicalize: bool) -> {capnp}::Result<()> {{")),
2813 indent(Line("pointer.set_capability(from.client.hook);".to_string())),
2814 indent(Line("::core::result::Result::Ok(())".to_string())),
2815 line("}")
2816 ]
2817 ),
2818 line("}")]));
2819
2820 mod_interior.push(Branch(vec![
2821 Line(fmt!(ctx,
2822 "impl {bracketed_params} {capnp}::traits::HasTypeId for Client{bracketed_params} {{"
2823 )),
2824 indent(Line(
2825 "const TYPE_ID: u64 = _private::TYPE_ID;".to_string(),
2826 )),
2827 line("}"),
2828 ]));
2829
2830 mod_interior.push(Branch(vec![
2831 Line(format!(
2832 "impl {bracketed_params} Clone for Client{bracketed_params} {{"
2833 )),
2834 indent(line("fn clone(&self) -> Self {")),
2835 indent(indent(Line(format!(
2836 "Self {{ client: self.client.clone(), {} }}",
2837 params.phantom_data_value
2838 )))),
2839 indent(line("}")),
2840 line("}"),
2841 ]));
2842
2843 mod_interior.push(Branch(vec![
2844 Line(format!(
2845 "impl {bracketed_params} Client{bracketed_params} {{"
2846 )),
2847 indent(client_impl_interior),
2848 line("}"),
2849 ]));
2850
2851 mod_interior.push(Branch(vec![
2852 Line(format!(
2853 "pub trait Server<{}> {} {} {{",
2854 params.params, server_base, params.where_clause
2855 )),
2856 indent(server_interior),
2857 line("}"),
2858 ]));
2859
2860 mod_interior.push(Branch(vec![
2861 Line(format!(
2862 "pub struct ServerDispatch<_T,{}> {{",
2863 params.params
2864 )),
2865 indent(line(fmt!(ctx, "pub server: {capnp}::capability::Rc<_T>,"))),
2866 indent(if is_generic {
2867 vec![Line(params.phantom_data_type.clone())]
2868 } else {
2869 vec![]
2870 }),
2871 line("}"),
2872 ]));
2873
2874 mod_interior.push(Branch(vec![
2875 Line(
2876 fmt!(ctx,"impl <_S: Server{1} + 'static, {0}> {capnp}::capability::FromServer<_S> for Client{1} {2} {{",
2877 params.params, bracketed_params, params.where_clause_with_static)),
2878 indent(vec![
2879 Line(format!("type Dispatch = ServerDispatch<_S, {}>;", params.params)),
2880 Line(fmt!(ctx, "fn from_server(s: {capnp}::capability::Rc<_S>) -> ServerDispatch<_S, {}> {{", params.params)),
2881 indent(Line(format!("ServerDispatch {{ server: s, {} }}", params.phantom_data_value))),
2882 line("}"),
2883 ]),
2884 line("}"),
2885 ]));
2886
2887 mod_interior.push(
2888 Branch(vec![
2889 (if is_generic {
2890 Line(format!("impl <{}, _T: Server{}> ::core::ops::Deref for ServerDispatch<_T,{}> {} {{", params.params, bracketed_params, params.params, params.where_clause))
2891 } else {
2892 line("impl <_T: Server> ::core::ops::Deref for ServerDispatch<_T> {")
2893 }),
2894 indent(line("type Target = _T;")),
2895 indent(line("fn deref(&self) -> &_T { &self.server}")),
2896 line("}"),
2897 ]));
2898
2899 mod_interior.push(
2900 Branch(vec![
2901 (if is_generic {
2902 Line(format!("impl <{}, _T: Server{}> ::core::clone::Clone for ServerDispatch<_T,{}> {} {{", params.params, bracketed_params, params.params, params.where_clause))
2903 } else {
2904 line("impl <_T: Server> ::core::clone::Clone for ServerDispatch<_T> {")
2905 }),
2906 indent(line(
2907 format!("fn clone(&self) -> Self {{ Self {{ server: self.server.clone(), {} }} }}", params.phantom_data_value))),
2908 line("}"),
2909 ]));
2910
2911 mod_interior.push(
2912 Branch(vec![
2913 (if is_generic {
2914 Line(fmt!(ctx,"impl <{}, _T: Server{}> {capnp}::capability::Server for ServerDispatch<_T,{}> {} {{", params.params, bracketed_params, params.params, params.where_clause_with_static))
2915 } else {
2916 Line(fmt!(ctx,"impl <_T: Server> {capnp}::capability::Server for ServerDispatch<_T> {{"))
2917 }),
2918 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 {{"))),
2919 indent(indent(line("match interface_id {"))),
2920 indent(indent(indent(line("_private::TYPE_ID => Self::dispatch_call_internal(self.server, method_id, params, results),")))),
2921 indent(indent(indent(base_dispatch_arms))),
2922 indent(indent(indent(Line(fmt!(ctx,"_ => {{ {capnp}::capability::DispatchCallResult::new({capnp}::capability::Promise::err({capnp}::Error::unimplemented(\"Method not implemented.\".to_string())), false) }}"))))),
2923 indent(indent(line("}"))),
2924 indent(line("}")),
2925
2926 indent(Line(fmt!(ctx, "fn as_ptr(&self) -> usize {{ {capnp}::capability::Rc::as_ptr(&self.server) as usize }}"))),
2927
2928 line("}")]));
2929
2930 mod_interior.push(
2931 Branch(vec![
2932 (if is_generic {
2933 Line(format!("impl <{}, _T: Server{}> ServerDispatch<_T,{}> {} {{", params.params, bracketed_params, params.params, params.where_clause_with_static))
2934 } else {
2935 line("impl <_T :Server> ServerDispatch<_T> {")
2936 }),
2937
2938 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 {{"))),
2939 indent(indent(line("match method_id {"))),
2940 indent(indent(indent(dispatch_arms))),
2941 indent(indent(indent(Line(fmt!(ctx,"_ => {{ {capnp}::capability::DispatchCallResult::new({capnp}::capability::Promise::err({capnp}::Error::unimplemented(\"Method not implemented.\".to_string())), false) }}"))))),
2942 indent(indent(line("}"))),
2943 indent(line("}")),
2944 line("}")]));
2945
2946 mod_interior.push(Branch(vec![
2947 line("pub mod _private {"),
2948 indent(private_mod_interior),
2949 line("}"),
2950 ]));
2951
2952 mod_interior.push(Branch(vec![Branch(nested_output)]));
2953
2954 output.push(BlankLine);
2955 if is_generic {
2956 output.push(Line(format!(
2957 "pub mod {} {{ /* ({}) */",
2958 node_name,
2959 params.expanded_list.join(",")
2960 )));
2961 } else {
2962 output.push(Line(format!("pub mod {node_name} {{")));
2963 }
2964 output.push(indent(mod_interior));
2965 output.push(line("}"));
2966 }
2967
2968 node::Const(c) => {
2969 let styled_name = snake_to_upper_case(ctx.get_last_name(node_id)?);
2970
2971 let typ = c.get_type()?;
2972 let formatted_text = match (typ.which()?, c.get_value()?.which()?) {
2973 (type_::Void(()), value::Void(())) => {
2974 Line(format!("pub const {styled_name}: () = ();"))
2975 }
2976 (type_::Bool(()), value::Bool(b)) => {
2977 Line(format!("pub const {styled_name}: bool = {b};"))
2978 }
2979 (type_::Int8(()), value::Int8(i)) => {
2980 Line(format!("pub const {styled_name}: i8 = {i};"))
2981 }
2982 (type_::Int16(()), value::Int16(i)) => {
2983 Line(format!("pub const {styled_name}: i16 = {i};"))
2984 }
2985 (type_::Int32(()), value::Int32(i)) => {
2986 Line(format!("pub const {styled_name}: i32 = {i};"))
2987 }
2988 (type_::Int64(()), value::Int64(i)) => {
2989 Line(format!("pub const {styled_name}: i64 = {i};"))
2990 }
2991 (type_::Uint8(()), value::Uint8(i)) => {
2992 Line(format!("pub const {styled_name}: u8 = {i};"))
2993 }
2994 (type_::Uint16(()), value::Uint16(i)) => {
2995 Line(format!("pub const {styled_name}: u16 = {i};"))
2996 }
2997 (type_::Uint32(()), value::Uint32(i)) => {
2998 Line(format!("pub const {styled_name}: u32 = {i};"))
2999 }
3000 (type_::Uint64(()), value::Uint64(i)) => {
3001 Line(format!("pub const {styled_name}: u64 = {i};"))
3002 }
3003
3004 (type_::Float32(()), value::Float32(f)) => {
3005 let literal = match f.classify() {
3006 std::num::FpCategory::Nan => "f32::NAN".into(),
3007 std::num::FpCategory::Infinite => {
3008 if f.is_sign_positive() {
3009 "f32::INFINITY".into()
3010 } else {
3011 "f32::NEG_INFINITY".into()
3012 }
3013 }
3014 _ => format!("{f:e}"),
3015 };
3016 Line(format!("pub const {styled_name}: f32 = {literal};"))
3017 }
3018
3019 (type_::Float64(()), value::Float64(f)) => {
3020 let literal = match f.classify() {
3021 std::num::FpCategory::Nan => "f64::NAN".into(),
3022 std::num::FpCategory::Infinite => {
3023 if f.is_sign_positive() {
3024 "f64::INFINITY".into()
3025 } else {
3026 "f64::NEG_INFINITY".into()
3027 }
3028 }
3029 _ => format!("{f:e}"),
3030 };
3031 Line(format!("pub const {styled_name}: f64 = {literal};"))
3032 }
3033
3034 (type_::Enum(e), value::Enum(v)) => {
3035 if let Some(node) = ctx.node_map.get(&e.get_type_id()) {
3036 match node.which()? {
3037 node::Enum(e) => {
3038 let enumerants = e.get_enumerants()?;
3039 if let Some(enumerant) = enumerants.try_get(u32::from(v)) {
3040 let variant =
3041 capitalize_first_letter(get_enumerant_name(enumerant)?);
3042 let type_string = typ.type_string(ctx, Leaf::Owned)?;
3043 Line(format!(
3044 "pub const {}: {} = {}::{};",
3045 styled_name, &type_string, &type_string, variant
3046 ))
3047 } else {
3048 return Err(Error::failed(format!(
3049 "enumerant out of range: {v}"
3050 )));
3051 }
3052 }
3053 _ => {
3054 return Err(Error::failed(format!(
3055 "bad enum type ID: {}",
3056 e.get_type_id()
3057 )));
3058 }
3059 }
3060 } else {
3061 return Err(Error::failed(format!(
3062 "bad enum type ID: {}",
3063 e.get_type_id()
3064 )));
3065 }
3066 }
3067
3068 (type_::Text(()), value::Text(t)) => Line(format!(
3069 "pub const {styled_name}: &str = {:?};",
3070 t?.to_str()?
3071 )),
3072 (type_::Data(()), value::Data(d)) => {
3073 Line(format!("pub const {styled_name}: &[u8] = &{:?};", d?))
3074 }
3075
3076 (type_::List(_), value::List(v)) => {
3077 generate_pointer_constant(ctx, &styled_name, typ, v)?
3078 }
3079 (type_::Struct(_), value::Struct(v)) => {
3080 generate_pointer_constant(ctx, &styled_name, typ, v)?
3081 }
3082
3083 (type_::Interface(_t), value::Interface(())) => {
3084 return Err(Error::unimplemented("interface constants".to_string()));
3085 }
3086 (type_::AnyPointer(_), value::AnyPointer(_pr)) => {
3087 return Err(Error::unimplemented("anypointer constants".to_string()));
3088 }
3089
3090 _ => {
3091 return Err(Error::failed("type does not match value".to_string()));
3092 }
3093 };
3094
3095 output.push(formatted_text);
3096 }
3097
3098 node::Annotation(annotation_reader) => {
3099 let is_generic = node_reader.get_is_generic();
3100 let params = node_reader.parameters_texts(ctx);
3101 let last_name = ctx.get_last_name(node_id)?;
3102 let mut interior = vec![];
3103 interior.push(Line(format!("pub const ID: u64 = 0x{node_id:x};")));
3104
3105 let ty = annotation_reader.get_type()?;
3106 if !is_generic {
3107 interior.push(Line(fmt!(ctx,
3108 "pub fn get_type() -> {capnp}::introspect::Type {{ <{} as {capnp}::introspect::Introspect>::introspect() }}", ty.type_string(ctx, Leaf::Owned)?)));
3109 } else {
3110 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)?)));
3111 }
3112 output.push(Branch(vec![
3113 Line(format!("pub mod {last_name} {{")),
3114 indent(interior),
3115 Line("}".into()),
3116 ]));
3117 }
3118 }
3119
3120 Ok(Branch(output))
3121}
3122
3123