Merge pull request #194 from zed-industries/investigate-compile-time

Explore some ways to reduce Zed's compile time
This commit is contained in:
Nathan Sobo
2021-10-01 15:35:51 -06:00
committed by GitHub
4 changed files with 340 additions and 215 deletions
+104 -64
View File
@@ -1,6 +1,6 @@
use crate::{
elements::ElementBox,
executor,
executor::{self, Task},
keymap::{self, Keystroke},
platform::{self, CursorStyle, Platform, PromptLevel, WindowOptions},
presenter::Presenter,
@@ -8,7 +8,6 @@ use crate::{
AssetCache, AssetSource, ClipboardItem, FontCache, PathPromptOptions, TextLayoutCache,
};
use anyhow::{anyhow, Result};
use async_task::Task;
use keymap::MatchResult;
use parking_lot::Mutex;
use platform::Event;
@@ -58,18 +57,19 @@ pub trait ReadModel {
}
pub trait ReadModelWith {
fn read_model_with<E: Entity, F: FnOnce(&E, &AppContext) -> T, T>(
fn read_model_with<E: Entity, T>(
&self,
handle: &ModelHandle<E>,
read: F,
read: &mut dyn FnMut(&E, &AppContext) -> T,
) -> T;
}
pub trait UpdateModel {
fn update_model<T, F, S>(&mut self, handle: &ModelHandle<T>, update: F) -> S
where
T: Entity,
F: FnOnce(&mut T, &mut ModelContext<T>) -> S;
fn update_model<T: Entity, O>(
&mut self,
handle: &ModelHandle<T>,
update: &mut dyn FnMut(&mut T, &mut ModelContext<T>) -> O,
) -> O;
}
pub trait UpgradeModelHandle {
@@ -82,17 +82,23 @@ pub trait ReadView {
}
pub trait ReadViewWith {
fn read_view_with<V, F, T>(&self, handle: &ViewHandle<V>, read: F) -> T
fn read_view_with<V, T>(
&self,
handle: &ViewHandle<V>,
read: &mut dyn FnMut(&V, &AppContext) -> T,
) -> T
where
V: View,
F: FnOnce(&V, &AppContext) -> T;
V: View;
}
pub trait UpdateView {
fn update_view<T, F, S>(&mut self, handle: &ViewHandle<T>, update: F) -> S
fn update_view<T, S>(
&mut self,
handle: &ViewHandle<T>,
update: &mut dyn FnMut(&mut T, &mut ViewContext<T>) -> S,
) -> S
where
T: View,
F: FnOnce(&mut T, &mut ViewContext<T>) -> S;
T: View;
}
pub trait Action: 'static + AnyAction {
@@ -532,11 +538,11 @@ impl AsyncAppContext {
}
impl UpdateModel for AsyncAppContext {
fn update_model<T, F, S>(&mut self, handle: &ModelHandle<T>, update: F) -> S
where
T: Entity,
F: FnOnce(&mut T, &mut ModelContext<T>) -> S,
{
fn update_model<E: Entity, O>(
&mut self,
handle: &ModelHandle<E>,
update: &mut dyn FnMut(&mut E, &mut ModelContext<E>) -> O,
) -> O {
let mut state = self.0.borrow_mut();
state.pending_flushes += 1;
let result = state.update_model(handle, update);
@@ -555,10 +561,10 @@ impl UpgradeModelHandle for AsyncAppContext {
}
impl ReadModelWith for AsyncAppContext {
fn read_model_with<E: Entity, F: FnOnce(&E, &AppContext) -> T, T>(
fn read_model_with<E: Entity, T>(
&self,
handle: &ModelHandle<E>,
read: F,
read: &mut dyn FnMut(&E, &AppContext) -> T,
) -> T {
let cx = self.0.borrow();
let cx = cx.as_ref();
@@ -567,10 +573,13 @@ impl ReadModelWith for AsyncAppContext {
}
impl UpdateView for AsyncAppContext {
fn update_view<T, F, S>(&mut self, handle: &ViewHandle<T>, update: F) -> S
fn update_view<T, S>(
&mut self,
handle: &ViewHandle<T>,
update: &mut dyn FnMut(&mut T, &mut ViewContext<T>) -> S,
) -> S
where
T: View,
F: FnOnce(&mut T, &mut ViewContext<T>) -> S,
{
let mut state = self.0.borrow_mut();
state.pending_flushes += 1;
@@ -581,10 +590,13 @@ impl UpdateView for AsyncAppContext {
}
impl ReadViewWith for AsyncAppContext {
fn read_view_with<V, F, T>(&self, handle: &ViewHandle<V>, read: F) -> T
fn read_view_with<V, T>(
&self,
handle: &ViewHandle<V>,
read: &mut dyn FnMut(&V, &AppContext) -> T,
) -> T
where
V: View,
F: FnOnce(&V, &AppContext) -> T,
{
let cx = self.0.borrow();
let cx = cx.as_ref();
@@ -593,11 +605,11 @@ impl ReadViewWith for AsyncAppContext {
}
impl UpdateModel for TestAppContext {
fn update_model<T, F, S>(&mut self, handle: &ModelHandle<T>, update: F) -> S
where
T: Entity,
F: FnOnce(&mut T, &mut ModelContext<T>) -> S,
{
fn update_model<T: Entity, O>(
&mut self,
handle: &ModelHandle<T>,
update: &mut dyn FnMut(&mut T, &mut ModelContext<T>) -> O,
) -> O {
let mut state = self.cx.borrow_mut();
state.pending_flushes += 1;
let result = state.update_model(handle, update);
@@ -607,10 +619,10 @@ impl UpdateModel for TestAppContext {
}
impl ReadModelWith for TestAppContext {
fn read_model_with<E: Entity, F: FnOnce(&E, &AppContext) -> T, T>(
fn read_model_with<E: Entity, T>(
&self,
handle: &ModelHandle<E>,
read: F,
read: &mut dyn FnMut(&E, &AppContext) -> T,
) -> T {
let cx = self.cx.borrow();
let cx = cx.as_ref();
@@ -619,10 +631,13 @@ impl ReadModelWith for TestAppContext {
}
impl UpdateView for TestAppContext {
fn update_view<T, F, S>(&mut self, handle: &ViewHandle<T>, update: F) -> S
fn update_view<T, S>(
&mut self,
handle: &ViewHandle<T>,
update: &mut dyn FnMut(&mut T, &mut ViewContext<T>) -> S,
) -> S
where
T: View,
F: FnOnce(&mut T, &mut ViewContext<T>) -> S,
{
let mut state = self.cx.borrow_mut();
state.pending_flushes += 1;
@@ -633,10 +648,13 @@ impl UpdateView for TestAppContext {
}
impl ReadViewWith for TestAppContext {
fn read_view_with<V, F, T>(&self, handle: &ViewHandle<V>, read: F) -> T
fn read_view_with<V, T>(
&self,
handle: &ViewHandle<V>,
read: &mut dyn FnMut(&V, &AppContext) -> T,
) -> T
where
V: View,
F: FnOnce(&V, &AppContext) -> T,
{
let cx = self.cx.borrow();
let cx = cx.as_ref();
@@ -1630,11 +1648,11 @@ impl ReadModel for MutableAppContext {
}
impl UpdateModel for MutableAppContext {
fn update_model<T, F, S>(&mut self, handle: &ModelHandle<T>, update: F) -> S
where
T: Entity,
F: FnOnce(&mut T, &mut ModelContext<T>) -> S,
{
fn update_model<T: Entity, V>(
&mut self,
handle: &ModelHandle<T>,
update: &mut dyn FnMut(&mut T, &mut ModelContext<T>) -> V,
) -> V {
if let Some(mut model) = self.cx.models.remove(&handle.model_id) {
self.pending_flushes += 1;
let mut cx = ModelContext::new(self, handle.model_id);
@@ -1674,10 +1692,13 @@ impl ReadView for MutableAppContext {
}
impl UpdateView for MutableAppContext {
fn update_view<T, F, S>(&mut self, handle: &ViewHandle<T>, update: F) -> S
fn update_view<T, S>(
&mut self,
handle: &ViewHandle<T>,
update: &mut dyn FnMut(&mut T, &mut ViewContext<T>) -> S,
) -> S
where
T: View,
F: FnOnce(&mut T, &mut ViewContext<T>) -> S,
{
self.pending_flushes += 1;
let mut view = self
@@ -2084,11 +2105,11 @@ impl<M> ReadModel for ModelContext<'_, M> {
}
impl<M> UpdateModel for ModelContext<'_, M> {
fn update_model<T, F, S>(&mut self, handle: &ModelHandle<T>, update: F) -> S
where
T: Entity,
F: FnOnce(&mut T, &mut ModelContext<T>) -> S,
{
fn update_model<T: Entity, V>(
&mut self,
handle: &ModelHandle<T>,
update: &mut dyn FnMut(&mut T, &mut ModelContext<T>) -> V,
) -> V {
self.app.update_model(handle, update)
}
}
@@ -2345,11 +2366,11 @@ impl<V: View> ReadModel for RenderContext<'_, V> {
}
impl<V: View> UpdateModel for RenderContext<'_, V> {
fn update_model<T, F, S>(&mut self, handle: &ModelHandle<T>, update: F) -> S
where
T: Entity,
F: FnOnce(&mut T, &mut ModelContext<T>) -> S,
{
fn update_model<T: Entity, O>(
&mut self,
handle: &ModelHandle<T>,
update: &mut dyn FnMut(&mut T, &mut ModelContext<T>) -> O,
) -> O {
self.app.update_model(handle, update)
}
}
@@ -2396,11 +2417,11 @@ impl<V> UpgradeModelHandle for ViewContext<'_, V> {
}
impl<V: View> UpdateModel for ViewContext<'_, V> {
fn update_model<T, F, S>(&mut self, handle: &ModelHandle<T>, update: F) -> S
where
T: Entity,
F: FnOnce(&mut T, &mut ModelContext<T>) -> S,
{
fn update_model<T: Entity, O>(
&mut self,
handle: &ModelHandle<T>,
update: &mut dyn FnMut(&mut T, &mut ModelContext<T>) -> O,
) -> O {
self.app.update_model(handle, update)
}
}
@@ -2412,10 +2433,13 @@ impl<V: View> ReadView for ViewContext<'_, V> {
}
impl<V: View> UpdateView for ViewContext<'_, V> {
fn update_view<T, F, S>(&mut self, handle: &ViewHandle<T>, update: F) -> S
fn update_view<T, S>(
&mut self,
handle: &ViewHandle<T>,
update: &mut dyn FnMut(&mut T, &mut ViewContext<T>) -> S,
) -> S
where
T: View,
F: FnOnce(&mut T, &mut ViewContext<T>) -> S,
{
self.app.update_view(handle, update)
}
@@ -2470,7 +2494,11 @@ impl<T: Entity> ModelHandle<T> {
C: ReadModelWith,
F: FnOnce(&T, &AppContext) -> S,
{
cx.read_model_with(self, read)
let mut read = Some(read);
cx.read_model_with(self, &mut |model, cx| {
let read = read.take().unwrap();
read(model, cx)
})
}
pub fn update<C, F, S>(&self, cx: &mut C, update: F) -> S
@@ -2478,7 +2506,11 @@ impl<T: Entity> ModelHandle<T> {
C: UpdateModel,
F: FnOnce(&mut T, &mut ModelContext<T>) -> S,
{
cx.update_model(self, update)
let mut update = Some(update);
cx.update_model(self, &mut |model, cx| {
let update = update.take().unwrap();
update(model, cx)
})
}
pub fn next_notification(&self, cx: &TestAppContext) -> impl Future<Output = ()> {
@@ -2744,7 +2776,11 @@ impl<T: View> ViewHandle<T> {
C: ReadViewWith,
F: FnOnce(&T, &AppContext) -> S,
{
cx.read_view_with(self, read)
let mut read = Some(read);
cx.read_view_with(self, &mut |view, cx| {
let read = read.take().unwrap();
read(view, cx)
})
}
pub fn update<C, F, S>(&self, cx: &mut C, update: F) -> S
@@ -2752,7 +2788,11 @@ impl<T: View> ViewHandle<T> {
C: UpdateView,
F: FnOnce(&mut T, &mut ViewContext<T>) -> S,
{
cx.update_view(self, update)
let mut update = Some(update);
cx.update_view(self, &mut |view, cx| {
let update = update.take().unwrap();
update(view, cx)
})
}
pub fn is_focused(&self, cx: &AppContext) -> bool {
+135 -53
View File
@@ -1,12 +1,12 @@
use anyhow::{anyhow, Result};
use async_task::Runnable;
pub use async_task::Task;
use backtrace::{Backtrace, BacktraceFmt, BytesOrWideString};
use parking_lot::Mutex;
use postage::{barrier, prelude::Stream as _};
use rand::prelude::*;
use smol::{channel, prelude::*, Executor, Timer};
use std::{
any::Any,
fmt::{self, Debug},
marker::PhantomData,
mem,
@@ -23,7 +23,10 @@ use std::{
};
use waker_fn::waker_fn;
use crate::{platform, util};
use crate::{
platform::{self, Dispatcher},
util,
};
pub enum Foreground {
Platform {
@@ -42,6 +45,24 @@ pub enum Background {
},
}
type AnyLocalFuture = Pin<Box<dyn 'static + Future<Output = Box<dyn Any + 'static>>>>;
type AnyFuture = Pin<Box<dyn 'static + Send + Future<Output = Box<dyn Any + Send + 'static>>>>;
type AnyTask = async_task::Task<Box<dyn Any + Send + 'static>>;
type AnyLocalTask = async_task::Task<Box<dyn Any + 'static>>;
pub enum Task<T> {
Local {
any_task: AnyLocalTask,
result_type: PhantomData<T>,
},
Send {
any_task: AnyTask,
result_type: PhantomData<T>,
},
}
unsafe impl<T: Send> Send for Task<T> {}
struct DeterministicState {
rng: StdRng,
seed: u64,
@@ -77,11 +98,7 @@ impl Deterministic {
}
}
pub fn spawn_from_foreground<F, T>(&self, future: F) -> Task<T>
where
T: 'static,
F: Future<Output = T> + 'static,
{
fn spawn_from_foreground(&self, future: AnyLocalFuture) -> AnyLocalTask {
let backtrace = Backtrace::new_unresolved();
let scheduled_once = AtomicBool::new(false);
let state = self.state.clone();
@@ -100,11 +117,7 @@ impl Deterministic {
task
}
pub fn spawn<F, T>(&self, future: F) -> Task<T>
where
T: 'static + Send,
F: 'static + Send + Future<Output = T>,
{
fn spawn(&self, future: AnyFuture) -> AnyTask {
let backtrace = Backtrace::new_unresolved();
let state = self.state.clone();
let unparker = self.parker.lock().unparker();
@@ -119,13 +132,8 @@ impl Deterministic {
task
}
pub fn run<F, T>(&self, future: F) -> T
where
T: 'static,
F: Future<Output = T> + 'static,
{
fn run(&self, mut future: AnyLocalFuture) -> Box<dyn Any> {
let woken = Arc::new(AtomicBool::new(false));
let mut future = Box::pin(future);
loop {
if let Some(result) = self.run_internal(woken.clone(), &mut future) {
return result;
@@ -142,16 +150,15 @@ impl Deterministic {
fn run_until_parked(&self) {
let woken = Arc::new(AtomicBool::new(false));
let future = std::future::pending::<()>();
smol::pin!(future);
self.run_internal(woken, future);
let mut future = any_local_future(std::future::pending::<()>());
self.run_internal(woken, &mut future);
}
pub fn run_internal<F, T>(&self, woken: Arc<AtomicBool>, mut future: F) -> Option<T>
where
T: 'static,
F: Future<Output = T> + Unpin,
{
fn run_internal(
&self,
woken: Arc<AtomicBool>,
future: &mut AnyLocalFuture,
) -> Option<Box<dyn Any>> {
let unparker = self.parker.lock().unparker();
let waker = waker_fn(move || {
woken.store(true, SeqCst);
@@ -205,13 +212,7 @@ impl Deterministic {
}
}
pub fn block_on<F, T>(&self, future: F) -> Option<T>
where
T: 'static,
F: Future<Output = T>,
{
smol::pin!(future);
fn block_on(&self, future: &mut AnyLocalFuture) -> Option<Box<dyn Any>> {
let unparker = self.parker.lock().unparker();
let waker = waker_fn(move || {
unparker.unpark();
@@ -396,25 +397,36 @@ impl Foreground {
}
pub fn spawn<T: 'static>(&self, future: impl Future<Output = T> + 'static) -> Task<T> {
match self {
let future = any_local_future(future);
let any_task = match self {
Self::Deterministic(executor) => executor.spawn_from_foreground(future),
Self::Platform { dispatcher, .. } => {
let dispatcher = dispatcher.clone();
let schedule = move |runnable: Runnable| dispatcher.run_on_main_thread(runnable);
let (runnable, task) = async_task::spawn_local(future, schedule);
runnable.schedule();
task
fn spawn_inner(
future: AnyLocalFuture,
dispatcher: &Arc<dyn Dispatcher>,
) -> AnyLocalTask {
let dispatcher = dispatcher.clone();
let schedule =
move |runnable: Runnable| dispatcher.run_on_main_thread(runnable);
let (runnable, task) = async_task::spawn_local(future, schedule);
runnable.schedule();
task
}
spawn_inner(future, dispatcher)
}
Self::Test(executor) => executor.spawn(future),
Self::Deterministic(executor) => executor.spawn_from_foreground(future),
}
};
Task::local(any_task)
}
pub fn run<T: 'static>(&self, future: impl 'static + Future<Output = T>) -> T {
match self {
let future = any_local_future(future);
let any_value = match self {
Self::Deterministic(executor) => executor.run(future),
Self::Platform { .. } => panic!("you can't call run on a platform foreground executor"),
Self::Test(executor) => smol::block_on(executor.run(future)),
Self::Deterministic(executor) => executor.run(future),
}
};
*any_value.downcast().unwrap()
}
pub fn forbid_parking(&self) {
@@ -500,29 +512,34 @@ impl Background {
T: 'static + Send,
F: Send + Future<Output = T> + 'static,
{
match self {
let future = any_future(future);
let any_task = match self {
Self::Production { executor, .. } => executor.spawn(future),
Self::Deterministic(executor) => executor.spawn(future),
}
};
Task::send(any_task)
}
pub fn block_with_timeout<F, T>(&self, timeout: Duration, mut future: F) -> Result<T, F>
pub fn block_with_timeout<F, T>(
&self,
timeout: Duration,
future: F,
) -> Result<T, impl Future<Output = T>>
where
T: 'static,
F: 'static + Unpin + Future<Output = T>,
{
let mut future = any_local_future(future);
if !timeout.is_zero() {
let output = match self {
Self::Production { .. } => {
smol::block_on(util::timeout(timeout, Pin::new(&mut future))).ok()
}
Self::Deterministic(executor) => executor.block_on(Pin::new(&mut future)),
Self::Production { .. } => smol::block_on(util::timeout(timeout, &mut future)).ok(),
Self::Deterministic(executor) => executor.block_on(&mut future),
};
if let Some(output) = output {
return Ok(output);
return Ok(*output.downcast().unwrap());
}
}
Err(future)
Err(async { *future.await.downcast().unwrap() })
}
pub async fn scoped<'scope, F>(&self, scheduler: F)
@@ -572,3 +589,68 @@ pub fn deterministic(seed: u64) -> (Rc<Foreground>, Arc<Background>) {
Arc::new(Background::Deterministic(executor)),
)
}
impl<T> Task<T> {
fn local(any_task: AnyLocalTask) -> Self {
Self::Local {
any_task,
result_type: PhantomData,
}
}
pub fn detach(self) {
match self {
Task::Local { any_task, .. } => any_task.detach(),
Task::Send { any_task, .. } => any_task.detach(),
}
}
}
impl<T: Send> Task<T> {
fn send(any_task: AnyTask) -> Self {
Self::Send {
any_task,
result_type: PhantomData,
}
}
}
impl<T: fmt::Debug> fmt::Debug for Task<T> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
Task::Local { any_task, .. } => any_task.fmt(f),
Task::Send { any_task, .. } => any_task.fmt(f),
}
}
}
impl<T: 'static> Future for Task<T> {
type Output = T;
fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
match unsafe { self.get_unchecked_mut() } {
Task::Local { any_task, .. } => {
any_task.poll(cx).map(|value| *value.downcast().unwrap())
}
Task::Send { any_task, .. } => {
any_task.poll(cx).map(|value| *value.downcast().unwrap())
}
}
}
}
fn any_future<T, F>(future: F) -> AnyFuture
where
T: 'static + Send,
F: Future<Output = T> + Send + 'static,
{
async { Box::new(future.await) as Box<dyn Any + Send> }.boxed()
}
fn any_local_future<T, F>(future: F) -> AnyLocalFuture
where
T: 'static,
F: Future<Output = T> + 'static,
{
async { Box::new(future.await) as Box<dyn Any> }.boxed_local()
}
+1 -11
View File
@@ -7,7 +7,7 @@ use crate::{
platform::Event,
text_layout::TextLayoutCache,
Action, AnyAction, AssetCache, ElementBox, Entity, FontSystem, ModelHandle, ReadModel,
ReadView, Scene, UpdateView, View, ViewHandle,
ReadView, Scene, View, ViewHandle,
};
use pathfinder_geometry::vector::{vec2f, Vector2F};
use serde_json::json;
@@ -264,16 +264,6 @@ impl<'a> ReadView for LayoutContext<'a> {
}
}
impl<'a> UpdateView for LayoutContext<'a> {
fn update_view<T, F, S>(&mut self, handle: &ViewHandle<T>, update: F) -> S
where
T: View,
F: FnOnce(&mut T, &mut crate::ViewContext<T>) -> S,
{
self.app.update_view(handle, update)
}
}
impl<'a> ReadModel for LayoutContext<'a> {
fn read_model<T: Entity>(&self, handle: &ModelHandle<T>) -> &T {
self.app.read_model(handle)
+100 -87
View File
@@ -1,6 +1,6 @@
use super::*;
use arrayvec::ArrayVec;
use std::{cmp::Ordering, sync::Arc};
use std::{cmp::Ordering, mem, sync::Arc};
#[derive(Clone)]
struct StackEntry<'a, T: Item, D> {
@@ -324,7 +324,7 @@ where
Target: SeekTarget<'a, T::Summary, D>,
{
self.reset();
self.seek_internal::<_, ()>(pos, bias, &mut SeekAggregate::None, cx)
self.seek_internal(pos, bias, &mut (), cx)
}
pub fn seek_forward<Target>(
@@ -336,7 +336,7 @@ where
where
Target: SeekTarget<'a, T::Summary, D>,
{
self.seek_internal::<_, ()>(pos, bias, &mut SeekAggregate::None, cx)
self.seek_internal(pos, bias, &mut (), cx)
}
pub fn slice<Target>(
@@ -348,23 +348,18 @@ where
where
Target: SeekTarget<'a, T::Summary, D>,
{
let mut slice = SeekAggregate::Slice(SumTree::new());
self.seek_internal::<_, ()>(end, bias, &mut slice, cx);
if let SeekAggregate::Slice(slice) = slice {
slice
} else {
unreachable!()
}
let mut slice = SliceSeekAggregate {
tree: SumTree::new(),
leaf_items: ArrayVec::new(),
leaf_item_summaries: ArrayVec::new(),
leaf_summary: T::Summary::default(),
};
self.seek_internal(end, bias, &mut slice, cx);
slice.tree
}
pub fn suffix(&mut self, cx: &<T::Summary as Summary>::Context) -> SumTree<T> {
let mut slice = SeekAggregate::Slice(SumTree::new());
self.seek_internal::<_, ()>(&End::new(), Bias::Right, &mut slice, cx);
if let SeekAggregate::Slice(slice) = slice {
slice
} else {
unreachable!()
}
self.slice(&End::new(), Bias::Right, cx)
}
pub fn summary<Target, Output>(
@@ -377,26 +372,18 @@ where
Target: SeekTarget<'a, T::Summary, D>,
Output: Dimension<'a, T::Summary>,
{
let mut summary = SeekAggregate::Summary(Output::default());
let mut summary = SummarySeekAggregate(Output::default());
self.seek_internal(end, bias, &mut summary, cx);
if let SeekAggregate::Summary(summary) = summary {
summary
} else {
unreachable!()
}
summary.0
}
fn seek_internal<Target, Output>(
fn seek_internal(
&mut self,
target: &Target,
target: &dyn SeekTarget<'a, T::Summary, D>,
bias: Bias,
aggregate: &mut SeekAggregate<T, Output>,
aggregate: &mut dyn SeekAggregate<'a, T>,
cx: &<T::Summary as Summary>::Context,
) -> bool
where
Target: SeekTarget<'a, T::Summary, D>,
Output: Dimension<'a, T::Summary>,
{
) -> bool {
debug_assert!(
target.cmp(&self.position, cx) >= Ordering::Equal,
"cannot seek backward from {:?} to {:?}",
@@ -437,15 +424,7 @@ where
|| (comparison == Ordering::Equal && bias == Bias::Right)
{
self.position = child_end;
match aggregate {
SeekAggregate::None => {}
SeekAggregate::Slice(slice) => {
slice.push_tree(child_tree.clone(), cx);
}
SeekAggregate::Summary(summary) => {
summary.add_summary(child_summary, cx);
}
}
aggregate.push_tree(child_tree, child_summary, cx);
entry.index += 1;
entry.position = self.position.clone();
} else {
@@ -464,12 +443,7 @@ where
ref item_summaries,
..
} => {
let mut slice_items = ArrayVec::<T, { 2 * TREE_BASE }>::new();
let mut slice_item_summaries = ArrayVec::<T::Summary, { 2 * TREE_BASE }>::new();
let mut slice_items_summary = match aggregate {
SeekAggregate::Slice(_) => Some(T::Summary::default()),
_ => None,
};
aggregate.begin_leaf();
for (item, item_summary) in items[entry.index..]
.iter()
@@ -483,49 +457,15 @@ where
|| (comparison == Ordering::Equal && bias == Bias::Right)
{
self.position = child_end;
match aggregate {
SeekAggregate::None => {}
SeekAggregate::Slice(_) => {
slice_items.push(item.clone());
slice_item_summaries.push(item_summary.clone());
<T::Summary as Summary>::add_summary(
slice_items_summary.as_mut().unwrap(),
item_summary,
cx,
);
}
SeekAggregate::Summary(summary) => {
summary.add_summary(item_summary, cx);
}
}
aggregate.push_item(item, item_summary, cx);
entry.index += 1;
} else {
if let SeekAggregate::Slice(slice) = aggregate {
slice.push_tree(
SumTree(Arc::new(Node::Leaf {
summary: slice_items_summary.unwrap(),
items: slice_items,
item_summaries: slice_item_summaries,
})),
cx,
);
}
aggregate.end_leaf(cx);
break 'outer;
}
}
if let SeekAggregate::Slice(slice) = aggregate {
if !slice_items.is_empty() {
slice.push_tree(
SumTree(Arc::new(Node::Leaf {
summary: slice_items_summary.unwrap(),
items: slice_items,
item_summaries: slice_item_summaries,
})),
cx,
);
}
}
aggregate.end_leaf(cx);
}
}
@@ -625,8 +565,81 @@ where
}
}
enum SeekAggregate<T: Item, D> {
None,
Slice(SumTree<T>),
Summary(D),
trait SeekAggregate<'a, T: Item> {
fn begin_leaf(&mut self);
fn end_leaf(&mut self, cx: &<T::Summary as Summary>::Context);
fn push_item(
&mut self,
item: &'a T,
summary: &'a T::Summary,
cx: &<T::Summary as Summary>::Context,
);
fn push_tree(
&mut self,
tree: &'a SumTree<T>,
summary: &'a T::Summary,
cx: &<T::Summary as Summary>::Context,
);
}
struct SliceSeekAggregate<T: Item> {
tree: SumTree<T>,
leaf_items: ArrayVec<T, { 2 * TREE_BASE }>,
leaf_item_summaries: ArrayVec<T::Summary, { 2 * TREE_BASE }>,
leaf_summary: T::Summary,
}
struct SummarySeekAggregate<D>(D);
impl<'a, T: Item> SeekAggregate<'a, T> for () {
fn begin_leaf(&mut self) {}
fn end_leaf(&mut self, _: &<T::Summary as Summary>::Context) {}
fn push_item(&mut self, _: &T, _: &T::Summary, _: &<T::Summary as Summary>::Context) {}
fn push_tree(&mut self, _: &SumTree<T>, _: &T::Summary, _: &<T::Summary as Summary>::Context) {}
}
impl<'a, T: Item> SeekAggregate<'a, T> for SliceSeekAggregate<T> {
fn begin_leaf(&mut self) {}
fn end_leaf(&mut self, cx: &<T::Summary as Summary>::Context) {
self.tree.push_tree(
SumTree(Arc::new(Node::Leaf {
summary: mem::take(&mut self.leaf_summary),
items: mem::take(&mut self.leaf_items),
item_summaries: mem::take(&mut self.leaf_item_summaries),
})),
cx,
);
}
fn push_item(&mut self, item: &T, summary: &T::Summary, cx: &<T::Summary as Summary>::Context) {
self.leaf_items.push(item.clone());
self.leaf_item_summaries.push(summary.clone());
Summary::add_summary(&mut self.leaf_summary, summary, cx);
}
fn push_tree(
&mut self,
tree: &SumTree<T>,
_: &T::Summary,
cx: &<T::Summary as Summary>::Context,
) {
self.tree.push_tree(tree.clone(), cx);
}
}
impl<'a, T: Item, D> SeekAggregate<'a, T> for SummarySeekAggregate<D>
where
D: Dimension<'a, T::Summary>,
{
fn begin_leaf(&mut self) {}
fn end_leaf(&mut self, _: &<T::Summary as Summary>::Context) {}
fn push_item(&mut self, _: &T, summary: &'a T::Summary, cx: &<T::Summary as Summary>::Context) {
self.0.add_summary(summary, cx);
}
fn push_tree(
&mut self,
_: &SumTree<T>,
summary: &'a T::Summary,
cx: &<T::Summary as Summary>::Context,
) {
self.0.add_summary(summary, cx);
}
}