Skip to main content

bcx_core/
lib.rs

1#![no_std]
2#![doc = "Core identifiers and validation primitives for BCX."]
3
4#[cfg(test)]
5extern crate std;
6
7mod error;
8mod ids;
9
10pub use error::ValidationError;
11pub use ids::{CapabilityRef, Digest, EventId, Nonce, OperationSequence, PolicyEpoch};
12
13#[cfg(test)]
14mod tests {
15    use super::*;
16    use std::{format, string::String};
17
18    #[test]
19    fn zero_digest_is_detected() {
20        let digest = Digest::new([0; Digest::LEN]);
21        assert!(digest.is_zero());
22    }
23
24    #[test]
25    fn digest_constant_shape_equality_matches_structural_equality() {
26        let left = Digest::new([7; Digest::LEN]);
27        let same = Digest::new([7; Digest::LEN]);
28        let different = Digest::new([8; Digest::LEN]);
29
30        assert!(left.ct_eq(&same));
31        assert!(!left.ct_eq(&different));
32    }
33
34    #[test]
35    fn nonce_debug_is_redacted() {
36        let nonce = Nonce::new([3; Nonce::LEN]);
37
38        assert_eq!(
39            nonce.map(|value| format!("{value:?}")),
40            Ok(String::from("Nonce(..)"))
41        );
42    }
43
44    #[test]
45    fn nonce_rejects_zero_and_compares_constant_shape() {
46        let left = Nonce::new([9; Nonce::LEN]);
47        let same = Nonce::new([9; Nonce::LEN]);
48        let different = Nonce::new([8; Nonce::LEN]);
49
50        assert_eq!(Nonce::new([0; Nonce::LEN]), Err(ValidationError::ZeroValue));
51        assert!(matches!((&left, &same), (Ok(a), Ok(b)) if a.ct_eq(b)));
52        assert!(matches!((&left, &different), (Ok(a), Ok(b)) if !a.ct_eq(b)));
53    }
54
55    #[test]
56    fn operation_sequence_rejects_zero() {
57        assert_eq!(OperationSequence::new(0), Err(ValidationError::ZeroValue));
58        assert_eq!(OperationSequence::new(7).map(OperationSequence::get), Ok(7));
59    }
60
61    #[test]
62    fn operation_sequence_checks_monotonic_successor() {
63        let previous = OperationSequence::new(7);
64        let next = previous.and_then(OperationSequence::next);
65
66        assert_eq!(next.map(OperationSequence::get), Ok(8));
67        assert!(matches!(
68            (OperationSequence::new(8), OperationSequence::new(7)),
69            (Ok(current), Ok(previous)) if current.immediately_follows(previous)
70        ));
71        assert_eq!(
72            OperationSequence::new(u64::MAX).and_then(OperationSequence::next),
73            Err(ValidationError::TooLarge)
74        );
75    }
76}