#![allow(unused)]
use crate::prelude::*;
use vizia_storage::{SparseSetGeneric, SparseSetIndex};
const INDEX_MASK: u32 = u32::MAX / 4;
const INLINE_MASK: u32 = 1 << 31;
const INHERITED_MASK: u32 = 1 << 30;
#[derive(Debug, Clone, Copy, PartialEq)]
struct DataIndex(u32);
impl DataIndex {
pub fn inline(index: usize) -> Self {
assert!((index as u32) < INDEX_MASK);
let value = (index as u32) | INLINE_MASK;
Self(value)
}
pub fn inherited(self) -> Self {
let value = self.0;
Self(value | INHERITED_MASK)
}
pub fn shared(index: usize) -> Self {
assert!((index as u32) < INDEX_MASK);
Self(index as u32)
}
pub fn index(&self) -> usize {
(self.0 & INDEX_MASK) as usize
}
pub fn is_inline(&self) -> bool {
(self.0 & INLINE_MASK).rotate_left(1) != 0
}
pub fn is_inherited(&self) -> bool {
(self.0 & INHERITED_MASK).rotate_left(2) != 0
}
pub fn null() -> Self {
Self(u32::MAX >> 1)
}
}
#[derive(Debug, Clone, Copy, PartialEq)]
struct Index {
data_index: DataIndex,
anim_index: u32,
}
impl Default for Index {
fn default() -> Self {
Index { data_index: DataIndex::null(), anim_index: u32::MAX }
}
}
impl SparseSetIndex for Index {
fn new(index: usize) -> Self {
Index { data_index: DataIndex::inline(index), anim_index: u32::MAX }
}
fn null() -> Self {
Self::default()
}
fn index(&self) -> usize {
self.data_index.index()
}
}
pub struct StyleSet<T> {
shared_data: SparseSetGeneric<Index, T>,
inline_data: SparseSetGeneric<Index, T>,
}
impl<T> Default for StyleSet<T> {
fn default() -> Self {
Self { shared_data: Default::default(), inline_data: Default::default() }
}
}
impl<T> StyleSet<T>
where
T: 'static + std::fmt::Debug,
{
pub fn new() -> Self {
Self::default()
}
pub fn insert(&mut self, entity: Entity, value: T) {
self.inline_data.insert(entity, value);
}
pub fn remove(&mut self, entity: Entity) -> Option<T> {
let entity_index = entity.index();
if entity_index < self.inline_data.sparse.len() {
let data_index = self.inline_data.sparse[entity_index].data_index;
if data_index.is_inline() && !data_index.is_inherited() {
self.inline_data.remove(entity)
} else {
self.inline_data.sparse[entity_index] = Index::null();
None
}
} else {
None
}
}
pub fn inherit_inline(&mut self, entity: Entity, parent: Entity) -> bool {
let entity_index = entity.index();
let parent_index = parent.index();
if parent_index < self.inline_data.sparse.len() {
let parent_sparse_index = self.inline_data.sparse[parent_index];
if parent_sparse_index.data_index.is_inline()
&& parent_sparse_index.data_index.index() < self.inline_data.dense.len()
{
if entity_index >= self.inline_data.sparse.len() {
self.inline_data.sparse.resize(entity_index + 1, Index::null());
}
let entity_sparse_index = self.inline_data.sparse[entity_index];
if self.inline_data.sparse[entity_index].data_index.index()
!= parent_sparse_index.data_index.index()
{
if entity_sparse_index.data_index.index() < self.inline_data.dense.len() {
if entity_sparse_index.data_index.is_inherited()
&& entity_sparse_index.data_index.is_inline()
{
self.inline_data.sparse[entity_index] = Index {
data_index: DataIndex::inline(
parent_sparse_index.data_index.index(),
)
.inherited(),
anim_index: u32::MAX,
};
return true;
}
} else {
self.inline_data.sparse[entity_index] = Index {
data_index: DataIndex::inline(parent_sparse_index.data_index.index())
.inherited(),
anim_index: u32::MAX,
};
return true;
}
}
}
}
false
}
pub fn inherit_shared(&mut self, entity: Entity, parent: Entity) -> bool {
let entity_index = entity.index();
let parent_index = parent.index();
if parent_index < self.inline_data.sparse.len() {
let parent_sparse_index = self.inline_data.sparse[parent_index];
if !parent_sparse_index.data_index.is_inline()
&& parent_sparse_index.data_index.index() < self.shared_data.dense.len()
{
if entity_index >= self.inline_data.sparse.len() {
self.inline_data.sparse.resize(entity_index + 1, Index::null());
}
let entity_sparse_index = self.inline_data.sparse[entity_index];
if !entity_sparse_index.data_index.is_inline()
&& self.inline_data.sparse[entity_index].data_index.index()
!= parent_sparse_index.data_index.index()
{
if entity_sparse_index.data_index.index() < self.shared_data.dense.len() {
if entity_sparse_index.data_index.is_inherited() {
self.inline_data.sparse[entity_index] = Index {
data_index: DataIndex::shared(
parent_sparse_index.data_index.index(),
)
.inherited(),
anim_index: u32::MAX,
};
return true;
}
} else {
self.inline_data.sparse[entity_index] = Index {
data_index: DataIndex::shared(parent_sparse_index.data_index.index())
.inherited(),
anim_index: u32::MAX,
};
return true;
}
}
}
}
false
}
pub fn clear_rules(&mut self) {
for _index in self.shared_data.sparse.iter() {
}
self.shared_data.clear();
for index in self.inline_data.sparse.iter_mut() {
if !index.data_index.is_inline() {
index.data_index = DataIndex::null();
}
}
}
pub(crate) fn insert_rule(&mut self, rule: Rule, value: T) {
self.shared_data.insert(rule, value);
}
pub fn get_inline(&self, entity: Entity) -> Option<&T> {
let entity_index = entity.index();
if entity_index < self.inline_data.sparse.len() {
let data_index = self.inline_data.sparse[entity_index].data_index;
if data_index.is_inline() {
return self.inline_data.get(entity);
}
}
None
}
pub fn get_inline_mut(&mut self, entity: Entity) -> Option<&mut T> {
let entity_index = entity.index();
if entity_index < self.inline_data.sparse.len() {
let data_index = self.inline_data.sparse[entity_index].data_index;
if data_index.is_inline() {
return self.inline_data.get_mut(entity);
}
}
None
}
pub fn get(&self, entity: Entity) -> Option<&T> {
let entity_index = entity.index();
if entity_index < self.inline_data.sparse.len() {
let data_index = self.inline_data.sparse[entity_index].data_index;
if data_index.is_inline() {
if data_index.index() < self.inline_data.dense.len() {
return Some(&self.inline_data.dense[data_index.index()].value);
}
} else if data_index.index() < self.shared_data.dense.len() {
return Some(&self.shared_data.dense[data_index.index()].value);
}
}
None
}
pub fn get_mut(&mut self, entity: Entity) -> Option<&mut T> {
let entity_index = entity.index();
if entity_index < self.inline_data.sparse.len() {
let data_index = self.inline_data.sparse[entity_index].data_index;
if data_index.is_inline() && data_index.index() < self.inline_data.dense.len() {
return Some(&mut self.inline_data.dense[data_index.index()].value);
}
}
None
}
pub(crate) fn link(&mut self, entity: Entity, rules: &[(Rule, u32)]) -> bool {
let entity_index = entity.index();
if entity_index < self.inline_data.sparse.len() {
let data_index = self.inline_data.sparse[entity_index].data_index;
if data_index.is_inline() && !data_index.is_inherited() {
return false;
}
}
for (rule, _) in rules {
if let Some(shared_data_index) = self.shared_data.dense_idx(*rule) {
if entity_index >= self.inline_data.sparse.len() {
self.inline_data.sparse.resize(entity_index + 1, Index::null());
}
let data_index = self.inline_data.sparse[entity_index].data_index;
if !data_index.is_inline() && data_index.index() == shared_data_index.index() {
return false;
}
self.inline_data.sparse[entity_index].data_index =
DataIndex::shared(shared_data_index.index());
return true;
}
}
if entity_index < self.inline_data.sparse.len() {
let data_index = self.inline_data.sparse[entity_index].data_index;
if !data_index.is_inline()
&& !data_index.is_inherited()
&& self.inline_data.sparse[entity_index].data_index != DataIndex::null()
{
self.inline_data.sparse[entity_index].data_index = DataIndex::null();
return true;
}
}
false
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn inline() {
let data_index = DataIndex::inline(5);
assert_eq!(data_index.0, INLINE_MASK + 5);
assert_eq!(data_index.index(), 5);
}
#[test]
#[should_panic]
fn invalid_inline() {
DataIndex::inline(usize::MAX);
}
#[test]
fn shared() {
let data_index = DataIndex::shared(5);
assert_eq!(data_index.0, 5);
assert_eq!(data_index.index(), 5);
}
#[test]
#[should_panic]
fn invalid_shared() {
DataIndex::shared(usize::MAX);
}
#[test]
fn is_inline() {
let data_index1 = DataIndex::inline(5);
assert!(data_index1.is_inline());
let data_index2 = DataIndex::shared(5);
assert!(!data_index2.is_inline());
}
#[test]
fn null() {
let data_index = DataIndex::null();
assert_eq!(data_index.0, 2147483647);
}
#[test]
fn new() {
let animatable_storage = StyleSet::<f32>::new();
assert!(animatable_storage.inline_data.is_empty());
assert!(animatable_storage.shared_data.is_empty());
}
#[test]
fn insert_inline() {
let mut animatable_storage = StyleSet::new();
animatable_storage.insert(Entity::root(), 5.0);
}
}