Skip to content

Commit

Permalink
Merge pull request #10 from ystorian/2-lowercase
Browse files Browse the repository at this point in the history
Move to a lowercase alphabet
  • Loading branch information
adriantombu authored Jul 10, 2024
2 parents c815b00 + a654057 commit 0fc0166
Show file tree
Hide file tree
Showing 9 changed files with 124 additions and 107 deletions.
92 changes: 50 additions & 42 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 2 additions & 2 deletions cli/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -6,14 +6,14 @@ authors = ["dylanhart <[email protected]>", "Kan-Ru Chen <[email protected]>"
license = "MIT"
readme = "../README.md"

description = "A command line interface for generating and inspecting ULIDs"
description = "A command line interface for generating and inspecting ULYSes"
keywords = ["ulys", "ulid", "uuid", "sortable", "identifier"]

repository = "https://github.com/ystorian/ulys"

edition = "2021"

[dependencies]
structopt = "0.2"
structopt = "0.3"
ulys = { version = "*", path = ".." }
time = "0.3.11"
File renamed without changes.
68 changes: 39 additions & 29 deletions src/base32.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,23 +3,23 @@ use core::fmt;
/// Length of a string-encoded Ulys
pub const ULYS_LEN: usize = 26;

const ALPHABET: &[u8; 32] = b"0123456789ABCDEFGHJKMNPQRSTVWXYZ";
const ALPHABET: &[u8; 32] = b"0123456789abcdefghjkmnpqrstvwxyz";

const NO_VALUE: u8 = 255;
const LOOKUP: [u8; 256] = [
255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 255, 255, 255,
255, 255, 255, 255, 10, 11, 12, 13, 14, 15, 16, 17, 255, 18, 19, 255, 20, 21, 255, 22, 23, 24,
25, 26, 255, 27, 28, 29, 30, 31, 255, 255, 255, 255, 255, 255, 10, 11, 12, 13, 14, 15, 16, 17,
255, 18, 19, 255, 20, 21, 255, 22, 23, 24, 25, 26, 255, 27, 28, 29, 30, 31, 255, 255, 255, 255,
255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 10, 11,
12, 13, 14, 15, 16, 17, 255, 18, 19, 255, 20, 21, 255, 22, 23, 24, 25, 26, 255, 27, 28, 29, 30,
31, 255, 255, 255, 255, 255, 255, 10, 11, 12, 13, 14, 15, 16, 17, 255, 18, 19, 255, 20, 21,
255, 22, 23, 24, 25, 26, 255, 27, 28, 29, 30, 31, 255, 255, 255, 255, 255, 255, 255, 255, 255,
255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
];

/// Generator code for `LOOKUP`
Expand All @@ -28,10 +28,10 @@ const LOOKUP: [u8; 256] = [
fn test_lookup_table() {
let mut lookup = [NO_VALUE; 256];
for (i, &c) in ALPHABET.iter().enumerate() {
lookup[c as usize] = i as u8;
lookup[c as usize] = u8::try_from(i).unwrap();
if !(c as char).is_numeric() {
//lowercase
lookup[(c + 32) as usize] = i as u8;
lookup[(c + 32) as usize] = u8::try_from(i).unwrap();
}
}
assert_eq!(LOOKUP, lookup);
Expand All @@ -52,7 +52,7 @@ impl fmt::Display for EncodeError {
let text = match *self {
EncodeError::BufferTooSmall => "buffer too small",
};
write!(f, "{}", text)
write!(f, "{text}")
}
}

Expand Down Expand Up @@ -113,7 +113,7 @@ impl fmt::Display for DecodeError {
DecodeError::InvalidLength => "invalid length",
DecodeError::InvalidChar => "invalid character",
};
write!(f, "{}", text)
write!(f, "{text}")
}
}

