22use std:: fmt:: { Display , Formatter } ;
33
44use minicbor:: { Decode , Decoder , Encode } ;
5+ use uuid:: Uuid ;
56
6- use super :: { decode_cbor_uuid, encode_cbor_uuid, CborContext , INVALID_UUID } ;
7+ use super :: { decode_cbor_uuid, encode_cbor_uuid, CborContext , UuidError , INVALID_UUID } ;
78
89/// Type representing a `UUIDv4`.
9- #[ derive( Copy , Clone , Debug , PartialEq , PartialOrd , serde:: Serialize , serde:: Deserialize ) ]
10- #[ serde( from = "uuid::Uuid" ) ]
11- #[ serde( into = "uuid::Uuid" ) ]
12- pub struct UuidV4 {
13- /// UUID
14- uuid : uuid:: Uuid ,
15- }
10+ #[ derive( Copy , Clone , Debug , PartialEq , PartialOrd , serde:: Serialize ) ]
11+ pub struct UuidV4 ( Uuid ) ;
1612
1713impl UuidV4 {
1814 /// Version for `UUIDv4`.
1915 const UUID_VERSION_NUMBER : usize = 4 ;
2016
17+ /// Generates a random `UUIDv4`.
18+ #[ must_use]
19+ #[ allow( clippy:: new_without_default) ]
20+ pub fn new ( ) -> Self {
21+ Self ( Uuid :: new_v4 ( ) )
22+ }
23+
2124 /// Generates a zeroed out `UUIDv4` that can never be valid.
2225 #[ must_use]
2326 pub fn invalid ( ) -> Self {
24- Self { uuid : INVALID_UUID }
27+ Self ( INVALID_UUID )
2528 }
2629
2730 /// Check if this is a valid `UUIDv4`.
2831 #[ must_use]
2932 pub fn is_valid ( & self ) -> bool {
30- self . uuid != INVALID_UUID && self . uuid . get_version_num ( ) == Self :: UUID_VERSION_NUMBER
33+ is_valid ( & self . uuid ( ) )
3134 }
3235
3336 /// Returns the `uuid::Uuid` type.
3437 #[ must_use]
35- pub fn uuid ( & self ) -> uuid :: Uuid {
36- self . uuid
38+ pub fn uuid ( & self ) -> Uuid {
39+ self . 0
3740 }
3841}
3942
43+ /// Check if this is a valid `UUIDv4`.
44+ fn is_valid ( uuid : & Uuid ) -> bool {
45+ uuid != & INVALID_UUID && uuid. get_version_num ( ) == UuidV4 :: UUID_VERSION_NUMBER
46+ }
47+
4048impl Display for UuidV4 {
4149 fn fmt ( & self , f : & mut Formatter < ' _ > ) -> Result < ( ) , std:: fmt:: Error > {
42- write ! ( f, "{}" , self . uuid )
50+ write ! ( f, "{}" , self . 0 )
4351 }
4452}
4553
4654impl Decode < ' _ , CborContext > for UuidV4 {
4755 fn decode ( d : & mut Decoder < ' _ > , ctx : & mut CborContext ) -> Result < Self , minicbor:: decode:: Error > {
4856 let uuid = decode_cbor_uuid ( d, ctx) ?;
49- Ok ( Self { uuid } )
57+ if is_valid ( & uuid) {
58+ Ok ( Self ( uuid) )
59+ } else {
60+ Err ( minicbor:: decode:: Error :: message ( UuidError :: InvalidUuidV4 (
61+ uuid,
62+ ) ) )
63+ }
5064 }
5165}
5266
@@ -59,27 +73,41 @@ impl Encode<CborContext> for UuidV4 {
5973}
6074
6175/// Returns a `UUIDv4` from `uuid::Uuid`.
62- ///
63- /// NOTE: This does not guarantee that the `UUID` is valid.
64- impl From < uuid:: Uuid > for UuidV4 {
65- fn from ( uuid : uuid:: Uuid ) -> Self {
66- Self { uuid }
76+ impl TryFrom < Uuid > for UuidV4 {
77+ type Error = UuidError ;
78+
79+ fn try_from ( uuid : Uuid ) -> Result < Self , Self :: Error > {
80+ if is_valid ( & uuid) {
81+ Ok ( Self ( uuid) )
82+ } else {
83+ Err ( UuidError :: InvalidUuidV4 ( uuid) )
84+ }
6785 }
6886}
6987
7088/// Returns a `uuid::Uuid` from `UUIDv4`.
7189///
7290/// NOTE: This does not guarantee that the `UUID` is valid.
73- impl From < UuidV4 > for uuid :: Uuid {
91+ impl From < UuidV4 > for Uuid {
7492 fn from ( value : UuidV4 ) -> Self {
75- value. uuid
93+ value. 0
94+ }
95+ }
96+
97+ impl < ' de > serde:: Deserialize < ' de > for UuidV4 {
98+ fn deserialize < D > ( deserializer : D ) -> Result < Self , D :: Error >
99+ where D : serde:: Deserializer < ' de > {
100+ let uuid = Uuid :: deserialize ( deserializer) ?;
101+ if is_valid ( & uuid) {
102+ Ok ( Self ( uuid) )
103+ } else {
104+ Err ( serde:: de:: Error :: custom ( UuidError :: InvalidUuidV4 ( uuid) ) )
105+ }
76106 }
77107}
78108
79109#[ cfg( test) ]
80110mod tests {
81- use uuid:: Uuid ;
82-
83111 use super :: * ;
84112
85113 #[ test]
@@ -95,15 +123,17 @@ mod tests {
95123
96124 #[ test]
97125 fn test_valid_uuid ( ) {
98- let valid_uuid = UuidV4 :: from ( Uuid :: new_v4 ( ) ) ;
126+ let valid_uuid = UuidV4 :: try_from ( Uuid :: new_v4 ( ) ) . unwrap ( ) ;
127+ assert ! ( valid_uuid. is_valid( ) , "Valid UUID should be valid" ) ;
128+
129+ let valid_uuid = UuidV4 :: new ( ) ;
99130 assert ! ( valid_uuid. is_valid( ) , "Valid UUID should be valid" ) ;
100131 }
101132
102133 #[ test]
103134 fn test_invalid_version_uuid ( ) {
104- let invalid_version_uuid = UuidV4 :: from ( Uuid :: from_u128 ( 0 ) ) ;
105135 assert ! (
106- !invalid_version_uuid . is_valid ( ) ,
136+ UuidV4 :: try_from ( INVALID_UUID ) . is_err ( ) ,
107137 "Zero UUID should not be valid"
108138 ) ;
109139 }
0 commit comments