Skip to content

Commit

Permalink
macros for defining alphabets again
Browse files Browse the repository at this point in the history
  • Loading branch information
rogusdev committed Dec 11, 2023
1 parent a148166 commit 1997656
Show file tree
Hide file tree
Showing 12 changed files with 177 additions and 103 deletions.
2 changes: 1 addition & 1 deletion d
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
#!/bin/fish
# https://stackoverflow.com/questions/61417452/how-to-get-a-feature-requirement-tag-in-the-documentation-generated-by-cargo-do#comment117282743_61417700
RUSTDOCFLAGS="--cfg docsrs" cargo +nightly doc --all-features
echo '*** http://localhost:5000/fast32/ ***'
caddy file-server --root ./target/doc --listen :5000
# http://localhost:5000/fast32/
36 changes: 32 additions & 4 deletions src/base32.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,12 +16,40 @@ pub use self::encode_bytes::{capacity_encode, encode, encode_into};
pub use self::encode_u128::{capacity_encode_u128, encode_u128, encode_u128_into};
pub use self::encode_u64::{capacity_encode_u64, encode_u64, encode_u64_into};

#[cfg(feature = "uuid")]
pub use self::uuid::{decode_uuid, encode_uuid, encode_uuid_into};

pub use self::alphabet::{Alphabet32Nopad, Alphabet32Padded};

/// Crockford Base32 (no padding)
///
/// [https://www.crockford.com/base32.html](https://www.crockford.com/base32.html)
pub use self::alphabet::CROCKFORD;

/// RFC 4648 Base32 normal, with padding
///
/// `"ABCDEFGHIJKLMNOPQRSTUVWXYZ234567"` and `'='`
///
/// [https://datatracker.ietf.org/doc/html/rfc4648#section-6](https://datatracker.ietf.org/doc/html/rfc4648#section-6)
pub use self::alphabet::RFC4648;
pub use self::alphabet::RFC4648_HEX;
pub use self::alphabet::RFC4648_HEX_NOPAD;

/// RFC 4648 Base32 normal, no padding
///
/// `"ABCDEFGHIJKLMNOPQRSTUVWXYZ234567"`
///
/// [https://datatracker.ietf.org/doc/html/rfc4648#section-6](https://datatracker.ietf.org/doc/html/rfc4648#section-6)
pub use self::alphabet::RFC4648_NOPAD;

#[cfg(feature = "uuid")]
pub use self::uuid::{decode_uuid, encode_uuid, encode_uuid_into};
/// RFC 4648 Base32 "hex" form, with padding
///
/// `"ABCDEFGHIJKLMNOPQRSTUVWXYZ234567"` and `'='`
///
/// [https://datatracker.ietf.org/doc/html/rfc4648#section-7](https://datatracker.ietf.org/doc/html/rfc4648#section-7)
pub use self::alphabet::RFC4648_HEX;

/// RFC 4648 Base32 "hex" form, no padding
///
/// `"0123456789ABCDEFGHIJKLMNOPQRSTUV"`
///
/// [https://datatracker.ietf.org/doc/html/rfc4648#section-7](https://datatracker.ietf.org/doc/html/rfc4648#section-7)
pub use self::alphabet::RFC4648_HEX_NOPAD;
80 changes: 42 additions & 38 deletions src/base32/alphabet.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@ use core::ptr::write;
#[cfg(feature = "uuid")]
use uuid::Uuid;

use crate::shared::{decoder_map, decoder_map_simple};
use crate::DecodeError;

use super::decode_bytes::{decode, decode_into};
Expand All @@ -16,46 +15,51 @@ use super::encode_u64::{encode_u64, encode_u64_into};
#[cfg(feature = "uuid")]
use super::uuid::{decode_uuid, encode_uuid, encode_uuid_into};

const ENC_CROCKFORD: &'static [u8; 32] = b"0123456789ABCDEFGHJKMNPQRSTVWXYZ";
const DEC_CROCKFORD: [u8; 256] = decoder_map(
ENC_CROCKFORD,
b"ILOabcdefghijklmnopqrstvwxyz",
b"110ABCDEFGH1JK1MN0PQRSTVWXYZ",
);
/// Crockford Base32 (no padding)
///
/// [https://www.crockford.com/base32.html](https://www.crockford.com/base32.html)
pub const CROCKFORD: Alphabet32Nopad = Alphabet32Nopad::new(ENC_CROCKFORD, &DEC_CROCKFORD);

