use core::ffi::c_void;
use core::fmt::{Debug, Display};
use core::marker::PhantomData;
use core::ops::Deref;
use alloc::vec::Vec;
use super::ffi::{QueueHandle, pdFALSE, vQueueDelete, xQueueGenericCreate, xQueueReceive, xQueueReceiveFromISR};
use super::types::{BaseType, UBaseType, TickType};
use super::system::System;
use crate::traits::{ToTick, QueueFn, SystemFn, QueueStreamedFn, BytesHasLen};
#[cfg(not(feature = "serde"))]
use crate::traits::{Serialize, Deserialize};
#[cfg(feature = "serde")]
use osal_rs_serde::{Serialize, Deserialize, to_bytes};
pub trait StructSerde : Serialize + BytesHasLen + Deserialize {}
use crate::utils::{Result, Error};
pub struct Queue (QueueHandle);
unsafe impl Send for Queue {}
unsafe impl Sync for Queue {}
impl Queue {
pub fn new (size: UBaseType, message_size: UBaseType) -> Result<Self> {
const QUEUE_TYPE_BASE: u8 = 0; let handle = unsafe { xQueueGenericCreate(size, message_size, QUEUE_TYPE_BASE) };
if handle.is_null() {
Err(Error::OutOfMemory)
} else {
Ok(Self (handle))
}
}
#[inline]
pub fn fetch_with_to_tick(&self, buffer: &mut [u8], time: impl ToTick) -> Result<()> {
self.fetch(buffer, time.to_ticks())
}
#[inline]
pub fn post_with_to_tick(&self, item: &[u8], time: impl ToTick) -> Result<()> {
self.post(item, time.to_ticks())
}
}
impl QueueFn for Queue {
fn fetch(&self, buffer: &mut [u8], time: TickType) -> Result<()> {
let ret = unsafe {
xQueueReceive(
self.0,
buffer.as_mut_ptr() as *mut c_void,
time,
)
};
if ret == 0 {
Err(Error::Timeout)
} else {
Ok(())
}
}
fn fetch_from_isr(&self, buffer: &mut [u8]) -> Result<()> {
let mut task_woken_by_receive: BaseType = pdFALSE;
let ret = unsafe {
xQueueReceiveFromISR(
self.0,
buffer.as_mut_ptr() as *mut c_void,
&mut task_woken_by_receive
)
};
if ret == 0 {
Err(Error::Timeout)
} else {
System::yield_from_isr(task_woken_by_receive);
Ok(())
}
}
fn post(&self, item: &[u8], time: TickType) -> Result<()> {
let ret = xQueueSendToBack!(
self.0,
item.as_ptr() as *const c_void,
time
);
if ret == 0 {
Err(Error::Timeout)
} else {
Ok(())
}
}
fn post_from_isr(&self, item: &[u8]) -> Result<()> {
let mut task_woken_by_receive: BaseType = pdFALSE;
let ret = xQueueSendToBackFromISR!(
self.0,
item.as_ptr() as *const c_void,
&mut task_woken_by_receive
);
if ret == 0 {
Err(Error::Timeout)
} else {
System::yield_from_isr(task_woken_by_receive);
Ok(())
}
}
fn delete(&mut self) {
unsafe {
vQueueDelete(self.0);
self.0 = core::ptr::null_mut();
}
}
}
impl Drop for Queue {
fn drop(&mut self) {
if self.0.is_null() {
return;
}
self.delete();
}
}
impl Deref for Queue {
type Target = QueueHandle;
fn deref(&self) -> &Self::Target {
&self.0
}
}
impl Debug for Queue {
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
f.debug_struct("Queue")
.field("handle", &self.0)
.finish()
}
}
impl Display for Queue {
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
write!(f, "Queue {{ handle: {:?} }}", self.0)
}
}
pub struct QueueStreamed<T: StructSerde> (Queue, PhantomData<T>);
unsafe impl<T: StructSerde> Send for QueueStreamed<T> {}
unsafe impl<T: StructSerde> Sync for QueueStreamed<T> {}
impl<T> QueueStreamed<T>
where
T: StructSerde {
#[inline]
pub fn new (size: UBaseType, message_size: UBaseType) -> Result<Self> {
Ok(Self (Queue::new(size, message_size)?, PhantomData))
}
#[inline]
fn fetch_with_to_tick(&self, buffer: &mut T, time: impl ToTick) -> Result<()> {
self.fetch(buffer, time.to_ticks())
}
#[inline]
fn post_with_to_tick(&self, item: &T, time: impl ToTick) -> Result<()> {
self.post(item, time.to_ticks())
}
}
#[cfg(not(feature = "serde"))]
impl<T> QueueStreamedFn<T> for QueueStreamed<T>
where
T: StructSerde {
fn fetch(&self, buffer: &mut T, time: TickType) -> Result<()> {
let mut buf_bytes = Vec::with_capacity(buffer.len());
if let Ok(()) = self.0.fetch(&mut buf_bytes, time) {
*buffer = T::from_bytes(&buf_bytes)?;
Ok(())
} else {
Err(Error::Timeout)
}
}
fn fetch_from_isr(&self, buffer: &mut T) -> Result<()> {
let mut buf_bytes = Vec::with_capacity(buffer.len());
if let Ok(()) = self.0.fetch_from_isr(&mut buf_bytes) {
*buffer = T::from_bytes(&buf_bytes)?;
Ok(())
} else {
Err(Error::Timeout)
}
}
#[inline]
fn post(&self, item: &T, time: TickType) -> Result<()> {
self.0.post(&item.to_bytes(), time)
}
#[inline]
fn post_from_isr(&self, item: &T) -> Result<()> {
self.0.post_from_isr(&item.to_bytes())
}
#[inline]
fn delete(&mut self) {
self.0.delete()
}
}
#[cfg(feature = "serde")]
impl<T> QueueStreamedFn<T> for QueueStreamed<T>
where
T: StructSerde {
fn fetch(&self, buffer: &mut T, time: TickType) -> Result<()> {
let mut buf_bytes = Vec::with_capacity(buffer.len());
if let Ok(()) = self.0.fetch(&mut buf_bytes, time) {
to_bytes(buffer, &mut buf_bytes).map_err(|_| Error::Unhandled("Deserializiation error"))?;
Ok(())
} else {
Err(Error::Timeout)
}
}
fn fetch_from_isr(&self, buffer: &mut T) -> Result<()> {
let mut buf_bytes = Vec::with_capacity(buffer.len());
if let Ok(()) = self.0.fetch_from_isr(&mut buf_bytes) {
to_bytes(buffer, &mut buf_bytes).map_err(|_| Error::Unhandled("Deserializiation error"))?;
Ok(())
} else {
Err(Error::Timeout)
}
}
fn post(&self, item: &T, time: TickType) -> Result<()> {
let mut buf_bytes = Vec::with_capacity(item.len());
to_bytes(item, &mut buf_bytes).map_err(|_| Error::Unhandled("Deserializiation error"))?;
self.0.post(&buf_bytes, time)
}
fn post_from_isr(&self, item: &T) -> Result<()> {
let mut buf_bytes = Vec::with_capacity(item.len());
to_bytes(item, &mut buf_bytes).map_err(|_| Error::Unhandled("Deserializiation error"))?;
self.0.post_from_isr(&buf_bytes)
}
#[inline]
fn delete(&mut self) {
self.0.delete()
}
}
impl<T> Deref for QueueStreamed<T>
where
T: StructSerde {
type Target = QueueHandle;
fn deref(&self) -> &Self::Target {
&self.0.0
}
}
impl<T> Debug for QueueStreamed<T>
where
T: StructSerde {
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
f.debug_struct("QueueStreamed")
.field("handle", &self.0.0)
.finish()
}
}
impl<T> Display for QueueStreamed<T>
where
T: StructSerde {
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
write!(f, "QueueStreamed {{ handle: {:?} }}", self.0.0)
}
}