@@ -3,50 +3,63 @@ use std::fmt::{Display, Formatter};
3
3
4
4
use minicbor:: { Decode , Decoder , Encode } ;
5
5
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 } ;
7
7
8
8
/// 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 ) ;
16
11
17
12
impl UuidV7 {
18
13
/// Version for `UUIDv7`.
19
14
const UUID_VERSION_NUMBER : usize = 7 ;
20
15
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
+
21
23
/// Generates a zeroed out `UUIDv7` that can never be valid.
22
24
#[ must_use]
23
25
pub fn invalid ( ) -> Self {
24
- Self { uuid : INVALID_UUID }
26
+ Self ( INVALID_UUID )
25
27
}
26
28
27
29
/// Check if this is a valid `UUIDv7`.
28
30
#[ must_use]
29
31
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 )
31
33
}
32
34
33
35
/// Returns the `uuid::Uuid` type.
34
36
#[ must_use]
35
37
pub fn uuid ( & self ) -> uuid:: Uuid {
36
- self . uuid
38
+ self . 0
37
39
}
38
40
}
39
41
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
+
40
47
impl Display for UuidV7 {
41
48
fn fmt ( & self , f : & mut Formatter < ' _ > ) -> Result < ( ) , std:: fmt:: Error > {
42
- write ! ( f, "{}" , self . uuid )
49
+ write ! ( f, "{}" , self . 0 )
43
50
}
44
51
}
45
52
46
53
impl Decode < ' _ , CborContext > for UuidV7 {
47
54
fn decode ( d : & mut Decoder < ' _ > , ctx : & mut CborContext ) -> Result < Self , minicbor:: decode:: Error > {
48
55
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
+ }
50
63
}
51
64
}
52
65
@@ -59,11 +72,15 @@ impl Encode<CborContext> for UuidV7 {
59
72
}
60
73
61
74
/// 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
+ }
67
84
}
68
85
}
69
86
@@ -72,7 +89,19 @@ impl From<uuid::Uuid> for UuidV7 {
72
89
/// NOTE: This does not guarantee that the `UUID` is valid.
73
90
impl From < UuidV7 > for uuid:: Uuid {
74
91
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
+ }
76
105
}
77
106
}
78
107
@@ -95,16 +124,17 @@ mod tests {
95
124
96
125
#[ test]
97
126
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 ( ) ;
100
131
assert ! ( valid_uuid. is_valid( ) , "Valid UUID should be valid" ) ;
101
132
}
102
133
103
134
#[ test]
104
135
fn test_invalid_version_uuid ( ) {
105
- let invalid_version_uuid = UuidV7 :: from ( Uuid :: from_u128 ( 0 ) ) ;
106
136
assert ! (
107
- !invalid_version_uuid . is_valid ( ) ,
137
+ UuidV7 :: try_from ( INVALID_UUID ) . is_err ( ) ,
108
138
"Zero UUID should not be valid"
109
139
) ;
110
140
}
0 commit comments