use std::fmt::{self, Debug};
use std::marker::PhantomData;
use std::ops::{Deref, DerefMut};
use rosidl_runtime_rs::{Sequence, SequenceAlloc, SequenceExceedsBoundsError};
use super::check;
#[doc(hidden)]
pub unsafe trait Proxy<'msg> {
type Metadata: 'msg + Copy;
fn size_in_memory(metadata: Self::Metadata) -> usize;
unsafe fn new(bytes: &'msg [u8], metadata: Self::Metadata) -> Self;
}
#[doc(hidden)]
pub unsafe trait ProxyMut<'msg> {
type Metadata: 'msg + Copy;
fn size_in_memory(metadata: Self::Metadata) -> usize;
unsafe fn new(bytes: &'msg mut [u8], metadata: Self::Metadata) -> Self;
}
#[doc(hidden)]
pub trait InnerSequence<T: PartialEq>: PartialEq {
fn as_slice(&self) -> &[T];
fn as_mut_slice(&mut self) -> &mut [T];
fn resize_unchecked(&mut self, resize_function: ResizeFunction, len: usize);
}
#[doc(hidden)]
pub struct ProxySequence<'msg, T: ProxyMut<'msg>> {
sequence: &'msg mut TypeErasedSequence,
proxies: Vec<T>,
metadata: T::Metadata,
}
impl<'msg, T> InnerSequence<T> for ProxySequence<'msg, T>
where
T: PartialEq + ProxyMut<'msg>,
{
fn as_slice(&self) -> &[T] {
self.proxies.as_slice()
}
fn as_mut_slice(&mut self) -> &mut [T] {
self.proxies.as_mut_slice()
}
fn resize_unchecked(&mut self, resize_function: ResizeFunction, len: usize) {
let is_ok =
unsafe { resize_function(self.sequence as *mut _ as *mut std::os::raw::c_void, len) };
assert!(is_ok);
self.proxies = unsafe { self.sequence.proxy_elems_mut(self.metadata) };
}
}
impl<'msg, T> InnerSequence<T> for &'msg mut Sequence<T>
where
T: PartialEq + SequenceAlloc,
{
fn as_slice(&self) -> &[T] {
Sequence::as_slice(self)
}
fn as_mut_slice(&mut self) -> &mut [T] {
Sequence::as_mut_slice(self)
}
fn resize_unchecked(&mut self, resize_function: ResizeFunction, len: usize) {
let is_ok = unsafe { resize_function(self as *mut _ as *mut std::os::raw::c_void, len) };
assert!(is_ok);
}
}
impl<'msg, T> PartialEq for ProxySequence<'msg, T>
where
T: PartialEq + ProxyMut<'msg>,
{
fn eq(&self, other: &Self) -> bool {
self.proxies.eq(&other.proxies)
}
}
#[doc(hidden)]
pub trait DynamicSequenceElementMut<'msg>: Debug + PartialEq + Sized {
type InnerSequence: InnerSequence<Self>;
}
impl<'msg, T> DynamicSequenceElementMut<'msg> for T
where
T: Debug + PartialEq + SequenceAlloc + 'static,
{
type InnerSequence = &'msg mut Sequence<T>;
}
#[repr(C)]
pub(crate) struct TypeErasedSequence {
pub(super) data: *mut std::os::raw::c_void,
pub(super) size: usize,
pub(super) capacity: usize,
}
impl TypeErasedSequence {
pub(super) unsafe fn proxy_elems<'msg, T>(&self, metadata: T::Metadata) -> Vec<T>
where
T: Proxy<'msg>,
{
let element_size = T::size_in_memory(metadata);
if self.data.is_null() {
return Vec::new();
};
let sequence_data =
std::slice::from_raw_parts(self.data as *const u8, self.size * element_size);
check::<T>(sequence_data);
sequence_data
.chunks(element_size)
.map(|bytes| T::new(bytes, metadata))
.collect()
}
pub(super) unsafe fn proxy_elems_mut<'msg, T>(&self, metadata: T::Metadata) -> Vec<T>
where
T: ProxyMut<'msg>,
{
let element_size = T::size_in_memory(metadata);
if self.data.is_null() {
return Vec::new();
};
let sequence_data =
std::slice::from_raw_parts_mut(self.data as *mut u8, self.size * element_size);
check::<T>(sequence_data);
sequence_data
.chunks_mut(element_size)
.map(|bytes| T::new(bytes, metadata))
.collect()
}
}
#[derive(PartialEq, Eq)]
pub struct DynamicSequence<'msg, T>
where
T: Proxy<'msg>,
{
elements: Box<[T]>,
phantom: PhantomData<&'msg u8>,
}
#[derive(PartialEq, Eq)]
enum BooSlice<'msg, T> {
Borrowed(&'msg [T]),
Owned(Box<[T]>),
}
#[derive(PartialEq, Eq)]
pub struct DynamicBoundedSequence<'msg, T> {
boo: BooSlice<'msg, T>,
upper_bound: usize,
}
impl<'msg, T> Debug for DynamicSequence<'msg, T>
where
T: Debug + Proxy<'msg>,
{
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> Result<(), fmt::Error> {
self.elements.iter().fmt(f)
}
}
impl<'msg, T> Deref for DynamicSequence<'msg, T>
where
T: Proxy<'msg>,
{
type Target = [T];
fn deref(&self) -> &Self::Target {
&*self.elements
}
}
impl<'msg, T> DynamicSequence<'msg, T>
where
T: Proxy<'msg>,
{
pub(super) unsafe fn new_proxy(bytes: &'msg [u8], metadata: T::Metadata) -> Self {
let sequence = &*(bytes.as_ptr() as *const TypeErasedSequence);
let elements = sequence.proxy_elems(metadata).into_boxed_slice();
Self {
elements,
phantom: PhantomData,
}
}
pub fn as_slice(&self) -> &[T] {
&*self.elements
}
}
impl<'msg, T> BooSlice<'msg, T> {
fn as_slice(&self) -> &[T] {
match self {
BooSlice::Borrowed(slice) => slice,
BooSlice::Owned(boxed_slice) => &**boxed_slice,
}
}
}
impl<'msg, T> Debug for DynamicBoundedSequence<'msg, T>
where
T: Debug,
{
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> Result<(), fmt::Error> {
self.boo.as_slice().fmt(f)
}
}
impl<'msg, T> Deref for DynamicBoundedSequence<'msg, T> {
type Target = [T];
fn deref(&self) -> &Self::Target {
self.boo.as_slice()
}
}
impl<'msg, T> DynamicBoundedSequence<'msg, T>
where
T: SequenceAlloc,
{
pub(super) unsafe fn new_primitive(bytes: &'msg [u8], upper_bound: usize) -> Self {
let sequence = &*(bytes.as_ptr() as *const Sequence<T>);
let slice = sequence.as_slice();
Self {
boo: BooSlice::Borrowed(slice),
upper_bound,
}
}
}
impl<'msg, T> DynamicBoundedSequence<'msg, T>
where
T: Proxy<'msg>,
{
pub(super) unsafe fn new_proxy(
bytes: &'msg [u8],
upper_bound: usize,
metadata: T::Metadata,
) -> Self {
let sequence = &*(bytes.as_ptr() as *const TypeErasedSequence);
Self {
boo: BooSlice::Owned(sequence.proxy_elems(metadata).into_boxed_slice()),
upper_bound,
}
}
}
impl<'msg, T: SequenceAlloc> DynamicBoundedSequence<'msg, T> {
pub fn as_slice(&self) -> &[T] {
self.boo.as_slice()
}
pub fn upper_bound(&self) -> usize {
self.upper_bound
}
}
pub(super) type ResizeFunction =
unsafe extern "C" fn(arg1: *mut std::os::raw::c_void, size: usize) -> bool;
#[derive(PartialEq)]
pub struct DynamicSequenceMut<'msg, T: DynamicSequenceElementMut<'msg>> {
sequence: T::InnerSequence,
resize_function: ResizeFunction,
}
#[derive(PartialEq)]
pub struct DynamicBoundedSequenceMut<'msg, T: DynamicSequenceElementMut<'msg>> {
inner: DynamicSequenceMut<'msg, T>,
upper_bound: usize,
}
impl<'msg, T> Debug for DynamicSequenceMut<'msg, T>
where
T: DynamicSequenceElementMut<'msg>,
{
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> Result<(), fmt::Error> {
self.sequence.as_slice().fmt(f)
}
}
impl<'msg, T> Deref for DynamicSequenceMut<'msg, T>
where
T: DynamicSequenceElementMut<'msg>,
{
type Target = [T];
fn deref(&self) -> &Self::Target {
self.sequence.as_slice()
}
}
impl<'msg, T> DerefMut for DynamicSequenceMut<'msg, T>
where
T: DynamicSequenceElementMut<'msg>,
{
fn deref_mut(&mut self) -> &mut Self::Target {
self.sequence.as_mut_slice()
}
}
impl<'msg, T> DynamicSequenceMut<'msg, T>
where
T: SequenceAlloc
+ DynamicSequenceElementMut<'msg, InnerSequence = &'msg mut Sequence<T>>
+ 'static,
{
pub(super) unsafe fn new_primitive(
bytes: &'msg mut [u8],
resize_function: ResizeFunction,
) -> Self {
let sequence = &mut *(bytes.as_mut_ptr() as *mut Sequence<T>);
Self {
sequence,
resize_function,
}
}
}
impl<'msg, T> DynamicSequenceMut<'msg, T>
where
T: ProxyMut<'msg> + DynamicSequenceElementMut<'msg, InnerSequence = ProxySequence<'msg, T>>,
{
pub(super) unsafe fn new_proxy(
bytes: &'msg mut [u8],
metadata: T::Metadata,
resize_function: ResizeFunction,
) -> Self {
let sequence = &mut *(bytes.as_mut_ptr() as *mut TypeErasedSequence);
let proxies = sequence.proxy_elems_mut(metadata);
let sequence = ProxySequence {
sequence,
proxies,
metadata,
};
Self {
sequence,
resize_function,
}
}
}
impl<'msg, T> DynamicSequenceMut<'msg, T>
where
T: DynamicSequenceElementMut<'msg>,
{
pub fn as_slice(&self) -> &[T] {
self.sequence.as_slice()
}
pub fn as_mut_slice(&mut self) -> &mut [T] {
self.sequence.as_mut_slice()
}
pub fn clear(&mut self) {
self.reset(0);
}
pub fn reset(&mut self, len: usize) {
self.sequence.resize_unchecked(self.resize_function, len)
}
}
impl<'msg, T> Debug for DynamicBoundedSequenceMut<'msg, T>
where
T: DynamicSequenceElementMut<'msg>,
{
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> Result<(), fmt::Error> {
self.inner.fmt(f)
}
}
impl<'msg, T: DynamicSequenceElementMut<'msg>> Deref for DynamicBoundedSequenceMut<'msg, T> {
type Target = [T];
fn deref(&self) -> &Self::Target {
self.inner.deref()
}
}
impl<'msg, T: DynamicSequenceElementMut<'msg>> DerefMut for DynamicBoundedSequenceMut<'msg, T> {
fn deref_mut(&mut self) -> &mut Self::Target {
self.inner.deref_mut()
}
}
impl<'msg, T> DynamicBoundedSequenceMut<'msg, T>
where
T: SequenceAlloc
+ DynamicSequenceElementMut<'msg, InnerSequence = &'msg mut Sequence<T>>
+ 'static,
{
pub(super) unsafe fn new_primitive(
bytes: &'msg mut [u8],
upper_bound: usize,
resize_function: ResizeFunction,
) -> Self {
let inner = DynamicSequenceMut::new_primitive(bytes, resize_function);
Self { inner, upper_bound }
}
}
impl<'msg, T> DynamicBoundedSequenceMut<'msg, T>
where
T: ProxyMut<'msg> + DynamicSequenceElementMut<'msg, InnerSequence = ProxySequence<'msg, T>>,
{
pub(super) unsafe fn new_proxy(
bytes: &'msg mut [u8],
metadata: T::Metadata,
upper_bound: usize,
resize_function: ResizeFunction,
) -> Self {
let inner = DynamicSequenceMut::new_proxy(bytes, metadata, resize_function);
Self { inner, upper_bound }
}
}
impl<'msg, T: DynamicSequenceElementMut<'msg>> DynamicBoundedSequenceMut<'msg, T> {
pub fn as_slice(&self) -> &[T] {
self.inner.as_slice()
}
pub fn as_mut_slice(&mut self) -> &mut [T] {
self.inner.as_mut_slice()
}
pub fn upper_bound(&self) -> usize {
self.upper_bound
}
pub fn clear(&mut self) {
self.inner.clear();
}
pub fn try_reset(&mut self, len: usize) -> Result<(), SequenceExceedsBoundsError> {
if len > self.upper_bound {
Err(SequenceExceedsBoundsError {
len,
upper_bound: self.upper_bound,
})
} else {
self.inner.reset(len);
Ok(())
}
}
}