mirror of
https://github.com/GraphiteEditor/Graphite.git
synced 2026-09-16 06:38:03 +08:00
Materialize a reducer's ranked input into a List and fold it
This commit is contained in:
@@ -1,6 +1,7 @@
|
||||
use crate::context::InjectIndex;
|
||||
use crate::gpoll::{Extent, Finality, GPoll, GraphError, Interrupt, Level};
|
||||
use std::cell::Cell;
|
||||
use std::marker::PhantomData;
|
||||
use std::mem::MaybeUninit;
|
||||
use std::ops::Range;
|
||||
|
||||
@@ -172,6 +173,66 @@ impl<'e> RecordLane<'_, crate::record::RecordValue<'e>> {
|
||||
}
|
||||
}
|
||||
|
||||
/// A materialized nesting level handed to a folding kernel: a thin element-typed
|
||||
/// view over the [`RecordBatch`] the level was collected into. `'a` is the batch
|
||||
/// view, `'e` the record payloads. The eventual `List` once `IList` is renamed.
|
||||
#[derive(Debug)]
|
||||
pub struct List<'a, 'e, T> {
|
||||
batch: RecordBatch<'a, crate::record::RecordValue<'e>>,
|
||||
_element: PhantomData<T>,
|
||||
}
|
||||
|
||||
impl<'a, 'e, T: Copy> List<'a, 'e, T> {
|
||||
/// # Safety
|
||||
/// `T` must be the batch's record element type, proven at the consumer's wiring.
|
||||
pub unsafe fn new(batch: RecordBatch<'a, crate::record::RecordValue<'e>>) -> Self {
|
||||
Self { batch, _element: PhantomData }
|
||||
}
|
||||
|
||||
pub fn len(&self) -> usize {
|
||||
self.batch.len()
|
||||
}
|
||||
|
||||
pub fn is_empty(&self) -> bool {
|
||||
self.batch.is_empty()
|
||||
}
|
||||
|
||||
pub fn get(&self, index: usize) -> T {
|
||||
// SAFETY: `List::new` established that `T` is the batch's element type.
|
||||
self.batch.get(index, |lane| unsafe { lane.element::<T>() })
|
||||
}
|
||||
|
||||
pub fn iter(&self) -> impl Iterator<Item = T> + '_ {
|
||||
(0..self.len()).map(move |index| self.get(index))
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, 'e, T: Copy> IntoIterator for List<'a, 'e, T> {
|
||||
type Item = T;
|
||||
type IntoIter = ListIter<'a, 'e, T>;
|
||||
|
||||
fn into_iter(self) -> ListIter<'a, 'e, T> {
|
||||
ListIter { list: self, position: 0 }
|
||||
}
|
||||
}
|
||||
|
||||
pub struct ListIter<'a, 'e, T> {
|
||||
list: List<'a, 'e, T>,
|
||||
position: usize,
|
||||
}
|
||||
|
||||
impl<T: Copy> Iterator for ListIter<'_, '_, T> {
|
||||
type Item = T;
|
||||
|
||||
fn next(&mut self) -> Option<T> {
|
||||
(self.position < self.list.len()).then(|| {
|
||||
let value = self.list.get(self.position);
|
||||
self.position += 1;
|
||||
value
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
pub trait Node<Input> {
|
||||
type Output;
|
||||
|
||||
|
||||
@@ -353,6 +353,13 @@ impl std::fmt::Debug for RecordValue<'_> {
|
||||
}
|
||||
}
|
||||
|
||||
// SAFETY: `element_write` requires the element `Send + Sync` and attribute payloads
|
||||
// are `Copy` or arena-backed, so the record bytes behind the pointer are thread-safe;
|
||||
// `'e` ties the pointer's validity to the shared arena and record-stack discipline.
|
||||
unsafe impl Send for RecordValue<'_> {}
|
||||
// SAFETY: as `Send`.
|
||||
unsafe impl Sync for RecordValue<'_> {}
|
||||
|
||||
impl<'e> RecordValue<'e> {
|
||||
#[doc(hidden)]
|
||||
pub fn zeroed() -> Self {
|
||||
|
||||
Reference in New Issue
Block a user