Skip to main content

tuwunel_core/matrix/pdu/
raw_id.rs

1use 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)]
12pub enum RawId {
13	Normal(RawIdNormal),
14	Backfilled(RawIdBackfilled),
15}
16
17type RawIdNormal = [u8; RawId::NORMAL_LEN];
18type RawIdBackfilled = [u8; RawId::BACKFILLED_LEN];
19
20struct RawIdVisitor;
21
22const INT_LEN: usize = size_of::<ShortId>();
23
24impl RawId {
25	const BACKFILLED_LEN: usize = size_of::<ShortRoomId>() + INT_LEN + size_of::<i64>();
26	const MAX_LEN: usize = Self::BACKFILLED_LEN;
27	const NORMAL_LEN: usize = size_of::<ShortRoomId>() + size_of::<u64>();
28
29	#[inline]
30	#[must_use]
31	pub fn is_room_eq(self, other: Self) -> bool { self.shortroomid() == other.shortroomid() }
32
33	#[inline]
34	#[must_use]
35	pub fn pdu_count(self) -> Count {
36		let id: Id = self.into();
37		id.count
38	}
39
40	#[inline]
41	#[must_use]
42	pub fn shortroomid(self) -> [u8; INT_LEN] {
43		match self {
44			| Self::Normal(raw) => raw[0..INT_LEN]
45				.try_into()
46				.expect("normal raw shortroomid array from slice"),
47			| Self::Backfilled(raw) => raw[0..INT_LEN]
48				.try_into()
49				.expect("backfilled raw shortroomid array from slice"),
50		}
51	}
52
53	#[inline]
54	#[must_use]
55	pub fn count(self) -> [u8; INT_LEN] {
56		match self {
57			| Self::Normal(raw) => raw[INT_LEN..INT_LEN * 2]
58				.try_into()
59				.expect("normal raw indice array from slice"),
60			| Self::Backfilled(raw) => raw[INT_LEN * 2..INT_LEN * 3]
61				.try_into()
62				.expect("backfilled raw indice array from slice"),
63		}
64	}
65
66	#[inline]
67	#[must_use]
68	pub fn as_bytes(&self) -> &[u8] {
69		match self {
70			| Self::Normal(raw) => raw,
71			| Self::Backfilled(raw) => raw,
72		}
73	}
74}
75
76impl fmt::Debug for RawId {
77	fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
78		let id: Id = (*self).into();
79		write!(f, "{id:?}")
80	}
81}
82
83impl<'de> Deserialize<'de> for RawId {
84	#[inline]
85	fn deserialize<D: Deserializer<'de>>(d: D) -> Result<Self, D::Error> {
86		d.deserialize_bytes(RawIdVisitor)
87	}
88}
89
90impl serde::de::Visitor<'_> for RawIdVisitor {
91	type Value = RawId;
92
93	fn expecting(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
94		f.write_str("RawId byte array")
95	}
96
97	#[inline]
98	fn visit_bytes<E>(self, buf: &[u8]) -> Result<RawId, E> { Ok(RawId::from(buf)) }
99}
100
101impl From<Id> for RawId {
102	#[inline]
103	fn from(id: Id) -> Self {
104		const MAX_LEN: usize = RawId::MAX_LEN;
105		type RawVec = ArrayVec<u8, MAX_LEN>;
106
107		let mut vec = RawVec::new();
108		vec.extend(id.shortroomid.to_be_bytes());
109		id.count.debug_assert_valid();
110		match id.count {
111			| Count::Normal(count) => {
112				vec.extend(count.to_be_bytes());
113				Self::Normal(
114					vec.as_ref()
115						.try_into()
116						.expect("RawVec into RawId::Normal"),
117				)
118			},
119			| Count::Backfilled(count) => {
120				vec.extend(0_u64.to_be_bytes());
121				vec.extend(count.to_be_bytes());
122				Self::Backfilled(
123					vec.as_ref()
124						.try_into()
125						.expect("RawVec into RawId::Backfilled"),
126				)
127			},
128		}
129	}
130}
131
132impl From<&[u8]> for RawId {
133	#[inline]
134	fn from(id: &[u8]) -> Self {
135		match id.len() {
136			| Self::NORMAL_LEN => Self::Normal(
137				id[0..Self::NORMAL_LEN]
138					.try_into()
139					.expect("normal RawId from [u8]"),
140			),
141			| Self::BACKFILLED_LEN => Self::Backfilled(
142				id[0..Self::BACKFILLED_LEN]
143					.try_into()
144					.expect("backfilled RawId from [u8]"),
145			),
146			| _ => unimplemented!("unrecognized RawId length"),
147		}
148	}
149}
150
151impl From<&[u8; Self::NORMAL_LEN]> for RawId {
152	#[inline]
153	fn from(id: &[u8; Self::NORMAL_LEN]) -> Self { Self::Normal(*id) }
154}
155
156impl From<&[u8; Self::BACKFILLED_LEN]> for RawId {
157	#[inline]
158	fn from(id: &[u8; Self::BACKFILLED_LEN]) -> Self { Self::Backfilled(*id) }
159}
160
161impl AsRef<[u8]> for RawId {
162	#[inline]
163	fn as_ref(&self) -> &[u8] { self.as_bytes() }
164}