Skip to main content

osal_rs/freertos/
queue.rs

1/***************************************************************************
2 *
3 * osal-rs
4 * Copyright (C) 2026 Antonio Salsi <passy.linux@zresa.it>
5 *
6 * This program is free software: you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation, either version 3 of the License
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
17 *
18 ***************************************************************************/
19
20//! Queue-based inter-thread communication for FreeRTOS.
21//!
22//! This module provides FIFO queue primitives for safe message passing between threads
23//! and interrupt service routines. Supports both byte-based and typed queues.
24
25use core::ffi::c_void;
26use core::fmt::{Debug, Display};
27use core::marker::PhantomData;
28use core::ops::Deref;
29
30use alloc::vec::Vec;
31
32use super::ffi::{QueueHandle, pdFALSE, vQueueDelete, xQueueCreateCountingSemaphore, xQueueReceive, xQueueReceiveFromISR};
33use super::types::{BaseType, UBaseType, TickType};
34use super::system::System;
35use crate::traits::{ToTick, QueueFn, SystemFn, QueueStreamedFn, BytesHasLen};
36#[cfg(not(feature = "serde"))]
37use crate::traits::{Serialize, Deserialize};
38
39#[cfg(feature = "serde")]
40use osal_rs_serde::{Serialize, Deserialize, to_bytes};
41
42pub trait StructSerde : Serialize + BytesHasLen + Deserialize {}
43
44use crate::utils::{Result, Error};
45use crate::{xQueueSendToBack, xQueueSendToBackFromISR};
46
47
48/// A FIFO queue for byte-based message passing.
49///
50/// Provides a thread-safe queue implementation for sending and receiving
51/// raw byte slices between threads. Supports both blocking and ISR-safe operations.
52///
53/// # Examples
54///
55/// ## Basic queue usage
56///
57/// ```ignore
58/// use osal_rs::os::{Queue, QueueFn};
59/// use core::time::Duration;
60/// 
61/// // Create a queue with 10 slots, each 32 bytes
62/// let queue = Queue::new(10, 32).unwrap();
63/// 
64/// // Send data
65/// let data = [1u8, 2, 3, 4];
66/// queue.post_with_to_tick(&data, Duration::from_millis(100)).unwrap();
67/// 
68/// // Receive data
69/// let mut buffer = [0u8; 4];
70/// queue.fetch_with_to_tick(&mut buffer, Duration::from_millis(100)).unwrap();
71/// assert_eq!(buffer, [1, 2, 3, 4]);
72/// ```
73///
74/// ## Producer-consumer pattern
75///
76/// ```ignore
77/// use osal_rs::os::{Queue, QueueFn, Thread};
78/// use alloc::sync::Arc;
79/// use core::time::Duration;
80/// 
81/// let queue = Arc::new(Queue::new(5, 4).unwrap());
82/// let queue_clone = queue.clone();
83/// 
84/// // Consumer thread
85/// let consumer = Thread::new("consumer", 2048, 5, move || {
86///     let mut buffer = [0u8; 4];
87///     loop {
88///         if queue_clone.fetch(&mut buffer, 1000).is_ok() {
89///             println!("Received: {:?}", buffer);
90///         }
91///     }
92/// }).unwrap();
93/// 
94/// consumer.start().unwrap();
95/// 
96/// // Producer
97/// let data = [0xAA, 0xBB, 0xCC, 0xDD];
98/// queue.post(&data, 1000).unwrap();
99/// ```
100pub struct Queue (QueueHandle);
101
102unsafe impl Send for Queue {}
103unsafe impl Sync for Queue {}
104
105impl Queue {
106    /// Creates a new queue.
107    ///
108    /// # Parameters
109    ///
110    /// * `size` - Maximum number of messages the queue can hold
111    /// * `message_size` - Size in bytes of each message
112    ///
113    /// # Returns
114    ///
115    /// * `Ok(Self)` - Successfully created queue
116    /// * `Err(Error)` - Creation failed (insufficient memory, etc.)
117    ///
118    /// # Examples
119    ///
120    /// ```ignore
121    /// use osal_rs::os::{Queue, QueueFn};
122    /// 
123    /// // Queue for 5 messages of 16 bytes each
124    /// let queue = Queue::new(5, 16).unwrap();
125    /// ```
126    pub fn new (size: UBaseType, message_size: UBaseType) -> Result<Self> {
127        let handle = unsafe { xQueueCreateCountingSemaphore(size, message_size) };
128        if handle.is_null() {
129            Err(Error::OutOfMemory)
130        } else {
131            Ok(Self (handle))
132        }
133    }
134
135    /// Receives data from the queue with a convertible timeout.
136    /// 
137    /// This is a convenience method that accepts any type implementing `ToTick`
138    /// (like `Duration`) and converts it to ticks before calling `fetch()`.
139    /// 
140    /// # Arguments
141    /// 
142    /// * `buffer` - Mutable slice to receive data into
143    /// * `time` - Timeout value (e.g., `Duration::from_millis(100)`)
144    /// 
145    /// # Returns
146    /// 
147    /// * `Ok(())` - Data successfully received
148    /// * `Err(Error::Timeout)` - No data available within timeout
149    /// 
150    /// # Examples
151    /// 
152    /// ```ignore
153    /// use osal_rs::os::{Queue, QueueFn};
154    /// use core::time::Duration;
155    /// 
156    /// let queue = Queue::new(5, 16).unwrap();
157    /// let mut buffer = [0u8; 16];
158    /// queue.fetch_with_to_tick(&mut buffer, Duration::from_millis(100))?;
159    /// ```
160    #[inline]
161    pub fn fetch_with_to_tick(&self, buffer: &mut [u8], time: impl ToTick) -> Result<()> {
162        self.fetch(buffer, time.to_ticks())
163    }
164
165    /// Sends data to the queue with a convertible timeout.
166    /// 
167    /// This is a convenience method that accepts any type implementing `ToTick`
168    /// (like `Duration`) and converts it to ticks before calling `post()`.
169    /// 
170    /// # Arguments
171    /// 
172    /// * `item` - Slice of data to send
173    /// * `time` - Timeout value (e.g., `Duration::from_millis(100)`)
174    /// 
175    /// # Returns
176    /// 
177    /// * `Ok(())` - Data successfully sent
178    /// * `Err(Error::Timeout)` - Queue full, could not send within timeout
179    /// 
180    /// # Examples
181    /// 
182    /// ```ignore
183    /// use osal_rs::os::{Queue, QueueFn};
184    /// use core::time::Duration;
185    /// 
186    /// let queue = Queue::new(5, 16).unwrap();
187    /// let data = [1u8, 2, 3, 4];
188    /// queue.post_with_to_tick(&data, Duration::from_millis(100))?;
189    /// ```
190    #[inline]
191    pub fn post_with_to_tick(&self, item: &[u8], time: impl ToTick) -> Result<()> {
192        self.post(item, time.to_ticks())
193    }
194}
195
196impl QueueFn for Queue {
197
198    /// Receives data from the queue, blocking until data is available or timeout.
199    /// 
200    /// This function blocks the calling thread until data is available or the
201    /// specified timeout expires.
202    /// 
203    /// # Arguments
204    /// 
205    /// * `buffer` - Mutable byte slice to receive data into
206    /// * `time` - Timeout in system ticks (0 = no wait, MAX = wait forever)
207    /// 
208    /// # Returns
209    /// 
210    /// * `Ok(())` - Data successfully received into buffer
211    /// * `Err(Error::Timeout)` - No data available within timeout period
212    /// 
213    /// # Examples
214    /// 
215    /// ```ignore
216    /// use osal_rs::os::{Queue, QueueFn};
217    /// 
218    /// let queue = Queue::new(5, 16).unwrap();
219    /// let mut buffer = [0u8; 16];
220    /// 
221    /// // Wait up to 1000 ticks for data
222    /// match queue.fetch(&mut buffer, 1000) {
223    ///     Ok(()) => println!("Received data: {:?}", buffer),
224    ///     Err(_) => println!("Timeout"),
225    /// }
226    /// ```
227    fn fetch(&self, buffer: &mut [u8], time: TickType) -> Result<()> {
228        let ret = unsafe {
229            xQueueReceive(
230                self.0,
231                buffer.as_mut_ptr() as *mut c_void,
232                time,
233            )
234        };
235        if ret == 0 {
236            Err(Error::Timeout)
237        } else {
238            Ok(())
239        }
240    }
241
242    /// Receives data from the queue in an interrupt service routine (ISR).
243    /// 
244    /// This is the ISR-safe version of `fetch()`. It does not block and will
245    /// trigger a context switch if a higher priority task is woken.
246    /// 
247    /// # Arguments
248    /// 
249    /// * `buffer` - Mutable byte slice to receive data into
250    /// 
251    /// # Returns
252    /// 
253    /// * `Ok(())` - Data successfully received
254    /// * `Err(Error::Timeout)` - Queue is empty
255    /// 
256    /// # Safety
257    /// 
258    /// Must only be called from ISR context.
259    /// 
260    /// # Examples
261    /// 
262    /// ```ignore
263    /// // In interrupt handler
264    /// use osal_rs::os::{Queue, QueueFn};
265    /// 
266    /// fn irq_handler(queue: &Queue) {
267    ///     let mut buffer = [0u8; 16];
268    ///     if queue.fetch_from_isr(&mut buffer).is_ok() {
269    ///         // Process received data
270    ///     }
271    /// }
272    /// ```
273    fn fetch_from_isr(&self, buffer: &mut [u8]) -> Result<()> {
274
275        let mut task_woken_by_receive: BaseType = pdFALSE;
276
277        let ret = unsafe {
278            xQueueReceiveFromISR(
279                self.0,
280                buffer.as_mut_ptr() as *mut c_void,
281                &mut task_woken_by_receive
282            )
283        };
284        if ret == 0 {
285            Err(Error::Timeout)
286        } else {
287
288            System::yield_from_isr(task_woken_by_receive);
289            
290            Ok(())
291        }
292    }
293
294    /// Sends data to the back of the queue, blocking until space is available.
295    /// 
296    /// This function blocks the calling thread until space becomes available
297    /// or the timeout expires.
298    /// 
299    /// # Arguments
300    /// 
301    /// * `item` - Byte slice to send
302    /// * `time` - Timeout in system ticks (0 = no wait, MAX = wait forever)
303    /// 
304    /// # Returns
305    /// 
306    /// * `Ok(())` - Data successfully sent
307    /// * `Err(Error::Timeout)` - Queue full, could not send within timeout
308    /// 
309    /// # Examples
310    /// 
311    /// ```ignore
312    /// use osal_rs::os::{Queue, QueueFn};
313    /// 
314    /// let queue = Queue::new(5, 16).unwrap();
315    /// let data = [0xAA, 0xBB, 0xCC, 0xDD];
316    /// 
317    /// // Wait up to 1000 ticks to send
318    /// queue.post(&data, 1000)?;
319    /// ```
320    fn post(&self, item: &[u8], time: TickType) -> Result<()> {
321        let ret = xQueueSendToBack!(
322                            self.0,
323                            item.as_ptr() as *const c_void,
324                            time
325                        );
326        
327        if ret == 0 {
328            Err(Error::Timeout)
329        } else {
330            Ok(())
331        }
332    }
333
334    /// Sends data to the queue from an interrupt service routine (ISR).
335    /// 
336    /// This is the ISR-safe version of `post()`. It does not block and will
337    /// trigger a context switch if a higher priority task is woken.
338    /// 
339    /// # Arguments
340    /// 
341    /// * `item` - Byte slice to send
342    /// 
343    /// # Returns
344    /// 
345    /// * `Ok(())` - Data successfully sent
346    /// * `Err(Error::Timeout)` - Queue is full
347    /// 
348    /// # Safety
349    /// 
350    /// Must only be called from ISR context.
351    /// 
352    /// # Examples
353    /// 
354    /// ```ignore
355    /// // In interrupt handler
356    /// use osal_rs::os::{Queue, QueueFn};
357    /// 
358    /// fn irq_handler(queue: &Queue) {
359    ///     let data = [0x01, 0x02, 0x03];
360    ///     queue.post_from_isr(&data).ok();
361    /// }
362    /// ```
363    fn post_from_isr(&self, item: &[u8]) -> Result<()> {
364
365        let mut task_woken_by_receive: BaseType = pdFALSE;
366
367        let ret = xQueueSendToBackFromISR!(
368                            self.0,
369                            item.as_ptr() as *const c_void,
370                            &mut task_woken_by_receive
371                        );
372        
373        if ret == 0 {
374            Err(Error::Timeout)
375        } else {
376            System::yield_from_isr(task_woken_by_receive);
377
378            Ok(())
379        }
380    }
381
382    /// Deletes the queue and frees its resources.
383    /// 
384    /// This function destroys the queue and releases any memory allocated for it.
385    /// After calling this, the queue should not be used. The handle is set to null.
386    /// 
387    /// # Safety
388    /// 
389    /// Ensure no threads are waiting on this queue before deleting it.
390    /// 
391    /// # Examples
392    /// 
393    /// ```ignore
394    /// use osal_rs::os::{Queue, QueueFn};
395    /// 
396    /// let mut queue = Queue::new(5, 16).unwrap();
397    /// // Use the queue...
398    /// queue.delete();
399    /// ```
400    fn delete(&mut self) {
401        unsafe {
402            vQueueDelete(self.0);
403            self.0 = core::ptr::null_mut();
404        }
405    }
406}
407
408/// Automatically deletes the queue when it goes out of scope.
409/// 
410/// This ensures proper cleanup of FreeRTOS resources.
411impl Drop for Queue {
412    fn drop(&mut self) {
413        if self.0.is_null() {
414            return;
415        }
416        self.delete();
417    }
418}
419
420/// Allows dereferencing to the underlying FreeRTOS queue handle.
421impl Deref for Queue {
422    type Target = QueueHandle;
423
424    fn deref(&self) -> &Self::Target {
425        &self.0
426    }
427}
428
429/// Formats the queue for debugging purposes.
430impl Debug for Queue {
431    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
432        f.debug_struct("Queue")
433            .field("handle", &self.0)
434            .finish()
435    }
436}
437
438/// Formats the queue for display purposes.
439impl Display for Queue {
440    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
441        write!(f, "Queue {{ handle: {:?} }}", self.0)
442    }
443}
444
445/// A type-safe FIFO queue for message passing.
446///
447/// Unlike [`Queue`], which works with raw byte slices, `QueueStreamed` provides
448/// a type-safe interface for sending and receiving structured data. The type must
449/// implement serialization traits.
450///
451/// # Type Parameters
452///
453/// * `T` - The message type. Must implement `ToBytes`, `BytesHasLen`, and `FromBytes`
454///
455/// # Examples
456///
457/// ## Basic typed queue usage
458///
459/// ```ignore
460/// use osal_rs::os::{QueueStreamed, QueueStreamedFn};
461/// use core::time::Duration;
462/// 
463/// #[derive(Debug, Clone, Copy)]
464/// struct Message {
465///     id: u32,
466///     value: i16,
467/// }
468/// 
469/// // Assuming Message implements the required traits
470/// let queue: QueueStreamed<Message> = QueueStreamed::new(10, size_of::<Message>()).unwrap();
471/// 
472/// // Send a message
473/// let msg = Message { id: 1, value: 42 };
474/// queue.post_with_to_tick(&msg, Duration::from_millis(100)).unwrap();
475/// 
476/// // Receive a message
477/// let mut received = Message { id: 0, value: 0 };
478/// queue.fetch_with_to_tick(&mut received, Duration::from_millis(100)).unwrap();
479/// assert_eq!(received.id, 1);
480/// assert_eq!(received.value, 42);
481/// ```
482///
483/// ## Command queue pattern
484///
485/// ```ignore
486/// use osal_rs::os::{QueueStreamed, Thread};
487/// use alloc::sync::Arc;
488/// 
489/// enum Command {
490///     Start,
491///     Stop,
492///     SetValue(u32),
493/// }
494/// 
495/// let cmd_queue = Arc::new(QueueStreamed::<Command>::new(10, 8).unwrap());
496/// let queue_clone = cmd_queue.clone();
497/// 
498/// let handler = Thread::new("handler", 2048, 5, move || {
499///     loop {
500///         let mut cmd = Command::Stop;
501///         if queue_clone.fetch(&mut cmd, 1000).is_ok() {
502///             match cmd {
503///                 Command::Start => { /* start operation */ },
504///                 Command::Stop => { /* stop operation */ },
505///                 Command::SetValue(val) => { /* set value */ },
506///             }
507///         }
508///     }
509/// }).unwrap();
510/// ```
511pub struct QueueStreamed<T: StructSerde> (Queue, PhantomData<T>);
512
513unsafe impl<T: StructSerde> Send for QueueStreamed<T> {}
514unsafe impl<T: StructSerde> Sync for QueueStreamed<T> {}
515
516impl<T> QueueStreamed<T> 
517where 
518    T: StructSerde {
519    /// Creates a new type-safe queue.
520    ///
521    /// # Parameters
522    ///
523    /// * `size` - Maximum number of messages
524    /// * `message_size` - Size of each message (typically `size_of::<T>()`)
525    ///
526    /// # Returns
527    ///
528    /// * `Ok(Self)` - Successfully created queue
529    /// * `Err(Error)` - Creation failed
530    #[inline]
531    pub fn new (size: UBaseType, message_size: UBaseType) -> Result<Self> {
532        Ok(Self (Queue::new(size, message_size)?, PhantomData))
533    }
534
535    /// Receives a typed message with a convertible timeout.
536    /// 
537    /// This is a convenience method that accepts any type implementing `ToTick`.
538    /// 
539    /// # Arguments
540    /// 
541    /// * `buffer` - Mutable reference to receive the message into
542    /// * `time` - Timeout value (e.g., `Duration::from_millis(100)`)
543    /// 
544    /// # Returns
545    /// 
546    /// * `Ok(())` - Message successfully received and deserialized
547    /// * `Err(Error)` - Timeout or deserialization error
548    /// 
549    /// # Examples
550    /// 
551    /// ```ignore
552    /// use osal_rs::os::QueueStreamed;
553    /// use core::time::Duration;
554    /// 
555    /// let queue: QueueStreamed<MyMessage> = QueueStreamed::new(5, size_of::<MyMessage>()).unwrap();
556    /// let mut msg = MyMessage::default();
557    /// queue.fetch_with_to_tick(&mut msg, Duration::from_millis(100))?;
558    /// ```
559    #[inline]
560    fn fetch_with_to_tick(&self, buffer: &mut T, time: impl ToTick) -> Result<()> {
561        self.fetch(buffer, time.to_ticks())
562    }
563
564    /// Sends a typed message with a convertible timeout.
565    /// 
566    /// This is a convenience method that accepts any type implementing `ToTick`.
567    /// 
568    /// # Arguments
569    /// 
570    /// * `item` - Reference to the message to send
571    /// * `time` - Timeout value (e.g., `Duration::from_millis(100)`)
572    /// 
573    /// # Returns
574    /// 
575    /// * `Ok(())` - Message successfully serialized and sent
576    /// * `Err(Error)` - Timeout or serialization error
577    /// 
578    /// # Examples
579    /// 
580    /// ```ignore
581    /// use osal_rs::os::QueueStreamed;
582    /// use core::time::Duration;
583    /// 
584    /// let queue: QueueStreamed<MyMessage> = QueueStreamed::new(5, size_of::<MyMessage>()).unwrap();
585    /// let msg = MyMessage { id: 1, value: 42 };
586    /// queue.post_with_to_tick(&msg, Duration::from_millis(100))?;
587    /// ```
588    #[inline]
589    fn post_with_to_tick(&self, item: &T, time: impl ToTick) -> Result<()> {
590        self.post(item, time.to_ticks())
591    }
592}
593
594#[cfg(not(feature = "serde"))]
595impl<T> QueueStreamedFn<T> for QueueStreamed<T> 
596where 
597    T: StructSerde {
598
599    /// Receives a typed message from the queue (without serde feature).
600    /// 
601    /// Deserializes the message from bytes using the custom serialization traits.
602    /// 
603    /// # Arguments
604    /// 
605    /// * `buffer` - Mutable reference to receive the deserialized message
606    /// * `time` - Timeout in system ticks
607    /// 
608    /// # Returns
609    /// 
610    /// * `Ok(())` - Message successfully received and deserialized
611    /// * `Err(Error::Timeout)` - Queue empty or timeout
612    /// * `Err(Error)` - Deserialization error
613    fn fetch(&self, buffer: &mut T, time: TickType) -> Result<()> {
614        let mut buf_bytes = Vec::with_capacity(buffer.len());         
615
616        if let Ok(()) = self.0.fetch(&mut buf_bytes, time) {
617            *buffer = T::from_bytes(&buf_bytes)?;
618            Ok(())
619        } else {
620            Err(Error::Timeout)
621        }
622    }
623
624    /// Receives a typed message from ISR context (without serde feature).
625    /// 
626    /// ISR-safe version that does not block. Deserializes the message from bytes.
627    /// 
628    /// # Arguments
629    /// 
630    /// * `buffer` - Mutable reference to receive the deserialized message
631    /// 
632    /// # Returns
633    /// 
634    /// * `Ok(())` - Message successfully received and deserialized
635    /// * `Err(Error::Timeout)` - Queue is empty
636    /// * `Err(Error)` - Deserialization error
637    /// 
638    /// # Safety
639    /// 
640    /// Must only be called from ISR context.
641    fn fetch_from_isr(&self, buffer: &mut T) -> Result<()> {
642        let mut buf_bytes = Vec::with_capacity(buffer.len());      
643
644        if let Ok(()) = self.0.fetch_from_isr(&mut buf_bytes) {
645            *buffer = T::from_bytes(&buf_bytes)?;
646            Ok(())
647        } else {
648            Err(Error::Timeout)
649        }
650    }
651
652    /// Sends a typed message to the queue (without serde feature).
653    /// 
654    /// Serializes the message to bytes using the custom serialization traits.
655    /// 
656    /// # Arguments
657    /// 
658    /// * `item` - Reference to the message to send
659    /// * `time` - Timeout in system ticks
660    /// 
661    /// # Returns
662    /// 
663    /// * `Ok(())` - Message successfully serialized and sent
664    /// * `Err(Error::Timeout)` - Queue full
665    /// * `Err(Error)` - Serialization error
666    #[inline]
667    fn post(&self, item: &T, time: TickType) -> Result<()> {
668        self.0.post(&item.to_bytes(), time)
669    }
670
671    /// Sends a typed message from ISR context (without serde feature).
672    /// 
673    /// ISR-safe version that does not block. Serializes the message to bytes.
674    /// 
675    /// # Arguments
676    /// 
677    /// * `item` - Reference to the message to send
678    /// 
679    /// # Returns
680    /// 
681    /// * `Ok(())` - Message successfully serialized and sent
682    /// * `Err(Error::Timeout)` - Queue is full
683    /// * `Err(Error)` - Serialization error
684    /// 
685    /// # Safety
686    /// 
687    /// Must only be called from ISR context.
688    #[inline]
689    fn post_from_isr(&self, item: &T) -> Result<()> {
690        self.0.post_from_isr(&item.to_bytes())
691    }
692
693    /// Deletes the typed queue.
694    /// 
695    /// Delegates to the underlying byte queue's delete method.
696    #[inline]
697    fn delete(&mut self) {
698        self.0.delete()
699    }
700}
701
702#[cfg(feature = "serde")]
703impl<T> QueueStreamedFn<T> for QueueStreamed<T> 
704where 
705    T: StructSerde {
706
707    /// Receives a typed message from the queue (with serde feature).
708    /// 
709    /// Deserializes the message from bytes using the serde framework.
710    /// 
711    /// # Arguments
712    /// 
713    /// * `buffer` - Mutable reference to receive the deserialized message
714    /// * `time` - Timeout in system ticks
715    /// 
716    /// # Returns
717    /// 
718    /// * `Ok(())` - Message successfully received and deserialized
719    /// * `Err(Error::Timeout)` - Queue empty or timeout
720    /// * `Err(Error::Unhandled)` - Deserialization error
721    fn fetch(&self, buffer: &mut T, time: TickType) -> Result<()> {
722        let mut buf_bytes = Vec::with_capacity(buffer.len());     
723
724        if let Ok(()) = self.0.fetch(&mut buf_bytes, time) {
725            
726            to_bytes(buffer, &mut buf_bytes).map_err(|_| Error::Unhandled("Deserializiation error"))?;
727
728            Ok(())
729        } else {
730            Err(Error::Timeout)
731        }
732    }
733
734    /// Receives a typed message from ISR context (with serde feature).
735    /// 
736    /// ISR-safe version that does not block. Deserializes using serde.
737    /// 
738    /// # Arguments
739    /// 
740    /// * `buffer` - Mutable reference to receive the deserialized message
741    /// 
742    /// # Returns
743    /// 
744    /// * `Ok(())` - Message successfully received and deserialized
745    /// * `Err(Error::Timeout)` - Queue is empty
746    /// * `Err(Error::Unhandled)` - Deserialization error
747    /// 
748    /// # Safety
749    /// 
750    /// Must only be called from ISR context.
751    fn fetch_from_isr(&self, buffer: &mut T) -> Result<()> {
752        let mut buf_bytes = Vec::with_capacity(buffer.len());       
753
754        if let Ok(()) = self.0.fetch_from_isr(&mut buf_bytes) {
755            to_bytes(buffer, &mut buf_bytes).map_err(|_| Error::Unhandled("Deserializiation error"))?;
756            Ok(())
757        } else {
758            Err(Error::Timeout)
759        }
760    }
761
762    /// Sends a typed message to the queue (with serde feature).
763    /// 
764    /// Serializes the message to bytes using the serde framework.
765    /// 
766    /// # Arguments
767    /// 
768    /// * `item` - Reference to the message to send
769    /// * `time` - Timeout in system ticks
770    /// 
771    /// # Returns
772    /// 
773    /// * `Ok(())` - Message successfully serialized and sent
774    /// * `Err(Error::Timeout)` - Queue full
775    /// * `Err(Error::Unhandled)` - Serialization error
776    fn post(&self, item: &T, time: TickType) -> Result<()> {
777
778
779        let mut buf_bytes = Vec::with_capacity(item.len()); 
780
781        to_bytes(item, &mut buf_bytes).map_err(|_| Error::Unhandled("Deserializiation error"))?;
782
783        self.0.post(&buf_bytes, time)
784    }
785
786    /// Sends a typed message from ISR context (with serde feature).
787    /// 
788    /// ISR-safe version that does not block. Serializes using serde.
789    /// 
790    /// # Arguments
791    /// 
792    /// * `item` - Reference to the message to send
793    /// 
794    /// # Returns
795    /// 
796    /// * `Ok(())` - Message successfully serialized and sent
797    /// * `Err(Error::Timeout)` - Queue is full
798    /// * `Err(Error::Unhandled)` - Serialization error
799    /// 
800    /// # Safety
801    /// 
802    /// Must only be called from ISR context.
803    fn post_from_isr(&self, item: &T) -> Result<()> {
804
805        let mut buf_bytes = Vec::with_capacity(item.len()); 
806
807        to_bytes(item, &mut buf_bytes).map_err(|_| Error::Unhandled("Deserializiation error"))?;
808
809        self.0.post_from_isr(&buf_bytes)
810    }
811
812    /// Deletes the typed queue (serde version).
813    /// 
814    /// Delegates to the underlying byte queue's delete method.
815    #[inline]
816    fn delete(&mut self) {
817        self.0.delete()
818    }
819}
820
821/// Allows dereferencing to the underlying FreeRTOS queue handle.
822impl<T> Deref for QueueStreamed<T> 
823where 
824    T: StructSerde {
825    type Target = QueueHandle;
826
827    fn deref(&self) -> &Self::Target {
828        &self.0.0
829    }   
830}
831
832/// Formats the typed queue for debugging purposes.
833impl<T> Debug for QueueStreamed<T> 
834where 
835    T: StructSerde {
836    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
837        f.debug_struct("QueueStreamed")
838            .field("handle", &self.0.0)
839            .finish()
840    }
841}
842
843/// Formats the typed queue for display purposes.
844impl<T> Display for QueueStreamed<T> 
845where 
846    T: StructSerde {
847    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
848        write!(f, "QueueStreamed {{ handle: {:?} }}", self.0.0)
849    }
850}
851