Skip to main content

sim_codec_bridge/
ownership.rs

1use sim_kernel::{Error, Result};
2
3use crate::{BridgeBook, BridgePacket, decode_bridge_text, encode_bridge_text};
4
5/// A rendered byte span owned by one BRIDGE packet component.
6#[derive(Clone, Debug, PartialEq, Eq)]
7pub enum OwnedSpan {
8    /// Structural packet syntax.
9    Structural(String),
10    /// Fluent frame sentence text.
11    Frame {
12        /// Frame part id.
13        id: String,
14        /// Rendered text.
15        text: String,
16    },
17    /// Registered part line.
18    Part {
19        /// Part id.
20        id: String,
21        /// Part kind.
22        kind: String,
23        /// Rendered text.
24        text: String,
25    },
26    /// Fenced data block.
27    Fence {
28        /// Fence id.
29        id: String,
30        /// Rendered text.
31        text: String,
32    },
33}
34
35impl OwnedSpan {
36    /// Returns the rendered text owned by this span.
37    pub fn rendered_text(&self) -> &str {
38        match self {
39            Self::Structural(text) => text,
40            Self::Frame { text, .. } | Self::Part { text, .. } | Self::Fence { text, .. } => text,
41        }
42    }
43}
44
45/// Asserts that encoding then decoding reproduces the same packet.
46pub fn assert_roundtrip(packet: &BridgePacket, book: &BridgeBook) -> Result<()> {
47    let text = encode_bridge_text(packet, book)?;
48    let decoded = decode_bridge_text(&text, book)?;
49    if decoded != *packet {
50        return Err(Error::Eval("bridge roundtrip mismatch".to_owned()));
51    }
52    Ok(())
53}
54
55/// Asserts that spans exactly cover the full rendered face in order.
56pub fn assert_total_ownership(rendered: &str, spans: &[OwnedSpan]) -> Result<()> {
57    let mut cursor = 0usize;
58    for span in spans {
59        let text = span.rendered_text();
60        if !rendered[cursor..].starts_with(text) {
61            return Err(Error::Eval(format!(
62                "bridge render has unowned bytes at {cursor}"
63            )));
64        }
65        cursor += text.len();
66    }
67    if cursor != rendered.len() {
68        return Err(Error::Eval(
69            "bridge render has unowned trailing bytes".to_owned(),
70        ));
71    }
72    Ok(())
73}