@@ -50,11 +50,24 @@ static inline php_uuid_v7_object *php_uuid_v7_object_from_obj(zend_object *objec
5050
5151#define Z_UUID_V7_OBJECT_P (zv ) php_uuid_v7_object_from_obj(Z_OBJ_P((zv)))
5252
53+ static zend_always_inline bool php_uuid_v7_is_valid (const php_uuid_v7 uuid )
54+ {
55+ return (uuid [6 ] & 0xf0 ) == 0x70 && (uuid [8 ] & 0xc0 ) == 0x80 ;
56+ }
57+
5358ZEND_ATTRIBUTE_NONNULL_ARGS (1 ) PHPAPI zend_result php_uuid_v7_parse (const zend_string * uuid_str , php_uuid_v7 uuid )
5459{
5560 int result = uuidv7_from_string (ZSTR_VAL (uuid_str ), uuid );
61+ if (result != 0 ) {
62+ return FAILURE ;
63+ }
5664
57- return result == 0 ? SUCCESS : FAILURE ;
65+ return php_uuid_v7_is_valid (uuid ) ? SUCCESS : FAILURE ;
66+ }
67+
68+ ZEND_ATTRIBUTE_NONNULL PHPAPI zend_string * php_uuid_v7_to_bytes (const uint8_t * uuid )
69+ {
70+ return zend_string_init ((const char * ) uuid , 16 , false);
5871}
5972
6073ZEND_ATTRIBUTE_NONNULL PHPAPI zend_string * php_uuid_v7_to_string (const uint8_t * uuid )
@@ -90,12 +103,12 @@ PHP_METHOD(Uuid_UuidV7, parse)
90103 object_init_ex (return_value , Z_CE_P (ZEND_THIS ));
91104 php_uuid_v7_object * uuid_object = Z_UUID_V7_OBJECT_P (return_value );
92105
93- if (uuidv7_from_string ( ZSTR_VAL ( uuid_str ) , uuid_object -> uuid ) == FAILURE ) {
94- zend_throw_exception ( NULL , "The specified UUID v7 is malformed" , 0 );
95- RETURN_THROWS ();
106+ if (php_uuid_v7_parse ( uuid_str , uuid_object -> uuid ) == FAILURE ) {
107+ zval_ptr_dtor ( return_value );
108+ RETURN_NULL ();
96109 }
97110
98- uuid_object -> is_initialized = false ;
111+ uuid_object -> is_initialized = true ;
99112}
100113
101114PHP_METHOD (Uuid_UuidV7 , generate )
@@ -113,7 +126,10 @@ PHP_METHOD(Uuid_UuidV7, generate)
113126
114127 uint64_t unix_time_ms ;
115128 if (datetime_object == NULL ) {
116- unix_time_ms = zend_time_mono_fallback_nsec () / 1000000 ;
129+ struct timespec ts ;
130+ zend_time_real_spec (& ts );
131+
132+ unix_time_ms = ts .tv_sec * 1000 + ts .tv_nsec / 1000000 ;
117133 } else {
118134 php_date_obj * datetime = php_date_obj_from_obj (datetime_object );
119135 if (!datetime -> time ) {
@@ -132,17 +148,17 @@ PHP_METHOD(Uuid_UuidV7, generate)
132148 unix_time_ms = (uint64_t ) Z_LVAL (zv_timestamp ) * 1000 ;
133149 }
134150
135- php_random_algo_with_state random_algo ;
151+ php_random_algo_with_state random_engine ;
136152 if (random_engine_object == NULL ) {
137- random_algo = php_random_default_engine ();
153+ random_engine .algo = & php_random_algo_secure ;
154+ random_engine .state = NULL ;
138155 } else {
139- php_random_engine * random_engine = php_random_engine_from_obj (random_engine_object );
140- random_algo = random_engine -> engine ;
156+ random_engine = php_random_engine_from_obj (random_engine_object )-> engine ;
141157 }
142158
143159 uint8_t random_bytes [10 ];
144160 for (int i = 0 ; i < 10 ; i ++ ) {
145- random_bytes [i ] = php_random_range (random_algo , 0 , 127 );
161+ random_bytes [i ] = php_random_range (random_engine , 0 , 255 );
146162 }
147163
148164 int8_t result = uuidv7_generate (uuid_object -> uuid , unix_time_ms , random_bytes , NULL );
@@ -156,11 +172,13 @@ PHP_METHOD(Uuid_UuidV7, generate)
156172 case UUIDV7_STATUS_TIMESTAMP_INC :
157173 ZEND_FALLTHROUGH ;
158174 case UUIDV7_STATUS_CLOCK_ROLLBACK :
159- ZEND_FALLTHROUGH ;
175+ break ;
160176 case UUIDV7_STATUS_ERR_TIMESTAMP :
161- ZEND_FALLTHROUGH ;
177+ zend_throw_error (NULL , "The generated UUID v7 timestamp is out of range" );
178+ RETURN_THROWS ();
162179 case UUIDV7_STATUS_ERR_TIMESTAMP_OVERFLOW :
163- break ;
180+ zend_throw_error (NULL , "The generated UUID v7 timestamp overflowed" );
181+ RETURN_THROWS ();
164182 default : ZEND_UNREACHABLE ();
165183 }
166184
@@ -169,9 +187,20 @@ PHP_METHOD(Uuid_UuidV7, generate)
169187
170188PHP_METHOD (Uuid_UuidV7 , __construct )
171189{
172- ZEND_PARSE_PARAMETERS_NONE ();
190+ zend_string * uuid_str ;
191+
192+ ZEND_PARSE_PARAMETERS_START (1 , 1 )
193+ Z_PARAM_STR (uuid_str )
194+ ZEND_PARSE_PARAMETERS_END ();
195+
196+ php_uuid_v7_object * uuid_object = Z_UUID_V7_OBJECT_P (ZEND_THIS );
173197
174- zend_throw_error (NULL , "Cannot directly construct %s, use the static factory methods instead" , ZSTR_VAL (Z_OBJCE_P (ZEND_THIS )-> name ));
198+ if (php_uuid_v7_parse (uuid_str , uuid_object -> uuid ) == FAILURE ) {
199+ zend_throw_exception (NULL , "The specified UUID v7 is malformed" , 0 );
200+ RETURN_THROWS ();
201+ }
202+
203+ uuid_object -> is_initialized = true;
175204}
176205
177206PHP_METHOD (Uuid_UuidV7 , equals )
@@ -209,7 +238,7 @@ PHP_METHOD(Uuid_UuidV7, toBytes)
209238
210239 php_uuid_v7_object * uuid_object = Z_UUID_V7_OBJECT_P (ZEND_THIS );
211240
212- RETURN_STR (php_uuid_v7_to_string (uuid_object -> uuid ));
241+ RETURN_STR (php_uuid_v7_to_bytes (uuid_object -> uuid ));
213242}
214243
215244PHP_METHOD (Uuid_UuidV7 , toString )
@@ -302,6 +331,8 @@ PHP_METHOD(Uuid_UuidV7, __unserialize)
302331 zend_throw_exception_ex (NULL , 0 , "Invalid serialization data for %s object" , ZSTR_VAL (uuid_object -> std .ce -> name ));
303332 RETURN_THROWS ();
304333 }
334+
335+ uuid_object -> is_initialized = true;
305336}
306337
307338PHP_METHOD (Uuid_UuidV7 , __debugInfo )
@@ -343,6 +374,7 @@ ZEND_ATTRIBUTE_NONNULL zend_object *php_uuid_v7_object_handler_clone(zend_object
343374 php_uuid_v7_object * new_uuid_object = php_uuid_v7_object_from_obj (object -> ce -> create_object (object -> ce ));
344375
345376 memcpy (new_uuid_object -> uuid , uuid_object -> uuid , sizeof (php_uuid_v7 ));
377+ new_uuid_object -> is_initialized = true;
346378 zend_objects_clone_members (& new_uuid_object -> std , & uuid_object -> std );
347379
348380 return & new_uuid_object -> std ;
0 commit comments