Skip to content

Commit

Permalink
Merge pull request #68 from WalterSmuts/master
Browse files Browse the repository at this point in the history
Raise str buffer size checking to type level
  • Loading branch information
dylanhart committed Oct 10, 2023
2 parents 8b21eaa + 77592a0 commit 5114a38
Show file tree
Hide file tree
Showing 4 changed files with 39 additions and 4 deletions.
2 changes: 1 addition & 1 deletion benches/bench.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ fn bench_to_str(b: &mut Bencher) {
let ulid = Ulid::new();
b.iter(|| {
let mut buffer = [0; ULID_LEN];
ulid.to_str(&mut buffer).unwrap();
ulid.array_to_str(&mut buffer);
});
}

Expand Down
16 changes: 15 additions & 1 deletion src/base32.rs
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,10 @@ impl fmt::Display for EncodeError {
}

/// Encode a u128 value to a given buffer. The provided buffer should be at least `ULID_LEN` long.
#[deprecated(
since = "1.2.0",
note = "Use the infallible `encode_to_array` instead."
)]
pub fn encode_to(mut value: u128, buffer: &mut [u8]) -> Result<usize, EncodeError> {
// NOTE: This function can't be made const because mut refs aren't allowed for some reason

Expand All @@ -72,11 +76,21 @@ pub fn encode_to(mut value: u128, buffer: &mut [u8]) -> Result<usize, EncodeErro
Ok(ULID_LEN)
}

/// Encode a u128 value to a given buffer.
pub fn encode_to_array(mut value: u128, buffer: &mut [u8; ULID_LEN]) {
// NOTE: This function can't be made const because mut refs aren't allowed for some reason

for i in 0..ULID_LEN {
buffer[ULID_LEN - 1 - i] = ALPHABET[(value & 0x1f) as usize];
value >>= 5;
}
}

#[cfg(feature = "std")]
pub fn encode(value: u128) -> String {
let mut buffer: [u8; ULID_LEN] = [0; ULID_LEN];

encode_to(value, &mut buffer).expect("unexpected encoding error");
encode_to_array(value, &mut buffer);

String::from_utf8(buffer.to_vec()).expect("unexpected failure in base32 encode for ulid")
}
Expand Down
23 changes: 22 additions & 1 deletion src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -190,11 +190,32 @@ impl Ulid {
///
/// assert_eq!(new_text, text);
/// ```
#[deprecated(since = "1.2.0", note = "Use the infallible `array_to_str` instead.")]
pub fn to_str<'buf>(&self, buf: &'buf mut [u8]) -> Result<&'buf mut str, EncodeError> {
#[allow(deprecated)]
let len = base32::encode_to(self.0, buf)?;
Ok(unsafe { core::str::from_utf8_unchecked_mut(&mut buf[..len]) })
}

/// Creates a Crockford Base32 encoded string that represents this Ulid
///
/// # Example
/// ```rust
/// use ulid::Ulid;
///
/// let text = "01D39ZY06FGSCTVN4T2V9PKHFZ";
/// let ulid = Ulid::from_string(text).unwrap();
///
/// let mut buf = [0; ulid::ULID_LEN];
/// let new_text = ulid.array_to_str(&mut buf);
///
/// assert_eq!(new_text, text);
/// ```
pub fn array_to_str<'buf>(&self, buf: &'buf mut [u8; ULID_LEN]) -> &'buf mut str {
base32::encode_to_array(self.0, buf);
unsafe { core::str::from_utf8_unchecked_mut(buf) }
}

/// Creates a Crockford Base32 encoded string that represents this Ulid
///
/// # Example
Expand Down Expand Up @@ -336,7 +357,7 @@ impl FromStr for Ulid {
impl fmt::Display for Ulid {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> Result<(), fmt::Error> {
let mut buffer = [0; ULID_LEN];
write!(f, "{}", self.to_str(&mut buffer).unwrap())
write!(f, "{}", self.array_to_str(&mut buffer))
}
}

Expand Down
2 changes: 1 addition & 1 deletion src/serde.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ impl Serialize for Ulid {
S: Serializer,
{
let mut buffer = [0; ULID_LEN];
let text = self.to_str(&mut buffer).unwrap();
let text = self.array_to_str(&mut buffer);
text.serialize(serializer)
}
}
Expand Down

0 comments on commit 5114a38

Please sign in to comment.