ruma_client_api/state/
get_state_event_for_key.rs1pub mod v3 {
6 #[cfg(feature = "client")]
11 use ruma_common::api::EmptyBody;
12 use ruma_common::{
13 OwnedRoomId,
14 api::{auth_scheme::AccessToken, error::Error, response},
15 metadata,
16 serde::{Raw, StringEnum},
17 };
18 use ruma_events::{AnyStateEvent, AnyStateEventContent, StateEventType};
19 use serde_json::value::RawValue as RawJsonValue;
20
21 use crate::PrivOwnedStr;
22
23 metadata! {
24 method: GET,
25 rate_limited: false,
26 authentication: AccessToken,
27 history: {
28 1.0 => "/_matrix/client/r0/rooms/{room_id}/state/{event_type}/{state_key}",
29 1.1 => "/_matrix/client/v3/rooms/{room_id}/state/{event_type}/{state_key}",
30 }
31 }
32
33 #[derive(Clone, Debug)]
35 #[cfg_attr(not(ruma_unstable_exhaustive_types), non_exhaustive)]
36 pub struct Request {
37 pub room_id: OwnedRoomId,
39
40 pub event_type: StateEventType,
42
43 pub state_key: String,
45
46 pub format: StateEventFormat,
48 }
49
50 impl Request {
51 pub fn new(room_id: OwnedRoomId, event_type: StateEventType, state_key: String) -> Self {
53 Self { room_id, event_type, state_key, format: StateEventFormat::default() }
54 }
55 }
56
57 #[doc = include_str!(concat!(env!("CARGO_MANIFEST_DIR"), "/src/doc/string_enum.md"))]
59 #[derive(Default, Clone, StringEnum)]
60 #[ruma_enum(rename_all = "lowercase")]
61 #[cfg_attr(not(ruma_unstable_exhaustive_types), non_exhaustive)]
62 pub enum StateEventFormat {
63 #[default]
67 Content,
68
69 Event,
72
73 #[doc(hidden)]
74 _Custom(PrivOwnedStr),
75 }
76
77 #[response]
83 pub struct Response {
84 #[ruma_api(body)]
86 pub event_or_content: Box<RawJsonValue>,
87 }
88
89 impl From<Raw<AnyStateEvent>> for Response {
90 fn from(value: Raw<AnyStateEvent>) -> Self {
91 Self { event_or_content: value.into_json() }
92 }
93 }
94
95 impl From<Raw<AnyStateEventContent>> for Response {
96 fn from(value: Raw<AnyStateEventContent>) -> Self {
97 Self { event_or_content: value.into_json() }
98 }
99 }
100
101 impl Response {
102 pub fn new(event_or_content: Box<RawJsonValue>) -> Self {
104 Self { event_or_content }
105 }
106
107 pub fn into_event(self) -> Raw<AnyStateEvent> {
112 Raw::from_json(self.event_or_content)
113 }
114
115 pub fn into_content(self) -> Raw<AnyStateEventContent> {
124 Raw::from_json(self.event_or_content)
125 }
126 }
127
128 #[cfg(feature = "client")]
129 impl ruma_common::api::OutgoingRequest for Request {
130 type Body = EmptyBody;
131 type EndpointError = Error;
132 type IncomingResponse = Response;
133
134 fn try_into_http_request_inner(
135 self,
136 base_url: &str,
137 considering: std::borrow::Cow<'_, ruma_common::api::SupportedVersions>,
138 ) -> Result<http::Request<EmptyBody>, ruma_common::api::error::IntoHttpError> {
139 use ruma_common::api::Metadata;
140
141 let Self { room_id, event_type, state_key, format } = self;
142
143 let query_string = serde_html_form::to_string(RequestQuery { format })?;
144
145 let http_request = http::Request::builder()
146 .method(Self::METHOD)
147 .uri(Self::make_endpoint_url(
148 considering,
149 base_url,
150 &[&room_id, &event_type, &state_key],
151 &query_string,
152 )?)
153 .body(EmptyBody)?;
154
155 Ok(http_request)
156 }
157 }
158
159 #[cfg(feature = "server")]
160 impl ruma_common::api::IncomingRequest for Request {
161 type EndpointError = Error;
162 type OutgoingResponse = Response;
163
164 fn try_from_http_request_inner(
165 request: http::Request<&[u8]>,
166 path_args: &[&str],
167 ) -> Result<Self, ruma_common::api::error::DeserializationError> {
168 let (room_id, event_type, state_key): (OwnedRoomId, StateEventType, String) =
171 if path_args.len() == 3 {
172 serde::Deserialize::deserialize(serde::de::value::SeqDeserializer::<
173 _,
174 serde::de::value::Error,
175 >::new(
176 path_args.iter().copied()
177 ))?
178 } else {
179 let (a, b) =
180 serde::Deserialize::deserialize(serde::de::value::SeqDeserializer::<
181 _,
182 serde::de::value::Error,
183 >::new(
184 path_args.iter().copied()
185 ))?;
186
187 (a, b, "".into())
188 };
189
190 let RequestQuery { format } =
191 serde_html_form::from_str(request.uri().query().unwrap_or(""))?;
192
193 Ok(Self { room_id, event_type, state_key, format })
194 }
195 }
196
197 #[derive(Debug)]
199 #[cfg_attr(feature = "client", derive(serde::Serialize))]
200 #[cfg_attr(feature = "server", derive(serde::Deserialize))]
201 struct RequestQuery {
202 #[serde(default, skip_serializing_if = "ruma_common::serde::is_default")]
204 format: StateEventFormat,
205 }
206}
207
208#[cfg(all(test, feature = "client"))]
209mod tests {
210 use ruma_common::api::IncomingResponseExt as _;
211 use ruma_events::room::name::RoomNameEventContent;
212 use serde_json::json;
213
214 use super::v3::Response;
215
216 #[test]
217 fn deserialize_response() {
218 let body = json!({
219 "name": "Nice room 🙂"
220 })
221 .to_string();
222 let response = http::Response::new(body.as_bytes());
223
224 let response = Response::try_from_http_response(response).unwrap();
225 let content =
226 response.into_content().deserialize_as_unchecked::<RoomNameEventContent>().unwrap();
227
228 assert_eq!(content.name, "Nice room 🙂");
229 }
230}