const ENC_RFC4648: &'static [u8; 32] = b"ABCDEFGHIJKLMNOPQRSTUVWXYZ234567";
const DEC_RFC4648: [u8; 256] = decoder_map_simple(ENC_RFC4648);
/// RFC 4648 Base32 normal, with padding
/// Creates an appropriate base32 alphabet (nopad, padded, simple, or with from:to mapping)
///
/// `"ABCDEFGHIJKLMNOPQRSTUVWXYZ234567"` and `'='`
/// Note that the second identifier is to make the decoder a constant static variable, for const fn usage.
///
/// [https://datatracker.ietf.org/doc/html/rfc4648#section-6](https://datatracker.ietf.org/doc/html/rfc4648#section-6)
pub const RFC4648: Alphabet32Padded = Alphabet32Padded::new(ENC_RFC4648, &DEC_RFC4648, '=');
/// RFC 4648 Base32 normal, no padding
///
/// `"ABCDEFGHIJKLMNOPQRSTUVWXYZ234567"`
///
/// [https://datatracker.ietf.org/doc/html/rfc4648#section-6](https://datatracker.ietf.org/doc/html/rfc4648#section-6)
pub const RFC4648_NOPAD: Alphabet32Nopad = Alphabet32Nopad::new(ENC_RFC4648, &DEC_RFC4648);
/// See examples in [tests/alphabet.rs](https://github.com/rogusdev/fast32/blob/main/tests/alphabets.rs)
#[macro_export]
macro_rules! make_base32_alpha {
( $n:ident, $dec:ident, $enc:expr ) => {
pub const $dec: [u8; 256] = $crate::decoder_map_simple($enc);
pub const $n: $crate::base32::Alphabet32Nopad =
$crate::base32::Alphabet32Nopad::new($enc, &$dec);
};
( $n:ident, $dec:ident, $enc:expr, $pad:literal ) => {
pub const $dec: [u8; 256] = $crate::decoder_map_simple($enc);
pub const $n: $crate::base32::Alphabet32Padded =
$crate::base32::Alphabet32Padded::new($enc, &$dec, $pad);
};
( $n:ident, $dec:ident, $enc:expr, $fr:literal, $to:literal ) => {
pub const $dec: [u8; 256] = $crate::decoder_map($enc, $fr, $to);
pub const $n: $crate::base32::Alphabet32Nopad =
$crate::base32::Alphabet32Nopad::new($enc, &$dec);
};
( $n:ident, $dec:ident, $enc:expr, $fr:literal, $to:literal, $pad:literal ) => {
pub const $dec: [u8; 256] = $crate::decoder_map($enc, $fr, $to);
pub const $n: $crate::base32::Alphabet32Padded =
$crate::base32::Alphabet32Padded::new($enc, &$dec, $pad);
};
}

const ENC_RFC4648_HEX: &'static [u8; 32] = b"0123456789ABCDEFGHIJKLMNOPQRSTUV";
const DEC_RFC4648_HEX: [u8; 256] = decoder_map_simple(ENC_RFC4648_HEX);
/// RFC 4648 Base32 "hex" form, with padding
///
/// `"ABCDEFGHIJKLMNOPQRSTUVWXYZ234567"` and `'='`
///
/// [https://datatracker.ietf.org/doc/html/rfc4648#section-7](https://datatracker.ietf.org/doc/html/rfc4648#section-7)
pub const RFC4648_HEX: Alphabet32Padded = Alphabet32Padded::new(ENC_RFC4648_HEX, &DEC_RFC4648_HEX, '=');
/// RFC 4648 Base32 "hex" form, no padding
///
/// `"0123456789ABCDEFGHIJKLMNOPQRSTUV"`
///
/// [https://datatracker.ietf.org/doc/html/rfc4648#section-7](https://datatracker.ietf.org/doc/html/rfc4648#section-7)
pub const RFC4648_HEX_NOPAD: Alphabet32Nopad = Alphabet32Nopad::new(ENC_RFC4648_HEX, &DEC_RFC4648_HEX);
const ENC_RFC4648: &'static [u8; BITS] = b"ABCDEFGHIJKLMNOPQRSTUVWXYZ234567";
make_base32_alpha!(RFC4648, DEC_RFC4648, ENC_RFC4648, '=');
make_base32_alpha!(RFC4648_NOPAD, DEC_RFC4648_2, ENC_RFC4648);

