1#![no_std]
6#![deny(missing_docs)]
7
8pub mod prelude;
10
11use embedded_hal::serial::Write;
12use heapless::LinearMap;
13use nb;
14
15pub struct OnlyFront(pub bool);
17
18#[derive(Clone, Copy, Debug, PartialEq, Eq)]
20#[repr(u8)]
21pub enum ValueType {
22 Bool = 0,
24 Int = 1,
26 Float = 2,
28}
29
30#[derive(Clone)]
32pub struct ValueRec<const P: usize> {
33 is_only_front: bool,
35 vtype: ValueType,
36 vals: [i32; P],
37}
38
39impl<const P: usize> ValueRec<P> {
40 pub const fn new(vtype: ValueType) -> Self {
42 Self {
43 is_only_front: false,
44 vtype,
45 vals: [0; P],
46 }
47 }
48}
49
50pub enum AddError {
52 MapOverflow,
54}
55
56pub trait NextValue {
58 fn next<F>(&mut self, f: F)
61 where
62 F: FnOnce(&Self);
63}
64
65#[derive(Clone, Copy)]
67pub struct SVStruct<M> {
68 current: usize,
69 map: M,
70}
71
72impl<M> core::ops::Deref for SVStruct<M> {
73 type Target = M;
74 fn deref(&self) -> &Self::Target {
75 &self.map
76 }
77}
78
79impl<M> core::ops::DerefMut for SVStruct<M> {
80 fn deref_mut(&mut self) -> &mut Self::Target {
81 &mut self.map
82 }
83}
84
85pub type SVMap<const N: usize, const P: usize> = SVStruct<LinearMap<&'static str, ValueRec<P>, N>>;
87
88impl<const N: usize, const P: usize> SVMap<N, P> {
89 pub const fn new() -> Self {
91 Self {
92 current: 0,
93 map: LinearMap::new(),
94 }
95 }
96
97 pub fn is_first(&self) -> bool {
99 self.current == 0
100 }
101
102 pub fn is_last(&self) -> bool {
104 self.current == P - 1
105 }
106
107 fn set_value(
108 &mut self,
109 name: &'static str,
110 vtype: ValueType,
111 val: i32,
112 only_pos_front: bool,
113 ) -> Result<(), AddError> {
114 if !self.map.contains_key(&name) {
115 if self.map.insert(name, ValueRec::new(vtype)).is_err() {
116 return Err(AddError::MapOverflow);
117 }
118 }
119
120 let vr = self.map.get_mut(name).unwrap();
121 vr.vals[self.current] = val;
122 vr.is_only_front = only_pos_front;
123
124 Ok(())
125 }
126
127 pub fn set<T: Value>(&mut self, name: &'static Name, value: T) -> Result<(), AddError> {
129 self.set_value(name, T::TYPE, value.to_i32(), T::ONLY_FRONT)
130 }
131}
132
133pub trait Value {
135 const TYPE: ValueType;
137 const ONLY_FRONT: bool;
139 fn to_i32(self) -> i32;
141}
142
143impl Value for i32 {
144 const TYPE: ValueType = ValueType::Int;
145 const ONLY_FRONT: bool = false;
146 fn to_i32(self) -> i32 {
147 self
148 }
149}
150
151impl Value for f32 {
152 const TYPE: ValueType = ValueType::Float;
153 const ONLY_FRONT: bool = false;
154 fn to_i32(self) -> i32 {
155 self.to_bits() as i32
156 }
157}
158
159impl Value for bool {
160 const TYPE: ValueType = ValueType::Bool;
161 const ONLY_FRONT: bool = false;
162 fn to_i32(self) -> i32 {
163 self as i32
164 }
165}
166
167impl Value for OnlyFront {
168 const TYPE: ValueType = ValueType::Bool;
169 const ONLY_FRONT: bool = true;
170 fn to_i32(self) -> i32 {
171 self.0 as i32
172 }
173}
174
175impl<const N: usize, const P: usize> NextValue for SVMap<N, P> {
176 fn next<F>(&mut self, f: F)
177 where
178 F: FnOnce(&Self),
179 {
180 let previous = self.current;
181 self.current += 1;
182 if self.current >= P {
183 self.current -= P;
184 f(self);
185 }
186 for (_, v) in self.map.iter_mut() {
187 v.vals[self.current] = if v.is_only_front { 0 } else { v.vals[previous] };
188 }
189 }
190}
191
192pub trait SendPackage<V> {
194 type Error;
196 fn send_package(&mut self, module: &'static Name, values: &V) -> Result<(), Self::Error>;
198}
199
200impl<Tx, const N: usize, const P: usize> SendPackage<SVMap<N, P>> for Tx
202where
203 Tx: WriteIter,
204{
205 type Error = <Tx as WriteIter>::Error;
206 fn send_package(
207 &mut self,
208 module: &'static Name,
209 values: &SVMap<N, P>,
210 ) -> Result<(), Self::Error> {
211 use core::iter::repeat;
212 let vl_size = Name::MAX_SIZE + 4 + P * 4;
213 let full_size = (Name::MAX_SIZE + vl_size * values.map.len()) as u32;
215
216 self.bwrite_iter(
218 "=begin="
219 .bytes()
220 .chain(full_size.to_le_bytes().iter().cloned())
221 .chain(module.bytes())
223 .chain(repeat(0).take(Name::MAX_SIZE - module.len())),
224 )?;
225 self.bflush()?;
226
227 for (&name, v) in values.map.iter() {
228 self.bwrite_iter(
230 name.bytes()
231 .chain(repeat(0).take(Name::MAX_SIZE - name.len()))
232 .chain((v.vtype as i32).to_le_bytes().iter().cloned())
234 .chain(v.vals.iter().flat_map(|val| val.to_le_bytes())),
236 )?;
237 self.bflush()?;
238 }
239
240 self.bwrite_iter("=end=".bytes())?;
242 self.bflush()?;
243
244 Ok(())
245 }
246}
247
248pub struct Name(&'static str);
250
251impl core::ops::Deref for Name {
252 type Target = str;
253 fn deref(&self) -> &Self::Target {
254 self.0
255 }
256}
257
258impl Name {
259 const MAX_SIZE: usize = 24;
261
262 pub const fn new(name: &'static str) -> Self {
264 assert!(!name.is_empty());
265 assert!(name.len() < Self::MAX_SIZE);
266 assert!(!equal(name, "=end="));
267 assert!(!equal(name, "=begin="));
268 Self(name)
269 }
270}
271
272const fn equal(first: &'static str, second: &'static str) -> bool {
273 if first.len() != second.len() {
274 return false;
275 }
276 let fb = first.as_bytes();
277 let sb = second.as_bytes();
278 let mut i = 0;
279 while i < first.len() {
280 if fb[i] != sb[i] {
281 return false;
282 }
283 i += 1;
284 }
285 true
286}
287
288pub trait WriteIter {
290 type Error;
292 fn bwrite_iter<WI>(&mut self, bytes: WI) -> Result<(), Self::Error>
294 where
295 WI: Iterator<Item = u8>;
296 fn bflush(&mut self) -> Result<(), Self::Error>;
298}
299
300impl<Tx> WriteIter for Tx
301where
302 Tx: Write<u8>,
303{
304 type Error = <Tx as Write<u8>>::Error;
305
306 fn bwrite_iter<WI>(&mut self, mut bytes: WI) -> Result<(), Self::Error>
307 where
308 WI: Iterator<Item = u8>,
309 {
310 bytes.try_for_each(|c| nb::block!(self.write(c)))
311 }
312
313 fn bflush(&mut self) -> Result<(), Self::Error> {
314 nb::block!(self.flush())
315 }
316}