diff --git a/node-graph/libraries/core-types/src/node.rs b/node-graph/libraries/core-types/src/node.rs index 0a49066195..98dce654d5 100644 --- a/node-graph/libraries/core-types/src/node.rs +++ b/node-graph/libraries/core-types/src/node.rs @@ -74,6 +74,10 @@ impl<'a> RecordBatch<'a> { self.layout } + pub(crate) fn frames_ptr(&self) -> *const u8 { + self.frames + } + pub fn get(&self, lane: usize) -> RecordLane<'a> { assert!(lane < self.len, "lane {lane} out of bounds for a batch of {}", self.len); RecordLane { @@ -214,6 +218,10 @@ impl<'a, T> List<'a, T> { self.batch.is_empty() } + pub fn batch(&self) -> RecordBatch<'a> { + self.batch + } + pub fn get(&self, index: usize) -> T where T: Copy, diff --git a/node-graph/libraries/core-types/src/record.rs b/node-graph/libraries/core-types/src/record.rs index 419b89c16b..74c3a016e7 100644 --- a/node-graph/libraries/core-types/src/record.rs +++ b/node-graph/libraries/core-types/src/record.rs @@ -1623,9 +1623,28 @@ impl GroupItem { &self.layout } + /// A `GroupItem` over the batch's frames, without copying. + /// + /// # Safety + /// The frames must stay valid for the evaluation. Arena-resident batches + /// qualify, caller stack scratch does not. + pub unsafe fn from_resident(batch: crate::node::RecordBatch<'_>) -> Self { + let layout = batch.layout().clone(); + assert!(!layout.element.parked || layout.element.content_hash.is_some(), "a parked element adopts only with content glue"); + for field in &layout.fields { + assert!(field.repark.is_none() || field.content_hash.is_some(), "a parked field adopts only with content glue"); + } + Self { + frames: batch.frames_ptr(), + len: batch.len(), + layout, + } + } + /// A batch view over the stored records. pub fn lanes(&self) -> crate::node::RecordBatch<'_> { - // SAFETY: `adopt` filled `len` lanes of `layout` at the layout's stride. + // SAFETY: the constructors store `len` lanes of `layout` at the + // layout's stride. unsafe { crate::node::RecordBatch::new(self.frames, self.len, &self.layout) } }