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}