serde_at 0.24.1

serde serializer/deserializer for AT commands
Documentation
use crate::HexStr;
use core::fmt::Write;
use serde::ser::Serialize;
use serde::Serializer;

macro_rules! impl_hex_str_serialize {
    ($type:ty, $len:expr, $len_delimited:expr, $hex_size:literal) => {
        impl Serialize for HexStr<$type> {
            fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
            where
                S: Serializer,
            {
                let val: $type = **self;
                if self.delimiter_after_nibble_count > 0 {
                    let mut string = heapless::String::<$len_delimited>::new();
                    let mut placeholder = heapless::String::<$len_delimited>::new();

                    if self.hex_in_caps {
                        write!(string, "{val:X}").unwrap();
                    } else {
                        write!(string, "{val:x}").unwrap();
                    }

                    for (index, c) in string.chars().rev().enumerate() {
                        if index != 0 && index % self.delimiter_after_nibble_count == 0 {
                            placeholder.push(self.delimiter).unwrap();
                        }
                        placeholder.push(c).unwrap();
                    }

                    if !self.skip_last_0_values {
                        for index in (string.len()..$hex_size) {
                            if index != 0 && index % self.delimiter_after_nibble_count == 0 {
                                placeholder.push(self.delimiter).unwrap();
                            }
                            placeholder.push('0').unwrap();
                        }
                    }

                    string.clear();
                    if self.add_0x_with_encoding {
                        string.push('0').unwrap();
                        string.push('x').unwrap();
                    }

                    for c in placeholder.chars().rev() {
                        string.push(c).unwrap();
                    }

                    serializer.serialize_str(string.as_str())
                } else {
                    let mut string = heapless::String::<$len>::new();
                    if self.skip_last_0_values {
                        match (self.add_0x_with_encoding, self.hex_in_caps) {
                            (true, true) => write!(string, "0x{val:X}").unwrap(),
                            (true, false) => write!(string, "0x{val:x}").unwrap(),
                            (false, true) => write!(string, "{val:X}").unwrap(),
                            (false, false) => write!(string, "{val:x}").unwrap(),
                        }
                    } else {
                        let mut hex = heapless::String::<$len>::new();
                        if self.hex_in_caps {
                            write!(hex, "{val:X}").unwrap();
                        } else {
                            write!(hex, "{val:x}").unwrap();
                        }

                        if self.add_0x_with_encoding {
                            string.push('0').unwrap();
                            string.push('x').unwrap();
                        }

                        for _i in (hex.len()..$hex_size) {
                            string.push('0').unwrap();
                        }

                        for c in hex.chars() {
                            string.push(c).unwrap();
                        }
                    }
                    serializer.serialize_str(string.as_str())
                }
            }
        }
    };
}

impl_hex_str_serialize!(u8, 8, 10, 2);
impl_hex_str_serialize!(u16, 12, 18, 4);
impl_hex_str_serialize!(u32, 20, 30, 8);
impl_hex_str_serialize!(u64, 36, 66, 16);
impl_hex_str_serialize!(u128, 68, 130, 32);

#[cfg(feature = "hex_str_arrays")]
mod unstable {

    use crate::HexStr;
    use core::fmt::Write;
    use serde::{Serialize, Serializer};

    impl<const N: usize> Serialize for HexStr<[u8; N]>
    where
        heapless::String<{ (1 + N * 4) * 2 }>: Sized,
    {
        fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
        where
            S: Serializer,
        {
            let val: &[u8] = if self.skip_last_0_values {
                let mut index = 0;
                for i in (0..(N - 1)).rev() {
                    index = i;
                    if self.val[i] != 0 {
                        break;
                    }
                }
                &self.val[0..=index]
            } else {
                &self.val
            };

            let mut string = heapless::String::<{ (1 + N * 4) * 2 }>::new();
            let mut nibble_count = 0;
            if self.add_0x_with_encoding {
                string.push_str("0x").unwrap();
            }
            for byte in val.iter() {
                let mut byte_string = heapless::String::<4>::new();
                if self.hex_in_caps {
                    write!(byte_string, "{:02X}", *byte).unwrap();
                } else {
                    write!(byte_string, "{:02x}", *byte).unwrap();
                }
                if self.delimiter_after_nibble_count != 0 {
                    for v in byte_string.as_str().chars() {
                        if nibble_count != 0
                            && nibble_count % self.delimiter_after_nibble_count == 0
                        {
                            string.push(self.delimiter).unwrap();
                        }
                        nibble_count += 1;
                        string.push(v).unwrap();
                    }
                } else {
                    for v in byte_string.as_str().chars() {
                        string.push(v).unwrap();
                    }
                }
            }
            serializer.serialize_str(string.as_str())
        }
    }
}