passkey_types/utils/
bytes.rs1use std::ops::{Deref, DerefMut};
2
3use serde::{Deserialize, Deserializer, Serialize, de::Visitor};
4#[cfg(feature = "typeshare")]
5use typeshare::typeshare;
6
7use super::encoding;
8
9#[cfg_attr(feature = "typeshare", typeshare(transparent))]
21#[derive(Debug, Default, PartialEq, Eq, Clone, Hash)]
22#[repr(transparent)]
23pub struct Bytes(Vec<u8>);
24
25impl Deref for Bytes {
26 type Target = Vec<u8>;
27
28 fn deref(&self) -> &Self::Target {
29 &self.0
30 }
31}
32
33impl DerefMut for Bytes {
34 fn deref_mut(&mut self) -> &mut Self::Target {
35 &mut self.0
36 }
37}
38
39impl From<Vec<u8>> for Bytes {
40 fn from(inner: Vec<u8>) -> Self {
41 Bytes(inner)
42 }
43}
44
45impl From<&[u8]> for Bytes {
46 fn from(value: &[u8]) -> Self {
47 Bytes(value.to_vec())
48 }
49}
50
51impl From<Bytes> for Vec<u8> {
52 fn from(src: Bytes) -> Self {
53 src.0
54 }
55}
56
57impl From<Bytes> for String {
58 fn from(src: Bytes) -> Self {
59 encoding::base64url(&src)
60 }
61}
62
63#[derive(Debug)]
65pub struct NotBase64Encoded;
66
67impl TryFrom<&str> for Bytes {
68 type Error = NotBase64Encoded;
69
70 fn try_from(value: &str) -> Result<Self, Self::Error> {
71 encoding::try_from_base64url(value)
72 .or_else(|| encoding::try_from_base64(value))
73 .ok_or(NotBase64Encoded)
74 .map(Self)
75 }
76}
77
78impl FromIterator<u8> for Bytes {
79 fn from_iter<T: IntoIterator<Item = u8>>(iter: T) -> Self {
80 Bytes(iter.into_iter().collect())
81 }
82}
83
84impl IntoIterator for Bytes {
85 type Item = u8;
86
87 type IntoIter = std::vec::IntoIter<u8>;
88
89 fn into_iter(self) -> Self::IntoIter {
90 self.0.into_iter()
91 }
92}
93
94impl<'a> IntoIterator for &'a Bytes {
95 type Item = &'a u8;
96
97 type IntoIter = std::slice::Iter<'a, u8>;
98
99 fn into_iter(self) -> Self::IntoIter {
100 self.0.iter()
101 }
102}
103
104impl Serialize for Bytes {
105 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
106 where
107 S: serde::Serializer,
108 {
109 if cfg!(feature = "serialize_bytes_as_base64_string") {
110 serializer.serialize_str(&encoding::base64url(&self.0))
111 } else {
112 serializer.serialize_bytes(&self.0)
113 }
114 }
115}
116
117impl<'de> Deserialize<'de> for Bytes {
118 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
119 where
120 D: Deserializer<'de>,
121 {
122 struct Base64Visitor;
123
124 impl<'de> Visitor<'de> for Base64Visitor {
125 type Value = Bytes;
126
127 fn expecting(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
128 write!(f, "A vector of bytes or a base46(url) encoded string")
129 }
130 fn visit_borrowed_str<E>(self, v: &'de str) -> Result<Self::Value, E>
131 where
132 E: serde::de::Error,
133 {
134 self.visit_str(v)
135 }
136 fn visit_string<E>(self, v: String) -> Result<Self::Value, E>
137 where
138 E: serde::de::Error,
139 {
140 self.visit_str(&v)
141 }
142 fn visit_str<E>(self, v: &str) -> Result<Self::Value, E>
143 where
144 E: serde::de::Error,
145 {
146 let v = v.trim();
148 v.try_into().map_err(|_| {
149 E::invalid_value(
150 serde::de::Unexpected::Str(v),
151 &"A base64(url) encoded string",
152 )
153 })
154 }
155 fn visit_seq<A>(self, mut seq: A) -> Result<Self::Value, A::Error>
156 where
157 A: serde::de::SeqAccess<'de>,
158 {
159 let mut buf = Vec::with_capacity(seq.size_hint().unwrap_or_default());
160 while let Some(byte) = seq.next_element()? {
161 buf.push(byte);
162 }
163 Ok(Bytes(buf))
164 }
165 fn visit_bytes<E>(self, v: &[u8]) -> Result<Self::Value, E>
166 where
167 E: serde::de::Error,
168 {
169 Ok(Bytes(v.to_vec()))
170 }
171 }
172 deserializer.deserialize_any(Base64Visitor)
173 }
174}
175
176#[cfg(test)]
177mod tests;