File: base64.rs

package info (click to toggle)
firefox 147.0.3-1
  • links: PTS, VCS
  • area: main
  • in suites: sid
  • size: 4,683,320 kB
  • sloc: cpp: 7,607,359; javascript: 6,533,295; ansic: 3,775,223; python: 1,415,500; xml: 634,561; asm: 438,949; java: 186,241; sh: 62,752; makefile: 18,079; objc: 13,092; perl: 12,808; yacc: 4,583; cs: 3,846; pascal: 3,448; lex: 1,720; ruby: 1,003; php: 436; lisp: 258; awk: 247; sql: 66; sed: 54; csh: 10; exp: 6
file content (146 lines) | stat: -rw-r--r-- 4,979 bytes parent folder | download | duplicates (3)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
//! ron initially encoded byte-slices and byte-bufs as base64-encoded strings.
//! However, since v0.9, ron now uses Rusty byte string literals instead.
//!
//! This example shows how the previous behaviour can be restored by serialising
//! bytes with strongly-typed base64-encoded strings, or accepting both Rusty
//! byte strings and the legacy base64-encoded string syntax.

use base64::engine::{general_purpose::STANDARD as BASE64, Engine};
use serde::{de::Visitor, Deserialize, Deserializer, Serialize, Serializer};

#[derive(Debug, PartialEq, Serialize, Deserialize)]
struct Config {
    #[serde(with = "ByteStr")]
    bytes: Vec<u8>,
    #[serde(with = "Base64")]
    base64: Vec<u8>,
    #[serde(with = "ByteStrOrBase64")]
    bytes_or_base64: Vec<u8>,
}

enum ByteStr {}

impl ByteStr {
    fn serialize<S: Serializer>(data: &[u8], serializer: S) -> Result<S::Ok, S::Error> {
        serializer.serialize_bytes(data)
    }

    fn deserialize<'de, D: Deserializer<'de>>(deserializer: D) -> Result<Vec<u8>, D::Error> {
        struct ByteStrVisitor;

        impl<'de> Visitor<'de> for ByteStrVisitor {
            type Value = Vec<u8>;

            fn expecting(&self, fmt: &mut core::fmt::Formatter) -> core::fmt::Result {
                fmt.write_str("a Rusty byte string")
            }

            fn visit_bytes<E: serde::de::Error>(self, bytes: &[u8]) -> Result<Self::Value, E> {
                Ok(bytes.to_vec())
            }

            fn visit_byte_buf<E: serde::de::Error>(self, bytes: Vec<u8>) -> Result<Self::Value, E> {
                Ok(bytes)
            }
        }

        deserializer.deserialize_byte_buf(ByteStrVisitor)
    }
}

enum Base64 {}

impl Base64 {
    fn serialize<S: Serializer>(data: &[u8], serializer: S) -> Result<S::Ok, S::Error> {
        serializer.serialize_str(&BASE64.encode(data))
    }

    fn deserialize<'de, D: Deserializer<'de>>(deserializer: D) -> Result<Vec<u8>, D::Error> {
        let base64_str = <&str>::deserialize(deserializer)?;
        BASE64.decode(base64_str).map_err(serde::de::Error::custom)
    }
}

enum ByteStrOrBase64 {}

impl ByteStrOrBase64 {
    fn serialize<S: Serializer>(data: &[u8], serializer: S) -> Result<S::Ok, S::Error> {
        if cfg!(all()) {
            // either of these would work
            serializer.serialize_str(&BASE64.encode(data))
        } else {
            serializer.serialize_bytes(data)
        }
    }

    fn deserialize<'de, D: Deserializer<'de>>(deserializer: D) -> Result<Vec<u8>, D::Error> {
        struct ByteStrOrBase64Visitor;

        impl<'de> Visitor<'de> for ByteStrOrBase64Visitor {
            type Value = Vec<u8>;

            fn expecting(&self, fmt: &mut core::fmt::Formatter) -> core::fmt::Result {
                fmt.write_str("a Rusty byte string or a base64-encoded string")
            }

            fn visit_str<E: serde::de::Error>(self, base64_str: &str) -> Result<Self::Value, E> {
                BASE64.decode(base64_str).map_err(serde::de::Error::custom)
            }

            fn visit_bytes<E: serde::de::Error>(self, bytes: &[u8]) -> Result<Self::Value, E> {
                Ok(bytes.to_vec())
            }

            fn visit_byte_buf<E: serde::de::Error>(self, bytes: Vec<u8>) -> Result<Self::Value, E> {
                Ok(bytes)
            }
        }

        deserializer.deserialize_any(ByteStrOrBase64Visitor)
    }
}

fn main() {
    let ron = r#"Config(
        bytes: b"only byte strings are allowed",
        base64: "b25seSBiYXNlNjQtZW5jb2RlZCBzdHJpbmdzIGFyZSBhbGxvd2Vk",
        bytes_or_base64: b"both byte strings and base64-encoded strings work",
    )"#;

    assert_eq!(
        ron::from_str::<Config>(ron).unwrap(),
        Config {
            bytes: b"only byte strings are allowed".to_vec(),
            base64: b"only base64-encoded strings are allowed".to_vec(),
            bytes_or_base64: b"both byte strings and base64-encoded strings work".to_vec()
        }
    );

    let ron = r#"Config(
        bytes: b"only byte strings are allowed",
        base64: "b25seSBiYXNlNjQtZW5jb2RlZCBzdHJpbmdzIGFyZSBhbGxvd2Vk",
        bytes_or_base64: "Ym90aCBieXRlIHN0cmluZ3MgYW5kIGJhc2U2NC1lbmNvZGVkIHN0cmluZ3Mgd29yaw==",
    )"#;

    assert_eq!(
        ron::from_str::<Config>(ron).unwrap(),
        Config {
            bytes: b"only byte strings are allowed".to_vec(),
            base64: b"only base64-encoded strings are allowed".to_vec(),
            bytes_or_base64: b"both byte strings and base64-encoded strings work".to_vec()
        }
    );

    println!(
        "{}",
        ron::ser::to_string_pretty(
            &Config {
                bytes: b"only byte strings are allowed".to_vec(),
                base64: b"only base64-encoded strings are allowed".to_vec(),
                bytes_or_base64: b"both byte strings and base64-encoded strings work".to_vec()
            },
            ron::ser::PrettyConfig::default().struct_names(true)
        )
        .unwrap()
    );
}