1
/*
2
 * Hurl (https://hurl.dev)
3
 * Copyright (C) 2024 Orange
4
 *
5
 * Licensed under the Apache License, Version 2.0 (the "License");
6
 * you may not use this file except in compliance with the License.
7
 * You may obtain a copy of the License at
8
 *
9
 *          http://www.apache.org/licenses/LICENSE-2.0
10
 *
11
 * Unless required by applicable law or agreed to in writing, software
12
 * distributed under the License is distributed on an "AS IS" BASIS,
13
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
 * See the License for the specific language governing permissions and
15
 * limitations under the License.
16
 *
17
 */
18
use crate::reader::Reader;
19

            
20
/// <https://en.wikipedia.org/wiki/Base64>
21
/// Test padding/no-padding
22
///
23
/// Encoded
24
/// YW55IGNhcm5hbCBwbGVhcw==    any carnal pleas   # [97, 110, 121, 32, 99, 97, 114, 110, 97, 108, 32, 112, 108, 101, 97, 115]
25
320
pub fn parse(reader: &mut Reader) -> Vec<u8> {
26
320
    let mut bytes = vec![];
27
320
    let mut buf = vec![]; // base64 text
28
    loop {
29
6335
        let pad = padding(reader);
30
6335
        if !pad.is_empty() {
31
70
            break;
32
        }
33
6265
        let save = reader.cursor();
34
6265
        match reader.read() {
35
            None => {
36
                break;
37
            }
38
            Some(' ') | Some('\n') | Some('\t') => {}
39
6265
            Some(c) => match value(c) {
40
                None => {
41
250
                    reader.seek(save);
42
250
                    break;
43
                }
44
6015
                Some(v) => {
45
6015
                    buf.push(v);
46
6015
                    if buf.len() == 4 {
47
1475
                        let bs = decode_four_chars(
48
1475
                            *buf.first().unwrap(),
49
1475
                            *buf.get(1).unwrap(),
50
1475
                            *buf.get(2).unwrap(),
51
1475
                            *buf.get(3).unwrap(),
52
1475
                        );
53
5900
                        for b in bs {
54
4425
                            bytes.push(b);
55
                        }
56
1475
                        buf = vec![];
57
                    }
58
                }
59
            },
60
        }
61
    }
62
320
    match buf.as_slice() {
63
55
        [c1, c2] => bytes.append(&mut decode_two_chars(*c1, *c2)),
64
        [c1, c2, c3] => bytes.append(&mut decode_three_chars(*c1, *c2, *c3)),
65
265
        _ => {}
66
    }
67
320
    bytes
68
}
69

            
70
6265
fn value(c: char) -> Option<i32> {
71
6265
    match c {
72
55
        'A' => Some(0),
73
15
        'B' => Some(1),
74
125
        'C' => Some(2),
75
55
        'D' => Some(3),
76
90
        'E' => Some(4),
77
15
        'F' => Some(5),
78
740
        'G' => Some(6),
79
15
        'H' => Some(7),
80
130
        'I' => Some(8),
81
15
        'J' => Some(9),
82
130
        'K' => Some(10),
83
15
        'L' => Some(11),
84
35
        'M' => Some(12),
85
70
        'N' => Some(13),
86
15
        'O' => Some(14),
87
15
        'P' => Some(15),
88
240
        'Q' => Some(16),
89
15
        'R' => Some(17),
90
200
        'S' => Some(18),
91
185
        'T' => Some(19),
92
70
        'U' => Some(20),
93
385
        'V' => Some(21),
94
15
        'W' => Some(22),
95
15
        'X' => Some(23),
96
15
        'Y' => Some(24),
97
185
        'Z' => Some(25),
98
40
        'a' => Some(26),
99
610
        'b' => Some(27),
100
15
        'c' => Some(28),
101
15
        'd' => Some(29),
102
15
        'e' => Some(30),
103
15
        'f' => Some(31),
104
255
        'g' => Some(32),
105
200
        'h' => Some(33),
106
15
        'i' => Some(34),
107
15
        'j' => Some(35),
108
15
        'k' => Some(36),
109
185
        'l' => Some(37),
110
125
        'm' => Some(38),
111
15
        'n' => Some(39),
112
15
        'o' => Some(40),
113
70
        'p' => Some(41),
114
15
        'q' => Some(42),
115
15
        'r' => Some(43),
116
200
        's' => Some(44),
117
15
        't' => Some(45),
118
185
        'u' => Some(46),
119
15
        'v' => Some(47),
120
15
        'w' => Some(48),
121
70
        'x' => Some(49),
122
200
        'y' => Some(50),
123
70
        'z' => Some(51),
124
15
        '0' => Some(52),
125
15
        '1' => Some(53),
126
200
        '2' => Some(54),
127
15
        '3' => Some(55),
128
15
        '4' => Some(56),
129
15
        '5' => Some(57),
130
15
        '6' => Some(58),
131
15
        '7' => Some(59),
132
200
        '8' => Some(60),
133
200
        '9' => Some(61),
134
15
        '+' => Some(62),
135
15
        '/' => Some(63),
136
250
        _ => None,
137
    }
138
}
139

            
140
6335
fn padding(reader: &mut Reader) -> String {
141
6335
    // consume padding can not fail
142
6335
    let mut buf = String::new();
143
    loop {
144
6475
        let save = reader.cursor();
145
6475
        match reader.read() {
146
140
            Some('=') => {
147
140
                buf.push('=');
148
            }
149
            _ => {
150
6335
                reader.seek(save);
151
6335
                break;
152
            }
153
        }
154
    }
155
6335
    buf
156
}
157

            
158
55
fn decode_two_chars(c1: i32, c2: i32) -> Vec<u8> {
159
55
    vec![((c1 << 2 & 255) + (c2 >> 4)) as u8]
160
}
161

            
162
fn decode_three_chars(c1: i32, c2: i32, c3: i32) -> Vec<u8> {
163
    vec![
164
        ((c1 << 2 & 255) + (c2 >> 4)) as u8,
165
        ((c2 << 4 & 255) + (c3 >> 2)) as u8,
166
    ]
167
}
168

            
169
1475
fn decode_four_chars(c1: i32, c2: i32, c3: i32, c4: i32) -> Vec<u8> {
170
1475
    vec![
171
1475
        ((c1 << 2 & 255) + (c2 >> 4)) as u8,
172
1475
        ((c2 << 4 & 255) + (c3 >> 2)) as u8,
173
1475
        (((c3 << 6) & 255) + c4) as u8,
174
1475
    ]
175
}
176

            
177
#[cfg(test)]
178
mod tests {
179
    use super::*;
180

            
181
    #[test]
182
    fn test_decode_one_block() {
183
        let mut reader = Reader::new("");
184
        assert_eq!(parse(&mut reader), vec![] as Vec<u8>);
185
        assert_eq!(reader.cursor().index, 0);
186

            
187
        let mut reader = Reader::new("AA==;");
188
        assert_eq!(parse(&mut reader), vec![0]);
189
        assert_eq!(reader.cursor().index, 4);
190

            
191
        let mut reader = Reader::new("AA");
192
        assert_eq!(parse(&mut reader), vec![0]);
193
        assert_eq!(reader.cursor().index, 2);
194

            
195
        let mut reader = Reader::new("AA;");
196
        assert_eq!(parse(&mut reader), vec![0]);
197
        assert_eq!(reader.cursor().index, 2);
198

            
199
        let mut reader = Reader::new("TWE=;");
200
        assert_eq!(parse(&mut reader), vec![77, 97]);
201
        assert_eq!(reader.cursor().index, 4);
202

            
203
        let mut reader = Reader::new("TWFu;");
204
        assert_eq!(parse(&mut reader), vec![77, 97, 110]);
205
        assert_eq!(reader.cursor().index, 4);
206
    }
207

            
208
    /*
209
    |   Y       |     W     |     5     |     5     |
210
    |     24    |    22     |      57   |     57    |
211
    |0|1|1|0|0|0|0|1|0|1|1|0|1|1|1|0|0|1|1|1|1|0|0|1|
212
    |      97       |     110       |      121      |
213
    */
214

            
215
    /*
216
    |   Y       |     W     |     5     |     5     |
217
    |     24    |    22     |      57   |     57    |
218
    |0|1|1|0|0|0|0|1|0|1|1|0|1|1|1|0|0|1|1|1|1|0|0|1|
219
    |      97       |     110       |      121      |
220
    */
221

            
222
    #[test]
223
    fn test_decode_with_padding() {
224
        let mut reader = Reader::new("YW55IGNhcm5hbCBwbGVhcw==;");
225
        let decoded = parse(&mut reader);
226
        assert_eq!(decoded, b"any carnal pleas");
227

            
228
        let mut reader = Reader::new("YW55IGNhcm5hbCBwbGVhc3U=;");
229
        assert_eq!(parse(&mut reader), b"any carnal pleasu");
230

            
231
        let mut reader = Reader::new("YW55IGNhcm5hbCBwbGVhc3Vy;");
232
        assert_eq!(parse(&mut reader), b"any carnal pleasur");
233
    }
234

            
235
    #[test]
236
    fn test_decode_without_padding() {
237
        let mut reader = Reader::new("YW55IGNhcm5hbCBwbGVhcw;");
238
        assert_eq!(parse(&mut reader), b"any carnal pleas");
239

            
240
        let mut reader = Reader::new("YW55IGNhcm5hbCBwbGVhc3U;");
241
        assert_eq!(parse(&mut reader), b"any carnal pleasu");
242
    }
243

            
244
    #[test]
245
    fn test_decode_with_whitespace() {
246
        let mut reader = Reader::new("TW E=\n;");
247
        assert_eq!(parse(&mut reader), vec![77, 97]);
248
        assert_eq!(reader.cursor().index, 5);
249
    }
250

            
251
    #[test]
252
    fn test_decode_two_chars() {
253
        assert_eq!(
254
            decode_two_chars(value('A').unwrap(), value('A').unwrap()),
255
            vec![0]
256
        );
257
        assert_eq!(
258
            decode_two_chars(value('A').unwrap(), value('Q').unwrap()),
259
            vec![1]
260
        );
261
        assert_eq!(
262
            decode_two_chars(value('T').unwrap(), value('Q').unwrap()),
263
            vec![77]
264
        );
265
    }
266

            
267
    #[test]
268
    fn test_decode_three_chars() {
269
        assert_eq!(
270
            decode_three_chars(
271
                value('T').unwrap(),
272
                value('W').unwrap(),
273
                value('E').unwrap(),
274
            ),
275
            vec![77, 97]
276
        );
277
    }
278

            
279
    #[test]
280
    fn test_decode_four_chars() {
281
        assert_eq!(
282
            decode_four_chars(
283
                value('Y').unwrap(),
284
                value('W').unwrap(),
285
                value('5').unwrap(),
286
                value('5').unwrap(),
287
            ),
288
            vec![97, 110, 121]
289
        );
290
        assert_eq!(
291
            decode_four_chars(
292
                value('T').unwrap(),
293
                value('W').unwrap(),
294
                value('F').unwrap(),
295
                value('u').unwrap(),
296
            ),
297
            vec![77, 97, 110]
298
        );
299
    }
300
}