@@ -3,50 +3,63 @@ use std::fmt::{Display, Formatter};
33
44use minicbor:: { Decode , Decoder , Encode } ;
55
6- use super :: { decode_cbor_uuid, encode_cbor_uuid, CborContext , INVALID_UUID } ;
6+ use super :: { decode_cbor_uuid, encode_cbor_uuid, CborContext , UuidError , INVALID_UUID } ;
77
88/// Type representing a `UUIDv7`.
9- #[ derive( Copy , Clone , Debug , PartialEq , PartialOrd , serde:: Serialize , serde:: Deserialize ) ]
10- #[ serde( from = "uuid::Uuid" ) ]
11- #[ serde( into = "uuid::Uuid" ) ]
12- pub struct UuidV7 {
13- /// UUID
14- uuid : uuid:: Uuid ,
15- }
9+ #[ derive( Copy , Clone , Debug , PartialEq , PartialOrd , serde:: Serialize ) ]
10+ pub struct UuidV7 ( uuid:: Uuid ) ;
1611
1712impl UuidV7 {
1813 /// Version for `UUIDv7`.
1914 const UUID_VERSION_NUMBER : usize = 7 ;
2015
16+ /// Generates a random `UUIDv4`.
17+ #[ must_use]
18+ #[ allow( clippy:: new_without_default) ]
19+ pub fn new ( ) -> Self {
20+ Self ( uuid:: Uuid :: now_v7 ( ) )
21+ }
22+
2123 /// Generates a zeroed out `UUIDv7` that can never be valid.
2224 #[ must_use]
2325 pub fn invalid ( ) -> Self {
24- Self { uuid : INVALID_UUID }
26+ Self ( INVALID_UUID )
2527 }
2628
2729 /// Check if this is a valid `UUIDv7`.
2830 #[ must_use]
2931 pub fn is_valid ( & self ) -> bool {
30- self . uuid != INVALID_UUID && self . uuid . get_version_num ( ) == Self :: UUID_VERSION_NUMBER
32+ is_valid ( & self . 0 )
3133 }
3234
3335 /// Returns the `uuid::Uuid` type.
3436 #[ must_use]
3537 pub fn uuid ( & self ) -> uuid:: Uuid {
36- self . uuid
38+ self . 0
3739 }
3840}
3941
42+ /// Check if this is a valid `UUIDv7`.
43+ fn is_valid ( uuid : & uuid:: Uuid ) -> bool {
44+ uuid != & INVALID_UUID && uuid. get_version_num ( ) == UuidV7 :: UUID_VERSION_NUMBER
45+ }
46+
4047impl Display for UuidV7 {
4148 fn fmt ( & self , f : & mut Formatter < ' _ > ) -> Result < ( ) , std:: fmt:: Error > {
42- write ! ( f, "{}" , self . uuid )
49+ write ! ( f, "{}" , self . 0 )
4350 }
4451}
4552
4653impl Decode < ' _ , CborContext > for UuidV7 {
4754 fn decode ( d : & mut Decoder < ' _ > , ctx : & mut CborContext ) -> Result < Self , minicbor:: decode:: Error > {
4855 let uuid = decode_cbor_uuid ( d, ctx) ?;
49- Ok ( Self { uuid } )
56+ if is_valid ( & uuid) {
57+ Ok ( Self ( uuid) )
58+ } else {
59+ Err ( minicbor:: decode:: Error :: message ( UuidError :: InvalidUuidV7 (
60+ uuid,
61+ ) ) )
62+ }
5063 }
5164}
5265
@@ -59,11 +72,15 @@ impl Encode<CborContext> for UuidV7 {
5972}
6073
6174/// Returns a `UUIDv7` from `uuid::Uuid`.
62- ///
63- /// NOTE: This does not guarantee that the `UUID` is valid.
64- impl From < uuid:: Uuid > for UuidV7 {
65- fn from ( uuid : uuid:: Uuid ) -> Self {
66- Self { uuid }
75+ impl TryFrom < uuid:: Uuid > for UuidV7 {
76+ type Error = UuidError ;
77+
78+ fn try_from ( uuid : uuid:: Uuid ) -> Result < Self , Self :: Error > {
79+ if is_valid ( & uuid) {
80+ Ok ( Self ( uuid) )
81+ } else {
82+ Err ( UuidError :: InvalidUuidV7 ( uuid) )
83+ }
6784 }
6885}
6986
@@ -72,7 +89,19 @@ impl From<uuid::Uuid> for UuidV7 {
7289/// NOTE: This does not guarantee that the `UUID` is valid.
7390impl From < UuidV7 > for uuid:: Uuid {
7491 fn from ( value : UuidV7 ) -> Self {
75- value. uuid
92+ value. 0
93+ }
94+ }
95+
96+ impl < ' de > serde:: Deserialize < ' de > for UuidV7 {
97+ fn deserialize < D > ( deserializer : D ) -> Result < Self , D :: Error >
98+ where D : serde:: Deserializer < ' de > {
99+ let uuid = uuid:: Uuid :: deserialize ( deserializer) ?;
100+ if is_valid ( & uuid) {
101+ Ok ( Self ( uuid) )
102+ } else {
103+ Err ( serde:: de:: Error :: custom ( UuidError :: InvalidUuidV7 ( uuid) ) )
104+ }
76105 }
77106}
78107
@@ -95,16 +124,17 @@ mod tests {
95124
96125 #[ test]
97126 fn test_valid_uuid ( ) {
98- let valid_uuid =
99- UuidV7 :: from ( Uuid :: try_parse ( "017f22e3-79b0-7cc7-98cf-e0bbf8a1c5f1" ) . unwrap ( ) ) ;
127+ let valid_uuid = UuidV7 :: try_from ( Uuid :: now_v7 ( ) ) . unwrap ( ) ;
128+ assert ! ( valid_uuid. is_valid( ) , "Valid UUID should be valid" ) ;
129+
130+ let valid_uuid = UuidV7 :: new ( ) ;
100131 assert ! ( valid_uuid. is_valid( ) , "Valid UUID should be valid" ) ;
101132 }
102133
103134 #[ test]
104135 fn test_invalid_version_uuid ( ) {
105- let invalid_version_uuid = UuidV7 :: from ( Uuid :: from_u128 ( 0 ) ) ;
106136 assert ! (
107- !invalid_version_uuid . is_valid ( ) ,
137+ UuidV7 :: try_from ( INVALID_UUID ) . is_err ( ) ,
108138 "Zero UUID should not be valid"
109139 ) ;
110140 }
0 commit comments