Skip to content

Commit 722ef59

Browse files
authored
[Variant] Add ObjectBuilder::with_field for convenience (apache#7950)
# Which issue does this PR close? - Closes apache#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
1 parent 233dad3 commit 722ef59

File tree

2 files changed

+112
-57
lines changed

2 files changed

+112
-57
lines changed

parquet-variant-json/src/to_json.rs

Lines changed: 15 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -858,14 +858,14 @@ mod tests {
858858
// Create a simple object with various field types
859859
let mut builder = VariantBuilder::new();
860860

861-
{
862-
let mut obj = builder.new_object();
863-
obj.insert("name", "Alice");
864-
obj.insert("age", 30i32);
865-
obj.insert("active", true);
866-
obj.insert("score", 95.5f64);
867-
obj.finish().unwrap();
868-
}
861+
builder
862+
.new_object()
863+
.with_field("name", "Alice")
864+
.with_field("age", 30i32)
865+
.with_field("active", true)
866+
.with_field("score", 95.5f64)
867+
.finish()
868+
.unwrap();
869869

870870
let (metadata, value) = builder.finish();
871871
let variant = Variant::try_new(&metadata, &value)?;
@@ -915,13 +915,13 @@ mod tests {
915915

916916
let mut builder = VariantBuilder::new();
917917

918-
{
919-
let mut obj = builder.new_object();
920-
obj.insert("message", "Hello \"World\"\nWith\tTabs");
921-
obj.insert("path", "C:\\Users\\Alice\\Documents");
922-
obj.insert("unicode", "😀 Smiley");
923-
obj.finish().unwrap();
924-
}
918+
builder
919+
.new_object()
920+
.with_field("message", "Hello \"World\"\nWith\tTabs")
921+
.with_field("path", "C:\\Users\\Alice\\Documents")
922+
.with_field("unicode", "😀 Smiley")
923+
.finish()
924+
.unwrap();
925925

926926
let (metadata, value) = builder.finish();
927927
let variant = Variant::try_new(&metadata, &value)?;

parquet-variant/src/builder.rs

Lines changed: 97 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -631,7 +631,7 @@ impl ParentState<'_> {
631631
/// let mut object_builder = builder.new_object();
632632
/// object_builder.insert("first_name", "Jiaying");
633633
/// object_builder.insert("last_name", "Li");
634-
/// object_builder.finish();
634+
/// object_builder.finish(); // call finish to finalize the object
635635
/// // Finish the builder to get the metadata and value
636636
/// let (metadata, value) = builder.finish();
637637
/// // use the Variant API to verify the result
@@ -647,6 +647,29 @@ impl ParentState<'_> {
647647
/// );
648648
/// ```
649649
///
650+
///
651+
/// You can also use the [`ObjectBuilder::with_field`] to add fields to the
652+
/// object
653+
/// ```
654+
/// # use parquet_variant::{Variant, VariantBuilder};
655+
/// // build the same object as above
656+
/// let mut builder = VariantBuilder::new();
657+
/// builder.new_object()
658+
/// .with_field("first_name", "Jiaying")
659+
/// .with_field("last_name", "Li")
660+
/// .finish();
661+
/// let (metadata, value) = builder.finish();
662+
/// let variant = Variant::try_new(&metadata, &value).unwrap();
663+
/// let variant_object = variant.as_object().unwrap();
664+
/// assert_eq!(
665+
/// variant_object.get("first_name"),
666+
/// Some(Variant::from("Jiaying"))
667+
/// );
668+
/// assert_eq!(
669+
/// variant_object.get("last_name"),
670+
/// Some(Variant::from("Li"))
671+
/// );
672+
/// ```
650673
/// # Example: Create a [`Variant::List`] (an Array)
651674
///
652675
/// This example shows how to create an array of integers: `[1, 2, 3]`.
@@ -846,6 +869,7 @@ impl VariantBuilder {
846869
}
847870
}
848871

872+
/// Create a new VariantBuilder with pre-existing [`VariantMetadata`].
849873
pub fn with_metadata(mut self, metadata: VariantMetadata) -> Self {
850874
self.metadata_builder.extend(metadata.iter());
851875

@@ -1094,6 +1118,10 @@ impl<'a> ObjectBuilder<'a> {
10941118

10951119
/// Add a field with key and value to the object
10961120
///
1121+
/// # See Also
1122+
/// - [`ObjectBuilder::try_insert`] for a fallible version.
1123+
/// - [`ObjectBuilder::with_field`] for a builder-style API.
1124+
///
10971125
/// # Panics
10981126
///
10991127
/// This method will panic if the variant contains duplicate field names in objects
@@ -1104,7 +1132,12 @@ impl<'a> ObjectBuilder<'a> {
11041132

11051133
/// Add a field with key and value to the object
11061134
///
1107-
/// Note: when inserting duplicate keys, the new value overwrites the previous mapping,
1135+
/// # See Also
1136+
/// - [`ObjectBuilder::insert`] for a infallabel version
1137+
/// - [`ObjectBuilder::try_with_field`] for a builder-style API.
1138+
///
1139+
/// # Note
1140+
/// When inserting duplicate keys, the new value overwrites the previous mapping,
11081141
/// but the old value remains in the buffer, resulting in a larger variant
11091142
pub fn try_insert<'m, 'd, T: Into<Variant<'m, 'd>>>(
11101143
&mut self,
@@ -1127,6 +1160,26 @@ impl<'a> ObjectBuilder<'a> {
11271160
Ok(())
11281161
}
11291162

1163+
/// Builder style API for adding a field with key and value to the object
1164+
///
1165+
/// Same as [`ObjectBuilder::insert`], but returns `self` for chaining.
1166+
pub fn with_field<'m, 'd, T: Into<Variant<'m, 'd>>>(mut self, key: &str, value: T) -> Self {
1167+
self.insert(key, value);
1168+
self
1169+
}
1170+
1171+
/// Builder style API for adding a field with key and value to the object
1172+
///
1173+
/// Same as [`ObjectBuilder::try_insert`], but returns `self` for chaining.
1174+
pub fn try_with_field<'m, 'd, T: Into<Variant<'m, 'd>>>(
1175+
mut self,
1176+
key: &str,
1177+
value: T,
1178+
) -> Result<Self, ArrowError> {
1179+
self.try_insert(key, value)?;
1180+
Ok(self)
1181+
}
1182+
11301183
/// Enables validation for unique field keys when inserting into this object.
11311184
///
11321185
/// When this is enabled, calling [`ObjectBuilder::finish`] will return an error
@@ -1410,12 +1463,12 @@ mod tests {
14101463
fn test_object() {
14111464
let mut builder = VariantBuilder::new();
14121465

1413-
{
1414-
let mut obj = builder.new_object();
1415-
obj.insert("name", "John");
1416-
obj.insert("age", 42i8);
1417-
let _ = obj.finish();
1418-
}
1466+
builder
1467+
.new_object()
1468+
.with_field("name", "John")
1469+
.with_field("age", 42i8)
1470+
.finish()
1471+
.unwrap();
14191472

14201473
let (metadata, value) = builder.finish();
14211474
assert!(!metadata.is_empty());
@@ -1426,13 +1479,13 @@ mod tests {
14261479
fn test_object_field_ordering() {
14271480
let mut builder = VariantBuilder::new();
14281481

1429-
{
1430-
let mut obj = builder.new_object();
1431-
obj.insert("zebra", "stripes"); // ID = 0
1432-
obj.insert("apple", "red"); // ID = 1
1433-
obj.insert("banana", "yellow"); // ID = 2
1434-
let _ = obj.finish();
1435-
}
1482+
builder
1483+
.new_object()
1484+
.with_field("zebra", "stripes")
1485+
.with_field("apple", "red")
1486+
.with_field("banana", "yellow")
1487+
.finish()
1488+
.unwrap();
14361489

14371490
let (_, value) = builder.finish();
14381491

@@ -1452,10 +1505,12 @@ mod tests {
14521505
#[test]
14531506
fn test_duplicate_fields_in_object() {
14541507
let mut builder = VariantBuilder::new();
1455-
let mut object_builder = builder.new_object();
1456-
object_builder.insert("name", "Ron Artest");
1457-
object_builder.insert("name", "Metta World Peace");
1458-
let _ = object_builder.finish();
1508+
builder
1509+
.new_object()
1510+
.with_field("name", "Ron Artest")
1511+
.with_field("name", "Metta World Peace") // Duplicate field
1512+
.finish()
1513+
.unwrap();
14591514

14601515
let (metadata, value) = builder.finish();
14611516
let variant = Variant::try_new(&metadata, &value).unwrap();
@@ -1572,19 +1627,19 @@ mod tests {
15721627

15731628
let mut list_builder = builder.new_list();
15741629

1575-
{
1576-
let mut object_builder = list_builder.new_object();
1577-
object_builder.insert("id", 1);
1578-
object_builder.insert("type", "Cauliflower");
1579-
let _ = object_builder.finish();
1580-
}
1630+
list_builder
1631+
.new_object()
1632+
.with_field("id", 1)
1633+
.with_field("type", "Cauliflower")
1634+
.finish()
1635+
.unwrap();
15811636

1582-
{
1583-
let mut object_builder = list_builder.new_object();
1584-
object_builder.insert("id", 2);
1585-
object_builder.insert("type", "Beets");
1586-
let _ = object_builder.finish();
1587-
}
1637+
list_builder
1638+
.new_object()
1639+
.with_field("id", 2)
1640+
.with_field("type", "Beets")
1641+
.finish()
1642+
.unwrap();
15881643

15891644
list_builder.finish();
15901645

@@ -1621,17 +1676,17 @@ mod tests {
16211676

16221677
let mut list_builder = builder.new_list();
16231678

1624-
{
1625-
let mut object_builder = list_builder.new_object();
1626-
object_builder.insert("a", 1);
1627-
let _ = object_builder.finish();
1628-
}
1629-
1630-
{
1631-
let mut object_builder = list_builder.new_object();
1632-
object_builder.insert("b", 2);
1633-
let _ = object_builder.finish();
1634-
}
1679+
list_builder
1680+
.new_object()
1681+
.with_field("a", 1)
1682+
.finish()
1683+
.unwrap();
1684+
1685+
list_builder
1686+
.new_object()
1687+
.with_field("b", 2)
1688+
.finish()
1689+
.unwrap();
16351690

16361691
list_builder.finish();
16371692

0 commit comments

Comments
 (0)