zulip_api/filter/
anchor.rs1use serde::{Deserialize, Serialize};
2
3use crate::error::Error;
4
5#[derive(Clone, Copy, Debug, Eq, PartialEq, Deserialize, Serialize)]
7#[serde(rename_all = "snake_case")]
8pub enum Anchor {
9 Newest,
11 Oldest,
13 FirstUnread,
15 #[serde(untagged)]
17 MessageId(u64),
18}
19
20impl Anchor {
21 pub const NEWEST: &str = "newest";
23 pub const OLDEST: &str = "oldest";
25 pub const FIRST_UNREAD: &str = "first_unread";
27
28 pub const fn new() -> Self {
30 Self::Newest
31 }
32
33 pub fn try_from_str(val: &str) -> Result<Self, Error> {
35 match val.to_lowercase().as_str() {
36 Self::NEWEST => Ok(Self::Newest),
37 Self::OLDEST => Ok(Self::Oldest),
38 Self::FIRST_UNREAD => Ok(Self::FirstUnread),
39 s => s
40 .parse::<u64>()
41 .map(Self::MessageId)
42 .map_err(|err| Error::io_other(format!("{err}"))),
43 }
44 }
45}
46
47impl Default for Anchor {
48 fn default() -> Self {
49 Self::new()
50 }
51}
52
53impl From<Anchor> for String {
54 fn from(val: Anchor) -> Self {
55 val.to_string()
56 }
57}
58
59impl From<&Anchor> for String {
60 fn from(val: &Anchor) -> Self {
61 val.to_string()
62 }
63}
64
65impl TryFrom<&str> for Anchor {
66 type Error = Error;
67
68 fn try_from(val: &str) -> Result<Self, Self::Error> {
69 Self::try_from_str(val)
70 }
71}
72
73impl TryFrom<String> for Anchor {
74 type Error = Error;
75
76 fn try_from(val: String) -> Result<Self, Self::Error> {
77 Self::try_from_str(val.as_str())
78 }
79}
80
81impl std::fmt::Display for Anchor {
82 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
83 match self {
84 Self::Newest => write!(f, "{}", Self::NEWEST),
85 Self::Oldest => write!(f, "{}", Self::OLDEST),
86 Self::FirstUnread => write!(f, "{}", Self::FIRST_UNREAD),
87 Self::MessageId(id) => write!(f, "{id}"),
88 }
89 }
90}
91
92#[cfg(test)]
93mod tests {
94 use super::*;
95
96 #[test]
97 fn test_anchor_strings() {
98 [Anchor::Newest, Anchor::Oldest, Anchor::FirstUnread]
99 .into_iter()
100 .for_each(|anchor| {
101 let anchor_json = format!(r#""{anchor}""#);
102
103 assert_eq!(serde_json::to_string(&anchor).unwrap(), anchor_json);
104 assert_eq!(
105 serde_json::from_str::<Anchor>(&anchor_json).unwrap(),
106 anchor
107 );
108 });
109 }
110
111 #[test]
112 fn test_anchor_ints() {
113 (0..=u64::BITS)
114 .map(|r| Anchor::MessageId(((1u128 << r) - 1) as u64))
115 .for_each(|anchor| {
116 let anchor_json = anchor.to_string();
117
118 assert_eq!(serde_json::to_string(&anchor).unwrap(), anchor_json);
119 assert_eq!(
120 serde_json::from_str::<Anchor>(&anchor_json).unwrap(),
121 anchor
122 );
123 });
124 }
125}