Skip to main content

inflorescence_libpijul/
text_encoding.rs

1use serde::{de::Visitor, Deserialize, Serialize};
2#[cfg(feature = "text-changes")]
3use std::borrow::Cow;
4use std::fmt;
5
6#[cfg(test)]
7use quickcheck::{Arbitrary, Gen};
8
9#[derive(Debug, PartialEq, Eq)]
10pub struct Encoding(pub &'static encoding_rs::Encoding);
11
12impl Encoding {
13    pub(crate) fn for_label(label: &str) -> Encoding {
14        Encoding(encoding_rs::Encoding::for_label_no_replacement(label.as_bytes()).unwrap())
15    }
16
17    pub(crate) fn label(&self) -> &str {
18        self.0.name()
19    }
20
21    #[cfg(feature = "text-changes")]
22    pub fn decode<'a>(&self, text: &'a [u8]) -> Cow<'a, str> {
23        self.0.decode(&text).0
24    }
25
26    #[cfg(feature = "text-changes")]
27    pub(crate) fn encode<'a>(&self, text: &'a str) -> Cow<'a, [u8]> {
28        self.0.encode(text).0
29    }
30}
31
32impl Clone for Encoding {
33    fn clone(&self) -> Self {
34        Encoding(self.0)
35    }
36}
37
38impl Serialize for Encoding {
39    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
40    where
41        S: serde::Serializer,
42    {
43        serializer.serialize_str(self.label())
44    }
45}
46
47#[cfg(test)]
48// TODO: more encodings. This is not critical, since it is not used ATM.
49// But the instance is needed.
50impl Arbitrary for Encoding {
51    fn arbitrary(g: &mut Gen) -> Self {
52        g.choose(&[
53            Encoding(encoding_rs::UTF_8),
54            Encoding(encoding_rs::SHIFT_JIS),
55        ])
56        .unwrap()
57        .clone()
58    }
59}
60
61struct EncodingVisitor;
62
63impl<'de> Visitor<'de> for EncodingVisitor {
64    type Value = Encoding;
65
66    fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
67        formatter.write_str("a string label meeting the encoding standard https://encoding.spec.whatwg.org/#concept-encoding-get")
68    }
69
70    fn visit_str<E>(self, v: &str) -> Result<Self::Value, E>
71    where
72        E: serde::de::Error,
73    {
74        Ok(Encoding::for_label(v))
75    }
76}
77
78impl<'de> Deserialize<'de> for Encoding {
79    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
80    where
81        D: serde::Deserializer<'de>,
82    {
83        deserializer.deserialize_str(EncodingVisitor)
84    }
85}