Skip to content

Commit f6375f8

Browse files
committed
add a LazyPatchedArray
this lets us deserialize BPArray with Patches without eagerly transposing Signed-off-by: Andrew Duffy <andrew@a10y.dev>
1 parent 05c6744 commit f6375f8

File tree

5 files changed

+235
-0
lines changed

5 files changed

+235
-0
lines changed
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
// SPDX-License-Identifier: Apache-2.0
2+
// SPDX-FileCopyrightText: Copyright the Vortex contributors
3+
4+
mod vtable;
5+
6+
pub use vtable::*;
Lines changed: 195 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,195 @@
1+
// SPDX-License-Identifier: Apache-2.0
2+
// SPDX-FileCopyrightText: Copyright the Vortex contributors
3+
4+
mod operations;
5+
mod validity;
6+
7+
use std::hash::Hasher;
8+
9+
use vortex_error::VortexResult;
10+
use vortex_error::vortex_ensure;
11+
use vortex_error::vortex_ensure_eq;
12+
use vortex_error::vortex_panic;
13+
use vortex_session::VortexSession;
14+
15+
use crate::ArrayEq;
16+
use crate::ArrayHash;
17+
use crate::ArrayRef;
18+
use crate::DeserializeMetadata;
19+
use crate::DynArray;
20+
use crate::ExecutionCtx;
21+
use crate::ExecutionResult;
22+
use crate::IntoArray;
23+
use crate::Precision;
24+
use crate::ProstMetadata;
25+
use crate::SerializeMetadata;
26+
use crate::arrays::PatchedArray;
27+
use crate::buffer::BufferHandle;
28+
use crate::dtype::DType;
29+
use crate::patches::Patches;
30+
use crate::serde::ArrayChildren;
31+
use crate::stats::StatsSetRef;
32+
use crate::vtable;
33+
use crate::vtable::ArrayId;
34+
use crate::vtable::VTable;
35+
use crate::vtable::ValidityVTableFromChild;
36+
37+
#[derive(Clone, Debug)]
38+
pub struct LazyPatched;
39+
40+
vtable!(LazyPatched);
41+
42+
#[derive(Clone, prost::Message)]
43+
pub struct LazyPatchedMetadata {
44+
#[prost(uint32, tag = "1")]
45+
pub(crate) num_patches: u32,
46+
}
47+
48+
impl VTable for LazyPatched {
49+
type Array = LazyPatchedArray;
50+
type Metadata = ProstMetadata<LazyPatchedMetadata>;
51+
52+
type OperationsVTable = Self;
53+
type ValidityVTable = ValidityVTableFromChild;
54+
55+
fn vtable(_array: &Self::Array) -> &Self {
56+
&LazyPatched
57+
}
58+
59+
fn id(&self) -> ArrayId {
60+
ArrayId::new_ref("vortex.patched_lazy")
61+
}
62+
63+
fn len(array: &Self::Array) -> usize {
64+
array.inner.len()
65+
}
66+
67+
fn dtype(array: &Self::Array) -> &DType {
68+
array.inner.dtype()
69+
}
70+
71+
fn stats(_array: &Self::Array) -> StatsSetRef<'_> {
72+
todo!()
73+
}
74+
75+
fn array_hash<H: Hasher>(array: &Self::Array, state: &mut H, precision: Precision) {
76+
array.inner.array_hash(state, precision);
77+
array.patches.array_hash(state, precision);
78+
}
79+
80+
fn array_eq(array: &Self::Array, other: &Self::Array, precision: Precision) -> bool {
81+
array.inner.array_eq(&other.inner, precision)
82+
&& array.patches.array_eq(&other.patches, precision)
83+
}
84+
85+
fn nbuffers(_array: &Self::Array) -> usize {
86+
0
87+
}
88+
89+
fn buffer(_array: &Self::Array, _idx: usize) -> BufferHandle {
90+
vortex_panic!("LazyPatched array holds no buffers")
91+
}
92+
93+
fn buffer_name(_array: &Self::Array, _idx: usize) -> Option<String> {
94+
vortex_panic!("LazyPatched array holds no buffers")
95+
}
96+
97+
fn nchildren(_array: &Self::Array) -> usize {
98+
3
99+
}
100+
101+
fn child(array: &Self::Array, idx: usize) -> ArrayRef {
102+
match idx {
103+
0 => array.inner.clone(),
104+
1 => array.patches.indices().clone(),
105+
2 => array.patches.values().clone(),
106+
_ => unreachable!("invalid LazyPatched child index {}", idx),
107+
}
108+
}
109+
110+
fn child_name(_array: &Self::Array, idx: usize) -> String {
111+
match idx {
112+
0 => "inner".to_string(),
113+
1 => "patch_indices".to_string(),
114+
2 => "patch_values".to_string(),
115+
_ => unreachable!("invalid LazyPatched child index {}", idx),
116+
}
117+
}
118+
119+
fn metadata(array: &Self::Array) -> VortexResult<Self::Metadata> {
120+
let num_patches = u32::try_from(array.patches.num_patches())?;
121+
122+
Ok(ProstMetadata(LazyPatchedMetadata { num_patches }))
123+
}
124+
125+
fn serialize(metadata: Self::Metadata) -> VortexResult<Option<Vec<u8>>> {
126+
Ok(Some(metadata.serialize()))
127+
}
128+
129+
fn deserialize(
130+
bytes: &[u8],
131+
_dtype: &DType,
132+
_len: usize,
133+
_buffers: &[BufferHandle],
134+
_session: &VortexSession,
135+
) -> VortexResult<Self::Metadata> {
136+
let deserialized = <Self::Metadata>::deserialize(bytes)?;
137+
Ok(ProstMetadata(deserialized))
138+
}
139+
140+
fn build(
141+
dtype: &DType,
142+
len: usize,
143+
metadata: &Self::Metadata,
144+
_buffers: &[BufferHandle],
145+
children: &dyn ArrayChildren,
146+
) -> VortexResult<Self::Array> {
147+
// There should be 3 children
148+
// 1. inner
149+
// 2. patch_indices
150+
// 3. patch_values
151+
vortex_ensure!(
152+
children.len() == 3,
153+
"expected exactly 3 children from LazyPatched, found {}",
154+
children.len()
155+
);
156+
157+
let inner = children.get(0, dtype, len)?;
158+
159+
let num_patches = metadata.num_patches as usize;
160+
let patch_indices = children.get(1, dtype, num_patches)?;
161+
let patch_values = children.get(2, dtype, num_patches)?;
162+
163+
let patches = Patches::new(len, 0, patch_indices, patch_values, None)?;
164+
165+
Ok(LazyPatchedArray { inner, patches })
166+
}
167+
168+
fn with_children(array: &mut Self::Array, mut children: Vec<ArrayRef>) -> VortexResult<()> {
169+
vortex_ensure_eq!(children.len(), 3);
170+
171+
array.inner = children.remove(0);
172+
173+
let patch_indices = children.remove(0);
174+
let patch_values = children.remove(0);
175+
176+
array.patches = Patches::new(array.inner.len(), 0, patch_indices, patch_values, None)?;
177+
178+
Ok(())
179+
}
180+
181+
fn execute(array: &Self::Array, ctx: &mut ExecutionCtx) -> VortexResult<ExecutionResult> {
182+
// Execution => actually transpose the patches, get back a `PatchedArray`.
183+
let patched =
184+
PatchedArray::from_array_and_patches(array.inner.clone(), &array.patches, ctx)?
185+
.into_array();
186+
187+
Ok(ExecutionResult::done(patched))
188+
}
189+
}
190+
191+
#[derive(Debug, Clone)]
192+
pub struct LazyPatchedArray {
193+
inner: ArrayRef,
194+
patches: Patches,
195+
}
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
// SPDX-License-Identifier: Apache-2.0
2+
// SPDX-FileCopyrightText: Copyright the Vortex contributors
3+
4+
use vortex_error::VortexResult;
5+
6+
use crate::DynArray;
7+
use crate::arrays::lazy_patched::LazyPatched;
8+
use crate::arrays::lazy_patched::LazyPatchedArray;
9+
use crate::scalar::Scalar;
10+
use crate::vtable::OperationsVTable;
11+
12+
impl OperationsVTable<LazyPatched> for LazyPatched {
13+
fn scalar_at(array: &LazyPatchedArray, index: usize) -> VortexResult<Scalar> {
14+
Ok(if let Some(scalar) = array.patches.get_patched(index)? {
15+
scalar
16+
} else {
17+
array.inner.scalar_at(index)?
18+
})
19+
}
20+
}
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
// SPDX-License-Identifier: Apache-2.0
2+
// SPDX-FileCopyrightText: Copyright the Vortex contributors
3+
4+
use crate::ArrayRef;
5+
use crate::arrays::lazy_patched::LazyPatched;
6+
use crate::arrays::lazy_patched::LazyPatchedArray;
7+
use crate::vtable::ValidityChild;
8+
9+
impl ValidityChild<LazyPatched> for LazyPatched {
10+
fn validity_child(array: &LazyPatchedArray) -> &ArrayRef {
11+
&array.inner
12+
}
13+
}

vortex-array/src/arrays/mod.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -104,3 +104,4 @@ pub use variant::VariantArray;
104104

105105
#[cfg(feature = "arbitrary")]
106106
pub mod arbitrary;
107+
pub mod lazy_patched;

0 commit comments

Comments
 (0)