ruma_client_api/typing/
create_typing_event.rs1pub mod v3 {
6 use std::time::Duration;
11
12 use ruma_common::{
13 OwnedRoomId, OwnedUserId,
14 api::{auth_scheme::AccessToken, request, response},
15 metadata,
16 };
17 use serde::{Deserialize, Deserializer, Serialize, de::Error};
18
19 metadata! {
20 method: PUT,
21 authentication: AccessToken,
22 rate_limited: true,
23 history: {
24 1.0 => "/_matrix/client/r0/rooms/{room_id}/typing/{user_id}",
25 1.1 => "/_matrix/client/v3/rooms/{room_id}/typing/{user_id}",
26 }
27 }
28
29 #[request(error = crate::Error)]
31 pub struct Request {
32 #[ruma_api(path)]
34 pub room_id: OwnedRoomId,
35
36 #[ruma_api(path)]
38 pub user_id: OwnedUserId,
39
40 #[ruma_api(body)]
42 pub state: Typing,
43 }
44
45 #[response(error = crate::Error)]
47 #[derive(Default)]
48 pub struct Response {}
49
50 impl Request {
51 pub fn new(user_id: OwnedUserId, room_id: OwnedRoomId, state: Typing) -> Self {
53 Self { user_id, room_id, state }
54 }
55 }
56
57 impl Response {
58 pub fn new() -> Self {
60 Self {}
61 }
62 }
63
64 #[derive(Clone, Copy, Debug)]
66 #[allow(clippy::exhaustive_enums)]
67 pub enum Typing {
68 No,
70
71 Yes(TypingInfo),
73 }
74
75 impl From<TypingInfo> for Typing {
76 fn from(value: TypingInfo) -> Self {
77 Self::Yes(value)
78 }
79 }
80
81 #[derive(Clone, Copy, Debug)]
83 #[cfg_attr(not(ruma_unstable_exhaustive_types), non_exhaustive)]
84 pub struct TypingInfo {
85 pub timeout: Duration,
87 }
88
89 impl TypingInfo {
90 pub fn new(timeout: Duration) -> Self {
92 Self { timeout }
93 }
94 }
95
96 #[derive(Deserialize, Serialize)]
97 struct TypingSerdeRepr {
98 typing: bool,
99
100 #[serde(
101 with = "ruma_common::serde::duration::opt_ms",
102 default,
103 skip_serializing_if = "Option::is_none"
104 )]
105 timeout: Option<Duration>,
106 }
107
108 impl Serialize for Typing {
109 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
110 where
111 S: serde::Serializer,
112 {
113 let repr = match self {
114 Self::No => TypingSerdeRepr { typing: false, timeout: None },
115 Self::Yes(TypingInfo { timeout }) => {
116 TypingSerdeRepr { typing: true, timeout: Some(*timeout) }
117 }
118 };
119
120 repr.serialize(serializer)
121 }
122 }
123
124 impl<'de> Deserialize<'de> for Typing {
125 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
126 where
127 D: Deserializer<'de>,
128 {
129 let repr = TypingSerdeRepr::deserialize(deserializer)?;
130
131 Ok(if repr.typing {
132 Typing::Yes(TypingInfo {
133 timeout: repr.timeout.ok_or_else(|| D::Error::missing_field("timeout"))?,
134 })
135 } else {
136 Typing::No
137 })
138 }
139 }
140}