x12/
fixed.rs

1use std::fmt;
2use std::str::FromStr;
3
4use serde::{Deserialize, Serialize};
5use serde::{ser, de};
6use serde::de::Error;
7
8#[derive(Clone, Copy, PartialEq)]
9pub struct Fixed<const N: usize>([u8; N]);
10
11impl<const N: usize> fmt::Debug for Fixed<N> {
12    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
13        let value = std::str::from_utf8(&self.0).unwrap();
14        write!(f, "{:?}", value)
15    }
16}
17
18impl std::ops::Deref for Fixed<1> {
19    type Target = [u8];
20
21    fn deref(&self) -> &Self::Target {
22        self.0.as_slice()
23    }
24}
25
26impl<const N: usize> Fixed<N> {
27    pub fn new(s: &[u8]) -> Self {
28        if s.len() != N {
29            panic!("wrong byte slice length");
30        }
31        let mut bytes = [b' '; N];
32        bytes[..s.len()].copy_from_slice(s);
33        Fixed(bytes)
34    }
35
36    pub fn as_arr(&self) -> &[u8; N] {
37        &self.0
38    }
39}
40
41impl<const N: usize> PartialEq<&[u8]> for Fixed<N> {
42    fn eq(&self, other: &&[u8]) -> bool {
43        self.0 == **other
44    }
45}
46
47impl<const N: usize> PartialEq<[u8; N]> for Fixed<N> {
48    fn eq(&self, other: &[u8; N]) -> bool {
49        self.0 == *other
50    }
51}
52
53impl<const N: usize> fmt::Display for Fixed<N> {
54    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
55        let value = std::str::from_utf8(&self.0).unwrap();
56        write!(f, "{}", value.trim())
57    }
58}
59
60#[derive(Debug)]
61pub struct InvalidLength;
62
63impl<const N: usize> FromStr for Fixed<N> {
64    type Err = InvalidLength;
65
66    fn from_str(s: &str) -> Result<Self, Self::Err> {
67        if s.len() > N {
68            return Err(InvalidLength);
69        }
70        let mut bytes = [b' '; N];
71        bytes[..s.len()].copy_from_slice(s.as_bytes());
72        Ok(Fixed(bytes))
73    }
74}
75
76impl<const N: usize> Serialize for Fixed<N> {
77    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error> where S: ser::Serializer {
78        if serializer.is_human_readable() {
79            let value = std::str::from_utf8(&self.0).unwrap();
80            let value = value.trim();
81            serializer.serialize_str(value)
82        } else {
83            serializer.serialize_bytes(&self.0)
84        }
85    }
86}
87
88struct FixedVisitor<const N: usize> {
89    exact: bool,
90}
91
92impl<'de, const N: usize> de::Visitor<'de> for FixedVisitor<N> {
93    type Value = Fixed<N>;
94
95    fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
96        formatter.write_str("a fixed length string")
97    }
98
99    fn visit_str<E>(self, v: &str) -> Result<Self::Value, E> where E: Error {
100        if v.len() > N || (self.exact && v.len() < N) {
101            return Err(E::invalid_length(v.len(), &format!("a string of length {}", N).as_str()));
102        }
103        let mut bytes = [b' '; N];
104        bytes[..v.len()].copy_from_slice(v.as_bytes());
105        Ok(Fixed(bytes))
106    }
107}
108
109impl<'de, const N: usize> Deserialize<'de> for Fixed<N> {
110    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error> where D: de::Deserializer<'de> {
111        let exact = !deserializer.is_human_readable();
112        deserializer.deserialize_str(FixedVisitor::<N> { exact })
113    }
114}