use std::any::{Any, TypeId};
use std::marker::PhantomData;
use std::slice;
use dync::{dync_mod, from_dyn, into_dyn, BoxValue, SliceDrop, SliceDropMut, SmallValue, VecDrop};
use hashbrown::HashSet;
#[cfg(feature = "serde")]
use serde::{Deserialize, Serialize};
use crate::index::*;
use crate::mesh::topology::*;
use super::Error;
pub use std::sync::Arc as Irc;
#[allow(missing_docs)]
#[dync_mod]
mod value_traits {
pub trait AttributeValue: Clone + PartialEq + std::fmt::Debug + Send + Sync + 'static {}
impl<T> AttributeValue for T where T: Clone + PartialEq + std::fmt::Debug + Send + Sync + 'static {}
pub trait AttributeValueHash: AttributeValue + Eq + std::hash::Hash {}
impl<T> AttributeValueHash for T where T: AttributeValue + Eq + std::hash::Hash {}
}
pub use self::value_traits::*;
pub type DataSlice<'a> = SliceDrop<'a, AttributeValueVTable>;
pub type HDataSlice<'a> = SliceDrop<'a, AttributeValueHashVTable>;
pub type DataSliceMut<'a> = SliceDropMut<'a, AttributeValueVTable>;
pub type HDataSliceMut<'a> = SliceDropMut<'a, AttributeValueHashVTable>;
pub type DataVec = VecDrop<AttributeValueVTable>;
pub type HDataVec = VecDrop<AttributeValueHashVTable>;
pub type Value = BoxValue<AttributeValueVTable>;
pub type ValueRef<'a> = dync::ValueRef<'a, AttributeValueVTable>;
pub type HValue = SmallValue<AttributeValueHashVTable>;
pub type HValueRef<'a> = dync::ValueRef<'a, AttributeValueHashVTable>;
pub type HValueMut<'a> = dync::ValueMut<'a, AttributeValueHashVTable>;
pub type AttribValueCache = HashSet<HValue>;
macro_rules! impl_data_base {
($vec_type:ty) => {
#[inline]
pub fn check<T: Any>(&self) -> Result<&Self, Error> {
self.buf
.check_ref::<T>()
.map(|_| self)
.ok_or_else(|| Error::type_mismatch_from_buf::<T, _>(&self.buf))
}
#[inline]
pub fn check_mut<T: Any>(&mut self) -> Result<&mut Self, Error> {
match self.buf.check_mut::<T>() {
Some(_) => Ok(self),
None => Err(Error::type_mismatch_from_buf::<T, _>(&self.buf)),
}
}
#[inline]
pub fn element_type_id(&self) -> TypeId {
self.buf.element_type_id()
}
#[inline]
pub fn element_size(&self) -> usize {
self.buf.element_size()
}
#[inline]
pub fn len(&self) -> usize {
self.buf.len()
}
#[inline]
pub fn byte_len(&self) -> usize {
self.buf.len() * self.buf.element_size()
}
#[inline]
pub fn is_empty(&self) -> bool {
self.buf.is_empty()
}
#[inline]
pub unsafe fn get_unchecked_ref<T: Any>(&self, i: usize) -> &T {
self.buf.get_unchecked_ref(i)
}
#[inline]
pub unsafe fn get_unchecked_mut<T: Any>(&mut self, i: usize) -> &mut T {
self.buf.get_unchecked_mut(i)
}
#[inline]
pub fn data_ref(&self) -> &$vec_type {
&self.buf
}
#[inline]
pub fn data_mut(&mut self) -> &mut $vec_type {
&mut self.buf
}
#[inline]
pub fn into_data(self) -> $vec_type {
self.buf
}
#[inline]
pub fn extend_by(&mut self, n: usize) {
let Self {
buf,
default_element,
..
} = self;
for _ in 0..n {
buf.push_cloned(default_element.as_ref());
}
}
#[inline]
pub fn rotate_left(&mut self, mid: usize) {
self.buf.rotate_left(mid);
}
#[inline]
pub fn rotate_right(&mut self, k: usize) {
self.buf.rotate_right(k);
}
};
}
#[derive(Clone, Debug, PartialEq)]
pub struct IndirectData {
buf: HDataVec,
default_element: HValue,
}
impl IndirectData {
impl_data_base!(HDataVec);
pub fn with_size<T: AttributeValueHash>(n: usize, def: T) -> Self {
let default_element = Irc::new(def);
IndirectData {
buf: HDataVec::with_size(n, Irc::clone(&default_element)),
default_element: HValue::new(default_element),
}
}
fn get_or_insert<T: AttributeValueHash>(set: &mut AttribValueCache, elem: T) -> Irc<T> {
let elem = HValue::new(Irc::new(elem));
if let Some(elem) = set.get(&elem) {
Irc::clone(elem.as_ref().downcast().unwrap())
} else {
assert!(set.insert(elem.clone()));
elem.downcast().unwrap()
}
}
pub fn from_vec<T: AttributeValueHash + Default>(
vec: Vec<T>,
cache: &mut AttribValueCache,
) -> Self {
let default_element = Irc::new(T::default());
let buf: Vec<_> = vec
.into_iter()
.map(|elem| Self::get_or_insert(cache, elem))
.collect();
IndirectData {
buf: HDataVec::from_vec(buf),
default_element: HValue::new(default_element),
}
}
#[inline]
pub fn from_slice<T: AttributeValueHash + Default>(
buf: &[T],
cache: &mut AttribValueCache,
) -> Self {
Self::from_vec(buf.to_vec(), cache)
}
pub fn duplicate_empty(&self) -> Self {
IndirectData {
buf: HDataVec::with_type_from(&self.buf),
default_element: self.default_element.clone(),
}
}
pub fn duplicate_with(
&self,
dup_data: impl FnOnce(HDataSlice) -> VecDrop<dyn HasAttributeValue>,
) -> Self {
IndirectData {
buf: from_dyn![VecDrop<dyn HasAttributeValue as AttributeValueHashVTable>](dup_data(
self.data_ref().as_slice(),
)),
default_element: self.default_element.clone(),
}
}
pub fn duplicate_with_len(
&self,
len: usize,
init: impl FnOnce(HDataSliceMut, HDataSlice),
) -> Self {
let mut attrib = self.duplicate_empty();
attrib.extend_by(len);
init(attrib.data_mut().as_mut_slice(), self.data_ref().as_slice());
attrib
}
#[inline]
pub fn clone_into_vec<T: AttributeValueHash>(&self) -> Result<Vec<T>, Error> {
let result = Vec::with_capacity(self.len());
self.buf
.iter_as::<Irc<T>>()
.unwrap()
.fold(Some(result), |mut acc, rc| {
if let Some(acc) = acc.as_mut() {
acc.push((**rc).clone());
}
acc
})
.ok_or_else(|| Error::type_mismatch_from_buf::<Irc<T>, _>(&self.buf))
}
#[inline]
pub fn iter<'a, T: Any>(&'a self) -> Result<impl Iterator<Item = &'a T> + 'a, Error> {
self.buf
.iter_as::<Irc<T>>()
.map(|iter| iter.map(|rc| &**rc))
.ok_or_else(|| Error::type_mismatch_from_buf::<Irc<T>, _>(&self.buf))
}
pub fn update_with<T, F>(
&mut self,
mut f: F,
cache: &mut AttribValueCache,
) -> Result<&mut Self, Error>
where
T: AttributeValueHash,
F: FnMut(usize, &Irc<T>) -> Option<Irc<T>>,
{
let id = self.buf.element_type_id();
for (i, val) in self.buf.iter_mut().enumerate() {
let rc = val
.downcast::<Irc<T>>()
.ok_or_else(|| Error::type_mismatch_id::<Irc<T>>(id))?;
if let Some(new_rc) = f(i, &*rc) {
let new_value = HValue::new(new_rc);
if let Some(existing) = cache.get(&new_value) {
HValueMut::new(rc).clone_from_other(existing.as_ref())?;
} else if new_value == self.default_element {
HValueMut::new(rc).clone_from_other(self.default_element.as_ref())?;
} else {
HValueMut::new(rc).clone_from_other(new_value.as_ref())?;
assert!(cache.insert(new_value));
}
}
}
Ok(self)
}
pub fn set_at<'a, T>(
&'a mut self,
i: usize,
new_value: T,
cache: &'a mut AttribValueCache,
) -> Result<&'a mut Self, Error>
where
T: AttributeValueHash,
{
self.set_value_at(i, &HValue::new(Irc::new(new_value)), cache)
}
pub fn set_value_at<'a>(
&'a mut self,
i: usize,
new_value: &HValue,
cache: &'a mut AttribValueCache,
) -> Result<&'a mut Self, Error> {
let mut value_out = self.buf.get_mut(i);
if let Some(existing) = cache.get(new_value) {
value_out.clone_from_other(existing.as_ref())?;
} else if new_value == &self.default_element {
value_out.clone_from_other(self.default_element.as_ref())?;
} else {
value_out.clone_from_other(new_value.as_ref())?;
assert!(cache.insert((*new_value).clone()));
}
Ok(self)
}
pub fn push_cloned(
&mut self,
new_value_ref: HValueRef,
cache: &mut AttribValueCache,
) -> Result<&mut Self, Error> {
let expected = self.buf.element_type_id();
let actual = new_value_ref.value_type_id();
let err = || Error::TypeMismatch { expected, actual };
let new_value = new_value_ref.clone_small_value();
if let Some(existing) = cache.get(&new_value) {
self.buf.push_cloned(existing.as_ref()).ok_or_else(err)?;
} else if new_value == self.default_element {
self.buf
.push_cloned(self.default_element.as_ref())
.ok_or_else(err)?;
} else {
self.buf.push_cloned(new_value.as_ref()).ok_or_else(err)?;
assert!(cache.insert(new_value));
}
Ok(self)
}
#[inline]
pub fn as_rc_slice<T: Any>(&self) -> Result<&[Irc<T>], Error> {
self.buf
.as_slice_as()
.ok_or_else(|| Error::type_mismatch_from_buf::<T, _>(&self.buf))
}
#[inline]
pub fn as_mut_rc_slice<T: Any>(&mut self) -> Result<&mut [Irc<T>], Error> {
let element_id = self.buf.element_type_id();
self.buf
.as_mut_slice_as()
.ok_or_else(|| Error::type_mismatch_id::<Irc<T>>(element_id))
}
#[inline]
pub fn default_element(&self) -> HValueRef {
self.default_element.as_ref()
}
}
#[derive(Clone, Debug, PartialEq)]
pub struct DirectData {
buf: DataVec,
default_element: Value,
}
impl DirectData {
impl_data_base!(DataVec);
pub fn with_size<T: AttributeValue>(n: usize, def: T) -> Self {
DirectData {
buf: DataVec::with_size(n, def.clone()),
default_element: Value::new(def),
}
}
pub fn from_vec<T: AttributeValue + Default>(vec: Vec<T>) -> Self {
DirectData {
buf: DataVec::from_vec(vec),
default_element: Value::new(T::default()),
}
}
pub unsafe fn from_raw_data(buf: DataVec, default_element: Value) -> Self {
DirectData {
buf,
default_element,
}
}
#[inline]
pub fn from_slice<T: AttributeValue + Default>(buf: &[T]) -> Self {
Self::from_vec(buf.to_vec())
}
pub fn duplicate_empty(&self) -> Self {
DirectData {
buf: DataVec::with_type_from(&self.buf),
default_element: self.default_element.clone(),
}
}
pub fn duplicate_with(
&self,
dup_data: impl FnOnce(DataSlice) -> VecDrop<dyn HasAttributeValue>,
) -> Self {
DirectData {
buf: from_dyn![VecDrop<dyn HasAttributeValue as AttributeValueVTable>](dup_data(
self.data_ref().as_slice(),
)),
default_element: self.default_element.clone(),
}
}
pub fn duplicate_with_len(
&self,
len: usize,
init: impl FnOnce(DataSliceMut, DataSlice),
) -> Self {
let mut attrib = self.duplicate_empty();
attrib.extend_by(len);
init(attrib.data_mut().as_mut_slice(), self.data_ref().as_slice());
attrib
}
#[inline]
pub fn as_slice<T: Any>(&self) -> Result<&[T], Error> {
self.buf
.as_slice_as()
.ok_or_else(|| Error::type_mismatch_from_buf::<T, _>(&self.buf))
}
#[inline]
pub fn as_mut_slice<T: Any>(&mut self) -> Result<&mut [T], Error> {
let element_id = self.buf.element_type_id();
self.buf
.as_mut_slice_as()
.ok_or_else(|| Error::type_mismatch_id::<T>(element_id))
}
#[inline]
pub fn clone_into_vec<T: Any + Clone>(&self) -> Result<Vec<T>, Error> {
self.buf
.clone_into_vec()
.ok_or_else(|| Error::type_mismatch_from_buf::<T, _>(&self.buf))
}
pub fn push_cloned(&mut self, new_value_ref: ValueRef) -> Result<&mut Self, Error> {
let expected = self.buf.element_type_id();
let actual = new_value_ref.value_type_id();
self.data_mut()
.push_cloned(new_value_ref)
.ok_or_else(|| Error::TypeMismatch { expected, actual })?;
Ok(self)
}
#[inline]
pub fn iter<'a, T: Any + 'a>(&'a self) -> Result<slice::Iter<T>, Error> {
self.buf
.iter_as::<T>()
.ok_or_else(|| Error::type_mismatch_from_buf::<T, _>(&self.buf))
}
#[inline]
pub fn iter_mut<'a, T: Any + 'a>(&'a mut self) -> Result<slice::IterMut<T>, Error> {
let element_id = self.buf.element_type_id();
self.buf
.iter_mut_as::<T>()
.ok_or_else(|| Error::type_mismatch_id::<T>(element_id))
}
#[inline]
pub fn into_vec<T: AttributeValue>(self) -> Result<Vec<T>, Error> {
let element_id = self.buf.element_type_id();
self.buf
.into_vec()
.ok_or_else(|| Error::type_mismatch_id::<T>(element_id))
}
#[inline]
pub fn default_element(&self) -> ValueRef {
self.default_element.as_ref()
}
}
#[derive(Clone, Debug, PartialEq)]
pub enum AttributeData {
Direct(DirectData),
Indirect(IndirectData),
}
impl AttributeData {
pub fn is_direct(&self) -> bool {
matches!(self, AttributeData::Direct(_))
}
pub fn is_indirect(&self) -> bool {
matches!(self, AttributeData::Indirect(_))
}
pub fn direct_with_size<T: AttributeValue>(n: usize, def: T) -> Self {
AttributeData::Direct(DirectData::with_size(n, def))
}
pub fn indirect_with_size<T: AttributeValueHash>(n: usize, def: T) -> Self {
AttributeData::Indirect(IndirectData::with_size(n, def))
}
pub fn direct_from_vec<T: AttributeValue + Default>(vec: Vec<T>) -> Self {
AttributeData::Direct(DirectData::from_vec(vec))
}
pub fn indirect_from_vec<T: AttributeValueHash + Default>(
vec: Vec<T>,
cache: &mut AttribValueCache,
) -> Self {
AttributeData::Indirect(IndirectData::from_vec(vec, cache))
}
pub fn indirect_from_data(data: IndirectData) -> Self {
AttributeData::Indirect(data)
}
#[inline]
pub fn direct_from_slice<T: AttributeValue + Default>(data: &[T]) -> Self {
Self::direct_from_vec(data.to_vec())
}
#[inline]
pub fn indirect_from_slice<T: AttributeValueHash + Default>(
data: &[T],
cache: &mut AttribValueCache,
) -> Self {
Self::indirect_from_vec(data.to_vec(), cache)
}
fn map(
&self,
direct: impl FnOnce(&DirectData) -> DirectData,
indirect: impl FnOnce(&IndirectData) -> IndirectData,
) -> Self {
self.map_to(
|d| AttributeData::Direct(direct(d)),
|i| AttributeData::Indirect(indirect(i)),
)
}
pub fn map_to<'a, O>(
&'a self,
direct: impl FnOnce(&'a DirectData) -> O,
indirect: impl FnOnce(&'a IndirectData) -> O,
) -> O {
match self {
AttributeData::Direct(data) => direct(data),
AttributeData::Indirect(data) => indirect(data),
}
}
pub fn map_mut_to<'a, O>(
&'a mut self,
direct: impl FnOnce(&'a mut DirectData) -> O,
indirect: impl FnOnce(&'a mut IndirectData) -> O,
) -> O {
match self {
AttributeData::Direct(data) => direct(data),
AttributeData::Indirect(data) => indirect(data),
}
}
#[inline]
pub fn as_slice<T: Any>(&self) -> Result<&[T], Error> {
self.map_to(|d| d.as_slice(), |_| Err(Error::KindMismatchFoundIndirect))
}
#[inline]
pub fn as_mut_slice<T: Any>(&mut self) -> Result<&mut [T], Error> {
self.map_mut_to(
|d| d.as_mut_slice(),
|_| Err(Error::KindMismatchFoundIndirect),
)
}
pub fn duplicate_empty(&self) -> Self {
self.map(|d| d.duplicate_empty(), |i| i.duplicate_empty())
}
pub fn duplicate_with(
&self,
dup_data: impl FnOnce(&mut VecDrop<dyn HasAttributeValue>, SliceDrop<dyn HasAttributeValue>),
) -> Self {
match self {
AttributeData::Direct(d) => AttributeData::Direct(d.duplicate_with(|input| {
let vec_drop = VecDrop::with_type_from(input.reborrow());
let mut vec_dyn = into_dyn![VecDrop<dyn HasAttributeValue>](vec_drop);
dup_data(
&mut vec_dyn,
into_dyn![SliceDrop<dyn HasAttributeValue>](input),
);
vec_dyn
})),
AttributeData::Indirect(i) => AttributeData::Indirect(i.duplicate_with(|input| {
let vec_drop = VecDrop::with_type_from(input.reborrow());
let mut vec_dyn = into_dyn![VecDrop<dyn HasAttributeValue>](vec_drop);
dup_data(
&mut vec_dyn,
into_dyn![SliceDrop<dyn HasAttributeValue>](input),
);
vec_dyn
})),
}
}
pub fn duplicate_with_len(
&self,
len: usize,
init: impl FnOnce(DataSliceMut, DataSlice),
) -> Self {
match self {
AttributeData::Direct(d) => AttributeData::Direct(d.duplicate_with_len(len, init)),
AttributeData::Indirect(i) => AttributeData::Indirect(
i.duplicate_with_len(len, |new, old| init(new.upcast(), old.upcast())),
),
}
}
#[inline]
pub fn check<T: Any>(&self) -> Result<&Self, Error> {
self.map_to(
|d| d.check::<T>().map(|_| self),
|i| i.check::<T>().map(|_| self),
)
}
#[inline]
pub fn check_mut<T: Any>(&mut self) -> Result<&mut Self, Error> {
match self {
AttributeData::Direct(d) => match d.check_mut::<T>() {
Ok(_) => Ok(self),
Err(e) => Err(e),
},
AttributeData::Indirect(i) => match i.check_mut::<T>() {
Ok(_) => Ok(self),
Err(e) => Err(e),
},
}
}
#[inline]
pub fn iter<'a, T: Any>(&'a self) -> Result<Box<dyn Iterator<Item = &'a T> + 'a>, Error> {
self.map_to(
|d| {
d.iter::<T>().map(|iter| {
let b: Box<dyn Iterator<Item = &T>> = Box::new(iter);
b
})
},
|i| {
i.iter::<T>().map(|iter| {
let b: Box<dyn Iterator<Item = &T>> = Box::new(iter);
b
})
},
)
}
#[inline]
pub fn direct_iter<T: Any>(&self) -> Result<slice::Iter<T>, Error> {
self.map_to(|d| d.iter::<T>(), |_| Err(Error::KindMismatchFoundIndirect))
}
#[inline]
pub fn indirect_iter<T: Any>(&self) -> Result<impl Iterator<Item = &T>, Error> {
self.map_to(|_| Err(Error::KindMismatchFoundDirect), |i| i.iter::<T>())
}
#[inline]
pub fn direct_iter_mut<T: Any>(&mut self) -> Result<slice::IterMut<T>, Error> {
self.map_mut_to(
|d| d.iter_mut::<T>(),
|_| Err(Error::KindMismatchFoundIndirect),
)
}
#[inline]
pub fn indirect_update_with<T: AttributeValueHash>(
&mut self,
f: impl FnMut(usize, &Irc<T>) -> Option<Irc<T>>,
cache: &mut AttribValueCache,
) -> Result<&mut Self, Error> {
match self {
AttributeData::Indirect(i) => match i.update_with::<T, _>(f, cache) {
Ok(_) => Ok(self),
Err(e) => Err(e),
},
_ => Err(Error::KindMismatchFoundDirect),
}
}
#[inline]
pub fn element_type_id(&self) -> TypeId {
self.map_to(|d| d.element_type_id(), |i| i.element_type_id())
}
#[inline]
pub fn clone_into_vec<T: AttributeValueHash>(&self) -> Result<Vec<T>, Error> {
self.map_to(|d| d.clone_into_vec::<T>(), |i| i.clone_into_vec::<T>())
}
#[inline]
pub fn direct_clone_into_vec<T: Any + Clone>(&self) -> Result<Vec<T>, Error> {
self.map_to(
|d| d.clone_into_vec::<T>(),
|_| Err(Error::KindMismatchFoundIndirect),
)
}
#[inline]
pub fn len(&self) -> usize {
self.map_to(|d| d.len(), |i| i.len())
}
#[inline]
pub fn is_empty(&self) -> bool {
self.map_to(|d| d.is_empty(), |i| i.is_empty())
}
#[inline]
pub fn data_slice(&self) -> DataSlice {
self.map_to(
|d| d.data_ref().as_slice(),
|i| i.data_ref().as_slice().upcast(),
)
}
#[inline]
pub fn data_mut_slice(&mut self) -> DataSliceMut {
self.map_mut_to(
|d| d.data_mut().as_mut_slice(),
|i| i.data_mut().as_mut_slice().upcast(),
)
}
#[inline]
pub fn indirect_data(&self) -> Result<&IndirectData, Error> {
self.map_to(|_| Err(Error::KindMismatchFoundDirect), Ok)
}
#[inline]
pub fn indirect_data_mut(&mut self) -> Result<&mut IndirectData, Error> {
self.map_mut_to(|_| Err(Error::KindMismatchFoundDirect), Ok)
}
#[inline]
pub fn direct_data(&self) -> Result<&DirectData, Error> {
self.map_to(Ok, |_| Err(Error::KindMismatchFoundDirect))
}
#[inline]
pub fn direct_data_mut(&mut self) -> Result<&mut DirectData, Error> {
self.map_mut_to(Ok, |_| Err(Error::KindMismatchFoundDirect))
}
#[inline]
pub fn into_data(self) -> DataVec {
match self {
AttributeData::Direct(d) => d.into_data(),
AttributeData::Indirect(i) => i.into_data().upcast(),
}
}
#[inline]
pub fn extend_by(&mut self, n: usize) {
self.map_mut_to(|d| d.extend_by(n), |i| i.extend_by(n))
}
#[inline]
pub fn rotate_left(&mut self, mid: usize) {
self.map_mut_to(|d| d.rotate_left(mid), |i| i.rotate_left(mid))
}
#[inline]
pub fn rotate_right(&mut self, k: usize) {
self.map_mut_to(|d| d.rotate_right(k), |i| i.rotate_right(k))
}
#[inline]
pub fn default_element(&self) -> ValueRef {
match self {
AttributeData::Direct(d) => d.default_element(),
AttributeData::Indirect(i) => i.default_element().upcast(),
}
}
}
#[derive(Clone, Debug, PartialEq)]
pub struct Attribute<I> {
pub data: AttributeData,
phantom: PhantomData<I>,
}
impl<I> Attribute<I> {
pub fn direct_with_size<T: AttributeValue>(n: usize, def: T) -> Self {
Attribute {
data: AttributeData::direct_with_size(n, def),
phantom: PhantomData,
}
}
pub fn indirect_with_size<T: AttributeValueHash>(n: usize, def: T) -> Self {
Attribute {
data: AttributeData::indirect_with_size(n, def),
phantom: PhantomData,
}
}
pub fn direct_from_vec<T: AttributeValue + Default>(vec: Vec<T>) -> Self {
Attribute {
data: AttributeData::direct_from_vec(vec),
phantom: PhantomData,
}
}
pub fn indirect_from_vec<T: AttributeValueHash + Default>(
vec: Vec<T>,
cache: &mut AttribValueCache,
) -> Self {
Attribute {
data: AttributeData::indirect_from_vec(vec, cache),
phantom: PhantomData,
}
}
pub fn indirect_from_data(data: IndirectData) -> Self {
Attribute {
data: AttributeData::indirect_from_data(data),
phantom: PhantomData,
}
}
#[inline]
pub fn as_slice<T: Any>(&self) -> Result<&[T], Error> {
self.data.as_slice()
}
#[inline]
pub fn as_mut_slice<T: Any>(&mut self) -> Result<&mut [T], Error> {
self.data.as_mut_slice()
}
#[inline]
pub fn duplicate_empty(&self) -> Self {
self.promote_empty()
}
#[inline]
pub fn duplicate_with(
&self,
duplicate_data: impl FnOnce(
&mut VecDrop<dyn HasAttributeValue>,
SliceDrop<dyn HasAttributeValue>,
),
) -> Self {
self.promote_with(duplicate_data)
}
#[inline]
pub fn duplicate_with_len(
&self,
len: usize,
init: impl FnOnce(DataSliceMut, DataSlice),
) -> Self {
self.promote_with_len(len, init)
}
#[inline]
pub fn promote_empty<J>(&self) -> Attribute<J> {
Attribute {
data: self.data.duplicate_empty(),
phantom: PhantomData,
}
}
#[inline]
pub fn promote_with<J>(
&self,
promote_data: impl FnOnce(&mut VecDrop<dyn HasAttributeValue>, SliceDrop<dyn HasAttributeValue>),
) -> Attribute<J> {
Attribute {
data: self.data.duplicate_with(promote_data),
phantom: PhantomData,
}
}
pub fn promote_with_len<J>(
&self,
len: usize,
init: impl FnOnce(DataSliceMut, DataSlice),
) -> Attribute<J> {
Attribute {
data: self.data.duplicate_with_len(len, init),
phantom: PhantomData,
}
}
#[inline]
pub fn direct_from_slice<T: AttributeValue + Default>(data: &[T]) -> Self {
Self::direct_from_vec(data.to_vec())
}
#[inline]
pub fn indirect_from_slice<T: AttributeValueHash + Default>(
data: &[T],
cache: &mut AttribValueCache,
) -> Self {
Self::indirect_from_vec(data.to_vec(), cache)
}
#[inline]
pub fn check<T: Any>(&self) -> Result<&Self, Error> {
self.data.check::<T>().map(|_| self)
}
#[inline]
pub fn check_mut<T: Any>(&mut self) -> Result<&mut Self, Error> {
match self.data.check_mut::<T>() {
Ok(_) => Ok(self),
Err(e) => Err(e),
}
}
#[inline]
pub fn iter<'a, T: Any>(&'a self) -> Result<Box<dyn Iterator<Item = &'a T> + 'a>, Error> {
self.data.iter::<T>()
}
#[inline]
pub fn direct_iter<T: Any>(&self) -> Result<slice::Iter<T>, Error> {
self.data.direct_iter()
}
#[inline]
pub fn indirect_iter<T: Any>(&self) -> Result<impl Iterator<Item = &T>, Error> {
self.data.indirect_iter()
}
#[inline]
pub fn direct_iter_mut<T: Any>(&mut self) -> Result<slice::IterMut<T>, Error> {
self.data.direct_iter_mut()
}
#[inline]
pub fn indirect_update_with<T, F>(
&mut self,
f: F,
cache: &mut AttribValueCache,
) -> Result<&mut Self, Error>
where
T: AttributeValueHash,
F: FnMut(usize, &Irc<T>) -> Option<Irc<T>>,
{
match self.data.indirect_update_with(f, cache) {
Ok(_) => Ok(self),
Err(e) => Err(e),
}
}
#[inline]
pub fn clone_into_vec<T: AttributeValueHash>(&self) -> Result<Vec<T>, Error> {
self.data.clone_into_vec::<T>()
}
#[inline]
pub fn direct_clone_into_vec<T: Any + Clone>(&self) -> Result<Vec<T>, Error> {
self.data.direct_clone_into_vec::<T>()
}
#[inline]
pub fn len(&self) -> usize {
self.data.len()
}
#[inline]
pub fn is_empty(&self) -> bool {
self.data.is_empty()
}
#[inline]
pub fn data_slice(&self) -> DataSlice {
self.data.data_slice()
}
#[inline]
pub fn data_mut_slice(&mut self) -> DataSliceMut {
self.data.data_mut_slice()
}
#[inline]
pub fn into_data(self) -> DataVec {
self.data.into_data()
}
#[inline]
pub fn extend_by(&mut self, n: usize) {
self.data.extend_by(n);
}
#[inline]
pub fn rotate_left(&mut self, mid: usize) {
self.data.rotate_left(mid);
}
#[inline]
pub fn rotate_right(&mut self, k: usize) {
self.data.rotate_right(k);
}
#[inline]
pub fn default_element(&self) -> ValueRef {
self.data.default_element()
}
}
macro_rules! impl_attribute_get {
($type:ty) => {
impl Attribute<$type> {
#[inline]
pub fn get<T: Any + Copy, I: Into<$type>>(&self, i: I) -> Result<T, Error> {
let element_id = self.data.element_type_id();
Index::from(i.into())
.map_or(None, move |x| {
self.data
.map_to(
|d| d.as_slice().map(|s| s[x]),
|i| i.as_rc_slice().map(|s| *s[x]),
)
.ok()
})
.ok_or(Error::type_mismatch_id::<T>(element_id))
}
#[inline]
pub fn get_ref<T: Any, I: Into<$type>>(&self, i: I) -> Result<&T, Error> {
let element_id = self.data.element_type_id();
Index::from(i.into())
.map_or(None, move |x| {
self.data
.map_to(
|d| d.as_slice().map(|s| &s[x]),
|i| i.as_rc_slice().map(|s| &*s[x]),
)
.ok()
})
.ok_or(Error::type_mismatch_id::<T>(element_id))
}
#[inline]
pub fn get_mut<T: Any, I: Into<$type>>(&mut self, i: I) -> Result<&mut T, Error> {
let element_id = self.data.element_type_id();
Index::from(i.into())
.map_or(None, move |x| {
self.data
.map_mut_to(
|d| d.as_mut_slice().map(|s| &mut s[x]),
|_| Err(Error::KindMismatchFoundIndirect),
)
.ok()
})
.ok_or(Error::type_mismatch_id::<T>(element_id))
}
}
};
}
impl_attribute_get!(MeshIndex);
impl_attribute_get!(VertexIndex);
impl_attribute_get!(EdgeIndex);
impl_attribute_get!(FaceIndex);
impl_attribute_get!(CellIndex);
impl_attribute_get!(EdgeVertexIndex);
impl_attribute_get!(FaceVertexIndex);
impl_attribute_get!(FaceEdgeIndex);
impl_attribute_get!(CellVertexIndex);
impl_attribute_get!(CellEdgeIndex);
impl_attribute_get!(CellFaceIndex);
impl_attribute_get!(VertexEdgeIndex);
impl_attribute_get!(VertexFaceIndex);
impl_attribute_get!(VertexCellIndex);
impl_attribute_get!(EdgeFaceIndex);
impl_attribute_get!(EdgeCellIndex);
impl_attribute_get!(FaceCellIndex);
#[derive(Clone, Debug, PartialEq)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
pub struct IntrinsicAttribute<T, I> {
data: Vec<T>,
phantom: PhantomData<I>,
}
impl<T, I> IntrinsicAttribute<T, I> {
pub fn with_size(n: usize, def: T) -> Self
where
T: Clone,
{
IntrinsicAttribute {
data: vec![def; n],
phantom: PhantomData,
}
}
pub fn from_vec(vec: Vec<T>) -> Self {
IntrinsicAttribute {
data: vec,
phantom: PhantomData,
}
}
#[inline]
pub fn from_slice(data: &[T]) -> Self
where
T: Clone,
{
Self::from_vec(data.to_vec())
}
#[inline]
pub fn as_slice(&self) -> &[T] {
self.data.as_slice()
}
#[inline]
pub fn as_mut_slice(&mut self) -> &mut [T] {
self.data.as_mut_slice()
}
#[inline]
pub fn into_vec(self) -> Vec<T> {
self.data
}
#[inline]
pub fn as_mut_vec(&mut self) -> &mut Vec<T> {
&mut self.data
}
#[inline]
pub fn clone_into_vec(&self) -> Vec<T>
where
T: Clone,
{
self.data.clone()
}
#[inline]
pub fn copy_into_vec(&self) -> Vec<T>
where
T: Copy,
{
let mut vec = Vec::with_capacity(self.len());
vec.extend(self.as_slice());
vec
}
#[inline]
pub fn iter(&self) -> slice::Iter<T> {
self.data.iter()
}
#[cfg(feature = "rayon")]
#[inline]
pub fn par_iter(&self) -> rayon::slice::Iter<T>
where
T: Sync,
{
use rayon::iter::IntoParallelRefIterator;
self.data.par_iter()
}
#[inline]
pub fn iter_mut(&mut self) -> slice::IterMut<T> {
self.data.iter_mut()
}
#[cfg(feature = "rayon")]
#[inline]
pub fn par_iter_mut(&mut self) -> rayon::slice::IterMut<T>
where
T: Sync + Send,
{
use rayon::iter::IntoParallelRefMutIterator;
self.data.par_iter_mut()
}
#[inline]
pub fn len(&self) -> usize {
self.data.len()
}
#[inline]
pub fn is_empty(&self) -> bool {
self.data.is_empty()
}
}
impl<T, I> From<Vec<T>> for IntrinsicAttribute<T, I> {
#[inline]
fn from(vec: Vec<T>) -> Self {
Self::from_vec(vec)
}
}
impl<T, I> Into<Vec<T>> for IntrinsicAttribute<T, I> {
#[inline]
fn into(self) -> Vec<T> {
self.into_vec()
}
}
impl<T, I: Into<usize>, J: Into<I>> std::ops::Index<J> for IntrinsicAttribute<T, I> {
type Output = T;
fn index(&self, index: J) -> &T {
&self.data[index.into().into()]
}
}
impl<T, I: Into<usize>, J: Into<I>> std::ops::IndexMut<J> for IntrinsicAttribute<T, I> {
fn index_mut(&mut self, index: J) -> &mut T {
&mut self.data[index.into().into()]
}
}
impl<T, I> std::iter::IntoIterator for IntrinsicAttribute<T, I> {
type Item = T;
type IntoIter = std::vec::IntoIter<T>;
fn into_iter(self) -> Self::IntoIter {
self.into_vec().into_iter()
}
}
impl<T, I> std::iter::FromIterator<T> for IntrinsicAttribute<T, I> {
fn from_iter<J>(iter: J) -> Self
where
J: IntoIterator<Item = T>,
{
Self::from_vec(Vec::from_iter(iter))
}
}
#[cfg(feature = "rayon")]
impl<T: Send, I> rayon::iter::IntoParallelIterator for IntrinsicAttribute<T, I> {
type Item = T;
type Iter = rayon::vec::IntoIter<T>;
fn into_par_iter(self) -> Self::Iter {
self.into_vec().into_par_iter()
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn indirect_set_value_at() {
let mut cache = AttribValueCache::default();
let mut data = IndirectData::with_size(3, String::from("default"));
let val = HValue::new(Irc::new(String::from("default")));
assert_eq!(&data.default_element, &val);
data.set_at(1, String::from("default"), &mut cache).unwrap();
assert!(cache.is_empty());
data.set_at(1, String::from("New Value"), &mut cache)
.unwrap();
assert_eq!(cache.len(), 1);
}
}