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 use rng::{Entropy, FuzzRng, ScriptedRng, TestRng, test_rng};
11});
12commonware_macros::stability_scope!(BETA {
13 #[cfg(not(feature = "std"))]
14 extern crate alloc;
15
16 pub trait Widen<T> {
19 fn widen(self) -> T;
21 }
22
23 macro_rules! impl_widen {
24 ($($nz:ty => $($t:ty),+);+ $(;)?) => {$($(
25 impl Widen<$t> for $nz {
26 #[inline]
27 fn widen(self) -> $t {
28 <$t>::from(self.get())
29 }
30 }
31 )+)+};
32 }
33 impl_widen!(
34 core::num::NonZeroU8 => u16, u32, u64, u128, usize;
35 core::num::NonZeroU16 => u32, u64, u128, usize;
36 core::num::NonZeroU32 => u64, u128;
37 core::num::NonZeroU64 => u128;
38 );
39
40 #[cfg(not(feature = "std"))]
41 use alloc::{boxed::Box, vec::Vec};
42 use bytes::{BufMut, BytesMut};
43 use core::time::Duration;
44 pub mod faults;
45 pub use faults::{Faults, N3f1, N5f1};
46
47 pub mod sequence;
48 pub use sequence::{Array, Span};
49
50 pub mod hostname;
51 pub use hostname::Hostname;
52
53 pub mod bitmap;
54 pub mod cache;
55 pub mod iter;
56 pub mod ordered;
57 pub mod probability;
58 pub use probability::Probability;
59 pub mod range;
60
61 use bytes::Buf;
62 use commonware_codec::{EncodeSize, Error as CodecError, Read, ReadExt, Write, varint::UInt};
63
64 pub const GOLDEN_RATIO: u64 = 0x9e37_79b9_7f4a_7c15;
69
70 #[derive(Copy, Clone, Debug, Default, PartialEq, Eq, PartialOrd, Ord, Hash)]
76 #[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
77 pub struct Participant(u32);
78
79 impl Participant {
80 pub const fn new(index: u32) -> Self {
82 Self(index)
83 }
84
85 pub fn from_usize(index: usize) -> Self {
91 Self(u32::try_from(index).expect("participant index exceeds u32::MAX"))
92 }
93
94 pub const fn get(self) -> u32 {
96 self.0
97 }
98 }
99
100 impl From<Participant> for usize {
101 fn from(p: Participant) -> Self {
102 p.0 as Self
103 }
104 }
105
106 impl core::fmt::Display for Participant {
107 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
108 write!(f, "{}", self.0)
109 }
110 }
111
112 impl Read for Participant {
113 type Cfg = ();
114
115 fn read_cfg(buf: &mut impl Buf, _cfg: &Self::Cfg) -> Result<Self, CodecError> {
116 let value: u32 = UInt::read(buf)?.into();
117 Ok(Self(value))
118 }
119 }
120
121 impl Write for Participant {
122 fn write(&self, buf: &mut impl bytes::BufMut) {
123 UInt(self.0).write(buf);
124 }
125 }
126
127 impl EncodeSize for Participant {
128 fn encode_size(&self) -> usize {
129 UInt(self.0).encode_size()
130 }
131 }
132
133 pub trait TryFromIterator<T>: Sized {
135 type Error;
137
138 fn try_from_iter<I: IntoIterator<Item = T>>(iter: I) -> Result<Self, Self::Error>;
140 }
141
142 pub trait TryCollect: Iterator + Sized {
144 fn try_collect<C: TryFromIterator<Self::Item>>(self) -> Result<C, C::Error> {
146 C::try_from_iter(self)
147 }
148 }
149
150 impl<I: Iterator> TryCollect for I {}
151
152 pub type BoxedError = Box<dyn core::error::Error + Send + Sync>;
154
155 pub fn union(a: &[u8], b: &[u8]) -> Vec<u8> {
157 let mut union = Vec::with_capacity(a.len() + b.len());
158 union.extend_from_slice(a);
159 union.extend_from_slice(b);
160 union
161 }
162
163 pub fn union_unique(namespace: &[u8], msg: &[u8]) -> Vec<u8> {
167 use commonware_codec::EncodeSize;
168 let len_prefix = namespace.len();
169 let mut buf =
170 BytesMut::with_capacity(len_prefix.encode_size() + namespace.len() + msg.len());
171 len_prefix.write(&mut buf);
172 BufMut::put_slice(&mut buf, namespace);
173 BufMut::put_slice(&mut buf, msg);
174 buf.into()
175 }
176
177 pub fn modulo(bytes: &[u8], n: u64) -> u64 {
185 assert_ne!(n, 0, "modulus must be non-zero");
186
187 let n = n as u128;
188 let mut result = 0u128;
189 for &byte in bytes {
190 result = (result << 8) | (byte as u128);
191 result %= n;
192 }
193
194 result as u64
196 }
197
198 #[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
200 pub struct NonZeroDuration(Duration);
201
202 impl NonZeroDuration {
203 pub fn new(duration: Duration) -> Option<Self> {
205 if duration == Duration::ZERO {
206 None
207 } else {
208 Some(Self(duration))
209 }
210 }
211
212 pub fn new_panic(duration: Duration) -> Self {
214 Self::new(duration).expect("duration must be non-zero")
215 }
216
217 pub const fn get(self) -> Duration {
219 self.0
220 }
221 }
222
223 impl From<NonZeroDuration> for Duration {
224 fn from(nz_duration: NonZeroDuration) -> Self {
225 nz_duration.0
226 }
227 }
228});
229commonware_macros::stability_scope!(BETA, cfg(feature = "std") {
230 pub mod rng;
231 pub use rng::sys_rng;
232
233 pub mod acknowledgement;
234 pub use acknowledgement::Acknowledgement;
235
236 pub mod net;
237 pub use net::IpAddrExt;
238
239 pub mod time;
240 pub use time::{DurationExt, SystemTimeExt};
241
242 pub mod rational;
243 pub use rational::BigRationalExt;
244
245 mod priority_set;
246 pub use priority_set::PrioritySet;
247
248 pub mod channel;
249 pub mod concurrency;
250 pub mod futures;
251 pub mod sync;
252
253 pub mod thread_local;
254 pub use thread_local::Cached;
255});
256#[cfg(not(any(
257 commonware_stability_GAMMA,
258 commonware_stability_DELTA,
259 commonware_stability_EPSILON,
260 commonware_stability_RESERVED
261)))] pub mod vec;
263
264#[macro_export]
268macro_rules! NZUsize {
269 ($val:literal) => {
270 const { ::core::num::NonZeroUsize::new($val).expect("value must be non-zero") }
271 };
272 ($val:expr) => {
273 ::core::num::NonZeroUsize::new($val).expect("value must be non-zero")
275 };
276}
277
278#[macro_export]
282macro_rules! NZU8 {
283 ($val:literal) => {
284 const { ::core::num::NonZeroU8::new($val).expect("value must be non-zero") }
285 };
286 ($val:expr) => {
287 ::core::num::NonZeroU8::new($val).expect("value must be non-zero")
289 };
290}
291
292#[macro_export]
296macro_rules! NZU16 {
297 ($val:literal) => {
298 const { ::core::num::NonZeroU16::new($val).expect("value must be non-zero") }
299 };
300 ($val:expr) => {
301 ::core::num::NonZeroU16::new($val).expect("value must be non-zero")
303 };
304}
305
306#[macro_export]
310macro_rules! NZU32 {
311 ($val:literal) => {
312 const { ::core::num::NonZeroU32::new($val).expect("value must be non-zero") }
313 };
314 ($val:expr) => {
315 ::core::num::NonZeroU32::new($val).expect("value must be non-zero")
317 };
318}
319
320#[macro_export]
324macro_rules! NZU64 {
325 ($val:literal) => {
326 const { ::core::num::NonZeroU64::new($val).expect("value must be non-zero") }
327 };
328 ($val:expr) => {
329 ::core::num::NonZeroU64::new($val).expect("value must be non-zero")
331 };
332}
333
334#[doc(hidden)]
337pub use ::commonware_formatting as __formatting;
338
339#[cfg(not(any(
342 commonware_stability_GAMMA,
343 commonware_stability_DELTA,
344 commonware_stability_EPSILON,
345 commonware_stability_RESERVED
346)))] #[macro_export]
348macro_rules! fixed_bytes {
349 ($s:tt) => {
350 const { $crate::sequence::FixedBytes::new($crate::__formatting::hex!($s)) }
351 };
352}
353
354#[macro_export]
356macro_rules! NZDuration {
357 ($val:expr) => {
358 $crate::NonZeroDuration::new_panic($val)
360 };
361}
362
363#[cfg(test)]
364mod tests {
365 use super::*;
366 use crate::TestRng;
367 use commonware_formatting::hex;
368 use num_bigint::BigUint;
369 use rand::RngExt as _;
370
371 #[test]
372 fn test_union() {
373 assert_eq!(union(&[], &[]), Vec::<u8>::new());
375
376 assert_eq!(union(&[], &hex!("0x010203")), hex!("0x010203"));
378
379 assert_eq!(
381 union(&hex!("0x010203"), &hex!("0x040506")),
382 hex!("0x010203040506")
383 );
384 }
385
386 #[test]
387 fn test_union_unique() {
388 let namespace = b"namespace";
389 let msg = b"message";
390
391 let length_encoding = vec![0b0000_1001];
392 let mut expected = Vec::with_capacity(length_encoding.len() + namespace.len() + msg.len());
393 expected.extend_from_slice(&length_encoding);
394 expected.extend_from_slice(namespace);
395 expected.extend_from_slice(msg);
396
397 let result = union_unique(namespace, msg);
398 assert_eq!(result, expected);
399 assert_eq!(result.len(), result.capacity());
400 }
401
402 #[test]
403 fn test_union_unique_zero_length() {
404 let namespace = b"";
405 let msg = b"message";
406
407 let length_encoding = vec![0];
408 let mut expected = Vec::with_capacity(length_encoding.len() + namespace.len() + msg.len());
409 expected.extend_from_slice(&length_encoding);
410 expected.extend_from_slice(msg);
411
412 let result = union_unique(namespace, msg);
413 assert_eq!(result, expected);
414 assert_eq!(result.len(), result.capacity());
415 }
416
417 #[test]
418 fn test_union_unique_long_length() {
419 let namespace = &b"n".repeat(256);
421 let msg = b"message";
422
423 let length_encoding = vec![0b1000_0000, 0b0000_0010];
424 let mut expected = Vec::with_capacity(length_encoding.len() + namespace.len() + msg.len());
425 expected.extend_from_slice(&length_encoding);
426 expected.extend_from_slice(namespace);
427 expected.extend_from_slice(msg);
428
429 let result = union_unique(namespace, msg);
430 assert_eq!(result, expected);
431 assert_eq!(result.len(), result.capacity());
432 }
433
434 #[test]
435 fn test_modulo() {
436 assert_eq!(modulo(&[], 1), 0);
438
439 assert_eq!(modulo(&hex!("0x01"), 1), 0);
441
442 assert_eq!(modulo(&hex!("0x010203"), 10), 1);
444
445 for i in 0..100 {
447 let mut rng = TestRng::new(i);
448 let bytes: [u8; 32] = rng.random();
449
450 let n = 11u64;
452 let big_modulo = BigUint::from_bytes_be(&bytes) % n;
453 let utils_modulo = modulo(&bytes, n);
454 assert_eq!(big_modulo, BigUint::from(utils_modulo));
455
456 let n = 11_111u64;
458 let big_modulo = BigUint::from_bytes_be(&bytes) % n;
459 let utils_modulo = modulo(&bytes, n);
460 assert_eq!(big_modulo, BigUint::from(utils_modulo));
461
462 let n = 0xDFFFFFFFFFFFFFFD;
464 let big_modulo = BigUint::from_bytes_be(&bytes) % n;
465 let utils_modulo = modulo(&bytes, n);
466 assert_eq!(big_modulo, BigUint::from(utils_modulo));
467 }
468 }
469
470 #[test]
471 #[should_panic]
472 fn test_modulo_zero_panics() {
473 modulo(&hex!("0x010203"), 0);
474 }
475
476 #[test]
477 fn test_non_zero_macros_compile_time() {
478 assert_eq!(NZUsize!(1).get(), 1);
481 assert_eq!(NZU8!(2).get(), 2);
482 assert_eq!(NZU16!(3).get(), 3);
483 assert_eq!(NZU32!(4).get(), 4);
484 assert_eq!(NZU64!(5).get(), 5);
485
486 const _: core::num::NonZeroUsize = NZUsize!(1);
488 const _: core::num::NonZeroU8 = NZU8!(2);
489 const _: core::num::NonZeroU16 = NZU16!(3);
490 const _: core::num::NonZeroU32 = NZU32!(4);
491 const _: core::num::NonZeroU64 = NZU64!(5);
492 }
493
494 #[test]
495 fn test_non_zero_macros_runtime() {
496 let one_usize: usize = 1;
498 let two_u8: u8 = 2;
499 let three_u16: u16 = 3;
500 let four_u32: u32 = 4;
501 let five_u64: u64 = 5;
502
503 assert_eq!(NZUsize!(one_usize).get(), 1);
504 assert_eq!(NZU8!(two_u8).get(), 2);
505 assert_eq!(NZU16!(three_u16).get(), 3);
506 assert_eq!(NZU32!(four_u32).get(), 4);
507 assert_eq!(NZU64!(five_u64).get(), 5);
508
509 let zero_usize: usize = 0;
511 let zero_u8: u8 = 0;
512 let zero_u16: u16 = 0;
513 let zero_u32: u32 = 0;
514 let zero_u64: u64 = 0;
515
516 assert!(std::panic::catch_unwind(|| NZUsize!(zero_usize)).is_err());
517 assert!(std::panic::catch_unwind(|| NZU8!(zero_u8)).is_err());
518 assert!(std::panic::catch_unwind(|| NZU16!(zero_u16)).is_err());
519 assert!(std::panic::catch_unwind(|| NZU32!(zero_u32)).is_err());
520 assert!(std::panic::catch_unwind(|| NZU64!(zero_u64)).is_err());
521
522 assert!(std::panic::catch_unwind(|| NZDuration!(Duration::ZERO)).is_err());
524 assert_eq!(
525 NZDuration!(Duration::from_secs(1)).get(),
526 Duration::from_secs(1)
527 );
528 }
529
530 #[test]
531 fn test_non_zero_duration() {
532 assert!(NonZeroDuration::new(Duration::ZERO).is_none());
534
535 let duration = Duration::from_millis(100);
537 let nz_duration = NonZeroDuration::new(duration).unwrap();
538 assert_eq!(nz_duration.get(), duration);
539 assert_eq!(Duration::from(nz_duration), duration);
540
541 assert!(std::panic::catch_unwind(|| NonZeroDuration::new_panic(Duration::ZERO)).is_err());
543
544 let d1 = NonZeroDuration::new(Duration::from_millis(100)).unwrap();
546 let d2 = NonZeroDuration::new(Duration::from_millis(200)).unwrap();
547 assert!(d1 < d2);
548 }
549
550 #[test]
551 fn test_participant_constructors() {
552 assert_eq!(Participant::new(0).get(), 0);
553 assert_eq!(Participant::new(42).get(), 42);
554 assert_eq!(Participant::from_usize(0).get(), 0);
555 assert_eq!(Participant::from_usize(42).get(), 42);
556 assert_eq!(Participant::from_usize(u32::MAX as usize).get(), u32::MAX);
557 }
558
559 #[test]
560 #[should_panic(expected = "participant index exceeds u32::MAX")]
561 fn test_participant_from_usize_overflow() {
562 Participant::from_usize((u32::MAX as usize) + 1);
563 }
564
565 #[test]
566 fn test_participant_display() {
567 assert_eq!(format!("{}", Participant::new(0)), "0");
568 assert_eq!(format!("{}", Participant::new(42)), "42");
569 assert_eq!(format!("{}", Participant::new(1000)), "1000");
570 }
571
572 #[test]
573 fn test_participant_ordering() {
574 assert!(Participant::new(0) < Participant::new(1));
575 assert!(Participant::new(5) < Participant::new(10));
576 assert!(Participant::new(10) > Participant::new(5));
577 assert_eq!(Participant::new(42), Participant::new(42));
578 }
579
580 #[test]
581 fn test_participant_encode_decode() {
582 use commonware_codec::{DecodeExt, Encode};
583
584 let cases = vec![0u32, 1, 127, 128, 255, 256, u32::MAX];
585 for value in cases {
586 let participant = Participant::new(value);
587 let encoded = participant.encode();
588 assert_eq!(encoded.len(), participant.encode_size());
589 let decoded = Participant::decode(encoded).unwrap();
590 assert_eq!(participant, decoded);
591 }
592 }
593
594 #[cfg(feature = "arbitrary")]
595 mod conformance {
596 use super::*;
597 use commonware_codec::conformance::CodecConformance;
598
599 commonware_conformance::conformance_tests! {
600 CodecConformance<Participant>,
601 }
602 }
603}