Skip to main content

tuwunel_service/rooms/spaces/
pagination_token.rs

1use std::{
2	fmt::{Display, Formatter},
3	str::FromStr,
4};
5
6use ruma::UInt;
7use tuwunel_core::{Err, Error, Result};
8
9use crate::rooms::short::ShortRoomId;
10
11// TODO: perhaps use some better form of token rather than just room count
12#[derive(Debug, Eq, PartialEq)]
13pub struct PaginationToken {
14	/// Path down the hierarchy of the room to start the response at,
15	/// excluding the root space.
16	pub short_room_ids: Vec<ShortRoomId>,
17	pub limit: UInt,
18	pub max_depth: UInt,
19	pub suggested_only: bool,
20}
21
22impl FromStr for PaginationToken {
23	type Err = Error;
24
25	fn from_str(value: &str) -> Result<Self> {
26		let mut values = value.split('_');
27		let mut pag_tok = || {
28			let short_room_ids = values
29				.next()?
30				.split(',')
31				.filter_map(|room_s| u64::from_str(room_s).ok())
32				.collect();
33
34			let limit = UInt::from_str(values.next()?).ok()?;
35			let max_depth = UInt::from_str(values.next()?).ok()?;
36			let slice = values.next()?;
37			let suggested_only = if values.next().is_none() {
38				if slice == "true" {
39					true
40				} else if slice == "false" {
41					false
42				} else {
43					None?
44				}
45			} else {
46				None?
47			};
48
49			Some(Self {
50				short_room_ids,
51				limit,
52				max_depth,
53				suggested_only,
54			})
55		};
56
57		pag_tok().map_or(Err!(Request(InvalidParam("invalid token"))), Ok)
58	}
59}
60
61impl Display for PaginationToken {
62	fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
63		let short_room_ids = self
64			.short_room_ids
65			.iter()
66			.map(ToString::to_string)
67			.collect::<Vec<_>>()
68			.join(",");
69
70		write!(f, "{short_room_ids}_{}_{}_{}", self.limit, self.max_depth, self.suggested_only)
71	}
72}