From cf270b4dff8f48d702652f7b958bc139581bafdf Mon Sep 17 00:00:00 2001 From: Nathan Sobo Date: Fri, 1 Oct 2021 15:55:21 -0600 Subject: [PATCH] Extract sum_tree to its own crate Co-Authored-By: Max Brunsfeld --- Cargo.lock | 11 +- Cargo.toml | 2 +- gpui/Cargo.toml | 2 +- gpui/src/elements/list.rs | 2 +- gpui/src/lib.rs | 1 - sum_tree/Cargo.toml | 12 ++ {gpui/src/sum_tree => sum_tree/src}/cursor.rs | 0 gpui/src/sum_tree.rs => sum_tree/src/lib.rs | 194 ++++++++++-------- zed/Cargo.toml | 1 + zed/src/channel.rs | 2 +- zed/src/editor/buffer.rs | 2 +- zed/src/editor/buffer/operation_queue.rs | 2 +- zed/src/editor/buffer/rope.rs | 2 +- zed/src/editor/display_map/fold_map.rs | 6 +- zed/src/editor/display_map/wrap_map.rs | 8 +- zed/src/util.rs | 4 +- zed/src/worktree.rs | 2 +- 17 files changed, 141 insertions(+), 112 deletions(-) create mode 100644 sum_tree/Cargo.toml rename {gpui/src/sum_tree => sum_tree/src}/cursor.rs (100%) rename gpui/src/sum_tree.rs => sum_tree/src/lib.rs (86%) diff --git a/Cargo.lock b/Cargo.lock index 57fb05322f..e1c8cb0c5f 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2175,7 +2175,6 @@ name = "gpui" version = "0.1.0" dependencies = [ "anyhow", - "arrayvec 0.7.1", "async-task", "backtrace", "bindgen", @@ -2212,6 +2211,7 @@ dependencies = [ "simplelog", "smallvec", "smol", + "sum_tree", "time 0.3.2", "tiny-skia", "tree-sitter", @@ -4940,6 +4940,14 @@ version = "2.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1e81da0851ada1f3e9d4312c704aa4f8806f0f9d69faaf8df2f3464b4a9437c2" +[[package]] +name = "sum_tree" +version = "0.1.0" +dependencies = [ + "arrayvec 0.7.1", + "rand 0.8.3", +] + [[package]] name = "surf" version = "2.2.0" @@ -5927,6 +5935,7 @@ dependencies = [ "simplelog", "smallvec", "smol", + "sum_tree", "surf", "tempdir", "thiserror", diff --git a/Cargo.toml b/Cargo.toml index 248326d871..96a40d043e 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,5 +1,5 @@ [workspace] -members = ["fsevent", "gpui", "gpui_macros", "server", "zed", "zrpc"] +members = ["fsevent", "gpui", "gpui_macros", "server", "sum_tree", "zed", "zrpc"] default-members = ["zed"] [patch.crates-io] diff --git a/gpui/Cargo.toml b/gpui/Cargo.toml index be86a788d8..ae01eaba63 100644 --- a/gpui/Cargo.toml +++ b/gpui/Cargo.toml @@ -8,7 +8,6 @@ version = "0.1.0" test-support = [] [dependencies] -arrayvec = "0.7.1" async-task = "4.0.3" backtrace = "0.3" ctor = "0.1" @@ -31,6 +30,7 @@ serde = { version = "1.0.125", features = ["derive"] } serde_json = "1.0.64" smallvec = { version = "1.6", features = ["union"] } smol = "1.2" +sum_tree = { path = "../sum_tree" } time = { version = "0.3" } tiny-skia = "0.5" tree-sitter = "0.19" diff --git a/gpui/src/elements/list.rs b/gpui/src/elements/list.rs index 219c175168..3fbd2a6d28 100644 --- a/gpui/src/elements/list.rs +++ b/gpui/src/elements/list.rs @@ -4,11 +4,11 @@ use crate::{ vector::{vec2f, Vector2F}, }, json::json, - sum_tree::{self, Bias, SumTree}, DebugContext, Element, ElementBox, ElementRc, Event, EventContext, LayoutContext, PaintContext, SizeConstraint, }; use std::{cell::RefCell, collections::VecDeque, ops::Range, rc::Rc}; +use sum_tree::{self, Bias, SumTree}; pub struct List { state: ListState, diff --git a/gpui/src/lib.rs b/gpui/src/lib.rs index 4b4d5f25d5..2ea6c32257 100644 --- a/gpui/src/lib.rs +++ b/gpui/src/lib.rs @@ -1,7 +1,6 @@ mod app; pub use app::*; mod assets; -pub mod sum_tree; #[cfg(test)] mod test; pub use assets::*; diff --git a/sum_tree/Cargo.toml b/sum_tree/Cargo.toml new file mode 100644 index 0000000000..510044cfb8 --- /dev/null +++ b/sum_tree/Cargo.toml @@ -0,0 +1,12 @@ +[package] +name = "sum_tree" +version = "0.1.0" +edition = "2018" + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[dependencies] +arrayvec = "0.7.1" + +[dev-dependencies] +rand = "0.8.3" diff --git a/gpui/src/sum_tree/cursor.rs b/sum_tree/src/cursor.rs similarity index 100% rename from gpui/src/sum_tree/cursor.rs rename to sum_tree/src/cursor.rs diff --git a/gpui/src/sum_tree.rs b/sum_tree/src/lib.rs similarity index 86% rename from gpui/src/sum_tree.rs rename to sum_tree/src/lib.rs index e256a1f33b..2bbb567ba1 100644 --- a/gpui/src/sum_tree.rs +++ b/sum_tree/src/lib.rs @@ -674,101 +674,115 @@ mod tests { ); } - #[crate::test(self, iterations = 100)] - fn test_random(mut rng: StdRng) { - let rng = &mut rng; - let mut tree = SumTree::::new(); - let count = rng.gen_range(0..10); - tree.extend(rng.sample_iter(distributions::Standard).take(count), &()); - - for _ in 0..5 { - let splice_end = rng.gen_range(0..tree.extent::(&()).0 + 1); - let splice_start = rng.gen_range(0..splice_end + 1); - let count = rng.gen_range(0..3); - let tree_end = tree.extent::(&()); - let new_items = rng - .sample_iter(distributions::Standard) - .take(count) - .collect::>(); - - let mut reference_items = tree.items(&()); - reference_items.splice(splice_start..splice_end, new_items.clone()); - - tree = { - let mut cursor = tree.cursor::(); - let mut new_tree = cursor.slice(&Count(splice_start), Bias::Right, &()); - new_tree.extend(new_items, &()); - cursor.seek(&Count(splice_end), Bias::Right, &()); - new_tree.push_tree(cursor.slice(&tree_end, Bias::Right, &()), &()); - new_tree - }; - - assert_eq!(tree.items(&()), reference_items); - - let mut filter_cursor = tree.filter::<_, Count>(|summary| summary.contains_even, &()); - let mut reference_filter = tree - .items(&()) - .into_iter() - .enumerate() - .filter(|(_, item)| (item & 1) == 0); - while let Some(actual_item) = filter_cursor.item() { - let (reference_index, reference_item) = reference_filter.next().unwrap(); - assert_eq!(actual_item, &reference_item); - assert_eq!(filter_cursor.start().0, reference_index); - filter_cursor.next(&()); - } - assert!(reference_filter.next().is_none()); - - let mut pos = rng.gen_range(0..tree.extent::(&()).0 + 1); - let mut before_start = false; - let mut cursor = tree.cursor::(); - cursor.seek(&Count(pos), Bias::Right, &()); - - for i in 0..10 { - assert_eq!(cursor.start().0, pos); - - if pos > 0 { - assert_eq!(cursor.prev_item().unwrap(), &reference_items[pos - 1]); - } else { - assert_eq!(cursor.prev_item(), None); - } - - if pos < reference_items.len() && !before_start { - assert_eq!(cursor.item().unwrap(), &reference_items[pos]); - } else { - assert_eq!(cursor.item(), None); - } - - if i < 5 { - cursor.next(&()); - if pos < reference_items.len() { - pos += 1; - before_start = false; - } - } else { - cursor.prev(&()); - if pos == 0 { - before_start = true; - } - pos = pos.saturating_sub(1); - } - } + #[test] + fn test_random() { + let mut starting_seed = 0; + if let Ok(value) = std::env::var("SEED") { + starting_seed = value.parse().expect("invalid SEED variable"); + } + let mut num_iterations = 100; + if let Ok(value) = std::env::var("ITERATIONS") { + num_iterations = value.parse().expect("invalid ITERATIONS variable"); } - for _ in 0..10 { - let end = rng.gen_range(0..tree.extent::(&()).0 + 1); - let start = rng.gen_range(0..end + 1); - let start_bias = if rng.gen() { Bias::Left } else { Bias::Right }; - let end_bias = if rng.gen() { Bias::Left } else { Bias::Right }; + for seed in starting_seed..(starting_seed + num_iterations) { + let mut rng = StdRng::seed_from_u64(seed); - let mut cursor = tree.cursor::(); - cursor.seek(&Count(start), start_bias, &()); - let slice = cursor.slice(&Count(end), end_bias, &()); + let rng = &mut rng; + let mut tree = SumTree::::new(); + let count = rng.gen_range(0..10); + tree.extend(rng.sample_iter(distributions::Standard).take(count), &()); - cursor.seek(&Count(start), start_bias, &()); - let summary = cursor.summary::<_, Sum>(&Count(end), end_bias, &()); + for _ in 0..5 { + let splice_end = rng.gen_range(0..tree.extent::(&()).0 + 1); + let splice_start = rng.gen_range(0..splice_end + 1); + let count = rng.gen_range(0..3); + let tree_end = tree.extent::(&()); + let new_items = rng + .sample_iter(distributions::Standard) + .take(count) + .collect::>(); - assert_eq!(summary.0, slice.summary().sum); + let mut reference_items = tree.items(&()); + reference_items.splice(splice_start..splice_end, new_items.clone()); + + tree = { + let mut cursor = tree.cursor::(); + let mut new_tree = cursor.slice(&Count(splice_start), Bias::Right, &()); + new_tree.extend(new_items, &()); + cursor.seek(&Count(splice_end), Bias::Right, &()); + new_tree.push_tree(cursor.slice(&tree_end, Bias::Right, &()), &()); + new_tree + }; + + assert_eq!(tree.items(&()), reference_items); + + let mut filter_cursor = + tree.filter::<_, Count>(|summary| summary.contains_even, &()); + let mut reference_filter = tree + .items(&()) + .into_iter() + .enumerate() + .filter(|(_, item)| (item & 1) == 0); + while let Some(actual_item) = filter_cursor.item() { + let (reference_index, reference_item) = reference_filter.next().unwrap(); + assert_eq!(actual_item, &reference_item); + assert_eq!(filter_cursor.start().0, reference_index); + filter_cursor.next(&()); + } + assert!(reference_filter.next().is_none()); + + let mut pos = rng.gen_range(0..tree.extent::(&()).0 + 1); + let mut before_start = false; + let mut cursor = tree.cursor::(); + cursor.seek(&Count(pos), Bias::Right, &()); + + for i in 0..10 { + assert_eq!(cursor.start().0, pos); + + if pos > 0 { + assert_eq!(cursor.prev_item().unwrap(), &reference_items[pos - 1]); + } else { + assert_eq!(cursor.prev_item(), None); + } + + if pos < reference_items.len() && !before_start { + assert_eq!(cursor.item().unwrap(), &reference_items[pos]); + } else { + assert_eq!(cursor.item(), None); + } + + if i < 5 { + cursor.next(&()); + if pos < reference_items.len() { + pos += 1; + before_start = false; + } + } else { + cursor.prev(&()); + if pos == 0 { + before_start = true; + } + pos = pos.saturating_sub(1); + } + } + } + + for _ in 0..10 { + let end = rng.gen_range(0..tree.extent::(&()).0 + 1); + let start = rng.gen_range(0..end + 1); + let start_bias = if rng.gen() { Bias::Left } else { Bias::Right }; + let end_bias = if rng.gen() { Bias::Left } else { Bias::Right }; + + let mut cursor = tree.cursor::(); + cursor.seek(&Count(start), start_bias, &()); + let slice = cursor.slice(&Count(end), end_bias, &()); + + cursor.seek(&Count(start), start_bias, &()); + let summary = cursor.summary::<_, Sum>(&Count(end), end_bias, &()); + + assert_eq!(summary.0, slice.summary().sum); + } } } diff --git a/zed/Cargo.toml b/zed/Cargo.toml index 17d42a04c9..6f14398eb0 100644 --- a/zed/Cargo.toml +++ b/zed/Cargo.toml @@ -51,6 +51,7 @@ similar = "1.3" simplelog = "0.9" smallvec = { version = "1.6", features = ["union"] } smol = "1.2.5" +sum_tree = { "path" = "../sum_tree" } surf = "2.2" tempdir = { version = "0.3.7", optional = true } thiserror = "1.0.29" diff --git a/zed/src/channel.rs b/zed/src/channel.rs index 40807cc585..5b4dfa6d39 100644 --- a/zed/src/channel.rs +++ b/zed/src/channel.rs @@ -5,7 +5,6 @@ use crate::{ }; use anyhow::{anyhow, Context, Result}; use gpui::{ - sum_tree::{self, Bias, SumTree}, AsyncAppContext, Entity, ModelContext, ModelHandle, MutableAppContext, Task, WeakModelHandle, }; use postage::prelude::Stream; @@ -16,6 +15,7 @@ use std::{ ops::Range, sync::Arc, }; +use sum_tree::{self, Bias, SumTree}; use time::OffsetDateTime; use zrpc::{ proto::{self, ChannelMessageSent}, diff --git a/zed/src/editor/buffer.rs b/zed/src/editor/buffer.rs index 99be7d4181..d7ad880093 100644 --- a/zed/src/editor/buffer.rs +++ b/zed/src/editor/buffer.rs @@ -13,8 +13,8 @@ use crate::{ }; pub use anchor::*; use anyhow::{anyhow, Result}; +use sum_tree::{self, FilterCursor, SumTree}; use gpui::{ - sum_tree::{self, FilterCursor, SumTree}, AppContext, Entity, ModelContext, ModelHandle, Task, }; use lazy_static::lazy_static; diff --git a/zed/src/editor/buffer/operation_queue.rs b/zed/src/editor/buffer/operation_queue.rs index 97ec360b8f..ae426d77a4 100644 --- a/zed/src/editor/buffer/operation_queue.rs +++ b/zed/src/editor/buffer/operation_queue.rs @@ -1,7 +1,7 @@ use super::Operation; use crate::time; -use gpui::sum_tree::{Cursor, Dimension, Edit, Item, KeyedItem, SumTree, Summary}; use std::{fmt::Debug, ops::Add}; +use sum_tree::{Cursor, Dimension, Edit, Item, KeyedItem, SumTree, Summary}; #[derive(Clone, Debug)] pub struct OperationQueue(SumTree); diff --git a/zed/src/editor/buffer/rope.rs b/zed/src/editor/buffer/rope.rs index a4fe867da6..414679c2d9 100644 --- a/zed/src/editor/buffer/rope.rs +++ b/zed/src/editor/buffer/rope.rs @@ -1,9 +1,9 @@ use super::Point; use crate::util::Bias; use arrayvec::ArrayString; -use gpui::sum_tree::{self, SumTree}; use smallvec::SmallVec; use std::{cmp, ops::Range, str}; +use sum_tree::{self, SumTree}; #[cfg(test)] const CHUNK_BASE: usize = 6; diff --git a/zed/src/editor/display_map/fold_map.rs b/zed/src/editor/display_map/fold_map.rs index 1fa3a22e3f..aa7d0f44fa 100644 --- a/zed/src/editor/display_map/fold_map.rs +++ b/zed/src/editor/display_map/fold_map.rs @@ -3,10 +3,7 @@ use super::{ Anchor, Buffer, Point, ToOffset, }; use crate::{editor::buffer, settings::HighlightId, time, util::Bias}; -use gpui::{ - sum_tree::{self, Cursor, FilterCursor, SumTree}, - AppContext, ModelHandle, -}; +use gpui::{AppContext, ModelHandle}; use parking_lot::Mutex; use std::{ cmp::{self, Ordering}, @@ -14,6 +11,7 @@ use std::{ ops::Range, sync::atomic::{AtomicUsize, Ordering::SeqCst}, }; +use sum_tree::{self, Cursor, FilterCursor, SumTree}; #[derive(Copy, Clone, Debug, Default, Eq, Ord, PartialOrd, PartialEq)] pub struct FoldPoint(pub super::Point); diff --git a/zed/src/editor/display_map/wrap_map.rs b/zed/src/editor/display_map/wrap_map.rs index 4bc31785ff..2aabe374ed 100644 --- a/zed/src/editor/display_map/wrap_map.rs +++ b/zed/src/editor/display_map/wrap_map.rs @@ -3,15 +3,11 @@ use super::{ tab_map::{self, Edit as TabEdit, Snapshot as TabSnapshot, TabPoint, TextSummary}, }; use crate::{editor::Point, settings::HighlightId, util::Bias}; -use gpui::{ - fonts::FontId, - sum_tree::{self, Cursor, SumTree}, - text_layout::LineWrapper, - Entity, ModelContext, Task, -}; +use gpui::{fonts::FontId, text_layout::LineWrapper, Entity, ModelContext, Task}; use lazy_static::lazy_static; use smol::future::yield_now; use std::{collections::VecDeque, ops::Range, time::Duration}; +use sum_tree::{self, Cursor, SumTree}; pub struct WrapMap { snapshot: Snapshot, diff --git a/zed/src/util.rs b/zed/src/util.rs index 9e7a912ce8..e199925d98 100644 --- a/zed/src/util.rs +++ b/zed/src/util.rs @@ -1,11 +1,11 @@ -use futures::{Future}; -pub use gpui::sum_tree::Bias; +use futures::Future; use rand::prelude::*; use std::{ cmp::Ordering, pin::Pin, task::{Context, Poll}, }; +pub use sum_tree::Bias; pub fn post_inc(value: &mut usize) -> usize { let prev = *value; diff --git a/zed/src/worktree.rs b/zed/src/worktree.rs index eaeefcd462..56ed2cb731 100644 --- a/zed/src/worktree.rs +++ b/zed/src/worktree.rs @@ -15,9 +15,9 @@ use ::ignore::gitignore::{Gitignore, GitignoreBuilder}; use anyhow::{anyhow, Result}; use futures::{Stream, StreamExt}; pub use fuzzy::{match_paths, PathMatch}; +use sum_tree::{self, Edit, SeekTarget, SumTree}; use gpui::{ executor, - sum_tree::{self, Edit, SeekTarget, SumTree}, AppContext, AsyncAppContext, Entity, ModelContext, ModelHandle, MutableAppContext, Task, UpgradeModelHandle, WeakModelHandle, };