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, vec::Vec};
22 use bytes::{BufMut, BytesMut};
23 use core::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 union(a: &[u8], b: &[u8]) -> Vec<u8> {
133 let mut union = Vec::with_capacity(a.len() + b.len());
134 union.extend_from_slice(a);
135 union.extend_from_slice(b);
136 union
137 }
138
139 pub fn union_unique(namespace: &[u8], msg: &[u8]) -> Vec<u8> {
143 use commonware_codec::EncodeSize;
144 let len_prefix = namespace.len();
145 let mut buf =
146 BytesMut::with_capacity(len_prefix.encode_size() + namespace.len() + msg.len());
147 len_prefix.write(&mut buf);
148 BufMut::put_slice(&mut buf, namespace);
149 BufMut::put_slice(&mut buf, msg);
150 buf.into()
151 }
152
153 pub fn modulo(bytes: &[u8], n: u64) -> u64 {
161 assert_ne!(n, 0, "modulus must be non-zero");
162
163 let n = n as u128;
164 let mut result = 0u128;
165 for &byte in bytes {
166 result = (result << 8) | (byte as u128);
167 result %= n;
168 }
169
170 result as u64
172 }
173
174 #[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
176 pub struct NonZeroDuration(Duration);
177
178 impl NonZeroDuration {
179 pub fn new(duration: Duration) -> Option<Self> {
181 if duration == Duration::ZERO {
182 None
183 } else {
184 Some(Self(duration))
185 }
186 }
187
188 pub fn new_panic(duration: Duration) -> Self {
190 Self::new(duration).expect("duration must be non-zero")
191 }
192
193 pub const fn get(self) -> Duration {
195 self.0
196 }
197 }
198
199 impl From<NonZeroDuration> for Duration {
200 fn from(nz_duration: NonZeroDuration) -> Self {
201 nz_duration.0
202 }
203 }
204});
205commonware_macros::stability_scope!(BETA, cfg(feature = "std") {
206 pub mod acknowledgement;
207 pub use acknowledgement::Acknowledgement;
208
209 pub mod net;
210 pub use net::IpAddrExt;
211
212 pub mod time;
213 pub use time::{DurationExt, SystemTimeExt};
214
215 pub mod rational;
216 pub use rational::BigRationalExt;
217
218 mod priority_set;
219 pub use priority_set::PrioritySet;
220
221 pub mod channel;
222 pub mod concurrency;
223 pub mod futures;
224 pub mod sync;
225});
226#[cfg(not(any(
227 commonware_stability_GAMMA,
228 commonware_stability_DELTA,
229 commonware_stability_EPSILON,
230 commonware_stability_RESERVED
231)))] pub mod vec;
233
234#[macro_export]
238macro_rules! NZUsize {
239 ($val:literal) => {
240 const { ::core::num::NonZeroUsize::new($val).expect("value must be non-zero") }
241 };
242 ($val:expr) => {
243 ::core::num::NonZeroUsize::new($val).expect("value must be non-zero")
245 };
246}
247
248#[macro_export]
252macro_rules! NZU8 {
253 ($val:literal) => {
254 const { ::core::num::NonZeroU8::new($val).expect("value must be non-zero") }
255 };
256 ($val:expr) => {
257 ::core::num::NonZeroU8::new($val).expect("value must be non-zero")
259 };
260}
261
262#[macro_export]
266macro_rules! NZU16 {
267 ($val:literal) => {
268 const { ::core::num::NonZeroU16::new($val).expect("value must be non-zero") }
269 };
270 ($val:expr) => {
271 ::core::num::NonZeroU16::new($val).expect("value must be non-zero")
273 };
274}
275
276#[macro_export]
280macro_rules! NZU32 {
281 ($val:literal) => {
282 const { ::core::num::NonZeroU32::new($val).expect("value must be non-zero") }
283 };
284 ($val:expr) => {
285 ::core::num::NonZeroU32::new($val).expect("value must be non-zero")
287 };
288}
289
290#[macro_export]
294macro_rules! NZU64 {
295 ($val:literal) => {
296 const { ::core::num::NonZeroU64::new($val).expect("value must be non-zero") }
297 };
298 ($val:expr) => {
299 ::core::num::NonZeroU64::new($val).expect("value must be non-zero")
301 };
302}
303
304#[doc(hidden)]
307pub use ::commonware_formatting as __formatting;
308
309#[cfg(not(any(
312 commonware_stability_GAMMA,
313 commonware_stability_DELTA,
314 commonware_stability_EPSILON,
315 commonware_stability_RESERVED
316)))] #[macro_export]
318macro_rules! fixed_bytes {
319 ($s:tt) => {
320 const { $crate::sequence::FixedBytes::new($crate::__formatting::hex!($s)) }
321 };
322}
323
324#[macro_export]
326macro_rules! NZDuration {
327 ($val:expr) => {
328 $crate::NonZeroDuration::new_panic($val)
330 };
331}
332
333#[cfg(test)]
334mod tests {
335 use super::*;
336 use commonware_formatting::hex;
337 use num_bigint::BigUint;
338 use rand::{rngs::StdRng, Rng, SeedableRng};
339
340 #[test]
341 fn test_union() {
342 assert_eq!(union(&[], &[]), Vec::<u8>::new());
344
345 assert_eq!(union(&[], &hex!("0x010203")), hex!("0x010203"));
347
348 assert_eq!(
350 union(&hex!("0x010203"), &hex!("0x040506")),
351 hex!("0x010203040506")
352 );
353 }
354
355 #[test]
356 fn test_union_unique() {
357 let namespace = b"namespace";
358 let msg = b"message";
359
360 let length_encoding = vec![0b0000_1001];
361 let mut expected = Vec::with_capacity(length_encoding.len() + namespace.len() + msg.len());
362 expected.extend_from_slice(&length_encoding);
363 expected.extend_from_slice(namespace);
364 expected.extend_from_slice(msg);
365
366 let result = union_unique(namespace, msg);
367 assert_eq!(result, expected);
368 assert_eq!(result.len(), result.capacity());
369 }
370
371 #[test]
372 fn test_union_unique_zero_length() {
373 let namespace = b"";
374 let msg = b"message";
375
376 let length_encoding = vec![0];
377 let mut expected = Vec::with_capacity(length_encoding.len() + namespace.len() + msg.len());
378 expected.extend_from_slice(&length_encoding);
379 expected.extend_from_slice(msg);
380
381 let result = union_unique(namespace, msg);
382 assert_eq!(result, expected);
383 assert_eq!(result.len(), result.capacity());
384 }
385
386 #[test]
387 fn test_union_unique_long_length() {
388 let namespace = &b"n".repeat(256);
390 let msg = b"message";
391
392 let length_encoding = vec![0b1000_0000, 0b0000_0010];
393 let mut expected = Vec::with_capacity(length_encoding.len() + namespace.len() + msg.len());
394 expected.extend_from_slice(&length_encoding);
395 expected.extend_from_slice(namespace);
396 expected.extend_from_slice(msg);
397
398 let result = union_unique(namespace, msg);
399 assert_eq!(result, expected);
400 assert_eq!(result.len(), result.capacity());
401 }
402
403 #[test]
404 fn test_modulo() {
405 assert_eq!(modulo(&[], 1), 0);
407
408 assert_eq!(modulo(&hex!("0x01"), 1), 0);
410
411 assert_eq!(modulo(&hex!("0x010203"), 10), 1);
413
414 for i in 0..100 {
416 let mut rng = StdRng::seed_from_u64(i);
417 let bytes: [u8; 32] = rng.gen();
418
419 let n = 11u64;
421 let big_modulo = BigUint::from_bytes_be(&bytes) % n;
422 let utils_modulo = modulo(&bytes, n);
423 assert_eq!(big_modulo, BigUint::from(utils_modulo));
424
425 let n = 11_111u64;
427 let big_modulo = BigUint::from_bytes_be(&bytes) % n;
428 let utils_modulo = modulo(&bytes, n);
429 assert_eq!(big_modulo, BigUint::from(utils_modulo));
430
431 let n = 0xDFFFFFFFFFFFFFFD;
433 let big_modulo = BigUint::from_bytes_be(&bytes) % n;
434 let utils_modulo = modulo(&bytes, n);
435 assert_eq!(big_modulo, BigUint::from(utils_modulo));
436 }
437 }
438
439 #[test]
440 #[should_panic]
441 fn test_modulo_zero_panics() {
442 modulo(&hex!("0x010203"), 0);
443 }
444
445 #[test]
446 fn test_non_zero_macros_compile_time() {
447 assert_eq!(NZUsize!(1).get(), 1);
450 assert_eq!(NZU8!(2).get(), 2);
451 assert_eq!(NZU16!(3).get(), 3);
452 assert_eq!(NZU32!(4).get(), 4);
453 assert_eq!(NZU64!(5).get(), 5);
454
455 const _: core::num::NonZeroUsize = NZUsize!(1);
457 const _: core::num::NonZeroU8 = NZU8!(2);
458 const _: core::num::NonZeroU16 = NZU16!(3);
459 const _: core::num::NonZeroU32 = NZU32!(4);
460 const _: core::num::NonZeroU64 = NZU64!(5);
461 }
462
463 #[test]
464 fn test_non_zero_macros_runtime() {
465 let one_usize: usize = 1;
467 let two_u8: u8 = 2;
468 let three_u16: u16 = 3;
469 let four_u32: u32 = 4;
470 let five_u64: u64 = 5;
471
472 assert_eq!(NZUsize!(one_usize).get(), 1);
473 assert_eq!(NZU8!(two_u8).get(), 2);
474 assert_eq!(NZU16!(three_u16).get(), 3);
475 assert_eq!(NZU32!(four_u32).get(), 4);
476 assert_eq!(NZU64!(five_u64).get(), 5);
477
478 let zero_usize: usize = 0;
480 let zero_u8: u8 = 0;
481 let zero_u16: u16 = 0;
482 let zero_u32: u32 = 0;
483 let zero_u64: u64 = 0;
484
485 assert!(std::panic::catch_unwind(|| NZUsize!(zero_usize)).is_err());
486 assert!(std::panic::catch_unwind(|| NZU8!(zero_u8)).is_err());
487 assert!(std::panic::catch_unwind(|| NZU16!(zero_u16)).is_err());
488 assert!(std::panic::catch_unwind(|| NZU32!(zero_u32)).is_err());
489 assert!(std::panic::catch_unwind(|| NZU64!(zero_u64)).is_err());
490
491 assert!(std::panic::catch_unwind(|| NZDuration!(Duration::ZERO)).is_err());
493 assert_eq!(
494 NZDuration!(Duration::from_secs(1)).get(),
495 Duration::from_secs(1)
496 );
497 }
498
499 #[test]
500 fn test_non_zero_duration() {
501 assert!(NonZeroDuration::new(Duration::ZERO).is_none());
503
504 let duration = Duration::from_millis(100);
506 let nz_duration = NonZeroDuration::new(duration).unwrap();
507 assert_eq!(nz_duration.get(), duration);
508 assert_eq!(Duration::from(nz_duration), duration);
509
510 assert!(std::panic::catch_unwind(|| NonZeroDuration::new_panic(Duration::ZERO)).is_err());
512
513 let d1 = NonZeroDuration::new(Duration::from_millis(100)).unwrap();
515 let d2 = NonZeroDuration::new(Duration::from_millis(200)).unwrap();
516 assert!(d1 < d2);
517 }
518
519 #[test]
520 fn test_participant_constructors() {
521 assert_eq!(Participant::new(0).get(), 0);
522 assert_eq!(Participant::new(42).get(), 42);
523 assert_eq!(Participant::from_usize(0).get(), 0);
524 assert_eq!(Participant::from_usize(42).get(), 42);
525 assert_eq!(Participant::from_usize(u32::MAX as usize).get(), u32::MAX);
526 }
527
528 #[test]
529 #[should_panic(expected = "participant index exceeds u32::MAX")]
530 fn test_participant_from_usize_overflow() {
531 Participant::from_usize((u32::MAX as usize) + 1);
532 }
533
534 #[test]
535 fn test_participant_display() {
536 assert_eq!(format!("{}", Participant::new(0)), "0");
537 assert_eq!(format!("{}", Participant::new(42)), "42");
538 assert_eq!(format!("{}", Participant::new(1000)), "1000");
539 }
540
541 #[test]
542 fn test_participant_ordering() {
543 assert!(Participant::new(0) < Participant::new(1));
544 assert!(Participant::new(5) < Participant::new(10));
545 assert!(Participant::new(10) > Participant::new(5));
546 assert_eq!(Participant::new(42), Participant::new(42));
547 }
548
549 #[test]
550 fn test_participant_encode_decode() {
551 use commonware_codec::{DecodeExt, Encode};
552
553 let cases = vec![0u32, 1, 127, 128, 255, 256, u32::MAX];
554 for value in cases {
555 let participant = Participant::new(value);
556 let encoded = participant.encode();
557 assert_eq!(encoded.len(), participant.encode_size());
558 let decoded = Participant::decode(encoded).unwrap();
559 assert_eq!(participant, decoded);
560 }
561 }
562
563 #[cfg(feature = "arbitrary")]
564 mod conformance {
565 use super::*;
566 use commonware_codec::conformance::CodecConformance;
567
568 commonware_conformance::conformance_tests! {
569 CodecConformance<Participant>,
570 }
571 }
572}