Expand All @@ -130,11 +130,12 @@ pub const fn decode(encoded: &str) -> Result<u128, DecodeError> {
let mut i = 0;
while i < ULYS_LEN {
let val = LOOKUP[bytes[i] as usize];
if val != NO_VALUE {
value = (value << 5) | val as u128;
} else {
if val == NO_VALUE {
return Err(DecodeError::InvalidChar);
}

value = (value << 5) | val as u128;

i += 1;
}

Expand All @@ -147,12 +148,12 @@ mod tests {

#[test]
fn test_valid() {
let val = 0x41414141414141414141414141414141;
assert_eq!(decode("21850M2GA1850M2GA1850M2GA1").unwrap(), val);
assert_eq!(encode(val), "21850M2GA1850M2GA1850M2GA1");
let val = 0x4141_4141_4141_4141_4141_4141_4141_4141;
assert_eq!(decode("21850m2ga1850m2ga1850m2ga1").unwrap(), val);
assert_eq!(encode(val), "21850m2ga1850m2ga1850m2ga1");

let val = 0x4d4e385051444a59454234335a413756;
let enc = "2D9RW50MA499CMAGHM6DD42DTP";
let val = 0x4d4e_3850_5144_4a59_4542_3433_5a41_3756;
let enc = "2d9rw50ma499cmaghm6dd42dtp";
let lower = enc.to_lowercase();
assert_eq!(encode(val), enc);
assert_eq!(decode(enc).unwrap(), val);
Expand All @@ -161,43 +162,52 @@ mod tests {

#[test]
fn test_length() {
assert_eq!(encode(0xffffffffffffffffffffffffffffffff).len(), ULYS_LEN);
assert_eq!(encode(0x0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f).len(), ULYS_LEN);
assert_eq!(encode(0x00000000000000000000000000000000).len(), ULYS_LEN);
assert_eq!(
encode(0xffff_ffff_ffff_ffff_ffff_ffff_ffff_ffff).len(),
ULYS_LEN
);
assert_eq!(
encode(0x0f0f_0f0f_0f0f_0f0f_0f0f_0f0f_0f0f_0f0f).len(),
ULYS_LEN
);
assert_eq!(
encode(0x0000_0000_0000_0000_0000_0000_0000_0000).len(),
ULYS_LEN
);

assert_eq!(decode(""), Err(DecodeError::InvalidLength));
assert_eq!(
decode("2D9RW50MA499CMAGHM6DD42DT"),
decode("2d9rw50ma499cmaghm6dd42dt"),
Err(DecodeError::InvalidLength)
);
assert_eq!(
decode("2D9RW50MA499CMAGHM6DD42DTPP"),
decode("2d9rw50ma499cmaghm6dd42dtpP"),
Err(DecodeError::InvalidLength)
);
}

#[test]
fn test_chars() {
for ref c in encode(0xffffffffffffffffffffffffffffffff).bytes() {
for ref c in encode(0xffff_ffff_ffff_ffff_ffff_ffff_ffff_ffff).bytes() {
assert!(ALPHABET.contains(c));
}
for ref c in encode(0x0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f).bytes() {
for ref c in encode(0x0f0f_0f0f_0f0f_0f0f_0f0f_0f0f_0f0f_0f0f).bytes() {
assert!(ALPHABET.contains(c));
}
for ref c in encode(0x00000000000000000000000000000000).bytes() {
for ref c in encode(0x0000_0000_0000_0000_0000_0000_0000_0000).bytes() {
assert!(ALPHABET.contains(c));
}

assert_eq!(
decode("2D9RW50[A499CMAGHM6DD42DTP"),
decode("2d9rw50[a499cmaghm6dd42dtp"),
Err(DecodeError::InvalidChar)
);
assert_eq!(
decode("2D9RW50LA499CMAGHM6DD42DTP"),
decode("2d9rw50la499cmaghm6dd42dtp"),
Err(DecodeError::InvalidChar)
);
assert_eq!(
decode("2D9RW50IA499CMAGHM6DD42DTP"),
decode("2d9rw50ia499cmaghm6dd42dtp"),
Err(DecodeError::InvalidChar)
);
}
Expand Down
Loading

0 comments on commit 0fc0166

Please sign in to comment.