const ENC_RFC4648_HEX: &'static [u8; BITS] = b"0123456789ABCDEFGHIJKLMNOPQRSTUV";
make_base32_alpha!(RFC4648_HEX, DEC_RFC4648_HEX, ENC_RFC4648_HEX, '=');
make_base32_alpha!(RFC4648_HEX_NOPAD, DEC_RFC4648_HEX_2, ENC_RFC4648_HEX);

const ENC_CROCKFORD: &'static [u8; BITS] = b"0123456789ABCDEFGHJKMNPQRSTVWXYZ";
make_base32_alpha!(
CROCKFORD,
DEC_CROCKFORD,
ENC_CROCKFORD,
b"ILOabcdefghijklmnopqrstvwxyz",
b"110ABCDEFGH1JK1MN0PQRSTVWXYZ"
);

pub const BITS: usize = 32;

Expand Down
6 changes: 1 addition & 5 deletions src/base32/decode_bytes.rs
Original file line number Diff line number Diff line change
Expand Up @@ -58,11 +58,7 @@ pub fn decode(dec: &'static [u8; 256], a: &[u8]) -> Result<Vec<u8>, DecodeError>
/// Returns [`DecodeError`] if input to decode is invalid
///
/// Panics if not enough capacity in `b` for decoding -- see [`capacity_decode`](self::capacity_decode())
pub fn decode_into(
dec: &'static [u8; 256],
a: &[u8],
b: &mut Vec<u8>,
) -> Result<(), DecodeError> {
pub fn decode_into(dec: &'static [u8; 256], a: &[u8], b: &mut Vec<u8>) -> Result<(), DecodeError> {
let len_enc = a.len();
let rem = len_enc % WIDTH_ENC;
let max = len_enc / WIDTH_ENC;
Expand Down
1 change: 0 additions & 1 deletion src/base32/uuid.rs
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,6 @@ pub fn encode_uuid(enc: &'static [u8; BITS], n: Uuid) -> String {
super::encode_u128(enc, n.as_u128())
}


/// Encode [`Uuid`] with given encoding, into an existing `Vec<u8>`
///
/// Example:
Expand Down
30 changes: 27 additions & 3 deletions src/base64.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,11 +16,35 @@ pub use self::encode_bytes::{capacity_encode, encode, encode_into};
pub use self::encode_u128::{capacity_encode_u128, encode_u128, encode_u128_into};
pub use self::encode_u64::{capacity_encode_u64, encode_u64, encode_u64_into};

#[cfg(feature = "uuid")]
pub use self::uuid::{decode_uuid, encode_uuid, encode_uuid_into};

pub use self::alphabet::{Alphabet64Nopad, Alphabet64Padded};

/// RFC 4648 Base64 normal, with padding
///
/// `"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"` and `'='`
///
/// [https://datatracker.ietf.org/doc/html/rfc4648#section-4](https://datatracker.ietf.org/doc/html/rfc4648#section-4)
pub use self::alphabet::RFC4648;

/// RFC 4648 Base64 normal, no padding
///
/// `"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"`
///
/// [https://datatracker.ietf.org/doc/html/rfc4648#section-4](https://datatracker.ietf.org/doc/html/rfc4648#section-4)
pub use self::alphabet::RFC4648_NOPAD;

/// RFC 4648 Base64 "url safe" form, with padding
///
/// `"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_"` and `'='`
///
/// [https://datatracker.ietf.org/doc/html/rfc4648#section-5](https://datatracker.ietf.org/doc/html/rfc4648#section-5)
pub use self::alphabet::RFC4648_URL;
pub use self::alphabet::RFC4648_URL_NOPAD;

#[cfg(feature = "uuid")]
pub use self::uuid::{decode_uuid, encode_uuid, encode_uuid_into};
/// RFC 4648 Base64 "url safe" form, no padding
///
/// `"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_"`
///
/// [https://datatracker.ietf.org/doc/html/rfc4648#section-5](https://datatracker.ietf.org/doc/html/rfc4648#section-5)
pub use self::alphabet::RFC4648_URL_NOPAD;
62 changes: 34 additions & 28 deletions src/base64/alphabet.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@ use core::ptr::write;
#[cfg(feature = "uuid")]
use uuid::Uuid;

use crate::shared::decoder_map_simple;
use crate::DecodeError;

use super::decode_bytes::{decode, decode_into};
Expand All @@ -16,37 +15,44 @@ use super::encode_u64::{encode_u64, encode_u64_into};
#[cfg(feature = "uuid")]
use super::uuid::{decode_uuid, encode_uuid, encode_uuid_into};

const ENC_RFC4648: &'static [u8; 64] =
b"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
const DEC_RFC4648: [u8; 256] = decoder_map_simple(ENC_RFC4648);
/// RFC 4648 Base64 normal, with padding
///
/// `"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"` and `'='`
///
/// [https://datatracker.ietf.org/doc/html/rfc4648#section-4](https://datatracker.ietf.org/doc/html/rfc4648#section-4)
pub const RFC4648: Alphabet64Padded = Alphabet64Padded::new(ENC_RFC4648, &DEC_RFC4648, '=');
/// RFC 4648 Base64 normal, no padding
/// Creates an appropriate base64 alphabet (nopad, padded, simple, or with from:to mapping)
///
/// `"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"`
/// Note that the second identifier is to make the decoder a constant static variable, for const fn usage.
///
/// [https://datatracker.ietf.org/doc/html/rfc4648#section-4](https://datatracker.ietf.org/doc/html/rfc4648#section-4)
pub const RFC4648_NOPAD: Alphabet64Nopad = Alphabet64Nopad::new(ENC_RFC4648, &DEC_RFC4648);
/// See examples in [tests/alphabet.rs](https://github.com/rogusdev/fast32/blob/main/tests/alphabets.rs)
#[macro_export]
macro_rules! make_base64_alpha {
( $n:ident, $dec:ident, $enc:expr ) => {
pub const $dec: [u8; 256] = $crate::decoder_map_simple($enc);
pub const $n: $crate::base64::Alphabet64Nopad =
$crate::base64::Alphabet64Nopad::new($enc, &$dec);
};
( $n:ident, $dec:ident, $enc:expr, $pad:literal ) => {
pub const $dec: [u8; 256] = $crate::decoder_map_simple($enc);
pub const $n: $crate::base64::Alphabet64Padded =
$crate::base64::Alphabet64Padded::new($enc, &$dec, $pad);
};
( $n:ident, $dec:ident, $enc:expr, $fr:literal, $to:literal ) => {
pub const $dec: [u8; 256] = $crate::decoder_map($enc, $fr, $to);
pub const $n: $crate::base64::Alphabet64Nopad =
$crate::base64::Alphabet64Nopad::new($enc, &$dec);
};
( $n:ident, $dec:ident, $enc:expr, $fr:literal, $to:literal, $pad:literal ) => {
pub const $dec: [u8; 256] = $crate::decoder_map($enc, $fr, $to);
pub const $n: $crate::base64::Alphabet64Padded =
$crate::base64::Alphabet64Padded::new($enc, &$dec, $pad);
};
}

const ENC_RFC4648: &'static [u8; BITS] =
b"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
make_base64_alpha!(RFC4648, DEC_RFC4648, ENC_RFC4648, '=');
make_base64_alpha!(RFC4648_NOPAD, DEC_RFC4648_2, ENC_RFC4648);

const ENC_RFC4648_URL: &'static [u8; 64] =
const ENC_RFC4648_URL: &'static [u8; BITS] =
b"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_";
const DEC_RFC4648_URL: [u8; 256] = decoder_map_simple(ENC_RFC4648_URL);
/// RFC 4648 Base64 "url safe" form, with padding
///
/// `"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_"` and `'='`
///
/// [https://datatracker.ietf.org/doc/html/rfc4648#section-5](https://datatracker.ietf.org/doc/html/rfc4648#section-5)
pub const RFC4648_URL: Alphabet64Padded = Alphabet64Padded::new(ENC_RFC4648_URL, &DEC_RFC4648_URL, '=');
/// RFC 4648 Base64 "url safe" form, no padding
///
/// `"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_"`
///
/// [https://datatracker.ietf.org/doc/html/rfc4648#section-5](https://datatracker.ietf.org/doc/html/rfc4648#section-5)
pub const RFC4648_URL_NOPAD: Alphabet64Nopad = Alphabet64Nopad::new(ENC_RFC4648_URL, &DEC_RFC4648_URL);
make_base64_alpha!(RFC4648_URL, DEC_RFC4648_URL, ENC_RFC4648_URL, '=');
make_base64_alpha!(RFC4648_URL_NOPAD, DEC_RFC4648_URL_2, ENC_RFC4648_URL);

pub const BITS: usize = 64;

Expand Down
6 changes: 1 addition & 5 deletions src/base64/decode_bytes.rs
Original file line number Diff line number Diff line change
Expand Up @@ -56,11 +56,7 @@ pub fn decode(dec: &'static [u8; 256], a: &[u8]) -> Result<Vec<u8>, DecodeError>
/// Returns [`DecodeError`] if input to decode is invalid
///
/// Panics if not enough capacity in `b` for decoding -- see [`capacity_decode`](self::capacity_decode())
pub fn decode_into(
dec: &'static [u8; 256],
a: &[u8],
b: &mut Vec<u8>,
) -> Result<(), DecodeError> {
pub fn decode_into(dec: &'static [u8; 256], a: &[u8], b: &mut Vec<u8>) -> Result<(), DecodeError> {
let len_enc = a.len();
let rem = len_enc % WIDTH_ENC;
let max = len_enc / WIDTH_ENC;
Expand Down
1 change: 0 additions & 1 deletion src/base64/uuid.rs
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,6 @@ pub fn encode_uuid(enc: &'static [u8; BITS], n: Uuid) -> String {
super::encode_u128(enc, n.as_u128())
}


/// Encode [`Uuid`] with given encoding, into an existing `Vec<u8>`
///
/// Example:
Expand Down
10 changes: 10 additions & 0 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,16 @@
//! assert_eq!(&b[1..17], n);
//! ```
//!
//! You can also define new alphabets of your own:
//! ```
//! use fast32::make_base32_alpha;
//!
//! make_base32_alpha!(RFC4648_LOWER_NOPAD, DEC_RFC4648_LOWER, b"abcdefghijklmnopqrstuvwxyz234567");
//!
//! assert_eq!(RFC4648_LOWER_NOPAD.encode_u64(31), "7");
//! assert_eq!(RFC4648_LOWER_NOPAD.decode_u64_str("7").unwrap(), 31);
//! ```
//!
//! The [tests](https://github.com/rogusdev/fast32/tree/main/tests)
//! have numerous examples that might help further.
//!
Expand Down
8 changes: 8 additions & 0 deletions src/shared.rs
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,10 @@ impl std::fmt::Display for DecodeError {

/// Build a new decoder array for the given bits (encoder array size), exactly of the encoder array
///
/// **You should use [`fast32::make_base32_alpha`](crate::make_base32_alpha)
/// or [`fast32::make_base64_alpha`](crate::make_base64_alpha) instead of this!**
/// (Those macros invoke this function as appropriate.)
///
/// Example:
/// ```
/// use fast32::decoder_map_simple;
Expand Down Expand Up @@ -133,6 +137,10 @@ const fn enc_index<const B: usize>(enc: &[u8; B], c: u8) -> u8 {

/// Build a new decoder array for the given bits (encoder array size), with additional character translations
///
/// **You should use [`fast32::make_base32_alpha`](crate::make_base32_alpha)
/// or [`fast32::make_base64_alpha`](crate::make_base64_alpha) instead of this!**
/// (Those macros invoke this function as appropriate.)
///
/// Example:
/// ```
/// use fast32::decoder_map;
Expand Down
Loading

0 comments on commit 1997656

Please sign in to comment.