Skip to main content

vexil_codegen_rust/
newtype.rs

1use std::collections::HashSet;
2
3use vexil_lang::ir::{FieldEncoding, NewtypeDef, TypeId, TypeRegistry};
4
5use crate::annotations::emit_type_annotations;
6use crate::emit::CodeWriter;
7use crate::message::{emit_read, emit_write};
8use crate::types::rust_type;
9
10/// Emit a newtype struct with `Pack` and `Unpack` implementations.
11///
12/// The struct wraps `inner_type` as its public field.  Encoding and decoding
13/// delegate entirely to `terminal_type` (the fully unwrapped primitive or
14/// named type at the base of the newtype chain) using a default `FieldEncoding`.
15pub fn emit_newtype(
16    w: &mut CodeWriter,
17    nt: &NewtypeDef,
18    registry: &TypeRegistry,
19    needs_box: &HashSet<(TypeId, usize)>,
20) {
21    let name = nt.name.as_str();
22
23    // ── Type-level annotations (doc, since, deprecated, non_exhaustive) ─────
24    emit_type_annotations(w, &nt.annotations);
25
26    // ── Struct definition ────────────────────────────────────────────────────
27    w.line("#[derive(Debug, Clone, PartialEq)]");
28    let inner_rust = rust_type(&nt.inner_type, registry, needs_box, None);
29    w.line(&format!("pub struct {name}(pub {inner_rust});"));
30    w.blank();
31
32    // ── Pack impl ────────────────────────────────────────────────────────────
33    w.open_block(&format!("impl vexil_runtime::Pack for {name}"));
34    w.open_block(
35        "fn pack(&self, w: &mut vexil_runtime::BitWriter) -> Result<(), vexil_runtime::EncodeError>",
36    );
37    let enc = FieldEncoding::default_encoding();
38    emit_write(w, "self.0", &nt.terminal_type, &enc, registry, name);
39    w.line("w.flush_to_byte_boundary();");
40    w.line("Ok(())");
41    w.close_block();
42    w.close_block();
43    w.blank();
44
45    // ── Unpack impl ──────────────────────────────────────────────────────────
46    w.open_block(&format!("impl vexil_runtime::Unpack for {name}"));
47    w.open_block(
48        "fn unpack(r: &mut vexil_runtime::BitReader<'_>) -> Result<Self, vexil_runtime::DecodeError>",
49    );
50    emit_read(w, "value", &nt.terminal_type, &enc, registry, name);
51    w.line("r.flush_to_byte_boundary();");
52    w.line("Ok(Self(value))");
53    w.close_block();
54    w.close_block();
55    w.blank();
56}