cranpose-core 0.1.164

Core runtime for a Jetpack Compose inspired UI framework in Rust
Documentation
use smallvec::SmallVec;

use super::super::GroupKey;
use crate::{
    Key,
    collections::map::{HashMap, HashSet},
};

const INLINE_KEY_STATE_CAPACITY: usize = 8;

#[derive(Default)]
pub(in crate::slot) struct FrameKeyState {
    ordinal_entries: SmallVec<[(Key, u32); INLINE_KEY_STATE_CAPACITY]>,
    ordinal_map: Option<HashMap<Key, u32>>,
    seen_entries: SmallVec<[GroupKey; INLINE_KEY_STATE_CAPACITY]>,
    seen_set: Option<HashSet<GroupKey>>,
}

impl FrameKeyState {
    pub(in crate::slot) fn clear(&mut self) {
        self.ordinal_entries.clear();
        if let Some(map) = &mut self.ordinal_map {
            map.clear();
        }
        self.seen_entries.clear();
        if let Some(set) = &mut self.seen_set {
            set.clear();
        }
    }

    pub(in crate::slot) fn expected_ordinal(&self, key: Key) -> u32 {
        if let Some(map) = &self.ordinal_map {
            return map.get(&key).copied().unwrap_or(0);
        }
        self.ordinal_entries
            .iter()
            .find_map(|(entry_key, ordinal)| (*entry_key == key).then_some(*ordinal))
            .unwrap_or(0)
    }

    pub(in crate::slot) fn next_ordinal(&mut self, key: Key) -> u32 {
        if let Some(map) = &mut self.ordinal_map {
            let ordinal = map.get(&key).copied().unwrap_or(0);
            map.insert(key, ordinal + 1);
            return ordinal;
        }

        if let Some((_, ordinal)) = self
            .ordinal_entries
            .iter_mut()
            .find(|(entry_key, _)| *entry_key == key)
        {
            let current = *ordinal;
            *ordinal += 1;
            return current;
        }

        if self.ordinal_entries.len() < INLINE_KEY_STATE_CAPACITY {
            self.ordinal_entries.push((key, 1));
            return 0;
        }

        let map = self.promote_ordinals();
        map.insert(key, 1);
        0
    }

    pub(in crate::slot) fn insert_seen(&mut self, key: GroupKey) -> bool {
        if let Some(set) = &mut self.seen_set {
            return set.insert(key);
        }

        if self.seen_entries.contains(&key) {
            return false;
        }

        if self.seen_entries.len() < INLINE_KEY_STATE_CAPACITY {
            self.seen_entries.push(key);
            return true;
        }

        self.promote_seen().insert(key)
    }

    fn promote_ordinals(&mut self) -> &mut HashMap<Key, u32> {
        let mut map = HashMap::default();
        map.reserve(self.ordinal_entries.len() * 2);
        for (key, ordinal) in self.ordinal_entries.drain(..) {
            map.insert(key, ordinal);
        }
        self.ordinal_map.insert(map)
    }

    fn promote_seen(&mut self) -> &mut HashSet<GroupKey> {
        let mut set = HashSet::default();
        set.reserve(self.seen_entries.len() * 2);
        for key in self.seen_entries.drain(..) {
            set.insert(key);
        }
        self.seen_set.insert(set)
    }

    #[cfg(test)]
    fn ordinals_are_promoted(&self) -> bool {
        self.ordinal_map.is_some()
    }

    #[cfg(test)]
    fn seen_is_promoted(&self) -> bool {
        self.seen_set.is_some()
    }
}

#[cfg(test)]
#[path = "tests/key_state_tests.rs"]
mod tests;