This is an automated email from the ASF dual-hosted git repository.
alamb pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/arrow-rs.git
The following commit(s) were added to refs/heads/main by this push:
new 722ef596d8 [Variant] Add ObjectBuilder::with_field for convenience
(#7950)
722ef596d8 is described below
commit 722ef596d8f9d4076c51eba36949e25407b5c6aa
Author: Andrew Lamb <[email protected]>
AuthorDate: Fri Jul 18 08:01:39 2025 -0400
[Variant] Add ObjectBuilder::with_field for convenience (#7950)
# Which issue does this PR close?
- Closes https://github.com/apache/arrow-rs/issues/7949
# Rationale for this change
I would like it to be easier / more ergonomic to make objects
# What changes are included in this PR?
1. Add `ObjectBuilder::with_field`
2. Add documentation w/ examples
3. Rewrite some tests
# Are these changes tested?
Yes, by doc tests
# Are there any user-facing changes?
Yes a new API
---
parquet-variant-json/src/to_json.rs | 30 ++++----
parquet-variant/src/builder.rs | 139 +++++++++++++++++++++++++-----------
2 files changed, 112 insertions(+), 57 deletions(-)
diff --git a/parquet-variant-json/src/to_json.rs
b/parquet-variant-json/src/to_json.rs
index 55e024a66c..31cf0447d3 100644
--- a/parquet-variant-json/src/to_json.rs
+++ b/parquet-variant-json/src/to_json.rs
@@ -858,14 +858,14 @@ mod tests {
// Create a simple object with various field types
let mut builder = VariantBuilder::new();
- {
- let mut obj = builder.new_object();
- obj.insert("name", "Alice");
- obj.insert("age", 30i32);
- obj.insert("active", true);
- obj.insert("score", 95.5f64);
- obj.finish().unwrap();
- }
+ builder
+ .new_object()
+ .with_field("name", "Alice")
+ .with_field("age", 30i32)
+ .with_field("active", true)
+ .with_field("score", 95.5f64)
+ .finish()
+ .unwrap();
let (metadata, value) = builder.finish();
let variant = Variant::try_new(&metadata, &value)?;
@@ -915,13 +915,13 @@ mod tests {
let mut builder = VariantBuilder::new();
- {
- let mut obj = builder.new_object();
- obj.insert("message", "Hello \"World\"\nWith\tTabs");
- obj.insert("path", "C:\\Users\\Alice\\Documents");
- obj.insert("unicode", "😀 Smiley");
- obj.finish().unwrap();
- }
+ builder
+ .new_object()
+ .with_field("message", "Hello \"World\"\nWith\tTabs")
+ .with_field("path", "C:\\Users\\Alice\\Documents")
+ .with_field("unicode", "😀 Smiley")
+ .finish()
+ .unwrap();
let (metadata, value) = builder.finish();
let variant = Variant::try_new(&metadata, &value)?;
diff --git a/parquet-variant/src/builder.rs b/parquet-variant/src/builder.rs
index 73fa15255e..6ef91e12e8 100644
--- a/parquet-variant/src/builder.rs
+++ b/parquet-variant/src/builder.rs
@@ -631,7 +631,7 @@ impl ParentState<'_> {
/// let mut object_builder = builder.new_object();
/// object_builder.insert("first_name", "Jiaying");
/// object_builder.insert("last_name", "Li");
-/// object_builder.finish();
+/// object_builder.finish(); // call finish to finalize the object
/// // Finish the builder to get the metadata and value
/// let (metadata, value) = builder.finish();
/// // use the Variant API to verify the result
@@ -647,6 +647,29 @@ impl ParentState<'_> {
/// );
/// ```
///
+///
+/// You can also use the [`ObjectBuilder::with_field`] to add fields to the
+/// object
+/// ```
+/// # use parquet_variant::{Variant, VariantBuilder};
+/// // build the same object as above
+/// let mut builder = VariantBuilder::new();
+/// builder.new_object()
+/// .with_field("first_name", "Jiaying")
+/// .with_field("last_name", "Li")
+/// .finish();
+/// let (metadata, value) = builder.finish();
+/// let variant = Variant::try_new(&metadata, &value).unwrap();
+/// let variant_object = variant.as_object().unwrap();
+/// assert_eq!(
+/// variant_object.get("first_name"),
+/// Some(Variant::from("Jiaying"))
+/// );
+/// assert_eq!(
+/// variant_object.get("last_name"),
+/// Some(Variant::from("Li"))
+/// );
+/// ```
/// # Example: Create a [`Variant::List`] (an Array)
///
/// This example shows how to create an array of integers: `[1, 2, 3]`.
@@ -846,6 +869,7 @@ impl VariantBuilder {
}
}
+ /// Create a new VariantBuilder with pre-existing [`VariantMetadata`].
pub fn with_metadata(mut self, metadata: VariantMetadata) -> Self {
self.metadata_builder.extend(metadata.iter());
@@ -1094,6 +1118,10 @@ impl<'a> ObjectBuilder<'a> {
/// Add a field with key and value to the object
///
+ /// # See Also
+ /// - [`ObjectBuilder::try_insert`] for a fallible version.
+ /// - [`ObjectBuilder::with_field`] for a builder-style API.
+ ///
/// # Panics
///
/// This method will panic if the variant contains duplicate field names
in objects
@@ -1104,7 +1132,12 @@ impl<'a> ObjectBuilder<'a> {
/// Add a field with key and value to the object
///
- /// Note: when inserting duplicate keys, the new value overwrites the
previous mapping,
+ /// # See Also
+ /// - [`ObjectBuilder::insert`] for a infallabel version
+ /// - [`ObjectBuilder::try_with_field`] for a builder-style API.
+ ///
+ /// # Note
+ /// When inserting duplicate keys, the new value overwrites the previous
mapping,
/// but the old value remains in the buffer, resulting in a larger variant
pub fn try_insert<'m, 'd, T: Into<Variant<'m, 'd>>>(
&mut self,
@@ -1127,6 +1160,26 @@ impl<'a> ObjectBuilder<'a> {
Ok(())
}
+ /// Builder style API for adding a field with key and value to the object
+ ///
+ /// Same as [`ObjectBuilder::insert`], but returns `self` for chaining.
+ pub fn with_field<'m, 'd, T: Into<Variant<'m, 'd>>>(mut self, key: &str,
value: T) -> Self {
+ self.insert(key, value);
+ self
+ }
+
+ /// Builder style API for adding a field with key and value to the object
+ ///
+ /// Same as [`ObjectBuilder::try_insert`], but returns `self` for chaining.
+ pub fn try_with_field<'m, 'd, T: Into<Variant<'m, 'd>>>(
+ mut self,
+ key: &str,
+ value: T,
+ ) -> Result<Self, ArrowError> {
+ self.try_insert(key, value)?;
+ Ok(self)
+ }
+
/// Enables validation for unique field keys when inserting into this
object.
///
/// When this is enabled, calling [`ObjectBuilder::finish`] will return an
error
@@ -1410,12 +1463,12 @@ mod tests {
fn test_object() {
let mut builder = VariantBuilder::new();
- {
- let mut obj = builder.new_object();
- obj.insert("name", "John");
- obj.insert("age", 42i8);
- let _ = obj.finish();
- }
+ builder
+ .new_object()
+ .with_field("name", "John")
+ .with_field("age", 42i8)
+ .finish()
+ .unwrap();
let (metadata, value) = builder.finish();
assert!(!metadata.is_empty());
@@ -1426,13 +1479,13 @@ mod tests {
fn test_object_field_ordering() {
let mut builder = VariantBuilder::new();
- {
- let mut obj = builder.new_object();
- obj.insert("zebra", "stripes"); // ID = 0
- obj.insert("apple", "red"); // ID = 1
- obj.insert("banana", "yellow"); // ID = 2
- let _ = obj.finish();
- }
+ builder
+ .new_object()
+ .with_field("zebra", "stripes")
+ .with_field("apple", "red")
+ .with_field("banana", "yellow")
+ .finish()
+ .unwrap();
let (_, value) = builder.finish();
@@ -1452,10 +1505,12 @@ mod tests {
#[test]
fn test_duplicate_fields_in_object() {
let mut builder = VariantBuilder::new();
- let mut object_builder = builder.new_object();
- object_builder.insert("name", "Ron Artest");
- object_builder.insert("name", "Metta World Peace");
- let _ = object_builder.finish();
+ builder
+ .new_object()
+ .with_field("name", "Ron Artest")
+ .with_field("name", "Metta World Peace") // Duplicate field
+ .finish()
+ .unwrap();
let (metadata, value) = builder.finish();
let variant = Variant::try_new(&metadata, &value).unwrap();
@@ -1572,19 +1627,19 @@ mod tests {
let mut list_builder = builder.new_list();
- {
- let mut object_builder = list_builder.new_object();
- object_builder.insert("id", 1);
- object_builder.insert("type", "Cauliflower");
- let _ = object_builder.finish();
- }
+ list_builder
+ .new_object()
+ .with_field("id", 1)
+ .with_field("type", "Cauliflower")
+ .finish()
+ .unwrap();
- {
- let mut object_builder = list_builder.new_object();
- object_builder.insert("id", 2);
- object_builder.insert("type", "Beets");
- let _ = object_builder.finish();
- }
+ list_builder
+ .new_object()
+ .with_field("id", 2)
+ .with_field("type", "Beets")
+ .finish()
+ .unwrap();
list_builder.finish();
@@ -1621,17 +1676,17 @@ mod tests {
let mut list_builder = builder.new_list();
- {
- let mut object_builder = list_builder.new_object();
- object_builder.insert("a", 1);
- let _ = object_builder.finish();
- }
-
- {
- let mut object_builder = list_builder.new_object();
- object_builder.insert("b", 2);
- let _ = object_builder.finish();
- }
+ list_builder
+ .new_object()
+ .with_field("a", 1)
+ .finish()
+ .unwrap();
+
+ list_builder
+ .new_object()
+ .with_field("b", 2)
+ .finish()
+ .unwrap();
list_builder.finish();