pub trait Base32UlidExt: UlidId{
// Provided methods
fn buf() -> <<Self as Id>::Ty as BeBytes>::Base32Array { ... }
fn encode(&self) -> Base32UlidFormatter<Self> { ... }
fn encode_to_buf<'buf>(
&self,
buf: &'buf mut <<Self as Id>::Ty as BeBytes>::Base32Array,
) -> Base32UlidFormatterRef<'buf, Self> { ... }
fn decode(s: impl AsRef<str>) -> Result<Self, Error<Self>> { ... }
}Expand description
Extension trait for Crockford Base32 encoding and decoding of ID types.
This trait enables converting IDs backed by integer types into fixed-length, lexicographically sortable Base32 representation using the Crockford Base32 alphabet.
Provided Methods§
Sourcefn buf() -> <<Self as Id>::Ty as BeBytes>::Base32Array
fn buf() -> <<Self as Id>::Ty as BeBytes>::Base32Array
Returns a stack-allocated, zero-initialized buffer for Base32 encoding.
This is a convenience method that returns a BeBytes::Base32Array
suitable for use with Base32UlidExt::encode_to_buf. The returned
buffer is stack-allocated, has a fixed size known at compile time, and
is guaranteed to match the Crockford Base32 output size for the backing
integer type.
See also: Base32UlidExt::encode_to_buf for usage.
Sourcefn encode(&self) -> Base32UlidFormatter<Self>
fn encode(&self) -> Base32UlidFormatter<Self>
Returns a formatter containing the Crockford Base32 representation of the ID.
The formatter is a lightweight, zero-allocation view over that internal
buffer that implements core::fmt::Display and AsRef<str>.
§Example
#[cfg(all(feature = "base32", feature = "ulid"))]
{
use ferroid::{Base32UlidExt, ULID};
use std::fmt::Write;
let id = ULID::from_raw(2_424_242_424_242_424_242);
// Formatter is a view over the internal encoded buffer
let formatter = id.encode();
assert_eq!(formatter, "000000000000023953MG16DJDJ");
}Sourcefn encode_to_buf<'buf>(
&self,
buf: &'buf mut <<Self as Id>::Ty as BeBytes>::Base32Array,
) -> Base32UlidFormatterRef<'buf, Self>
fn encode_to_buf<'buf>( &self, buf: &'buf mut <<Self as Id>::Ty as BeBytes>::Base32Array, ) -> Base32UlidFormatterRef<'buf, Self>
Encodes this ID into the provided buffer without heap allocation and
returns a formatter view over the buffer similar to
Base32UlidExt::encode.
The buffer must be exactly BeBytes::BASE32_SIZE bytes long, which is
guaranteed at compile time when using Base32UlidExt::buf.
§Example
#[cfg(all(feature = "base32", feature = "ulid"))]
{
use ferroid::{Base32UlidExt, BeBytes, Id, ULID};
let id = ULID::from_raw(2_424_242_424_242_424_242);
// Stack-allocated buffer of the correct size.
let mut buf = ULID::buf();
// Formatter is a view over the external buffer
let formatter = id.encode_to_buf(&mut buf);
assert_eq!(formatter, "000000000000023953MG16DJDJ");
// Or access the raw bytes directly:
let as_str = unsafe { core::str::from_utf8_unchecked(buf.as_ref()) };
assert_eq!(as_str, "000000000000023953MG16DJDJ");
}See also: Base32UlidExt::encode for a version that manages its own
buffer.
Sourcefn decode(s: impl AsRef<str>) -> Result<Self, Error<Self>>
fn decode(s: impl AsRef<str>) -> Result<Self, Error<Self>>
Decodes a Base32-encoded string back into an ID.
⚠️ Note:
This method structurally decodes a Crockford base32 string into an
integer representing a ULID, regardless of whether the input is a
canonical ULID.
- If the input string’s Crockford encoding is larger than the ULID spec’s maximum (i.e. “7ZZZZZZZZZZZZZZZZZZZZZZZZZ” for 128-bit integers), the excess bits are automatically ignored (i.e., the top 2 bits of the decoded value are discarded), so no overflow or error occurs.
- As a result, base32 strings that are technically invalid per the ULID spec (i.e., lexicographically greater than the max ULID string) will still successfully decode.
- However, if your ID type reserves bits (e.g., reserved or unused
bits in your layout), decoding a string with excess bits may set these
reserved bits to 1, causing
.is_valid()to fail, and decode to return an error.
§Errors
Returns an error if the input string:
- is not the expected fixed length of the backing integer representation (i.e. 26 chars for u128)
- contains invalid ASCII characters (i.e., not in the Crockford Base32 alphabet)
- sets reserved bits that make the decoded value invalid for this ID type
§Example
#[cfg(all(feature = "base32", feature = "ulid"))]
{
use ferroid::{Base32Error, Base32UlidExt, Error, Id, ULID, UlidId};
// Crockford Base32 encodes values in 5-bit chunks, so encoding a u128 (128
// bits) requires 26 characters (26 × 5 = 130 bits). Since u128 can only hold
// 128 bits, the highest 2 bits are discarded during decoding.
//
// This means *any* 26-character Base32 string will decode into a u128, even
// if it represents a value that exceeds the canonical range of a specific
// ID type.
//
// Other ID formats may reserve one or more high bits for future use. These
// reserved bits **must remain unset** for the decoded value to be
// considered valid.
//
// For example, in a `ULID`, "7ZZZZZZZZZZZZZZZZZZZZZZZZZ" represents the
// largest lexicographically valid encoding that fills all 128 bits with
// ones. Lexicographically larger values like "ZZZZZZZZZZZZZZZZZZZZZZZZZZ"
// decode to the *same* ID because their first character differs only in the
// highest bits (129th & 130th), which are discarded:
// - '7' = 0b00111 → top bits 00, rest = 111...
// - 'Z' = 0b11111 → top bits 11, rest = 111...
// ↑↑↑ identical after discarding MSBs
let id1 = ULID::decode("7ZZZZZZZZZZZZZZZZZZZZZZZZZ").unwrap();
let id2 = ULID::decode("ZZZZZZZZZZZZZZZZZZZZZZZZZZ").unwrap();
assert_eq!(id1, id2);
}Dyn Compatibility§
This trait is not dyn compatible.
In older versions of Rust, dyn compatibility was called "object safety", so this trait is not object safe.