Skip to content

Commit

Permalink
refactor: Support object from chunks
Browse files Browse the repository at this point in the history
  • Loading branch information
ritchie46 committed Mar 6, 2025
1 parent aa8e47f commit 017d16b
Show file tree
Hide file tree
Showing 3 changed files with 30 additions and 15 deletions.
3 changes: 3 additions & 0 deletions crates/polars-core/src/chunked_array/object/builder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,9 @@ impl<T> ObjectChunkedBuilder<T>
where
T: PolarsObject,
{
pub fn field(&self) -> &Field {
&self.field
}
pub fn new(name: PlSmallStr, capacity: usize) -> Self {
ObjectChunkedBuilder {
field: Field::new(name, DataType::Object(T::type_name())),
Expand Down
13 changes: 12 additions & 1 deletion crates/polars-core/src/chunked_array/object/registry.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,13 +7,14 @@ use std::fmt::{Debug, Formatter};
use std::ops::Deref;
use std::sync::{Arc, RwLock};

use arrow::array::ArrayRef;
use arrow::datatypes::ArrowDataType;
use once_cell::sync::Lazy;
use polars_utils::pl_str::PlSmallStr;

use crate::chunked_array::object::builder::ObjectChunkedBuilder;
use crate::datatypes::AnyValue;
use crate::prelude::{ListBuilderTrait, PolarsObject};
use crate::prelude::{ListBuilderTrait, ObjectChunked, PolarsObject};
use crate::series::{IntoSeries, Series};

/// Takes a `name` and `capacity` and constructs a new builder.
Expand All @@ -40,6 +41,10 @@ static GLOBAL_OBJECT_REGISTRY: Lazy<RwLock<Option<ObjectRegistry>>> = Lazy::new(
/// This trait can be registered, after which that global registration
/// can be used to materialize object types
pub trait AnonymousObjectBuilder {
/// # Safety
/// Expect ObjectArray<T> arrays.
unsafe fn from_chunks(self: Box<Self>, chunks: Vec<ArrayRef>) -> Series;

/// Append a `null` value.
fn append_null(&mut self);

Expand Down Expand Up @@ -68,6 +73,12 @@ pub trait AnonymousObjectBuilder {
}

impl<T: PolarsObject> AnonymousObjectBuilder for ObjectChunkedBuilder<T> {
// Expect ObjectArray<T> arrays.
unsafe fn from_chunks(self: Box<Self>, chunks: Vec<ArrayRef>) -> Series {
ObjectChunked::<T>::new_with_compute_len(Arc::new(self.field().clone()), chunks)
.into_series()
}

fn append_null(&mut self) {
self.append_null()
}
Expand Down
29 changes: 15 additions & 14 deletions crates/polars-core/src/series/from.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ use polars_utils::itertools::Itertools;
use crate::chunked_array::cast::{cast_chunks, CastOptions};
#[cfg(feature = "object")]
use crate::chunked_array::object::extension::polars_extension::PolarsExtension;
use crate::chunked_array::object::registry::get_object_builder;
#[cfg(feature = "timezones")]
use crate::chunked_array::temporal::parse_fixed_offset;
#[cfg(feature = "timezones")]
Expand Down Expand Up @@ -111,20 +112,20 @@ impl Series {
},
#[cfg(feature = "object")]
Object(_) => {
assert_eq!(chunks.len(), 1);
let arr = chunks[0]
.as_any()
.downcast_ref::<FixedSizeBinaryArray>()
.unwrap();
// SAFETY:
// this is highly unsafe. it will dereference a raw ptr on the heap
// make sure the ptr is allocated and from this pid
// (the pid is checked before dereference)
{
let pe = PolarsExtension::new(arr.clone());
let s = pe.get_series(&name);
pe.take_and_forget();
s
if let Some(arr) = chunks[0].as_any().downcast_ref::<FixedSizeBinaryArray>() {
assert_eq!(chunks.len(), 1);
// SAFETY:
// this is highly unsafe. it will dereference a raw ptr on the heap
// make sure the ptr is allocated and from this pid
// (the pid is checked before dereference)
{
let pe = PolarsExtension::new(arr.clone());
let s = pe.get_series(&name);
pe.take_and_forget();
s
}
} else {
unsafe { get_object_builder(name, 0).from_chunks(chunks) }
}
},
Null => new_null(name, &chunks),
Expand Down

0 comments on commit 017d16b

Please sign in to comment.