зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1493435 - Upgrade to uluru 0.3. r=nox,emilio
This cherry-picks servo/servo#21789.
This commit is contained in:
Родитель
e049a50395
Коммит
9a8bd3b5d7
|
@ -2137,7 +2137,7 @@ dependencies = [
|
|||
"thin-slice 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"time 0.1.40 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"toml 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"uluru 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"uluru 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"unicode-bidi 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"unicode-segmentation 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"void 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
|
@ -2502,7 +2502,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||
|
||||
[[package]]
|
||||
name = "uluru"
|
||||
version = "0.2.0"
|
||||
version = "0.3.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"arrayvec 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
|
@ -3053,7 +3053,7 @@ dependencies = [
|
|||
"checksum toml 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)" = "a7540f4ffc193e0d3c94121edb19b055670d369f77d5804db11ae053a45b6e7e"
|
||||
"checksum try-lock 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "e604eb7b43c06650e854be16a2a03155743d3752dd1c943f6829e26b7a36e382"
|
||||
"checksum ucd-util 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "fd2be2d6639d0f8fe6cdda291ad456e23629558d466e2789d2c3e9892bda285d"
|
||||
"checksum uluru 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "519130f0ea964ba540a9d8af1373738c2226f1d465eda07e61db29feb5479db9"
|
||||
"checksum uluru 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d2606e9192f308ddc4f0b3c5d1bf3400e28a70fff956e9d9f46d23b094746d9f"
|
||||
"checksum unicode-bidi 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)" = "49f2bd0c6468a8230e1db229cff8029217cf623c767ea5d60bfbd42729ea54d5"
|
||||
"checksum unicode-normalization 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "51ccda9ef9efa3f7ef5d91e8f9b83bbe6955f9bf86aec89d5cce2c874625920f"
|
||||
"checksum unicode-segmentation 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "aa6024fc12ddfd1c6dbc14a80fa2324d4568849869b779f6bd37e5e4c03344d1"
|
||||
|
|
|
@ -70,7 +70,7 @@ style_traits = {path = "../style_traits"}
|
|||
servo_url = {path = "../url", optional = true}
|
||||
thin-slice = "0.1.0"
|
||||
time = "0.1"
|
||||
uluru = "0.2"
|
||||
uluru = "0.3"
|
||||
unicode-bidi = "0.3"
|
||||
unicode-segmentation = "1.0"
|
||||
void = "1.0.2"
|
||||
|
|
|
@ -1 +1 @@
|
|||
{"files":{"Cargo.toml":"7c10953d660c87fe16c4bf1936007deadebe6832ff81adadb962acf1a87c5432","LICENSE":"3db78572e8657cca9e9446ce56a057b8a981eb41af318c49a5fe08e7a10fa52a","README.md":"de12b77db6f2e0a9e8c3d0c16dc0e23e3d97d7b93010d522552339f619a5e4c1","lib.rs":"125207560eb1b29d06869e7c24da2daba6c19a5c51d33c2377e710de4fb553b0","tests.rs":"3bc80e05bdc7b95fc4443f0b2face27c9ce36a16ee697183328d441c82c7a951"},"package":"519130f0ea964ba540a9d8af1373738c2226f1d465eda07e61db29feb5479db9"}
|
||||
{"files":{".cargo_vcs_info.json":"bd4e94a467fbc1c26612dc6dada6298fe1ec73663b47810797b1492de7ed520c","Cargo.toml":"7040d9d576e67a8c86293a132992390b64adc5380917abce864dd9d8f3df7b06","LICENSE":"3db78572e8657cca9e9446ce56a057b8a981eb41af318c49a5fe08e7a10fa52a","README.md":"e918fd4e18659a1d4438ca8f198f979cfdd7a9d27dc8e16f65bcf198c2f3d1cd","lib.rs":"4393ac1bd1d1d41bdcf21901d2aee31187232f95af273dead63913a2fc195b51","tests.rs":"056ea5bd7bd7793107c057cb1600ba831400c29be8938df41a3f9ac8d92fccfd"},"package":"d2606e9192f308ddc4f0b3c5d1bf3400e28a70fff956e9d9f46d23b094746d9f"}
|
|
@ -0,0 +1,5 @@
|
|||
{
|
||||
"git": {
|
||||
"sha1": "feb5fbafe004a3483d99669775bffc4d4b99ce3f"
|
||||
}
|
||||
}
|
|
@ -12,7 +12,7 @@
|
|||
|
||||
[package]
|
||||
name = "uluru"
|
||||
version = "0.2.0"
|
||||
version = "0.3.0"
|
||||
authors = ["The Servo Project Developers"]
|
||||
description = "A simple, fast, LRU cache implementation"
|
||||
readme = "README.md"
|
||||
|
|
|
@ -1,3 +1,12 @@
|
|||
# uluru
|
||||
|
||||
A simple, fast, least-recently-used (LRU) cache implementation used for Servo's style system.
|
||||
A simple, fast, least-recently-used (LRU) cache implementation used for
|
||||
Servo's style system.
|
||||
|
||||
`LRUCache` uses a fixed-capacity array for storage. It provides `O(1)`
|
||||
insertion, and `O(n)` lookup. It does not require an allocator and can be
|
||||
used in `no_std` crates.
|
||||
|
||||
* [Documentation](https://docs.rs/uluru)
|
||||
* [crates.io](https://crates.io/crates/uluru)
|
||||
* [Release notes](https://github.com/servo/uluru/releases)
|
||||
|
|
|
@ -4,7 +4,12 @@
|
|||
|
||||
#![no_std]
|
||||
|
||||
//! A simple least-recently-used (LRU) cache.
|
||||
//! A simple, fast, least-recently-used (LRU) cache.
|
||||
//!
|
||||
//! `LRUCache` uses a fixed-capacity array for storage. It provides `O(1)` insertion, and `O(n)`
|
||||
//! lookup. It does not require an allocator and can be used in `no_std` crates.
|
||||
//!
|
||||
//! See the [`LRUCache`](LRUCache) docs for details.
|
||||
|
||||
extern crate arrayvec;
|
||||
|
||||
|
@ -20,6 +25,37 @@ use arrayvec::{Array, ArrayVec};
|
|||
/// All items are stored inline within the `LRUCache`, so it does not impose any heap allocation or
|
||||
/// indirection. A linked list is used to record the cache order, so the items themselves do not
|
||||
/// need to be moved when the order changes. (This is important for speed if the items are large.)
|
||||
///
|
||||
/// # Example
|
||||
///
|
||||
/// ```
|
||||
/// use uluru::{LRUCache, Entry};
|
||||
///
|
||||
/// struct MyValue {
|
||||
/// id: u32,
|
||||
/// name: &'static str,
|
||||
/// }
|
||||
///
|
||||
/// // A cache with a capacity of three.
|
||||
/// type MyCache = LRUCache<[Entry<MyValue>; 3]>;
|
||||
///
|
||||
/// // Create an empty cache, then insert some items.
|
||||
/// let mut cache = MyCache::default();
|
||||
/// cache.insert(MyValue { id: 1, name: "Mercury" });
|
||||
/// cache.insert(MyValue { id: 2, name: "Venus" });
|
||||
/// cache.insert(MyValue { id: 3, name: "Earth" });
|
||||
///
|
||||
/// {
|
||||
/// // Use the `find` method to retrieve an item from the cache.
|
||||
/// // This also "touches" the item, marking it most-recently-used.
|
||||
/// let item = cache.find(|x| x.id == 1);
|
||||
/// assert_eq!(item.unwrap().name, "Mercury");
|
||||
/// }
|
||||
///
|
||||
/// // If the cache is full, inserting a new item evicts the least-recently-used item:
|
||||
/// cache.insert(MyValue { id: 4, name: "Mars" });
|
||||
/// assert!(cache.find(|x| x.id == 2).is_none());
|
||||
/// ```
|
||||
pub struct LRUCache<A: Array> {
|
||||
/// The most-recently-used entry is at index `head`. The entries form a linked list, linked to
|
||||
/// each other by indices within the `entries` array. After an entry is added to the array,
|
||||
|
@ -31,9 +67,6 @@ pub struct LRUCache<A: Array> {
|
|||
tail: u16,
|
||||
}
|
||||
|
||||
/// An opaque token used as an index into an LRUCache.
|
||||
pub struct CacheIndex(u16);
|
||||
|
||||
/// An entry in an LRUCache.
|
||||
pub struct Entry<T> {
|
||||
val: T,
|
||||
|
@ -63,10 +96,10 @@ impl<T, A: Array<Item=Entry<T>>> LRUCache<A> {
|
|||
|
||||
#[inline]
|
||||
/// Touch a given entry, putting it first in the list.
|
||||
pub fn touch(&mut self, idx: CacheIndex) {
|
||||
if idx.0 != self.head {
|
||||
self.remove(idx.0);
|
||||
self.push_front(idx.0);
|
||||
fn touch(&mut self, idx: u16) {
|
||||
if idx != self.head {
|
||||
self.remove(idx);
|
||||
self.push_front(idx);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -80,18 +113,8 @@ impl<T, A: Array<Item=Entry<T>>> LRUCache<A> {
|
|||
self.entries.get_mut(self.head as usize).map(|e| &mut e.val)
|
||||
}
|
||||
|
||||
/// Iterate over the contents of this cache, from more to less recently
|
||||
/// used.
|
||||
pub fn iter(&self) -> LRUCacheIterator<A> {
|
||||
LRUCacheIterator {
|
||||
pos: self.head,
|
||||
done: self.entries.len() == 0,
|
||||
cache: self,
|
||||
}
|
||||
}
|
||||
|
||||
/// Iterate mutably over the contents of this cache.
|
||||
pub fn iter_mut(&mut self) -> LRUCacheMutIterator<A> {
|
||||
fn iter_mut(&mut self) -> LRUCacheMutIterator<A> {
|
||||
LRUCacheMutIterator {
|
||||
pos: self.head,
|
||||
done: self.entries.len() == 0,
|
||||
|
@ -204,36 +227,8 @@ impl<T, A: Array<Item=Entry<T>>> LRUCache<A> {
|
|||
}
|
||||
}
|
||||
|
||||
/// Immutable iterator over values in an LRUCache, from most-recently-used to least-recently-used.
|
||||
pub struct LRUCacheIterator<'a, A: 'a + Array> {
|
||||
cache: &'a LRUCache<A>,
|
||||
pos: u16,
|
||||
done: bool,
|
||||
}
|
||||
|
||||
impl<'a, T, A> Iterator for LRUCacheIterator<'a, A>
|
||||
where T: 'a,
|
||||
A: 'a + Array<Item=Entry<T>>
|
||||
{
|
||||
type Item = (CacheIndex, &'a T);
|
||||
|
||||
fn next(&mut self) -> Option<Self::Item> {
|
||||
if self.done { return None }
|
||||
|
||||
let entry = &self.cache.entries[self.pos as usize];
|
||||
|
||||
let index = CacheIndex(self.pos);
|
||||
if self.pos == self.cache.tail {
|
||||
self.done = true;
|
||||
}
|
||||
self.pos = entry.next;
|
||||
|
||||
Some((index, &entry.val))
|
||||
}
|
||||
}
|
||||
|
||||
/// Mutable iterator over values in an LRUCache, from most-recently-used to least-recently-used.
|
||||
pub struct LRUCacheMutIterator<'a, A: 'a + Array> {
|
||||
struct LRUCacheMutIterator<'a, A: 'a + Array> {
|
||||
cache: &'a mut LRUCache<A>,
|
||||
pos: u16,
|
||||
done: bool,
|
||||
|
@ -243,7 +238,7 @@ impl<'a, T, A> Iterator for LRUCacheMutIterator<'a, A>
|
|||
where T: 'a,
|
||||
A: 'a + Array<Item=Entry<T>>
|
||||
{
|
||||
type Item = (CacheIndex, &'a mut T);
|
||||
type Item = (u16, &'a mut T);
|
||||
|
||||
fn next(&mut self) -> Option<Self::Item> {
|
||||
if self.done { return None }
|
||||
|
@ -253,7 +248,7 @@ where T: 'a,
|
|||
&mut *(&mut self.cache.entries[self.pos as usize] as *mut Entry<T>)
|
||||
};
|
||||
|
||||
let index = CacheIndex(self.pos);
|
||||
let index = self.pos;
|
||||
if self.pos == self.cache.tail {
|
||||
self.done = true;
|
||||
}
|
||||
|
|
|
@ -6,19 +6,19 @@ use super::*;
|
|||
type TestCache = LRUCache<[Entry<i32>; 4]>;
|
||||
|
||||
/// Convenience function for test assertions
|
||||
fn items<T, A>(cache: &LRUCache<A>) -> Vec<T>
|
||||
fn items<T, A>(cache: &mut LRUCache<A>) -> Vec<T>
|
||||
where
|
||||
T: Clone,
|
||||
A: Array<Item=Entry<T>>
|
||||
{
|
||||
cache.iter().map(|(_, x)| x.clone()).collect()
|
||||
cache.iter_mut().map(|(_, x)| x.clone()).collect()
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn empty() {
|
||||
let cache = TestCache::default();
|
||||
let mut cache = TestCache::default();
|
||||
assert_eq!(cache.num_entries(), 0);
|
||||
assert_eq!(items(&cache), []);
|
||||
assert_eq!(items(&mut cache), []);
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
@ -32,17 +32,17 @@ fn insert() {
|
|||
assert_eq!(cache.num_entries(), 3);
|
||||
cache.insert(4);
|
||||
assert_eq!(cache.num_entries(), 4);
|
||||
assert_eq!(items(&cache), [4, 3, 2, 1], "Ordered from most- to least-recent.");
|
||||
assert_eq!(items(&mut cache), [4, 3, 2, 1], "Ordered from most- to least-recent.");
|
||||
|
||||
cache.insert(5);
|
||||
assert_eq!(cache.num_entries(), 4);
|
||||
assert_eq!(items(&cache), [5, 4, 3, 2], "Least-recently-used item evicted.");
|
||||
assert_eq!(items(&mut cache), [5, 4, 3, 2], "Least-recently-used item evicted.");
|
||||
|
||||
cache.insert(6);
|
||||
cache.insert(7);
|
||||
cache.insert(8);
|
||||
cache.insert(9);
|
||||
assert_eq!(items(&cache), [9, 8, 7, 6], "Least-recently-used item evicted.");
|
||||
assert_eq!(items(&mut cache), [9, 8, 7, 6], "Least-recently-used item evicted.");
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
@ -55,12 +55,12 @@ fn lookup() {
|
|||
|
||||
let result = cache.lookup(|x| if *x == 5 { Some(()) } else { None });
|
||||
assert_eq!(result, None, "Cache miss.");
|
||||
assert_eq!(items(&cache), [4, 3, 2, 1], "Order not changed.");
|
||||
assert_eq!(items(&mut cache), [4, 3, 2, 1], "Order not changed.");
|
||||
|
||||
// Cache hit
|
||||
let result = cache.lookup(|x| if *x == 3 { Some(*x * 2) } else { None });
|
||||
assert_eq!(result, Some(6), "Cache hit.");
|
||||
assert_eq!(items(&cache), [3, 4, 2, 1], "Matching item moved to front.");
|
||||
assert_eq!(items(&mut cache), [3, 4, 2, 1], "Matching item moved to front.");
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
@ -68,14 +68,14 @@ fn evict_all() {
|
|||
let mut cache = TestCache::default();
|
||||
cache.insert(1);
|
||||
cache.evict_all();
|
||||
assert_eq!(items(&cache), [], "all items evicted");
|
||||
assert_eq!(items(&mut cache), [], "all items evicted");
|
||||
|
||||
cache.insert(1);
|
||||
cache.insert(2);
|
||||
cache.insert(3);
|
||||
cache.insert(4);
|
||||
assert_eq!(items(&cache), [4, 3, 2, 1]);
|
||||
assert_eq!(items(&mut cache), [4, 3, 2, 1]);
|
||||
cache.evict_all();
|
||||
assert_eq!(items(&cache), [], "all items evicted again");
|
||||
assert_eq!(items(&mut cache), [], "all items evicted again");
|
||||
}
|
||||
|
||||
|
|
Загрузка…
Ссылка в новой задаче