1#![doc(
4 html_logo_url = "https://commonware.xyz/imgs/rustdoc_logo.svg",
5 html_favicon_url = "https://commonware.xyz/favicon.ico"
6)]
7#![cfg_attr(not(any(feature = "std", test)), no_std)]
8
9commonware_macros::stability_scope!(ALPHA, cfg(feature = "std") {
10 pub mod rng;
11 pub use rng::{test_rng, test_rng_seeded, FuzzRng};
12
13 pub mod thread_local;
14 pub use thread_local::Cached;
15});
16commonware_macros::stability_scope!(BETA {
17 #[cfg(not(feature = "std"))]
18 extern crate alloc;
19
20 #[cfg(not(feature = "std"))]
21 use alloc::{boxed::Box, string::String, vec::Vec};
22 use bytes::{BufMut, BytesMut};
23 use core::{fmt::Write as FmtWrite, time::Duration};
24 pub mod faults;
25 pub use faults::{Faults, N3f1, N5f1};
26
27 pub mod sequence;
28 pub use sequence::{Array, Span};
29
30 pub mod hostname;
31 pub use hostname::Hostname;
32
33 pub mod bitmap;
34 pub mod ordered;
35 pub mod range;
36
37 use bytes::Buf;
38 use commonware_codec::{varint::UInt, EncodeSize, Error as CodecError, Read, ReadExt, Write};
39
40 pub const GOLDEN_RATIO: u64 = 0x9e37_79b9_7f4a_7c15;
45
46 #[derive(Copy, Clone, Debug, Default, PartialEq, Eq, PartialOrd, Ord, Hash)]
52 #[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
53 pub struct Participant(u32);
54
55 impl Participant {
56 pub const fn new(index: u32) -> Self {
58 Self(index)
59 }
60
61 pub fn from_usize(index: usize) -> Self {
67 Self(u32::try_from(index).expect("participant index exceeds u32::MAX"))
68 }
69
70 pub const fn get(self) -> u32 {
72 self.0
73 }
74 }
75
76 impl From<Participant> for usize {
77 fn from(p: Participant) -> Self {
78 p.0 as Self
79 }
80 }
81
82 impl core::fmt::Display for Participant {
83 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
84 write!(f, "{}", self.0)
85 }
86 }
87
88 impl Read for Participant {
89 type Cfg = ();
90
91 fn read_cfg(buf: &mut impl Buf, _cfg: &Self::Cfg) -> Result<Self, CodecError> {
92 let value: u32 = UInt::read(buf)?.into();
93 Ok(Self(value))
94 }
95 }
96
97 impl Write for Participant {
98 fn write(&self, buf: &mut impl bytes::BufMut) {
99 UInt(self.0).write(buf);
100 }
101 }
102
103 impl EncodeSize for Participant {
104 fn encode_size(&self) -> usize {
105 UInt(self.0).encode_size()
106 }
107 }
108
109 pub trait TryFromIterator<T>: Sized {
111 type Error;
113
114 fn try_from_iter<I: IntoIterator<Item = T>>(iter: I) -> Result<Self, Self::Error>;
116 }
117
118 pub trait TryCollect: Iterator + Sized {
120 fn try_collect<C: TryFromIterator<Self::Item>>(self) -> Result<C, C::Error> {
122 C::try_from_iter(self)
123 }
124 }
125
126 impl<I: Iterator> TryCollect for I {}
127
128 pub type BoxedError = Box<dyn core::error::Error + Send + Sync>;
130
131 pub fn hex(bytes: &[u8]) -> String {
133 let mut hex = String::with_capacity(bytes.len() * 2);
134 for byte in bytes.iter() {
135 write!(hex, "{byte:02x}").expect("writing to string should never fail");
136 }
137 hex
138 }
139
140 pub fn from_hex(hex: &str) -> Option<Vec<u8>> {
142 let bytes = hex.as_bytes();
143 if !bytes.len().is_multiple_of(2) {
144 return None;
145 }
146
147 bytes
148 .chunks_exact(2)
149 .map(|chunk| {
150 let hi = decode_hex_digit(chunk[0])?;
151 let lo = decode_hex_digit(chunk[1])?;
152 Some((hi << 4) | lo)
153 })
154 .collect()
155 }
156
157 pub fn from_hex_formatted(hex: &str) -> Option<Vec<u8>> {
160 let hex = hex.replace(['\t', '\n', '\r', ' '], "");
161 let res = hex.strip_prefix("0x").unwrap_or(&hex);
162 from_hex(res)
163 }
164
165 pub fn union(a: &[u8], b: &[u8]) -> Vec<u8> {
167 let mut union = Vec::with_capacity(a.len() + b.len());
168 union.extend_from_slice(a);
169 union.extend_from_slice(b);
170 union
171 }
172
173 pub fn union_unique(namespace: &[u8], msg: &[u8]) -> Vec<u8> {
177 use commonware_codec::EncodeSize;
178 let len_prefix = namespace.len();
179 let mut buf =
180 BytesMut::with_capacity(len_prefix.encode_size() + namespace.len() + msg.len());
181 len_prefix.write(&mut buf);
182 BufMut::put_slice(&mut buf, namespace);
183 BufMut::put_slice(&mut buf, msg);
184 buf.into()
185 }
186
187 pub fn modulo(bytes: &[u8], n: u64) -> u64 {
195 assert_ne!(n, 0, "modulus must be non-zero");
196
197 let n = n as u128;
198 let mut result = 0u128;
199 for &byte in bytes {
200 result = (result << 8) | (byte as u128);
201 result %= n;
202 }
203
204 result as u64
206 }
207
208 #[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
210 pub struct NonZeroDuration(Duration);
211
212 impl NonZeroDuration {
213 pub fn new(duration: Duration) -> Option<Self> {
215 if duration == Duration::ZERO {
216 None
217 } else {
218 Some(Self(duration))
219 }
220 }
221
222 pub fn new_panic(duration: Duration) -> Self {
224 Self::new(duration).expect("duration must be non-zero")
225 }
226
227 pub const fn get(self) -> Duration {
229 self.0
230 }
231 }
232
233 impl From<NonZeroDuration> for Duration {
234 fn from(nz_duration: NonZeroDuration) -> Self {
235 nz_duration.0
236 }
237 }
238});
239commonware_macros::stability_scope!(BETA, cfg(feature = "std") {
240 pub mod acknowledgement;
241 pub use acknowledgement::Acknowledgement;
242
243 pub mod net;
244 pub use net::IpAddrExt;
245
246 pub mod time;
247 pub use time::{DurationExt, SystemTimeExt};
248
249 pub mod rational;
250 pub use rational::BigRationalExt;
251
252 mod priority_set;
253 pub use priority_set::PrioritySet;
254
255 pub mod channel;
256 pub mod concurrency;
257 pub mod futures;
258 pub mod sync;
259});
260#[cfg(not(any(
261 commonware_stability_GAMMA,
262 commonware_stability_DELTA,
263 commonware_stability_EPSILON,
264 commonware_stability_RESERVED
265)))] pub mod hex_literal;
267#[cfg(not(any(
268 commonware_stability_GAMMA,
269 commonware_stability_DELTA,
270 commonware_stability_EPSILON,
271 commonware_stability_RESERVED
272)))] pub mod vec;
274
275#[commonware_macros::stability(BETA)]
276#[inline]
277const fn decode_hex_digit(byte: u8) -> Option<u8> {
278 match byte {
279 b'0'..=b'9' => Some(byte - b'0'),
280 b'a'..=b'f' => Some(byte - b'a' + 10),
281 b'A'..=b'F' => Some(byte - b'A' + 10),
282 _ => None,
283 }
284}
285
286#[macro_export]
290macro_rules! NZUsize {
291 ($val:literal) => {
292 const { ::core::num::NonZeroUsize::new($val).expect("value must be non-zero") }
293 };
294 ($val:expr) => {
295 ::core::num::NonZeroUsize::new($val).expect("value must be non-zero")
297 };
298}
299
300#[macro_export]
304macro_rules! NZU8 {
305 ($val:literal) => {
306 const { ::core::num::NonZeroU8::new($val).expect("value must be non-zero") }
307 };
308 ($val:expr) => {
309 ::core::num::NonZeroU8::new($val).expect("value must be non-zero")
311 };
312}
313
314#[macro_export]
318macro_rules! NZU16 {
319 ($val:literal) => {
320 const { ::core::num::NonZeroU16::new($val).expect("value must be non-zero") }
321 };
322 ($val:expr) => {
323 ::core::num::NonZeroU16::new($val).expect("value must be non-zero")
325 };
326}
327
328#[macro_export]
332macro_rules! NZU32 {
333 ($val:literal) => {
334 const { ::core::num::NonZeroU32::new($val).expect("value must be non-zero") }
335 };
336 ($val:expr) => {
337 ::core::num::NonZeroU32::new($val).expect("value must be non-zero")
339 };
340}
341
342#[macro_export]
346macro_rules! NZU64 {
347 ($val:literal) => {
348 const { ::core::num::NonZeroU64::new($val).expect("value must be non-zero") }
349 };
350 ($val:expr) => {
351 ::core::num::NonZeroU64::new($val).expect("value must be non-zero")
353 };
354}
355
356#[macro_export]
358macro_rules! NZDuration {
359 ($val:expr) => {
360 $crate::NonZeroDuration::new_panic($val)
362 };
363}
364
365#[cfg(test)]
366mod tests {
367 use super::*;
368 use num_bigint::BigUint;
369 use rand::{rngs::StdRng, Rng, SeedableRng};
370
371 #[test]
372 fn test_hex() {
373 let b = &[];
375 let h = hex(b);
376 assert_eq!(h, "");
377 assert_eq!(from_hex(&h).unwrap(), b.to_vec());
378
379 let b = &hex!("0x01");
381 let h = hex(b);
382 assert_eq!(h, "01");
383 assert_eq!(from_hex(&h).unwrap(), b.to_vec());
384
385 let b = &hex!("0x010203");
387 let h = hex(b);
388 assert_eq!(h, "010203");
389 assert_eq!(from_hex(&h).unwrap(), b.to_vec());
390
391 let h = "0102030";
393 assert!(from_hex(h).is_none());
394
395 let h = "01g3";
397 assert!(from_hex(h).is_none());
398
399 let h = "+123";
401 assert!(from_hex(h).is_none());
402
403 assert_eq!(from_hex(""), Some(vec![]));
405 }
406
407 #[test]
408 fn test_from_hex_formatted() {
409 let b = &[];
411 let h = hex(b);
412 assert_eq!(h, "");
413 assert_eq!(from_hex_formatted(&h).unwrap(), b.to_vec());
414
415 let b = &hex!("0x01");
417 let h = hex(b);
418 assert_eq!(h, "01");
419 assert_eq!(from_hex_formatted(&h).unwrap(), b.to_vec());
420
421 let b = &hex!("0x010203");
423 let h = hex(b);
424 assert_eq!(h, "010203");
425 assert_eq!(from_hex_formatted(&h).unwrap(), b.to_vec());
426
427 let h = "0102030";
429 assert!(from_hex_formatted(h).is_none());
430
431 let h = "01g3";
433 assert!(from_hex_formatted(h).is_none());
434
435 let h = "01 02 03";
437 assert_eq!(from_hex_formatted(h).unwrap(), b.to_vec());
438
439 let h = "0x010203";
441 assert_eq!(from_hex_formatted(h).unwrap(), b.to_vec());
442
443 let h = " \n\n0x\r\n01
445 02\t03\n";
446 assert_eq!(from_hex_formatted(h).unwrap(), b.to_vec());
447 }
448
449 #[test]
450 fn test_from_hex_utf8_char_boundaries() {
451 const MISALIGNMENT_CASE: &str = "쀘\n";
452
453 let b = from_hex(MISALIGNMENT_CASE);
455 assert!(b.is_none());
456 }
457
458 #[test]
459 fn test_union() {
460 assert_eq!(union(&[], &[]), Vec::<u8>::new());
462
463 assert_eq!(union(&[], &hex!("0x010203")), hex!("0x010203"));
465
466 assert_eq!(
468 union(&hex!("0x010203"), &hex!("0x040506")),
469 hex!("0x010203040506")
470 );
471 }
472
473 #[test]
474 fn test_union_unique() {
475 let namespace = b"namespace";
476 let msg = b"message";
477
478 let length_encoding = vec![0b0000_1001];
479 let mut expected = Vec::with_capacity(length_encoding.len() + namespace.len() + msg.len());
480 expected.extend_from_slice(&length_encoding);
481 expected.extend_from_slice(namespace);
482 expected.extend_from_slice(msg);
483
484 let result = union_unique(namespace, msg);
485 assert_eq!(result, expected);
486 assert_eq!(result.len(), result.capacity());
487 }
488
489 #[test]
490 fn test_union_unique_zero_length() {
491 let namespace = b"";
492 let msg = b"message";
493
494 let length_encoding = vec![0];
495 let mut expected = Vec::with_capacity(length_encoding.len() + namespace.len() + msg.len());
496 expected.extend_from_slice(&length_encoding);
497 expected.extend_from_slice(msg);
498
499 let result = union_unique(namespace, msg);
500 assert_eq!(result, expected);
501 assert_eq!(result.len(), result.capacity());
502 }
503
504 #[test]
505 fn test_union_unique_long_length() {
506 let namespace = &b"n".repeat(256);
508 let msg = b"message";
509
510 let length_encoding = vec![0b1000_0000, 0b0000_0010];
511 let mut expected = Vec::with_capacity(length_encoding.len() + namespace.len() + msg.len());
512 expected.extend_from_slice(&length_encoding);
513 expected.extend_from_slice(namespace);
514 expected.extend_from_slice(msg);
515
516 let result = union_unique(namespace, msg);
517 assert_eq!(result, expected);
518 assert_eq!(result.len(), result.capacity());
519 }
520
521 #[test]
522 fn test_modulo() {
523 assert_eq!(modulo(&[], 1), 0);
525
526 assert_eq!(modulo(&hex!("0x01"), 1), 0);
528
529 assert_eq!(modulo(&hex!("0x010203"), 10), 1);
531
532 for i in 0..100 {
534 let mut rng = StdRng::seed_from_u64(i);
535 let bytes: [u8; 32] = rng.gen();
536
537 let n = 11u64;
539 let big_modulo = BigUint::from_bytes_be(&bytes) % n;
540 let utils_modulo = modulo(&bytes, n);
541 assert_eq!(big_modulo, BigUint::from(utils_modulo));
542
543 let n = 11_111u64;
545 let big_modulo = BigUint::from_bytes_be(&bytes) % n;
546 let utils_modulo = modulo(&bytes, n);
547 assert_eq!(big_modulo, BigUint::from(utils_modulo));
548
549 let n = 0xDFFFFFFFFFFFFFFD;
551 let big_modulo = BigUint::from_bytes_be(&bytes) % n;
552 let utils_modulo = modulo(&bytes, n);
553 assert_eq!(big_modulo, BigUint::from(utils_modulo));
554 }
555 }
556
557 #[test]
558 #[should_panic]
559 fn test_modulo_zero_panics() {
560 modulo(&hex!("0x010203"), 0);
561 }
562
563 #[test]
564 fn test_non_zero_macros_compile_time() {
565 assert_eq!(NZUsize!(1).get(), 1);
568 assert_eq!(NZU8!(2).get(), 2);
569 assert_eq!(NZU16!(3).get(), 3);
570 assert_eq!(NZU32!(4).get(), 4);
571 assert_eq!(NZU64!(5).get(), 5);
572
573 const _: core::num::NonZeroUsize = NZUsize!(1);
575 const _: core::num::NonZeroU8 = NZU8!(2);
576 const _: core::num::NonZeroU16 = NZU16!(3);
577 const _: core::num::NonZeroU32 = NZU32!(4);
578 const _: core::num::NonZeroU64 = NZU64!(5);
579 }
580
581 #[test]
582 fn test_non_zero_macros_runtime() {
583 let one_usize: usize = 1;
585 let two_u8: u8 = 2;
586 let three_u16: u16 = 3;
587 let four_u32: u32 = 4;
588 let five_u64: u64 = 5;
589
590 assert_eq!(NZUsize!(one_usize).get(), 1);
591 assert_eq!(NZU8!(two_u8).get(), 2);
592 assert_eq!(NZU16!(three_u16).get(), 3);
593 assert_eq!(NZU32!(four_u32).get(), 4);
594 assert_eq!(NZU64!(five_u64).get(), 5);
595
596 let zero_usize: usize = 0;
598 let zero_u8: u8 = 0;
599 let zero_u16: u16 = 0;
600 let zero_u32: u32 = 0;
601 let zero_u64: u64 = 0;
602
603 assert!(std::panic::catch_unwind(|| NZUsize!(zero_usize)).is_err());
604 assert!(std::panic::catch_unwind(|| NZU8!(zero_u8)).is_err());
605 assert!(std::panic::catch_unwind(|| NZU16!(zero_u16)).is_err());
606 assert!(std::panic::catch_unwind(|| NZU32!(zero_u32)).is_err());
607 assert!(std::panic::catch_unwind(|| NZU64!(zero_u64)).is_err());
608
609 assert!(std::panic::catch_unwind(|| NZDuration!(Duration::ZERO)).is_err());
611 assert_eq!(
612 NZDuration!(Duration::from_secs(1)).get(),
613 Duration::from_secs(1)
614 );
615 }
616
617 #[test]
618 fn test_non_zero_duration() {
619 assert!(NonZeroDuration::new(Duration::ZERO).is_none());
621
622 let duration = Duration::from_millis(100);
624 let nz_duration = NonZeroDuration::new(duration).unwrap();
625 assert_eq!(nz_duration.get(), duration);
626 assert_eq!(Duration::from(nz_duration), duration);
627
628 assert!(std::panic::catch_unwind(|| NonZeroDuration::new_panic(Duration::ZERO)).is_err());
630
631 let d1 = NonZeroDuration::new(Duration::from_millis(100)).unwrap();
633 let d2 = NonZeroDuration::new(Duration::from_millis(200)).unwrap();
634 assert!(d1 < d2);
635 }
636
637 #[test]
638 fn test_participant_constructors() {
639 assert_eq!(Participant::new(0).get(), 0);
640 assert_eq!(Participant::new(42).get(), 42);
641 assert_eq!(Participant::from_usize(0).get(), 0);
642 assert_eq!(Participant::from_usize(42).get(), 42);
643 assert_eq!(Participant::from_usize(u32::MAX as usize).get(), u32::MAX);
644 }
645
646 #[test]
647 #[should_panic(expected = "participant index exceeds u32::MAX")]
648 fn test_participant_from_usize_overflow() {
649 Participant::from_usize((u32::MAX as usize) + 1);
650 }
651
652 #[test]
653 fn test_participant_display() {
654 assert_eq!(format!("{}", Participant::new(0)), "0");
655 assert_eq!(format!("{}", Participant::new(42)), "42");
656 assert_eq!(format!("{}", Participant::new(1000)), "1000");
657 }
658
659 #[test]
660 fn test_participant_ordering() {
661 assert!(Participant::new(0) < Participant::new(1));
662 assert!(Participant::new(5) < Participant::new(10));
663 assert!(Participant::new(10) > Participant::new(5));
664 assert_eq!(Participant::new(42), Participant::new(42));
665 }
666
667 #[test]
668 fn test_participant_encode_decode() {
669 use commonware_codec::{DecodeExt, Encode};
670
671 let cases = vec![0u32, 1, 127, 128, 255, 256, u32::MAX];
672 for value in cases {
673 let participant = Participant::new(value);
674 let encoded = participant.encode();
675 assert_eq!(encoded.len(), participant.encode_size());
676 let decoded = Participant::decode(encoded).unwrap();
677 assert_eq!(participant, decoded);
678 }
679 }
680
681 #[cfg(feature = "arbitrary")]
682 mod conformance {
683 use super::*;
684 use commonware_codec::conformance::CodecConformance;
685
686 commonware_conformance::conformance_tests! {
687 CodecConformance<Participant>,
688 }
689 }
690}