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 request_context;
124pub use request_context::*;
125
126mod server_middleware;
127pub use server_middleware::*;
128
129mod client_middleware;
130pub use client_middleware::*;
131
132mod observer;
133pub use observer::*;
134
135pub mod time;
136
137mod debug_snapshot;
138pub use debug_snapshot::*;
139
140mod calls;
141pub use calls::*;
142
143pub mod channel;
144pub use channel::*;
145
146mod shape_classify;
147pub use shape_classify::*;
148
149mod method_identity;
150pub use method_identity::*;
151
152pub mod schema;
153pub use schema::*;
154
155/// Pairs a value with the `SchemaRecvTracker` that was active when the value
156/// was received. Used to thread per-message schema context through the caller
157/// API without storing trackers on long-lived structs.
158pub struct WithTracker<T> {
159    pub value: T,
160    pub tracker: std::sync::Arc<SchemaRecvTracker>,
161}
162
163impl<T> std::fmt::Debug for WithTracker<T> {
164    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
165        f.debug_struct("WithTracker").finish_non_exhaustive()
166    }
167}
168
169impl<T> std::ops::Deref for WithTracker<T> {
170    type Target = T;
171    fn deref(&self) -> &T {
172        &self.value
173    }
174}
175
176impl<T> std::ops::DerefMut for WithTracker<T> {
177    fn deref_mut(&mut self) -> &mut T {
178        &mut self.value
179    }
180}