1pub mod bag;
10pub mod bits;
11pub mod node;
12pub mod short;
13
14use std::{
15 cmp::Ordering,
16 collections::HashSet,
17 fmt,
18 hash::{Hash, Hasher},
19 str::FromStr,
20};
21
22use crate::{
23 errors::{Error, Result},
24 formatting, hash, packer,
25};
26use lazy_static::lazy_static;
27use serde::{self, de::Visitor, Deserialize, Deserializer, Serialize, Serializer};
28use zerocopy::{AsBytes, FromBytes, FromZeroes, Unaligned};
29
30pub const LEN: usize = 32;
31
32lazy_static! {
33 static ref EMPTY: Vec<u8> = vec![0; LEN];
34}
35
36#[derive(Debug, Clone, Copy, Eq, AsBytes, FromZeroes, FromBytes, Unaligned)]
39#[repr(transparent)]
40pub struct Id([u8; LEN]);
41
42impl Default for Id {
43 fn default() -> Self {
44 Self::empty()
45 }
46}
47
48impl Id {
49 pub fn empty() -> Self {
50 Id([0; LEN])
51 }
52
53 pub fn is_empty(&self) -> bool {
54 (*self) == Self::empty()
55 }
56
57 pub fn to_vec(&self) -> Vec<u8> {
58 self.0.to_vec()
59 }
60
61 pub fn sha256(d: impl AsRef<[u8]>) -> Self {
64 Id::from_slice(&hash::sha256(d))
65 }
66
67 pub fn from_slice(d: &[u8]) -> Self {
70 assert!(d.len() <= LEN);
71 let mut d: Vec<u8> = Vec::from(d);
72 if d.len() < LEN {
73 d.resize(LEN, 0);
74 }
75 let d: [u8; LEN] = d.try_into().unwrap();
76 Id(d)
77 }
78
79 pub fn prefix(&self, prefixes: &[u64]) -> Result<Self> {
81 let n = prefixes.len() + packer::U64_LEN + 32;
82 let packer = packer::Packer::new(n, n);
83 for pfx in prefixes {
84 packer.pack_u64(*pfx)?;
85 }
86 packer.pack_bytes(&self.0)?;
87
88 let b = packer.take_bytes();
89 let d = hash::sha256(&b);
90 Ok(Self::from_slice(&d))
91 }
92
93 pub fn bit(&self, i: usize) -> bits::Bit {
96 let byte_index = i / 8;
97 let bit_index = i % 8;
98
99 let mut b = self.0[byte_index];
100
101 b >>= bit_index;
104
105 b &= 1;
109
110 bits::Bit::from(b as usize)
114 }
115}
116
117impl AsRef<[u8]> for Id {
118 fn as_ref(&self) -> &[u8] {
119 &self.0
120 }
121}
122
123impl fmt::Display for Id {
127 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
128 let s = formatting::encode_cb58_with_checksum_string(&self.0);
129 write!(f, "{}", s)
130 }
131}
132
133impl FromStr for Id {
135 type Err = std::io::Error;
136 fn from_str(s: &str) -> std::result::Result<Self, Self::Err> {
137 let decoded = formatting::decode_cb58_with_checksum(s.trim()).map_err(|e| {
139 std::io::Error::new(
140 std::io::ErrorKind::Other,
141 format!("failed decode_cb58_with_checksum '{}'", e),
142 )
143 })?;
144 Ok(Self::from_slice(&decoded))
145 }
146}
147
148impl From<std::borrow::Cow<'static, str>> for Id {
149 fn from(v: std::borrow::Cow<'static, str>) -> Self {
150 Id::from_str(v.as_ref()).unwrap()
151 }
152}
153
154impl Serialize for Id {
157 fn serialize<S>(&self, serializer: S) -> std::result::Result<S::Ok, S::Error>
158 where
159 S: Serializer,
160 {
161 serializer.serialize_str(&self.to_string())
162 }
163}
164
165impl<'de> Deserialize<'de> for Id {
168 fn deserialize<D>(deserializer: D) -> std::result::Result<Id, D::Error>
169 where
170 D: Deserializer<'de>,
171 {
172 struct IdVisitor;
173
174 impl<'de> Visitor<'de> for IdVisitor {
175 type Value = Id;
176
177 fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
178 formatter.write_str("a base-58 encoded ID-string with checksum")
179 }
180
181 fn visit_str<E>(self, v: &str) -> std::result::Result<Self::Value, E>
182 where
183 E: serde::de::Error,
184 {
185 Id::from_str(v).map_err(E::custom)
186 }
187 }
188
189 deserializer.deserialize_any(IdVisitor)
190 }
191}
192
193#[test]
195fn test_custom_de_serializer() {
196 #[derive(Debug, Serialize, Deserialize, PartialEq, Eq, Clone)]
197 struct Data {
198 id: Id,
199 }
200
201 let d = Data {
202 id: Id::from_str("g25v3qDyAaHfR7kBev8tLUHouSgN5BJuZjy1BYS1oiHd2vres").unwrap(),
203 };
204
205 let yaml_encoded = serde_yaml::to_string(&d).unwrap();
206 println!("yaml_encoded:\n{}", yaml_encoded);
207 let yaml_decoded = serde_yaml::from_str(&yaml_encoded).unwrap();
208 assert_eq!(d, yaml_decoded);
209
210 let json_encoded = serde_json::to_string(&d).unwrap();
211 println!("json_encoded:\n{}", json_encoded);
212 let json_decoded = serde_json::from_str(&json_encoded).unwrap();
213 assert_eq!(d, json_decoded);
214
215 let json_decoded_2: Data = serde_json::from_str(
216 "
217
218{
219 \"id\":\"g25v3qDyAaHfR7kBev8tLUHouSgN5BJuZjy1BYS1oiHd2vres\"
220}
221
222",
223 )
224 .unwrap();
225 assert_eq!(d, json_decoded_2);
226
227 let json_encoded_3 = serde_json::json!(
228 {
229 "id": "g25v3qDyAaHfR7kBev8tLUHouSgN5BJuZjy1BYS1oiHd2vres"
230 }
231 );
232 let json_decoded_3: Data = serde_json::from_value(json_encoded_3).unwrap();
233 assert_eq!(d, json_decoded_3);
234}
235
236fn fmt_id<'de, D>(deserializer: D) -> std::result::Result<Id, D::Error>
237where
238 D: Deserializer<'de>,
239{
240 let s = String::deserialize(deserializer)?;
241 Id::from_str(&s).map_err(serde::de::Error::custom)
242}
243
244pub fn deserialize_id<'de, D>(deserializer: D) -> std::result::Result<Option<Id>, D::Error>
247where
248 D: Deserializer<'de>,
249{
250 #[derive(Deserialize)]
251 struct Wrapper(#[serde(deserialize_with = "fmt_id")] Id);
252 let v = Option::deserialize(deserializer)?;
253 Ok(v.map(|Wrapper(a)| a))
254}
255
256pub fn must_deserialize_id<'de, D>(deserializer: D) -> std::result::Result<Id, D::Error>
260where
261 D: Deserializer<'de>,
262{
263 #[derive(Deserialize)]
264 struct Wrapper(#[serde(deserialize_with = "fmt_id")] Id);
265 let v = Option::deserialize(deserializer)?;
266 match v.map(|Wrapper(a)| a) {
267 Some(unwrapped) => Ok(unwrapped),
268 None => Err(serde::de::Error::custom("empty Id from deserialization")),
269 }
270}
271
272pub fn deserialize_ids<'de, D>(deserializer: D) -> std::result::Result<Option<Vec<Id>>, D::Error>
275where
276 D: Deserializer<'de>,
277{
278 #[derive(Deserialize)]
279 struct Wrapper(#[serde(deserialize_with = "fmt_ids")] Vec<Id>);
280 let v = Option::deserialize(deserializer)?;
281 Ok(v.map(|Wrapper(a)| a))
282}
283
284pub fn must_deserialize_ids<'de, D>(deserializer: D) -> std::result::Result<Vec<Id>, D::Error>
288where
289 D: Deserializer<'de>,
290{
291 #[derive(Deserialize)]
292 struct Wrapper(#[serde(deserialize_with = "fmt_ids")] Vec<Id>);
293 let v = Option::deserialize(deserializer)?;
294 match v.map(|Wrapper(a)| a) {
295 Some(unwrapped) => Ok(unwrapped),
296 None => Err(serde::de::Error::custom("empty Ids from deserialization")),
297 }
298}
299
300fn fmt_ids<'de, D>(deserializer: D) -> std::result::Result<Vec<Id>, D::Error>
301where
302 D: serde::Deserializer<'de>,
303{
304 type Strings = Vec<String>;
305 let ss = Strings::deserialize(deserializer)?;
306 match ss
307 .iter()
308 .map(|x| x.parse::<Id>())
309 .collect::<std::result::Result<Vec<Id>, std::io::Error>>()
310 {
311 Ok(x) => Ok(x),
312 Err(e) => Err(serde::de::Error::custom(format!(
313 "failed to deserialize Ids {}",
314 e
315 ))),
316 }
317}
318
319#[test]
321fn test_serialize() {
322 let id = Id::from_slice(&<Vec<u8>>::from([
323 0x3d, 0x0a, 0xd1, 0x2b, 0x8e, 0xe8, 0x92, 0x8e, 0xdf, 0x24, 0x8c, 0xa9, 0x1c, 0xa5, 0x56, 0x00, 0xfb, 0x38, 0x3f, 0x07, 0xc3, 0x2b, 0xff, 0x1d, 0x6d, 0xec, 0x47, 0x2b, 0x25, 0xcf, 0x59, 0xa7,
327 ]));
328 assert_eq!(
329 id.to_string(),
330 "TtF4d2QWbk5vzQGTEPrN48x6vwgAoAmKQ9cbp79inpQmcRKES"
331 );
332
333 use serde::{Deserialize, Serialize};
334 #[derive(Debug, Serialize, Deserialize, PartialEq, Eq, Clone)]
335 struct Data {
336 id: Id,
337 id2: Option<Id>,
338 ids: Vec<Id>,
339 }
340 let d = Data {
341 id,
342 id2: Some(id),
343 ids: vec![id, id, id, id, id],
344 };
345
346 let yaml_encoded = serde_yaml::to_string(&d).unwrap();
347 assert!(yaml_encoded.contains("TtF4d2QWbk5vzQGTEPrN48x6vwgAoAmKQ9cbp79inpQmcRKES"));
348 let yaml_decoded = serde_yaml::from_str(&yaml_encoded).unwrap();
349 assert_eq!(d, yaml_decoded);
350
351 let json_encoded = serde_json::to_string(&d).unwrap();
352 assert!(json_encoded.contains("TtF4d2QWbk5vzQGTEPrN48x6vwgAoAmKQ9cbp79inpQmcRKES"));
353 let json_decoded = serde_json::from_str(&json_encoded).unwrap();
354 assert_eq!(d, json_decoded);
355}
356
357pub type Set = HashSet<Id>;
360
361pub fn new_set(size: usize) -> Set {
364 let set: HashSet<Id> = HashSet::with_capacity(size);
365 set
366}
367
368#[test]
371fn test_id() {
372 let id = Id::from_slice(&<Vec<u8>>::from([
373 0x3d, 0x0a, 0xd1, 0x2b, 0x8e, 0xe8, 0x92, 0x8e, 0xdf, 0x24, 0x8c, 0xa9, 0x1c, 0xa5, 0x56, 0x00, 0xfb, 0x38, 0x3f, 0x07, 0xc3, 0x2b, 0xff, 0x1d, 0x6d, 0xec, 0x47, 0x2b, 0x25, 0xcf, 0x59, 0xa7,
377 ]));
378 assert_eq!(
379 id.to_string(),
380 "TtF4d2QWbk5vzQGTEPrN48x6vwgAoAmKQ9cbp79inpQmcRKES"
381 );
382 assert_eq!(
383 id.to_vec(),
384 <Vec<u8>>::from([
385 0x3d, 0x0a, 0xd1, 0x2b, 0x8e, 0xe8, 0x92, 0x8e, 0xdf, 0x24, 0x8c, 0xa9, 0x1c, 0xa5, 0x56, 0x00, 0xfb, 0x38, 0x3f, 0x07, 0xc3, 0x2b, 0xff, 0x1d, 0x6d, 0xec, 0x47, 0x2b, 0x25, 0xcf, 0x59, 0xa7,
389 ])
390 );
391
392 let id_from_str = Id::from_str("TtF4d2QWbk5vzQGTEPrN48x6vwgAoAmKQ9cbp79inpQmcRKES").unwrap();
393 assert_eq!(id, id_from_str);
394
395 let id = Id::from_slice(&<Vec<u8>>::from([
396 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
400 ]));
401 assert_eq!(id.to_string(), "11111111111111111111111111111111LpoYY");
402 let id_from_str = Id::from_str("11111111111111111111111111111111LpoYY").unwrap();
403 assert_eq!(id, id_from_str);
404}
405
406impl Ord for Id {
407 fn cmp(&self, other: &Id) -> Ordering {
408 self.0.cmp(&(other.0))
409 }
410}
411
412impl PartialOrd for Id {
413 fn partial_cmp(&self, other: &Id) -> Option<Ordering> {
414 Some(self.cmp(other))
415 }
416}
417
418impl PartialEq for Id {
419 fn eq(&self, other: &Id) -> bool {
420 self.cmp(other) == Ordering::Equal
421 }
422}
423
424impl Hash for Id {
426 fn hash<H: Hasher>(&self, state: &mut H) {
427 self.0.hash(state);
428 }
429}
430
431#[derive(Debug, Eq, Clone)]
432pub struct Ids(Vec<Id>);
433
434impl Ids {
435 pub fn new(ids: &[Id]) -> Self {
436 Ids(Vec::from(ids))
437 }
438}
439
440impl From<Vec<Id>> for Ids {
441 fn from(ids: Vec<Id>) -> Self {
442 Self::new(&ids)
443 }
444}
445
446impl Ord for Ids {
447 fn cmp(&self, other: &Ids) -> Ordering {
448 let l1 = self.0.len();
451 let l2 = other.0.len();
452 l1.cmp(&l2) .then_with(
454 || self.0.cmp(&other.0), )
456 }
457}
458
459impl PartialOrd for Ids {
460 fn partial_cmp(&self, other: &Ids) -> Option<Ordering> {
461 Some(self.cmp(other))
462 }
463}
464
465impl PartialEq for Ids {
466 fn eq(&self, other: &Ids) -> bool {
467 self.cmp(other) == Ordering::Equal
468 }
469}
470
471#[test]
473fn test_sort() {
474 let id1 = Id::from_slice(&<Vec<u8>>::from([0x01]));
475 let id2 = Id::from_slice(&<Vec<u8>>::from([0x02]));
476 let id3 = Id::from_slice(&<Vec<u8>>::from([0x03]));
477 assert!(id1 < id2);
478 assert!(id2 < id3);
479 assert!(id1 < id3);
480
481 let id1 = Id::from_slice(&<Vec<u8>>::from([0x01, 0x00, 0x00, 0x00]));
483 let id2 = Id::from_slice(&<Vec<u8>>::from([0x01, 0x00, 0x00, 0x00, 0x00]));
484 assert!(id1 == id2);
485
486 let id1 = Id::from_slice(&<Vec<u8>>::from([0x01, 0x00, 0x00, 0x00, 0x00]));
488 let id2 = Id::from_slice(&<Vec<u8>>::from([0x02]));
489 assert!(id1 < id2);
490
491 let id1 = Id::from_slice(&<Vec<u8>>::from([0x02, 0x00, 0x00, 0x00, 0x00]));
493 let id2 = Id::from_slice(&<Vec<u8>>::from([0x01, 0x00, 0x00, 0x00, 0x00]));
494 assert!(id1 > id2);
495
496 let ids1 = Ids(vec![
498 Id::from_slice(&<Vec<u8>>::from([0x01])),
499 Id::from_slice(&<Vec<u8>>::from([0x02])),
500 Id::from_slice(&<Vec<u8>>::from([0x03])),
501 ]);
502 let ids2 = Ids(vec![
503 Id::from_slice(&<Vec<u8>>::from([0x01])),
504 Id::from_slice(&<Vec<u8>>::from([0x02])),
505 Id::from_slice(&<Vec<u8>>::from([0x03])),
506 ]);
507 assert!(ids1 == ids2);
508
509 let ids1 = Ids(vec![
511 Id::from_slice(&<Vec<u8>>::from([0x05])),
512 Id::from_slice(&<Vec<u8>>::from([0x06])),
513 Id::from_slice(&<Vec<u8>>::from([0x07])),
514 ]);
515 let ids2 = Ids(vec![
516 Id::from_slice(&<Vec<u8>>::from([0x01])),
517 Id::from_slice(&<Vec<u8>>::from([0x02])),
518 Id::from_slice(&<Vec<u8>>::from([0x03])),
519 Id::from_slice(&<Vec<u8>>::from([0x04])),
520 ]);
521 assert!(ids1 < ids2);
522
523 let ids1 = Ids(vec![
525 Id::from_slice(&<Vec<u8>>::from([0x01])),
526 Id::from_slice(&<Vec<u8>>::from([0x02])),
527 Id::from_slice(&<Vec<u8>>::from([0x03])),
528 Id::from_slice(&<Vec<u8>>::from([0x04])),
529 ]);
530 let ids2 = Ids(vec![
531 Id::from_slice(&<Vec<u8>>::from([0x09])),
532 Id::from_slice(&<Vec<u8>>::from([0x09])),
533 Id::from_slice(&<Vec<u8>>::from([0x09])),
534 ]);
535 assert!(ids1 > ids2);
536
537 let ids1 = Ids(vec![
539 Id::from_slice(&<Vec<u8>>::from([0x01])),
540 Id::from_slice(&<Vec<u8>>::from([0x02])),
541 Id::from_slice(&<Vec<u8>>::from([0x03])),
542 ]);
543 let ids2 = Ids(vec![
544 Id::from_slice(&<Vec<u8>>::from([0x01])),
545 Id::from_slice(&<Vec<u8>>::from([0x02])),
546 Id::from_slice(&<Vec<u8>>::from([0x05])),
547 ]);
548 assert!(ids1 < ids2);
549
550 let mut ids1 = Ids(vec![
551 Id::from_slice(&<Vec<u8>>::from([0x03])),
552 Id::from_slice(&<Vec<u8>>::from([0x02])),
553 Id::from_slice(&<Vec<u8>>::from([0x01])),
554 ]);
555 ids1.0.sort();
556 let ids2 = Ids(vec![
557 Id::from_slice(&<Vec<u8>>::from([0x01])),
558 Id::from_slice(&<Vec<u8>>::from([0x02])),
559 Id::from_slice(&<Vec<u8>>::from([0x03])),
560 ]);
561 assert!(ids1 == ids2);
562
563 let mut ids1 = vec![
564 Id::from_slice(&<Vec<u8>>::from([0x03])),
565 Id::from_slice(&<Vec<u8>>::from([0x02])),
566 Id::from_slice(&<Vec<u8>>::from([0x01])),
567 ];
568 ids1.sort();
569 let ids2 = vec![
570 Id::from_slice(&<Vec<u8>>::from([0x01])),
571 Id::from_slice(&<Vec<u8>>::from([0x02])),
572 Id::from_slice(&<Vec<u8>>::from([0x03])),
573 ];
574 assert!(ids1 == ids2);
575}
576
577pub fn encode_vm_name_to_id(name: &str) -> Result<Id> {
579 let n = name.len();
580 if n > LEN {
581 return Err(Error::Other {
582 message: format!("can't id {} bytes (>{})", n, LEN),
583 retryable: false,
584 });
585 }
586
587 let input = name.as_bytes().to_vec();
588 Ok(Id::from_slice(&input))
589}
590
591#[test]
593fn test_vm_id() {
594 use log::info;
595 let _ = env_logger::builder()
596 .filter_level(log::LevelFilter::Info)
597 .is_test(true)
598 .try_init();
599
600 let subnet_evm_id = encode_vm_name_to_id("subnetevm").expect("failed to generate id from str");
601 assert_eq!(
602 format!("{}", subnet_evm_id),
603 "srEXiWaHuhNyGwPUi444Tu47ZEDwxTWrbQiuD7FmgSAQ6X7Dy"
604 );
605
606 let contents = random_manager::secure_string(30);
607 let v = encode_vm_name_to_id(&contents).expect("failed to generate id from str");
608 info!("vm_id_from_str: {}", v);
609}