arminius_lib_component/
message_token.rs1#![allow(
8 clippy::allow_attributes,
9 reason = "This source file contains enums which allow `clippy::missing_docs_in_private_items`. But an exception to this lint will mistakenly report that it's unfulfilled when used with expect, even though it is not."
10)]
11
12mod tests;
13
14use axum::http::StatusCode;
15use ruma::{OwnedEventId, api::error::ErrorKind};
16use serde::{Deserialize, Serialize};
17
18use crate::error::MatrixApiError;
19
20const MESSAGES_TOKEN_PREFIX: &str = "m_";
22
23#[derive(
25 thiserror::Error, Debug, MatrixApiError, PartialEq, Eq, serde::Serialize, serde::Deserialize,
26)]
27#[matrix_api_error(status_code = StatusCode::BAD_REQUEST, error_kind = ErrorKind::InvalidParam, component_crate_root = crate)]
28#[error(transparent)]
29#[allow(
30 clippy::missing_docs_in_private_items,
31 missing_docs,
32 reason = "TODO(#2003): This exception predates us enabling `clippy::allow_attributes_without_reason`, so we don't know why it was enabled"
33)]
34pub enum MessageTokenParseError {
35 #[error("Missing messages token prefix")]
36 MissingMessagesTokenPrefix,
37 #[error("Missing event stream position")]
38 MissingEventStreamPosition,
39 #[error("Could not parse event stream position")]
40 InvalidEventStreamPosition,
41}
42
43#[derive(Clone, Debug, Serialize, Deserialize)]
48pub struct MessagesToken(pub OwnedEventId);
49
50impl TryFrom<&str> for MessagesToken {
51 type Error = MessageTokenParseError;
52
53 fn try_from(input: &str) -> Result<Self, Self::Error> {
54 if input.get(0..MESSAGES_TOKEN_PREFIX.len()) != Some(MESSAGES_TOKEN_PREFIX) {
55 return Err(MessageTokenParseError::MissingMessagesTokenPrefix);
56 }
57
58 let event_stream_position: OwnedEventId = input
59 .get(MESSAGES_TOKEN_PREFIX.len()..)
60 .ok_or(MessageTokenParseError::MissingEventStreamPosition)?
61 .parse()
62 .map_err(|_| MessageTokenParseError::InvalidEventStreamPosition)?;
63
64 Ok(MessagesToken(event_stream_position))
65 }
66}
67
68impl From<&MessagesToken> for String {
69 fn from(value: &MessagesToken) -> Self {
70 let MessagesToken(event_stream_position) = value;
71 format!("{MESSAGES_TOKEN_PREFIX}{event_stream_position}")
72 }
73}