flash_lso/amf3/
element_cache.rs

1use crate::amf3::length::Length;
2use std::cell::RefCell;
3use std::fmt::Debug;
4
5/// Abstraction over the Amf3 caching mechanism
6#[derive(Clone, Debug)]
7pub struct ElementCache<T> {
8    cache: RefCell<Vec<T>>,
9}
10
11impl<T> Default for ElementCache<T> {
12    /// Create a new ElementCache
13    fn default() -> Self {
14        ElementCache {
15            cache: RefCell::new(Vec::new()),
16        }
17    }
18}
19
20impl<T: PartialEq + Clone + Debug> ElementCache<T> {
21    /// Check if the cache contains a given element
22    #[inline]
23    pub(crate) fn has(&self, val: &T) -> bool {
24        self.cache.borrow().contains(val)
25    }
26
27    /// Add the given item to the cache, if the item already exists will do nothing
28    #[inline]
29    pub(crate) fn store(&self, val: T) {
30        if !self.has(&val) {
31            self.cache.borrow_mut().push(val);
32        }
33    }
34
35    /// Retrieve the item at the given index from the cache
36    #[inline]
37    pub fn get_element(&self, index: usize) -> Option<T> {
38        self.cache.borrow().get(index).cloned()
39    }
40
41    /// Retrieve the index for the given value
42    #[inline]
43    pub(crate) fn get_index(&self, val: T) -> Option<usize> {
44        self.cache.borrow().iter().position(|i| *i == val)
45    }
46
47    /// Get a Length reference to an item in the cache
48    /// If the item exists, will return a `Length::Reference` to the item
49    /// If the item does not exist, will return the given size as `Length::Size`
50    pub(crate) fn to_length(&self, val: T, length: u32) -> Length {
51        if let Some(i) = self.get_index(val) {
52            Length::Reference(i)
53        } else {
54            Length::Size(length)
55        }
56    }
57
58    /// See #to_length, except will store the given value via #add after retrieving the index (if it does not already exist)
59    pub(crate) fn to_length_store(&self, val: T, length: u32) -> Length {
60        let len = self.to_length(val.clone(), length);
61        self.store(val);
62        len
63    }
64}
65
66impl<T: PartialEq + Clone + Debug> ElementCache<Vec<T>> {
67    /// See #store, will convert slices of &[T] into Vec<T> before storing
68    #[inline]
69    pub(crate) fn store_slice(&self, val: &[T]) {
70        self.store(val.to_vec());
71    }
72
73    /// See #get_index, will convert slices of &[T] into Vec<T> before retrieving
74    #[inline]
75    pub fn get_slice_index(&self, val: &[T]) -> Option<usize> {
76        self.get_index(val.to_vec())
77    }
78}