mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-11-23 21:01:08 +00:00
Bug 1723791 - Upgrade to uluru 1.1.1. r=emilio
MANUAL PUSH: Patch wasn't pushed via phabricator.
This commit is contained in:
parent
2e7b1387b7
commit
3c9cf910ab
4
Cargo.lock
generated
4
Cargo.lock
generated
@ -5366,9 +5366,9 @@ checksum = "879f6906492a7cd215bfa4cf595b600146ccfac0c79bcbd1f3000162af5e8b06"
|
||||
|
||||
[[package]]
|
||||
name = "uluru"
|
||||
version = "0.4.0"
|
||||
version = "1.1.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "6d7b39d0c32eba57d52d334e4bdd150df6e755264eefaa1ae2e7cd125f35e1ca"
|
||||
checksum = "b6ee6f45294ecb6e220e76b8afddb50a8b69d433f31ad9eb2d16fb44029ef5db"
|
||||
dependencies = [
|
||||
"arrayvec",
|
||||
]
|
||||
|
@ -75,7 +75,7 @@ thin-slice = "0.1.0"
|
||||
to_shmem = {path = "../to_shmem"}
|
||||
to_shmem_derive = {path = "../to_shmem_derive"}
|
||||
time = "0.1"
|
||||
uluru = "0.4"
|
||||
uluru = "1.1"
|
||||
unicode-bidi = "0.3"
|
||||
unicode-segmentation = "1.0"
|
||||
void = "1.0.2"
|
||||
|
@ -568,7 +568,7 @@ impl<E: TElement> SelectorFlagsMap<E> {
|
||||
/// Applies the flags. Must be called on the main thread.
|
||||
fn apply_flags(&mut self) {
|
||||
debug_assert_eq!(thread_state::get(), ThreadState::LAYOUT);
|
||||
self.cache.evict_all();
|
||||
self.cache.clear();
|
||||
for (el, flags) in self.map.drain() {
|
||||
unsafe {
|
||||
el.set_selector_flags(flags);
|
||||
|
@ -470,11 +470,11 @@ impl<Candidate> Default for SharingCacheBase<Candidate> {
|
||||
|
||||
impl<Candidate> SharingCacheBase<Candidate> {
|
||||
fn clear(&mut self) {
|
||||
self.entries.evict_all();
|
||||
self.entries.clear();
|
||||
}
|
||||
|
||||
fn is_empty(&self) -> bool {
|
||||
self.entries.num_entries() == 0
|
||||
self.entries.len() == 0
|
||||
}
|
||||
}
|
||||
|
||||
|
2
third_party/rust/uluru/.cargo-checksum.json
vendored
2
third_party/rust/uluru/.cargo-checksum.json
vendored
@ -1 +1 @@
|
||||
{"files":{"Cargo.toml":"c17f68b45f66a90fe49f9798875d31b7dbca4cabeead79e2ed6d963cbdb76fe3","LICENSE":"3db78572e8657cca9e9446ce56a057b8a981eb41af318c49a5fe08e7a10fa52a","README.md":"e918fd4e18659a1d4438ca8f198f979cfdd7a9d27dc8e16f65bcf198c2f3d1cd","lib.rs":"4393ac1bd1d1d41bdcf21901d2aee31187232f95af273dead63913a2fc195b51","tests.rs":"056ea5bd7bd7793107c057cb1600ba831400c29be8938df41a3f9ac8d92fccfd"},"package":"6d7b39d0c32eba57d52d334e4bdd150df6e755264eefaa1ae2e7cd125f35e1ca"}
|
||||
{"files":{"Cargo.toml":"f45ca8b5456a8aa181cf782f41378e1402bfe71e625547dee9be7ed2510b5a9c","LICENSE":"3db78572e8657cca9e9446ce56a057b8a981eb41af318c49a5fe08e7a10fa52a","README.md":"ba37d1f9ea9f852f81d984b612c9028ccc96d9e1da6d9bf2c7fb51cbf10c9066","lib.rs":"2d4fdb02d09b843abac3d474f8d4293c93e8404d8162736c813f738c969aa935","tests.rs":"8e47261aa40ac4245e46532c7b42931f693bc6d460414fd548c0411911b46cea"},"package":"b6ee6f45294ecb6e220e76b8afddb50a8b69d433f31ad9eb2d16fb44029ef5db"}
|
9
third_party/rust/uluru/Cargo.toml
vendored
9
third_party/rust/uluru/Cargo.toml
vendored
@ -12,8 +12,8 @@
|
||||
|
||||
[package]
|
||||
name = "uluru"
|
||||
version = "0.4.0"
|
||||
authors = ["The Servo Project Developers"]
|
||||
version = "1.1.1"
|
||||
authors = ["The Servo Project Developers", "Matt Brubeck <mbrubeck@limpet.net>"]
|
||||
description = "A simple, fast, LRU cache implementation"
|
||||
readme = "README.md"
|
||||
keywords = ["cache", "linkedlist", "array", "no_std"]
|
||||
@ -27,3 +27,8 @@ path = "lib.rs"
|
||||
[dependencies.arrayvec]
|
||||
version = "0.5"
|
||||
default-features = false
|
||||
[dev-dependencies.quickcheck]
|
||||
version = "0.9"
|
||||
|
||||
[dev-dependencies.quickcheck_macros]
|
||||
version = "0.9"
|
||||
|
2
third_party/rust/uluru/README.md
vendored
2
third_party/rust/uluru/README.md
vendored
@ -5,7 +5,7 @@ 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.
|
||||
used in `no_std` crates. It is implemented in 100% safe Rust.
|
||||
|
||||
* [Documentation](https://docs.rs/uluru)
|
||||
* [crates.io](https://crates.io/crates/uluru)
|
||||
|
180
third_party/rust/uluru/lib.rs
vendored
180
third_party/rust/uluru/lib.rs
vendored
@ -3,6 +3,7 @@
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#![no_std]
|
||||
#![deny(unsafe_code)]
|
||||
|
||||
//! A simple, fast, least-recently-used (LRU) cache.
|
||||
//!
|
||||
@ -15,7 +16,17 @@ extern crate arrayvec;
|
||||
|
||||
use arrayvec::{Array, ArrayVec};
|
||||
|
||||
#[cfg(test)] mod tests;
|
||||
use core::fmt;
|
||||
|
||||
#[cfg(test)]
|
||||
extern crate quickcheck;
|
||||
|
||||
#[cfg(test)]
|
||||
#[macro_use(quickcheck)]
|
||||
extern crate quickcheck_macros;
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests;
|
||||
|
||||
/// A LRU cache using a statically-sized array for storage.
|
||||
///
|
||||
@ -68,6 +79,7 @@ pub struct LRUCache<A: Array> {
|
||||
}
|
||||
|
||||
/// An entry in an LRUCache.
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct Entry<T> {
|
||||
val: T,
|
||||
/// Index of the previous entry. If this entry is the head, ignore this field.
|
||||
@ -83,24 +95,28 @@ impl<A: Array> Default for LRUCache<A> {
|
||||
head: 0,
|
||||
tail: 0,
|
||||
};
|
||||
assert!(cache.entries.capacity() < u16::max_value() as usize, "Capacity overflow");
|
||||
assert!(
|
||||
cache.entries.capacity() < u16::max_value() as usize,
|
||||
"Capacity overflow"
|
||||
);
|
||||
cache
|
||||
}
|
||||
}
|
||||
|
||||
impl<T, A: Array<Item=Entry<T>>> LRUCache<A> {
|
||||
impl<T, A> LRUCache<A>
|
||||
where
|
||||
A: Array<Item = Entry<T>>,
|
||||
{
|
||||
/// Returns the number of elements in the cache.
|
||||
pub fn num_entries(&self) -> usize {
|
||||
pub fn len(&self) -> usize {
|
||||
self.entries.len()
|
||||
}
|
||||
|
||||
/// Returns the number of elements in the cache.
|
||||
#[inline]
|
||||
/// Touch a given entry, putting it first in the list.
|
||||
fn touch(&mut self, idx: u16) {
|
||||
if idx != self.head {
|
||||
self.remove(idx);
|
||||
self.push_front(idx);
|
||||
}
|
||||
#[deprecated = "Use the 'len' method instead."]
|
||||
pub fn num_entries(&self) -> usize {
|
||||
self.len()
|
||||
}
|
||||
|
||||
/// Returns the front entry in the list (most recently used).
|
||||
@ -113,50 +129,56 @@ impl<T, A: Array<Item=Entry<T>>> LRUCache<A> {
|
||||
self.entries.get_mut(self.head as usize).map(|e| &mut e.val)
|
||||
}
|
||||
|
||||
/// Iterate mutably over the contents of this cache.
|
||||
fn iter_mut(&mut self) -> LRUCacheMutIterator<A> {
|
||||
LRUCacheMutIterator {
|
||||
pos: self.head,
|
||||
done: self.entries.len() == 0,
|
||||
cache: self,
|
||||
}
|
||||
}
|
||||
|
||||
/// Performs a lookup on the cache with the given test routine. Touches
|
||||
/// the result on a hit.
|
||||
pub fn lookup<F, R>(&mut self, mut test_one: F) -> Option<R>
|
||||
where
|
||||
F: FnMut(&mut T) -> Option<R>
|
||||
F: FnMut(&mut T) -> Option<R>,
|
||||
{
|
||||
let mut result = None;
|
||||
for (i, candidate) in self.iter_mut() {
|
||||
if let Some(r) = test_one(candidate) {
|
||||
let mut iter = self.iter_mut();
|
||||
while let Some((i, val)) = iter.next() {
|
||||
if let Some(r) = test_one(val) {
|
||||
result = Some((i, r));
|
||||
break;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
match result {
|
||||
None => None,
|
||||
Some((i, r)) => {
|
||||
self.touch(i);
|
||||
self.touch_index(i);
|
||||
Some(r)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Touches the first item in the cache that matches the given predicate.
|
||||
/// Returns `true` on a hit, `false` if no matches.
|
||||
pub fn touch<F>(&mut self, mut pred: F) -> bool
|
||||
where
|
||||
F: FnMut(&T) -> bool,
|
||||
{
|
||||
let mut iter = self.iter_mut();
|
||||
while let Some((i, val)) = iter.next() {
|
||||
if pred(val) {
|
||||
self.touch_index(i);
|
||||
return true
|
||||
}
|
||||
}
|
||||
false
|
||||
}
|
||||
|
||||
/// Returns the first item in the cache that matches the given predicate.
|
||||
/// Touches the result on a hit.
|
||||
pub fn find<F>(&mut self, mut pred: F) -> Option<&mut T>
|
||||
pub fn find<F>(&mut self, pred: F) -> Option<&mut T>
|
||||
where
|
||||
F: FnMut(&T) -> bool
|
||||
F: FnMut(&T) -> bool,
|
||||
{
|
||||
match self.iter_mut().find(|&(_, ref x)| pred(x)) {
|
||||
Some((i, _)) => {
|
||||
self.touch(i);
|
||||
self.front_mut()
|
||||
}
|
||||
None => None
|
||||
if self.touch(pred) {
|
||||
self.front_mut()
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
@ -165,7 +187,11 @@ impl<T, A: Array<Item=Entry<T>>> LRUCache<A> {
|
||||
/// This item becomes the front (most-recently-used) item in the cache. If the cache is full,
|
||||
/// the back (least-recently-used) item will be removed.
|
||||
pub fn insert(&mut self, val: T) {
|
||||
let entry = Entry { val, prev: 0, next: 0 };
|
||||
let entry = Entry {
|
||||
val,
|
||||
prev: 0,
|
||||
next: 0,
|
||||
};
|
||||
|
||||
// If the cache is full, replace the oldest entry. Otherwise, add an entry.
|
||||
let new_head = if self.entries.len() == self.entries.capacity() {
|
||||
@ -180,6 +206,35 @@ impl<T, A: Array<Item=Entry<T>>> LRUCache<A> {
|
||||
self.push_front(new_head);
|
||||
}
|
||||
|
||||
/// Evict all elements from the cache.
|
||||
pub fn clear(&mut self) {
|
||||
self.entries.clear();
|
||||
}
|
||||
|
||||
/// Evict all elements from the cache.
|
||||
#[inline]
|
||||
#[deprecated = "Use the 'clear' method instead."]
|
||||
pub fn evict_all(&mut self) {
|
||||
self.clear();
|
||||
}
|
||||
|
||||
/// Iterate mutably over the contents of this cache.
|
||||
fn iter_mut(&mut self) -> IterMut<A> {
|
||||
IterMut {
|
||||
pos: self.head,
|
||||
cache: self,
|
||||
}
|
||||
}
|
||||
|
||||
/// Touch a given entry, putting it first in the list.
|
||||
#[inline]
|
||||
fn touch_index(&mut self, idx: u16) {
|
||||
if idx != self.head {
|
||||
self.remove(idx);
|
||||
self.push_front(idx);
|
||||
}
|
||||
}
|
||||
|
||||
/// Remove an entry from the linked list.
|
||||
///
|
||||
/// Note: This only unlinks the entry from the list; it does not remove it from the array.
|
||||
@ -220,40 +275,55 @@ impl<T, A: Array<Item=Entry<T>>> LRUCache<A> {
|
||||
self.tail = new_tail;
|
||||
old_tail
|
||||
}
|
||||
}
|
||||
|
||||
/// Evict all elements from the cache.
|
||||
pub fn evict_all(&mut self) {
|
||||
self.entries.clear();
|
||||
impl<T, A> Clone for LRUCache<A>
|
||||
where
|
||||
A: Array<Item = Entry<T>>,
|
||||
T: Clone,
|
||||
{
|
||||
fn clone(&self) -> Self {
|
||||
Self {
|
||||
entries: self.entries.clone(),
|
||||
head: self.head,
|
||||
tail: self.tail,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<T, A> fmt::Debug for LRUCache<A>
|
||||
where
|
||||
A: Array<Item = Entry<T>>,
|
||||
T: fmt::Debug,
|
||||
{
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
f.debug_struct("LRUCache")
|
||||
.field("head", &self.head)
|
||||
.field("tail", &self.tail)
|
||||
.field("entries", &self.entries)
|
||||
.finish()
|
||||
}
|
||||
}
|
||||
|
||||
/// Mutable iterator over values in an LRUCache, from most-recently-used to least-recently-used.
|
||||
struct LRUCacheMutIterator<'a, A: 'a + Array> {
|
||||
struct IterMut<'a, A: 'a + Array> {
|
||||
cache: &'a mut LRUCache<A>,
|
||||
pos: u16,
|
||||
done: bool,
|
||||
}
|
||||
|
||||
impl<'a, T, A> Iterator for LRUCacheMutIterator<'a, A>
|
||||
where T: 'a,
|
||||
A: 'a + Array<Item=Entry<T>>
|
||||
impl<'a, A, T> IterMut<'a, A>
|
||||
where
|
||||
A: Array<Item = Entry<T>>,
|
||||
{
|
||||
type Item = (u16, &'a mut T);
|
||||
|
||||
fn next(&mut self) -> Option<Self::Item> {
|
||||
if self.done { return None }
|
||||
|
||||
// Use a raw pointer because the compiler doesn't know that subsequent calls can't alias.
|
||||
let entry = unsafe {
|
||||
&mut *(&mut self.cache.entries[self.pos as usize] as *mut Entry<T>)
|
||||
};
|
||||
|
||||
fn next(&mut self) -> Option<(u16, &mut T)> {
|
||||
let index = self.pos;
|
||||
if self.pos == self.cache.tail {
|
||||
self.done = true;
|
||||
}
|
||||
self.pos = entry.next;
|
||||
let entry = self.cache.entries.get_mut(index as usize)?;
|
||||
|
||||
self.pos = if index == self.cache.tail {
|
||||
A::CAPACITY as u16 // Point past the end of the array to signal we are done.
|
||||
} else {
|
||||
entry.next
|
||||
};
|
||||
Some((index, &mut entry.val))
|
||||
}
|
||||
}
|
||||
|
139
third_party/rust/uluru/tests.rs
vendored
139
third_party/rust/uluru/tests.rs
vendored
@ -9,15 +9,20 @@ type TestCache = LRUCache<[Entry<i32>; 4]>;
|
||||
fn items<T, A>(cache: &mut LRUCache<A>) -> Vec<T>
|
||||
where
|
||||
T: Clone,
|
||||
A: Array<Item=Entry<T>>
|
||||
A: Array<Item = Entry<T>>,
|
||||
{
|
||||
cache.iter_mut().map(|(_, x)| x.clone()).collect()
|
||||
let mut v = Vec::new();
|
||||
let mut iter = cache.iter_mut();
|
||||
while let Some((_idx, val)) = iter.next() {
|
||||
v.push(val.clone())
|
||||
}
|
||||
v
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn empty() {
|
||||
let mut cache = TestCache::default();
|
||||
assert_eq!(cache.num_entries(), 0);
|
||||
assert_eq!(cache.len(), 0);
|
||||
assert_eq!(items(&mut cache), []);
|
||||
}
|
||||
|
||||
@ -25,24 +30,36 @@ fn empty() {
|
||||
fn insert() {
|
||||
let mut cache = TestCache::default();
|
||||
cache.insert(1);
|
||||
assert_eq!(cache.num_entries(), 1);
|
||||
assert_eq!(cache.len(), 1);
|
||||
cache.insert(2);
|
||||
assert_eq!(cache.num_entries(), 2);
|
||||
assert_eq!(cache.len(), 2);
|
||||
cache.insert(3);
|
||||
assert_eq!(cache.num_entries(), 3);
|
||||
assert_eq!(cache.len(), 3);
|
||||
cache.insert(4);
|
||||
assert_eq!(cache.num_entries(), 4);
|
||||
assert_eq!(items(&mut cache), [4, 3, 2, 1], "Ordered from most- to least-recent.");
|
||||
assert_eq!(cache.len(), 4);
|
||||
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(&mut cache), [5, 4, 3, 2], "Least-recently-used item evicted.");
|
||||
assert_eq!(cache.len(), 4);
|
||||
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(&mut 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]
|
||||
@ -60,14 +77,18 @@ fn lookup() {
|
||||
// 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(&mut 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]
|
||||
fn evict_all() {
|
||||
fn clear() {
|
||||
let mut cache = TestCache::default();
|
||||
cache.insert(1);
|
||||
cache.evict_all();
|
||||
cache.clear();
|
||||
assert_eq!(items(&mut cache), [], "all items evicted");
|
||||
|
||||
cache.insert(1);
|
||||
@ -75,7 +96,95 @@ fn evict_all() {
|
||||
cache.insert(3);
|
||||
cache.insert(4);
|
||||
assert_eq!(items(&mut cache), [4, 3, 2, 1]);
|
||||
cache.evict_all();
|
||||
cache.clear();
|
||||
assert_eq!(items(&mut cache), [], "all items evicted again");
|
||||
}
|
||||
|
||||
#[quickcheck]
|
||||
fn touch(num: i32) {
|
||||
let first = num;
|
||||
let second = num + 1;
|
||||
let third = num + 2;
|
||||
let fourth = num + 3;
|
||||
|
||||
let mut cache = TestCache::default();
|
||||
|
||||
cache.insert(first);
|
||||
cache.insert(second);
|
||||
cache.insert(third);
|
||||
cache.insert(fourth);
|
||||
|
||||
cache.touch(|x| *x == fourth + 1);
|
||||
|
||||
assert_eq!(
|
||||
items(&mut cache),
|
||||
[fourth, third, second, first],
|
||||
"Nothing is touched."
|
||||
);
|
||||
|
||||
cache.touch(|x| *x == second);
|
||||
|
||||
assert_eq!(
|
||||
items(&mut cache),
|
||||
[second, fourth, third, first],
|
||||
"Touched item is moved to front."
|
||||
);
|
||||
}
|
||||
|
||||
#[quickcheck]
|
||||
fn find(num: i32) {
|
||||
let first = num;
|
||||
let second = num + 1;
|
||||
let third = num + 2;
|
||||
let fourth = num + 3;
|
||||
|
||||
let mut cache = TestCache::default();
|
||||
|
||||
cache.insert(first);
|
||||
cache.insert(second);
|
||||
cache.insert(third);
|
||||
cache.insert(fourth);
|
||||
|
||||
cache.find(|x| *x == fourth + 1);
|
||||
|
||||
assert_eq!(
|
||||
items(&mut cache),
|
||||
[fourth, third, second, first],
|
||||
"Nothing is touched."
|
||||
);
|
||||
|
||||
cache.find(|x| *x == second);
|
||||
|
||||
assert_eq!(
|
||||
items(&mut cache),
|
||||
[second, fourth, third, first],
|
||||
"Touched item is moved to front."
|
||||
);
|
||||
}
|
||||
|
||||
#[quickcheck]
|
||||
fn front(num: i32) {
|
||||
let first = num;
|
||||
let second = num + 1;
|
||||
|
||||
let mut cache = TestCache::default();
|
||||
|
||||
assert_eq!(cache.front(), None, "Nothing is in the front.");
|
||||
|
||||
cache.insert(first);
|
||||
cache.insert(second);
|
||||
|
||||
assert_eq!(
|
||||
cache.front(),
|
||||
Some(&second),
|
||||
"The last inserted item should be in the front."
|
||||
);
|
||||
|
||||
cache.touch(|x| *x == first);
|
||||
|
||||
assert_eq!(
|
||||
cache.front(),
|
||||
Some(&first),
|
||||
"Touched item should be in the front."
|
||||
);
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user