summaryrefslogtreecommitdiff
path: root/vendor/base64/src/encode.rs
diff options
context:
space:
mode:
authormo khan <mo@mokhan.ca>2025-07-15 16:37:08 -0600
committermo khan <mo@mokhan.ca>2025-07-17 16:30:22 -0600
commit45df4d0d9b577fecee798d672695fe24ff57fb1b (patch)
tree1b99bf645035b58e0d6db08c7a83521f41f7a75b /vendor/base64/src/encode.rs
parentf94f79608393d4ab127db63cc41668445ef6b243 (diff)
feat: migrate from Cedar to SpiceDB authorization system
This is a major architectural change that replaces the Cedar policy-based authorization system with SpiceDB's relation-based authorization. Key changes: - Migrate from Rust to Go implementation - Replace Cedar policies with SpiceDB schema and relationships - Switch from envoy `ext_authz` with Cedar to SpiceDB permission checks - Update build system and dependencies for Go ecosystem - Maintain Envoy integration for external authorization This change enables more flexible permission modeling through SpiceDB's Google Zanzibar inspired relation-based system, supporting complex hierarchical permissions that were difficult to express in Cedar. Breaking change: Existing Cedar policies and Rust-based configuration will no longer work and need to be migrated to SpiceDB schema.
Diffstat (limited to 'vendor/base64/src/encode.rs')
-rw-r--r--vendor/base64/src/encode.rs492
1 files changed, 0 insertions, 492 deletions
diff --git a/vendor/base64/src/encode.rs b/vendor/base64/src/encode.rs
deleted file mode 100644
index ae6d7907..00000000
--- a/vendor/base64/src/encode.rs
+++ /dev/null
@@ -1,492 +0,0 @@
-#[cfg(any(feature = "alloc", test))]
-use alloc::string::String;
-use core::fmt;
-#[cfg(any(feature = "std", test))]
-use std::error;
-
-#[cfg(any(feature = "alloc", test))]
-use crate::engine::general_purpose::STANDARD;
-use crate::engine::{Config, Engine};
-use crate::PAD_BYTE;
-
-/// Encode arbitrary octets as base64 using the [`STANDARD` engine](STANDARD).
-///
-/// See [Engine::encode].
-#[allow(unused)]
-#[deprecated(since = "0.21.0", note = "Use Engine::encode")]
-#[cfg(any(feature = "alloc", test))]
-pub fn encode<T: AsRef<[u8]>>(input: T) -> String {
- STANDARD.encode(input)
-}
-
-///Encode arbitrary octets as base64 using the provided `Engine` into a new `String`.
-///
-/// See [Engine::encode].
-#[allow(unused)]
-#[deprecated(since = "0.21.0", note = "Use Engine::encode")]
-#[cfg(any(feature = "alloc", test))]
-pub fn encode_engine<E: Engine, T: AsRef<[u8]>>(input: T, engine: &E) -> String {
- engine.encode(input)
-}
-
-///Encode arbitrary octets as base64 into a supplied `String`.
-///
-/// See [Engine::encode_string].
-#[allow(unused)]
-#[deprecated(since = "0.21.0", note = "Use Engine::encode_string")]
-#[cfg(any(feature = "alloc", test))]
-pub fn encode_engine_string<E: Engine, T: AsRef<[u8]>>(
- input: T,
- output_buf: &mut String,
- engine: &E,
-) {
- engine.encode_string(input, output_buf)
-}
-
-/// Encode arbitrary octets as base64 into a supplied slice.
-///
-/// See [Engine::encode_slice].
-#[allow(unused)]
-#[deprecated(since = "0.21.0", note = "Use Engine::encode_slice")]
-pub fn encode_engine_slice<E: Engine, T: AsRef<[u8]>>(
- input: T,
- output_buf: &mut [u8],
- engine: &E,
-) -> Result<usize, EncodeSliceError> {
- engine.encode_slice(input, output_buf)
-}
-
-/// B64-encode and pad (if configured).
-///
-/// This helper exists to avoid recalculating encoded_size, which is relatively expensive on short
-/// inputs.
-///
-/// `encoded_size` is the encoded size calculated for `input`.
-///
-/// `output` must be of size `encoded_size`.
-///
-/// All bytes in `output` will be written to since it is exactly the size of the output.
-pub(crate) fn encode_with_padding<E: Engine + ?Sized>(
- input: &[u8],
- output: &mut [u8],
- engine: &E,
- expected_encoded_size: usize,
-) {
- debug_assert_eq!(expected_encoded_size, output.len());
-
- let b64_bytes_written = engine.internal_encode(input, output);
-
- let padding_bytes = if engine.config().encode_padding() {
- add_padding(b64_bytes_written, &mut output[b64_bytes_written..])
- } else {
- 0
- };
-
- let encoded_bytes = b64_bytes_written
- .checked_add(padding_bytes)
- .expect("usize overflow when calculating b64 length");
-
- debug_assert_eq!(expected_encoded_size, encoded_bytes);
-}
-
-/// Calculate the base64 encoded length for a given input length, optionally including any
-/// appropriate padding bytes.
-///
-/// Returns `None` if the encoded length can't be represented in `usize`. This will happen for
-/// input lengths in approximately the top quarter of the range of `usize`.
-pub const fn encoded_len(bytes_len: usize, padding: bool) -> Option<usize> {
- let rem = bytes_len % 3;
-
- let complete_input_chunks = bytes_len / 3;
- // `?` is disallowed in const, and `let Some(_) = _ else` requires 1.65.0, whereas this
- // messier syntax works on 1.48
- let complete_chunk_output =
- if let Some(complete_chunk_output) = complete_input_chunks.checked_mul(4) {
- complete_chunk_output
- } else {
- return None;
- };
-
- if rem > 0 {
- if padding {
- complete_chunk_output.checked_add(4)
- } else {
- let encoded_rem = match rem {
- 1 => 2,
- // only other possible remainder is 2
- // can't use a separate _ => unreachable!() in const fns in ancient rust versions
- _ => 3,
- };
- complete_chunk_output.checked_add(encoded_rem)
- }
- } else {
- Some(complete_chunk_output)
- }
-}
-
-/// Write padding characters.
-/// `unpadded_output_len` is the size of the unpadded but base64 encoded data.
-/// `output` is the slice where padding should be written, of length at least 2.
-///
-/// Returns the number of padding bytes written.
-pub(crate) fn add_padding(unpadded_output_len: usize, output: &mut [u8]) -> usize {
- let pad_bytes = (4 - (unpadded_output_len % 4)) % 4;
- // for just a couple bytes, this has better performance than using
- // .fill(), or iterating over mutable refs, which call memset()
- #[allow(clippy::needless_range_loop)]
- for i in 0..pad_bytes {
- output[i] = PAD_BYTE;
- }
-
- pad_bytes
-}
-
-/// Errors that can occur while encoding into a slice.
-#[derive(Clone, Debug, PartialEq, Eq)]
-pub enum EncodeSliceError {
- /// The provided slice is too small.
- OutputSliceTooSmall,
-}
-
-impl fmt::Display for EncodeSliceError {
- fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
- match self {
- Self::OutputSliceTooSmall => write!(f, "Output slice too small"),
- }
- }
-}
-
-#[cfg(any(feature = "std", test))]
-impl error::Error for EncodeSliceError {}
-
-#[cfg(test)]
-mod tests {
- use super::*;
-
- use crate::{
- alphabet,
- engine::general_purpose::{GeneralPurpose, NO_PAD, STANDARD},
- tests::{assert_encode_sanity, random_config, random_engine},
- };
- use rand::{
- distributions::{Distribution, Uniform},
- Rng, SeedableRng,
- };
- use std::str;
-
- const URL_SAFE_NO_PAD_ENGINE: GeneralPurpose = GeneralPurpose::new(&alphabet::URL_SAFE, NO_PAD);
-
- #[test]
- fn encoded_size_correct_standard() {
- assert_encoded_length(0, 0, &STANDARD, true);
-
- assert_encoded_length(1, 4, &STANDARD, true);
- assert_encoded_length(2, 4, &STANDARD, true);
- assert_encoded_length(3, 4, &STANDARD, true);
-
- assert_encoded_length(4, 8, &STANDARD, true);
- assert_encoded_length(5, 8, &STANDARD, true);
- assert_encoded_length(6, 8, &STANDARD, true);
-
- assert_encoded_length(7, 12, &STANDARD, true);
- assert_encoded_length(8, 12, &STANDARD, true);
- assert_encoded_length(9, 12, &STANDARD, true);
-
- assert_encoded_length(54, 72, &STANDARD, true);
-
- assert_encoded_length(55, 76, &STANDARD, true);
- assert_encoded_length(56, 76, &STANDARD, true);
- assert_encoded_length(57, 76, &STANDARD, true);
-
- assert_encoded_length(58, 80, &STANDARD, true);
- }
-
- #[test]
- fn encoded_size_correct_no_pad() {
- assert_encoded_length(0, 0, &URL_SAFE_NO_PAD_ENGINE, false);
-
- assert_encoded_length(1, 2, &URL_SAFE_NO_PAD_ENGINE, false);
- assert_encoded_length(2, 3, &URL_SAFE_NO_PAD_ENGINE, false);
- assert_encoded_length(3, 4, &URL_SAFE_NO_PAD_ENGINE, false);
-
- assert_encoded_length(4, 6, &URL_SAFE_NO_PAD_ENGINE, false);
- assert_encoded_length(5, 7, &URL_SAFE_NO_PAD_ENGINE, false);
- assert_encoded_length(6, 8, &URL_SAFE_NO_PAD_ENGINE, false);
-
- assert_encoded_length(7, 10, &URL_SAFE_NO_PAD_ENGINE, false);
- assert_encoded_length(8, 11, &URL_SAFE_NO_PAD_ENGINE, false);
- assert_encoded_length(9, 12, &URL_SAFE_NO_PAD_ENGINE, false);
-
- assert_encoded_length(54, 72, &URL_SAFE_NO_PAD_ENGINE, false);
-
- assert_encoded_length(55, 74, &URL_SAFE_NO_PAD_ENGINE, false);
- assert_encoded_length(56, 75, &URL_SAFE_NO_PAD_ENGINE, false);
- assert_encoded_length(57, 76, &URL_SAFE_NO_PAD_ENGINE, false);
-
- assert_encoded_length(58, 78, &URL_SAFE_NO_PAD_ENGINE, false);
- }
-
- #[test]
- fn encoded_size_overflow() {
- assert_eq!(None, encoded_len(usize::MAX, true));
- }
-
- #[test]
- fn encode_engine_string_into_nonempty_buffer_doesnt_clobber_prefix() {
- let mut orig_data = Vec::new();
- let mut prefix = String::new();
- let mut encoded_data_no_prefix = String::new();
- let mut encoded_data_with_prefix = String::new();
- let mut decoded = Vec::new();
-
- let prefix_len_range = Uniform::new(0, 1000);
- let input_len_range = Uniform::new(0, 1000);
-
- let mut rng = rand::rngs::SmallRng::from_entropy();
-
- for _ in 0..10_000 {
- orig_data.clear();
- prefix.clear();
- encoded_data_no_prefix.clear();
- encoded_data_with_prefix.clear();
- decoded.clear();
-
- let input_len = input_len_range.sample(&mut rng);
-
- for _ in 0..input_len {
- orig_data.push(rng.gen());
- }
-
- let prefix_len = prefix_len_range.sample(&mut rng);
- for _ in 0..prefix_len {
- // getting convenient random single-byte printable chars that aren't base64 is
- // annoying
- prefix.push('#');
- }
- encoded_data_with_prefix.push_str(&prefix);
-
- let engine = random_engine(&mut rng);
- engine.encode_string(&orig_data, &mut encoded_data_no_prefix);
- engine.encode_string(&orig_data, &mut encoded_data_with_prefix);
-
- assert_eq!(
- encoded_data_no_prefix.len() + prefix_len,
- encoded_data_with_prefix.len()
- );
- assert_encode_sanity(
- &encoded_data_no_prefix,
- engine.config().encode_padding(),
- input_len,
- );
- assert_encode_sanity(
- &encoded_data_with_prefix[prefix_len..],
- engine.config().encode_padding(),
- input_len,
- );
-
- // append plain encode onto prefix
- prefix.push_str(&encoded_data_no_prefix);
-
- assert_eq!(prefix, encoded_data_with_prefix);
-
- engine
- .decode_vec(&encoded_data_no_prefix, &mut decoded)
- .unwrap();
- assert_eq!(orig_data, decoded);
- }
- }
-
- #[test]
- fn encode_engine_slice_into_nonempty_buffer_doesnt_clobber_suffix() {
- let mut orig_data = Vec::new();
- let mut encoded_data = Vec::new();
- let mut encoded_data_original_state = Vec::new();
- let mut decoded = Vec::new();
-
- let input_len_range = Uniform::new(0, 1000);
-
- let mut rng = rand::rngs::SmallRng::from_entropy();
-
- for _ in 0..10_000 {
- orig_data.clear();
- encoded_data.clear();
- encoded_data_original_state.clear();
- decoded.clear();
-
- let input_len = input_len_range.sample(&mut rng);
-
- for _ in 0..input_len {
- orig_data.push(rng.gen());
- }
-
- // plenty of existing garbage in the encoded buffer
- for _ in 0..10 * input_len {
- encoded_data.push(rng.gen());
- }
-
- encoded_data_original_state.extend_from_slice(&encoded_data);
-
- let engine = random_engine(&mut rng);
-
- let encoded_size = encoded_len(input_len, engine.config().encode_padding()).unwrap();
-
- assert_eq!(
- encoded_size,
- engine.encode_slice(&orig_data, &mut encoded_data).unwrap()
- );
-
- assert_encode_sanity(
- str::from_utf8(&encoded_data[0..encoded_size]).unwrap(),
- engine.config().encode_padding(),
- input_len,
- );
-
- assert_eq!(
- &encoded_data[encoded_size..],
- &encoded_data_original_state[encoded_size..]
- );
-
- engine
- .decode_vec(&encoded_data[0..encoded_size], &mut decoded)
- .unwrap();
- assert_eq!(orig_data, decoded);
- }
- }
-
- #[test]
- fn encode_to_slice_random_valid_utf8() {
- let mut input = Vec::new();
- let mut output = Vec::new();
-
- let input_len_range = Uniform::new(0, 1000);
-
- let mut rng = rand::rngs::SmallRng::from_entropy();
-
- for _ in 0..10_000 {
- input.clear();
- output.clear();
-
- let input_len = input_len_range.sample(&mut rng);
-
- for _ in 0..input_len {
- input.push(rng.gen());
- }
-
- let config = random_config(&mut rng);
- let engine = random_engine(&mut rng);
-
- // fill up the output buffer with garbage
- let encoded_size = encoded_len(input_len, config.encode_padding()).unwrap();
- for _ in 0..encoded_size {
- output.push(rng.gen());
- }
-
- let orig_output_buf = output.clone();
-
- let bytes_written = engine.internal_encode(&input, &mut output);
-
- // make sure the part beyond bytes_written is the same garbage it was before
- assert_eq!(orig_output_buf[bytes_written..], output[bytes_written..]);
-
- // make sure the encoded bytes are UTF-8
- let _ = str::from_utf8(&output[0..bytes_written]).unwrap();
- }
- }
-
- #[test]
- fn encode_with_padding_random_valid_utf8() {
- let mut input = Vec::new();
- let mut output = Vec::new();
-
- let input_len_range = Uniform::new(0, 1000);
-
- let mut rng = rand::rngs::SmallRng::from_entropy();
-
- for _ in 0..10_000 {
- input.clear();
- output.clear();
-
- let input_len = input_len_range.sample(&mut rng);
-
- for _ in 0..input_len {
- input.push(rng.gen());
- }
-
- let engine = random_engine(&mut rng);
-
- // fill up the output buffer with garbage
- let encoded_size = encoded_len(input_len, engine.config().encode_padding()).unwrap();
- for _ in 0..encoded_size + 1000 {
- output.push(rng.gen());
- }
-
- let orig_output_buf = output.clone();
-
- encode_with_padding(&input, &mut output[0..encoded_size], &engine, encoded_size);
-
- // make sure the part beyond b64 is the same garbage it was before
- assert_eq!(orig_output_buf[encoded_size..], output[encoded_size..]);
-
- // make sure the encoded bytes are UTF-8
- let _ = str::from_utf8(&output[0..encoded_size]).unwrap();
- }
- }
-
- #[test]
- fn add_padding_random_valid_utf8() {
- let mut output = Vec::new();
-
- let mut rng = rand::rngs::SmallRng::from_entropy();
-
- // cover our bases for length % 4
- for unpadded_output_len in 0..20 {
- output.clear();
-
- // fill output with random
- for _ in 0..100 {
- output.push(rng.gen());
- }
-
- let orig_output_buf = output.clone();
-
- let bytes_written = add_padding(unpadded_output_len, &mut output);
-
- // make sure the part beyond bytes_written is the same garbage it was before
- assert_eq!(orig_output_buf[bytes_written..], output[bytes_written..]);
-
- // make sure the encoded bytes are UTF-8
- let _ = str::from_utf8(&output[0..bytes_written]).unwrap();
- }
- }
-
- fn assert_encoded_length<E: Engine>(
- input_len: usize,
- enc_len: usize,
- engine: &E,
- padded: bool,
- ) {
- assert_eq!(enc_len, encoded_len(input_len, padded).unwrap());
-
- let mut bytes: Vec<u8> = Vec::new();
- let mut rng = rand::rngs::SmallRng::from_entropy();
-
- for _ in 0..input_len {
- bytes.push(rng.gen());
- }
-
- let encoded = engine.encode(&bytes);
- assert_encode_sanity(&encoded, padded, input_len);
-
- assert_eq!(enc_len, encoded.len());
- }
-
- #[test]
- fn encode_imap() {
- assert_eq!(
- &GeneralPurpose::new(&alphabet::IMAP_MUTF7, NO_PAD).encode(b"\xFB\xFF"),
- &GeneralPurpose::new(&alphabet::STANDARD, NO_PAD)
- .encode(b"\xFB\xFF")
- .replace('/', ",")
- );
- }
-}