Skip to main content

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    /// FIXME - this is currently unused, since our implementation is incorrect (we need to compare 'Rc's by pointer,
60    /// to avoid combining two distinct objects into the same reference).
61    #[allow(unused)]
62    pub(crate) fn to_length_store(&self, val: T, length: u32) -> Length {
63        let len = self.to_length(val.clone(), length);
64        self.store(val);
65        len
66    }
67}
68
69impl<T: PartialEq + Clone + Debug> ElementCache<Vec<T>> {
70    /// See #store, will convert slices of &\[T\] into Vec<T> before storing
71    #[inline]
72    #[allow(unused)]
73    pub(crate) fn store_slice(&self, val: &[T]) {
74        self.store(val.to_vec());
75    }
76
77    /// See #get_index, will convert slices of &\[T\] into Vec<T> before retrieving
78    #[inline]
79    pub fn get_slice_index(&self, val: &[T]) -> Option<usize> {
80        self.get_index(val.to_vec())
81    }
82}