Skip to main content

vox_types/
lib.rs

1/// Debug logging macro — enabled by setting VOX_DLOG=1 environment variable.
2#[macro_export]
3macro_rules! dlog {
4    ($($arg:tt)*) => {
5        {
6            use ::std::sync::atomic::{AtomicU8, Ordering};
7            static ENABLED: AtomicU8 = AtomicU8::new(2); // 2 = uninitialized
8            let enabled = match ENABLED.load(Ordering::Relaxed) {
9                0 => false,
10                1 => true,
11                _ => {
12                    let val = ::std::env::var("VOX_DLOG").is_ok_and(|v| v == "1");
13                    ENABLED.store(val as u8, Ordering::Relaxed);
14                    val
15                }
16            };
17            if enabled {
18                eprintln!($($arg)*);
19            }
20        }
21    };
22}
23
24macro_rules! declare_id {
25    ($(#[$meta:meta])* $name:ident, $inner:ty) => {
26        $(#[$meta])*
27        #[derive(Facet, PartialEq, Eq, PartialOrd, Ord, Hash, Debug, Clone, Copy)]
28        #[repr(transparent)]
29        #[facet(transparent)]
30        pub struct $name(pub $inner);
31
32        impl ::std::fmt::Display for $name {
33            fn fmt(&self, f: &mut ::std::fmt::Formatter<'_>) -> ::std::fmt::Result {
34                write!(f, "{}", self.0)
35            }
36        }
37
38        impl $name {
39            /// Returns `true` if this ID has the given parity (even or odd).
40            pub fn has_parity(self, parity: crate::Parity) -> bool {
41                match parity {
42                    crate::Parity::Even => self.0.is_multiple_of(2),
43                    crate::Parity::Odd => !self.0.is_multiple_of(2),
44                }
45            }
46        }
47
48        impl crate::IdType for $name {
49            fn from_raw(raw: u64) -> Self {
50                Self(raw as $inner)
51            }
52        }
53
54    };
55}
56
57/// Trait implemented by all `declare_id!` types, enabling generic ID allocation.
58pub trait IdType: Copy {
59    fn from_raw(raw: u64) -> Self;
60}
61
62/// Allocates IDs with a given parity (odd or even), stepping by 2.
63///
64/// Odd parity: 1, 3, 5, 7, ...
65/// Even parity: 2, 4, 6, 8, ...
66// r[impl rpc.request.id-allocation]
67pub struct IdAllocator<T: IdType> {
68    next: u64,
69    _phantom: std::marker::PhantomData<T>,
70}
71
72impl<T: IdType> IdAllocator<T> {
73    /// Create a new allocator for the given parity.
74    pub fn new(parity: Parity) -> Self {
75        let next = match parity {
76            Parity::Odd => 1,
77            Parity::Even => 2,
78        };
79        Self {
80            next,
81            _phantom: std::marker::PhantomData,
82        }
83    }
84
85    /// Allocate the next ID.
86    pub fn alloc(&mut self) -> T {
87        let id = T::from_raw(self.next);
88        self.next += 2;
89        id
90    }
91}
92
93mod vox_error;
94pub use vox_error::*;
95
96mod services;
97pub use services::*;
98
99mod requests;
100pub use requests::*;
101
102mod message;
103pub use message::*;
104
105mod handshake;
106pub use handshake::*;
107
108mod selfref;
109pub use selfref::*;
110
111mod link;
112pub use link::*;
113
114mod conduit;
115pub use conduit::*;
116
117mod metadata;
118pub use metadata::*;
119
120mod retry_support;
121pub use retry_support::*;
122
123mod session_resume_support;
124pub use session_resume_support::*;
125
126mod request_context;
127pub use request_context::*;
128
129mod server_middleware;
130pub use server_middleware::*;
131
132mod client_middleware;
133pub use client_middleware::*;
134
135mod calls;
136pub use calls::*;
137
138pub mod channel;
139pub use channel::*;
140
141mod shape_classify;
142pub use shape_classify::*;
143
144mod method_identity;
145pub use method_identity::*;
146
147pub mod schema;
148pub use schema::*;
149
150/// Pairs a value with the `SchemaRecvTracker` that was active when the value
151/// was received. Used to thread per-message schema context through the caller
152/// API without storing trackers on long-lived structs.
153pub struct WithTracker<T> {
154    pub value: T,
155    pub tracker: std::sync::Arc<SchemaRecvTracker>,
156}
157
158impl<T> std::fmt::Debug for WithTracker<T> {
159    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
160        f.debug_struct("WithTracker").finish_non_exhaustive()
161    }
162}
163
164impl<T> std::ops::Deref for WithTracker<T> {
165    type Target = T;
166    fn deref(&self) -> &T {
167        &self.value
168    }
169}
170
171impl<T> std::ops::DerefMut for WithTracker<T> {
172    fn deref_mut(&mut self) -> &mut T {
173        &mut self.value
174    }
175}