ruma_common/serde/
cow.rs

1use std::{borrow::Cow, str};
2
3use serde::de::{self, Deserializer, Unexpected, Visitor};
4
5/// Deserialize a `Cow<'de, str>`.
6///
7/// Different from serde's implementation of `Deserialize` for `Cow` since it borrows from the
8/// input when possible.
9///
10/// This will become unnecessary if Rust gains lifetime specialization at some point; see
11/// <https://github.com/serde-rs/serde/issues/1497#issuecomment-716246686>.
12pub fn deserialize_cow_str<'de, D>(deserializer: D) -> Result<Cow<'de, str>, D::Error>
13where
14    D: Deserializer<'de>,
15{
16    deserializer.deserialize_string(CowStrVisitor)
17}
18
19struct CowStrVisitor;
20
21impl<'de> Visitor<'de> for CowStrVisitor {
22    type Value = Cow<'de, str>;
23
24    fn expecting(&self, formatter: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
25        formatter.write_str("a string")
26    }
27
28    fn visit_borrowed_str<E>(self, v: &'de str) -> Result<Self::Value, E>
29    where
30        E: de::Error,
31    {
32        Ok(Cow::Borrowed(v))
33    }
34
35    fn visit_borrowed_bytes<E>(self, v: &'de [u8]) -> Result<Self::Value, E>
36    where
37        E: de::Error,
38    {
39        match str::from_utf8(v) {
40            Ok(s) => Ok(Cow::Borrowed(s)),
41            Err(_) => Err(de::Error::invalid_value(Unexpected::Bytes(v), &self)),
42        }
43    }
44
45    fn visit_str<E>(self, v: &str) -> Result<Self::Value, E>
46    where
47        E: de::Error,
48    {
49        Ok(Cow::Owned(v.to_owned()))
50    }
51
52    fn visit_string<E>(self, v: String) -> Result<Self::Value, E>
53    where
54        E: de::Error,
55    {
56        Ok(Cow::Owned(v))
57    }
58
59    fn visit_bytes<E>(self, v: &[u8]) -> Result<Self::Value, E>
60    where
61        E: de::Error,
62    {
63        match str::from_utf8(v) {
64            Ok(s) => Ok(Cow::Owned(s.to_owned())),
65            Err(_) => Err(de::Error::invalid_value(Unexpected::Bytes(v), &self)),
66        }
67    }
68
69    fn visit_byte_buf<E>(self, v: Vec<u8>) -> Result<Self::Value, E>
70    where
71        E: de::Error,
72    {
73        match String::from_utf8(v) {
74            Ok(s) => Ok(Cow::Owned(s)),
75            Err(e) => Err(de::Error::invalid_value(Unexpected::Bytes(&e.into_bytes()), &self)),
76        }
77    }
78}