seaplane_cli/ops/
encoded_string.rs

1use std::{fmt, result::Result as StdResult};
2
3use base64::{alphabet, engine::fast_portable};
4use serde::{ser::Serializer, Serialize};
5
6use crate::error::Result;
7
8#[derive(Clone, PartialEq, Eq, Debug)]
9pub struct EncodedString(String);
10
11impl Serialize for EncodedString {
12    fn serialize<S: Serializer>(&self, serializer: S) -> StdResult<S::Ok, S::Error> {
13        self.to_string().serialize(serializer)
14    }
15}
16
17impl EncodedString {
18    pub fn new(s: String) -> Self { EncodedString(s) }
19
20    /// Decodes into binary format
21    pub fn decoded(&self) -> Result<Vec<u8>> {
22        let engine = fast_portable::FastPortable::from(&alphabet::URL_SAFE, fast_portable::NO_PAD);
23        Ok(base64::decode_engine(&self.0, &engine)?)
24    }
25
26    /// Decodes into display-safe format
27    pub fn decoded_safe(&self) -> Result<String> {
28        let engine = fast_portable::FastPortable::from(&alphabet::URL_SAFE, fast_portable::NO_PAD);
29        Ok(stfu8::encode_u8(&base64::decode_engine(&self.0, &engine)?))
30    }
31}
32
33impl Default for EncodedString {
34    fn default() -> Self { EncodedString("".to_owned()) }
35}
36
37impl fmt::Display for EncodedString {
38    // Bit of a footgun here, we "display" as Base64 regardless of encoding.
39    // Use direct writes for binary data.
40    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { write!(f, "{}", self.0) }
41}
42
43#[cfg(test)]
44mod tests {
45    use super::*;
46
47    fn bin() -> Vec<u8> { b"Hey\x01There".to_vec() }
48
49    fn base64() -> String { "SGV5AVRoZXJl".to_owned() }
50
51    #[test]
52    fn test_decode() -> Result<()> {
53        let decoded = EncodedString(base64()).decoded()?;
54        assert_eq!(decoded, bin());
55        Ok(())
56    }
57}