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(feature = "std"), no_std)]
8
9#[cfg(not(feature = "std"))]
10extern crate alloc;
11
12#[cfg(not(feature = "std"))]
13use alloc::{boxed::Box, string::String, vec::Vec};
14use bytes::{BufMut, BytesMut};
15use commonware_codec::{EncodeSize, Write};
16use core::{
17 fmt::{Debug, Write as FmtWrite},
18 time::Duration,
19};
20
21pub mod sequence;
22pub use sequence::{Array, Span};
23#[cfg(feature = "std")]
24pub mod acknowledgement;
25#[cfg(feature = "std")]
26pub use acknowledgement::Acknowledgement;
27pub mod bitmap;
28#[cfg(feature = "std")]
29pub mod channels;
30pub mod hex_literal;
31pub mod hostname;
32pub use hostname::Hostname;
33#[cfg(feature = "std")]
34pub mod net;
35pub mod ordered;
36pub mod vec;
37
38pub trait TryFromIterator<T>: Sized {
40 type Error;
42
43 fn try_from_iter<I: IntoIterator<Item = T>>(iter: I) -> Result<Self, Self::Error>;
45}
46
47pub trait TryCollect: Iterator + Sized {
49 fn try_collect<C: TryFromIterator<Self::Item>>(self) -> Result<C, C::Error> {
51 C::try_from_iter(self)
52 }
53}
54
55impl<I: Iterator> TryCollect for I {}
56#[cfg(feature = "std")]
57pub use net::IpAddrExt;
58#[cfg(feature = "std")]
59pub mod time;
60#[cfg(feature = "std")]
61pub use time::{DurationExt, SystemTimeExt};
62#[cfg(feature = "std")]
63pub mod rational;
64#[cfg(feature = "std")]
65pub use rational::BigRationalExt;
66#[cfg(feature = "std")]
67mod priority_set;
68#[cfg(feature = "std")]
69pub use priority_set::PrioritySet;
70#[cfg(feature = "std")]
71pub mod futures;
72mod stable_buf;
73pub use stable_buf::StableBuf;
74#[cfg(feature = "std")]
75pub mod concurrency;
76
77pub type BoxedError = Box<dyn core::error::Error + Send + Sync>;
79
80pub fn hex(bytes: &[u8]) -> String {
82 let mut hex = String::new();
83 for byte in bytes.iter() {
84 write!(hex, "{byte:02x}").expect("writing to string should never fail");
85 }
86 hex
87}
88
89pub fn from_hex(hex: &str) -> Option<Vec<u8>> {
91 let bytes = hex.as_bytes();
92 if !bytes.len().is_multiple_of(2) {
93 return None;
94 }
95
96 bytes
97 .chunks_exact(2)
98 .map(|chunk| {
99 let hi = decode_hex_digit(chunk[0])?;
100 let lo = decode_hex_digit(chunk[1])?;
101 Some((hi << 4) | lo)
102 })
103 .collect()
104}
105
106#[inline]
107const fn decode_hex_digit(byte: u8) -> Option<u8> {
108 match byte {
109 b'0'..=b'9' => Some(byte - b'0'),
110 b'a'..=b'f' => Some(byte - b'a' + 10),
111 b'A'..=b'F' => Some(byte - b'A' + 10),
112 _ => None,
113 }
114}
115
116pub fn from_hex_formatted(hex: &str) -> Option<Vec<u8>> {
119 let hex = hex.replace(['\t', '\n', '\r', ' '], "");
120 let res = hex.strip_prefix("0x").unwrap_or(&hex);
121 from_hex(res)
122}
123
124pub const fn max_faults(n: u32) -> u32 {
127 n.saturating_sub(1) / 3
128}
129
130pub fn quorum(n: u32) -> u32 {
138 assert!(n > 0, "n must not be zero");
139 n - max_faults(n)
140}
141
142pub fn quorum_from_slice<T>(slice: &[T]) -> u32 {
148 let n: u32 = slice
149 .len()
150 .try_into()
151 .expect("slice length must be less than u32::MAX");
152 quorum(n)
153}
154
155pub 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
163pub fn union_unique(namespace: &[u8], msg: &[u8]) -> Vec<u8> {
167 let len_prefix = namespace.len();
168 let mut buf = BytesMut::with_capacity(len_prefix.encode_size() + namespace.len() + msg.len());
169 len_prefix.write(&mut buf);
170 BufMut::put_slice(&mut buf, namespace);
171 BufMut::put_slice(&mut buf, msg);
172 buf.into()
173}
174
175pub fn modulo(bytes: &[u8], n: u64) -> u64 {
183 assert_ne!(n, 0, "modulus must be non-zero");
184
185 let n = n as u128;
186 let mut result = 0u128;
187 for &byte in bytes {
188 result = (result << 8) | (byte as u128);
189 result %= n;
190 }
191
192 result as u64
194}
195
196#[macro_export]
200macro_rules! NZUsize {
201 ($val:literal) => {
202 const { core::num::NonZeroUsize::new($val).expect("value must be non-zero") }
203 };
204 ($val:expr) => {
205 core::num::NonZeroUsize::new($val).expect("value must be non-zero")
207 };
208}
209
210#[macro_export]
214macro_rules! NZU8 {
215 ($val:literal) => {
216 const { core::num::NonZeroU8::new($val).expect("value must be non-zero") }
217 };
218 ($val:expr) => {
219 core::num::NonZeroU8::new($val).expect("value must be non-zero")
221 };
222}
223
224#[macro_export]
228macro_rules! NZU16 {
229 ($val:literal) => {
230 const { core::num::NonZeroU16::new($val).expect("value must be non-zero") }
231 };
232 ($val:expr) => {
233 core::num::NonZeroU16::new($val).expect("value must be non-zero")
235 };
236}
237
238#[macro_export]
242macro_rules! NZU32 {
243 ($val:literal) => {
244 const { core::num::NonZeroU32::new($val).expect("value must be non-zero") }
245 };
246 ($val:expr) => {
247 core::num::NonZeroU32::new($val).expect("value must be non-zero")
249 };
250}
251
252#[macro_export]
256macro_rules! NZU64 {
257 ($val:literal) => {
258 const { core::num::NonZeroU64::new($val).expect("value must be non-zero") }
259 };
260 ($val:expr) => {
261 core::num::NonZeroU64::new($val).expect("value must be non-zero")
263 };
264}
265
266#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
268pub struct NonZeroDuration(Duration);
269
270impl NonZeroDuration {
271 pub fn new(duration: Duration) -> Option<Self> {
273 if duration == Duration::ZERO {
274 None
275 } else {
276 Some(Self(duration))
277 }
278 }
279
280 pub fn new_panic(duration: Duration) -> Self {
282 Self::new(duration).expect("duration must be non-zero")
283 }
284
285 pub const fn get(self) -> Duration {
287 self.0
288 }
289}
290
291impl From<NonZeroDuration> for Duration {
292 fn from(nz_duration: NonZeroDuration) -> Self {
293 nz_duration.0
294 }
295}
296
297#[macro_export]
299macro_rules! NZDuration {
300 ($val:expr) => {
301 $crate::NonZeroDuration::new_panic($val)
303 };
304}
305
306#[cfg(test)]
307mod tests {
308 use super::*;
309 use num_bigint::BigUint;
310 use rand::{rngs::StdRng, Rng, SeedableRng};
311 use rstest::rstest;
312
313 #[test]
314 fn test_hex() {
315 let b = &[];
317 let h = hex(b);
318 assert_eq!(h, "");
319 assert_eq!(from_hex(&h).unwrap(), b.to_vec());
320
321 let b = &hex!("0x01");
323 let h = hex(b);
324 assert_eq!(h, "01");
325 assert_eq!(from_hex(&h).unwrap(), b.to_vec());
326
327 let b = &hex!("0x010203");
329 let h = hex(b);
330 assert_eq!(h, "010203");
331 assert_eq!(from_hex(&h).unwrap(), b.to_vec());
332
333 let h = "0102030";
335 assert!(from_hex(h).is_none());
336
337 let h = "01g3";
339 assert!(from_hex(h).is_none());
340
341 let h = "+123";
343 assert!(from_hex(h).is_none());
344
345 assert_eq!(from_hex(""), Some(vec![]));
347 }
348
349 #[test]
350 fn test_from_hex_formatted() {
351 let b = &[];
353 let h = hex(b);
354 assert_eq!(h, "");
355 assert_eq!(from_hex_formatted(&h).unwrap(), b.to_vec());
356
357 let b = &hex!("0x01");
359 let h = hex(b);
360 assert_eq!(h, "01");
361 assert_eq!(from_hex_formatted(&h).unwrap(), b.to_vec());
362
363 let b = &hex!("0x010203");
365 let h = hex(b);
366 assert_eq!(h, "010203");
367 assert_eq!(from_hex_formatted(&h).unwrap(), b.to_vec());
368
369 let h = "0102030";
371 assert!(from_hex_formatted(h).is_none());
372
373 let h = "01g3";
375 assert!(from_hex_formatted(h).is_none());
376
377 let h = "01 02 03";
379 assert_eq!(from_hex_formatted(h).unwrap(), b.to_vec());
380
381 let h = "0x010203";
383 assert_eq!(from_hex_formatted(h).unwrap(), b.to_vec());
384
385 let h = " \n\n0x\r\n01
387 02\t03\n";
388 assert_eq!(from_hex_formatted(h).unwrap(), b.to_vec());
389 }
390
391 #[test]
392 fn test_from_hex_utf8_char_boundaries() {
393 const MISALIGNMENT_CASE: &str = "쀘\n";
394
395 let b = from_hex(MISALIGNMENT_CASE);
397 assert!(b.is_none());
398 }
399
400 #[test]
401 fn test_max_faults_zero() {
402 assert_eq!(max_faults(0), 0);
403 }
404
405 #[test]
406 #[should_panic]
407 fn test_quorum_zero() {
408 quorum(0);
409 }
410
411 #[rstest]
412 #[case(1, 0, 1)]
413 #[case(2, 0, 2)]
414 #[case(3, 0, 3)]
415 #[case(4, 1, 3)]
416 #[case(5, 1, 4)]
417 #[case(6, 1, 5)]
418 #[case(7, 2, 5)]
419 #[case(8, 2, 6)]
420 #[case(9, 2, 7)]
421 #[case(10, 3, 7)]
422 #[case(11, 3, 8)]
423 #[case(12, 3, 9)]
424 #[case(13, 4, 9)]
425 #[case(14, 4, 10)]
426 #[case(15, 4, 11)]
427 #[case(16, 5, 11)]
428 #[case(17, 5, 12)]
429 #[case(18, 5, 13)]
430 #[case(19, 6, 13)]
431 #[case(20, 6, 14)]
432 #[case(21, 6, 15)]
433 fn test_quorum_and_max_faults(
434 #[case] n: u32,
435 #[case] expected_f: u32,
436 #[case] expected_q: u32,
437 ) {
438 assert_eq!(max_faults(n), expected_f);
439 assert_eq!(quorum(n), expected_q);
440 assert_eq!(n, expected_f + expected_q);
441 }
442
443 #[test]
444 fn test_union() {
445 assert_eq!(union(&[], &[]), []);
447
448 assert_eq!(union(&[], &hex!("0x010203")), hex!("0x010203"));
450
451 assert_eq!(
453 union(&hex!("0x010203"), &hex!("0x040506")),
454 hex!("0x010203040506")
455 );
456 }
457
458 #[test]
459 fn test_union_unique() {
460 let namespace = b"namespace";
461 let msg = b"message";
462
463 let length_encoding = vec![0b0000_1001];
464 let mut expected = Vec::with_capacity(length_encoding.len() + namespace.len() + msg.len());
465 expected.extend_from_slice(&length_encoding);
466 expected.extend_from_slice(namespace);
467 expected.extend_from_slice(msg);
468
469 let result = union_unique(namespace, msg);
470 assert_eq!(result, expected);
471 assert_eq!(result.len(), result.capacity());
472 }
473
474 #[test]
475 fn test_union_unique_zero_length() {
476 let namespace = b"";
477 let msg = b"message";
478
479 let length_encoding = vec![0];
480 let mut expected = Vec::with_capacity(length_encoding.len() + namespace.len() + msg.len());
481 expected.extend_from_slice(&length_encoding);
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_long_length() {
491 let namespace = &b"n".repeat(256);
493 let msg = b"message";
494
495 let length_encoding = vec![0b1000_0000, 0b0000_0010];
496 let mut expected = Vec::with_capacity(length_encoding.len() + namespace.len() + msg.len());
497 expected.extend_from_slice(&length_encoding);
498 expected.extend_from_slice(namespace);
499 expected.extend_from_slice(msg);
500
501 let result = union_unique(namespace, msg);
502 assert_eq!(result, expected);
503 assert_eq!(result.len(), result.capacity());
504 }
505
506 #[test]
507 fn test_modulo() {
508 assert_eq!(modulo(&[], 1), 0);
510
511 assert_eq!(modulo(&hex!("0x01"), 1), 0);
513
514 assert_eq!(modulo(&hex!("0x010203"), 10), 1);
516
517 for i in 0..100 {
519 let mut rng = StdRng::seed_from_u64(i);
520 let bytes: [u8; 32] = rng.gen();
521
522 let n = 11u64;
524 let big_modulo = BigUint::from_bytes_be(&bytes) % n;
525 let utils_modulo = modulo(&bytes, n);
526 assert_eq!(big_modulo, BigUint::from(utils_modulo));
527
528 let n = 11_111u64;
530 let big_modulo = BigUint::from_bytes_be(&bytes) % n;
531 let utils_modulo = modulo(&bytes, n);
532 assert_eq!(big_modulo, BigUint::from(utils_modulo));
533
534 let n = 0xDFFFFFFFFFFFFFFD;
536 let big_modulo = BigUint::from_bytes_be(&bytes) % n;
537 let utils_modulo = modulo(&bytes, n);
538 assert_eq!(big_modulo, BigUint::from(utils_modulo));
539 }
540 }
541
542 #[test]
543 #[should_panic]
544 fn test_modulo_zero_panics() {
545 modulo(&hex!("0x010203"), 0);
546 }
547
548 #[test]
549 fn test_non_zero_macros_compile_time() {
550 assert_eq!(NZUsize!(1).get(), 1);
553 assert_eq!(NZU8!(2).get(), 2);
554 assert_eq!(NZU16!(3).get(), 3);
555 assert_eq!(NZU32!(4).get(), 4);
556 assert_eq!(NZU64!(5).get(), 5);
557
558 const _: core::num::NonZeroUsize = NZUsize!(1);
560 const _: core::num::NonZeroU8 = NZU8!(2);
561 const _: core::num::NonZeroU16 = NZU16!(3);
562 const _: core::num::NonZeroU32 = NZU32!(4);
563 const _: core::num::NonZeroU64 = NZU64!(5);
564 }
565
566 #[test]
567 fn test_non_zero_macros_runtime() {
568 let one_usize: usize = 1;
570 let two_u8: u8 = 2;
571 let three_u16: u16 = 3;
572 let four_u32: u32 = 4;
573 let five_u64: u64 = 5;
574
575 assert_eq!(NZUsize!(one_usize).get(), 1);
576 assert_eq!(NZU8!(two_u8).get(), 2);
577 assert_eq!(NZU16!(three_u16).get(), 3);
578 assert_eq!(NZU32!(four_u32).get(), 4);
579 assert_eq!(NZU64!(five_u64).get(), 5);
580
581 let zero_usize: usize = 0;
583 let zero_u8: u8 = 0;
584 let zero_u16: u16 = 0;
585 let zero_u32: u32 = 0;
586 let zero_u64: u64 = 0;
587
588 assert!(std::panic::catch_unwind(|| NZUsize!(zero_usize)).is_err());
589 assert!(std::panic::catch_unwind(|| NZU8!(zero_u8)).is_err());
590 assert!(std::panic::catch_unwind(|| NZU16!(zero_u16)).is_err());
591 assert!(std::panic::catch_unwind(|| NZU32!(zero_u32)).is_err());
592 assert!(std::panic::catch_unwind(|| NZU64!(zero_u64)).is_err());
593
594 assert!(std::panic::catch_unwind(|| NZDuration!(Duration::ZERO)).is_err());
596 assert_eq!(
597 NZDuration!(Duration::from_secs(1)).get(),
598 Duration::from_secs(1)
599 );
600 }
601
602 #[test]
603 fn test_non_zero_duration() {
604 assert!(NonZeroDuration::new(Duration::ZERO).is_none());
606
607 let duration = Duration::from_millis(100);
609 let nz_duration = NonZeroDuration::new(duration).unwrap();
610 assert_eq!(nz_duration.get(), duration);
611 assert_eq!(Duration::from(nz_duration), duration);
612
613 assert!(std::panic::catch_unwind(|| NonZeroDuration::new_panic(Duration::ZERO)).is_err());
615
616 let d1 = NonZeroDuration::new(Duration::from_millis(100)).unwrap();
618 let d2 = NonZeroDuration::new(Duration::from_millis(200)).unwrap();
619 assert!(d1 < d2);
620 }
621}