fill in a few non-nil methods

This commit is contained in:
KodrAus 2025-01-14 19:15:53 +10:00
parent 618e8174a4
commit 402a8be60c
5 changed files with 57 additions and 16 deletions

View File

@ -30,6 +30,8 @@ pub(crate) enum ErrorKind {
},
/// The input was not a valid UTF8 string
InvalidUTF8,
/// The UUID is nil.
Nil,
/// Some other error occurred.
Other,
}
@ -158,6 +160,7 @@ impl fmt::Display for Error {
)
}
ErrorKind::InvalidUTF8 => write!(f, "non-UTF8 input"),
ErrorKind::Nil => write!(f, "the UUID is nil"),
ErrorKind::Other => write!(f, "failed to parse a UUID"),
}
}

View File

@ -227,10 +227,10 @@ use zerocopy::{FromBytes, Immutable, IntoBytes, KnownLayout, Unaligned};
mod builder;
mod error;
mod non_nil;
mod parser;
pub mod fmt;
pub mod non_nil;
pub mod timestamp;
pub use timestamp::{context::NoContext, ClockSequence, Timestamp};
@ -282,7 +282,7 @@ pub mod __macro_support {
use crate::std::convert;
pub use crate::{builder::Builder, error::Error};
pub use crate::{builder::Builder, error::Error, non_nil::NonNilUuid};
/// A 128-bit (16 byte) buffer containing the UUID.
///

View File

@ -4,12 +4,28 @@
use core::convert::TryFrom;
use std::{fmt, num::NonZeroU128};
use crate::Uuid;
use crate::{
error::{Error, ErrorKind},
Uuid,
};
/// A UUID that is guaranteed not to be the nil UUID.
///
/// This is useful for representing optional UUIDs more efficiently, as `Option<NonNilUuid>`
/// takes up the same space as `Uuid`.
///
/// Note that `Uuid`s created by the following methods are guaranteed to be non-nil:
///
/// - [`Uuid::new_v1`]
/// - [`Uuid::now_v1`]
/// - [`Uuid::new_v3`]
/// - [`Uuid::new_v4`]
/// - [`Uuid::new_v5`]
/// - [`Uuid::new_v6`]
/// - [`Uuid::now_v6`]
/// - [`Uuid::new_v7`]
/// - [`Uuid::now_v7`]
/// - [`Uuid::new_v8`]
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
pub struct NonNilUuid(NonZeroU128);
@ -20,7 +36,24 @@ impl fmt::Display for NonNilUuid {
}
impl NonNilUuid {
/// Returns the underlying `Uuid`.
/// Creates a non-nil UUID if the value is non-nil.
pub const fn new(uuid: Uuid) -> Option<Self> {
match NonZeroU128::new(uuid.as_u128()) {
Some(non_nil) => Some(NonNilUuid(non_nil)),
None => None,
}
}
/// Creates a non-nil without checking whether the value is non-nil. This results in undefined behavior if the value is nil.
///
/// # Safety
///
/// The value must not be nil.
pub const unsafe fn new_unchecked(uuid: Uuid) -> Self {
NonNilUuid(unsafe { NonZeroU128::new_unchecked(uuid.as_u128()) })
}
/// Get the underlying [`Uuid`] value.
#[inline]
pub const fn get(self) -> Uuid {
Uuid::from_u128(self.0.get())
@ -47,7 +80,7 @@ impl From<NonNilUuid> for Uuid {
}
impl TryFrom<Uuid> for NonNilUuid {
type Error = &'static str;
type Error = Error;
/// Attempts to convert a [`Uuid`] into a [`NonNilUuid`].
///
@ -62,7 +95,7 @@ impl TryFrom<Uuid> for NonNilUuid {
fn try_from(uuid: Uuid) -> Result<Self, Self::Error> {
NonZeroU128::new(uuid.as_u128())
.map(Self)
.ok_or("Attempted to convert nil Uuid to NonNilUuid")
.ok_or(Error(ErrorKind::Nil))
}
}
@ -81,13 +114,12 @@ mod tests {
#[test]
fn test_non_nil() {
let uuid = Uuid::from_u128(0x0123456789abcdef0123456789abcdef);
let nn_uuid = NonNilUuid::try_from(uuid);
assert!(nn_uuid.is_ok());
assert_eq!(Uuid::from(nn_uuid.unwrap()), uuid);
assert_eq!(Uuid::from(NonNilUuid::try_from(uuid).unwrap()), uuid);
assert_eq!(NonNilUuid::new(uuid).unwrap().get(), uuid);
assert_eq!(unsafe { NonNilUuid::new_unchecked(uuid) }.get(), uuid);
let nil_uuid = Uuid::nil();
let nn_uuid = NonNilUuid::try_from(nil_uuid);
assert!(nn_uuid.is_err());
assert!(NonNilUuid::try_from(Uuid::nil()).is_err());
assert!(NonNilUuid::new(Uuid::nil()).is_none());
}
}

View File

@ -128,7 +128,7 @@ impl Timestamp {
///
/// If conversion from the internal timestamp format to ticks would overflow
/// then it will wrap.
///
///
/// If the internal counter is wider than 14 bits then it will be truncated to 14 bits.
pub const fn to_gregorian(&self) -> (u64, u16) {
(
@ -165,7 +165,10 @@ impl Timestamp {
#[doc(hidden)]
impl Timestamp {
#[deprecated(since = "1.11.1", note = "use `Timestamp::from_gregorian(ticks, counter)`")]
#[deprecated(
since = "1.11.1",
note = "use `Timestamp::from_gregorian(ticks, counter)`"
)]
pub const fn from_rfc4122(ticks: u64, counter: u16) -> Self {
Timestamp::from_gregorian(ticks, counter)
}
@ -175,7 +178,10 @@ impl Timestamp {
self.to_gregorian()
}
#[deprecated(since = "1.2.0", note = "`Timestamp::to_unix_nanos()` is deprecated and will be removed: use `Timestamp::to_unix()`")]
#[deprecated(
since = "1.2.0",
note = "`Timestamp::to_unix_nanos()` is deprecated and will be removed: use `Timestamp::to_unix()`"
)]
pub const fn to_unix_nanos(&self) -> u32 {
panic!("`Timestamp::to_unix_nanos()` is deprecated and will be removed: use `Timestamp::to_unix()`")
}

View File

@ -31,7 +31,7 @@ impl Uuid {
/// # Examples
///
/// A v7 UUID can be created from a unix [`Timestamp`] plus a 128 bit
/// random number. When supplied as such, the data will be combined
/// random number. When supplied as such, the data will be combined
/// to ensure uniqueness and sortability at millisecond granularity.
///
/// ```rust