1use std::{fmt, num::NonZeroU128};
5
6use crate::{
7 error::{Error, ErrorKind},
8 Uuid,
9};
10
11#[repr(transparent)]
35#[derive(Copy, Clone, PartialEq, Eq, Hash)]
36pub struct NonNilUuid(NonZeroU128);
37
38impl fmt::Debug for NonNilUuid {
39 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
40 fmt::Debug::fmt(&Uuid::from(*self), f)
41 }
42}
43
44impl fmt::Display for NonNilUuid {
45 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
46 fmt::Display::fmt(&Uuid::from(*self), f)
47 }
48}
49
50impl PartialEq<Uuid> for NonNilUuid {
51 fn eq(&self, other: &Uuid) -> bool {
52 self.get() == *other
53 }
54}
55
56impl PartialEq<NonNilUuid> for Uuid {
57 fn eq(&self, other: &NonNilUuid) -> bool {
58 *self == other.get()
59 }
60}
61
62impl NonNilUuid {
63 pub const fn new(uuid: Uuid) -> Option<Self> {
65 match NonZeroU128::new(uuid.as_u128()) {
66 Some(non_nil) => Some(NonNilUuid(non_nil)),
67 None => None,
68 }
69 }
70
71 pub const unsafe fn new_unchecked(uuid: Uuid) -> Self {
77 NonNilUuid(unsafe { NonZeroU128::new_unchecked(uuid.as_u128()) })
78 }
79
80 #[inline]
82 pub const fn get(self) -> Uuid {
83 Uuid::from_u128(self.0.get())
84 }
85}
86
87impl From<NonNilUuid> for Uuid {
88 fn from(non_nil: NonNilUuid) -> Self {
100 Uuid::from_u128(non_nil.0.get())
101 }
102}
103
104impl TryFrom<Uuid> for NonNilUuid {
105 type Error = Error;
106
107 fn try_from(uuid: Uuid) -> Result<Self, Self::Error> {
116 NonZeroU128::new(uuid.as_u128())
117 .map(Self)
118 .ok_or(Error(ErrorKind::Nil))
119 }
120}
121
122#[cfg(test)]
123mod tests {
124 use super::*;
125
126 #[test]
127 fn test_non_nil_with_option_size() {
128 assert_eq!(
129 std::mem::size_of::<Option<NonNilUuid>>(),
130 std::mem::size_of::<Uuid>()
131 );
132 }
133
134 #[test]
135 fn test_non_nil() {
136 let uuid = Uuid::from_u128(0x0123456789abcdef0123456789abcdef);
137
138 assert_eq!(Uuid::from(NonNilUuid::try_from(uuid).unwrap()), uuid);
139 assert_eq!(NonNilUuid::new(uuid).unwrap(), uuid);
140 assert_eq!(unsafe { NonNilUuid::new_unchecked(uuid) }, uuid);
141
142 assert!(NonNilUuid::try_from(Uuid::nil()).is_err());
143 assert!(NonNilUuid::new(Uuid::nil()).is_none());
144 }
145
146 #[test]
147 fn test_non_nil_formatting() {
148 let uuid = Uuid::from_u128(0x0123456789abcdef0123456789abcdef);
149 let non_nil = NonNilUuid::try_from(uuid).unwrap();
150
151 assert_eq!(format!("{uuid}"), format!("{non_nil}"));
152 assert_eq!(format!("{uuid:?}"), format!("{non_nil:?}"));
153 }
154}