1#![cfg_attr(not(feature = "std"), no_std)]
4
5extern crate alloc;
6
7use alloc::string::String;
8use core::fmt::Display;
9
10#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Default)]
12pub struct QosProfile {
13 pub reliability: QosReliability,
14 pub durability: QosDurability,
15 pub history: QosHistory,
16}
17
18impl QosProfile {
19 pub fn encode(&self) -> String {
22 use alloc::format;
23 let default_qos = Self::default();
24
25 let reliability = if self.reliability != default_qos.reliability {
27 match self.reliability {
28 QosReliability::Reliable => "1",
29 QosReliability::BestEffort => "2",
30 }
31 } else {
32 ""
33 };
34
35 let durability = if self.durability != default_qos.durability {
37 match self.durability {
38 QosDurability::TransientLocal => "1",
39 QosDurability::Volatile => "2",
40 }
41 } else {
42 ""
43 };
44
45 let history = match self.history {
48 QosHistory::KeepLast(depth) => {
49 if self.history != default_qos.history {
50 format!("1,{}", depth)
51 } else {
52 format!(",{}", depth)
53 }
54 }
55 QosHistory::KeepAll => "2,".to_string(),
56 };
57
58 let deadline = ",";
60 let lifespan = ",";
61 let liveliness = ",,";
62
63 format!(
64 "{}:{}:{}:{}:{}:{}",
65 reliability, durability, history, deadline, lifespan, liveliness
66 )
67 }
68
69 pub fn decode(s: &str) -> Result<Self, QosDecodeError> {
71 let fields: alloc::vec::Vec<&str> = s.split(':').collect();
72 if fields.len() < 3 {
73 return Err(QosDecodeError::InvalidFormat);
74 }
75
76 let default_qos = Self::default();
77
78 let reliability = match fields[0] {
80 "" => default_qos.reliability,
81 "1" => QosReliability::Reliable,
82 "2" => QosReliability::BestEffort,
83 _ => return Err(QosDecodeError::InvalidReliability),
84 };
85
86 let durability = match fields[1] {
88 "" => default_qos.durability,
89 "1" => QosDurability::TransientLocal,
90 "2" => QosDurability::Volatile,
91 _ => return Err(QosDecodeError::InvalidDurability),
92 };
93
94 let history_parts: alloc::vec::Vec<&str> = fields[2].split(',').collect();
96 if history_parts.len() < 2 {
97 return Err(QosDecodeError::InvalidHistory);
98 }
99
100 let history = match history_parts[0] {
101 "" | "1" => {
102 let depth = history_parts[1]
104 .parse::<usize>()
105 .map_err(|_| QosDecodeError::InvalidHistory)?;
106 QosHistory::KeepLast(depth)
107 }
108 "2" => QosHistory::KeepAll,
109 _ => return Err(QosDecodeError::InvalidHistory),
110 };
111
112 Ok(QosProfile {
113 reliability,
114 durability,
115 history,
116 })
117 }
118}
119
120#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Default)]
124#[repr(u8)]
125pub enum QosReliability {
126 BestEffort = 0,
127 #[default]
128 Reliable = 1,
129}
130
131#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Default)]
133#[repr(u8)]
134pub enum QosDurability {
135 #[default]
136 Volatile = 0,
137 TransientLocal = 1,
138}
139
140#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
142pub enum QosHistory {
143 KeepLast(usize),
144 KeepAll,
145}
146
147impl Default for QosHistory {
148 fn default() -> Self {
149 QosHistory::KeepLast(10)
150 }
151}
152
153impl QosHistory {
154 pub fn from_depth(depth: usize) -> Self {
155 QosHistory::KeepLast(depth)
156 }
157
158 pub fn depth(&self) -> usize {
159 match self {
160 QosHistory::KeepLast(d) => *d,
161 QosHistory::KeepAll => 0,
162 }
163 }
164}
165
166#[derive(Debug, Clone, Copy, PartialEq, Eq)]
168pub enum QosDecodeError {
169 InvalidFormat,
170 InvalidReliability,
171 InvalidDurability,
172 InvalidHistory,
173}
174
175impl Display for QosDecodeError {
176 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
177 match self {
178 QosDecodeError::InvalidFormat => write!(f, "Invalid QoS format"),
179 QosDecodeError::InvalidReliability => write!(f, "Invalid reliability value"),
180 QosDecodeError::InvalidDurability => write!(f, "Invalid durability value"),
181 QosDecodeError::InvalidHistory => write!(f, "Invalid history value"),
182 }
183 }
184}