tuwunel_matrix/pdu/
raw_id.rs1use std::fmt;
2
3use arrayvec::ArrayVec;
4use serde::{Deserialize, Deserializer};
5
6use super::{
7 super::{ShortId, ShortRoomId},
8 Count, Id,
9};
10
11#[derive(Clone, Copy, Eq, Hash, PartialEq)]
16pub enum RawId {
17 Normal(RawIdNormal),
22
23 Backfilled(RawIdBackfilled),
28}
29
30type RawIdNormal = [u8; RawId::NORMAL_LEN];
31type RawIdBackfilled = [u8; RawId::BACKFILLED_LEN];
32
33struct RawIdVisitor;
34
35const INT_LEN: usize = size_of::<ShortId>();
36
37impl RawId {
38 const BACKFILLED_LEN: usize = size_of::<ShortRoomId>() + INT_LEN + size_of::<i64>();
39 const MAX_LEN: usize = Self::BACKFILLED_LEN;
40 const NORMAL_LEN: usize = size_of::<ShortRoomId>() + size_of::<u64>();
41
42 #[inline]
48 #[must_use]
49 pub fn try_from_bytes(id: &[u8]) -> Option<Self> {
50 <&RawIdNormal>::try_from(id)
51 .map(Self::from)
52 .or_else(|_| <&RawIdBackfilled>::try_from(id).map(Self::from))
53 .ok()
54 }
55
56 #[inline]
61 #[must_use]
62 pub fn is_room_eq(self, other: Self) -> bool { self.shortroomid() == other.shortroomid() }
63
64 #[inline]
69 #[must_use]
70 pub fn pdu_count(self) -> Count {
71 let id: Id = self.into();
72 id.count
73 }
74
75 #[inline]
80 #[must_use]
81 pub fn shortroomid(self) -> [u8; INT_LEN] {
82 match self {
83 | Self::Normal(raw) => raw[0..INT_LEN]
84 .try_into()
85 .expect("normal raw shortroomid array from slice"),
86 | Self::Backfilled(raw) => raw[0..INT_LEN]
87 .try_into()
88 .expect("backfilled raw shortroomid array from slice"),
89 }
90 }
91
92 #[inline]
97 #[must_use]
98 pub fn count(self) -> [u8; INT_LEN] {
99 match self {
100 | Self::Normal(raw) => raw[INT_LEN..INT_LEN * 2]
101 .try_into()
102 .expect("normal raw indice array from slice"),
103 | Self::Backfilled(raw) => raw[INT_LEN * 2..INT_LEN * 3]
104 .try_into()
105 .expect("backfilled raw indice array from slice"),
106 }
107 }
108
109 #[inline]
114 #[must_use]
115 pub fn as_bytes(&self) -> &[u8] {
116 match self {
117 | Self::Normal(raw) => raw,
118 | Self::Backfilled(raw) => raw,
119 }
120 }
121}
122
123impl fmt::Debug for RawId {
124 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
125 let id: Id = (*self).into();
126 write!(f, "{id:?}")
127 }
128}
129
130impl<'de> Deserialize<'de> for RawId {
131 #[inline]
132 fn deserialize<D: Deserializer<'de>>(d: D) -> Result<Self, D::Error> {
133 d.deserialize_bytes(RawIdVisitor)
134 }
135}
136
137impl serde::de::Visitor<'_> for RawIdVisitor {
138 type Value = RawId;
139
140 fn expecting(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
141 f.write_str("RawId byte array")
142 }
143
144 #[inline]
145 fn visit_bytes<E>(self, buf: &[u8]) -> Result<RawId, E> { Ok(RawId::from(buf)) }
146}
147
148impl From<Id> for RawId {
149 #[inline]
150 fn from(id: Id) -> Self {
151 const MAX_LEN: usize = RawId::MAX_LEN;
152 type RawVec = ArrayVec<u8, MAX_LEN>;
153
154 let mut vec = RawVec::new();
155 vec.extend(id.shortroomid.to_be_bytes());
156 id.count.debug_assert_valid();
157 match id.count {
158 | Count::Normal(count) => {
159 vec.extend(count.to_be_bytes());
160 Self::Normal(
161 vec.as_ref()
162 .try_into()
163 .expect("RawVec into RawId::Normal"),
164 )
165 },
166 | Count::Backfilled(count) => {
167 vec.extend(0_u64.to_be_bytes());
168 vec.extend(count.to_be_bytes());
169 Self::Backfilled(
170 vec.as_ref()
171 .try_into()
172 .expect("RawVec into RawId::Backfilled"),
173 )
174 },
175 }
176 }
177}
178
179impl From<&[u8]> for RawId {
180 #[inline]
181 fn from(id: &[u8]) -> Self {
182 match id.len() {
183 | Self::NORMAL_LEN => Self::Normal(
184 id[0..Self::NORMAL_LEN]
185 .try_into()
186 .expect("normal RawId from [u8]"),
187 ),
188 | Self::BACKFILLED_LEN => Self::Backfilled(
189 id[0..Self::BACKFILLED_LEN]
190 .try_into()
191 .expect("backfilled RawId from [u8]"),
192 ),
193 | _ => unimplemented!("unrecognized RawId length"),
194 }
195 }
196}
197
198impl From<&[u8; Self::NORMAL_LEN]> for RawId {
199 #[inline]
200 fn from(id: &[u8; Self::NORMAL_LEN]) -> Self { Self::Normal(*id) }
201}
202
203impl From<&[u8; Self::BACKFILLED_LEN]> for RawId {
204 #[inline]
205 fn from(id: &[u8; Self::BACKFILLED_LEN]) -> Self { Self::Backfilled(*id) }
206}
207
208impl AsRef<[u8]> for RawId {
209 #[inline]
210 fn as_ref(&self) -> &[u8] { self.as_bytes() }
211}