use crate::register::{Access, Register, WriteError};
use canadensis_data_types::uavcan::primitive::array::bit_1_0::Bit;
use canadensis_data_types::uavcan::primitive::array::integer16_1_0::Integer16;
use canadensis_data_types::uavcan::primitive::array::integer32_1_0::Integer32;
use canadensis_data_types::uavcan::primitive::array::integer64_1_0::Integer64;
use canadensis_data_types::uavcan::primitive::array::integer8_1_0::Integer8;
use canadensis_data_types::uavcan::primitive::array::natural16_1_0::Natural16;
use canadensis_data_types::uavcan::primitive::array::natural32_1_0::Natural32;
use canadensis_data_types::uavcan::primitive::array::natural64_1_0::Natural64;
use canadensis_data_types::uavcan::primitive::array::natural8_1_0::Natural8;
use canadensis_data_types::uavcan::primitive::array::real16_1_0::Real16;
use canadensis_data_types::uavcan::primitive::array::real32_1_0::Real32;
use canadensis_data_types::uavcan::primitive::array::real64_1_0::Real64;
use canadensis_data_types::uavcan::primitive::string_1_0;
use canadensis_data_types::uavcan::primitive::unstructured_1_0;
use canadensis_data_types::uavcan::register::value_1_0::Value;
use canadensis_encoding::bits::BitArray;
use core::convert::TryFrom;
use half::f16;
#[derive(Debug, Clone)]
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
pub struct SimpleRegister<T> {
name: &'static str,
access: Access,
value: T,
}
impl<T> SimpleRegister<T> {
pub fn new(name: &'static str, mutable: bool, persistent: bool) -> Self
where
T: Default,
{
Self::with_value(name, mutable, persistent, T::default())
}
pub fn with_value(name: &'static str, mutable: bool, persistent: bool, value: T) -> Self {
SimpleRegister {
name,
access: Access {
mutable,
persistent,
},
value,
}
}
pub fn value(&self) -> &T {
&self.value
}
pub fn value_mut(&mut self) -> &mut T {
&mut self.value
}
pub fn set_value(&mut self, value: T) {
self.value = value;
}
}
impl<T> Register for SimpleRegister<T>
where
T: RegisterType,
{
fn name(&self) -> &str {
self.name
}
fn access(&self) -> Access {
self.access.clone()
}
fn read(&self) -> Value {
self.value.read()
}
fn write(&mut self, value: &Value) -> Result<(), WriteError> {
self.value.write(value)
}
}
pub struct ValidatedRegister<T, V = fn(&T) -> bool> {
name: &'static str,
access: Access,
value: T,
validator: V,
}
impl<T, V> core::fmt::Debug for ValidatedRegister<T, V>
where
T: core::fmt::Debug,
{
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
f.debug_struct("ValidatedRegister")
.field("name", &self.name)
.field("access", &self.access)
.field("value", &self.value)
.finish()
}
}
#[cfg(feature = "defmt")]
impl<T, V> defmt::Format for ValidatedRegister<T, V>
where
T: defmt::Format,
{
fn format(&self, f: defmt::Formatter) {
defmt::write!(
f,
"ValidatedRegister {{ name: \"{}\", access: {}, value: {} }}",
self.name,
self.access,
self.value
)
}
}
impl<T, V> ValidatedRegister<T, V>
where
T: Default,
{
pub fn new(name: &'static str, mutable: bool, persistent: bool, validator: V) -> Self {
Self::with_value(name, mutable, persistent, T::default(), validator)
}
}
impl<T, V> ValidatedRegister<T, V> {
pub fn with_value(
name: &'static str,
mutable: bool,
persistent: bool,
value: T,
validator: V,
) -> Self {
ValidatedRegister {
name,
access: Access {
mutable,
persistent,
},
value,
validator,
}
}
pub fn value(&self) -> &T {
&self.value
}
pub fn value_mut(&mut self) -> &mut T {
&mut self.value
}
pub fn set_value(&mut self, value: T) {
self.value = value;
}
}
impl<T, V> Register for ValidatedRegister<T, V>
where
T: RegisterType + Clone,
V: Validator<T>,
{
fn name(&self) -> &str {
self.name
}
fn access(&self) -> Access {
self.access.clone()
}
fn read(&self) -> Value {
self.value.read()
}
fn write(&mut self, value: &Value) -> Result<(), WriteError> {
let mut new_value = self.value.clone();
new_value.write(value)?;
if self.validator.accept(&new_value) {
self.value = new_value;
Ok(())
} else {
Err(WriteError::Type)
}
}
}
pub trait Validator<T> {
fn accept(&mut self, value: &T) -> bool;
}
impl<F, T> Validator<T> for F
where
F: FnMut(&T) -> bool,
{
fn accept(&mut self, value: &T) -> bool {
self(value)
}
}
pub trait RegisterType {
fn read(&self) -> Value;
fn write(&mut self, value: &Value) -> Result<(), WriteError>;
}
macro_rules! register_primitive {
($type:ty, $variant:ident) => {
impl RegisterType for $type {
fn read(&self) -> Value {
Value::$variant($variant {
value: heapless::Vec::from_slice(&[*self]).unwrap(),
})
}
fn write(&mut self, value: &Value) -> Result<(), WriteError> {
if let Value::$variant($variant { value: values }) = value {
if values.len() == 1 {
*self = values[0];
Ok(())
} else {
Err(WriteError::Type)
}
} else {
Err(WriteError::Type)
}
}
}
};
}
register_primitive!(u8, Natural8);
register_primitive!(u16, Natural16);
register_primitive!(u32, Natural32);
register_primitive!(u64, Natural64);
register_primitive!(i8, Integer8);
register_primitive!(i16, Integer16);
register_primitive!(i32, Integer32);
register_primitive!(i64, Integer64);
register_primitive!(f16, Real16);
register_primitive!(f32, Real32);
register_primitive!(f64, Real64);
macro_rules! register_primitive_array {
($type:ty, $variant:ident) => {
impl<const N: usize> RegisterType for [$type; N] {
fn read(&self) -> Value {
let mut value_vec = heapless::Vec::new();
if N <= value_vec.capacity() {
value_vec
.extend_from_slice(&*self)
.expect("Incorrect length calculation");
} else {
value_vec
.extend_from_slice(&self[..value_vec.capacity()])
.expect("Incorrect length calculation");
}
Value::$variant($variant { value: value_vec })
}
fn write(&mut self, value: &Value) -> Result<(), WriteError> {
match value {
Value::$variant($variant { value: values }) => {
if values.len() == N {
self.copy_from_slice(&values);
Ok(())
} else {
Err(WriteError::Type)
}
}
_ => Err(WriteError::Type),
}
}
}
};
}
register_primitive_array!(u8, Natural8);
register_primitive_array!(u16, Natural16);
register_primitive_array!(u32, Natural32);
register_primitive_array!(u64, Natural64);
register_primitive_array!(i8, Integer8);
register_primitive_array!(i16, Integer16);
register_primitive_array!(i32, Integer32);
register_primitive_array!(i64, Integer64);
register_primitive_array!(f16, Real16);
register_primitive_array!(f32, Real32);
register_primitive_array!(f64, Real64);
#[derive(Debug, Clone, Default)]
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
pub struct RegisterString(pub heapless::Vec<u8, 256>);
impl RegisterType for RegisterString {
fn read(&self) -> Value {
Value::String(string_1_0::String {
value: self.0.clone(),
})
}
fn write(&mut self, value: &Value) -> Result<(), WriteError> {
match value {
Value::String(string_1_0::String { value: bytes }) => {
self.0.clone_from(bytes);
Ok(())
}
_ => Err(WriteError::Type),
}
}
}
impl TryFrom<&[u8]> for RegisterString {
type Error = LengthError;
fn try_from(value: &[u8]) -> Result<Self, Self::Error> {
let byte_vec = heapless::Vec::from_slice(value).map_err(|_| LengthError(()))?;
Ok(RegisterString(byte_vec))
}
}
impl TryFrom<&str> for RegisterString {
type Error = LengthError;
fn try_from(value: &str) -> Result<Self, Self::Error> {
RegisterString::try_from(value.as_bytes())
}
}
#[derive(Debug, Clone, Default)]
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
pub struct Unstructured(pub heapless::Vec<u8, 256>);
impl RegisterType for Unstructured {
fn read(&self) -> Value {
Value::Unstructured(unstructured_1_0::Unstructured {
value: self.0.clone(),
})
}
fn write(&mut self, value: &Value) -> Result<(), WriteError> {
match value {
Value::Unstructured(unstructured_1_0::Unstructured { value: bytes }) => {
self.0.clone_from(bytes);
Ok(())
}
_ => Err(WriteError::Type),
}
}
}
impl TryFrom<&[u8]> for Unstructured {
type Error = LengthError;
fn try_from(value: &[u8]) -> Result<Self, Self::Error> {
let byte_vec = heapless::Vec::from_slice(value).map_err(|_| LengthError(()))?;
Ok(Unstructured(byte_vec))
}
}
impl RegisterType for bool {
fn read(&self) -> Value {
let mut value = BitArray::new(1);
value.set(0, *self);
Value::Bit(Bit { value })
}
fn write(&mut self, value: &Value) -> Result<(), WriteError> {
if let Value::Bit(Bit { value: values }) = value {
if values.len() == 1 {
*self = values.get(0);
Ok(())
} else {
Err(WriteError::Type)
}
} else {
Err(WriteError::Type)
}
}
}
impl<const N: usize> RegisterType for [bool; N] {
fn read(&self) -> Value {
let mut value = BitArray::new(N);
for (i, val) in self.iter().enumerate() {
value.set(i, *val);
}
Value::Bit(Bit { value })
}
fn write(&mut self, value: &Value) -> Result<(), WriteError> {
if let Value::Bit(Bit { value: values }) = value {
if values.len() == N {
for (i, val) in values.iter().enumerate() {
self[i] = val
}
Ok(())
} else {
Err(WriteError::Type)
}
} else {
Err(WriteError::Type)
}
}
}
#[derive(Debug)]
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
pub struct LengthError(());
#[derive(Debug)]
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
pub struct FixedStringRegister {
name: &'static str,
value: &'static str,
}
impl FixedStringRegister {
pub fn new(name: &'static str, value: &'static str) -> Option<Self> {
if !name.is_empty() && name.len() <= 256 && value.len() <= 256 {
Some(FixedStringRegister { name, value })
} else {
None
}
}
}
impl Register for FixedStringRegister {
fn name(&self) -> &str {
self.name
}
fn access(&self) -> Access {
Access {
mutable: false,
persistent: true,
}
}
fn read(&self) -> Value {
Value::String(string_1_0::String {
value: heapless::Vec::from_slice(self.value.as_bytes())
.expect("Register value too long"),
})
}
fn write(&mut self, _value: &Value) -> Result<(), WriteError> {
unimplemented!("A FixedStringRegister cannot be written")
}
}