base64-url-3.0.0/.cargo_vcs_info.json0000644000000001360000000000100127200ustar { "git": { "sha1": "a344b879039cc96fa50b8fee9e5724329b1de489" }, "path_in_vcs": "" }base64-url-3.0.0/Cargo.toml0000644000000022060000000000100107160ustar # THIS FILE IS AUTOMATICALLY GENERATED BY CARGO # # When uploading crates to the registry Cargo will automatically # "normalize" Cargo.toml files for maximal compatibility # with all versions of Cargo and also rewrite `path` dependencies # to registry (e.g., crates.io) dependencies. # # If you are reading this file be aware that the original Cargo.toml # will likely look very different (and much more reasonable). # See Cargo.toml.orig for the original contents. [package] edition = "2021" rust-version = "1.57" name = "base64-url" version = "3.0.0" authors = ["Magic Len "] include = [ "src/**/*", "Cargo.toml", "README.md", "LICENSE", ] description = "Base64 encode, decode, escape and unescape for URL applications." homepage = "https://magiclen.org/base64-url" readme = "README.md" keywords = [ "decode", "base64", "encode", "utf8", "url", ] categories = [ "no-std", "encoding", ] license = "MIT" repository = "https://github.com/magiclen/base64-url" [dependencies.base64] version = "0.22" features = ["alloc"] default-features = false [features] default = ["std"] std = ["base64/std"] base64-url-3.0.0/Cargo.toml.orig000064400000000000000000000013001046102023000143710ustar 00000000000000[package] name = "base64-url" version = "3.0.0" authors = ["Magic Len "] edition = "2021" rust-version = "1.57" repository = "https://github.com/magiclen/base64-url" homepage = "https://magiclen.org/base64-url" keywords = ["decode", "base64", "encode", "utf8", "url"] categories = ["no-std", "encoding"] description = "Base64 encode, decode, escape and unescape for URL applications." license = "MIT" include = ["src/**/*", "Cargo.toml", "README.md", "LICENSE"] [dependencies] base64 = { version = "0.22", default-features = false, features = ["alloc"] } [features] default = ["std"] std = ["base64/std"] # Only for the `base64` crate itself. This crate doesn't use the `std` feature.base64-url-3.0.0/LICENSE000064400000000000000000000020661046102023000125210ustar 00000000000000MIT License Copyright (c) 2018 magiclen.org (Ron Li) Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. base64-url-3.0.0/README.md000064400000000000000000000033331046102023000127710ustar 00000000000000Base64 URL ==================== [![CI](https://github.com/magiclen/base64-url/actions/workflows/ci.yml/badge.svg)](https://github.com/magiclen/base64-url/actions/workflows/ci.yml) Base64 encode, decode, escape and unescape for URL applications. ## Examples Encode data to a Base64-URL string. ```rust assert_eq!("SGVsbG8sIHdvcmxkIQ", base64_url::encode("Hello, world!")); ``` Decode a Base64-URL string to data. ```rust assert_eq!(b"Hello, world!", base64_url::decode("SGVsbG8sIHdvcmxkIQ").unwrap().as_slice()); ``` Escape a Base64 string to a Base64-URL string. The conversion is not concerning with Base64 decoding. You need to make sure the input string is a correct Base64 string by yourself. ```rust assert_eq!("SGVsbG8sIHdvcmxkIQ", base64_url::escape("SGVsbG8sIHdvcmxkIQ==")); ``` Unescape a Base64-URL string to a Base64-URL string. The conversion is not concerning with Base64 decoding. You need to make sure the input string is a correct Base64-URL string by yourself. ```rust assert_eq!("SGVsbG8sIHdvcmxkIQ==", base64_url::unescape("SGVsbG8sIHdvcmxkIQ")); ``` Besides, you can also use other `encode_*`, `decode_*`, `escape_*`, `unescape_*` associated functions to deal with more specific cases. For example, ```rust let hash = &[1, 2, 3, 4, 5, 6, 7, 8, 9]; let mut url = String::from("https://example.com/?hash="); assert_eq!("AQIDBAUGBwgJ", base64_url::encode_to_string(hash, &mut url)); assert_eq!("https://example.com/?hash=AQIDBAUGBwgJ", url); ``` ## No Std Disable the default features to compile this crate without std. ```toml [dependencies.base64-url] version = "*" default-features = false ``` ## Crates.io https://crates.io/crates/base64-url ## Documentation https://docs.rs/base64-url ## License [MIT](LICENSE)base64-url-3.0.0/src/decode.rs000064400000000000000000000026331046102023000140740ustar 00000000000000use alloc::vec::Vec; use base64::Engine; /// Decode a Base64-URL string to data. #[inline] pub fn decode>(input: &T) -> Result, base64::DecodeError> { base64::engine::general_purpose::URL_SAFE_NO_PAD.decode(input) } /// Decode a Base64-URL string to data and directly store into a mutable `Vec` reference by concatenating them and return the slice of the decoded data. #[inline] pub fn decode_to_vec<'a, T: ?Sized + AsRef<[u8]>>( input: &T, output: &'a mut Vec, ) -> Result<&'a [u8], base64::DecodeSliceError> { let bytes = input.as_ref(); let current_length = output.len(); let original_max_length = ((bytes.len() + 3) >> 2) * 3; output.reserve(original_max_length); #[allow(clippy::uninit_vec)] unsafe { output.set_len(current_length + original_max_length); } let original_length = decode_to_slice(bytes, &mut output[current_length..])?.len(); unsafe { output.set_len(current_length + original_length); } Ok(&output[current_length..]) } /// Decode a Base64-URL string to data into a slice and return the slice with a valid length. #[inline] pub fn decode_to_slice<'a, T: ?Sized + AsRef<[u8]>>( input: &T, output: &'a mut [u8], ) -> Result<&'a [u8], base64::DecodeSliceError> { let length = base64::engine::general_purpose::URL_SAFE_NO_PAD.decode_slice(input, output)?; Ok(&output[..length]) } base64-url-3.0.0/src/encode.rs000064400000000000000000000035031046102023000141030ustar 00000000000000use alloc::{string::String, vec::Vec}; use core::str::from_utf8_unchecked; use base64::Engine; /// Encode data to a Base64-URL string. #[inline] pub fn encode>(input: &T) -> String { base64::engine::general_purpose::URL_SAFE_NO_PAD.encode(input) } /// Encode data to a Base64-URL string and directly store to a mutable `String` reference by concatenating them and return the slice of the Base64-URL string. It is usually for generating a URL. #[inline] pub fn encode_to_string<'a, T: ?Sized + AsRef<[u8]>>(input: &T, output: &'a mut String) -> &'a str { let base64_url = encode_to_vec(input, unsafe { output.as_mut_vec() }); unsafe { from_utf8_unchecked(base64_url) } } /// Encode data to Base64-URL data and directly store to a mutable `Vec` reference by concatenating them and return the slice of the Base64-URL data. It is usually for generating a URL. #[inline] pub fn encode_to_vec<'a, T: ?Sized + AsRef<[u8]>>(input: &T, output: &'a mut Vec) -> &'a [u8] { let bytes = input.as_ref(); let current_length = output.len(); let base64_length = ((bytes.len() << 2) + 2) / 3; output.reserve(base64_length); #[allow(clippy::uninit_vec)] unsafe { output.set_len(current_length + base64_length); } let base64_length = encode_to_slice(bytes, &mut output[current_length..]).unwrap().len(); unsafe { output.set_len(current_length + base64_length); } &output[current_length..] } /// Encode data to a Base64-URL string to a slice and return the slice with a valid length. #[inline] pub fn encode_to_slice<'a, T: ?Sized + AsRef<[u8]>>( input: &T, output: &'a mut [u8], ) -> Result<&'a [u8], base64::EncodeSliceError> { let length = base64::engine::general_purpose::URL_SAFE_NO_PAD.encode_slice(input, output)?; Ok(&output[..length]) } base64-url-3.0.0/src/escape.rs000064400000000000000000000122701046102023000141070ustar 00000000000000use alloc::{borrow::Cow, string::String, vec::Vec}; use core::str::from_utf8_unchecked; /// Escape a Base64 string to a Base64-URL string. The conversion is not concerning with Base64 decoding. You need to make sure the input string is a correct Base64 string by yourself. #[inline] pub fn escape>(base64: &S) -> Cow { let base64 = base64.as_ref(); match escape_u8_slice(base64) { Cow::Owned(base64_url) => { let base64_url = unsafe { String::from_utf8_unchecked(base64_url) }; Cow::from(base64_url) }, Cow::Borrowed(base64_url) => { let base64_url = unsafe { from_utf8_unchecked(base64_url) }; Cow::from(base64_url) }, } } /// Escape Base64 data to Base64-URL data. The conversion is not concerning with Base64 decoding. You need to make sure the input Base64 data is correct by yourself. #[inline] pub fn escape_u8_slice>(base64: &S) -> Cow<[u8]> { let base64 = base64.as_ref(); let length = base64.len(); let mut p = 0; let first = loop { if p == length { return Cow::from(base64); } let e = base64[p]; match e { 43 => { break 45; }, 47 => { break 95; }, 61 => { return Cow::from(&base64[..p]); }, _ => (), } p += 1; }; let mut base64_url = Vec::with_capacity(base64.len()); base64_url.extend_from_slice(&base64[..p]); base64_url.push(first); let mut start = p; p += 1; loop { if p == length { break; } let e = base64[p]; match e { 43 => { base64_url.extend_from_slice(&base64[start..p]); start = p + 1; base64_url.push(45); }, 47 => { base64_url.extend_from_slice(&base64[start..p]); start = p + 1; base64_url.push(95); }, 61 => break, _ => (), } p += 1; } base64_url.extend_from_slice(&base64[start..p]); Cow::from(base64_url) } /// In-place escape a Base64 string to a Base64-URL string. The conversion is not concerning with Base64 decoding. You need to make sure the input string is a correct Base64 string by yourself. #[inline] pub fn escape_in_place(base64: &mut String) -> &str { let v = unsafe { base64.as_mut_vec() }; escape_vec_in_place(v); base64.as_str() } /// In-place escape Base64 data to Base64-URL data. The conversion is not concerning with Base64 decoding. You need to make sure the input Base64 data is correct by yourself. #[inline] pub fn escape_vec_in_place(base64: &mut Vec) -> &[u8] { let length = escape_u8_slice_in_place(base64.as_mut_slice()).len(); unsafe { base64.set_len(length); } base64.as_slice() } /// In-place escape Base64 data to Base64-URL data. The conversion is not concerning with Base64 decoding. You need to make sure the input Base64 data is correct by yourself. #[inline] pub fn escape_u8_slice_in_place>(base64: &mut S) -> &[u8] { let base64 = base64.as_mut(); let mut len = base64.len(); for (index, n) in base64.iter_mut().enumerate() { match *n { 43 => *n = 45, 47 => *n = 95, 61 => { len = index; break; }, _ => (), } } &base64[..len] } #[deprecated(since = "1.3.0", note = "Please use the `escape_in_place` function instead")] /// Escape a Base64 string to a Base64-URL string. It is unsafe because the conversion is not concerning with Base64 decoding. You need to make sure the input string is a correct Base64 string by yourself. #[inline] pub fn unsafe_escape>(base64: S) -> String { let mut base64 = base64.into(); escape_in_place(&mut base64); base64 } #[deprecated(since = "1.3.0", note = "Please use the `escape_in_place` function instead")] /// In-place escape a Base64 string to a Base64-URL string. It is unsafe because the conversion is not concerning with Base64 decoding. You need to make sure the input string is a correct Base64 string by yourself. #[inline] pub fn unsafe_escape_string(base64: &mut String) { escape_in_place(base64); } #[deprecated(since = "1.3.0", note = "Please use the `escape_vec_in_place` function instead")] /// In-place escape Base64 data to Base64-URL data. It is unsafe because the conversion is not concerning with Base64 decoding. You need to make sure the input Base64 data is correct by yourself. #[inline] pub fn unsafe_escape_vec(base64: &mut Vec) { escape_vec_in_place(base64); } #[deprecated(since = "1.3.0", note = "Please use the `escape_u8_slice_in_place` function instead")] /// In-place escape Base64 data to Base64-URL data. It is unsafe because the conversion is not concerning with Base64 decoding. You need to make sure the input Base64 data is correct by yourself. #[inline] pub fn unsafe_escape_u8_slice>(base64: &mut S) -> &[u8] { escape_u8_slice_in_place(base64) } base64-url-3.0.0/src/lib.rs000064400000000000000000000032331046102023000134140ustar 00000000000000/*! # Base64 URL Base64 encode, decode, escape and unescape for URL applications. ## Examples Encode data to a Base64-URL string. ```rust assert_eq!("SGVsbG8sIHdvcmxkIQ", base64_url::encode("Hello, world!")); ``` Decode a Base64-URL string to data. ```rust assert_eq!(b"Hello, world!", base64_url::decode("SGVsbG8sIHdvcmxkIQ").unwrap().as_slice()); ``` Escape a Base64 string to a Base64-URL string. The conversion is not concerning with Base64 decoding. You need to make sure the input string is a correct Base64 string by yourself. ```rust assert_eq!("SGVsbG8sIHdvcmxkIQ", base64_url::escape("SGVsbG8sIHdvcmxkIQ==")); ``` Unescape a Base64-URL string to a Base64-URL string. The conversion is not concerning with Base64 decoding. You need to make sure the input string is a correct Base64-URL string by yourself. ```rust assert_eq!("SGVsbG8sIHdvcmxkIQ==", base64_url::unescape("SGVsbG8sIHdvcmxkIQ")); ``` Besides, you can also use other `encode_*`, `decode_*`, `escape_*`, `unescape_*` associated functions to deal with more specific cases. For example, ```rust let hash = &[1, 2, 3, 4, 5, 6, 7, 8, 9]; let mut url = String::from("https://example.com/?hash="); assert_eq!("AQIDBAUGBwgJ", base64_url::encode_to_string(hash, &mut url)); assert_eq!("https://example.com/?hash=AQIDBAUGBwgJ", url); ``` ## No Std Disable the default features to compile this crate without std. ```toml [dependencies.base64-url] version = "*" default-features = false ``` */ #![cfg_attr(not(feature = "std"), no_std)] extern crate alloc; pub extern crate base64; mod decode; mod encode; mod escape; mod unescape; pub use decode::*; pub use encode::*; pub use escape::*; pub use unescape::*; base64-url-3.0.0/src/unescape.rs000064400000000000000000000151541046102023000144560ustar 00000000000000use alloc::{borrow::Cow, string::String, vec::Vec}; use core::{mem::swap, str::from_utf8_unchecked}; /// Unescape a Base64-URL string to a Base64 string. The conversion is not concerning with Base64 decoding. You need to make sure the input string is a correct Base64-URL string by yourself. #[inline] pub fn unescape>(base64_url: &S) -> Cow { let base64_url = base64_url.as_ref(); match unescape_u8_slice(base64_url) { Cow::Owned(base64) => { let base64 = unsafe { String::from_utf8_unchecked(base64) }; Cow::from(base64) }, Cow::Borrowed(base64) => { let base64 = unsafe { from_utf8_unchecked(base64) }; Cow::from(base64) }, } } /// Unescape Base64-URL data to Base64 data. The conversion is not concerning with Base64 decoding. You need to make sure the input Base64-URL data is correct by yourself. pub fn unescape_u8_slice>(base64_url: &S) -> Cow<[u8]> { let base64_url = base64_url.as_ref(); let length = base64_url.len(); let padding = length & 0b11; if padding > 0 { let new_size = base64_url.len() + (4 - padding); let mut base64 = Vec::with_capacity(new_size); let mut p = 0; let mut start = 0; loop { if p == length { break; } let e = base64_url[p]; match e { 45 => { base64.extend_from_slice(&base64_url[start..p]); start = p + 1; base64.push(43); }, 95 => { base64.extend_from_slice(&base64_url[start..p]); start = p + 1; base64.push(47); }, _ => (), } p += 1; } base64.extend_from_slice(&base64_url[start..p]); base64.resize(new_size, 61); Cow::from(base64) } else { let mut p = 0; let first = loop { if p == length { return Cow::from(base64_url); } let e = base64_url[p]; match e { 45 => { break 43; }, 95 => { break 47; }, _ => (), } p += 1; }; let mut base64 = Vec::with_capacity(base64_url.len()); base64.extend_from_slice(&base64_url[..p]); base64.push(first); let mut start = p; p += 1; loop { if p == length { break; } let e = base64_url[p]; match e { 45 => { base64.extend_from_slice(&base64_url[start..p]); start = p + 1; base64.push(43); }, 95 => { base64.extend_from_slice(&base64_url[start..p]); start = p + 1; base64.push(47); }, _ => (), } p += 1; } base64.extend_from_slice(&base64_url[start..p]); Cow::from(base64) } } /// In-place unescape a Base64-URL string to a Base64 string. It is unsafe because the conversion is not concerning with Base64 decoding. You need to make sure the input string is a correct Base64-URL string by yourself. #[inline] pub fn unescape_in_place(base64_url: &mut String) -> &str { let v = unsafe { base64_url.as_mut_vec() }; unescape_vec_in_place(v); base64_url.as_str() } /// In-place unescape Base64-URL data to Base64 data. It is unsafe because the conversion is not concerning with Base64 decoding. You need to make sure the input Base64-URL data is correct by yourself. #[inline] pub fn unescape_vec_in_place(base64_url: &mut Vec) -> &[u8] { let base64 = unescape_u8_slice_try_in_place(base64_url.as_mut_slice()); if let Cow::Owned(mut base64) = base64 { swap(base64_url, &mut base64); } base64_url.as_slice() } /// Unescape Base64-URL data to Base64 data and try to do it in-place. It is unsafe because the conversion is not concerning with Base64 decoding. You need to make sure the input Base64-URL data is correct by yourself. #[inline] pub fn unescape_u8_slice_try_in_place>(base64_url: &mut S) -> Cow<[u8]> { let base64_url = base64_url.as_mut(); for n in base64_url.iter_mut() { match *n { 45 => *n = 43, 95 => *n = 47, _ => (), } } let padding = base64_url.len() & 0b11; if padding > 0 { let mut base64_url_vec = base64_url.to_vec(); let new_size = base64_url.len() + (4 - padding); base64_url_vec.resize(new_size, 61); Cow::from(base64_url_vec) } else { Cow::from(base64_url as &[u8]) } } #[deprecated(since = "1.3.0", note = "Please use the `unescape_in_place` function instead")] /// Unescape a Base64-URL string to a Base64 string. It is unsafe because the conversion is not concerning with Base64 decoding. You need to make sure the input string is a correct Base64-URL string by yourself. #[inline] pub fn unsafe_unescape>(base64_url: S) -> String { let mut base64_url = base64_url.into(); unescape_in_place(&mut base64_url); base64_url } #[deprecated(since = "1.3.0", note = "Please use the `unescape_in_place` function instead")] /// In-place unescape a Base64-URL string to a Base64 string. It is unsafe because the conversion is not concerning with Base64 decoding. You need to make sure the input string is a correct Base64-URL string by yourself. #[inline] pub fn unsafe_unescape_string(base64_url: &mut String) { unescape_in_place(base64_url); } #[deprecated(since = "1.3.0", note = "Please use the `unescape_vec_in_place` function instead")] /// In-place unescape Base64-URL data to Base64 data. It is unsafe because the conversion is not concerning with Base64 decoding. You need to make sure the input Base64-URL data is correct by yourself. pub fn unsafe_unescape_vec(base64_url: &mut Vec) { unescape_vec_in_place(base64_url); } #[deprecated( since = "1.3.0", note = "Please use the `unescape_u8_slice_try_in_place` function instead" )] /// Unescape Base64-URL data to Base64 data. It is unsafe because the conversion is not concerning with Base64 decoding. You need to make sure the input Base64-URL data is correct by yourself. pub fn unsafe_unescape_u8_slice>(base64_url: &mut S) -> Cow<[u8]> { unescape_u8_slice_try_in_place(base64_url) }