logiguard fork v3: full patch set on verified 8c74db0 tree
Includes prior-session patches (carry forward so the app compiles): - crates/gpui/build.rs: cross-compile manifest fix - crates/gpui/src/platform.rs: PlatformWindow::activate_with_token trait method - crates/gpui/src/window.rs: Window::activate_with_token public API - crates/gpui_linux/src/linux/wayland/window.rs: WaylandWindow::activate_with_token + activate() keyboard-serial fix Plus the focus-serial fix: - serial.rs: SerialKind::KeyboardEnter - client.rs: store wl_keyboard.enter serial; latest_serial_of() Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
21
crates/collections/Cargo.toml
Normal file
21
crates/collections/Cargo.toml
Normal file
@@ -0,0 +1,21 @@
|
||||
[package]
|
||||
name = "collections"
|
||||
version = "0.1.0"
|
||||
edition.workspace = true
|
||||
publish = false
|
||||
license = "Apache-2.0"
|
||||
description = "Standard collection types used by Zed and GPUI"
|
||||
|
||||
[lints]
|
||||
workspace = true
|
||||
|
||||
[lib]
|
||||
path = "src/collections.rs"
|
||||
doctest = false
|
||||
|
||||
[features]
|
||||
test-support = []
|
||||
|
||||
[dependencies]
|
||||
indexmap.workspace = true
|
||||
rustc-hash.workspace = true
|
||||
1
crates/collections/LICENSE-APACHE
Symbolic link
1
crates/collections/LICENSE-APACHE
Symbolic link
@@ -0,0 +1 @@
|
||||
../../LICENSE-APACHE
|
||||
13
crates/collections/src/collections.rs
Normal file
13
crates/collections/src/collections.rs
Normal file
@@ -0,0 +1,13 @@
|
||||
pub type HashMap<K, V> = FxHashMap<K, V>;
|
||||
pub type HashSet<T> = FxHashSet<T>;
|
||||
pub type IndexMap<K, V> = indexmap::IndexMap<K, V, rustc_hash::FxBuildHasher>;
|
||||
pub type IndexSet<T> = indexmap::IndexSet<T, rustc_hash::FxBuildHasher>;
|
||||
|
||||
pub use indexmap::Equivalent;
|
||||
pub use rustc_hash::FxHasher;
|
||||
pub use rustc_hash::{FxHashMap, FxHashSet};
|
||||
pub use std::collections::*;
|
||||
|
||||
pub mod vecmap;
|
||||
#[cfg(test)]
|
||||
mod vecmap_tests;
|
||||
192
crates/collections/src/vecmap.rs
Normal file
192
crates/collections/src/vecmap.rs
Normal file
@@ -0,0 +1,192 @@
|
||||
/// A collection that provides a map interface but is backed by vectors.
|
||||
///
|
||||
/// This is suitable for small key-value stores where the item count is not
|
||||
/// large enough to overcome the overhead of a more complex algorithm.
|
||||
///
|
||||
/// If this meets your use cases, then [`VecMap`] should be a drop-in
|
||||
/// replacement for [`std::collections::HashMap`] or [`crate::HashMap`]. Note
|
||||
/// that we are adding APIs on an as-needed basis. If the API you need is not
|
||||
/// present yet, please add it!
|
||||
///
|
||||
/// Because it uses vectors as a backing store, the map also iterates over items
|
||||
/// in insertion order, like [`crate::IndexMap`].
|
||||
///
|
||||
/// This struct uses a struct-of-arrays (SoA) representation which tends to be
|
||||
/// more cache efficient and promotes autovectorization when using simple key or
|
||||
/// value types.
|
||||
#[derive(Default)]
|
||||
pub struct VecMap<K, V> {
|
||||
keys: Vec<K>,
|
||||
values: Vec<V>,
|
||||
}
|
||||
|
||||
impl<K, V> VecMap<K, V> {
|
||||
pub fn new() -> Self {
|
||||
Self {
|
||||
keys: Vec::new(),
|
||||
values: Vec::new(),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn iter(&self) -> Iter<'_, K, V> {
|
||||
Iter {
|
||||
iter: self.keys.iter().zip(self.values.iter()),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<K: Eq, V> VecMap<K, V> {
|
||||
pub fn entry(&mut self, key: K) -> Entry<'_, K, V> {
|
||||
match self.keys.iter().position(|k| k == &key) {
|
||||
Some(index) => Entry::Occupied(OccupiedEntry {
|
||||
key: &self.keys[index],
|
||||
value: &mut self.values[index],
|
||||
}),
|
||||
None => Entry::Vacant(VacantEntry { map: self, key }),
|
||||
}
|
||||
}
|
||||
|
||||
/// Like [`Self::entry`] but takes its key by reference instead of by value.
|
||||
///
|
||||
/// This can be helpful if you have a key where cloning is expensive, as we
|
||||
/// can avoid cloning the key until a value is inserted under that entry.
|
||||
pub fn entry_ref<'a, 'k>(&'a mut self, key: &'k K) -> EntryRef<'k, 'a, K, V> {
|
||||
match self.keys.iter().position(|k| k == key) {
|
||||
Some(index) => EntryRef::Occupied(OccupiedEntry {
|
||||
key: &self.keys[index],
|
||||
value: &mut self.values[index],
|
||||
}),
|
||||
None => EntryRef::Vacant(VacantEntryRef { map: self, key }),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub struct Iter<'a, K, V> {
|
||||
iter: std::iter::Zip<std::slice::Iter<'a, K>, std::slice::Iter<'a, V>>,
|
||||
}
|
||||
|
||||
impl<'a, K, V> Iterator for Iter<'a, K, V> {
|
||||
type Item = (&'a K, &'a V);
|
||||
|
||||
fn next(&mut self) -> Option<Self::Item> {
|
||||
self.iter.next()
|
||||
}
|
||||
}
|
||||
|
||||
pub enum Entry<'a, K, V> {
|
||||
Occupied(OccupiedEntry<'a, K, V>),
|
||||
Vacant(VacantEntry<'a, K, V>),
|
||||
}
|
||||
|
||||
impl<'a, K, V> Entry<'a, K, V> {
|
||||
pub fn key(&self) -> &K {
|
||||
match self {
|
||||
Entry::Occupied(entry) => entry.key,
|
||||
Entry::Vacant(entry) => &entry.key,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn or_insert_with_key<F>(self, default: F) -> &'a mut V
|
||||
where
|
||||
F: FnOnce(&K) -> V,
|
||||
{
|
||||
match self {
|
||||
Entry::Occupied(entry) => entry.value,
|
||||
Entry::Vacant(entry) => {
|
||||
entry.map.values.push(default(&entry.key));
|
||||
entry.map.keys.push(entry.key);
|
||||
match entry.map.values.last_mut() {
|
||||
Some(value) => value,
|
||||
None => unreachable!("vec empty after pushing to it"),
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn or_insert_with<F>(self, default: F) -> &'a mut V
|
||||
where
|
||||
F: FnOnce() -> V,
|
||||
{
|
||||
self.or_insert_with_key(|_| default())
|
||||
}
|
||||
|
||||
pub fn or_insert(self, value: V) -> &'a mut V {
|
||||
self.or_insert_with_key(|_| value)
|
||||
}
|
||||
|
||||
pub fn or_insert_default(self) -> &'a mut V
|
||||
where
|
||||
V: Default,
|
||||
{
|
||||
self.or_insert_with_key(|_| Default::default())
|
||||
}
|
||||
}
|
||||
|
||||
pub struct OccupiedEntry<'a, K, V> {
|
||||
key: &'a K,
|
||||
value: &'a mut V,
|
||||
}
|
||||
|
||||
pub struct VacantEntry<'a, K, V> {
|
||||
map: &'a mut VecMap<K, V>,
|
||||
key: K,
|
||||
}
|
||||
|
||||
pub enum EntryRef<'key, 'map, K, V> {
|
||||
Occupied(OccupiedEntry<'map, K, V>),
|
||||
Vacant(VacantEntryRef<'key, 'map, K, V>),
|
||||
}
|
||||
|
||||
impl<'key, 'map, K, V> EntryRef<'key, 'map, K, V> {
|
||||
pub fn key(&self) -> &K {
|
||||
match self {
|
||||
EntryRef::Occupied(entry) => entry.key,
|
||||
EntryRef::Vacant(entry) => entry.key,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'key, 'map, K, V> EntryRef<'key, 'map, K, V>
|
||||
where
|
||||
K: Clone,
|
||||
{
|
||||
pub fn or_insert_with_key<F>(self, default: F) -> &'map mut V
|
||||
where
|
||||
F: FnOnce(&K) -> V,
|
||||
{
|
||||
match self {
|
||||
EntryRef::Occupied(entry) => entry.value,
|
||||
EntryRef::Vacant(entry) => {
|
||||
entry.map.values.push(default(entry.key));
|
||||
entry.map.keys.push(entry.key.clone());
|
||||
match entry.map.values.last_mut() {
|
||||
Some(value) => value,
|
||||
None => unreachable!("vec empty after pushing to it"),
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn or_insert_with<F>(self, default: F) -> &'map mut V
|
||||
where
|
||||
F: FnOnce() -> V,
|
||||
{
|
||||
self.or_insert_with_key(|_| default())
|
||||
}
|
||||
|
||||
pub fn or_insert(self, value: V) -> &'map mut V {
|
||||
self.or_insert_with_key(|_| value)
|
||||
}
|
||||
|
||||
pub fn or_insert_default(self) -> &'map mut V
|
||||
where
|
||||
V: Default,
|
||||
{
|
||||
self.or_insert_with_key(|_| Default::default())
|
||||
}
|
||||
}
|
||||
|
||||
pub struct VacantEntryRef<'key, 'map, K, V> {
|
||||
map: &'map mut VecMap<K, V>,
|
||||
key: &'key K,
|
||||
}
|
||||
211
crates/collections/src/vecmap_tests.rs
Normal file
211
crates/collections/src/vecmap_tests.rs
Normal file
@@ -0,0 +1,211 @@
|
||||
//! Tests for the VecMap collection.
|
||||
//!
|
||||
//! This is in a sibling module so that the tests are guaranteed to only cover
|
||||
//! states that can be created by the public API.
|
||||
|
||||
use crate::vecmap::*;
|
||||
|
||||
#[test]
|
||||
fn test_entry_vacant_or_insert() {
|
||||
let mut map: VecMap<&str, i32> = VecMap::new();
|
||||
let value = map.entry("a").or_insert(1);
|
||||
assert_eq!(*value, 1);
|
||||
assert_eq!(map.iter().collect::<Vec<_>>(), vec![(&"a", &1)]);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_entry_occupied_or_insert_keeps_existing() {
|
||||
let mut map: VecMap<&str, i32> = VecMap::new();
|
||||
map.entry("a").or_insert(1);
|
||||
let value = map.entry("a").or_insert(99);
|
||||
assert_eq!(*value, 1);
|
||||
assert_eq!(map.iter().collect::<Vec<_>>(), vec![(&"a", &1)]);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_entry_or_insert_with() {
|
||||
let mut map: VecMap<&str, i32> = VecMap::new();
|
||||
map.entry("a").or_insert_with(|| 42);
|
||||
assert_eq!(map.iter().collect::<Vec<_>>(), vec![(&"a", &42)]);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_entry_or_insert_with_not_called_when_occupied() {
|
||||
let mut map: VecMap<&str, i32> = VecMap::new();
|
||||
map.entry("a").or_insert(1);
|
||||
map.entry("a")
|
||||
.or_insert_with(|| panic!("should not be called"));
|
||||
assert_eq!(map.iter().collect::<Vec<_>>(), vec![(&"a", &1)]);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_entry_or_insert_with_key() {
|
||||
let mut map: VecMap<&str, String> = VecMap::new();
|
||||
map.entry("hello").or_insert_with_key(|k| k.to_uppercase());
|
||||
assert_eq!(
|
||||
map.iter().collect::<Vec<_>>(),
|
||||
vec![(&"hello", &"HELLO".to_string())]
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_entry_or_insert_default() {
|
||||
let mut map: VecMap<&str, i32> = VecMap::new();
|
||||
map.entry("a").or_insert_default();
|
||||
assert_eq!(map.iter().collect::<Vec<_>>(), vec![(&"a", &0)]);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_entry_key() {
|
||||
let mut map: VecMap<&str, i32> = VecMap::new();
|
||||
assert_eq!(*map.entry("a").key(), "a");
|
||||
map.entry("a").or_insert(1);
|
||||
assert_eq!(*map.entry("a").key(), "a");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_entry_mut_ref_can_be_updated() {
|
||||
let mut map: VecMap<&str, i32> = VecMap::new();
|
||||
let value = map.entry("a").or_insert(0);
|
||||
*value = 5;
|
||||
assert_eq!(map.iter().collect::<Vec<_>>(), vec![(&"a", &5)]);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_insertion_order_preserved() {
|
||||
let mut map: VecMap<&str, i32> = VecMap::new();
|
||||
map.entry("b").or_insert(2);
|
||||
map.entry("a").or_insert(1);
|
||||
map.entry("c").or_insert(3);
|
||||
assert_eq!(
|
||||
map.iter().collect::<Vec<_>>(),
|
||||
vec![(&"b", &2), (&"a", &1), (&"c", &3)]
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_multiple_entries_independent() {
|
||||
let mut map: VecMap<i32, i32> = VecMap::new();
|
||||
map.entry(1).or_insert(10);
|
||||
map.entry(2).or_insert(20);
|
||||
map.entry(3).or_insert(30);
|
||||
assert_eq!(map.iter().count(), 3);
|
||||
// Re-inserting does not duplicate keys
|
||||
map.entry(1).or_insert(99);
|
||||
assert_eq!(map.iter().count(), 3);
|
||||
}
|
||||
|
||||
// entry_ref tests
|
||||
|
||||
use std::cell::Cell;
|
||||
use std::rc::Rc;
|
||||
|
||||
#[derive(PartialEq, Eq)]
|
||||
struct CountedKey {
|
||||
value: String,
|
||||
clone_count: Rc<Cell<usize>>,
|
||||
}
|
||||
|
||||
impl Clone for CountedKey {
|
||||
fn clone(&self) -> Self {
|
||||
self.clone_count.set(self.clone_count.get() + 1);
|
||||
CountedKey {
|
||||
value: self.value.clone(),
|
||||
clone_count: self.clone_count.clone(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_entry_ref_vacant_or_insert() {
|
||||
let mut map: VecMap<String, i32> = VecMap::new();
|
||||
let key = "a".to_string();
|
||||
let value = map.entry_ref(&key).or_insert(1);
|
||||
assert_eq!(*value, 1);
|
||||
assert_eq!(map.iter().count(), 1);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_entry_ref_occupied_or_insert_keeps_existing() {
|
||||
let mut map: VecMap<String, i32> = VecMap::new();
|
||||
map.entry_ref(&"a".to_string()).or_insert(1);
|
||||
let value = map.entry_ref(&"a".to_string()).or_insert(99);
|
||||
assert_eq!(*value, 1);
|
||||
assert_eq!(map.iter().count(), 1);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_entry_ref_key_not_cloned_when_occupied() {
|
||||
let clone_count = Rc::new(Cell::new(0));
|
||||
let key = CountedKey {
|
||||
value: "a".to_string(),
|
||||
clone_count: clone_count.clone(),
|
||||
};
|
||||
|
||||
let mut map: VecMap<CountedKey, i32> = VecMap::new();
|
||||
map.entry_ref(&key).or_insert(1);
|
||||
let clones_after_insert = clone_count.get();
|
||||
|
||||
// Looking up an existing key must not clone it.
|
||||
map.entry_ref(&key).or_insert(99);
|
||||
assert_eq!(clone_count.get(), clones_after_insert);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_entry_ref_key_cloned_exactly_once_on_vacant_insert() {
|
||||
let clone_count = Rc::new(Cell::new(0));
|
||||
let key = CountedKey {
|
||||
value: "a".to_string(),
|
||||
clone_count: clone_count.clone(),
|
||||
};
|
||||
|
||||
let mut map: VecMap<CountedKey, i32> = VecMap::new();
|
||||
map.entry_ref(&key).or_insert(1);
|
||||
assert_eq!(clone_count.get(), 1);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_entry_ref_or_insert_with_key() {
|
||||
let mut map: VecMap<String, String> = VecMap::new();
|
||||
let key = "hello".to_string();
|
||||
map.entry_ref(&key).or_insert_with_key(|k| k.to_uppercase());
|
||||
assert_eq!(
|
||||
map.iter().collect::<Vec<_>>(),
|
||||
vec![(&"hello".to_string(), &"HELLO".to_string())]
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_entry_ref_or_insert_with_not_called_when_occupied() {
|
||||
let mut map: VecMap<String, i32> = VecMap::new();
|
||||
let key = "a".to_string();
|
||||
map.entry_ref(&key).or_insert(1);
|
||||
map.entry_ref(&key)
|
||||
.or_insert_with(|| panic!("should not be called"));
|
||||
assert_eq!(map.iter().collect::<Vec<_>>(), vec![(&key, &1)]);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_entry_ref_or_insert_default() {
|
||||
let mut map: VecMap<String, i32> = VecMap::new();
|
||||
map.entry_ref(&"a".to_string()).or_insert_default();
|
||||
assert_eq!(map.iter().collect::<Vec<_>>(), vec![(&"a".to_string(), &0)]);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_entry_ref_key() {
|
||||
let mut map: VecMap<String, i32> = VecMap::new();
|
||||
let key = "a".to_string();
|
||||
assert_eq!(*map.entry_ref(&key).key(), key);
|
||||
map.entry_ref(&key).or_insert(1);
|
||||
assert_eq!(*map.entry_ref(&key).key(), key);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_entry_ref_mut_ref_can_be_updated() {
|
||||
let mut map: VecMap<String, i32> = VecMap::new();
|
||||
let key = "a".to_string();
|
||||
let value = map.entry_ref(&key).or_insert(0);
|
||||
*value = 5;
|
||||
assert_eq!(map.iter().collect::<Vec<_>>(), vec![(&key, &5)]);
|
||||
}
|
||||
Reference in New Issue
Block a user