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::{test_rng, FuzzRng, TestRng};
11});
12commonware_macros::stability_scope!(BETA {
13 #[cfg(not(feature = "std"))]
14 extern crate alloc;
15
16 #[cfg(not(feature = "std"))]
17 use alloc::{boxed::Box, vec::Vec};
18 use bytes::{BufMut, BytesMut};
19 use core::time::Duration;
20 pub mod faults;
21 pub use faults::{Faults, N3f1, N5f1};
22
23 pub mod sequence;
24 pub use sequence::{Array, Span};
25
26 pub mod hostname;
27 pub use hostname::Hostname;
28
29 pub mod bitmap;
30 pub mod cache;
31 pub mod ordered;
32 pub mod range;
33
34 use bytes::Buf;
35 use commonware_codec::{varint::UInt, EncodeSize, Error as CodecError, Read, ReadExt, Write};
36
37 pub const GOLDEN_RATIO: u64 = 0x9e37_79b9_7f4a_7c15;
42
43 #[derive(Copy, Clone, Debug, Default, PartialEq, Eq, PartialOrd, Ord, Hash)]
49 #[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
50 pub struct Participant(u32);
51
52 impl Participant {
53 pub const fn new(index: u32) -> Self {
55 Self(index)
56 }
57
58 pub fn from_usize(index: usize) -> Self {
64 Self(u32::try_from(index).expect("participant index exceeds u32::MAX"))
65 }
66
67 pub const fn get(self) -> u32 {
69 self.0
70 }
71 }
72
73 impl From<Participant> for usize {
74 fn from(p: Participant) -> Self {
75 p.0 as Self
76 }
77 }
78
79 impl core::fmt::Display for Participant {
80 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
81 write!(f, "{}", self.0)
82 }
83 }
84
85 impl Read for Participant {
86 type Cfg = ();
87
88 fn read_cfg(buf: &mut impl Buf, _cfg: &Self::Cfg) -> Result<Self, CodecError> {
89 let value: u32 = UInt::read(buf)?.into();
90 Ok(Self(value))
91 }
92 }
93
94 impl Write for Participant {
95 fn write(&self, buf: &mut impl bytes::BufMut) {
96 UInt(self.0).write(buf);
97 }
98 }
99
100 impl EncodeSize for Participant {
101 fn encode_size(&self) -> usize {
102 UInt(self.0).encode_size()
103 }
104 }
105
106 pub trait TryFromIterator<T>: Sized {
108 type Error;
110
111 fn try_from_iter<I: IntoIterator<Item = T>>(iter: I) -> Result<Self, Self::Error>;
113 }
114
115 pub trait TryCollect: Iterator + Sized {
117 fn try_collect<C: TryFromIterator<Self::Item>>(self) -> Result<C, C::Error> {
119 C::try_from_iter(self)
120 }
121 }
122
123 impl<I: Iterator> TryCollect for I {}
124
125 pub type BoxedError = Box<dyn core::error::Error + Send + Sync>;
127
128 pub fn union(a: &[u8], b: &[u8]) -> Vec<u8> {
130 let mut union = Vec::with_capacity(a.len() + b.len());
131 union.extend_from_slice(a);
132 union.extend_from_slice(b);
133 union
134 }
135
136 pub fn union_unique(namespace: &[u8], msg: &[u8]) -> Vec<u8> {
140 use commonware_codec::EncodeSize;
141 let len_prefix = namespace.len();
142 let mut buf =
143 BytesMut::with_capacity(len_prefix.encode_size() + namespace.len() + msg.len());
144 len_prefix.write(&mut buf);
145 BufMut::put_slice(&mut buf, namespace);
146 BufMut::put_slice(&mut buf, msg);
147 buf.into()
148 }
149
150 pub fn modulo(bytes: &[u8], n: u64) -> u64 {
158 assert_ne!(n, 0, "modulus must be non-zero");
159
160 let n = n as u128;
161 let mut result = 0u128;
162 for &byte in bytes {
163 result = (result << 8) | (byte as u128);
164 result %= n;
165 }
166
167 result as u64
169 }
170
171 #[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
173 pub struct NonZeroDuration(Duration);
174
175 impl NonZeroDuration {
176 pub fn new(duration: Duration) -> Option<Self> {
178 if duration == Duration::ZERO {
179 None
180 } else {
181 Some(Self(duration))
182 }
183 }
184
185 pub fn new_panic(duration: Duration) -> Self {
187 Self::new(duration).expect("duration must be non-zero")
188 }
189
190 pub const fn get(self) -> Duration {
192 self.0
193 }
194 }
195
196 impl From<NonZeroDuration> for Duration {
197 fn from(nz_duration: NonZeroDuration) -> Self {
198 nz_duration.0
199 }
200 }
201});
202commonware_macros::stability_scope!(BETA, cfg(feature = "std") {
203 pub mod rng;
204 pub use rng::sys_rng;
205
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 pub mod thread_local;
227 pub use thread_local::Cached;
228});
229#[cfg(not(any(
230 commonware_stability_GAMMA,
231 commonware_stability_DELTA,
232 commonware_stability_EPSILON,
233 commonware_stability_RESERVED
234)))] pub mod vec;
236
237#[macro_export]
241macro_rules! NZUsize {
242 ($val:literal) => {
243 const { ::core::num::NonZeroUsize::new($val).expect("value must be non-zero") }
244 };
245 ($val:expr) => {
246 ::core::num::NonZeroUsize::new($val).expect("value must be non-zero")
248 };
249}
250
251#[macro_export]
255macro_rules! NZU8 {
256 ($val:literal) => {
257 const { ::core::num::NonZeroU8::new($val).expect("value must be non-zero") }
258 };
259 ($val:expr) => {
260 ::core::num::NonZeroU8::new($val).expect("value must be non-zero")
262 };
263}
264
265#[macro_export]
269macro_rules! NZU16 {
270 ($val:literal) => {
271 const { ::core::num::NonZeroU16::new($val).expect("value must be non-zero") }
272 };
273 ($val:expr) => {
274 ::core::num::NonZeroU16::new($val).expect("value must be non-zero")
276 };
277}
278
279#[macro_export]
283macro_rules! NZU32 {
284 ($val:literal) => {
285 const { ::core::num::NonZeroU32::new($val).expect("value must be non-zero") }
286 };
287 ($val:expr) => {
288 ::core::num::NonZeroU32::new($val).expect("value must be non-zero")
290 };
291}
292
293#[macro_export]
297macro_rules! NZU64 {
298 ($val:literal) => {
299 const { ::core::num::NonZeroU64::new($val).expect("value must be non-zero") }
300 };
301 ($val:expr) => {
302 ::core::num::NonZeroU64::new($val).expect("value must be non-zero")
304 };
305}
306
307#[doc(hidden)]
310pub use ::commonware_formatting as __formatting;
311
312#[cfg(not(any(
315 commonware_stability_GAMMA,
316 commonware_stability_DELTA,
317 commonware_stability_EPSILON,
318 commonware_stability_RESERVED
319)))] #[macro_export]
321macro_rules! fixed_bytes {
322 ($s:tt) => {
323 const { $crate::sequence::FixedBytes::new($crate::__formatting::hex!($s)) }
324 };
325}
326
327#[macro_export]
329macro_rules! NZDuration {
330 ($val:expr) => {
331 $crate::NonZeroDuration::new_panic($val)
333 };
334}
335
336#[cfg(test)]
337mod tests {
338 use super::*;
339 use crate::TestRng;
340 use commonware_formatting::hex;
341 use num_bigint::BigUint;
342 use rand::RngExt as _;
343
344 #[test]
345 fn test_union() {
346 assert_eq!(union(&[], &[]), Vec::<u8>::new());
348
349 assert_eq!(union(&[], &hex!("0x010203")), hex!("0x010203"));
351
352 assert_eq!(
354 union(&hex!("0x010203"), &hex!("0x040506")),
355 hex!("0x010203040506")
356 );
357 }
358
359 #[test]
360 fn test_union_unique() {
361 let namespace = b"namespace";
362 let msg = b"message";
363
364 let length_encoding = vec![0b0000_1001];
365 let mut expected = Vec::with_capacity(length_encoding.len() + namespace.len() + msg.len());
366 expected.extend_from_slice(&length_encoding);
367 expected.extend_from_slice(namespace);
368 expected.extend_from_slice(msg);
369
370 let result = union_unique(namespace, msg);
371 assert_eq!(result, expected);
372 assert_eq!(result.len(), result.capacity());
373 }
374
375 #[test]
376 fn test_union_unique_zero_length() {
377 let namespace = b"";
378 let msg = b"message";
379
380 let length_encoding = vec![0];
381 let mut expected = Vec::with_capacity(length_encoding.len() + namespace.len() + msg.len());
382 expected.extend_from_slice(&length_encoding);
383 expected.extend_from_slice(msg);
384
385 let result = union_unique(namespace, msg);
386 assert_eq!(result, expected);
387 assert_eq!(result.len(), result.capacity());
388 }
389
390 #[test]
391 fn test_union_unique_long_length() {
392 let namespace = &b"n".repeat(256);
394 let msg = b"message";
395
396 let length_encoding = vec![0b1000_0000, 0b0000_0010];
397 let mut expected = Vec::with_capacity(length_encoding.len() + namespace.len() + msg.len());
398 expected.extend_from_slice(&length_encoding);
399 expected.extend_from_slice(namespace);
400 expected.extend_from_slice(msg);
401
402 let result = union_unique(namespace, msg);
403 assert_eq!(result, expected);
404 assert_eq!(result.len(), result.capacity());
405 }
406
407 #[test]
408 fn test_modulo() {
409 assert_eq!(modulo(&[], 1), 0);
411
412 assert_eq!(modulo(&hex!("0x01"), 1), 0);
414
415 assert_eq!(modulo(&hex!("0x010203"), 10), 1);
417
418 for i in 0..100 {
420 let mut rng = TestRng::new(i);
421 let bytes: [u8; 32] = rng.random();
422
423 let n = 11u64;
425 let big_modulo = BigUint::from_bytes_be(&bytes) % n;
426 let utils_modulo = modulo(&bytes, n);
427 assert_eq!(big_modulo, BigUint::from(utils_modulo));
428
429 let n = 11_111u64;
431 let big_modulo = BigUint::from_bytes_be(&bytes) % n;
432 let utils_modulo = modulo(&bytes, n);
433 assert_eq!(big_modulo, BigUint::from(utils_modulo));
434
435 let n = 0xDFFFFFFFFFFFFFFD;
437 let big_modulo = BigUint::from_bytes_be(&bytes) % n;
438 let utils_modulo = modulo(&bytes, n);
439 assert_eq!(big_modulo, BigUint::from(utils_modulo));
440 }
441 }
442
443 #[test]
444 #[should_panic]
445 fn test_modulo_zero_panics() {
446 modulo(&hex!("0x010203"), 0);
447 }
448
449 #[test]
450 fn test_non_zero_macros_compile_time() {
451 assert_eq!(NZUsize!(1).get(), 1);
454 assert_eq!(NZU8!(2).get(), 2);
455 assert_eq!(NZU16!(3).get(), 3);
456 assert_eq!(NZU32!(4).get(), 4);
457 assert_eq!(NZU64!(5).get(), 5);
458
459 const _: core::num::NonZeroUsize = NZUsize!(1);
461 const _: core::num::NonZeroU8 = NZU8!(2);
462 const _: core::num::NonZeroU16 = NZU16!(3);
463 const _: core::num::NonZeroU32 = NZU32!(4);
464 const _: core::num::NonZeroU64 = NZU64!(5);
465 }
466
467 #[test]
468 fn test_non_zero_macros_runtime() {
469 let one_usize: usize = 1;
471 let two_u8: u8 = 2;
472 let three_u16: u16 = 3;
473 let four_u32: u32 = 4;
474 let five_u64: u64 = 5;
475
476 assert_eq!(NZUsize!(one_usize).get(), 1);
477 assert_eq!(NZU8!(two_u8).get(), 2);
478 assert_eq!(NZU16!(three_u16).get(), 3);
479 assert_eq!(NZU32!(four_u32).get(), 4);
480 assert_eq!(NZU64!(five_u64).get(), 5);
481
482 let zero_usize: usize = 0;
484 let zero_u8: u8 = 0;
485 let zero_u16: u16 = 0;
486 let zero_u32: u32 = 0;
487 let zero_u64: u64 = 0;
488
489 assert!(std::panic::catch_unwind(|| NZUsize!(zero_usize)).is_err());
490 assert!(std::panic::catch_unwind(|| NZU8!(zero_u8)).is_err());
491 assert!(std::panic::catch_unwind(|| NZU16!(zero_u16)).is_err());
492 assert!(std::panic::catch_unwind(|| NZU32!(zero_u32)).is_err());
493 assert!(std::panic::catch_unwind(|| NZU64!(zero_u64)).is_err());
494
495 assert!(std::panic::catch_unwind(|| NZDuration!(Duration::ZERO)).is_err());
497 assert_eq!(
498 NZDuration!(Duration::from_secs(1)).get(),
499 Duration::from_secs(1)
500 );
501 }
502
503 #[test]
504 fn test_non_zero_duration() {
505 assert!(NonZeroDuration::new(Duration::ZERO).is_none());
507
508 let duration = Duration::from_millis(100);
510 let nz_duration = NonZeroDuration::new(duration).unwrap();
511 assert_eq!(nz_duration.get(), duration);
512 assert_eq!(Duration::from(nz_duration), duration);
513
514 assert!(std::panic::catch_unwind(|| NonZeroDuration::new_panic(Duration::ZERO)).is_err());
516
517 let d1 = NonZeroDuration::new(Duration::from_millis(100)).unwrap();
519 let d2 = NonZeroDuration::new(Duration::from_millis(200)).unwrap();
520 assert!(d1 < d2);
521 }
522
523 #[test]
524 fn test_participant_constructors() {
525 assert_eq!(Participant::new(0).get(), 0);
526 assert_eq!(Participant::new(42).get(), 42);
527 assert_eq!(Participant::from_usize(0).get(), 0);
528 assert_eq!(Participant::from_usize(42).get(), 42);
529 assert_eq!(Participant::from_usize(u32::MAX as usize).get(), u32::MAX);
530 }
531
532 #[test]
533 #[should_panic(expected = "participant index exceeds u32::MAX")]
534 fn test_participant_from_usize_overflow() {
535 Participant::from_usize((u32::MAX as usize) + 1);
536 }
537
538 #[test]
539 fn test_participant_display() {
540 assert_eq!(format!("{}", Participant::new(0)), "0");
541 assert_eq!(format!("{}", Participant::new(42)), "42");
542 assert_eq!(format!("{}", Participant::new(1000)), "1000");
543 }
544
545 #[test]
546 fn test_participant_ordering() {
547 assert!(Participant::new(0) < Participant::new(1));
548 assert!(Participant::new(5) < Participant::new(10));
549 assert!(Participant::new(10) > Participant::new(5));
550 assert_eq!(Participant::new(42), Participant::new(42));
551 }
552
553 #[test]
554 fn test_participant_encode_decode() {
555 use commonware_codec::{DecodeExt, Encode};
556
557 let cases = vec![0u32, 1, 127, 128, 255, 256, u32::MAX];
558 for value in cases {
559 let participant = Participant::new(value);
560 let encoded = participant.encode();
561 assert_eq!(encoded.len(), participant.encode_size());
562 let decoded = Participant::decode(encoded).unwrap();
563 assert_eq!(participant, decoded);
564 }
565 }
566
567 #[cfg(feature = "arbitrary")]
568 mod conformance {
569 use super::*;
570 use commonware_codec::conformance::CodecConformance;
571
572 commonware_conformance::conformance_tests! {
573 CodecConformance<Participant>,
574 }
575 }
576}