#![no_std]
#![deny(missing_docs)]
pub mod prelude;
use embedded_hal::serial::Write;
use heapless::LinearMap;
use nb;
pub struct OnlyFront(pub bool);
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
#[repr(u8)]
pub enum ValueType {
Bool = 0,
Int = 1,
Float = 2,
}
#[derive(Clone)]
pub struct ValueRec<const P: usize> {
is_only_front: bool,
vtype: ValueType,
vals: [i32; P],
}
impl<const P: usize> ValueRec<P> {
pub const fn new(vtype: ValueType) -> Self {
Self {
is_only_front: false,
vtype,
vals: [0; P],
}
}
}
pub enum AddError {
MapOverflow,
}
pub trait NextValue {
fn next<F>(&mut self, f: F)
where
F: FnOnce(&Self);
}
#[derive(Clone, Copy)]
pub struct SVStruct<M> {
current: usize,
map: M,
}
impl<M> core::ops::Deref for SVStruct<M> {
type Target = M;
fn deref(&self) -> &Self::Target {
&self.map
}
}
impl<M> core::ops::DerefMut for SVStruct<M> {
fn deref_mut(&mut self) -> &mut Self::Target {
&mut self.map
}
}
pub type SVMap<const N: usize, const P: usize> = SVStruct<LinearMap<&'static str, ValueRec<P>, N>>;
impl<const N: usize, const P: usize> SVMap<N, P> {
pub const fn new() -> Self {
Self {
current: 0,
map: LinearMap::new(),
}
}
pub fn is_first(&self) -> bool {
self.current == 0
}
pub fn is_last(&self) -> bool {
self.current == P - 1
}
fn set_value(
&mut self,
name: &'static str,
vtype: ValueType,
val: i32,
only_pos_front: bool,
) -> Result<(), AddError> {
if !self.map.contains_key(&name) {
if self.map.insert(name, ValueRec::new(vtype)).is_err() {
return Err(AddError::MapOverflow);
}
}
let vr = self.map.get_mut(name).unwrap();
vr.vals[self.current] = val;
vr.is_only_front = only_pos_front;
Ok(())
}
pub fn set<T: Value>(&mut self, name: &'static Name, value: T) -> Result<(), AddError> {
self.set_value(name, T::TYPE, value.to_i32(), T::ONLY_FRONT)
}
}
pub trait Value {
const TYPE: ValueType;
const ONLY_FRONT: bool;
fn to_i32(self) -> i32;
}
impl Value for i32 {
const TYPE: ValueType = ValueType::Int;
const ONLY_FRONT: bool = false;
fn to_i32(self) -> i32 {
self
}
}
impl Value for f32 {
const TYPE: ValueType = ValueType::Float;
const ONLY_FRONT: bool = false;
fn to_i32(self) -> i32 {
self.to_bits() as i32
}
}
impl Value for bool {
const TYPE: ValueType = ValueType::Bool;
const ONLY_FRONT: bool = false;
fn to_i32(self) -> i32 {
self as i32
}
}
impl Value for OnlyFront {
const TYPE: ValueType = ValueType::Bool;
const ONLY_FRONT: bool = true;
fn to_i32(self) -> i32 {
self.0 as i32
}
}
impl<const N: usize, const P: usize> NextValue for SVMap<N, P> {
fn next<F>(&mut self, f: F)
where
F: FnOnce(&Self),
{
let previous = self.current;
self.current += 1;
if self.current >= P {
self.current -= P;
f(self);
}
for (_, v) in self.map.iter_mut() {
v.vals[self.current] = if v.is_only_front { 0 } else { v.vals[previous] };
}
}
}
pub trait SendPackage<V> {
type Error;
fn send_package(&mut self, module: &'static Name, values: &V) -> Result<(), Self::Error>;
}
impl<Tx, const N: usize, const P: usize> SendPackage<SVMap<N, P>> for Tx
where
Tx: WriteIter,
{
type Error = <Tx as WriteIter>::Error;
fn send_package(
&mut self,
module: &'static Name,
values: &SVMap<N, P>,
) -> Result<(), Self::Error> {
use core::iter::repeat;
let vl_size = Name::MAX_SIZE + 4 + P * 4;
let full_size = (Name::MAX_SIZE + vl_size * values.map.len()) as u32;
self.bwrite_iter(
"=begin="
.bytes()
.chain(full_size.to_le_bytes().iter().cloned())
.chain(module.bytes())
.chain(repeat(0).take(Name::MAX_SIZE - module.len())),
)?;
self.bflush()?;
for (&name, v) in values.map.iter() {
self.bwrite_iter(
name.bytes()
.chain(repeat(0).take(Name::MAX_SIZE - name.len()))
.chain((v.vtype as i32).to_le_bytes().iter().cloned())
.chain(v.vals.iter().flat_map(|val| val.to_le_bytes())),
)?;
self.bflush()?;
}
self.bwrite_iter("=end=".bytes())?;
self.bflush()?;
Ok(())
}
}
pub struct Name(&'static str);
impl core::ops::Deref for Name {
type Target = str;
fn deref(&self) -> &Self::Target {
self.0
}
}
impl Name {
const MAX_SIZE: usize = 24;
pub const fn new(name: &'static str) -> Self {
assert!(!name.is_empty());
assert!(name.len() < Self::MAX_SIZE);
assert!(!equal(name, "=end="));
assert!(!equal(name, "=begin="));
Self(name)
}
}
const fn equal(first: &'static str, second: &'static str) -> bool {
if first.len() != second.len() {
return false;
}
let fb = first.as_bytes();
let sb = second.as_bytes();
let mut i = 0;
while i < first.len() {
if fb[i] != sb[i] {
return false;
}
i += 1;
}
true
}
pub trait WriteIter {
type Error;
fn bwrite_iter<WI>(&mut self, bytes: WI) -> Result<(), Self::Error>
where
WI: Iterator<Item = u8>;
fn bflush(&mut self) -> Result<(), Self::Error>;
}
impl<Tx> WriteIter for Tx
where
Tx: Write<u8>,
{
type Error = <Tx as Write<u8>>::Error;
fn bwrite_iter<WI>(&mut self, mut bytes: WI) -> Result<(), Self::Error>
where
WI: Iterator<Item = u8>,
{
bytes.try_for_each(|c| nb::block!(self.write(c)))
}
fn bflush(&mut self) -> Result<(), Self::Error> {
nb::block!(self.flush())
}
}