1use ecow::EcoString;
2
3use crate::{
4 ast::{
5 Constant, Publicity, SrcSpan, TypedConstant, TypedConstantBitArraySegment,
6 TypedConstantBitArraySegmentOption,
7 },
8 reference::{Reference, ReferenceKind, ReferenceMap},
9 schema_capnp::{self as schema, *},
10 type_::{
11 self, AccessorsMap, Deprecation, FieldMap, Opaque, RecordAccessor, Type,
12 TypeAliasConstructor, TypeConstructor, TypeValueConstructor, TypeVar,
13 TypeVariantConstructors, ValueConstructor, ValueConstructorVariant,
14 expression::{Implementations, Purity},
15 },
16};
17use std::{collections::HashMap, ops::Deref, sync::Arc};
18
19#[derive(Debug)]
20pub struct ModuleEncoder<'a> {
21 data: &'a type_::ModuleInterface,
22 next_type_var_id: u64,
23 type_var_id_map: HashMap<u64, u64>,
24}
25
26impl<'a> ModuleEncoder<'a> {
27 pub fn new(data: &'a type_::ModuleInterface) -> Self {
28 Self {
29 data,
30 next_type_var_id: 0,
31 type_var_id_map: HashMap::new(),
32 }
33 }
34
35 pub fn encode(mut self) -> crate::Result<Vec<u8>> {
36 let span = tracing::info_span!("metadata");
37 let _enter = span.enter();
38 let mut buffer = Vec::new();
39
40 let mut message = capnp::message::Builder::new_default();
41
42 let mut module = message.init_root::<module::Builder<'_>>();
43 module.set_name(&self.data.name);
44 module.set_package(&self.data.package);
45 module.set_src_path(self.data.src_path.as_str());
46 module.set_is_internal(self.data.is_internal);
47 module.set_contains_echo(self.data.contains_echo);
48 self.set_module_types(&mut module);
49 self.set_module_values(&mut module);
50 self.set_module_accessors(&mut module);
51 self.set_module_types_constructors(&mut module);
52 self.set_line_numbers(&mut module);
53 self.set_version(&mut module);
54 self.set_module_documentation(&mut module);
55 self.set_module_type_aliases(&mut module);
56 self.set_module_references(&mut module);
57
58 capnp::serialize_packed::write_message(&mut buffer, &message).expect("capnp encode");
59 Ok(buffer)
60 }
61
62 fn set_line_numbers(&mut self, module: &mut module::Builder<'_>) {
63 let mut line_numbers = module.reborrow().init_line_numbers();
64 line_numbers.set_length(self.data.line_numbers.length);
65
66 let mut line_starts = line_numbers
67 .reborrow()
68 .init_line_starts(self.data.line_numbers.line_starts.len() as u32);
69 for (i, l) in self.data.line_numbers.line_starts.iter().enumerate() {
70 line_starts.reborrow().set(i as u32, *l);
71 }
72
73 let mut mapping = line_numbers.init_mapping(self.data.line_numbers.mapping.len() as u32);
74 for (i, (byte_index, character)) in self.data.line_numbers.mapping.iter().enumerate() {
75 let mut builder = mapping.reborrow().get(i as u32);
76 builder.set_byte_index(*byte_index as u64);
77 builder.set_length_utf8(character.length_utf8);
78 builder.set_length_utf16(character.length_utf16);
79 }
80 }
81
82 fn set_module_documentation(&mut self, module: &mut module::Builder<'_>) {
83 let mut documentation = module
84 .reborrow()
85 .init_documentation(self.data.documentation.len() as u32);
86 for (i, documentation_part) in self.data.documentation.iter().enumerate() {
87 documentation.set(i as u32, documentation_part.as_str());
88 }
89 }
90
91 fn set_module_accessors(&mut self, module: &mut module::Builder<'_>) {
92 let mut builder = module
93 .reborrow()
94 .init_accessors(self.data.accessors.len() as u32);
95 for (i, (key, map)) in self.data.accessors.iter().enumerate() {
96 let mut property = builder.reborrow().get(i as u32);
97 property.set_key(key);
98 self.build_accessors_map(property.init_value(), map);
99 }
100 }
101
102 fn build_accessors_map(
103 &mut self,
104 mut builder: accessors_map::Builder<'_>,
105 accessors: &AccessorsMap,
106 ) {
107 self.build_type(builder.reborrow().init_type(), &accessors.type_);
108 self.build_publicity(builder.reborrow().init_publicity(), accessors.publicity);
109 let mut accessors_builder = builder
110 .reborrow()
111 .init_shared_accessors(accessors.shared_accessors.len() as u32);
112 for (i, (name, accessor)) in accessors.shared_accessors.iter().enumerate() {
113 let mut property = accessors_builder.reborrow().get(i as u32);
114 property.set_key(name);
115 self.build_record_accessor(property.init_value(), accessor)
116 }
117
118 let mut builder = builder
119 .init_variant_specific_accessors(accessors.variant_specific_accessors.len() as u32);
120 for (i, map) in accessors.variant_specific_accessors.iter().enumerate() {
121 self.build_constructor_accessors(builder.reborrow().get(i as u32), map);
122 }
123 }
124
125 fn build_constructor_accessors(
126 &mut self,
127 builder: variant_specific_accessors::Builder<'_>,
128 accessors: &HashMap<EcoString, RecordAccessor>,
129 ) {
130 let mut builder = builder.init_accessors(accessors.len() as u32);
131 for (i, (name, accessor)) in accessors.iter().enumerate() {
132 let mut property = builder.reborrow().get(i as u32);
133 property.set_key(name);
134 self.build_record_accessor(property.init_value(), accessor)
135 }
136 }
137
138 fn build_record_accessor(
139 &mut self,
140 mut builder: record_accessor::Builder<'_>,
141 accessor: &RecordAccessor,
142 ) {
143 self.build_type(builder.reborrow().init_type(), &accessor.type_);
144 builder.reborrow().set_label(&accessor.label);
145 builder.set_index(accessor.index as u16);
146 }
147
148 fn set_module_types(&mut self, module: &mut module::Builder<'_>) {
149 let mut types = module.reborrow().init_types(self.data.types.len() as u32);
150 for (i, (name, type_)) in self.data.types.iter().enumerate() {
151 let mut property = types.reborrow().get(i as u32);
152 property.set_key(name);
153 self.build_type_constructor(property.init_value(), type_)
154 }
155 }
156
157 fn set_module_type_aliases(&mut self, module: &mut module::Builder<'_>) {
158 let mut types = module
159 .reborrow()
160 .init_type_aliases(self.data.type_aliases.len() as u32);
161 for (i, (name, alias)) in self.data.type_aliases.iter().enumerate() {
162 let mut property = types.reborrow().get(i as u32);
163 property.set_key(name);
164 self.build_type_alias_constructor(property.init_value(), alias)
165 }
166 }
167
168 fn set_module_types_constructors(&mut self, module: &mut module::Builder<'_>) {
169 let mut types_constructors = module
170 .reborrow()
171 .init_types_constructors(self.data.types_value_constructors.len() as u32);
172 for (i, (name, data)) in self.data.types_value_constructors.iter().enumerate() {
173 let mut property = types_constructors.reborrow().get(i as u32);
174 property.set_key(name);
175 self.build_type_variant_constructors(property.init_value(), data)
176 }
177 }
178
179 fn build_type_variant_constructors(
180 &mut self,
181 mut builder: types_variant_constructors::Builder<'_>,
182 data: &TypeVariantConstructors,
183 ) {
184 match data.opaque {
185 Opaque::Opaque => builder.set_opaque(true),
186 Opaque::NotOpaque => builder.set_opaque(false),
187 }
188 {
189 let mut builder = builder
190 .reborrow()
191 .init_type_parameters_ids(data.type_parameters_ids.len() as u32);
192 for (i, id) in data.type_parameters_ids.iter().enumerate() {
193 let id = self.get_or_insert_type_var_id(*id);
194 builder.set(i as u32, id as u16);
195 }
196 }
197 let mut builder = builder.init_variants(data.variants.len() as u32);
198 for (i, constructor) in data.variants.iter().enumerate() {
199 self.build_type_value_constructor(builder.reborrow().get(i as u32), constructor);
200 }
201 }
202
203 fn set_module_values(&mut self, module: &mut module::Builder<'_>) {
204 let mut values = module.reborrow().init_values(self.data.values.len() as u32);
205 for (i, (name, value)) in self.data.values.iter().enumerate() {
206 let mut property = values.reborrow().get(i as u32);
207 property.set_key(name);
208 self.build_value_constructor(property.init_value(), value)
209 }
210 }
211
212 fn set_module_references(&mut self, module: &mut module::Builder<'_>) {
213 let references = &self.data.references;
214 let mut builder = module.reborrow().init_references();
215 let mut imported_modules = builder
216 .reborrow()
217 .init_imported_modules(references.imported_modules.len() as u32);
218 for (i, module) in references.imported_modules.iter().enumerate() {
219 imported_modules.set(i as u32, module);
220 }
221
222 let value_references = builder
223 .reborrow()
224 .init_value_references(references.value_references.len() as u32);
225 self.build_reference_map(value_references, &references.value_references);
226 let type_references = builder
227 .reborrow()
228 .init_type_references(references.type_references.len() as u32);
229 self.build_reference_map(type_references, &references.type_references);
230 }
231
232 fn build_reference_map(
233 &mut self,
234 mut builder: capnp::struct_list::Builder<'_, reference_map::Owned>,
235 map: &ReferenceMap,
236 ) {
237 for (i, ((module, name), references)) in map.iter().enumerate() {
238 let mut builder = builder.reborrow().get(i as u32);
239 builder.set_module(module);
240 builder.set_name(name);
241 let mut references_builder =
242 builder.reborrow().init_references(references.len() as u32);
243 for (i, reference) in references.iter().enumerate() {
244 let builder = references_builder.reborrow().get(i as u32);
245 self.build_reference(builder, reference);
246 }
247 }
248 }
249
250 fn build_reference(&mut self, mut builder: reference::Builder<'_>, reference: &Reference) {
251 let mut kind = builder.reborrow().init_kind();
252 match reference.kind {
253 ReferenceKind::Qualified => kind.set_qualified(()),
254 ReferenceKind::Unqualified => kind.set_unqualified(()),
255 ReferenceKind::Import => kind.set_import(()),
256 ReferenceKind::Definition => kind.set_definition(()),
257 ReferenceKind::Alias => kind.set_alias(()),
258 }
259 self.build_src_span(builder.init_location(), reference.location);
260 }
261
262 fn set_version(&mut self, module: &mut module::Builder<'_>) {
263 let mut version = module.reborrow().init_required_version();
264 version.set_major(self.data.minimum_required_version.major);
265 version.set_minor(self.data.minimum_required_version.minor);
266 version.set_patch(self.data.minimum_required_version.patch);
267 }
268
269 fn build_type_constructor(
270 &mut self,
271 mut builder: type_constructor::Builder<'_>,
272 constructor: &TypeConstructor,
273 ) {
274 builder.set_module(&constructor.module);
275 builder.set_deprecated(match &constructor.deprecation {
276 Deprecation::NotDeprecated => "",
277 Deprecation::Deprecated { message } => message,
278 });
279 self.build_publicity(builder.reborrow().init_publicity(), constructor.publicity);
280 let type_builder = builder.reborrow().init_type();
281 self.build_type(type_builder, &constructor.type_);
282 self.build_types(
283 builder
284 .reborrow()
285 .init_parameters(constructor.parameters.len() as u32),
286 &constructor.parameters,
287 );
288 self.build_src_span(builder.reborrow().init_origin(), constructor.origin);
289 builder.set_documentation(
290 constructor
291 .documentation
292 .as_ref()
293 .map(EcoString::as_str)
294 .unwrap_or_default(),
295 );
296 }
297
298 fn build_type_alias_constructor(
299 &mut self,
300 mut builder: type_alias_constructor::Builder<'_>,
301 constructor: &TypeAliasConstructor,
302 ) {
303 builder.set_module(&constructor.module);
304 builder.set_deprecation(match &constructor.deprecation {
305 Deprecation::NotDeprecated => "",
306 Deprecation::Deprecated { message } => message,
307 });
308 self.build_publicity(builder.reborrow().init_publicity(), constructor.publicity);
309 let type_builder = builder.reborrow().init_type();
310 self.build_type(type_builder, &constructor.type_);
311 self.build_src_span(builder.reborrow().init_origin(), constructor.origin);
312 builder.set_documentation(constructor.documentation.as_deref().unwrap_or_default());
313 builder.set_arity(constructor.arity as u32)
314 }
315
316 fn build_type_value_constructor(
317 &mut self,
318 mut builder: type_value_constructor::Builder<'_>,
319 constructor: &TypeValueConstructor,
320 ) {
321 builder.set_name(&constructor.name);
322 builder.set_documentation(constructor.documentation.as_deref().unwrap_or_default());
323 let mut builder = builder.init_parameters(constructor.parameters.len() as u32);
324 for (i, parameter) in constructor.parameters.iter().enumerate() {
325 self.build_type_value_constructor_parameter(
326 builder.reborrow().get(i as u32),
327 parameter,
328 );
329 }
330 }
331
332 fn build_type_value_constructor_parameter(
333 &mut self,
334 mut builder: type_value_constructor_parameter::Builder<'_>,
335 parameter: &type_::TypeValueConstructorField,
336 ) {
337 self.build_type(builder.reborrow().init_type(), parameter.type_.as_ref());
338 builder.set_label(parameter.label.as_deref().unwrap_or_default());
339 }
340
341 fn build_value_constructor(
342 &mut self,
343 mut builder: value_constructor::Builder<'_>,
344 constructor: &ValueConstructor,
345 ) {
346 builder.set_deprecated(match &constructor.deprecation {
347 Deprecation::NotDeprecated => "",
348 Deprecation::Deprecated { message } => message,
349 });
350
351 self.build_publicity(builder.reborrow().init_publicity(), constructor.publicity);
352 self.build_type(builder.reborrow().init_type(), &constructor.type_);
353 self.build_value_constructor_variant(builder.init_variant(), &constructor.variant);
354 }
355
356 fn build_publicity(&mut self, mut builder: publicity::Builder<'_>, publicity: Publicity) {
357 match publicity {
358 Publicity::Public => builder.set_public(()),
359 Publicity::Private => builder.set_private(()),
360 Publicity::Internal {
361 attribute_location: None,
362 } => {
363 let mut builder = builder.init_internal();
364 builder.set_none(());
365 }
366 Publicity::Internal {
367 attribute_location: Some(location),
368 } => {
369 let builder = builder.init_internal();
370 let builder = builder.init_some();
371 self.build_src_span(builder, location);
372 }
373 }
374 }
375
376 fn build_src_span(&mut self, mut builder: src_span::Builder<'_>, span: SrcSpan) {
377 builder.set_start(span.start);
378 builder.set_end(span.end);
379 }
380
381 fn build_value_constructor_variant(
382 &mut self,
383 builder: value_constructor_variant::Builder<'_>,
384 constructor: &ValueConstructorVariant,
385 ) {
386 match constructor {
387 ValueConstructorVariant::LocalVariable { .. } => {
388 panic!("Unexpected local variable value constructor in module interface",)
389 }
390
391 ValueConstructorVariant::LocalConstant { .. } => {
392 panic!("Unexpected local constant value constructor in module interface",)
393 }
394
395 ValueConstructorVariant::ModuleConstant {
396 literal,
397 location,
398 module,
399 documentation: doc,
400 implementations,
401 name,
402 } => {
403 let mut builder = builder.init_module_constant();
404 builder.set_documentation(doc.as_ref().map(EcoString::as_str).unwrap_or_default());
405 self.build_src_span(builder.reborrow().init_location(), *location);
406 self.build_constant(builder.reborrow().init_literal(), literal);
407 builder.reborrow().set_module(module);
408 builder.reborrow().set_name(name);
409 self.build_implementations(builder.init_implementations(), *implementations)
410 }
411
412 ValueConstructorVariant::Record {
413 name,
414 field_map,
415 arity,
416 location,
417 module,
418 variants_count: constructors_count,
419 variant_index: constructor_index,
420 documentation: doc,
421 } => {
422 let mut builder = builder.init_record();
423 builder.set_name(name);
424 builder.set_module(module);
425 builder.set_arity(*arity);
426 builder.set_documentation(doc.as_ref().map(EcoString::as_str).unwrap_or_default());
427 builder.set_constructors_count(*constructors_count);
428 builder.set_constructor_index(*constructor_index);
429 self.build_optional_field_map(builder.reborrow().init_field_map(), field_map);
430 self.build_src_span(builder.init_location(), *location);
431 }
432
433 ValueConstructorVariant::ModuleFn {
434 arity,
435 field_map,
436 module,
437 name,
438 location,
439 documentation: doc,
440 implementations,
441 external_erlang,
442 external_javascript,
443 purity,
444 } => {
445 let mut builder = builder.init_module_fn();
446 builder.set_name(name);
447 builder.set_module(module);
448 builder.set_arity(*arity as u16);
449 builder.set_documentation(doc.as_ref().map(EcoString::as_str).unwrap_or_default());
450
451 let mut purity_builder = builder.reborrow().init_purity();
452 match purity {
453 Purity::Pure => purity_builder.set_pure(()),
454 Purity::TrustedPure => purity_builder.set_trusted_pure(()),
455 Purity::Impure => purity_builder.set_impure(()),
456 Purity::Unknown => purity_builder.set_unknown(()),
457 }
458
459 self.build_external(builder.reborrow().init_external_erlang(), external_erlang);
460 self.build_external(
461 builder.reborrow().init_external_javascript(),
462 external_javascript,
463 );
464 self.build_optional_field_map(builder.reborrow().init_field_map(), field_map);
465 self.build_src_span(builder.reborrow().init_location(), *location);
466 self.build_implementations(builder.init_implementations(), *implementations);
467 }
468 }
469 }
470
471 fn build_optional_field_map(
472 &mut self,
473 mut builder: option::Builder<'_, field_map::Owned>,
474 field_map: &Option<FieldMap>,
475 ) {
476 match field_map {
477 Some(field_map) => self.build_field_map(builder.init_some(), field_map),
478 None => builder.set_none(()),
479 };
480 }
481
482 fn build_field_map(&mut self, mut builder: field_map::Builder<'_>, field_map: &FieldMap) {
483 builder.set_arity(field_map.arity);
484 let mut builder = builder.init_fields(field_map.fields.len() as u32);
485 for (i, (name, &position)) in field_map.fields.iter().enumerate() {
486 let mut field = builder.reborrow().get(i as u32);
487 field.set_key(name);
488 field.init_value().set_value(position);
489 }
490 }
491
492 fn build_constant(&mut self, mut builder: constant::Builder<'_>, constant: &TypedConstant) {
493 match constant {
494 Constant::Int { value, .. } => builder.set_int(value),
495 Constant::Float { value, .. } => builder.set_float(value),
496 Constant::String { value, .. } => builder.set_string(value),
497
498 Constant::Tuple { elements, .. } => {
499 self.build_constants(builder.init_tuple(elements.len() as u32), elements)
500 }
501
502 Constant::List {
503 elements, type_, ..
504 } => {
505 let mut builder = builder.init_list();
506 self.build_constants(
507 builder.reborrow().init_elements(elements.len() as u32),
508 elements,
509 );
510 self.build_type(builder.init_type(), type_);
511 }
512
513 Constant::BitArray { segments, .. } => {
514 let mut builder = builder.init_bit_array(segments.len() as u32);
515 for (i, segment) in segments.iter().enumerate() {
516 self.build_bit_array_segment(builder.reborrow().get(i as u32), segment);
517 }
518 }
519
520 Constant::Record {
521 args, tag, type_, ..
522 } => {
523 let mut builder = builder.init_record();
524 {
525 let mut builder = builder.reborrow().init_args(args.len() as u32);
526 for (i, arg) in args.iter().enumerate() {
527 self.build_constant(builder.reborrow().get(i as u32), &arg.value);
528 }
529 }
530 builder.reborrow().set_tag(tag);
531 self.build_type(builder.reborrow().init_type(), type_);
532 }
533
534 Constant::Var {
535 module,
536 name,
537 type_,
538 constructor,
539 ..
540 } => {
541 let mut builder = builder.init_var();
542 match module {
543 Some((name, _)) => builder.set_module(name),
544 None => builder.set_module(""),
545 };
546 builder.set_name(name);
547 self.build_type(builder.reborrow().init_type(), type_);
548 self.build_value_constructor(
549 builder.reborrow().init_constructor(),
550 constructor
551 .as_ref()
552 .expect("This is guaranteed to hold a value."),
553 );
554 }
555
556 Constant::StringConcatenation { right, left, .. } => {
557 let mut builder = builder.init_string_concatenation();
558 self.build_constant(builder.reborrow().init_right(), right);
559 self.build_constant(builder.reborrow().init_left(), left);
560 }
561
562 Constant::Invalid { .. } => {
563 panic!("invalid constants should not reach code generation")
564 }
565 }
566 }
567
568 fn build_constants(
569 &mut self,
570 mut builder: capnp::struct_list::Builder<'_, constant::Owned>,
571 constant: &[TypedConstant],
572 ) {
573 for (i, constant) in constant.iter().enumerate() {
574 self.build_constant(builder.reborrow().get(i as u32), constant);
575 }
576 }
577
578 fn build_bit_array_segment(
579 &mut self,
580 mut builder: bit_array_segment::Builder<'_>,
581 segment: &TypedConstantBitArraySegment,
582 ) {
583 self.build_constant(builder.reborrow().init_value(), &segment.value);
584 {
585 let mut builder = builder
586 .reborrow()
587 .init_options(segment.options.len() as u32);
588 for (i, option) in segment.options.iter().enumerate() {
589 self.build_bit_array_segment_option(builder.reborrow().get(i as u32), option);
590 }
591 }
592 self.build_type(builder.init_type(), &segment.type_);
593 }
594
595 fn build_bit_array_segment_option(
596 &mut self,
597 mut builder: bit_array_segment_option::Builder<'_>,
598 option: &TypedConstantBitArraySegmentOption,
599 ) {
600 use crate::ast::TypedConstantBitArraySegmentOption as Opt;
601 match option {
602 Opt::Bytes { .. } => builder.set_bytes(()),
603 Opt::Int { .. } => builder.set_integer(()),
604 Opt::Float { .. } => builder.set_float(()),
605 Opt::Bits { .. } => builder.set_bits(()),
606 Opt::Utf8 { .. } => builder.set_utf8(()),
607 Opt::Utf16 { .. } => builder.set_utf16(()),
608 Opt::Utf32 { .. } => builder.set_utf32(()),
609 Opt::Utf8Codepoint { .. } => builder.set_utf8_codepoint(()),
610 Opt::Utf16Codepoint { .. } => builder.set_utf16_codepoint(()),
611 Opt::Utf32Codepoint { .. } => builder.set_utf32_codepoint(()),
612 Opt::Signed { .. } => builder.set_signed(()),
613 Opt::Unsigned { .. } => builder.set_unsigned(()),
614 Opt::Big { .. } => builder.set_big(()),
615 Opt::Little { .. } => builder.set_little(()),
616 Opt::Native { .. } => builder.set_native(()),
617
618 Opt::Size {
619 value, short_form, ..
620 } => {
621 let mut builder = builder.init_size();
622 self.build_constant(builder.reborrow().init_value(), value);
623 builder.set_short_form(*short_form);
624 }
625
626 Opt::Unit { value, .. } => {
627 let mut builder = builder.init_unit();
628 builder.set_value(*value);
629 }
630 }
631 }
632
633 fn build_type(&mut self, builder: schema::type_::Builder<'_>, type_: &Type) {
634 match type_ {
635 Type::Fn { args, return_ } => {
636 let mut fun = builder.init_fn();
637 self.build_types(fun.reborrow().init_arguments(args.len() as u32), args);
638 self.build_type(fun.init_return(), return_)
639 }
640
641 Type::Named {
642 name,
643 args,
644 module,
645 package,
646 inferred_variant,
647 ..
648 } => {
649 let mut app = builder.init_app();
650 app.set_name(name);
651 app.set_module(module);
652 app.set_package(package);
653 let mut variant_builder = app.reborrow().init_inferred_variant();
654 match inferred_variant {
655 Some(variant) => variant_builder.set_inferred(*variant),
656 None => variant_builder.set_unknown(()),
657 }
658 self.build_types(app.reborrow().init_parameters(args.len() as u32), args);
659 }
660
661 Type::Tuple { elements } => self.build_types(
662 builder.init_tuple().init_elements(elements.len() as u32),
663 elements,
664 ),
665
666 Type::Var { type_ } => match type_.borrow().deref() {
667 TypeVar::Link { type_ } => self.build_type(builder, type_),
668 TypeVar::Unbound { id, .. } | TypeVar::Generic { id } => {
669 self.build_type_var(builder.init_var(), *id)
670 }
671 },
672 }
673 }
674
675 fn build_types(
676 &mut self,
677 mut builder: capnp::struct_list::Builder<'_, schema::type_::Owned>,
678 types: &[Arc<Type>],
679 ) {
680 for (i, type_) in types.iter().enumerate() {
681 self.build_type(builder.reborrow().get(i as u32), type_);
682 }
683 }
684
685 fn build_type_var(&mut self, mut builder: schema::type_::var::Builder<'_>, id: u64) {
686 let serialised_id = self.get_or_insert_type_var_id(id);
687 builder.set_id(serialised_id);
688 }
689
690 fn get_or_insert_type_var_id(&mut self, id: u64) -> u64 {
691 match self.type_var_id_map.get(&id) {
692 Some(&id) => id,
693 None => {
694 let new_id = self.next_type_var_id;
695 self.next_type_var_id += 1;
696 let _ = self.type_var_id_map.insert(id, new_id);
697 new_id
698 }
699 }
700 }
701
702 fn build_implementations(
703 &self,
704 mut builder: implementations::Builder<'_>,
705 implementations: Implementations,
706 ) {
707 builder.set_gleam(implementations.gleam);
708 builder.set_uses_erlang_externals(implementations.uses_erlang_externals);
709 builder.set_uses_javascript_externals(implementations.uses_javascript_externals);
710 builder.set_can_run_on_erlang(implementations.can_run_on_erlang);
711 builder.set_can_run_on_javascript(implementations.can_run_on_javascript);
712 }
713
714 fn build_external(
715 &self,
716 mut builder: option::Builder<'_, external::Owned>,
717 external: &Option<(EcoString, EcoString)>,
718 ) {
719 match external {
720 None => builder.set_none(()),
721 Some((module, function)) => {
722 let mut builder = builder.init_some();
723 builder.set_module(module);
724 builder.set_function(function);
725 }
726 }
727 }
728}