@@ -6,12 +6,37 @@ mod to_type_hash;
6
6
7
7
use core:: fmt;
8
8
use core:: hash:: { BuildHasher , BuildHasherDefault , Hash as _, Hasher } ;
9
+ use core:: num:: NonZero ;
9
10
10
11
#[ cfg( feature = "musli" ) ]
11
12
use musli:: { Decode , Encode } ;
12
13
use serde:: { Deserialize , Serialize } ;
13
14
use twox_hash:: XxHash64 ;
14
15
16
+ /// Error raised when too many parameters are added to a [`ParametersBuilder`].
17
+ ///
18
+ /// # Examples
19
+ ///
20
+ /// ```
21
+ /// use rune::TypeHash;
22
+ /// use rune::hash::ParametersBuilder;
23
+ ///
24
+ /// let mut params = ParametersBuilder::new();
25
+ ///
26
+ /// let err = 'outer: {
27
+ /// for _ in 0.. {
28
+ /// params = match params.add(i64::HASH) {
29
+ /// Ok(params) => params,
30
+ /// Err(err) => break 'outer err,
31
+ /// };
32
+ /// };
33
+ ///
34
+ /// panic!("expected error");
35
+ /// };
36
+ ///
37
+ /// let err = err.to_string();
38
+ /// # Ok::<_, rune::hash::TooManyParameters>(())
39
+ /// ```
15
40
#[ derive( Debug ) ]
16
41
#[ non_exhaustive]
17
42
pub struct TooManyParameters ;
@@ -75,13 +100,90 @@ const PARAMETERS: [u64; 32] = [
75
100
76
101
/// The primitive hash that among other things is used to reference items,
77
102
/// types, and native functions.
103
+ ///
104
+ /// # Examples
105
+ ///
106
+ /// ```
107
+ /// use rune::Hash;
108
+ ///
109
+ /// assert!(Hash::index(0).as_non_empty().is_some());
110
+ /// ```
111
+ #[ derive( Clone , Copy , PartialEq , Eq , PartialOrd , Ord , Hash , Serialize , Deserialize ) ]
112
+ #[ cfg_attr( feature = "musli" , derive( Decode , Encode ) , musli( transparent) ) ]
113
+ #[ repr( transparent) ]
114
+ pub struct NonZeroHash ( #[ doc( hidden) ] pub NonZero < u64 > ) ;
115
+
116
+ impl NonZeroHash {
117
+ /// Get the value as a hash.
118
+ ///
119
+ /// # Examples
120
+ ///
121
+ /// ```
122
+ /// use rune::Hash;
123
+ ///
124
+ /// let hash = Hash::index(0).as_non_empty().ok_or("expected non-empty")?;
125
+ /// assert_eq!(hash.get(), Hash::index(0));
126
+ /// # Ok::<_, &'static str>(())
127
+ /// ```
128
+ pub const fn get ( self ) -> Hash {
129
+ Hash ( self . 0 . get ( ) )
130
+ }
131
+ }
132
+
133
+ impl TryClone for NonZeroHash {
134
+ #[ inline]
135
+ fn try_clone ( & self ) -> alloc:: Result < Self > {
136
+ Ok ( * self )
137
+ }
138
+ }
139
+
140
+ impl fmt:: Display for NonZeroHash {
141
+ #[ inline]
142
+ fn fmt ( & self , f : & mut fmt:: Formatter < ' _ > ) -> fmt:: Result {
143
+ write ! ( f, "0x{:x}" , self . 0 . get( ) )
144
+ }
145
+ }
146
+
147
+ impl fmt:: Debug for NonZeroHash {
148
+ #[ inline]
149
+ fn fmt ( & self , f : & mut fmt:: Formatter < ' _ > ) -> fmt:: Result {
150
+ write ! ( f, "0x{:x}" , self . 0 . get( ) )
151
+ }
152
+ }
153
+
154
+ impl PartialEq < Hash > for NonZeroHash {
155
+ #[ inline]
156
+ fn eq ( & self , other : & Hash ) -> bool {
157
+ self . 0 . get ( ) == other. 0
158
+ }
159
+ }
160
+
161
+ /// The primitive hash that among other things is used to reference items,
162
+ /// types, and native functions.
163
+ ///
164
+ /// # Examples
165
+ ///
166
+ /// ```
167
+ /// use rune::Hash;
168
+ ///
169
+ /// assert_ne!(Hash::index(0), Hash::index(1));
170
+ /// ```
78
171
#[ derive( Default , Clone , Copy , PartialEq , Eq , PartialOrd , Ord , Hash , Serialize , Deserialize ) ]
79
172
#[ cfg_attr( feature = "musli" , derive( Decode , Encode ) , musli( transparent) ) ]
80
173
#[ repr( transparent) ]
81
174
pub struct Hash ( #[ doc( hidden) ] pub u64 ) ;
82
175
83
176
impl Hash {
84
177
/// The empty hash.
178
+ ///
179
+ /// # Examples
180
+ ///
181
+ /// ```
182
+ /// use rune::Hash;
183
+ ///
184
+ /// assert_ne!(Hash::index(0), Hash::EMPTY);
185
+ /// assert!(Hash::EMPTY.as_non_empty().is_none());
186
+ /// ```
85
187
pub const EMPTY : Self = Self ( 0 ) ;
86
188
87
189
/// Construct a new raw hash.
@@ -97,13 +199,18 @@ impl Hash {
97
199
}
98
200
99
201
/// Return the current hash if it is non-empty.
202
+ ///
203
+ /// # Examples
204
+ ///
205
+ /// ```
206
+ /// use rune::Hash;
207
+ ///
208
+ /// assert!(Hash::index(0).as_non_empty().is_some());
209
+ /// assert!(Hash::EMPTY.as_non_empty().is_none());
210
+ /// ```
100
211
#[ inline]
101
- pub fn as_non_empty ( & self ) -> Option < Self > {
102
- if self . is_empty ( ) {
103
- None
104
- } else {
105
- Some ( * self )
106
- }
212
+ pub fn as_non_empty ( & self ) -> Option < NonZeroHash > {
213
+ Some ( NonZeroHash ( NonZero :: new ( self . 0 ) ?) )
107
214
}
108
215
109
216
/// Coerce a hash into its inner numerical value.
@@ -119,26 +226,60 @@ impl Hash {
119
226
}
120
227
121
228
/// Construct a hash from an index.
229
+ ///
230
+ /// # Examples
231
+ ///
232
+ /// ```
233
+ /// use rune::Hash;
234
+ ///
235
+ /// assert_ne!(Hash::index(0), Hash::index(1));
236
+ /// ```
122
237
#[ inline]
123
238
pub fn index ( index : usize ) -> Self {
124
239
Self ( INDEX ^ ( index as u64 ) )
125
240
}
126
241
127
242
/// Get the hash corresponding to a string identifier like `function` or
128
243
/// `hello_world`.
244
+ ///
245
+ /// # Examples
246
+ ///
247
+ /// ```
248
+ /// use rune::Hash;
249
+ ///
250
+ /// assert_ne!(Hash::ident("foo"), Hash::index(0));
251
+ /// ```
129
252
pub fn ident ( name : & str ) -> Hash {
130
253
let mut hasher = Self :: new_hasher ( ) ;
131
254
name. hash ( & mut hasher) ;
132
255
Self ( IDENT ^ hasher. finish ( ) )
133
256
}
134
257
135
258
/// Get the hash of a type.
259
+ ///
260
+ /// # Examples
261
+ ///
262
+ /// ```
263
+ /// use rune::Hash;
264
+ ///
265
+ /// assert!(!Hash::type_hash(["main"]).is_empty());
266
+ /// assert!(!Hash::type_hash(["main", "other"]).is_empty());
267
+ /// ```
136
268
pub fn type_hash ( path : impl ToTypeHash ) -> Self {
137
269
path. to_type_hash ( )
138
270
}
139
271
140
272
/// Construct a hash to an instance function, where the instance is a
141
273
/// pre-determined type.
274
+ ///
275
+ /// # Examples
276
+ ///
277
+ /// ```
278
+ /// use rune::Hash;
279
+ /// use rune::runtime::Protocol;
280
+ ///
281
+ /// assert!(!Hash::associated_function("main", &Protocol::INTO_TYPE_NAME).is_empty());
282
+ /// ```
142
283
#[ inline]
143
284
pub fn associated_function ( type_hash : impl IntoHash , name : impl IntoHash ) -> Self {
144
285
let type_hash = type_hash. into_hash ( ) ;
@@ -147,13 +288,31 @@ impl Hash {
147
288
}
148
289
149
290
/// Construct a hash corresponding to a field function.
291
+ ///
292
+ /// # Examples
293
+ ///
294
+ /// ```
295
+ /// use rune::{Hash, TypeHash};
296
+ /// use rune::runtime::Protocol;
297
+ ///
298
+ /// assert!(!Hash::field_function(&Protocol::ADD, i64::HASH, "field").is_empty());
299
+ /// ```
150
300
#[ inline]
151
301
pub fn field_function ( protocol : impl IntoHash , type_hash : Hash , name : impl IntoHash ) -> Self {
152
302
let protocol = protocol. into_hash ( ) ;
153
303
Self :: associated_function ( Hash ( type_hash. 0 ^ protocol. 0 ) , name)
154
304
}
155
305
156
306
/// Construct an index function.
307
+ ///
308
+ /// # Examples
309
+ ///
310
+ /// ```
311
+ /// use rune::{Hash, TypeHash};
312
+ /// use rune::runtime::Protocol;
313
+ ///
314
+ /// assert!(!Hash::index_function(&Protocol::ADD, i64::HASH, Hash::index(1)).is_empty());
315
+ /// ```
157
316
#[ inline]
158
317
pub fn index_function ( protocol : impl IntoHash , type_hash : Hash , index : Hash ) -> Self {
159
318
let protocol = protocol. into_hash ( ) ;
@@ -170,8 +329,7 @@ impl Hash {
170
329
/// Hash the given iterator of object keys.
171
330
pub fn object_keys < I > ( keys : I ) -> Self
172
331
where
173
- I : IntoIterator ,
174
- I :: Item : AsRef < str > ,
332
+ I : IntoIterator < Item : AsRef < str > > ,
175
333
{
176
334
let mut hasher = Self :: new_hasher ( ) ;
177
335
OBJECT_KEYS . hash ( & mut hasher) ;
@@ -226,18 +384,21 @@ impl Hash {
226
384
}
227
385
228
386
impl TryClone for Hash {
387
+ #[ inline]
229
388
fn try_clone ( & self ) -> alloc:: Result < Self > {
230
389
Ok ( * self )
231
390
}
232
391
}
233
392
234
393
impl fmt:: Display for Hash {
394
+ #[ inline]
235
395
fn fmt ( & self , f : & mut fmt:: Formatter < ' _ > ) -> fmt:: Result {
236
396
write ! ( f, "0x{:x}" , self . 0 )
237
397
}
238
398
}
239
399
240
400
impl fmt:: Debug for Hash {
401
+ #[ inline]
241
402
fn fmt ( & self , f : & mut fmt:: Formatter < ' _ > ) -> fmt:: Result {
242
403
write ! ( f, "0x{:x}" , self . 0 )
243
404
}
@@ -273,6 +434,19 @@ pub struct ParametersBuilder {
273
434
274
435
impl ParametersBuilder {
275
436
/// Construct a new collection of parameters.
437
+ ///
438
+ /// # Examples
439
+ ///
440
+ /// ```
441
+ /// use rune::{Hash, TypeHash};
442
+ /// use rune::hash::ParametersBuilder;
443
+ ///
444
+ /// let mut params = ParametersBuilder::new();
445
+ ///
446
+ /// let hash = params.finish();
447
+ /// assert_eq!(hash, Hash::EMPTY);
448
+ /// # Ok::<_, rune::hash::TooManyParameters>(())
449
+ /// ```
276
450
pub const fn new ( ) -> Self {
277
451
Self {
278
452
base : 0 ,
@@ -286,6 +460,21 @@ impl ParametersBuilder {
286
460
/// # Errors
287
461
///
288
462
/// Errors if too many parameters are added.
463
+ ///
464
+ /// # Examples
465
+ ///
466
+ /// ```
467
+ /// use rune::TypeHash;
468
+ /// use rune::hash::ParametersBuilder;
469
+ ///
470
+ /// let mut params = ParametersBuilder::new();
471
+ ///
472
+ /// let params = params.add(String::HASH)?;
473
+ /// let params = params.add(i64::HASH)?;
474
+ ///
475
+ /// let hash = params.finish();
476
+ /// # Ok::<_, rune::hash::TooManyParameters>(())
477
+ /// ```
289
478
pub const fn add ( mut self , Hash ( hash) : Hash ) -> Result < Self , TooManyParameters > {
290
479
if self . index >= PARAMETERS . len ( ) {
291
480
self . shift += 8 ;
@@ -302,7 +491,29 @@ impl ParametersBuilder {
302
491
}
303
492
304
493
/// Finish building the parameters hash.
494
+ ///
495
+ /// # Examples
496
+ ///
497
+ /// ```
498
+ /// use rune::TypeHash;
499
+ /// use rune::hash::ParametersBuilder;
500
+ ///
501
+ /// let mut params = ParametersBuilder::new();
502
+ ///
503
+ /// let params = params.add(String::HASH)?;
504
+ /// let params = params.add(i64::HASH)?;
505
+ ///
506
+ /// let hash = params.finish();
507
+ /// # Ok::<_, rune::hash::TooManyParameters>(())
508
+ /// ```
305
509
pub const fn finish ( self ) -> Hash {
306
510
Hash :: new ( self . base )
307
511
}
308
512
}
513
+
514
+ impl PartialEq < NonZeroHash > for Hash {
515
+ #[ inline]
516
+ fn eq ( & self , other : & NonZeroHash ) -> bool {
517
+ self . 0 == other. 0 . get ( )
518
+ }
519
+ }
0 commit comments