subtle_encoding/
encoding.rs1#[cfg(feature = "alloc")]
4use alloc::{string::String, vec::Vec};
5#[cfg(feature = "std")]
6use std::{
7 fs::File,
8 io::{Read, Write},
9 path::Path,
10};
11#[cfg(all(unix, feature = "std"))]
12use std::{fs::OpenOptions, os::unix::fs::OpenOptionsExt};
13#[cfg(feature = "std")]
14use zeroize::Zeroize;
15
16use super::Error;
17
18#[cfg(unix)]
21pub const FILE_MODE: u32 = 0o600;
22
23pub trait Encoding: Send + Sync {
25 fn encode_to_slice(&self, src: &[u8], dst: &mut [u8]) -> Result<usize, Error>;
30
31 fn encoded_len(&self, bytes: &[u8]) -> usize;
33
34 #[cfg(feature = "alloc")]
36 fn encode<B: AsRef<[u8]>>(&self, bytes: B) -> Vec<u8> {
37 let expected_length = self.encoded_len(bytes.as_ref());
38 let mut encoded = vec![0u8; expected_length];
39
40 let actual_length = self.encode_to_slice(bytes.as_ref(), &mut encoded).unwrap();
41 debug_assert_eq!(expected_length, actual_length);
42
43 encoded
44 }
45
46 #[cfg(feature = "alloc")]
51 fn encode_to_string<B: AsRef<[u8]>>(&self, bytes: B) -> Result<String, Error> {
52 Ok(String::from_utf8(self.encode(bytes))?)
53 }
54
55 #[cfg(feature = "std")]
58 fn encode_to_writer<B, W>(&self, bytes: B, writer: &mut W) -> Result<usize, Error>
59 where
60 B: AsRef<[u8]>,
61 W: Write,
62 {
63 let mut encoded_bytes = self.encode(bytes);
64 writer.write_all(encoded_bytes.as_ref())?;
65 encoded_bytes.zeroize();
66 Ok(encoded_bytes.len())
67 }
68
69 #[cfg(all(unix, feature = "std"))]
76 fn encode_to_file<B, P>(&self, bytes: B, path: P) -> Result<File, Error>
77 where
78 B: AsRef<[u8]>,
79 P: AsRef<Path>,
80 {
81 let mut file = OpenOptions::new()
82 .create(true)
83 .write(true)
84 .truncate(true)
85 .mode(FILE_MODE)
86 .open(path)?;
87
88 self.encode_to_writer(bytes, &mut file)?;
89 Ok(file)
90 }
91
92 #[cfg(all(not(unix), feature = "std"))]
97 fn encode_to_file<B, P>(&self, bytes: B, path: P) -> Result<File, Error>
98 where
99 B: AsRef<[u8]>,
100 P: AsRef<Path>,
101 {
102 let mut file = File::create(path.as_ref())?;
103 self.encode_to_writer(bytes, &mut file)?;
104 Ok(file)
105 }
106
107 fn decode_to_slice(&self, src: &[u8], dst: &mut [u8]) -> Result<usize, Error>;
109
110 fn decoded_len(&self, encoded_bytes: &[u8]) -> Result<usize, Error>;
112
113 #[cfg(feature = "alloc")]
115 fn decode<B: AsRef<[u8]>>(&self, encoded_bytes: B) -> Result<Vec<u8>, Error> {
116 let expected_length = self.decoded_len(encoded_bytes.as_ref())?;
117 let mut decoded = vec![0u8; expected_length];
118
119 let actual_length = self.decode_to_slice(encoded_bytes.as_ref(), &mut decoded)?;
120 debug_assert_eq!(expected_length, actual_length);
121
122 Ok(decoded)
123 }
124
125 #[cfg(feature = "std")]
128 fn decode_from_str<S: AsRef<str>>(&self, encoded: S) -> Result<Vec<u8>, Error> {
129 self.decode(encoded.as_ref().as_bytes())
130 }
131
132 #[cfg(feature = "std")]
135 fn decode_from_reader<R: Read>(&self, reader: &mut R) -> Result<Vec<u8>, Error> {
136 let mut bytes = vec![];
137 reader.read_to_end(bytes.as_mut())?;
138 let result = self.decode(&bytes);
139 bytes.zeroize();
140 result
141 }
142
143 #[cfg(feature = "std")]
146 fn decode_from_file<P: AsRef<Path>>(&self, path: P) -> Result<Vec<u8>, Error> {
147 self.decode_from_reader(&mut File::open(path.as_ref())?)
148 }
149}
150
151#[cfg(feature = "alloc")]
153#[cfg(test)]
154mod tests {
155 use super::*;
156
157 const TEST_DATA: &[u8] = b"Testing 1, 2, 3...";
159
160 struct TestEncoding {}
162
163 impl Default for TestEncoding {
164 fn default() -> Self {
165 Self {}
166 }
167 }
168
169 impl Encoding for TestEncoding {
170 fn encode_to_slice(&self, src: &[u8], dst: &mut [u8]) -> Result<usize, Error> {
171 let length = self.encoded_len(src);
172 assert_eq!(dst.len(), length);
173 Ok(length)
174 }
175
176 fn encoded_len(&self, bytes: &[u8]) -> usize {
177 bytes.len() * 4 / 3
178 }
179
180 fn decode_to_slice(&self, src: &[u8], dst: &mut [u8]) -> Result<usize, Error> {
181 let length = self.decoded_len(src)?;
182 assert_eq!(dst.len(), length);
183 Ok(length)
184 }
185
186 fn decoded_len(&self, bytes: &[u8]) -> Result<usize, Error> {
187 Ok(bytes.len() * 3 / 4)
188 }
189 }
190
191 #[test]
193 fn test_encode() {
194 TestEncoding::default().encode(TEST_DATA);
195 }
196
197 #[test]
199 fn test_decode() {
200 let encoding = TestEncoding::default();
201 let encoded = encoding.encode(TEST_DATA);
202 encoding.decode(&encoded).unwrap();
203 }
204}