Skip to main content

sim_lib_stream_core/
citizen.rs

1//! Object/class citizenship for stream packets in the runtime.
2//!
3//! [`StreamPacketDescriptor`] is the runtime citizen wrapping a
4//! [`StreamPacket`]: it derives `Citizen` under the `stream/Packet` class so a
5//! packet can live as a first-class object, and stores the packet in its
6//! encoded [`Expr`] form while validating that the expr decodes back to a
7//! packet. [`stream_packet_class_symbol`] returns the class symbol that
8//! identifies these citizens.
9
10use sim_citizen_derive::Citizen;
11use sim_kernel::{Expr, Result, Symbol};
12
13use crate::{DataPacket, StreamPacket};
14
15/// Runtime citizen wrapping a [`StreamPacket`] under the `stream/Packet` class.
16///
17/// The packet is held in its encoded [`Expr`] form; construction validates that
18/// the expr round-trips to a [`StreamPacket`].
19#[derive(Clone, Debug, PartialEq, Citizen)]
20#[citizen(symbol = "stream/Packet", version = 1)]
21pub struct StreamPacketDescriptor {
22    #[citizen(with = "packet_expr")]
23    packet: Expr,
24}
25
26impl StreamPacketDescriptor {
27    /// Wraps a [`StreamPacket`], storing its encoded [`Expr`] form.
28    pub fn new(packet: StreamPacket) -> Self {
29        Self {
30            packet: packet.to_expr(),
31        }
32    }
33
34    /// Wraps an already-encoded packet [`Expr`], validating that it decodes to a
35    /// [`StreamPacket`].
36    ///
37    /// Returns an error if the expression is not a valid encoded stream packet.
38    pub fn from_expr(expr: Expr) -> Result<Self> {
39        packet_expr::decode(&expr)?;
40        Ok(Self { packet: expr })
41    }
42
43    /// Decodes and returns the wrapped [`StreamPacket`].
44    ///
45    /// Returns an error if the stored expression no longer decodes to a packet.
46    pub fn packet(&self) -> Result<StreamPacket> {
47        StreamPacket::try_from(self.packet.clone())
48    }
49
50    /// Returns the wrapped packet in its encoded [`Expr`] form.
51    pub fn as_expr(&self) -> &Expr {
52        &self.packet
53    }
54}
55
56impl Default for StreamPacketDescriptor {
57    fn default() -> Self {
58        Self::new(StreamPacket::Data(DataPacket::new(
59            Symbol::qualified("stream/data", "citizen-fixture"),
60            Expr::String("packet".to_owned()),
61        )))
62    }
63}
64
65/// Returns the `stream/Packet` class symbol that identifies stream-packet
66/// citizens.
67pub fn stream_packet_class_symbol() -> Symbol {
68    Symbol::qualified("stream", "Packet")
69}
70
71pub(crate) mod packet_expr {
72    use sim_kernel::{Expr, Result};
73
74    use crate::StreamPacket;
75
76    pub fn encode(expr: &Expr) -> Expr {
77        expr.clone()
78    }
79
80    pub fn decode(expr: &Expr) -> Result<Expr> {
81        StreamPacket::try_from(expr.clone())?;
82        Ok(expr.clone())
83    }
84}