1//! Encoding and decoding utilities using the `encoding` crate.
2use std::fmt::Debug;
3
4use anyhow::{Error, Result};
5use encoding::Encoding;
6use serde::{Deserialize, de::Visitor};
7
8/// A wrapper around `encoding::Encoding` to implement `Send` and `Sync`.
9/// Since the reference is static, it is safe to send it across threads.
10pub struct EncodingWrapper(&'static dyn Encoding);
11
12impl Debug for EncodingWrapper {
13 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
14 f.debug_tuple("EncodingWrapper")
15 .field(&self.0.name())
16 .finish()
17 }
18}
19
20pub struct EncodingWrapperVisitor;
21
22impl<'vi> Visitor<'vi> for EncodingWrapperVisitor {
23 type Value = EncodingWrapper;
24
25 fn expecting(&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result {
26 formatter.write_str("a valid encoding name")
27 }
28
29 fn visit_str<E: serde::de::Error>(self, encoding: &str) -> Result<EncodingWrapper, E> {
30 Ok(EncodingWrapper(
31 encoding::label::encoding_from_whatwg_label(encoding)
32 .ok_or_else(|| serde::de::Error::custom("Invalid Encoding"))?,
33 ))
34 }
35
36 fn visit_string<E: serde::de::Error>(self, encoding: String) -> Result<EncodingWrapper, E> {
37 Ok(EncodingWrapper(
38 encoding::label::encoding_from_whatwg_label(&encoding)
39 .ok_or_else(|| serde::de::Error::custom("Invalid Encoding"))?,
40 ))
41 }
42}
43
44impl<'de> Deserialize<'de> for EncodingWrapper {
45 fn deserialize<D>(deserializer: D) -> std::result::Result<Self, D::Error>
46 where
47 D: serde::Deserializer<'de>,
48 {
49 deserializer.deserialize_str(EncodingWrapperVisitor)
50 }
51}
52
53impl PartialEq for EncodingWrapper {
54 fn eq(&self, other: &Self) -> bool {
55 self.0.name() == other.0.name()
56 }
57}
58
59unsafe impl Send for EncodingWrapper {}
60unsafe impl Sync for EncodingWrapper {}
61
62impl Clone for EncodingWrapper {
63 fn clone(&self) -> Self {
64 EncodingWrapper(self.0)
65 }
66}
67
68impl EncodingWrapper {
69 pub fn new(encoding: &'static dyn Encoding) -> EncodingWrapper {
70 EncodingWrapper(encoding)
71 }
72
73 pub async fn decode(&self, input: Vec<u8>) -> Result<String> {
74 match self.0.decode(&input, encoding::DecoderTrap::Replace) {
75 Ok(v) => Ok(v),
76 Err(e) => Err(Error::msg(e.to_string())),
77 }
78 }
79
80 pub async fn encode(&self, input: String) -> Result<Vec<u8>> {
81 match self.0.encode(&input, encoding::EncoderTrap::Replace) {
82 Ok(v) => Ok(v),
83 Err(e) => Err(Error::msg(e.to_string())),
84 }
85 }
86}
87
88/// Convert a byte vector from a specified encoding to a UTF-8 string.
89pub async fn to_utf8(input: Vec<u8>, encoding: EncodingWrapper) -> Result<String> {
90 encoding.decode(input).await
91}
92
93/// Convert a UTF-8 string to a byte vector in a specified encoding.
94pub async fn from_utf8(input: String, target: EncodingWrapper) -> Result<Vec<u8>> {
95 target.encode(input).await
96}