ergot_base/
lib.rs

1#![doc = include_str!("../README.md")]
2#![cfg_attr(not(any(test, feature = "std")), no_std)]
3#![allow(clippy::uninlined_format_args)]
4
5pub mod address;
6pub mod interface_manager;
7pub mod nash;
8pub mod net_stack;
9pub mod socket;
10pub mod wire_frames;
11
12pub use address::Address;
13use interface_manager::InterfaceSendError;
14use log::warn;
15use nash::NameHash;
16pub use net_stack::{NetStack, NetStackSendError};
17use serde::{Deserialize, Serialize};
18
19#[cfg_attr(feature = "defmt-v1", derive(defmt::Format))]
20#[derive(Debug, Clone, Copy, PartialEq, Serialize, Deserialize)]
21pub struct FrameKind(pub u8);
22
23#[cfg_attr(feature = "defmt-v1", derive(defmt::Format))]
24#[derive(Debug, Clone, Copy, PartialEq, Serialize, Deserialize)]
25pub struct Key(pub [u8; 8]);
26
27#[derive(Debug, Clone, Copy, PartialEq, Serialize, Deserialize)]
28pub struct ProtocolError(pub u16);
29
30#[cfg_attr(feature = "defmt-v1", derive(defmt::Format))]
31#[derive(Debug, Clone)]
32pub struct AnyAllAppendix {
33    pub key: Key,
34    pub nash: Option<NameHash>,
35}
36
37#[cfg_attr(feature = "defmt-v1", derive(defmt::Format))]
38#[derive(Debug, Clone)]
39pub struct Header {
40    pub src: Address,
41    pub dst: Address,
42    pub any_all: Option<AnyAllAppendix>,
43    pub seq_no: Option<u16>,
44    pub kind: FrameKind,
45    pub ttl: u8,
46}
47
48#[derive(Debug, Clone)]
49pub struct HeaderSeq {
50    pub src: Address,
51    pub dst: Address,
52    pub any_all: Option<AnyAllAppendix>,
53    pub seq_no: u16,
54    pub kind: FrameKind,
55    pub ttl: u8,
56}
57
58impl FrameKind {
59    pub const RESERVED: Self = Self(0);
60    pub const ENDPOINT_REQ: Self = Self(1);
61    pub const ENDPOINT_RESP: Self = Self(2);
62    pub const TOPIC_MSG: Self = Self(3);
63    pub const PROTOCOL_ERROR: Self = Self(u8::MAX);
64}
65
66#[cfg(feature = "postcard-schema-v0_2")]
67impl postcard_schema::Schema for FrameKind {
68    const SCHEMA: &'static postcard_schema::schema::NamedType =
69        &postcard_schema::schema::NamedType {
70            name: "FrameKind",
71            ty: u8::SCHEMA.ty,
72        };
73}
74
75#[cfg(feature = "postcard-schema-v0_2")]
76impl postcard_schema::Schema for Key {
77    const SCHEMA: &'static postcard_schema::schema::NamedType =
78        &postcard_schema::schema::NamedType {
79            name: "Key",
80            ty: <[u8; 8]>::SCHEMA.ty,
81        };
82}
83
84impl ProtocolError {
85    pub const RESERVED: Self = Self(0);
86    // 1..11: SocketSendError
87    pub const SSE_NO_SPACE: Self = Self(1);
88    pub const SSE_DESER_FAILED: Self = Self(2);
89    pub const SSE_TYPE_MISMATCH: Self = Self(3);
90    pub const SSE_WHAT_THE_HELL: Self = Self(4);
91    // 11..21: InterfaceSendError
92    pub const ISE_DESTINATION_LOCAL: Self = Self(11);
93    pub const ISE_NO_ROUTE_TO_DEST: Self = Self(12);
94    pub const ISE_INTERFACE_FULL: Self = Self(13);
95    pub const ISE_PLACEHOLDER_OH_NO: Self = Self(14);
96    pub const ISE_ANY_PORT_MISSING_KEY: Self = Self(15);
97    pub const ISE_TTL_EXPIRED: Self = Self(16);
98    // 21..31: NetStackSendError
99    pub const NSSE_NO_ROUTE: Self = Self(21);
100    pub const NSSE_ANY_PORT_MISSING_KEY: Self = Self(22);
101    pub const NSSE_WRONG_PORT_KIND: Self = Self(23);
102    pub const NSSE_ANY_PORT_NOT_UNIQUE: Self = Self(24);
103    pub const NSSE_ALL_PORT_MISSING_KEY: Self = Self(25);
104}
105
106impl Header {
107    #[inline]
108    pub fn with_seq(self, seq_no: u16) -> HeaderSeq {
109        let Self {
110            src,
111            dst,
112            any_all,
113            seq_no: _,
114            kind,
115            ttl,
116        } = self;
117        HeaderSeq {
118            src,
119            dst,
120            any_all,
121            seq_no,
122            kind,
123            ttl,
124        }
125    }
126
127    #[inline]
128    pub fn to_headerseq_or_with_seq<F: FnOnce() -> u16>(&self, f: F) -> HeaderSeq {
129        HeaderSeq {
130            src: self.src,
131            dst: self.dst,
132            any_all: self.any_all.clone(),
133            seq_no: self.seq_no.unwrap_or_else(f),
134            kind: self.kind,
135            ttl: self.ttl,
136        }
137    }
138
139    #[inline]
140    pub fn decrement_ttl(&mut self) -> Result<(), InterfaceSendError> {
141        self.ttl = self.ttl.checked_sub(1).ok_or_else(|| {
142            warn!("Header TTL expired: {self:?}");
143            InterfaceSendError::TtlExpired
144        })?;
145        Ok(())
146    }
147}
148
149impl From<HeaderSeq> for Header {
150    fn from(val: HeaderSeq) -> Self {
151        Self {
152            src: val.src,
153            dst: val.dst,
154            any_all: val.any_all.clone(),
155            seq_no: Some(val.seq_no),
156            kind: val.kind,
157            ttl: val.ttl,
158        }
159    }
160}
161
162pub const DEFAULT_TTL: u8 = 16;
163
164/// Exports of used crate versions
165pub mod exports {
166    pub use bbq2;
167    pub use mutex;
168}