Skip to main content

ruvix_types/
queue.rs

1//! Queue IPC types.
2//!
3//! All inter-task communication in RuVix goes through queues. There are no
4//! synchronous IPC calls, no shared memory without explicit region grants,
5//! and no signals. Queues use io_uring-style ring buffers.
6
7use crate::handle::Handle;
8
9/// Handle to a kernel queue.
10#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
11#[repr(transparent)]
12pub struct QueueHandle(pub Handle);
13
14impl QueueHandle {
15    /// Creates a new queue handle.
16    #[inline]
17    #[must_use]
18    pub const fn new(id: u32, generation: u32) -> Self {
19        Self(Handle::new(id, generation))
20    }
21
22    /// Creates a null (invalid) queue handle.
23    #[inline]
24    #[must_use]
25    pub const fn null() -> Self {
26        Self(Handle::null())
27    }
28
29    /// Checks if this handle is null.
30    #[inline]
31    #[must_use]
32    pub const fn is_null(&self) -> bool {
33        self.0.is_null()
34    }
35
36    /// Returns the raw handle.
37    #[inline]
38    #[must_use]
39    pub const fn raw(&self) -> Handle {
40        self.0
41    }
42}
43
44impl Default for QueueHandle {
45    fn default() -> Self {
46        Self::null()
47    }
48}
49
50/// Message priority for queue operations.
51///
52/// Higher priority messages are delivered before lower priority messages
53/// when multiple messages are available.
54#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
55#[repr(u8)]
56pub enum MsgPriority {
57    /// Lowest priority. Background messages, bulk transfers.
58    Low = 0,
59
60    /// Normal priority. Default for most messages.
61    Normal = 1,
62
63    /// High priority. Time-sensitive messages.
64    High = 2,
65
66    /// Urgent priority. Control messages, error notifications.
67    Urgent = 3,
68}
69
70impl MsgPriority {
71    /// Converts from a raw u8 value.
72    #[inline]
73    #[must_use]
74    pub const fn from_u8(value: u8) -> Option<Self> {
75        match value {
76            0 => Some(Self::Low),
77            1 => Some(Self::Normal),
78            2 => Some(Self::High),
79            3 => Some(Self::Urgent),
80            _ => None,
81        }
82    }
83}
84
85impl Default for MsgPriority {
86    fn default() -> Self {
87        Self::Normal
88    }
89}
90
91/// Queue ring buffer configuration.
92///
93/// Used internally by the kernel to manage queue state.
94#[derive(Debug, Clone, Copy, PartialEq, Eq)]
95#[repr(C)]
96pub struct QueueConfig {
97    /// Ring buffer size (must be a power of 2).
98    pub ring_size: u32,
99
100    /// Maximum message size in bytes.
101    pub max_msg_size: u32,
102
103    /// RVF WIT type identifier for message validation.
104    /// Zero means no schema validation (raw bytes).
105    pub schema_id: u32,
106}
107
108impl QueueConfig {
109    /// Creates a new queue configuration.
110    #[inline]
111    #[must_use]
112    pub const fn new(ring_size: u32, max_msg_size: u32) -> Self {
113        Self {
114            ring_size,
115            max_msg_size,
116            schema_id: 0,
117        }
118    }
119
120    /// Creates a queue configuration with schema validation.
121    #[inline]
122    #[must_use]
123    pub const fn with_schema(ring_size: u32, max_msg_size: u32, schema_id: u32) -> Self {
124        Self {
125            ring_size,
126            max_msg_size,
127            schema_id,
128        }
129    }
130
131    /// Checks if the ring size is valid (power of 2).
132    #[inline]
133    #[must_use]
134    pub const fn is_valid(&self) -> bool {
135        self.ring_size > 0 && (self.ring_size & (self.ring_size - 1)) == 0
136    }
137}
138
139impl Default for QueueConfig {
140    fn default() -> Self {
141        Self {
142            ring_size: 64,
143            max_msg_size: 4096,
144            schema_id: 0,
145        }
146    }
147}
148
149#[cfg(test)]
150mod tests {
151    use super::*;
152
153    #[test]
154    fn test_queue_handle() {
155        let h = QueueHandle::new(7, 3);
156        assert!(!h.is_null());
157        assert_eq!(h.raw().id, 7);
158    }
159
160    #[test]
161    fn test_msg_priority_ordering() {
162        assert!(MsgPriority::Low < MsgPriority::Normal);
163        assert!(MsgPriority::Normal < MsgPriority::High);
164        assert!(MsgPriority::High < MsgPriority::Urgent);
165    }
166
167    #[test]
168    fn test_queue_config_valid() {
169        let config = QueueConfig::new(64, 4096);
170        assert!(config.is_valid());
171
172        let invalid = QueueConfig::new(63, 4096);
173        assert!(!invalid.is_valid());
174    }
175}