use std::convert::TryFrom;
use crate::component::{Component, ComponentTypeID};
#[derive(Debug, Clone)]
pub struct ComponentValueRef<'a> {
type_id: ComponentTypeID,
slice: &'a [u8],
}
impl<'a> ComponentValueRef<'a> {
pub unsafe fn from_raw(type_id: ComponentTypeID, data: &'a [u8]) -> ComponentValueRef<'a> {
ComponentValueRef {
type_id,
slice: data,
}
}
pub fn type_id(&self) -> ComponentTypeID {
self.type_id
}
pub fn as_slice(&self) -> &'a [u8] {
self.slice
}
pub fn downcast<T: Component>(&self) -> Option<&T> {
if T::type_id() == self.type_id {
Some(unsafe { std::mem::transmute(self.slice.as_ptr()) })
} else {
None
}
}
}
impl<'a, T: Component> From<&T> for ComponentValueRef<'a> {
fn from(v: &T) -> Self {
let slice = unsafe {
let ptr = v as *const _;
std::slice::from_raw_parts(ptr as _, std::mem::size_of::<T>())
};
ComponentValueRef {
type_id: T::type_id(),
slice,
}
}
}
pub trait ComponentData<'a> {
type Iterator: Iterator<Item=ComponentValueRef<'a>> + Clone;
fn iter(&self) -> Self::Iterator;
}
pub struct ComponentDataSlice<'a, 'b>(pub &'b [ComponentValueRef<'a>]);
impl<'a, 'b> ComponentDataSlice<'a, 'b> {
pub fn to_owned(&self) -> ComponentDataVec<'a> {
ComponentDataVec(self.0.to_owned())
}
}
impl<'a, 'b> ComponentData<'a> for ComponentDataSlice<'a, 'b> {
type Iterator = std::iter::Cloned<std::slice::Iter<'b, ComponentValueRef<'a>>>;
fn iter(&self) -> Self::Iterator {
self.0.iter().cloned()
}
}
impl<'a, 'b> TryFrom<&'b [ComponentValueRef<'a>]> for ComponentDataSlice<'a, 'b> {
type Error = ();
fn try_from(value: &'b [ComponentValueRef<'a>]) -> Result<Self, Self::Error> {
for s in value.windows(2) {
let a = &s[0];
let b = &s[1];
if b.type_id <= a.type_id {
return Err(());
}
}
Ok(ComponentDataSlice(value))
}
}
impl<'a, 'b> TryFrom<&'b mut [ComponentValueRef<'a>]> for ComponentDataSlice<'a, 'b> {
type Error = ();
fn try_from(value: &'b mut [ComponentValueRef<'a>]) -> Result<Self, Self::Error> {
for s in value.windows(2) {
let a = &s[0];
let b = &s[1];
if b.type_id == a.type_id {
return Err(());
}
}
value.sort_by(|a, b| a.type_id.cmp(&b.type_id));
Ok(ComponentDataSlice(value))
}
}
#[derive(Debug, Clone)]
pub struct ComponentDataVec<'a>(Vec<ComponentValueRef<'a>>);
impl<'a> ComponentDataVec<'a> {
pub fn new() -> ComponentDataVec<'a> {
ComponentDataVec(Vec::new())
}
pub fn as_slice(&self) -> &[ComponentValueRef<'a>] {
&self.0[..]
}
pub fn len(&self) -> usize {
self.0.len()
}
pub fn clear(&mut self) {
self.0.clear()
}
pub fn set_component(&mut self, component_data: ComponentValueRef<'a>) {
match self.0.binary_search_by_key(&component_data.type_id(), |r| r.type_id()) {
Ok(idx) => self.0[idx] = component_data,
Err(idx) => self.0.insert(idx, component_data),
}
}
pub fn remove_component(&mut self, type_id: ComponentTypeID) {
match self.0.binary_search_by_key(&type_id, |r| r.type_id()) {
Ok(idx) => { self.0.remove(idx); }
Err(_) => {}
};
}
}
impl<'a> ComponentData<'a> for ComponentDataVec<'a> {
type Iterator = std::iter::Cloned<std::slice::Iter<'a, ComponentValueRef<'a>>>;
fn iter(&self) -> Self::Iterator {
unsafe { std::mem::transmute(self.0.iter().cloned()) }
}
}
impl<'a> TryFrom<Vec<ComponentValueRef<'a>>> for ComponentDataVec<'a> {
type Error = ();
fn try_from(mut value: Vec<ComponentValueRef<'a>>) -> Result<Self, Self::Error> {
ComponentDataSlice::try_from(&mut value[..])?;
Ok(ComponentDataVec(value))
}
}
#[derive(Debug)]
pub struct ComponentDataVecWriter<'a, 'b> {
vec: &'b mut Vec<ComponentValueRef<'a>>,
offset: usize,
}
impl<'a, 'b> ComponentDataVecWriter<'a, 'b> {
pub fn new(vec: &'b mut Vec<ComponentValueRef<'a>>) -> ComponentDataVecWriter<'a, 'b> {
let offset = vec.len();
ComponentDataVecWriter {
vec,
offset,
}
}
pub fn as_slice(&self) -> &[ComponentValueRef<'a>] {
&self.vec[self.offset..]
}
pub fn len(&self) -> usize {
self.vec.len() - self.offset
}
pub fn set_component(&mut self, component_data: ComponentValueRef<'a>) {
let slice = &mut self.vec[self.offset..];
match slice.binary_search_by_key(&component_data.type_id(), |r| r.type_id()) {
Ok(idx) => slice[idx] = component_data,
Err(idx) => self.vec.insert(self.offset + idx, component_data),
}
}
pub fn remove_component(&mut self, type_id: ComponentTypeID) {
let slice = &mut self.vec[self.offset..];
match slice.binary_search_by_key(&type_id, |r| r.type_id()) {
Ok(idx) => { self.vec.remove(self.offset + idx); }
Err(_) => {}
};
}
pub fn range(&self) -> (usize, usize) {
(self.offset, self.vec.len())
}
}
#[cfg(test)]
mod test {
use super::*;
use crate::component;
#[test]
fn test_component_data() {
#[derive(Clone, Copy, Default, Debug)]
struct A(u8);
component!(A);
#[derive(Clone, Copy, Default, Debug)]
struct B(u8);
component!(B);
let value_ref = ComponentValueRef::from(&A(23));
assert_eq!(value_ref.type_id(), A::type_id());
assert_eq!(value_ref.as_slice()[0], 23);
let mut unsorted_data = [
(&B(24)).into(),
(&A(51)).into(),
];
let data = ComponentDataSlice::try_from(&mut unsorted_data[..]).unwrap();
assert_eq!(data.0.len(), 2);
assert_eq!(data.0[0].type_id(), A::type_id());
assert_eq!(data.0[1].type_id(), B::type_id());
assert_eq!(data.0[0].as_slice()[0], 51);
assert_eq!(data.0[1].as_slice()[0], 24);
}
}