Vendor dependencies

This commit is contained in:
2026-08-01 16:11:49 +03:00
parent 7f139a0241
commit 6b5e7f0f8b
29706 changed files with 9575646 additions and 0 deletions
+926
View File
@@ -0,0 +1,926 @@
use std::{
cell::{Cell, RefCell},
hash::{Hash, Hasher},
panic::{catch_unwind, AssertUnwindSafe},
rc::Rc,
};
use hashlink::{linked_hash_map, LinkedHashMap};
#[allow(dead_code)]
fn assert_covariance() {
fn set<'new>(v: LinkedHashMap<&'static str, ()>) -> LinkedHashMap<&'new str, ()> {
v
}
fn iter<'a, 'new>(
v: linked_hash_map::Iter<'a, &'static str, &'static str>,
) -> linked_hash_map::Iter<'a, &'new str, &'new str> {
v
}
fn iter_mut<'a, 'new>(
v: linked_hash_map::Iter<'a, &'static str, ()>,
) -> linked_hash_map::Iter<'a, &'new str, ()> {
v
}
fn into_iter<'new>(
v: linked_hash_map::IntoIter<&'static str, &'static str>,
) -> linked_hash_map::IntoIter<&'new str, &'new str> {
v
}
fn drain<'new>(
d: linked_hash_map::Drain<'static, &'static str, &'static str>,
) -> linked_hash_map::Drain<'new, &'new str, &'new str> {
d
}
fn raw_entry_builder<'a, 'new>(
v: linked_hash_map::RawEntryBuilder<'a, &'static str, &'static str, ()>,
) -> linked_hash_map::RawEntryBuilder<'a, &'new str, &'new str, ()> {
v
}
}
#[test]
fn test_index() {
let mut map = LinkedHashMap::new();
map.insert(1, 10);
map.insert(2, 20);
assert_eq!(10, map[&1]);
map[&2] = 22;
assert_eq!(22, map[&2]);
}
#[test]
fn test_insert_and_get() {
let mut map = LinkedHashMap::new();
map.insert(1, 10);
map.insert(2, 20);
assert_eq!(map.get(&1), Some(&10));
assert_eq!(map.get(&2), Some(&20));
assert_eq!(map.len(), 2);
}
#[test]
fn test_insert_update() {
let mut map = LinkedHashMap::new();
map.insert("1".to_string(), vec![10, 10]);
map.insert("1".to_string(), vec![10, 19]);
assert_eq!(map.get(&"1".to_string()), Some(&vec![10, 19]));
assert_eq!(map.len(), 1);
}
#[test]
fn test_entry_insert_vacant() {
let mut map = LinkedHashMap::new();
match map.entry("1".to_string()) {
linked_hash_map::Entry::Vacant(e) => {
assert_eq!(*e.insert(vec![10, 10]), vec![10, 10]);
}
_ => panic!("fail"),
}
assert!(map.contains_key("1"));
assert_eq!(map["1"], vec![10, 10]);
match map.entry("1".to_string()) {
linked_hash_map::Entry::Occupied(mut e) => {
assert_eq!(*e.get(), vec![10, 10]);
assert_eq!(e.insert(vec![10, 16]), vec![10, 10]);
}
_ => panic!("fail"),
}
assert!(map.contains_key("1"));
assert_eq!(map["1"], vec![10, 16]);
match map.entry("1".to_string()) {
linked_hash_map::Entry::Occupied(e) => {
assert_eq!(e.remove(), vec![10, 16]);
}
_ => panic!("fail"),
}
}
#[test]
fn test_remove() {
let mut map = LinkedHashMap::new();
map.insert(1, 10);
map.insert(2, 20);
map.insert(3, 30);
map.insert(4, 40);
map.insert(5, 50);
map.remove(&3);
map.remove(&4);
assert!(map.get(&3).is_none());
assert!(map.get(&4).is_none());
map.insert(6, 60);
map.insert(7, 70);
map.insert(8, 80);
assert_eq!(map.get(&6), Some(&60));
assert_eq!(map.get(&7), Some(&70));
assert_eq!(map.get(&8), Some(&80));
}
#[test]
fn test_pop() {
let mut map = LinkedHashMap::new();
map.insert(1, 10);
map.insert(2, 20);
map.insert(3, 30);
map.insert(4, 40);
map.insert(5, 50);
assert_eq!(map.pop_front(), Some((1, 10)));
assert!(map.get(&1).is_none());
assert_eq!(map.pop_back(), Some((5, 50)));
assert!(map.get(&5).is_none());
map.insert(6, 60);
map.insert(7, 70);
map.insert(8, 80);
assert_eq!(map.pop_front(), Some((2, 20)));
assert!(map.get(&2).is_none());
assert_eq!(map.pop_back(), Some((8, 80)));
assert!(map.get(&8).is_none());
map.insert(3, 30);
assert_eq!(map.pop_front(), Some((4, 40)));
assert!(map.get(&4).is_none());
assert_eq!(map.pop_back(), Some((3, 30)));
assert!(map.get(&3).is_none());
}
#[test]
fn test_move() {
let to_back = |map: &mut LinkedHashMap<_, _>, key| match map.entry(key) {
linked_hash_map::Entry::Occupied(mut occupied) => occupied.to_back(),
linked_hash_map::Entry::Vacant(_) => panic!(),
};
let to_front = |map: &mut LinkedHashMap<_, _>, key| match map.entry(key) {
linked_hash_map::Entry::Occupied(mut occupied) => occupied.to_front(),
linked_hash_map::Entry::Vacant(_) => panic!(),
};
let mut map = LinkedHashMap::new();
map.insert(1, 10);
map.insert(2, 20);
map.insert(3, 30);
map.insert(4, 40);
map.insert(5, 50);
to_back(&mut map, 1);
assert_eq!(map.keys().copied().collect::<Vec<_>>(), vec![2, 3, 4, 5, 1]);
to_front(&mut map, 4);
assert_eq!(map.keys().copied().collect::<Vec<_>>(), vec![4, 2, 3, 5, 1]);
to_back(&mut map, 3);
assert_eq!(map.keys().copied().collect::<Vec<_>>(), vec![4, 2, 5, 1, 3]);
to_front(&mut map, 2);
assert_eq!(map.keys().copied().collect::<Vec<_>>(), vec![2, 4, 5, 1, 3]);
to_back(&mut map, 3);
assert_eq!(map.keys().copied().collect::<Vec<_>>(), vec![2, 4, 5, 1, 3]);
to_front(&mut map, 2);
assert_eq!(map.keys().copied().collect::<Vec<_>>(), vec![2, 4, 5, 1, 3]);
}
#[test]
fn test_clear() {
let mut map = LinkedHashMap::new();
map.insert(1, 10);
map.insert(2, 20);
map.clear();
assert!(map.get(&1).is_none());
assert!(map.get(&2).is_none());
assert!(map.is_empty());
}
#[test]
fn test_iter() {
let mut map = LinkedHashMap::new();
// empty iter
assert_eq!(None, map.iter().next());
map.insert("a", 10);
map.insert("b", 20);
map.insert("c", 30);
// regular iter
let mut iter = map.iter();
assert_eq!((&"a", &10), iter.next().unwrap());
assert_eq!((&"b", &20), iter.next().unwrap());
assert_eq!((&"c", &30), iter.next().unwrap());
assert_eq!(None, iter.next());
assert_eq!(None, iter.next());
let mut iter = map.iter();
assert_eq!((&"a", &10), iter.next().unwrap());
let mut iclone = iter.clone();
assert_eq!((&"b", &20), iter.next().unwrap());
assert_eq!((&"b", &20), iclone.next().unwrap());
assert_eq!((&"c", &30), iter.next().unwrap());
assert_eq!((&"c", &30), iclone.next().unwrap());
// reversed iter
let mut rev_iter = map.iter().rev();
assert_eq!((&"c", &30), rev_iter.next().unwrap());
assert_eq!((&"b", &20), rev_iter.next().unwrap());
assert_eq!((&"a", &10), rev_iter.next().unwrap());
assert_eq!(None, rev_iter.next());
assert_eq!(None, rev_iter.next());
// mixed
let mut mixed_iter = map.iter();
assert_eq!((&"a", &10), mixed_iter.next().unwrap());
assert_eq!((&"c", &30), mixed_iter.next_back().unwrap());
assert_eq!((&"b", &20), mixed_iter.next().unwrap());
assert_eq!(None, mixed_iter.next());
assert_eq!(None, mixed_iter.next_back());
}
#[test]
fn test_borrow() {
#[derive(PartialEq, Eq, Hash)]
struct Foo(Bar);
#[derive(PartialEq, Eq, Hash)]
struct Bar(i32);
impl ::std::borrow::Borrow<Bar> for Foo {
fn borrow(&self) -> &Bar {
&self.0
}
}
let mut map = LinkedHashMap::new();
map.insert(Foo(Bar(1)), "a");
map.insert(Foo(Bar(2)), "b");
assert!(map.contains_key(&Bar(1)));
assert!(map.contains_key(&Bar(2)));
assert!(map.contains_key(&Foo(Bar(1))));
assert!(map.contains_key(&Foo(Bar(2))));
assert_eq!(map.get(&Bar(1)), Some(&"a"));
assert_eq!(map.get(&Bar(2)), Some(&"b"));
assert_eq!(map.get(&Foo(Bar(1))), Some(&"a"));
assert_eq!(map.get(&Foo(Bar(2))), Some(&"b"));
assert_eq!(map.get_mut(&Bar(1)), Some(&mut "a"));
assert_eq!(map.get_mut(&Bar(2)), Some(&mut "b"));
assert_eq!(map.get_mut(&Foo(Bar(1))), Some(&mut "a"));
assert_eq!(map.get_mut(&Foo(Bar(2))), Some(&mut "b"));
assert_eq!(map[&Bar(1)], "a");
assert_eq!(map[&Bar(2)], "b");
assert_eq!(map[&Foo(Bar(1))], "a");
assert_eq!(map[&Foo(Bar(2))], "b");
assert_eq!(map.remove(&Bar(1)), Some("a"));
assert_eq!(map.remove(&Bar(2)), Some("b"));
assert_eq!(map.remove(&Foo(Bar(1))), None);
assert_eq!(map.remove(&Foo(Bar(2))), None);
}
#[test]
fn test_iter_mut() {
let mut map = LinkedHashMap::new();
map.insert("a", 10);
map.insert("c", 30);
map.insert("b", 20);
{
let mut iter = map.iter_mut();
let entry = iter.next().unwrap();
assert_eq!("a", *entry.0);
*entry.1 = 17;
assert_eq!(format!("{:?}", iter), "[(\"c\", 30), (\"b\", 20)]");
// reverse iterator
let mut iter = iter.rev();
let entry = iter.next().unwrap();
assert_eq!("b", *entry.0);
*entry.1 = 23;
let entry = iter.next().unwrap();
assert_eq!("c", *entry.0);
assert_eq!(None, iter.next());
assert_eq!(None, iter.next());
}
assert_eq!(17, map[&"a"]);
assert_eq!(23, map[&"b"]);
}
#[test]
fn test_consuming_iter() {
let map = {
let mut map = LinkedHashMap::new();
map.insert("a", 10);
map.insert("c", 30);
map.insert("b", 20);
map
};
let mut iter = map.into_iter();
assert_eq!(Some(("a", 10)), iter.next());
assert_eq!(Some(("b", 20)), iter.next_back());
assert_eq!(iter.len(), 1);
assert_eq!(format!("{:?}", iter), "[(\"c\", 30)]");
assert_eq!(Some(("c", 30)), iter.next());
assert_eq!(None, iter.next());
}
#[test]
fn test_consuming_iter_empty() {
let map = LinkedHashMap::<&str, i32>::new();
let mut iter = map.into_iter();
assert_eq!(None, iter.next());
}
#[test]
fn test_consuming_iter_with_free_list() {
let mut map = LinkedHashMap::new();
map.insert("a", 10);
map.insert("c", 30);
map.insert("b", 20);
map.remove("a");
map.remove("b");
let mut iter = map.into_iter();
assert_eq!(Some(("c", 30)), iter.next());
assert_eq!(None, iter.next());
}
#[test]
fn test_into_iter_drop() {
struct Counter<'a>(&'a mut usize);
impl Drop for Counter<'_> {
fn drop(&mut self) {
*self.0 += 1;
}
}
let mut a = 0;
let mut b = 0;
let mut c = 0;
{
let mut map = LinkedHashMap::new();
map.insert("a", Counter(&mut a));
map.insert("b", Counter(&mut b));
map.insert("c", Counter(&mut c));
let mut iter = map.into_iter();
assert_eq!(iter.next().map(|p| p.0), Some("a"));
assert_eq!(iter.next_back().map(|p| p.0), Some("c"));
}
assert_eq!(a, 1);
assert_eq!(b, 1);
assert_eq!(c, 1);
}
#[test]
fn test_drain() {
use std::{cell::Cell, rc::Rc};
struct Counter(Rc<Cell<u32>>);
impl Drop for Counter {
fn drop(&mut self) {
self.0.set(self.0.get() + 1);
}
}
let mut map = LinkedHashMap::new();
let a = Rc::new(Cell::new(0));
let b = Rc::new(Cell::new(0));
let c = Rc::new(Cell::new(0));
map.insert("a", Counter(a.clone()));
map.insert("b", Counter(b.clone()));
map.insert("c", Counter(c.clone()));
let mut iter = map.drain();
assert_eq!(iter.next().map(|p| p.0), Some("a"));
assert_eq!(iter.next_back().map(|p| p.0), Some("c"));
assert_eq!(iter.next_back().map(|p| p.0), Some("b"));
assert!(iter.next().is_none());
assert!(iter.next_back().is_none());
drop(iter);
assert_eq!(map.len(), 0);
assert_eq!(a.get(), 1);
assert_eq!(b.get(), 1);
assert_eq!(c.get(), 1);
map.insert("a", Counter(a.clone()));
map.insert("b", Counter(b.clone()));
map.insert("c", Counter(c.clone()));
let mut iter = map.drain();
assert_eq!(iter.next().map(|p| p.0), Some("a"));
assert_eq!(iter.next().map(|p| p.0), Some("b"));
assert_eq!(iter.next_back().map(|p| p.0), Some("c"));
assert!(iter.next().is_none());
assert!(iter.next_back().is_none());
drop(iter);
assert_eq!(map.len(), 0);
assert_eq!(a.get(), 2);
assert_eq!(b.get(), 2);
assert_eq!(c.get(), 2);
map.insert("a", Counter(a.clone()));
map.insert("b", Counter(b.clone()));
map.insert("c", Counter(c.clone()));
map.drain();
assert_eq!(map.len(), 0);
assert_eq!(a.get(), 3);
assert_eq!(b.get(), 3);
assert_eq!(c.get(), 3);
}
#[test]
fn test_send_sync() {
fn is_send_sync<T: Send + Sync>() {}
is_send_sync::<LinkedHashMap<u32, i32>>();
is_send_sync::<linked_hash_map::Entry<u32, i32, ()>>();
is_send_sync::<linked_hash_map::RawEntryBuilder<u32, i32, ()>>();
is_send_sync::<linked_hash_map::RawEntryBuilderMut<u32, i32, ()>>();
is_send_sync::<linked_hash_map::RawEntryMut<u32, i32, ()>>();
is_send_sync::<linked_hash_map::Iter<u32, i32>>();
is_send_sync::<linked_hash_map::IterMut<u32, i32>>();
is_send_sync::<linked_hash_map::Drain<u32, i32>>();
is_send_sync::<linked_hash_map::Keys<u32, i32>>();
is_send_sync::<linked_hash_map::Values<u32, i32>>();
}
#[test]
fn test_retain() {
use std::{cell::Cell, rc::Rc};
let xs = [1, 2, 3, 4, 5, 6];
let mut map: LinkedHashMap<String, i32> = xs.iter().map(|i| (i.to_string(), *i)).collect();
map.retain(|_, v| *v % 2 == 0);
assert_eq!(map.len(), 3);
assert!(map.contains_key("2"));
assert!(map.contains_key("4"));
assert!(map.contains_key("6"));
struct Counter(Rc<Cell<u32>>);
impl Drop for Counter {
fn drop(&mut self) {
self.0.set(self.0.get() + 1);
}
}
let c = Rc::new(Cell::new(0));
let mut map = LinkedHashMap::new();
map.insert(1, Counter(Rc::clone(&c)));
map.insert(2, Counter(Rc::clone(&c)));
map.insert(3, Counter(Rc::clone(&c)));
map.insert(4, Counter(Rc::clone(&c)));
map.retain(|k, _| *k % 2 == 0);
assert!(c.get() == 2);
drop(map);
assert!(c.get() == 4);
}
#[test]
fn test_order_equality() {
let xs = [1, 2, 3, 4, 5, 6];
let mut map1: LinkedHashMap<String, i32> = xs.iter().map(|i| (i.to_string(), *i)).collect();
let mut map2: LinkedHashMap<String, i32> = xs.iter().map(|i| (i.to_string(), *i)).collect();
assert_eq!(map1, map2);
map1.to_front("4");
assert_ne!(map1, map2);
map2.to_front("4");
assert_eq!(map1, map2);
}
#[test]
fn test_replace() {
let mut map = LinkedHashMap::new();
map.insert(1, 1);
map.insert(2, 2);
map.insert(3, 3);
map.insert(4, 4);
assert!(map
.iter()
.map(|(k, v)| (*k, *v))
.eq([(1, 1), (2, 2), (3, 3), (4, 4)].iter().copied()));
map.insert(3, 5);
assert!(map
.iter()
.map(|(k, v)| (*k, *v))
.eq([(1, 1), (2, 2), (4, 4), (3, 5)].iter().copied()));
map.replace(2, 6);
assert!(map
.iter()
.map(|(k, v)| (*k, *v))
.eq([(1, 1), (2, 6), (4, 4), (3, 5)].iter().copied()));
}
#[test]
fn test_reserve() {
let mut map = LinkedHashMap::new();
map.insert(1, 1);
map.insert(2, 2);
map.insert(3, 3);
map.insert(4, 4);
assert!(map.capacity() - map.len() < 100);
map.reserve(100);
assert!(map.capacity() - map.len() >= 100);
}
#[test]
fn test_shrink_to_fit_resize() {
let mut map = LinkedHashMap::new();
map.shrink_to_fit();
for i in 0..100 {
map.insert(i, i);
}
map.shrink_to_fit();
for _ in 0..50 {
map.pop_front();
map.shrink_to_fit();
}
assert_eq!(map.len(), 50);
for i in 50..100 {
assert_eq!(map.get(&i).unwrap(), &i);
}
}
#[test]
fn test_cursor_mut_current() {
let mut map = LinkedHashMap::new();
map.insert(3, 3);
if let linked_hash_map::Entry::Occupied(entry) = map.entry(3) {
let mut cursor = entry.cursor_mut();
let value = cursor.current().unwrap();
assert_eq!(value, (&3, &mut 3));
*value.1 = 5;
let value = cursor.current().unwrap();
assert_eq!(value, (&3, &mut 5));
}
}
#[test]
fn test_cursor_mut_move_next() {
let mut map = LinkedHashMap::new();
map.insert(3, 3);
map.insert(4, 4);
map.insert(5, 5);
map.insert(6, 6);
if let linked_hash_map::Entry::Occupied(entry) = map.entry(3) {
let mut cursor = entry.cursor_mut();
let value = cursor.current();
assert!(&value.is_some());
assert_eq!(value.unwrap().1, &mut 3);
cursor.move_next();
let value = cursor.current();
assert!(&value.is_some());
assert_eq!(value.unwrap().1, &mut 4);
cursor.move_next();
let value = cursor.current();
assert!(&value.is_some());
assert_eq!(value.unwrap().1, &mut 5);
cursor.move_next();
let value = cursor.current();
assert!(&value.is_some());
assert_eq!(value.unwrap().1, &mut 6);
cursor.move_next();
let value = cursor.current();
assert!(value.is_none());
cursor.move_next();
let value = cursor.current();
assert!(value.is_some());
assert_eq!(value.unwrap().1, &mut 3);
cursor.move_next();
let value = cursor.current();
assert!(&value.is_some());
assert_eq!(value.unwrap().1, &mut 4);
}
}
#[test]
fn test_cursor_mut_move_prev() {
let mut map = LinkedHashMap::new();
map.insert(3, 3);
if let linked_hash_map::Entry::Occupied(entry) = map.entry(3) {
let mut cursor = entry.cursor_mut();
cursor.move_prev();
let value = cursor.current();
assert!(value.is_none());
cursor.move_prev();
let value = cursor.current();
assert!(&value.is_some());
assert_eq!(value.unwrap().1, &mut 3);
}
}
#[test]
fn test_cursor_mut_pick_next() {
let mut map = LinkedHashMap::new();
map.insert(3, 3);
map.insert(4, 4);
if let linked_hash_map::Entry::Occupied(entry) = map.entry(3) {
let mut cursor = entry.cursor_mut();
let next = cursor.peek_next();
assert!(&next.is_some());
assert_eq!(next.unwrap().1, &mut 4);
cursor.move_next();
let next = cursor.peek_next();
assert!(&next.is_none());
cursor.move_next();
let next = cursor.peek_next();
assert!(&next.is_some());
let value = next.as_ref().unwrap().to_owned();
assert_eq!(*value.1, 3);
*next.unwrap().1 = 5;
let next = cursor.peek_next();
assert!(&next.is_some());
assert_eq!(next.unwrap().1, &mut 5);
}
}
#[test]
fn test_cursor_mut_pick_prev() {
let mut map = LinkedHashMap::new();
map.insert(3, 3);
map.insert(4, 4);
if let linked_hash_map::Entry::Occupied(entry) = map.entry(3) {
let mut cursor = entry.cursor_mut();
let next = cursor.peek_prev();
assert!(&next.is_none());
cursor.move_prev();
let next = cursor.peek_prev();
assert!(&next.is_some());
assert_eq!(next.unwrap(), (&4, &mut 4));
}
}
#[test]
fn test_cursor_mut_insert_before() {
let mut map = LinkedHashMap::new();
map.insert(3, 3);
map.insert(4, 4);
// Insert new element in the middle
if let linked_hash_map::Entry::Occupied(entry) = map.entry(4) {
entry.cursor_mut().insert_before(5, 5);
assert!(map
.iter()
.map(|(k, v)| (*k, *v))
.eq([(3, 3), (5, 5), (4, 4)].iter().copied()));
}
// Insert new element at the very end of the list
if let linked_hash_map::Entry::Occupied(entry) = map.entry(3) {
let mut cursor = entry.cursor_mut();
cursor.move_prev();
cursor.insert_before(6, 6);
assert!(map
.iter()
.map(|(k, v)| (*k, *v))
.eq([(3, 3), (5, 5), (4, 4), (6, 6)].iter().copied()));
}
// Relocate element and override value
if let linked_hash_map::Entry::Occupied(entry) = map.entry(5) {
entry.cursor_mut().insert_before(4, 42);
assert!(map
.iter()
.map(|(k, v)| (*k, *v))
.eq([(3, 3), (4, 42), (5, 5), (6, 6)].iter().copied()));
}
}
#[test]
fn test_cursor_mut_insert_after() {
let mut map = LinkedHashMap::new();
map.insert(3, 3);
map.insert(4, 4);
// Insert new element in the middle.
if let linked_hash_map::Entry::Occupied(entry) = map.entry(3) {
entry.cursor_mut().insert_after(5, 5);
assert!(map
.iter()
.map(|(k, v)| (*k, *v))
.eq([(3, 3), (5, 5), (4, 4)].iter().copied()));
}
// Insert new element as the first one.
if let linked_hash_map::Entry::Occupied(entry) = map.entry(4) {
let mut cursor = entry.cursor_mut();
cursor.move_next();
cursor.insert_after(6, 6);
assert!(map
.iter()
.map(|(k, v)| (*k, *v))
.eq([(6, 6), (3, 3), (5, 5), (4, 4)].iter().copied()));
}
}
#[test]
fn test_cursor_mut_insert_before_itself() {
let mut map = LinkedHashMap::new();
map.insert(2, 2);
map.insert(3, 3);
map.insert(4, 4);
// Insert a new value before its key. This is a corner case that needs to be
// handled explicitly.
if let linked_hash_map::Entry::Occupied(entry) = map.entry(3) {
entry.cursor_mut().insert_before(3, 5);
assert!(map
.iter()
.map(|(k, v)| (*k, *v))
.eq([(2, 2), (3, 5), (4, 4)].iter().copied()));
}
}
#[test]
fn test_cursor_front_mut() {
let mut map: LinkedHashMap<i32, i32> = LinkedHashMap::new();
// The `CursorMut`` in an empty LinkedHashMap will always return `None` as its
// current element, regardless of any move in any direction.
let mut cursor = map.cursor_front_mut();
assert!(cursor.current().is_none());
cursor.move_next();
assert!(cursor.current().is_none());
cursor.insert_after(1, 1);
cursor.move_next();
assert!(cursor.current().is_some());
assert_eq!(cursor.current().unwrap().1, &mut 1);
cursor.move_next();
assert!(cursor.current().is_none());
assert!(map
.iter()
.map(|(k, v)| (*k, *v))
.eq([(1, 1)].iter().copied()));
map.insert(2, 2);
map.insert(3, 3);
let mut cursor = map.cursor_front_mut();
assert!(cursor.current().is_some());
assert_eq!(cursor.current().unwrap().1, &mut 1);
}
#[test]
fn test_cursor_back_mut() {
let mut map: LinkedHashMap<i32, i32> = LinkedHashMap::new();
map.insert(1, 1);
map.insert(2, 2);
map.insert(3, 3);
let mut cursor = map.cursor_back_mut();
assert!(cursor.current().is_some());
assert_eq!(cursor.current().unwrap().1, &mut 3);
}
// Regression test for https://github.com/djc/hashlink/issues/43
//
// A panic while dropping an entry during `clear` must not leave a moved-out node reachable
// from the value list, which would cause its entry to be dropped again.
#[test]
fn test_clear_panic_safe() {
struct PanicOnDrop {
should_panic: Rc<Cell<bool>>,
}
impl Drop for PanicOnDrop {
fn drop(&mut self) {
if self.should_panic.replace(false) {
panic!("intentional panic while clearing LinkedHashMap");
}
}
}
let should_panic = Rc::new(Cell::new(true));
let mut map = LinkedHashMap::new();
map.insert(
1,
PanicOnDrop {
should_panic: Rc::clone(&should_panic),
},
);
map.insert(
2,
PanicOnDrop {
should_panic: Rc::clone(&should_panic),
},
);
let result = catch_unwind(AssertUnwindSafe(|| map.clear()));
assert!(result.is_err());
should_panic.set(false);
// Dropping (or reusing) the map after the caught panic must not traverse a
// stale, moved-out node.
drop(map);
}
// Regression test for https://github.com/djc/hashlink/issues/42
//
// A key that changes its hash/equality through interior mutability inside the
// `retain_with_order` callback must not make the method remove a different table entry than the
// node it frees, which would leave the table referencing a freed node.
#[test]
fn test_retain_with_order_key_mutation_sound() {
#[derive(Debug)]
struct Key(RefCell<String>);
impl Key {
fn new(value: &str) -> Self {
Self(RefCell::new(value.to_owned()))
}
fn set(&self, value: &str) {
*self.0.borrow_mut() = value.to_owned();
}
}
impl PartialEq for Key {
fn eq(&self, other: &Self) -> bool {
self.0.borrow().as_str() == other.0.borrow().as_str()
}
}
impl Eq for Key {}
impl Hash for Key {
fn hash<H: Hasher>(&self, state: &mut H) {
self.0.borrow().hash(state);
}
}
let mut map = LinkedHashMap::new();
map.insert(Key::new("a"), 1);
map.insert(Key::new("b"), 2);
// The callback mutates the first key to compare equal to the second, then
// asks to drop it.
let mut first = true;
map.retain_with_order(|key, _| {
if first {
first = false;
key.set("b");
false
} else {
true
}
});
// Looking up a stale key must not dereference a freed node.
let _ = map.contains_key(&Key::new("a"));
}
+549
View File
@@ -0,0 +1,549 @@
use hashlink::linked_hash_set::{self, LinkedHashSet};
use hashlink::DefaultHashBuilder;
#[allow(dead_code)]
fn assert_covariance() {
fn set<'new>(v: LinkedHashSet<&'static str>) -> LinkedHashSet<&'new str> {
v
}
fn iter<'a, 'new>(
v: linked_hash_set::Iter<'a, &'static str>,
) -> linked_hash_set::Iter<'a, &'new str> {
v
}
fn into_iter<'new>(
v: linked_hash_set::IntoIter<&'static str>,
) -> linked_hash_set::IntoIter<&'new str> {
v
}
fn difference<'a, 'new>(
v: linked_hash_set::Difference<'a, &'static str, DefaultHashBuilder>,
) -> linked_hash_set::Difference<'a, &'new str, DefaultHashBuilder> {
v
}
fn symmetric_difference<'a, 'new>(
v: linked_hash_set::SymmetricDifference<'a, &'static str, DefaultHashBuilder>,
) -> linked_hash_set::SymmetricDifference<'a, &'new str, DefaultHashBuilder> {
v
}
fn intersection<'a, 'new>(
v: linked_hash_set::Intersection<'a, &'static str, DefaultHashBuilder>,
) -> linked_hash_set::Intersection<'a, &'new str, DefaultHashBuilder> {
v
}
fn union<'a, 'new>(
v: linked_hash_set::Union<'a, &'static str, DefaultHashBuilder>,
) -> linked_hash_set::Union<'a, &'new str, DefaultHashBuilder> {
v
}
fn drain<'new>(
d: linked_hash_set::Drain<'static, &'static str>,
) -> linked_hash_set::Drain<'new, &'new str> {
d
}
}
#[test]
fn test_zero_capacities() {
type HS = LinkedHashSet<i32>;
let s = HS::new();
assert_eq!(s.capacity(), 0);
let s = HS::default();
assert_eq!(s.capacity(), 0);
let s = HS::with_hasher(DefaultHashBuilder::default());
assert_eq!(s.capacity(), 0);
let s = HS::with_capacity(0);
assert_eq!(s.capacity(), 0);
let s = HS::with_capacity_and_hasher(0, DefaultHashBuilder::default());
assert_eq!(s.capacity(), 0);
let mut s = HS::new();
s.insert(1);
s.insert(2);
s.remove(&1);
s.remove(&2);
s.shrink_to_fit();
assert_eq!(s.capacity(), 0);
let mut s = HS::new();
s.reserve(0);
assert_eq!(s.capacity(), 0);
}
#[test]
fn test_disjoint() {
let mut xs = LinkedHashSet::new();
let mut ys = LinkedHashSet::new();
assert!(xs.is_disjoint(&ys));
assert!(ys.is_disjoint(&xs));
assert!(xs.insert(5));
assert!(ys.insert(11));
assert!(xs.is_disjoint(&ys));
assert!(ys.is_disjoint(&xs));
assert!(xs.insert(7));
assert!(xs.insert(19));
assert!(xs.insert(4));
assert!(ys.insert(2));
assert!(ys.insert(-11));
assert!(xs.is_disjoint(&ys));
assert!(ys.is_disjoint(&xs));
assert!(ys.insert(7));
assert!(!xs.is_disjoint(&ys));
assert!(!ys.is_disjoint(&xs));
}
#[test]
fn test_subset_and_superset() {
let mut a = LinkedHashSet::new();
assert!(a.insert(0));
assert!(a.insert(5));
assert!(a.insert(11));
assert!(a.insert(7));
let mut b = LinkedHashSet::new();
assert!(b.insert(0));
assert!(b.insert(7));
assert!(b.insert(19));
assert!(b.insert(250));
assert!(b.insert(11));
assert!(b.insert(200));
assert!(!a.is_subset(&b));
assert!(!a.is_superset(&b));
assert!(!b.is_subset(&a));
assert!(!b.is_superset(&a));
assert!(b.insert(5));
assert!(a.is_subset(&b));
assert!(!a.is_superset(&b));
assert!(!b.is_subset(&a));
assert!(b.is_superset(&a));
}
#[test]
fn test_iterate() {
let mut a = LinkedHashSet::new();
for i in 0..32 {
assert!(a.insert(i));
}
let mut observed: u32 = 0;
for k in &a {
observed |= 1 << *k;
}
assert_eq!(observed, 0xFFFF_FFFF);
}
#[test]
fn test_intersection() {
let mut a = LinkedHashSet::new();
let mut b = LinkedHashSet::new();
assert!(a.insert(11));
assert!(a.insert(1));
assert!(a.insert(3));
assert!(a.insert(77));
assert!(a.insert(103));
assert!(a.insert(5));
assert!(a.insert(-5));
assert!(b.insert(2));
assert!(b.insert(11));
assert!(b.insert(77));
assert!(b.insert(-9));
assert!(b.insert(-42));
assert!(b.insert(5));
assert!(b.insert(3));
let mut i = 0;
let expected = [3, 5, 11, 77];
for x in a.intersection(&b) {
assert!(expected.contains(x));
i += 1
}
assert_eq!(i, expected.len());
}
#[test]
fn test_difference() {
let mut a = LinkedHashSet::new();
let mut b = LinkedHashSet::new();
assert!(a.insert(1));
assert!(a.insert(3));
assert!(a.insert(5));
assert!(a.insert(9));
assert!(a.insert(11));
assert!(b.insert(3));
assert!(b.insert(9));
let mut i = 0;
let expected = [1, 5, 11];
for x in a.difference(&b) {
assert!(expected.contains(x));
i += 1
}
assert_eq!(i, expected.len());
}
#[test]
fn test_symmetric_difference() {
let mut a = LinkedHashSet::new();
let mut b = LinkedHashSet::new();
assert!(a.insert(1));
assert!(a.insert(3));
assert!(a.insert(5));
assert!(a.insert(9));
assert!(a.insert(11));
assert!(b.insert(-2));
assert!(b.insert(3));
assert!(b.insert(9));
assert!(b.insert(14));
assert!(b.insert(22));
let mut i = 0;
let expected = [-2, 1, 5, 11, 14, 22];
for x in a.symmetric_difference(&b) {
assert!(expected.contains(x));
i += 1
}
assert_eq!(i, expected.len());
}
#[test]
fn test_union() {
let mut a = LinkedHashSet::new();
let mut b = LinkedHashSet::new();
assert!(a.insert(1));
assert!(a.insert(3));
assert!(a.insert(5));
assert!(a.insert(9));
assert!(a.insert(11));
assert!(a.insert(16));
assert!(a.insert(19));
assert!(a.insert(24));
assert!(b.insert(-2));
assert!(b.insert(1));
assert!(b.insert(5));
assert!(b.insert(9));
assert!(b.insert(13));
assert!(b.insert(19));
let mut i = 0;
let expected = [-2, 1, 3, 5, 9, 11, 13, 16, 19, 24];
for x in a.union(&b) {
assert!(expected.contains(x));
i += 1
}
assert_eq!(i, expected.len());
}
#[test]
fn test_from_iter() {
let xs = [1, 2, 3, 4, 5, 6, 7, 8, 9];
let set: LinkedHashSet<_> = xs.iter().cloned().collect();
for x in &xs {
assert!(set.contains(x));
}
}
#[test]
fn test_move_iter() {
let hs = {
let mut hs = LinkedHashSet::new();
hs.insert('a');
hs.insert('b');
hs
};
let v = hs.into_iter().collect::<Vec<char>>();
assert!(v == ['a', 'b'] || v == ['b', 'a']);
}
#[test]
fn test_eq() {
let mut s1 = LinkedHashSet::new();
s1.insert(1);
s1.insert(2);
s1.insert(3);
let mut s2 = LinkedHashSet::new();
s2.insert(1);
s2.insert(2);
assert!(s1 != s2);
s2.insert(3);
assert_eq!(s1, s2);
}
#[test]
fn test_show() {
let mut set = LinkedHashSet::new();
let empty = LinkedHashSet::<i32>::new();
set.insert(1);
set.insert(2);
let set_str = format!("{:?}", set);
assert!(set_str == "{1, 2}" || set_str == "{2, 1}");
assert_eq!(format!("{:?}", empty), "{}");
}
#[test]
fn test_trivial_drain() {
let mut s = LinkedHashSet::<i32>::new();
for _ in s.drain() {}
assert!(s.is_empty());
drop(s);
let mut s = LinkedHashSet::<i32>::new();
drop(s.drain());
assert!(s.is_empty());
}
#[test]
fn test_drain() {
let mut s: LinkedHashSet<_> = (1..100).collect();
for _ in 0..20 {
assert_eq!(s.len(), 99);
{
let mut last_i = 0;
let mut d = s.drain();
for (i, x) in d.by_ref().take(50).enumerate() {
last_i = i;
assert!(x != 0);
}
assert_eq!(last_i, 49);
}
assert_eq!((&s).into_iter().count(), 0);
s.extend(1..100);
}
}
#[test]
fn test_replace() {
use core::hash;
#[derive(Debug)]
struct Foo(&'static str, i32);
impl PartialEq for Foo {
fn eq(&self, other: &Self) -> bool {
self.0 == other.0
}
}
impl Eq for Foo {}
impl hash::Hash for Foo {
fn hash<H: hash::Hasher>(&self, h: &mut H) {
self.0.hash(h);
}
}
impl Foo {
fn really_eq(&self, other: &Self) -> bool {
self.0 == other.0 && self.1 == other.1
}
}
let mut s = LinkedHashSet::new();
assert_eq!(s.replace(Foo("a", 1)), None);
assert_eq!(s.len(), 1);
assert_eq!(
s.replace(Foo("a", 2)).map(|f| f.really_eq(&Foo("a", 1))),
Some(true)
);
assert_eq!(s.len(), 1);
let mut it = s.iter();
assert_eq!(it.next().map(|f| f.really_eq(&Foo("a", 2))), Some(true));
assert_eq!(it.next(), None);
}
#[test]
fn test_extend_ref() {
let mut a = LinkedHashSet::new();
a.insert(1);
a.extend(&[2, 3, 4]);
assert_eq!(a.len(), 4);
assert!(a.contains(&1));
assert!(a.contains(&2));
assert!(a.contains(&3));
assert!(a.contains(&4));
let mut b = LinkedHashSet::new();
b.insert(5);
b.insert(6);
a.extend(&b);
assert_eq!(a.len(), 6);
assert!(a.contains(&1));
assert!(a.contains(&2));
assert!(a.contains(&3));
assert!(a.contains(&4));
assert!(a.contains(&5));
assert!(a.contains(&6));
}
#[test]
fn test_retain() {
let xs = [1, 2, 3, 4, 5, 6];
let mut set: LinkedHashSet<i32> = xs.iter().cloned().collect();
set.retain(|&k| k % 2 == 0);
assert_eq!(set.len(), 3);
assert!(set.contains(&2));
assert!(set.contains(&4));
assert!(set.contains(&6));
}
#[test]
fn test_retain_with_order() {
let xs = [1, 2, 3, 4, 5, 6];
let mut set: LinkedHashSet<i32> = xs.iter().cloned().collect();
let mut vec = Vec::new();
set.retain_with_order(|&k| {
if k % 2 == 0 {
true
} else {
vec.push(k);
false
}
});
assert_eq!(vec![1, 3, 5], vec);
}
#[test]
fn insert_order() {
let mut set = LinkedHashSet::new();
set.insert(1);
set.insert(2);
set.insert(3);
set.insert(4);
assert_eq!(
set.clone().into_iter().collect::<Vec<_>>(),
vec![1, 2, 3, 4]
);
assert_eq!(set.into_iter().collect::<Vec<_>>(), vec![1, 2, 3, 4]);
}
#[test]
fn front_back() {
let mut set = LinkedHashSet::new();
set.insert(1);
set.insert(2);
set.insert(3);
set.insert(4);
assert_eq!(set.front(), Some(&1));
assert_eq!(set.back(), Some(&4));
assert_eq!(set.pop_back(), Some(4));
assert_eq!(set.back(), Some(&3));
assert_eq!(set.pop_front(), Some(1));
assert_eq!(set.front(), Some(&2));
}
#[test]
fn double_ended_iter() {
let mut set = LinkedHashSet::new();
set.insert(1);
set.insert(2);
set.insert(3);
set.insert(4);
let mut iter = set.iter();
assert_eq!(iter.next(), Some(&1));
assert_eq!(iter.next(), Some(&2));
assert_eq!(iter.next_back(), Some(&4));
assert_eq!(iter.next_back(), Some(&3));
assert_eq!(iter.next_back(), None);
assert_eq!(iter.next(), None);
assert_eq!(iter.next_back(), None);
let mut iter = set.drain();
assert_eq!(iter.next(), Some(1));
assert_eq!(iter.next(), Some(2));
assert_eq!(iter.next_back(), Some(4));
assert_eq!(iter.next_back(), Some(3));
assert_eq!(iter.next_back(), None);
assert_eq!(iter.next(), None);
assert_eq!(iter.next_back(), None);
drop(iter);
set.insert(1);
set.insert(2);
set.insert(3);
set.insert(4);
let mut iter = set.into_iter();
assert_eq!(iter.next(), Some(1));
assert_eq!(iter.next(), Some(2));
assert_eq!(iter.next_back(), Some(4));
assert_eq!(iter.next_back(), Some(3));
assert_eq!(iter.next_back(), None);
assert_eq!(iter.next(), None);
assert_eq!(iter.next_back(), None);
}
#[test]
fn to_back_front_order() {
let mut set = LinkedHashSet::new();
set.insert(1);
set.insert(2);
set.insert(3);
set.insert(4);
assert_eq!(set.back().copied(), Some(4));
assert_eq!(set.front().copied(), Some(1));
set.to_back(&2);
assert_eq!(set.back().copied(), Some(2));
set.to_front(&3);
assert_eq!(set.front().copied(), Some(3));
}
#[test]
fn test_order_equality() {
let xs = [1, 2, 3, 4, 5, 6];
let mut set1: LinkedHashSet<i32> = xs.iter().copied().collect();
let mut set2: LinkedHashSet<i32> = xs.iter().copied().collect();
assert_eq!(set1, set2);
set1.to_front(&4);
assert_ne!(set1, set2);
set2.to_front(&4);
assert_eq!(set1, set2);
}
+166
View File
@@ -0,0 +1,166 @@
use hashlink::LruCache;
#[test]
fn test_put_and_get() {
let mut cache = LruCache::new(2);
cache.insert(1, 10);
cache.insert(2, 20);
assert_eq!(cache.get_mut(&1), Some(&mut 10));
assert_eq!(cache.get_mut(&2), Some(&mut 20));
assert_eq!(cache.len(), 2);
}
#[test]
fn test_put_update() {
let mut cache = LruCache::new(1);
cache.insert("1", 10);
cache.insert("1", 19);
assert_eq!(cache.get_mut("1"), Some(&mut 19));
assert_eq!(cache.len(), 1);
}
#[test]
fn test_contains_key() {
let mut cache = LruCache::new(1);
cache.insert("1", 10);
assert!(cache.contains_key("1"));
}
#[test]
fn test_expire_lru() {
let mut cache = LruCache::new(2);
cache.insert("foo1", "bar1");
cache.insert("foo2", "bar2");
cache.insert("foo3", "bar3");
assert!(cache.get_mut("foo1").is_none());
cache.insert("foo2", "bar2update");
cache.insert("foo4", "bar4");
assert!(cache.get_mut("foo3").is_none());
}
#[test]
fn test_pop() {
let mut cache = LruCache::new(2);
cache.insert(1, 10);
cache.insert(2, 20);
assert_eq!(cache.len(), 2);
let opt1 = cache.remove(&1);
assert!(opt1.is_some());
assert_eq!(opt1.unwrap(), 10);
assert!(cache.get_mut(&1).is_none());
assert_eq!(cache.len(), 1);
}
#[test]
fn test_change_capacity() {
let mut cache = LruCache::new(2);
assert_eq!(cache.capacity(), 2);
cache.insert(1, 10);
cache.insert(2, 20);
cache.set_capacity(1);
assert!(cache.get_mut(&1).is_none());
assert_eq!(cache.capacity(), 1);
}
#[test]
fn test_remove() {
let mut cache = LruCache::new(3);
cache.insert(1, 10);
cache.insert(2, 20);
cache.insert(3, 30);
cache.insert(4, 40);
cache.insert(5, 50);
cache.remove(&3);
cache.remove(&4);
assert!(cache.get_mut(&3).is_none());
assert!(cache.get_mut(&4).is_none());
cache.insert(6, 60);
cache.insert(7, 70);
cache.insert(8, 80);
assert!(cache.get_mut(&5).is_none());
assert_eq!(cache.get_mut(&6), Some(&mut 60));
assert_eq!(cache.get_mut(&7), Some(&mut 70));
assert_eq!(cache.get_mut(&8), Some(&mut 80));
}
#[test]
fn test_clear() {
let mut cache = LruCache::new(2);
cache.insert(1, 10);
cache.insert(2, 20);
cache.clear();
assert!(cache.get_mut(&1).is_none());
assert!(cache.get_mut(&2).is_none());
assert!(cache.is_empty())
}
#[test]
fn test_iter() {
let mut cache = LruCache::new(3);
cache.insert(1, 10);
cache.insert(2, 20);
cache.insert(3, 30);
cache.insert(4, 40);
cache.insert(5, 50);
assert_eq!(
cache.iter().collect::<Vec<_>>(),
[(&3, &30), (&4, &40), (&5, &50)]
);
assert_eq!(
cache.iter_mut().collect::<Vec<_>>(),
[(&3, &mut 30), (&4, &mut 40), (&5, &mut 50)]
);
assert_eq!(
cache.iter().rev().collect::<Vec<_>>(),
[(&5, &50), (&4, &40), (&3, &30)]
);
assert_eq!(
cache.iter_mut().rev().collect::<Vec<_>>(),
[(&5, &mut 50), (&4, &mut 40), (&3, &mut 30)]
);
}
#[test]
fn test_peek() {
let mut cache = LruCache::new_unbounded();
cache.insert(1, 10);
cache.insert(2, 20);
cache.insert(3, 30);
cache.insert(4, 40);
cache.insert(5, 50);
cache.insert(6, 60);
assert_eq!(cache.remove_lru(), Some((1, 10)));
assert_eq!(cache.peek(&2), Some(&20));
assert_eq!(cache.remove_lru(), Some((2, 20)));
assert_eq!(cache.peek_mut(&3), Some(&mut 30));
assert_eq!(cache.remove_lru(), Some((3, 30)));
assert_eq!(cache.get(&4), Some(&40));
assert_eq!(cache.remove_lru(), Some((5, 50)));
}
#[test]
fn test_entry() {
let mut cache = LruCache::new(4);
cache.insert(1, 10);
cache.insert(2, 20);
cache.insert(3, 30);
cache.insert(4, 40);
cache.insert(5, 50);
cache.insert(6, 60);
assert_eq!(cache.len(), 4);
cache.entry(7).or_insert(70);
cache.entry(8).or_insert(80);
cache.entry(9).or_insert(90);
assert!(cache.len() <= 5);
cache.raw_entry_mut().from_key(&10).or_insert(10, 100);
cache.raw_entry_mut().from_key(&11).or_insert(11, 110);
cache.raw_entry_mut().from_key(&12).or_insert(12, 120);
assert!(cache.len() <= 5);
}
+110
View File
@@ -0,0 +1,110 @@
#![cfg(feature = "serde_impl")]
use std::hash::BuildHasherDefault;
use hashlink::{LinkedHashMap, LinkedHashSet};
use rustc_hash::FxHasher;
use serde_test::{assert_tokens, Token};
#[test]
fn map_serde_tokens_empty() {
let map = LinkedHashMap::<char, u32>::new();
assert_tokens(&map, &[Token::Map { len: Some(0) }, Token::MapEnd]);
}
#[test]
fn map_serde_tokens() {
let mut map = LinkedHashMap::new();
map.insert('a', 10);
map.insert('b', 20);
map.insert('c', 30);
assert_tokens(
&map,
&[
Token::Map { len: Some(3) },
Token::Char('a'),
Token::I32(10),
Token::Char('b'),
Token::I32(20),
Token::Char('c'),
Token::I32(30),
Token::MapEnd,
],
);
}
#[test]
fn map_serde_tokens_empty_generic() {
let map = LinkedHashMap::<char, u32, BuildHasherDefault<FxHasher>>::default();
assert_tokens(&map, &[Token::Map { len: Some(0) }, Token::MapEnd]);
}
#[test]
fn map_serde_tokens_generic() {
let mut map = LinkedHashMap::<char, i32, BuildHasherDefault<FxHasher>>::default();
map.insert('a', 10);
map.insert('b', 20);
map.insert('c', 30);
assert_tokens(
&map,
&[
Token::Map { len: Some(3) },
Token::Char('a'),
Token::I32(10),
Token::Char('b'),
Token::I32(20),
Token::Char('c'),
Token::I32(30),
Token::MapEnd,
],
);
}
#[test]
fn set_serde_tokens_empty() {
let set = LinkedHashSet::<u32>::new();
assert_tokens(&set, &[Token::Seq { len: Some(0) }, Token::SeqEnd]);
}
#[test]
fn set_serde_tokens() {
let mut set = LinkedHashSet::new();
set.insert(10);
set.insert(20);
set.insert(30);
assert_tokens(
&set,
&[
Token::Seq { len: Some(3) },
Token::I32(10),
Token::I32(20),
Token::I32(30),
Token::SeqEnd,
],
);
}
#[test]
fn set_serde_tokens_generic() {
let mut set = LinkedHashSet::<char, BuildHasherDefault<FxHasher>>::default();
set.insert('a');
set.insert('b');
set.insert('c');
assert_tokens(
&set,
&[
Token::Seq { len: Some(3) },
Token::Char('a'),
Token::Char('b'),
Token::Char('c'),
Token::SeqEnd,
],
);
}