Detailed changes
@@ -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 {
@@ -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()
+}
@@ -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)
@@ -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);
+ }
}