From 4e3cbb00982557e2836be39c3b001ba57a38b2b9 Mon Sep 17 00:00:00 2001 From: Tanveer Wahid Date: Mon, 14 Sep 2026 18:49:37 -0700 Subject: [PATCH] refactor!: remove the derive feature and fallbacks --- consumer-test/Cargo.toml | 1 - scripts/test_features.sh | 2 +- tightbeam-derive/Cargo.toml | 6 - tightbeam-derive/src/lib.rs | 70 +++++----- tightbeam/Cargo.toml | 18 +-- tightbeam/src/builder/frame.rs | 69 ---------- tightbeam/src/colony/worker/mod.rs | 9 +- tightbeam/src/core.rs | 4 - tightbeam/src/crypto/profiles.rs | 4 +- tightbeam/src/lib.rs | 1 - tightbeam/src/macros/cfg.rs | 22 +++ tightbeam/src/macros/server.rs | 16 +-- tightbeam/src/prelude.rs | 15 +- tightbeam/src/testing/config.rs | 32 +---- .../src/testing/macros/verification_spec.rs | 10 +- tightbeam/src/testing/specs/error.rs | 129 +++--------------- tightbeam/src/transport/client/mod.rs | 1 - tightbeam/src/transport/envelopes.rs | 15 +- .../src/transport/handshake/negotiation.rs | 35 ++--- .../transport/handshake/primitives/prekeys.rs | 9 +- tightbeam/src/transport/handshake/receipt.rs | 3 +- tightbeam/src/utils/urn/builders/urn.rs | 37 ----- tightbeam/src/utils/urn/specs/tightbeam.rs | 86 ------------ tightbeam/tests/protocol_core/frame_der.rs | 44 +----- tightbeam/tests/tightbeam_core/tests.rs | 44 +----- tightbeam/tests/tightbeam_core/zero_queue.rs | 2 +- 26 files changed, 127 insertions(+), 557 deletions(-) diff --git a/consumer-test/Cargo.toml b/consumer-test/Cargo.toml index 341cbbea..a7b08cd2 100644 --- a/consumer-test/Cargo.toml +++ b/consumer-test/Cargo.toml @@ -12,7 +12,6 @@ workspace = true [dependencies] tightbeam = { package = "tightbeam-rs", path = "../tightbeam", default-features = false, features = [ "std", - "derive", "builder", "crypto", "digest", diff --git a/scripts/test_features.sh b/scripts/test_features.sh index 1d521604..b2e0a9a7 100755 --- a/scripts/test_features.sh +++ b/scripts/test_features.sh @@ -38,7 +38,7 @@ echo "[4/16] Check: Transport Full + TCP + Async" cargo check --package tightbeam-rs --no-default-features --features "std,transport-cms,transport-ecies,tcp,tokio,testing" echo "[5/16] Check: Transport CMS + Derive" -cargo check --package tightbeam-rs --no-default-features --features "std,transport-cms,derive,testing" +cargo check --package tightbeam-rs --no-default-features --features "std,transport-cms,testing" echo "[6/16] Check: Testing CSP/FDR" cargo check --package tightbeam-rs --no-default-features --features "std,transport-cms,testing,testing-csp,testing-fdr" diff --git a/tightbeam-derive/Cargo.toml b/tightbeam-derive/Cargo.toml index 9a197b4b..18437c34 100644 --- a/tightbeam-derive/Cargo.toml +++ b/tightbeam-derive/Cargo.toml @@ -20,9 +20,3 @@ workspace = true proc-macro2 = { workspace = true } quote = { workspace = true } syn = { workspace = true } - -[features] -aead = [] -digest = [] -signature = [] -compress = [] diff --git a/tightbeam-derive/src/lib.rs b/tightbeam-derive/src/lib.rs index 461b2b41..b1c0c047 100644 --- a/tightbeam-derive/src/lib.rs +++ b/tightbeam-derive/src/lib.rs @@ -183,6 +183,30 @@ pub fn derive_beamable(input: TokenStream) -> TokenStream { expand_beamable(&input).unwrap_or_else(syn::Error::into_compile_error).into() } +/// A compile error that fires when a `#[beam]` requirement names a tightbeam +/// feature the build disables. +/// +/// The check runs through tightbeam's `shim` macro, so tightbeam's own feature +/// state decides it. This crate carries no copy of tightbeam's features. +fn feature_check( + name: &syn::Ident, + shim: impl AsRef, + requirement: impl AsRef, + feature: impl AsRef, +) -> proc_macro2::TokenStream { + let shim = syn::Ident::new(shim.as_ref(), name.span()); + let message = format!( + "Message type `{name}` is marked as {} but the `{feature}` feature is not enabled. \ + Enable the feature in Cargo.toml: features = [\"{feature}\"]", + requirement.as_ref(), + feature = feature.as_ref(), + ); + + quote! { + ::tightbeam::#shim! { else { compile_error!(#message); } } + } +} + fn expand_beamable(input: &DeriveInput) -> syn::Result { let name = &input.ident; @@ -226,45 +250,17 @@ fn expand_beamable(input: &DeriveInput) -> syn::Result let final_frame_integrity = frame_integrity; let mut feature_checks = Vec::new(); - - if final_confidential && !cfg!(feature = "aead") { - feature_checks.push(quote! { - compile_error!(concat!( - "Message type `", stringify!(#name), "` is marked as confidential ", - "but the `aead` feature is not enabled. ", - "Enable the feature in Cargo.toml: features = [\"aead\"]" - )); - }); + if final_confidential { + feature_checks.push(feature_check(name, "__tb_if_aead", "confidential", "aead")); } - - if final_nonrep && !cfg!(feature = "signature") { - feature_checks.push(quote! { - compile_error!(concat!( - "Message type `", stringify!(#name), "` is marked as non-repudiable ", - "but the `signature` feature is not enabled. ", - "Enable the feature in Cargo.toml: features = [\"signature\"]" - )); - }); + if final_nonrep { + feature_checks.push(feature_check(name, "__tb_if_signature", "non-repudiable", "signature")); } - - if compressed && !cfg!(feature = "compress") { - feature_checks.push(quote! { - compile_error!(concat!( - "Message type `", stringify!(#name), "` is marked as compressed ", - "but the `compress` feature is not enabled. ", - "Enable the feature in Cargo.toml: features = [\"compress\"]" - )); - }); + if compressed { + feature_checks.push(feature_check(name, "__tb_if_compress", "compressed", "compress")); } - - if (final_message_integrity || final_frame_integrity) && !cfg!(feature = "digest") { - feature_checks.push(quote! { - compile_error!(concat!( - "Message type `", stringify!(#name), "` is marked as requiring message integrity ", - "but the `digest` feature is not enabled. ", - "Enable the feature in Cargo.toml: features = [\"digest\"]" - )); - }); + if final_message_integrity || final_frame_integrity { + feature_checks.push(feature_check(name, "__tb_if_digest", "requiring message integrity", "digest")); } let min_version_value = if let Some(version) = final_min_version { @@ -290,7 +286,7 @@ fn expand_beamable(input: &DeriveInput) -> syn::Result }; // Generate checker trait implementations for compile-time OID validation - // When HAS_PROFILE = true: generates impls ONLY for the matching OID type from the profile (compile-time enforcement) + // When HAS_PROFILE = true: generates impls ONLY for the matching OID type from the profile // When HAS_PROFILE = false: generates generic impls for all OID types (no enforcement, allows any) // All types using #[derive(Beamable)] get these impls - types not using derive must implement manually let oid_validation_helpers = if let Some(profile_ty) = &profile_type { diff --git a/tightbeam/Cargo.toml b/tightbeam/Cargo.toml index 2530dbbf..8c17ae01 100644 --- a/tightbeam/Cargo.toml +++ b/tightbeam/Cargo.toml @@ -112,7 +112,6 @@ full = [ "kdf", "ecies", "ecdh", - "derive", "tokio", "futures", "constants", @@ -126,7 +125,7 @@ full = [ # Core features constants = ["hex"] crypto = ["random", "dep:crypto-common", "zeroize"] -builder = ["derive", "x509-cert/builder", "crypto"] +builder = ["x509-cert/builder", "crypto"] policy = [] router = [] transport = [ @@ -139,7 +138,7 @@ transport = [ "kdf", "ecdh", ] -compress = ["tightbeam-derive/compress"] +compress = [] transport-policy = ["transport", "policy"] transport-multiplex = ["transport", "std", "futures", "futures/std"] # UNSTABLE: PQXDH prekey/kdf-chain/hybrid-KEM primitives. @@ -152,7 +151,6 @@ colony = [ "builder", "policy", "router", - "derive", "transport", "transport-ecies", "transport-multiplex", @@ -170,11 +168,9 @@ testing-schedulability = ["testing", "testing-timing"] testing-fault = ["testing", "testing-fdr"] testing-fmea = ["testing", "testing-fault", "instrument"] testing-fuzz = ["testing", "testing-csp", "dep:afl"] -# Property-based tests over the wire types. Off by default: the strategies -# only compile when a consumer asks for them. testing-property = ["testing", "dep:proptest"] testing-fuzz-ijon = ["testing-fuzz"] -instrument = ["std", "sha3", "digest", "derive"] +instrument = ["std", "sha3", "digest"] logging = [] # TODO @@ -188,7 +184,6 @@ aead = [ "dep:aead", "dep:ecdsa", "dep:crypto-common", - "tightbeam-derive/aead", "aead/rand_core", "dep:aes", "dep:aes-kw", @@ -203,12 +198,11 @@ signature = [ "dep:ecdsa", "ecdsa/verifying", "ecdsa/pem", - "tightbeam-derive/signature", "dep:signature", "cms/signature", "x509-cert/signature", ] -digest = ["crypto", "dep:digest", "tightbeam-derive/digest", "sha3"] +digest = ["crypto", "dep:digest", "sha3"] x509 = ["crypto", "dep:x509-cert", "ecdsa/pem", "digest"] kdf = ["crypto", "random", "zeroize", "digest", "dep:hkdf"] ecies = ["crypto", "kdf", "aead", "k256/ecdh", "secp256k1", "sha3"] @@ -255,10 +249,6 @@ transport-ecies = [ "ecdh", ] -# Gates the `Beamable` and `Flaggable` re-exports and the generated error and -# URN implementations. `builder` and `instrument` both select it. -derive = [] - # Standard library support std = [ "der/std", diff --git a/tightbeam/src/builder/frame.rs b/tightbeam/src/builder/frame.rs index 2e42dbd2..9fd50dee 100644 --- a/tightbeam/src/builder/frame.rs +++ b/tightbeam/src/builder/frame.rs @@ -963,7 +963,6 @@ mod tests { // V1 is the first version whose metadata carries integrity info. // `MetadataBuilder::build` rejects V0 with `message_integrity`. #[test] - #[cfg(feature = "derive")] fn test_compose_macro() -> Result<()> { let message = TestMessage::sample(None); let frame = compose! { @@ -1038,82 +1037,30 @@ mod tests { macro_rules! test_msg_struct { // BasicMessage: (false, false, false, false, V0) (false, false, false, false, V0) => { - #[cfg(feature = "derive")] #[derive($crate::Beamable, Clone, Debug, PartialEq, der::Sequence)] #[beam(min_version = "V0")] struct TestMsg { content: String, } - #[cfg(not(feature = "derive"))] - #[derive(Clone, Debug, PartialEq, der::Sequence)] - struct TestMsg { - content: String, - } - #[cfg(not(feature = "derive"))] - impl $crate::Message for TestMsg { - const MUST_BE_CONFIDENTIAL: bool = false; - const MUST_BE_NON_REPUDIABLE: bool = false; - const MUST_BE_COMPRESSED: bool = false; - const MUST_BE_PRIORITIZED: bool = false; - const MUST_HAVE_MESSAGE_INTEGRITY: bool = false; - const MUST_HAVE_FRAME_INTEGRITY: bool = false; - const MIN_VERSION: Version = Version::V0; - type Profile = $crate::crypto::profiles::TightbeamProfile; - } }; // ConfidentialMessage: (true, false, false, false, V1) (true, false, false, false, V1) => { - #[cfg(feature = "derive")] #[derive($crate::Beamable, Clone, Debug, PartialEq, der::Sequence)] #[beam(confidential, min_version = "V1")] struct TestMsg { content: String, } - #[cfg(not(feature = "derive"))] - #[derive(Clone, Debug, PartialEq, der::Sequence)] - struct TestMsg { - content: String, - } - #[cfg(not(feature = "derive"))] - impl $crate::Message for TestMsg { - const MUST_BE_CONFIDENTIAL: bool = true; - const MUST_BE_NON_REPUDIABLE: bool = false; - const MUST_BE_COMPRESSED: bool = false; - const MUST_BE_PRIORITIZED: bool = false; - const MUST_HAVE_MESSAGE_INTEGRITY: bool = false; - const MUST_HAVE_FRAME_INTEGRITY: bool = false; - const MIN_VERSION: Version = Version::V1; - type Profile = $crate::crypto::profiles::TightbeamProfile; - } }; // NonrepudiableMessage: (false, true, false, false, V1) (false, true, false, false, V1) => { - #[cfg(feature = "derive")] #[derive($crate::Beamable, Clone, Debug, PartialEq, der::Sequence)] #[beam(nonrepudiable, min_version = "V1")] struct TestMsg { content: String, } - #[cfg(not(feature = "derive"))] - #[derive(Clone, Debug, PartialEq, der::Sequence)] - struct TestMsg { - content: String, - } - #[cfg(not(feature = "derive"))] - impl $crate::Message for TestMsg { - const MUST_BE_CONFIDENTIAL: bool = false; - const MUST_BE_NON_REPUDIABLE: bool = true; - const MUST_BE_COMPRESSED: bool = false; - const MUST_BE_PRIORITIZED: bool = false; - const MUST_HAVE_MESSAGE_INTEGRITY: bool = false; - const MUST_HAVE_FRAME_INTEGRITY: bool = false; - const MIN_VERSION: Version = Version::V1; - type Profile = $crate::crypto::profiles::TightbeamProfile; - } }; // FullSecurityMessage: (true, true, true, true, V2) (true, true, true, true, V2) => { - #[cfg(feature = "derive")] #[derive($crate::Beamable, Clone, Debug, PartialEq, der::Sequence)] #[beam( confidential, @@ -1125,22 +1072,6 @@ mod tests { struct TestMsg { content: String, } - #[cfg(not(feature = "derive"))] - #[derive(Clone, Debug, PartialEq, der::Sequence)] - struct TestMsg { - content: String, - } - #[cfg(not(feature = "derive"))] - impl $crate::Message for TestMsg { - const MUST_BE_CONFIDENTIAL: bool = true; - const MUST_BE_NON_REPUDIABLE: bool = true; - const MUST_BE_COMPRESSED: bool = false; - const MUST_BE_PRIORITIZED: bool = false; - const MUST_HAVE_MESSAGE_INTEGRITY: bool = true; - const MUST_HAVE_FRAME_INTEGRITY: bool = true; - const MIN_VERSION: Version = Version::V2; - type Profile = $crate::crypto::profiles::TightbeamProfile; - } }; } diff --git a/tightbeam/src/colony/worker/mod.rs b/tightbeam/src/colony/worker/mod.rs index 79517611..2a38a9bf 100644 --- a/tightbeam/src/colony/worker/mod.rs +++ b/tightbeam/src/colony/worker/mod.rs @@ -56,14 +56,13 @@ pub struct WorkerRequest { pub trace: Arc, } -#[cfg_attr(feature = "derive", derive(Errorizable))] -#[derive(Debug)] +#[derive(Errorizable, Debug)] pub enum WorkerRelayError { - #[cfg_attr(feature = "derive", error("Worker queue closed"))] + #[error("Worker queue closed")] QueueClosed, - #[cfg_attr(feature = "derive", error("Worker response channel dropped"))] + #[error("Worker response channel dropped")] ResponseDropped, - #[cfg_attr(feature = "derive", error("Message rejected with status {:?}"))] + #[error("Message rejected with status {:?}")] Rejected(TransitStatus), } diff --git a/tightbeam/src/core.rs b/tightbeam/src/core.rs index 0c34a046..eeab15e1 100644 --- a/tightbeam/src/core.rs +++ b/tightbeam/src/core.rs @@ -429,7 +429,6 @@ mod tests { } => EncryptedContentInfo, } - #[cfg(feature = "derive")] #[derive(Beamable, Clone, Debug, PartialEq, der::Sequence)] #[beam(profile = 1)] struct NumericProfileMessage { @@ -437,7 +436,6 @@ mod tests { data: String, } - #[cfg(feature = "derive")] #[derive(Beamable, Clone, Debug, PartialEq, der::Sequence)] #[beam(profile(crate::crypto::profiles::TightbeamProfile))] struct TypeProfileMessage { @@ -445,14 +443,12 @@ mod tests { data: String, } - #[cfg(feature = "derive")] #[derive(Beamable, Clone, Debug, PartialEq, der::Sequence)] struct NoProfileMessage { id: u64, data: String, } - #[cfg(feature = "derive")] #[test] #[allow(clippy::assertions_on_constants)] fn test_profile_types() { diff --git a/tightbeam/src/crypto/profiles.rs b/tightbeam/src/crypto/profiles.rs index ee2b2f97..681cd439 100644 --- a/tightbeam/src/crypto/profiles.rs +++ b/tightbeam/src/crypto/profiles.rs @@ -56,7 +56,6 @@ use crate::der::oid::AssociatedOid; use crate::spki::AlgorithmIdentifierOwned; #[cfg(feature = "transport")] use crate::transport::handshake::HandshakeError; -#[cfg(feature = "derive")] use crate::Beamable; use crate::Errorizable; /// Macro to generate key wrapper implementations. @@ -124,8 +123,7 @@ impl AeadKeySize for crate::crypto::aead::Aes256GcmOid { /// /// Every field is `Option`: `None` uniformly means "algorithm not part of /// this profile" (feature disabled on the producing side). -#[derive(Clone, Copy, Debug, Eq, PartialEq, Hash, Sequence)] -#[cfg_attr(feature = "derive", derive(Beamable))] +#[derive(Clone, Copy, Debug, Eq, PartialEq, Hash, Sequence, Beamable)] pub struct SecurityProfileDesc { pub digest: Option, pub aead: Option, diff --git a/tightbeam/src/lib.rs b/tightbeam/src/lib.rs index 7a81c229..bedf3376 100644 --- a/tightbeam/src/lib.rs +++ b/tightbeam/src/lib.rs @@ -184,7 +184,6 @@ pub use tightbeam_derive::Errorizable; #[cfg(feature = "hex")] pub use hex_literal::hex; -#[cfg(feature = "derive")] pub use tightbeam_derive::{Beamable, Flaggable}; #[cfg(feature = "time")] pub use time; diff --git a/tightbeam/src/macros/cfg.rs b/tightbeam/src/macros/cfg.rs index a1727a89..d1e0b0ec 100644 --- a/tightbeam/src/macros/cfg.rs +++ b/tightbeam/src/macros/cfg.rs @@ -254,6 +254,7 @@ macro_rules! __tb_if_crypto { #[macro_export] #[doc(hidden)] macro_rules! __tb_if_digest { + (else { $($absent:tt)* }) => {}; ($($item:item)*) => { $($item)* }; } @@ -261,6 +262,7 @@ macro_rules! __tb_if_digest { #[macro_export] #[doc(hidden)] macro_rules! __tb_if_digest { + (else { $($absent:tt)* }) => { $($absent)* }; ($($item:item)*) => {}; } @@ -268,6 +270,7 @@ macro_rules! __tb_if_digest { #[macro_export] #[doc(hidden)] macro_rules! __tb_if_aead { + (else { $($absent:tt)* }) => {}; ($($item:item)*) => { $($item)* }; } @@ -275,6 +278,7 @@ macro_rules! __tb_if_aead { #[macro_export] #[doc(hidden)] macro_rules! __tb_if_aead { + (else { $($absent:tt)* }) => { $($absent)* }; ($($item:item)*) => {}; } @@ -282,6 +286,7 @@ macro_rules! __tb_if_aead { #[macro_export] #[doc(hidden)] macro_rules! __tb_if_signature { + (else { $($absent:tt)* }) => {}; ($($item:item)*) => { $($item)* }; } @@ -289,6 +294,23 @@ macro_rules! __tb_if_signature { #[macro_export] #[doc(hidden)] macro_rules! __tb_if_signature { + (else { $($absent:tt)* }) => { $($absent)* }; + ($($item:item)*) => {}; +} + +#[cfg(feature = "compress")] +#[macro_export] +#[doc(hidden)] +macro_rules! __tb_if_compress { + (else { $($absent:tt)* }) => {}; + ($($item:item)*) => { $($item)* }; +} + +#[cfg(not(feature = "compress"))] +#[macro_export] +#[doc(hidden)] +macro_rules! __tb_if_compress { + (else { $($absent:tt)* }) => { $($absent)* }; ($($item:item)*) => {}; } diff --git a/tightbeam/src/macros/server.rs b/tightbeam/src/macros/server.rs index 9b5ccb96..48459f46 100644 --- a/tightbeam/src/macros/server.rs +++ b/tightbeam/src/macros/server.rs @@ -15,20 +15,18 @@ use crate::Frame; #[cfg(feature = "tokio")] use crate::policy::TransitStatus; -#[cfg(feature = "tokio")] -use crate::transport::MessageCollector; -#[cfg(feature = "tokio")] -use crate::TightBeamError; - -#[cfg(all(feature = "tokio", feature = "x509"))] -use crate::transport::state::EncryptedProtocolState; - #[cfg(pooled_mux)] use crate::transport::multiplex::MuxAcceptor; #[cfg(pooled_mux)] use crate::transport::multiplex::{ReplySink, StreamBody, StreamRoute}; #[cfg(pooled_mux)] use crate::transport::serve::{serve_mux, CallContext, MuxService}; +#[cfg(all(feature = "tokio", feature = "x509"))] +use crate::transport::state::EncryptedProtocolState; +#[cfg(feature = "tokio")] +use crate::transport::MessageCollector; +#[cfg(feature = "tokio")] +use crate::TightBeamError; #[cfg(feature = "tokio")] use self::server_runtime::rt::{ErrorSender, OkSender}; @@ -666,7 +664,7 @@ macro_rules! __tightbeam_server_protocol_service_handle { macro_rules! __tightbeam_server_protocol_service_handle { ($protocol:path, $listener:expr, [$($policy_name:ident: [ $( $policy_expr:expr ),* $(,)? ]),* $(,)?], $error_tx:expr, $ok_tx:expr, $service:expr) => { compile_error!( - "server!(protocol ..., service: ...) requires the pooled multiplexing feature set (`tokio`, `x509`, `transport-policy`, `transport-multiplex`, and a handshake protocol)" + "server!(protocol ..., service: ...) requires the pooled multiplexing feature set that the `pooled_mux` alias in tightbeam's build.rs defines" ); }; } diff --git a/tightbeam/src/prelude.rs b/tightbeam/src/prelude.rs index 3fa22653..bf88ea36 100644 --- a/tightbeam/src/prelude.rs +++ b/tightbeam/src/prelude.rs @@ -15,8 +15,9 @@ // Multi-threading support #[cfg(feature = "std")] pub use crate::mpsc; + // ASN.1/DER support -pub use der::{Decode, Encode, Sequence}; +pub use crate::der::{Decode, Encode, Sequence}; // Core types pub use crate::asn1; @@ -25,6 +26,7 @@ pub use crate::flags; pub use crate::flags::FlagSet; pub use crate::matrix::{IntoMatrixDyn, Matrix, MatrixDyn, MatrixError, MatrixLike, MatrixResult}; pub use crate::utils; +pub use crate::Beamable; pub use crate::TightBeamError; pub use crate::{Frame, Message, Version}; @@ -32,28 +34,21 @@ pub use crate::{Frame, Message, Version}; pub use crate::builder::{FrameBuilder, TypeBuilder}; #[cfg(feature = "builder")] pub use crate::compose; -#[cfg(feature = "derive")] -pub use crate::Beamable; - #[cfg(feature = "tcp")] pub use crate::transport::tcp::TightBeamSocketAddr; /// Message collection and processing pub mod collect { - #[cfg(feature = "transport")] - pub use crate::transport::MessageCollector; - #[cfg(feature = "transport-policy")] pub use crate::transport::policy::{ self, CollectorGateConfig, EmitterGateConfig, PolicyConfig, RestartConfig, TimeoutConfig, }; - #[cfg(feature = "tcp")] pub use crate::transport::tcp; - #[cfg(all(feature = "tcp", feature = "tokio"))] pub use crate::transport::tcp::r#async::TokioListener; - #[cfg(feature = "tcp")] pub use crate::transport::tcp::sync::TcpListener; + #[cfg(feature = "transport")] + pub use crate::transport::MessageCollector; } diff --git a/tightbeam/src/testing/config.rs b/tightbeam/src/testing/config.rs index d089092c..1dd4e649 100644 --- a/tightbeam/src/testing/config.rs +++ b/tightbeam/src/testing/config.rs @@ -17,8 +17,6 @@ use crate::testing::result::ScenarioVerdict; use crate::testing::specs::{CspValidationResult, Layer, SpecViolation, TBSpec, Violations}; use crate::trace::ConsumedTrace; use crate::transport::error::TransportError; - -#[cfg(feature = "derive")] use crate::Errorizable; #[cfg(feature = "testing-fdr")] @@ -49,41 +47,17 @@ impl Expect { } /// Why [`ScenarioConfigBuilder::build`] refused a configuration. -#[derive(Clone, Copy, Debug, Eq, PartialEq)] -#[cfg_attr(feature = "derive", derive(Errorizable))] +#[derive(Clone, Copy, Debug, Eq, PartialEq, Errorizable)] pub enum ScenarioConfigError { /// Nothing this configuration names can reject a run. - #[cfg_attr( - feature = "derive", - error("no configured verifier can reject a run, so the scenario cannot fail") - )] + #[error("no configured verifier can reject a run, so the scenario cannot fail")] NoEffectiveVerifier, /// The expectation names a layer that cannot reject this configuration. - #[cfg_attr( - feature = "derive", - error("expected a violation from {0:?}, which cannot reject this configuration") - )] + #[error("expected a violation from {0:?}, which cannot reject this configuration")] ExpectViolationWithoutVerifier(Layer), } -#[cfg(not(feature = "derive"))] -impl core::fmt::Display for ScenarioConfigError { - fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { - match self { - Self::NoEffectiveVerifier => { - write!(f, "no configured verifier can reject a run, so the scenario cannot fail") - } - Self::ExpectViolationWithoutVerifier(layer) => { - write!(f, "expected a violation from {layer:?}, which cannot reject this configuration") - } - } - } -} - -#[cfg(not(feature = "derive"))] -impl std::error::Error for ScenarioConfigError {} - /// Unified configuration for tb_scenario! tests (zero-copy with Arc wrapping) #[derive(Clone)] pub struct ScenarioConfig { diff --git a/tightbeam/src/testing/macros/verification_spec.rs b/tightbeam/src/testing/macros/verification_spec.rs index 2ae955b4..22ca4a05 100644 --- a/tightbeam/src/testing/macros/verification_spec.rs +++ b/tightbeam/src/testing/macros/verification_spec.rs @@ -17,7 +17,6 @@ use crate::crypto::hash::{Digest, Sha3_256}; use crate::policy::TransitStatus; #[cfg(feature = "testing-timing")] use crate::testing::schedulability::{SchedulerType, TaskSet}; -#[cfg(feature = "derive")] use crate::Errorizable; // --------------------------------------------------------------------------- @@ -128,14 +127,13 @@ pub const fn versions_strictly_ascending(versions: &[(u16, u16, u16)]) -> bool { // --------------------------------------------------------------------------- /// Error type for spec building operations -#[derive(Debug)] -#[cfg_attr(feature = "derive", derive(Errorizable))] +#[derive(Debug, Errorizable)] pub enum SpecBuildError { - #[cfg_attr(feature = "derive", error("Duplicate label: {0}"))] + #[error("Duplicate label: {0}")] DuplicateLabel(Urn<'static>), - #[cfg_attr(feature = "derive", error("Unknown ordering label: {0}"))] + #[error("Unknown ordering label: {0}")] UnknownOrderingLabel(Urn<'static>), - #[cfg_attr(feature = "derive", error("Invalid range: {0}"))] + #[error("Invalid range: {0}")] InvalidRange(Urn<'static>), } diff --git a/tightbeam/src/testing/specs/error.rs b/tightbeam/src/testing/specs/error.rs index 8266e730..892d8389 100644 --- a/tightbeam/src/testing/specs/error.rs +++ b/tightbeam/src/testing/specs/error.rs @@ -12,7 +12,6 @@ use crate::trace::ExecutionMode; use crate::policy::TransitStatus; #[cfg(feature = "testing-timing")] use crate::testing::schedulability::{SchedulabilityError, SchedulabilityResult}; -#[cfg(feature = "derive")] use crate::Errorizable; /// Gate decision mismatch details @@ -47,42 +46,41 @@ pub struct EventCountMismatchDetail { } /// Spec violation error type -#[derive(Clone, Debug, PartialEq)] -#[cfg_attr(feature = "derive", derive(Errorizable))] +#[derive(Clone, Debug, PartialEq, Errorizable)] pub enum SpecViolation { /// The scenario body itself returned an error, carrying its rendering - #[cfg_attr(feature = "derive", error("Execution failed: {0}"))] + #[error("Execution failed: {0}")] ExecutionFailed(String), /// Response assertion mismatch - #[cfg_attr(feature = "derive", error("Response present but spec forbids it"))] + #[error("Response present but spec forbids it")] ResponseUnexpectedPresence, - #[cfg_attr(feature = "derive", error("Response absent but spec requires it"))] + #[error("Response absent but spec requires it")] ResponseUnexpectedAbsence, - #[cfg_attr(feature = "derive", error("Response validation failed"))] + #[error("Response validation failed")] ResponseValidationFailed, /// Execution mode mismatch - #[cfg_attr(feature = "derive", error("Execution mode mismatch: {0}"))] + #[error("Execution mode mismatch: {0}")] ModeMismatch(ReceivedExpectedError), /// Gate decision mismatch - #[cfg_attr(feature = "derive", error("Gate decision mismatch: {0:?}"))] + #[error("Gate decision mismatch: {0:?}")] GateDecisionMismatch(GateDecisionMismatch), /// Assertion contract violated - #[cfg_attr(feature = "derive", error("Assertion contract violated: {0:?}"))] + #[error("Assertion contract violated: {0:?}")] AssertionViolation(AssertionViolationDetail), /// Event ordering violation (instrumentation) - #[cfg_attr(feature = "derive", error("Event order violation: {0:?}"))] + #[error("Event order violation: {0:?}")] EventOrderViolation(EventOrderViolationDetail), /// Event count mismatch - #[cfg_attr(feature = "derive", error("Event count mismatch: {0:?}"))] + #[error("Event count mismatch: {0:?}")] EventCountMismatch(EventCountMismatchDetail), /// CSP process validation failed (Layer 2) - #[cfg_attr(feature = "derive", error("CSP process violation: {0:?}"))] + #[error("CSP process violation: {0:?}")] CspProcessViolation(Vec), /// Refinement checking rejected the scenario (Layer 3) /// /// The witness for each failed check is on the verdict itself, reachable /// through [`ScenarioVerdict::fdr`](crate::testing::ScenarioVerdict::fdr). - #[cfg_attr(feature = "derive", error("Refinement check failed"))] + #[error("Refinement check failed")] RefinementViolation, /// Refinement checking did not conclude (Layer 3) /// @@ -90,115 +88,22 @@ pub enum SpecViolation { /// refuted the run nor cleared it. The bounds are on the verdict itself, /// reachable through /// [`ScenarioVerdict::fdr`](crate::testing::ScenarioVerdict::fdr). - #[cfg_attr( - feature = "derive", - error("Refinement check did not conclude within its exploration bounds") - )] + #[error("Refinement check did not conclude within its exploration bounds")] RefinementInconclusive, /// A layer the scenario expected a violation from accepted the run - #[cfg_attr( - feature = "derive", - error("Expected a violation from {0:?}, which accepted the run") - )] + #[error("Expected a violation from {0:?}, which accepted the run")] ExpectationUnmet(Layer), /// Schedulability violation (analysis failed) #[cfg(feature = "testing-timing")] - #[cfg_attr(feature = "derive", error("Schedulability violation: {0:?}"))] + #[error("Schedulability violation: {0:?}")] SchedulabilityViolation(SchedulabilityResult), /// Schedulability analysis error (couldn't perform analysis) #[cfg(feature = "testing-timing")] - #[cfg_attr(feature = "derive", error("Schedulability analysis error: {0}"))] - #[cfg_attr(feature = "derive", from)] + #[error("Schedulability analysis error: {0}")] + #[from] SchedulabilityError(SchedulabilityError), } -#[cfg(not(feature = "derive"))] -impl std::fmt::Display for SpecViolation { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - match self { - Self::ExecutionFailed(rendering) => write!(f, "Execution failed: {rendering}"), - Self::ModeMismatch(err) => write!(f, "Execution mode mismatch: {err}"), - Self::ResponseUnexpectedPresence => write!(f, "Response present but spec forbids it"), - Self::ResponseUnexpectedAbsence => write!(f, "Response absent but spec requires it"), - Self::ResponseValidationFailed => write!(f, "Response validation failed"), - Self::GateDecisionMismatch(detail) => { - write!( - f, - "Gate decision mismatch: expected {:?}, got {:?}", - detail.expected, detail.actual - ) - } - Self::AssertionViolation(detail) => { - let tag_desc = if let Some(ref t) = detail.tags { - format!(" with tags {t:?}") - } else { - String::new() - }; - write!( - f, - "Assertion contract violated: {:?}{tag_desc} expected {}, found {}", - detail.label, detail.expected, detail.actual - ) - } - Self::EventOrderViolation(detail) => { - write!( - f, - "Event order violation: expected {:?} at position {}", - detail.expected_kind, detail.position - ) - } - Self::EventCountMismatch(detail) => { - write!( - f, - "Event count mismatch: {:?} expected {}, found {}", - detail.kind, detail.expected, detail.actual - ) - } - Self::CspProcessViolation(violations) => { - write!(f, "CSP process violation:")?; - for violation in violations { - write!(f, "\n - {violation}")?; - } - Ok(()) - } - Self::RefinementViolation => write!(f, "Refinement check failed"), - Self::RefinementInconclusive => { - write!(f, "Refinement check did not conclude within its exploration bounds") - } - Self::ExpectationUnmet(layer) => { - write!(f, "Expected a violation from {layer:?}, which accepted the run") - } - #[cfg(feature = "testing-timing")] - Self::SchedulabilityViolation(result) => { - use crate::testing::schedulability::SchedulerType; - let scheduler_name = match result.scheduler { - SchedulerType::RateMonotonic => "Rate Monotonic", - SchedulerType::EarliestDeadlineFirst => "Earliest Deadline First", - }; - write!( - f, - "Schedulability violation ({} scheduler): utilization {:.3} exceeds bound {:.3}", - scheduler_name, result.utilization, result.utilization_bound - )?; - if !result.violations.is_empty() { - write!(f, "\nViolations:")?; - for v in &result.violations { - write!(f, "\n - [{}] {}", v.task_id, v.message)?; - } - } - Ok(()) - } - #[cfg(feature = "testing-timing")] - Self::SchedulabilityError(error) => { - write!(f, "Schedulability analysis error: {}", error) - } - } - } -} - -#[cfg(not(feature = "derive"))] -impl std::error::Error for SpecViolation {} - /// Every layer that rejected one scenario. /// /// A value of this type exists only where at least one layer rejected the diff --git a/tightbeam/src/transport/client/mod.rs b/tightbeam/src/transport/client/mod.rs index 77f17048..18d77e67 100644 --- a/tightbeam/src/transport/client/mod.rs +++ b/tightbeam/src/transport/client/mod.rs @@ -5,7 +5,6 @@ use crate::transport::{MessageEmitter, Protocol, TransportResult}; #[cfg(feature = "builder")] pub mod builder; -#[cfg(feature = "derive")] pub mod macros; #[cfg(feature = "std")] pub mod pool; diff --git a/tightbeam/src/transport/envelopes.rs b/tightbeam/src/transport/envelopes.rs index 5dcddac9..e80e7a1c 100644 --- a/tightbeam/src/transport/envelopes.rs +++ b/tightbeam/src/transport/envelopes.rs @@ -18,10 +18,7 @@ use crate::der::{Choice, Decode, Encode, EncodeValue, Length, Reader, Result as use crate::policy::TransitStatus; use crate::transport::error::TransportError; -#[cfg(feature = "derive")] use crate::Beamable; -#[cfg(not(feature = "derive"))] -use crate::{Message, Version}; #[cfg(feature = "transport-multiplex")] mod multiplex { @@ -744,8 +741,7 @@ pub enum MuxEnvelope { /// Transport envelope wrapping all messages at the transport layer. /// This is transparent to users and handled internally. -#[cfg_attr(feature = "derive", derive(Beamable))] -#[derive(Choice, Clone, Debug, PartialEq)] +#[derive(Beamable, Choice, Clone, Debug, PartialEq)] pub enum TransportEnvelope { #[asn1(context_specific = "0", constructed = "true")] Request(RequestPackage), @@ -780,15 +776,6 @@ pub enum WireMode { Encrypted, } -#[cfg(not(feature = "derive"))] -impl Message for TransportEnvelope { - const MUST_BE_NON_REPUDIABLE: bool = false; - const MUST_BE_CONFIDENTIAL: bool = false; - const MUST_BE_COMPRESSED: bool = false; - const MUST_BE_PRIORITIZED: bool = false; - const MIN_VERSION: Version = Version::V0; -} - impl From for TransportEnvelope { fn from(pkg: ResponsePackage) -> Self { Self::Response(pkg) diff --git a/tightbeam/src/transport/handshake/negotiation.rs b/tightbeam/src/transport/handshake/negotiation.rs index 43168ee7..417be310 100644 --- a/tightbeam/src/transport/handshake/negotiation.rs +++ b/tightbeam/src/transport/handshake/negotiation.rs @@ -10,12 +10,16 @@ #[cfg(not(feature = "std"))] extern crate alloc; +#[cfg(not(feature = "std"))] +use alloc::boxed::Box; +#[cfg(not(feature = "std"))] +use alloc::vec::Vec; +#[cfg(feature = "std")] +use std::vec::Vec; use crate::constants::{ DEFAULT_MUX_CHUNK_SIZE, DEFAULT_MUX_CREDIT_UNIT, DEFAULT_MUX_STREAM_CREDIT, MAX_MUX_STREAM_CAP, }; -#[cfg(any(feature = "transport-cms", feature = "transport-ecies"))] -use crate::constants::{MAX_MUX_CHUNK_SIZE, MAX_MUX_SESSION_BUDGET, MAX_MUX_STREAM_CREDIT, MIN_MUX_CHUNK_SIZE}; use crate::crypto::profiles::SecurityProfileDesc; use crate::der::asn1::{ObjectIdentifier, OctetString}; use crate::der::Error as DerDecodeError; @@ -24,14 +28,9 @@ use crate::transport::handshake::receipt::SessionReceipt; use crate::utils::marker::{MaybeSend, MaybeSendFuture, MaybeSync}; use crate::Beamable; -#[cfg(not(feature = "std"))] -use alloc::boxed::Box; -#[cfg(not(feature = "std"))] -use alloc::vec::Vec; -#[cfg(feature = "std")] -use std::vec::Vec; +#[cfg(any(feature = "transport-cms", feature = "transport-ecies"))] +use crate::constants::{MAX_MUX_CHUNK_SIZE, MAX_MUX_SESSION_BUDGET, MAX_MUX_STREAM_CREDIT, MIN_MUX_CHUNK_SIZE}; -#[cfg(feature = "derive")] use crate::Errorizable; /// Maximum number of profiles accepted in a [`SecurityOffer`]. @@ -45,8 +44,7 @@ pub const MAX_OFFER_PROFILES: usize = 32; /// Advertises algorithm combinations the client supports. Preference /// order is first-most-preferred, but the server selects in *its* local /// order (peer offer ordering carries no weight). -#[derive(Clone, Debug, Eq, PartialEq)] -#[cfg_attr(feature = "derive", derive(Beamable, Sequence))] +#[derive(Clone, Debug, Eq, PartialEq, Beamable, Sequence)] pub struct SecurityOffer { /// Ordered list of security profile descriptors (preference: first is most preferred). pub profiles: Vec, @@ -69,8 +67,7 @@ impl SecurityOffer { /// /// Carries the profile selected from the client's [`SecurityOffer`] /// under local preference and any [`ProfileStrengthPolicy`]. -#[derive(Clone, Debug, Eq, PartialEq)] -#[cfg_attr(feature = "derive", derive(Beamable, Sequence))] +#[derive(Clone, Debug, Eq, PartialEq, Beamable, Sequence)] pub struct SecurityAccept { /// The selected security profile descriptor. pub profile: SecurityProfileDesc, @@ -92,8 +89,7 @@ impl SecurityAccept { /// /// Fixed per key epoch; only shrinks inside an epoch. Value semantics /// (free, fiat, or other) live outside the protocol. -#[derive(Clone, Copy, Debug, Eq, PartialEq)] -#[cfg_attr(feature = "derive", derive(Beamable, Sequence))] +#[derive(Clone, Copy, Debug, Eq, PartialEq, Beamable, Sequence)] pub struct MuxBudgets { /// Credits spendable on client-to-server data chunks. pub client_to_server: u64, @@ -136,8 +132,7 @@ impl MuxBudgets { /// - `requested_budgets` - metering request (`None` = unmetered). /// - `authorization` - opaque token for [`TransportAuthorizer`] (never /// parsed by TightBeam). -#[derive(Clone, Debug, Eq, PartialEq)] -#[cfg_attr(feature = "derive", derive(Beamable, Sequence))] +#[derive(Clone, Debug, Eq, PartialEq, Beamable, Sequence)] pub struct TransportOffer { /// Sender supports stream multiplexing. pub mux: bool, @@ -223,10 +218,8 @@ impl TransportOffer { /// # Additionally /// /// - `credit_unit` - wins for both directions. -/// - `granted_budgets` - metered terms (may be lower than requested per -/// direction; absent = unmetered). -#[derive(Clone, Copy, Debug, Eq, PartialEq)] -#[cfg_attr(feature = "derive", derive(Beamable, Sequence))] +/// - `granted_budgets` - metered terms. +#[derive(Clone, Copy, Debug, Eq, PartialEq, Beamable, Sequence)] pub struct TransportAccept { /// Sender supports stream multiplexing. pub mux: bool, diff --git a/tightbeam/src/transport/handshake/primitives/prekeys.rs b/tightbeam/src/transport/handshake/primitives/prekeys.rs index e7c69a1b..8414cb35 100644 --- a/tightbeam/src/transport/handshake/primitives/prekeys.rs +++ b/tightbeam/src/transport/handshake/primitives/prekeys.rs @@ -26,8 +26,7 @@ use crate::Beamable; /// - `onetime_prekey`: Optional single-use prekey (EC) /// - `pq_prekey`: Optional post-quantum KEM public key /// - `prekey_ids`: Identifiers for retrieving/referencing keys -#[derive(Sequence, Clone, Debug, PartialEq)] -#[cfg_attr(feature = "derive", derive(Beamable))] +#[derive(Sequence, Clone, Debug, PartialEq, Beamable)] pub struct PrekeyBundle { /// Identity public key (long-term) pub identity_key: SubjectPublicKeyInfoOwned, @@ -55,8 +54,7 @@ pub struct PrekeyBundle { /// /// Used to reference specific prekeys when constructing initial messages, /// and for tracking/rotating prekeys on the server. -#[derive(Sequence, Clone, Debug, PartialEq, Eq)] -#[cfg_attr(feature = "derive", derive(Beamable))] +#[derive(Sequence, Clone, Debug, PartialEq, Eq, Beamable)] pub struct PrekeyIdentifiers { /// Signed prekey ID pub signed_prekey_id: u32, @@ -83,8 +81,7 @@ pub struct PrekeyIdentifiers { /// - `used_prekeys`: Identifiers of which prekeys from bundle were used /// - `kem_ciphertext`: KEM encapsulation output (if using PQ prekey) /// - `encrypted_payload`: Initial message encrypted under derived session key -#[derive(Sequence, Clone, Debug, PartialEq)] -#[cfg_attr(feature = "derive", derive(Beamable))] +#[derive(Sequence, Clone, Debug, PartialEq, Beamable)] pub struct PrekeyInitialMessage { /// Sender's identity key pub sender_identity: SubjectPublicKeyInfoOwned, diff --git a/tightbeam/src/transport/handshake/receipt.rs b/tightbeam/src/transport/handshake/receipt.rs index a2f84d4c..e5968c07 100644 --- a/tightbeam/src/transport/handshake/receipt.rs +++ b/tightbeam/src/transport/handshake/receipt.rs @@ -114,8 +114,7 @@ use x509::*; /// - `ancillary` is the server's settlement challenge (unsigned /// transaction, invoice, or other opaque bytes). Public wire data, /// never a secret; never parsed by TightBeam. -#[derive(Clone, Debug, Eq, PartialEq)] -#[cfg_attr(feature = "derive", derive(Beamable, Sequence))] +#[derive(Clone, Debug, Eq, PartialEq, Beamable, Sequence)] pub struct SessionReceipt { /// Handshake transcript digest pinning the receipt to a session per /// [RFC 8017 ยง9.2](https://datatracker.ietf.org/doc/html/rfc8017#section-9.2). diff --git a/tightbeam/src/utils/urn/builders/urn.rs b/tightbeam/src/utils/urn/builders/urn.rs index 17986382..af23bf0b 100644 --- a/tightbeam/src/utils/urn/builders/urn.rs +++ b/tightbeam/src/utils/urn/builders/urn.rs @@ -221,7 +221,6 @@ mod tests { use super::*; use crate::utils::urn::builders::spec::Pattern; - #[cfg(feature = "derive")] crate::urn_spec! { /// Test URN spec for testing URN builder functionality TestUrnSpec, @@ -234,42 +233,6 @@ mod tests { nss_format: "{}:{}/{}" } - #[cfg(not(feature = "derive"))] - use crate::utils::urn::{UrnComponents, UrnSpec, UrnSpecBuilder}; - - #[cfg(not(feature = "derive"))] - struct TestUrnSpec; - - #[cfg(not(feature = "derive"))] - impl TestUrnSpec { - fn spec_builder() -> UrnSpecBuilder { - UrnSpecBuilder::from("test") - .field_required("category") - .field_const("category", "instrumentation") - .field_nss_separator("category", ":") - .field_required("type") - .field_oneof("type", &["trace", "event", "seed", "verdict"]) - .field_nss_separator("type", "/") - .field_required("id") - .field_pattern("id", Pattern::AlphaNumericHyphen) - .nss_format("{}:{}/{}") - } - } - - #[cfg(not(feature = "derive"))] - impl UrnSpec for TestUrnSpec { - const NID: &'static str = "test"; - - fn validate<'a>(components: &dyn UrnComponents<'a>) -> Result<(), UrnValidationError> { - Self::spec_builder().validate(components) - } - - fn build_nss<'a>(components: &dyn UrnComponents<'a>) -> Result, UrnValidationError> { - let nss = Self::spec_builder().build_nss(components)?; - Ok(nss.into()) - } - } - #[test] fn test_urn_builder_with_nss() -> Result<(), UrnValidationError> { // (nid, nss, expected_urn_string) diff --git a/tightbeam/src/utils/urn/specs/tightbeam.rs b/tightbeam/src/utils/urn/specs/tightbeam.rs index 28ef7d1f..6cfd9d73 100644 --- a/tightbeam/src/utils/urn/specs/tightbeam.rs +++ b/tightbeam/src/utils/urn/specs/tightbeam.rs @@ -8,18 +8,9 @@ extern crate alloc; #[cfg(not(feature = "std"))] use alloc::{borrow::Cow, string::String, vec::Vec}; -#[cfg(all(feature = "std", not(feature = "derive")))] -use std::borrow::Cow; - use crate::utils::urn::builders::spec::Pattern; use crate::utils::urn::UrnValidationError; -#[cfg(not(feature = "derive"))] -use crate::utils::urn::spec::UrnSpec; -#[cfg(not(feature = "derive"))] -use crate::utils::urn::UrnComponents; - -#[cfg(feature = "derive")] crate::urn_spec! { /// TightbeamUrnSpec URN specification /// @@ -42,83 +33,6 @@ crate::urn_spec! { } } -#[cfg(not(feature = "derive"))] -/// TightbeamUrnSpec URN specification -/// -/// Format: `urn:tightbeam:instrumentation:/` -pub struct TightbeamUrnSpec; - -#[cfg(not(feature = "derive"))] -impl UrnSpec for TightbeamUrnSpec { - const NID: &'static str = "tightbeam"; - - fn transform<'a>(components: &mut dyn UrnComponents<'a>) { - // Normalize resource_type to lowercase - for (key, value) in components.iter_mut() { - if key == "resource_type" { - *value = value.to_lowercase().into(); - } - } - } - - fn validate<'a>(components: &dyn UrnComponents<'a>) -> Result<(), UrnValidationError> { - // Validate category: required and must equal "instrumentation" - let category = components - .get_component("category") - .ok_or_else(|| UrnValidationError::RequiredFieldMissing("category"))?; - if category.as_ref() != "instrumentation" { - return Err(UrnValidationError::InvalidFormat { field: "category", pattern: None }); - } - - // Validate resource_type: required and must be one of ["trace", "event", "seed", "verdict"] - let resource_type = components - .get_component("resource_type") - .ok_or_else(|| UrnValidationError::RequiredFieldMissing("resource_type"))?; - let valid_types = &["trace", "event", "seed", "verdict"]; - if !valid_types.iter().any(|&t| resource_type.as_ref() == t) { - return Err(UrnValidationError::InvalidFormat { field: "resource_type", pattern: None }); - } - - // Validate resource_id: required and must match AlphaNumericHyphen pattern - let resource_id = components - .get_component("resource_id") - .ok_or_else(|| UrnValidationError::RequiredFieldMissing("resource_id"))?; - if !Pattern::AlphaNumericHyphen.matches(resource_id.as_ref()) { - return Err(UrnValidationError::InvalidFormat { - field: "resource_id", - pattern: Some(Pattern::AlphaNumericHyphen), - }); - } - - Ok(()) - } - - fn build_nss<'a>(components: &dyn UrnComponents<'a>) -> Result, UrnValidationError> { - let category = components - .get_component("category") - .ok_or_else(|| UrnValidationError::RequiredFieldMissing("category"))?; - let resource_type = components - .get_component("resource_type") - .ok_or_else(|| UrnValidationError::RequiredFieldMissing("resource_type"))?; - let resource_id = components - .get_component("resource_id") - .ok_or_else(|| UrnValidationError::RequiredFieldMissing("resource_id"))?; - - let mut result = "{}:{}/{}".to_string(); - if let Some(pos) = result.find("{}") { - result.replace_range(pos..pos + 2, category.as_ref()); - } - if let Some(pos) = result.find("{}") { - result.replace_range(pos..pos + 2, resource_type.as_ref()); - } - if let Some(pos) = result.find("{}") { - result.replace_range(pos..pos + 2, resource_id.as_ref()); - } - - Ok(result.into()) - } -} - #[cfg(test)] mod tests { use super::*; diff --git a/tightbeam/tests/protocol_core/frame_der.rs b/tightbeam/tests/protocol_core/frame_der.rs index b0b1b4cd..cfa396fc 100644 --- a/tightbeam/tests/protocol_core/frame_der.rs +++ b/tightbeam/tests/protocol_core/frame_der.rs @@ -14,8 +14,7 @@ pub(crate) const MATRIX_PRESENT: Urn<'static> = tightbeam::urn!("test", "event:f pub(crate) const ROUNDTRIP_OK: Urn<'static> = tightbeam::urn!("test", "event:frame-der/roundtrip-ok"); pub(crate) const VERSION: Urn<'static> = tightbeam::urn!("test", "event:frame-der/version"); -#[cfg_attr(feature = "derive", derive(tightbeam::Beamable))] -#[derive(Clone, Debug, PartialEq, Sequence)] +#[derive(tightbeam::Beamable, Clone, Debug, PartialEq, Sequence)] struct TestMessage { content: String, } @@ -26,16 +25,7 @@ impl AsRef<[u8]> for TestMessage { } } -#[cfg(not(feature = "derive"))] -impl tightbeam::Message for TestMessage { - const MUST_BE_NON_REPUDIABLE: bool = false; - const MUST_BE_CONFIDENTIAL: bool = false; - const MUST_BE_COMPRESSED: bool = false; - const MUST_BE_PRIORITIZED: bool = false; - const MIN_VERSION: asn1::Version = asn1::Version::V0; -} - -#[cfg_attr(feature = "derive", derive(tightbeam::Flaggable))] +#[derive(tightbeam::Flaggable)] #[repr(u8)] #[derive(Default, Debug, Clone, Copy, PartialEq, Eq)] enum FlagTestDevelopmentMode { @@ -44,21 +34,7 @@ enum FlagTestDevelopmentMode { IsMaintenanceMode = 2, } -#[cfg(not(feature = "derive"))] -impl From for u8 { - fn from(flag: FlagTestDevelopmentMode) -> u8 { - flag as u8 - } -} - -#[cfg(not(feature = "derive"))] -impl PartialEq for FlagTestDevelopmentMode { - fn eq(&self, other: &u8) -> bool { - (*self as u8) == *other - } -} - -#[cfg_attr(feature = "derive", derive(tightbeam::Flaggable))] +#[derive(tightbeam::Flaggable)] #[repr(u8)] #[derive(Default, Debug, Clone, Copy, PartialEq, Eq)] enum FlagTestDebugLevel { @@ -67,20 +43,6 @@ enum FlagTestDebugLevel { Basic = 1, } -#[cfg(not(feature = "derive"))] -impl From for u8 { - fn from(flag: FlagTestDebugLevel) -> u8 { - flag as u8 - } -} - -#[cfg(not(feature = "derive"))] -impl PartialEq for FlagTestDebugLevel { - fn eq(&self, other: &u8) -> bool { - (*self as u8) == *other - } -} - tightbeam::flagset!(TestFlagSet: FlagTestDevelopmentMode, FlagTestDebugLevel); fn build_v3_frame(message: &TestMessage) -> Result { diff --git a/tightbeam/tests/tightbeam_core/tests.rs b/tightbeam/tests/tightbeam_core/tests.rs index 54bfd088..7ff8da9d 100644 --- a/tightbeam/tests/tightbeam_core/tests.rs +++ b/tightbeam/tests/tightbeam_core/tests.rs @@ -32,8 +32,7 @@ pub(crate) const SIG_VALID: Urn<'static> = tightbeam::urn!("test", "event:tightb pub(crate) const VERSION: Urn<'static> = tightbeam::urn!("test", "event:tightbeam-core-tests/version"); /// Simple test message -#[cfg_attr(feature = "derive", derive(tightbeam::Beamable))] -#[derive(Clone, Debug, PartialEq, Sequence)] +#[derive(tightbeam::Beamable, Clone, Debug, PartialEq, Sequence)] struct TestMessage { content: String, } @@ -44,17 +43,8 @@ impl AsRef<[u8]> for TestMessage { } } -#[cfg(not(feature = "derive"))] -impl tightbeam::Message for TestMessage { - const MUST_BE_NON_REPUDIABLE: bool = false; - const MUST_BE_CONFIDENTIAL: bool = false; - const MUST_BE_COMPRESSED: bool = false; - const MUST_BE_PRIORITIZED: bool = false; - const MIN_VERSION: asn1::Version = asn1::Version::V0; -} - /// Custom test matrix for message metadata -#[cfg_attr(feature = "derive", derive(tightbeam::Flaggable))] +#[derive(tightbeam::Flaggable)] #[repr(u8)] #[derive(Default, Debug, Clone, Copy, PartialEq, Eq)] enum FlagTestDevelopmentMode { @@ -63,22 +53,8 @@ enum FlagTestDevelopmentMode { IsMaintenanceMode = 2, } -#[cfg(not(feature = "derive"))] -impl From for u8 { - fn from(flag: FlagTestDevelopmentMode) -> u8 { - flag as u8 - } -} - -#[cfg(not(feature = "derive"))] -impl PartialEq for FlagTestDevelopmentMode { - fn eq(&self, other: &u8) -> bool { - (*self as u8) == *other - } -} - /// Custom test matrix for message metadata -#[cfg_attr(feature = "derive", derive(tightbeam::Flaggable))] +#[derive(tightbeam::Flaggable)] #[repr(u8)] #[derive(Default, Debug, Clone, Copy, PartialEq, Eq)] enum FlagTestDebugLevel { @@ -87,20 +63,6 @@ enum FlagTestDebugLevel { Basic = 1, } -#[cfg(not(feature = "derive"))] -impl From for u8 { - fn from(flag: FlagTestDebugLevel) -> u8 { - flag as u8 - } -} - -#[cfg(not(feature = "derive"))] -impl PartialEq for FlagTestDebugLevel { - fn eq(&self, other: &u8) -> bool { - (*self as u8) == *other - } -} - // Define the flag set with automatic position assignment tightbeam::flagset!(TestFlagSet: FlagTestDevelopmentMode, FlagTestDebugLevel); diff --git a/tightbeam/tests/tightbeam_core/zero_queue.rs b/tightbeam/tests/tightbeam_core/zero_queue.rs index 328e29c5..9df42f6c 100644 --- a/tightbeam/tests/tightbeam_core/zero_queue.rs +++ b/tightbeam/tests/tightbeam_core/zero_queue.rs @@ -44,7 +44,7 @@ const WORKER_1_TAG: &str = "worker:1"; #[derive(Beamable, Sequence, Clone, Debug, PartialEq)] struct WorkOrder { - #[cfg_attr(feature = "derive", beam(bytes))] + #[beam(bytes)] payload: Vec, }