base_encoding/encode/
base64url.rs

1// Copyright 2017 ThetaSinner
2//
3// This file is part of base-encoding.
4//
5// base-encoding is free software: you can redistribute it and/or modify
6// it under the terms of the GNU General Public License as published by
7// the Free Software Foundation, either version 3 of the License, or
8// (at your option) any later version.
9//
10// base-encoding is distributed in the hope that it will be useful,
11// but WITHOUT ANY WARRANTY; without even the implied warranty of
12// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13// GNU General Public License for more details.
14//
15// You should have received a copy of the GNU General Public License
16// along with base-encoding. If not, see <http://www.gnu.org/licenses/>.
17
18const BASE_64_URL_ALPHABET: [u8; 64] = [
19    b'A', b'B', b'C', b'D', b'E', b'F', b'G', b'H', b'I', b'J', b'K', b'L', b'M', b'N', b'O', b'P', b'Q', b'R', b'S', b'T', b'U', b'V', b'W', b'X', b'Y', b'Z',
20    b'a', b'b', b'c', b'd', b'e', b'f', b'g', b'h', b'i', b'j', b'k', b'l', b'm', b'n', b'o', b'p', b'q', b'r', b's', b't', b'u', b'v', b'w', b'x', b'y', b'z',
21    b'0', b'1', b'2', b'3', b'4', b'5', b'6', b'7', b'8', b'9',
22    b'-', b'_'
23];
24
25const BASE_64_URL_MASK: usize = 0x3f;
26
27pub fn base64url(input: &[u8]) -> String {
28    let r = input.chunks(3).map(|x| {
29        match x.len() {
30            3 => {
31                let buf: u32 = 
32                    ((x[0] as u32) << 16) +
33                    ((x[1] as u32) << 8) +
34                    x[2] as u32;
35
36                [
37                    BASE_64_URL_ALPHABET[(buf >> 18) as usize],
38                    BASE_64_URL_ALPHABET[((buf >> 12) as usize) & BASE_64_URL_MASK],
39                    BASE_64_URL_ALPHABET[((buf >> 6) as usize) & BASE_64_URL_MASK],
40                    BASE_64_URL_ALPHABET[(buf as usize) & BASE_64_URL_MASK]
41                ].to_vec()
42            },
43            2 => {
44                let buf: u32 = 
45                    ((x[0] as u32) << 16) +
46                    ((x[1] as u32) << 8);
47
48                [
49                    BASE_64_URL_ALPHABET[(buf >> 18) as usize],
50                    BASE_64_URL_ALPHABET[((buf >> 12) as usize) & BASE_64_URL_MASK],
51                    BASE_64_URL_ALPHABET[((buf >> 6) as usize) & BASE_64_URL_MASK],
52                    b'='
53                ].to_vec()
54            },
55            1 => {
56                let buf: u32 = (x[0] as u32) << 16;
57
58                [
59                    BASE_64_URL_ALPHABET[(buf >> 18) as usize],
60                    BASE_64_URL_ALPHABET[((buf >> 12) as usize) & BASE_64_URL_MASK],
61                    b'=',
62                    b'='
63                ].to_vec()
64            }
65            _ => {
66                unreachable!("chunks 3");
67            }
68        }
69    }).fold(Vec::new(), |mut acc, x| {
70        acc.extend(x);
71        acc
72    });
73
74    String::from_utf8(r).unwrap()
75}