pub struct GrainId(/* private fields */);Expand description
Grain id struct
§Examples
// Generate random value.
let random = GrainId::random();
assert_ne!(random, GrainId::NIL);
// Parse from string.
let from_str: GrainId = "012abcd".parse()?;
// Parse from integer.
let from_int: GrainId = 35990925u64.try_into()?;
assert_eq!(from_str, from_int);Implementations§
Source§impl GrainId
impl GrainId
Sourcepub const BITS: u32 = 35
pub const BITS: u32 = 35
The size of the integer type in bits.
This is not equal actually stored size.
Sourcepub const fn from_u64_lossy(int: u64) -> GrainId
pub const fn from_u64_lossy(int: u64) -> GrainId
“Converts an unsigned integer to GrainId by truncating bits that exceed the valid range.”)]
This is a lossy conversion that masks the input value to fit within the ID’s bit limit.
If you need to detect out-of-range values, use TryFrom instead.
§Examples
// Values within range are preserved
let valid_int = 123;
let id = GrainId::from_u64_lossy(valid_int);
assert_eq!(u64::from(id), valid_int);
// values exceeding 35 bits are truncated (MSB(s) dropped
let oversized_int = valid_int + GrainId::CAPACITY;
let overflowed_id = GrainId::from_u64_lossy(oversized_int);
assert_ne!(u64::from(overflowed_id), oversized_int);
// Only lower 35 bits retained
assert_eq!(u64::from(overflowed_id), valid_int)Sourcepub const fn from_u64(value: u64) -> Result<GrainId, Error>
pub const fn from_u64(value: u64) -> Result<GrainId, Error>
Attempts to convert a u64 to GrainId.
Return error if the value is larger than GrainId::MAX.
If you don’t need to detect out-of-range values, use from_uint_lossy.
§Examples
assert_eq!(GrainId::from_u64(0x7FFFFFFFF)?, GrainId::MAX);
assert!(GrainId::from_u64(0x800000000).is_err());Sourcepub const fn as_u64(&self) -> &u64
pub const fn as_u64(&self) -> &u64
Returns a reference of internal 64bit integer.
§Examples
let id = GrainId::from_u64(0x123456789)?;
assert_eq!(id.as_u64(), &0x123456789);Sourcepub const fn to_u64(self) -> u64
pub const fn to_u64(self) -> u64
Returns an internal 64bit integer value.
§Examples
let id = GrainId::from_u64(0x123456789)?;
assert_eq!(id.to_u64(), 0x123456789);Sourcepub fn from_duration(duration: Duration) -> GrainId
pub fn from_duration(duration: Duration) -> GrainId
Creates a GrainId from a Duration based on decisecond precision.
This method converts the given duration into deciseconds (0.1 second units)
and generates a GrainId from it. The resulting 35-bit identifier can
represent approximately 109 years worth of deciseconds.
§Timestamp Format
The entire 35 bits are used to represent the timestamp in deciseconds, allowing for chronological sorting while maintaining a compact 7-character BASE32 representation.
§Overflow Behavior
If the duration exceeds the maximum representable value (2^35 deciseconds, approximately 109 years), the timestamp will wrap around. This is generally not a concern for personal applications within a human lifespan.
§Examples
use std::time::Duration;
let duration = Duration::new(5, 730_023_852);
let id = GrainId::from_duration(duration);
assert_eq!(id, GrainId::from_u64(57)?);Sourcepub const fn to_be_bytes(self) -> [u8; 8]
👎Deprecated since 0.15.0: Use to_u64().to_be_bytes() instead.
pub const fn to_be_bytes(self) -> [u8; 8]
Use to_u64().to_be_bytes() instead.
Returns the memory representation of the internal integer of GrainId as a byte array in big endian byte order.
§Examples
let bytes = GrainId::from_u64(0x123456789)?.to_be_bytes();
assert_eq!(bytes, [0, 0, 0, 0x01, 0x23, 0x45, 0x67, 0x89]);Sourcepub const fn to_le_bytes(self) -> [u8; 8]
👎Deprecated since 0.15.0: Use to_u64().to_le_bytes() instead.
pub const fn to_le_bytes(self) -> [u8; 8]
Use to_u64().to_le_bytes() instead.
Returns the memory representation of the internal integer of GrainId as a byte array in little endian byte order.
§Examples
let bytes = GrainId::from_u64(0x123456789)?.to_le_bytes();
assert_eq!(bytes, [0x89, 0x67, 0x45, 0x23, 0x01, 0, 0, 0]);Sourcepub fn from_be_bytes(bytes: [u8; 8]) -> Result<GrainId, Error>
👎Deprecated since 0.15.0: Use GrainId::from_u64(u64::from_be_bytes(bytes))? instead.
pub fn from_be_bytes(bytes: [u8; 8]) -> Result<GrainId, Error>
Use GrainId::from_u64(u64::from_be_bytes(bytes))? instead.
Attempt to creata new GrainId from its representaion as a byte array in big endian.
§Error
Returns error if the value is larger than GrainId::MAX.
See from_u64 for more details.
If you don’t need to detect out-of-range values, use Self::from_be_bytes_lossy.
§Examples
let value = [0, 0, 0, 0x01, 0x23, 0x45, 0x67, 0x89];
assert_eq!(
GrainId::from_be_bytes(value)?,
GrainId::from_u64(0x123456789)?
);
// Oversized value returns error
let oversized_value = [0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef];
assert!(GrainId::from_be_bytes(oversized_value).is_err());Sourcepub fn from_le_bytes(bytes: [u8; 8]) -> Result<GrainId, Error>
👎Deprecated since 0.15.0: Use GrainId::from_u64(u64::from_le_bytes(bytes))? instead.
pub fn from_le_bytes(bytes: [u8; 8]) -> Result<GrainId, Error>
Use GrainId::from_u64(u64::from_le_bytes(bytes))? instead.
Attempt to creata new GrainId from its representaion as a byte array in little endian.
§Error
Returns error if the value is larger than GrainId::MAX.
See from_u64 for more details.
If you don’t need to detect out-of-range values, use Self::from_le_bytes_lossy.
§Examples
let value = [0x89, 0x67, 0x45, 0x23, 0x01, 0, 0, 0];
assert_eq!(
GrainId::from_le_bytes(value)?,
GrainId::from_u64(0x123456789)?
);
// Oversized value returns error
let oversized_value = [0xef, 0xcd, 0xab, 0x89, 0x67, 0x45, 0x23, 0x01];
assert!(GrainId::from_le_bytes(oversized_value).is_err());Sourcepub fn from_be_bytes_lossy(bytes: [u8; 8]) -> GrainId
👎Deprecated since 0.15.0: Use GrainId::from_u64_lossy(u64::from_be_bytes(bytes)) instead.
pub fn from_be_bytes_lossy(bytes: [u8; 8]) -> GrainId
Use GrainId::from_u64_lossy(u64::from_be_bytes(bytes)) instead.
Create new GrainId from its representaion as a byte array in big endianwith truncation of the upper 29 bit.
See from_u64_lossy for more details.
§Examples
let value = [0, 0, 0, 0x01, 0x23, 0x45, 0x67, 0x89];
assert_eq!(
GrainId::from_be_bytes_lossy(value),
GrainId::from_u64(0x123456789)?
);
// Oversized value will be truncated.
let oversized_value = [0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef];
assert_eq!(
GrainId::from_be_bytes_lossy(oversized_value),
GrainId::from_u64(0x789abcdef)?
);Sourcepub fn from_le_bytes_lossy(bytes: [u8; 8]) -> GrainId
👎Deprecated since 0.15.0: Use GrainId::from_u64_lossy(u64::from_le_bytes(bytes)) instead.
pub fn from_le_bytes_lossy(bytes: [u8; 8]) -> GrainId
Use GrainId::from_u64_lossy(u64::from_le_bytes(bytes)) instead.
Create new GrainId from its representaion as a byte array in little endianwith truncation of the upper 29 bit.
See from_u64_lossy for more details.
§Examples
let value = [0x89, 0x67, 0x45, 0x23, 0x01, 0, 0, 0];
assert_eq!(
GrainId::from_le_bytes_lossy(value),
GrainId::from_u64(0x123456789)?
);
// Oversized value will be truncated.
let oversized_value = [0xef, 0xcd, 0xab, 0x89, 0x67, 0x45, 0x23, 0x01];
assert_eq!(
GrainId::from_le_bytes_lossy(oversized_value),
GrainId::from_u64(0x789abcdef)?
);Sourcepub const fn to_be_bytes_compact(self) -> [u8; 5]
👎Deprecated since 0.15.0: Use to_byte_suffix() instead.
pub const fn to_be_bytes_compact(self) -> [u8; 5]
Use to_byte_suffix() instead.
Returns the memory representation of the internal integer of GrainId as a compact byte array in big endian byte order.
§Examples
let bytes = GrainId::from_u64(0x123456789)?.to_be_bytes_compact();
assert_eq!(bytes, [0x01, 0x23, 0x45, 0x67, 0x89]);Sourcepub const fn to_le_bytes_compact(self) -> [u8; 5]
👎Deprecated since 0.15.0: Use to_u64().to_le_bytes() for an 8-byte little-endian representation.
pub const fn to_le_bytes_compact(self) -> [u8; 5]
Use to_u64().to_le_bytes() for an 8-byte little-endian representation.
Returns the memory representation of the internal integer of GrainId as a compact byte array in little endian byte order.
§Examples
let bytes = GrainId::from_u64(0x123456789)?.to_le_bytes_compact();
assert_eq!(bytes, [0x89, 0x67, 0x45, 0x23, 0x01]);Sourcepub fn from_be_bytes_compact(bytes: [u8; 5]) -> Result<GrainId, Error>
👎Deprecated since 0.15.0: Use from_byte_suffix() for lossy conversion, or GrainId::from_u64(u64::from_be_bytes([0, 0, 0, bytes[0], bytes[1], bytes[2], bytes[3], bytes[4]]))? for checked conversion.
pub fn from_be_bytes_compact(bytes: [u8; 5]) -> Result<GrainId, Error>
Use from_byte_suffix() for lossy conversion, or GrainId::from_u64(u64::from_be_bytes([0, 0, 0, bytes[0], bytes[1], bytes[2], bytes[3], bytes[4]]))? for checked conversion.
Attempt to creata new GrainId from its representaion as a byte array in big endian.
§Error
Returns error if the value is larger than GrainId::MAX.
See from_u64 for more details.
If you don’t need to detect out-of-range values, use [compact].
§Examples
let value = [0x01, 0x23, 0x45, 0x67, 0x89];
assert_eq!(
GrainId::from_be_bytes_compact(value)?,
GrainId::from_u64(0x123456789)?
);
// Overflowed value returns error.
let oversized_value = [0x12, 0x34, 0x56, 0x78, 0x90];
assert!(GrainId::from_be_bytes_compact(oversized_value).is_err());Sourcepub fn from_le_bytes_compact(bytes: [u8; 5]) -> Result<GrainId, Error>
👎Deprecated since 0.15.0: Use GrainId::from_u64(u64::from_le_bytes([bytes[0], bytes[1], bytes[2], bytes[3], bytes[4], 0, 0, 0]))? instead.
pub fn from_le_bytes_compact(bytes: [u8; 5]) -> Result<GrainId, Error>
Use GrainId::from_u64(u64::from_le_bytes([bytes[0], bytes[1], bytes[2], bytes[3], bytes[4], 0, 0, 0]))? instead.
Attempt to creata new GrainId from its representaion as a byte array in little endian.
§Error
Returns error if the value is larger than GrainId::MAX.
See from_u64 for more details.
If you don’t need to detect out-of-range values, use [compact].
§Examples
let value = [0x89, 0x67, 0x45, 0x23, 0x01];
assert_eq!(
GrainId::from_le_bytes_compact(value)?,
GrainId::from_u64(0x123456789)?
);
// Oversized value returns error.
let oversized_value = [0x90, 0x78, 0x56, 0x34, 0x12];
assert!(GrainId::from_le_bytes_compact(oversized_value).is_err());Sourcepub fn from_be_bytes_compact_lossy(bytes: [u8; 5]) -> GrainId
👎Deprecated since 0.15.0: Use from_byte_suffix() instead.
pub fn from_be_bytes_compact_lossy(bytes: [u8; 5]) -> GrainId
Use from_byte_suffix() instead.
Create new GrainId from its compact representaion as a byte array in big endianwith truncation of the upper 5 bits.
See from_u64_lossy for more details.
§Examples
let value = [0x01, 0x23, 0x45, 0x67, 0x89];
assert_eq!(
GrainId::from_be_bytes_compact_lossy(value),
GrainId::from_u64(0x123456789)?
);
// Oversized value will be truncated.
let oversized_value = [0x12, 0x34, 0x56, 0x78, 0x90];
assert_eq!(
GrainId::from_be_bytes_compact_lossy(oversized_value),
GrainId::from_u64(0x234567890)?
);Sourcepub fn from_le_bytes_compact_lossy(bytes: [u8; 5]) -> GrainId
👎Deprecated since 0.15.0: Use GrainId::from_u64_lossy(u64::from_le_bytes([bytes[0], bytes[1], bytes[2], bytes[3], bytes[4], 0, 0, 0])) instead.
pub fn from_le_bytes_compact_lossy(bytes: [u8; 5]) -> GrainId
Use GrainId::from_u64_lossy(u64::from_le_bytes([bytes[0], bytes[1], bytes[2], bytes[3], bytes[4], 0, 0, 0])) instead.
Create new GrainId from its compact representaion as a byte array in little endianwith truncation of the upper 5 bits.
See from_u64_lossy for more details.
§Examples
let value = [0x89, 0x67, 0x45, 0x23, 0x01];
assert_eq!(
GrainId::from_le_bytes_compact_lossy(value),
GrainId::from_u64(0x123456789)?
);
// Oversized value will be truncated
let oversized_value = [0x90, 0x78, 0x56, 0x34, 0x12];
assert_eq!(
GrainId::from_le_bytes_compact_lossy(oversized_value),
GrainId::from_u64(0x234567890)?
);Sourcepub const fn wrapping_sub(self, rhs: GrainId) -> GrainId
pub const fn wrapping_sub(self, rhs: GrainId) -> GrainId
Wrapping (modular) subtraction. Computes self - rhs, wrapping around at the boundary of the type.
§Examples
assert_eq!(
GrainId::from_u64(100)?.wrapping_sub(GrainId::from_u64(100)?),
GrainId::NIL
);
assert_eq!(
GrainId::from_u64(100)?.wrapping_sub(GrainId::from_u64(101)?),
GrainId::MAX
);Sourcepub const fn from_byte_prefix(bytes: &[u8; 5]) -> GrainId
pub const fn from_byte_prefix(bytes: &[u8; 5]) -> GrainId
Creates a GrainId from the leading (most significant) 35 bits of a 5-byte array.
This is useful for generating a compact identifier from a pre-computed hash, public key, or any arbitrary byte sequence.
§Examples
// Extract leading 35 bits from a byte array
let bytes = [0xFF, 0xFF, 0xFF, 0xFF, 0xFF];
let id = GrainId::from_byte_prefix(&bytes);
assert_eq!(id, GrainId::MAX);
// For longer data, slice the first 5 bytes
let hash: [u8; 32] = [0; 32];
let id = GrainId::from_byte_prefix(hash[..5].try_into().unwrap());
assert_eq!(id, GrainId::NIL);Sourcepub const fn from_byte_suffix(bytes: &[u8; 5]) -> GrainId
pub const fn from_byte_suffix(bytes: &[u8; 5]) -> GrainId
Creates a GrainId from the trailing (least significant) 35 bits of a 5-byte array.
This is the counterpart to from_byte_prefix.
The upper 5 bits of the first byte are ignored.
§Examples
// Extract trailing 35 bits from a byte array
let bytes = [0xFF, 0xFF, 0xFF, 0xFF, 0xFF];
let id = GrainId::from_byte_suffix(&bytes);
assert_eq!(id, GrainId::MAX);
// Upper 5 bits of the first byte are ignored
let bytes = [0xF8, 0x00, 0x00, 0x00, 0x00];
let id = GrainId::from_byte_suffix(&bytes);
assert_eq!(id, GrainId::NIL);Sourcepub const fn to_byte_prefix(self) -> [u8; 5]
pub const fn to_byte_prefix(self) -> [u8; 5]
Returns a 5-byte array with the GrainId value stored in the leading (most significant) 35 bits.
This is the counterpart to from_byte_prefix.
The lower 5 bits of the last byte are always zero.
§Examples
let bytes = GrainId::from_u64(0x123456789)?.to_byte_prefix();
assert_eq!(bytes, [0x24, 0x68, 0xAC, 0xF1, 0x20]);
// Round-trip
let id = GrainId::from_u64(0x123456789)?;
assert_eq!(GrainId::from_byte_prefix(&id.to_byte_prefix()), id);Sourcepub const fn to_byte_suffix(self) -> [u8; 5]
pub const fn to_byte_suffix(self) -> [u8; 5]
Returns a 5-byte array with the GrainId value stored in the trailing (least significant) 35 bits.
This is the counterpart to from_byte_suffix.
The upper 5 bits of the first byte are always zero.
§Examples
let bytes = GrainId::from_u64(0x123456789)?.to_byte_suffix();
assert_eq!(bytes, [0x01, 0x23, 0x45, 0x67, 0x89]);
// Round-trip
let id = GrainId::from_u64(0x123456789)?;
assert_eq!(GrainId::from_byte_suffix(&id.to_byte_suffix()), id);Sourcepub const fn increment(self) -> GrainId
pub const fn increment(self) -> GrainId
Increments the value by 1, wrapping around to GrainId::NIL on overflow.
§Examples
assert_eq!(GrainId::from_u64(100)?.increment(), GrainId::from_u64(101)?);
assert_eq!(GrainId::MAX.increment(), GrainId::NIL);Source§impl GrainId
impl GrainId
Sourcepub fn from_timestamp_unix<T>(timestamp: T) -> GrainIdwhere
T: Into<SystemTime>,
pub fn from_timestamp_unix<T>(timestamp: T) -> GrainIdwhere
T: Into<SystemTime>,
Creates a GrainId from a Duration from UNIX_EPOCH to timestamp based on decisecond precision.
See GrainId::from_duration and GrainId::from_timestamp_since for more details.
§Examples
use chrono::Utc;
let timestamp = Utc::now();
let id = GrainId::from_timestamp_unix(timestamp);
assert_eq!(id.to_u64(), ((timestamp.timestamp_millis() / 100) as u64));Sourcepub fn from_timestamp_since<T, U>(timestamp: T, base_time: U) -> GrainId
pub fn from_timestamp_since<T, U>(timestamp: T, base_time: U) -> GrainId
Creates a GrainId from a Duration from base_time to timestamp based on decisecond precision.
See GrainId::from_duration for more details.
§Behavior when timestamp is earlier than base_time
If timestamp is earlier than base_time, Returns the value obtained by wrapping substracting the absolute value of the duration from NIL
§Examples
use chrono::NaiveDate;
let base_time = NaiveDate::from_ymd_opt(2025, 1, 1)
.unwrap()
.and_hms_opt(0, 0, 0)
.unwrap()
.and_utc();
let timestamp = NaiveDate::from_ymd_opt(2025, 11, 28)
.unwrap()
.and_hms_micro_opt(12, 34, 56, 789)
.unwrap()
.and_utc();
let id = GrainId::from_timestamp_since(timestamp, base_time);
assert_eq!(
id.to_u64(),
(((timestamp - base_time).num_milliseconds() / 100) as u64)
);Sourcepub fn now_unix() -> GrainId
pub fn now_unix() -> GrainId
Creates a GrainId from a Duration from UNIX_EPOCH to SystemTime::now() based on decisecond precision.
See GrainId::from_duration and GrainId::from_timestamp_since for more details.
Sourcepub fn now_since<T>(base_time: T) -> GrainIdwhere
T: Into<SystemTime>,
pub fn now_since<T>(base_time: T) -> GrainIdwhere
T: Into<SystemTime>,
Creates a GrainId from a Duration from base_time to SystemTime::now() based on decisecond precision.
See GrainId::from_duration and GrainId::from_timestamp_since for more details.
Trait Implementations§
impl Copy for GrainId
Source§impl<'de> Deserialize<'de> for GrainId
impl<'de> Deserialize<'de> for GrainId
Source§fn deserialize<D>(
deserializer: D,
) -> Result<GrainId, <D as Deserializer<'de>>::Error>where
D: Deserializer<'de>,
fn deserialize<D>(
deserializer: D,
) -> Result<GrainId, <D as Deserializer<'de>>::Error>where
D: Deserializer<'de>,
impl Eq for GrainId
Source§impl Ord for GrainId
impl Ord for GrainId
1.21.0 (const: unstable) · Source§fn max(self, other: Self) -> Selfwhere
Self: Sized,
fn max(self, other: Self) -> Selfwhere
Self: Sized,
1.21.0 (const: unstable) · Source§fn min(self, other: Self) -> Selfwhere
Self: Sized,
fn min(self, other: Self) -> Selfwhere
Self: Sized,
Source§impl PartialOrd for GrainId
impl PartialOrd for GrainId
Source§impl Serialize for GrainId
impl Serialize for GrainId
Source§fn serialize<S>(
&self,
serializer: S,
) -> Result<<S as Serializer>::Ok, <S as Serializer>::Error>where
S: Serializer,
fn serialize<S>(
&self,
serializer: S,
) -> Result<<S as Serializer>::Ok, <S as Serializer>::Error>where
S: Serializer,
impl StructuralPartialEq for GrainId
Source§impl TryFrom<u64> for GrainId
impl TryFrom<u64> for GrainId
Source§fn try_from(value: u64) -> Result<GrainId, <GrainId as TryFrom<u64>>::Error>
fn try_from(value: u64) -> Result<GrainId, <GrainId as TryFrom<u64>>::Error>
Attempts to convert a u64 to GrainId.
§Error
Return error if the value is larger than GrainId::MAX.
If you don’t need to detect out-of-range values, use from_u64_lossy.
§Examples
assert!(GrainId::try_from(GrainId::CAPACITY - 1).is_ok());
assert!(GrainId::try_from(GrainId::CAPACITY).is_err());