inflorescence_libpijul/
text_encoding.rs1use 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)]
48impl 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}