Skip to main content

parquet_variant/builder/
object.rs

1// Licensed to the Apache Software Foundation (ASF) under one
2// or more contributor license agreements.  See the NOTICE file
3// distributed with this work for additional information
4// regarding copyright ownership.  The ASF licenses this file
5// to you under the Apache License, Version 2.0 (the
6// "License"); you may not use this file except in compliance
7// with the License.  You may obtain a copy of the License at
8//
9//   http://www.apache.org/licenses/LICENSE-2.0
10//
11// Unless required by applicable law or agreed to in writing,
12// software distributed under the License is distributed on an
13// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
14// KIND, either express or implied.  See the License for the
15// specific language governing permissions and limitations
16// under the License.
17use crate::builder::list::ListBuilder;
18use crate::builder::metadata::MetadataBuilder;
19use crate::decoder::VariantBasicType;
20use crate::{
21    BASIC_TYPE_BITS, BuilderSpecificState, ParentState, ValueBuilder, Variant, VariantBuilderExt,
22    int_size,
23};
24use arrow_schema::ArrowError;
25use indexmap::IndexMap;
26
27fn object_header<const LARGE_BIT: u8, const ID_SIZE: u8, const OFFSET_SIZE: u8>() -> u8 {
28    (LARGE_BIT << (BASIC_TYPE_BITS + 4))
29        | ((ID_SIZE - 1) << (BASIC_TYPE_BITS + 2))
30        | ((OFFSET_SIZE - 1) << BASIC_TYPE_BITS)
31        | VariantBasicType::Object as u8
32}
33
34struct ObjectHeaderWriter<const OFFSET_SIZE: u8, const ID_SIZE: u8>();
35
36impl<const OFFSET_SIZE: u8, const ID_SIZE: u8> ObjectHeaderWriter<OFFSET_SIZE, ID_SIZE> {
37    fn write(
38        dst: &mut Vec<u8>,
39        num_fields: usize,
40        field_ids: impl Iterator<Item = u32>,
41        offsets: impl Iterator<Item = usize>,
42        data_size: usize,
43    ) {
44        let is_large = num_fields > u8::MAX as usize;
45        // num_fields will consume 4 bytes when it is larger than u8::MAX
46        if is_large {
47            dst.push(object_header::<1, { ID_SIZE }, { OFFSET_SIZE }>());
48            append_packed_u32::<4>(dst, num_fields);
49        } else {
50            dst.push(object_header::<0, { ID_SIZE }, { OFFSET_SIZE }>());
51            append_packed_u32::<1>(dst, num_fields);
52        }
53
54        for id in field_ids {
55            append_packed_u32::<ID_SIZE>(dst, id as usize);
56        }
57
58        for off in offsets {
59            append_packed_u32::<OFFSET_SIZE>(dst, off);
60        }
61
62        append_packed_u32::<OFFSET_SIZE>(dst, data_size);
63    }
64}
65
66#[inline(always)]
67fn append_packed_u32<const SIZE: u8>(dest: &mut Vec<u8>, value: usize) {
68    dest.extend_from_slice(&value.to_le_bytes()[..SIZE as usize]);
69}
70
71/// A builder for creating [`Variant::Object`] values.
72///
73/// See the examples on [`VariantBuilder`] for usage.
74///
75/// [`VariantBuilder`]: crate::VariantBuilder
76#[derive(Debug)]
77pub struct ObjectBuilder<'a, S: BuilderSpecificState> {
78    parent_state: ParentState<'a, S>,
79    pub(crate) fields: IndexMap<u32, usize>, // (field_id, offset)
80    validate_unique_fields: bool,
81}
82
83impl<'a, S: BuilderSpecificState> ObjectBuilder<'a, S> {
84    /// Creates a new object builder, nested on top of the given parent state.
85    pub fn new(parent_state: ParentState<'a, S>, validate_unique_fields: bool) -> Self {
86        Self {
87            parent_state,
88            fields: IndexMap::new(),
89            validate_unique_fields,
90        }
91    }
92
93    /// Add a field with key and value to the object
94    ///
95    /// # See Also
96    /// - [`ObjectBuilder::try_insert`] for a fallible version.
97    /// - [`ObjectBuilder::with_field`] for a builder-style API.
98    ///
99    /// # Panics
100    ///
101    /// This method will panic if the variant contains duplicate field names in objects
102    /// when validation is enabled. For a fallible version, use [`ObjectBuilder::try_insert`]
103    pub fn insert<'m, 'd, T: Into<Variant<'m, 'd>>>(&mut self, key: &str, value: T) {
104        let (state, _) = self.parent_state(key).unwrap();
105        ValueBuilder::append_variant(state, value.into())
106    }
107
108    /// Add a field with key and value to the object
109    ///
110    /// # See Also
111    /// - [`ObjectBuilder::insert`] for an infallible version that panics
112    /// - [`ObjectBuilder::try_with_field`] for a builder-style API.
113    ///
114    /// # Note
115    /// Attempting to insert a duplicate field name produces an error if unique field
116    /// validation is enabled. Otherwise, the new value overwrites the previous field mapping
117    /// without erasing the old value, resulting in a larger variant
118    pub fn try_insert<'m, 'd, T: Into<Variant<'m, 'd>>>(
119        &mut self,
120        key: &str,
121        value: T,
122    ) -> Result<(), ArrowError> {
123        let (state, _) = self.parent_state(key)?;
124        ValueBuilder::try_append_variant(state, value.into())
125    }
126
127    /// Add a field with key and value to the object by copying raw bytes when possible.
128    ///
129    /// For objects and lists, this directly copies their underlying byte representation instead of
130    /// performing a logical copy, and without touching the metadata builder. For other variant
131    /// types, this falls back to the standard append behavior.
132    ///
133    /// The caller must ensure that the metadata dictionary is already built and correct for
134    /// any objects or lists being appended, but the value's new field name is handled normally.
135    ///
136    /// # Panics
137    ///
138    /// This method will panic if the variant contains duplicate field names in objects
139    /// when validation is enabled. For a fallible version, use [`ObjectBuilder::try_insert_bytes`]
140    pub fn insert_bytes<'m, 'd>(&mut self, key: &str, value: impl Into<Variant<'m, 'd>>) {
141        self.try_insert_bytes(key, value).unwrap()
142    }
143
144    /// Add a field with key and value to the object by copying raw bytes when possible.
145    ///
146    /// For objects and lists, this directly copies their underlying byte representation instead of
147    /// performing a logical copy, and without touching the metadata builder. For other variant
148    /// types, this falls back to the standard append behavior.
149    ///
150    /// The caller must ensure that the metadata dictionary is already built and correct for
151    /// any objects or lists being appended, but the value's new field name is handled normally.
152    ///
153    /// # Note
154    /// When inserting duplicate keys, the new value overwrites the previous mapping,
155    /// but the old value remains in the buffer, resulting in a larger variant
156    pub fn try_insert_bytes<'m, 'd>(
157        &mut self,
158        key: &str,
159        value: impl Into<Variant<'m, 'd>>,
160    ) -> Result<(), ArrowError> {
161        let (state, _) = self.parent_state(key)?;
162        ValueBuilder::append_variant_bytes(state, value.into());
163        Ok(())
164    }
165
166    /// Builder style API for adding a field with key and value to the object
167    ///
168    /// Same as [`ObjectBuilder::insert`], but returns `self` for chaining.
169    pub fn with_field<'m, 'd, T: Into<Variant<'m, 'd>>>(mut self, key: &str, value: T) -> Self {
170        self.insert(key, value);
171        self
172    }
173
174    /// Builder style API for adding a field with key and value to the object
175    ///
176    /// Same as [`ObjectBuilder::try_insert`], but returns `self` for chaining.
177    pub fn try_with_field<'m, 'd, T: Into<Variant<'m, 'd>>>(
178        mut self,
179        key: &str,
180        value: T,
181    ) -> Result<Self, ArrowError> {
182        self.try_insert(key, value)?;
183        Ok(self)
184    }
185
186    /// Enables validation for unique field keys when inserting into this object.
187    ///
188    /// When this is enabled, calling [`ObjectBuilder::finish`] will return an error
189    /// if any duplicate field keys were added using [`ObjectBuilder::insert`].
190    pub fn with_validate_unique_fields(mut self, validate_unique_fields: bool) -> Self {
191        self.validate_unique_fields = validate_unique_fields;
192        self
193    }
194
195    // Returns validate_unique_fields because we can no longer reference self once this method returns.
196    fn parent_state<'b>(
197        &'b mut self,
198        field_name: &str,
199    ) -> Result<(ParentState<'b, ObjectState<'b>>, bool), ArrowError> {
200        let validate_unique_fields = self.validate_unique_fields;
201        let state = ParentState::try_object(
202            self.parent_state.value_builder,
203            self.parent_state.metadata_builder,
204            &mut self.fields,
205            self.parent_state.saved_value_builder_offset,
206            field_name,
207            validate_unique_fields,
208        )?;
209        Ok((state, validate_unique_fields))
210    }
211
212    /// Returns an object builder that can be used to append a new (nested) object to this object.
213    ///
214    /// WARNING: The builder will have no effect unless/until [`ObjectBuilder::finish`] is called.
215    ///
216    /// # Panics
217    ///
218    /// Panics if the proposed key was a duplicate
219    pub fn new_object<'b>(&'b mut self, key: &'b str) -> ObjectBuilder<'b, ObjectState<'b>> {
220        self.try_new_object(key).unwrap()
221    }
222
223    /// Returns an object builder that can be used to append a new (nested) object to this object.
224    ///
225    /// Fails if the proposed key was a duplicate
226    ///
227    /// WARNING: The builder will have no effect unless/until [`ObjectBuilder::finish`] is called.
228    pub fn try_new_object<'b>(
229        &'b mut self,
230        key: &str,
231    ) -> Result<ObjectBuilder<'b, ObjectState<'b>>, ArrowError> {
232        let (parent_state, validate_unique_fields) = self.parent_state(key)?;
233        Ok(ObjectBuilder::new(parent_state, validate_unique_fields))
234    }
235
236    /// Returns a list builder that can be used to append a new (nested) list to this object.
237    ///
238    /// WARNING: The builder will have no effect unless/until [`ListBuilder::finish`] is called.
239    ///
240    /// # Panics
241    ///
242    /// Panics if the proposed key was a duplicate
243    pub fn new_list<'b>(&'b mut self, key: &str) -> ListBuilder<'b, ObjectState<'b>> {
244        self.try_new_list(key).unwrap()
245    }
246
247    /// Returns a list builder that can be used to append a new (nested) list to this object.
248    ///
249    /// Fails if the proposed key was a duplicate
250    ///
251    /// WARNING: The builder will have no effect unless/until [`ListBuilder::finish`] is called.
252    pub fn try_new_list<'b>(
253        &'b mut self,
254        key: &str,
255    ) -> Result<ListBuilder<'b, ObjectState<'b>>, ArrowError> {
256        let (parent_state, validate_unique_fields) = self.parent_state(key)?;
257        Ok(ListBuilder::new(parent_state, validate_unique_fields))
258    }
259
260    /// Finalizes this object and appends it to its parent, which otherwise remains unmodified.
261    pub fn finish(mut self) {
262        let metadata_builder = self.parent_state.metadata_builder();
263
264        self.fields.sort_by(|&field_a_id, _, &field_b_id, _| {
265            let field_a_name = metadata_builder.field_name(field_a_id as usize);
266            let field_b_name = metadata_builder.field_name(field_b_id as usize);
267            field_a_name.cmp(field_b_name)
268        });
269
270        let max_id = self.fields.iter().map(|(i, _)| *i).max().unwrap_or(0);
271        let id_size = int_size(max_id as usize);
272
273        let starting_offset = self.parent_state.saved_value_builder_offset;
274        let value_builder = self.parent_state.value_builder();
275        let current_offset = value_builder.offset();
276        // Current object starts from `object_start_offset`
277        let data_size = current_offset - starting_offset;
278        let offset_size = int_size(data_size);
279
280        let num_fields = self.fields.len();
281        let is_large = num_fields > u8::MAX as usize;
282
283        let header_size = 1 + // header byte
284            (if is_large { 4 } else { 1 }) + // num_fields
285            (num_fields * id_size as usize) + // field IDs
286            ((num_fields + 1) * offset_size as usize); // field offsets + data_size
287
288        let mut bytes_to_splice = Vec::with_capacity(header_size);
289
290        macro_rules! write_header {
291            ($offset_size:expr, $id_size:expr) => {
292                ObjectHeaderWriter::<{ $offset_size as u8 }, { $id_size as u8 }>::write(
293                    &mut bytes_to_splice,
294                    num_fields,
295                    self.fields.keys().copied(),
296                    self.fields.values().copied(),
297                    data_size,
298                )
299            };
300        }
301
302        use crate::decoder::OffsetSizeBytes::*;
303        match (offset_size, id_size) {
304            (One, One) => write_header!(One, One),
305            (One, Two) => write_header!(One, Two),
306            (One, Three) => write_header!(One, Three),
307            (One, Four) => write_header!(One, Four),
308            (Two, One) => write_header!(Two, One),
309            (Two, Two) => write_header!(Two, Two),
310            (Two, Three) => write_header!(Two, Three),
311            (Two, Four) => write_header!(Two, Four),
312            (Three, One) => write_header!(Three, One),
313            (Three, Two) => write_header!(Three, Two),
314            (Three, Three) => write_header!(Three, Three),
315            (Three, Four) => write_header!(Three, Four),
316            (Four, One) => write_header!(Four, One),
317            (Four, Two) => write_header!(Four, Two),
318            (Four, Three) => write_header!(Four, Three),
319            (Four, Four) => write_header!(Four, Four),
320        }
321
322        // Shift existing data to make room for the header
323        value_builder
324            .inner_mut()
325            .splice(starting_offset..starting_offset, bytes_to_splice);
326
327        self.parent_state.finish();
328    }
329}
330
331impl<'m, 'v, S, K, V> Extend<(K, V)> for ObjectBuilder<'_, S>
332where
333    S: BuilderSpecificState,
334    K: AsRef<str>,
335    V: Into<Variant<'m, 'v>>,
336{
337    fn extend<T: IntoIterator<Item = (K, V)>>(&mut self, iter: T) {
338        for (key, value) in iter {
339            self.insert(key.as_ref(), value);
340        }
341    }
342}
343
344/// Internal state for object building
345#[derive(Debug)]
346pub struct ObjectState<'a> {
347    fields: &'a mut IndexMap<u32, usize>,
348    saved_fields_size: usize,
349}
350
351// `ObjectBuilder::finish()` eagerly updates the field offsets, which we should rollback on failure.
352impl BuilderSpecificState for ObjectState<'_> {
353    fn rollback(&mut self) {
354        self.fields.truncate(self.saved_fields_size);
355    }
356}
357
358impl<'a> ParentState<'a, ObjectState<'a>> {
359    /// Creates a new instance suitable for an [`ObjectBuilder`]. The value and metadata builder state
360    /// is checkpointed and will roll back on drop, unless [`Self::finish`] is called. The new
361    /// field's name and offset are also captured eagerly and will also roll back if not finished.
362    ///
363    /// The call fails if the field name is invalid (e.g. because it duplicates an existing field).
364    pub fn try_object(
365        value_builder: &'a mut ValueBuilder,
366        metadata_builder: &'a mut dyn MetadataBuilder,
367        fields: &'a mut IndexMap<u32, usize>,
368        saved_parent_value_builder_offset: usize,
369        field_name: &str,
370        validate_unique_fields: bool,
371    ) -> Result<Self, ArrowError> {
372        // The saved_parent_buffer_offset is the buffer size as of when the parent builder was
373        // constructed. The saved_buffer_offset is the buffer size as of now (when a child builder
374        // is created). The variant field_offset entry for this field is their difference.
375        let saved_value_builder_offset = value_builder.offset();
376        let saved_fields_size = fields.len();
377        let saved_metadata_builder_dict_size = metadata_builder.num_field_names();
378        let field_id = metadata_builder.try_upsert_field_name(field_name)?;
379        let field_start = saved_value_builder_offset - saved_parent_value_builder_offset;
380        if fields.insert(field_id, field_start).is_some() && validate_unique_fields {
381            return Err(ArrowError::InvalidArgumentError(format!(
382                "Duplicate field name: {field_name}"
383            )));
384        }
385
386        let builder_state = ObjectState {
387            fields,
388            saved_fields_size,
389        };
390        Ok(Self {
391            saved_metadata_builder_dict_size,
392            saved_value_builder_offset,
393            value_builder,
394            metadata_builder,
395            builder_state,
396            finished: false,
397        })
398    }
399}
400
401/// A [`VariantBuilderExt`] that inserts a new field into a variant object.
402pub struct ObjectFieldBuilder<'o, 'v, 's, S: BuilderSpecificState> {
403    key: &'s str,
404    builder: &'o mut ObjectBuilder<'v, S>,
405}
406
407impl<'o, 'v, 's, S: BuilderSpecificState> ObjectFieldBuilder<'o, 'v, 's, S> {
408    pub fn new(key: &'s str, builder: &'o mut ObjectBuilder<'v, S>) -> Self {
409        Self { key, builder }
410    }
411}
412
413impl<S: BuilderSpecificState> VariantBuilderExt for ObjectFieldBuilder<'_, '_, '_, S> {
414    type State<'a>
415        = ObjectState<'a>
416    where
417        Self: 'a;
418
419    /// A NULL object field is interpreted as missing, so nothing gets inserted at all.
420    fn append_null(&mut self) {}
421    fn append_value<'m, 'v>(&mut self, value: impl Into<Variant<'m, 'v>>) {
422        self.builder.insert(self.key, value);
423    }
424
425    fn try_new_list(&mut self) -> Result<ListBuilder<'_, Self::State<'_>>, ArrowError> {
426        self.builder.try_new_list(self.key)
427    }
428
429    fn try_new_object(&mut self) -> Result<ObjectBuilder<'_, Self::State<'_>>, ArrowError> {
430        self.builder.try_new_object(self.key)
431    }
432}
433
434#[cfg(test)]
435mod tests {
436    use crate::{
437        ParentState, ValueBuilder, Variant, VariantBuilder, VariantMetadata,
438        WritableMetadataBuilder,
439        builder::{metadata::ReadOnlyMetadataBuilder, object::ObjectBuilder},
440        decoder::VariantBasicType,
441    };
442
443    #[test]
444    fn test_object() {
445        let mut builder = VariantBuilder::new();
446
447        builder
448            .new_object()
449            .with_field("name", "John")
450            .with_field("age", 42i8)
451            .finish();
452
453        let (metadata, value) = builder.finish();
454        assert!(!metadata.is_empty());
455        assert!(!value.is_empty());
456    }
457
458    #[test]
459    fn test_object_field_ordering() {
460        let mut builder = VariantBuilder::new();
461
462        builder
463            .new_object()
464            .with_field("zebra", "stripes")
465            .with_field("apple", "red")
466            .with_field("banana", "yellow")
467            .finish();
468
469        let (_, value) = builder.finish();
470
471        let header = value[0];
472        assert_eq!(header & 0x03, VariantBasicType::Object as u8);
473
474        let field_count = value[1] as usize;
475        assert_eq!(field_count, 3);
476
477        // Get field IDs from the object header
478        let field_ids: Vec<u8> = value[2..5].to_vec();
479
480        // apple(1), banana(2), zebra(0)
481        assert_eq!(field_ids, vec![1, 2, 0]);
482    }
483
484    #[test]
485    fn test_duplicate_fields_in_object() {
486        let mut builder = VariantBuilder::new();
487        builder
488            .new_object()
489            .with_field("name", "Ron Artest")
490            .with_field("name", "Metta World Peace") // Duplicate field
491            .finish();
492
493        let (metadata, value) = builder.finish();
494        let variant = Variant::try_new(&metadata, &value).unwrap();
495
496        let obj = variant.as_object().unwrap();
497        assert_eq!(obj.len(), 1);
498        assert_eq!(obj.field(0).unwrap(), Variant::from("Metta World Peace"));
499
500        assert_eq!(
501            vec![("name", Variant::from("Metta World Peace"))],
502            obj.iter().collect::<Vec<_>>()
503        );
504    }
505
506    #[test]
507    fn test_read_only_metadata_builder() {
508        // First create some metadata with a few field names
509        let mut default_builder = WritableMetadataBuilder::default();
510        default_builder.upsert_field_name("name");
511        default_builder.upsert_field_name("age");
512        default_builder.upsert_field_name("active");
513        default_builder.finish();
514        let metadata_bytes = default_builder.into_inner();
515
516        // Use the metadata to build new variant values
517        let metadata = VariantMetadata::try_new(&metadata_bytes).unwrap();
518        let mut metadata_builder = ReadOnlyMetadataBuilder::new(&metadata);
519        let mut value_builder = ValueBuilder::new();
520
521        {
522            let state = ParentState::variant(&mut value_builder, &mut metadata_builder);
523            let mut obj = ObjectBuilder::new(state, false);
524
525            // These should succeed because the fields exist in the metadata
526            obj.insert("name", "Alice");
527            obj.insert("age", 30i8);
528            obj.insert("active", true);
529            obj.finish();
530        }
531
532        let value = value_builder.into_inner();
533
534        // Verify the variant was built correctly
535        let variant = Variant::try_new(&metadata_bytes, &value).unwrap();
536        let obj = variant.as_object().unwrap();
537        assert_eq!(obj.get("name"), Some(Variant::from("Alice")));
538        assert_eq!(obj.get("age"), Some(Variant::Int8(30)));
539        assert_eq!(obj.get("active"), Some(Variant::from(true)));
540    }
541
542    /// A dictionary that is not marked sorted may legally hold the same string at more than one
543    /// field id. A field name must still resolve to a single id, or an object builder sharing that
544    /// dictionary would emit two fields with the same name.
545    ///
546    /// Metadata dictionary `["a", "a"]`, unsorted:
547    const DUPLICATE_ENTRY_METADATA: &[u8] = &[
548        0b0000_0001, // header: offset_size_minus_one=0, sorted=0, version=1
549        2,           // dictionary_size
550        0x00,
551        0x01,
552        0x02,
553        b'a',
554        b'a',
555    ];
556
557    #[test]
558    fn test_read_only_metadata_builder_duplicate_dictionary_entries_are_detected() {
559        let metadata = VariantMetadata::try_new(DUPLICATE_ENTRY_METADATA).unwrap();
560        assert!(!metadata.is_sorted());
561
562        let mut metadata_builder = ReadOnlyMetadataBuilder::new(&metadata);
563        let mut value_builder = ValueBuilder::new();
564        let state = ParentState::variant(&mut value_builder, &mut metadata_builder);
565        let mut obj = ObjectBuilder::new(state, true);
566
567        // Both dictionary entries name "a", so inserting both must be reported as a duplicate
568        // field name rather than producing an object with two fields named "a".
569        obj.insert(metadata.get(0).unwrap(), 1i8);
570        let err = obj
571            .try_insert(metadata.get(1).unwrap(), 2i8)
572            .expect_err("duplicate field name should be rejected");
573        assert!(
574            err.to_string().contains("Duplicate field name"),
575            "unexpected error: {err}"
576        );
577    }
578
579    #[test]
580    fn test_read_only_metadata_builder_duplicate_dictionary_entries_build_valid_object() {
581        let metadata = VariantMetadata::try_new(DUPLICATE_ENTRY_METADATA).unwrap();
582
583        let mut metadata_builder = ReadOnlyMetadataBuilder::new(&metadata);
584        let mut value_builder = ValueBuilder::new();
585        {
586            let state = ParentState::variant(&mut value_builder, &mut metadata_builder);
587            let mut obj = ObjectBuilder::new(state, false);
588
589            // A name borrowed from the dictionary and an owned copy of that same name must resolve
590            // to the same field id, so that the last write wins instead of both being emitted.
591            obj.insert(metadata.get(1).unwrap(), 1i8);
592            let owned = String::from("a");
593            obj.insert(owned.as_str(), 2i8);
594            obj.finish();
595        }
596
597        let value = value_builder.into_inner();
598        let variant = Variant::try_new(DUPLICATE_ENTRY_METADATA, &value).unwrap();
599        let obj = variant.as_object().unwrap();
600        assert_eq!(obj.len(), 1);
601        assert_eq!(obj.get("a"), Some(Variant::Int8(2)));
602    }
603
604    // matthew
605    #[test]
606    fn test_append_object() {
607        let (m1, v1) = make_object();
608        let variant = Variant::new(&m1, &v1);
609
610        let mut builder = VariantBuilder::new().with_metadata(VariantMetadata::new(&m1));
611
612        builder.append_value(variant.clone());
613
614        let (metadata, value) = builder.finish();
615        assert_eq!(variant, Variant::new(&metadata, &value));
616    }
617
618    /// make an object variant with field names in reverse lexicographical order
619    fn make_object() -> (Vec<u8>, Vec<u8>) {
620        let mut builder = VariantBuilder::new();
621
622        let mut obj = builder.new_object();
623
624        obj.insert("b", true);
625        obj.insert("a", false);
626        obj.finish();
627        builder.finish()
628    }
629
630    #[test]
631    fn test_append_nested_object() {
632        let (m1, v1) = make_nested_object();
633        let variant = Variant::new(&m1, &v1);
634
635        // because we can guarantee metadata is validated through the builder
636        let mut builder = VariantBuilder::new().with_metadata(VariantMetadata::new(&m1));
637        builder.append_value(variant.clone());
638
639        let (metadata, value) = builder.finish();
640        let result_variant = Variant::new(&metadata, &value);
641
642        assert_eq!(variant, result_variant);
643    }
644
645    /// make a nested object variant
646    fn make_nested_object() -> (Vec<u8>, Vec<u8>) {
647        let mut builder = VariantBuilder::new();
648
649        {
650            let mut outer_obj = builder.new_object();
651
652            {
653                let mut inner_obj = outer_obj.new_object("b");
654                inner_obj.insert("a", "inner_value");
655                inner_obj.finish();
656            }
657
658            outer_obj.finish();
659        }
660
661        builder.finish()
662    }
663
664    #[test]
665    fn test_nested_object() {
666        /*
667        {
668            "c": {
669                "b": "a"
670            }
671        }
672
673        */
674
675        let mut builder = VariantBuilder::new();
676        {
677            let mut outer_object_builder = builder.new_object();
678            {
679                let mut inner_object_builder = outer_object_builder.new_object("c");
680                inner_object_builder.insert("b", "a");
681                inner_object_builder.finish();
682            }
683
684            outer_object_builder.finish();
685        }
686
687        let (metadata, value) = builder.finish();
688        let variant = Variant::try_new(&metadata, &value).unwrap();
689        let outer_object = variant.as_object().unwrap();
690
691        assert_eq!(outer_object.len(), 1);
692        assert_eq!(outer_object.field_name(0).unwrap(), "c");
693
694        let inner_object_variant = outer_object.field(0).unwrap();
695        let inner_object = inner_object_variant.as_object().unwrap();
696
697        assert_eq!(inner_object.len(), 1);
698        assert_eq!(inner_object.field_name(0).unwrap(), "b");
699        assert_eq!(inner_object.field(0).unwrap(), Variant::from("a"));
700    }
701
702    #[test]
703    fn test_nested_object_with_duplicate_field_names_per_object() {
704        /*
705        {
706            "c": {
707                "b": false,
708                "c": "a"
709            },
710            "b": false,
711        }
712
713        */
714
715        let mut builder = VariantBuilder::new();
716        {
717            let mut outer_object_builder = builder.new_object();
718            {
719                let mut inner_object_builder = outer_object_builder.new_object("c");
720                inner_object_builder.insert("b", false);
721                inner_object_builder.insert("c", "a");
722
723                inner_object_builder.finish();
724            }
725
726            outer_object_builder.insert("b", false);
727            outer_object_builder.finish();
728        }
729
730        let (metadata, value) = builder.finish();
731        let variant = Variant::try_new(&metadata, &value).unwrap();
732        let outer_object = variant.as_object().unwrap();
733
734        assert_eq!(outer_object.len(), 2);
735        assert_eq!(outer_object.field_name(0).unwrap(), "b");
736
737        let inner_object_variant = outer_object.field(1).unwrap();
738        let inner_object = inner_object_variant.as_object().unwrap();
739
740        assert_eq!(inner_object.len(), 2);
741        assert_eq!(inner_object.field_name(0).unwrap(), "b");
742        assert_eq!(inner_object.field(0).unwrap(), Variant::from(false));
743        assert_eq!(inner_object.field_name(1).unwrap(), "c");
744        assert_eq!(inner_object.field(1).unwrap(), Variant::from("a"));
745    }
746
747    #[test]
748    fn test_nested_object_with_heterogeneous_fields() {
749        /*
750        {
751            "a": false,
752            "c": {
753                "b": "a",
754                "c": {
755                   "aa": "bb",
756                },
757                "d": {
758                    "cc": "dd"
759                }
760            },
761            "b": true,
762            "d": {
763               "e": 1,
764               "f": [1, true],
765               "g": ["tree", false],
766            }
767        }
768        */
769
770        let mut builder = VariantBuilder::new();
771        {
772            let mut outer_object_builder = builder.new_object();
773
774            outer_object_builder.insert("a", false);
775
776            {
777                let mut inner_object_builder = outer_object_builder.new_object("c");
778                inner_object_builder.insert("b", "a");
779
780                {
781                    let mut inner_inner_object_builder = inner_object_builder.new_object("c");
782                    inner_inner_object_builder.insert("aa", "bb");
783                    inner_inner_object_builder.finish();
784                }
785
786                {
787                    let mut inner_inner_object_builder = inner_object_builder.new_object("d");
788                    inner_inner_object_builder.insert("cc", "dd");
789                    inner_inner_object_builder.finish();
790                }
791                inner_object_builder.finish();
792            }
793
794            outer_object_builder.insert("b", true);
795
796            {
797                let mut inner_object_builder = outer_object_builder.new_object("d");
798                inner_object_builder.insert("e", 1);
799                {
800                    let mut inner_list_builder = inner_object_builder.new_list("f");
801                    inner_list_builder.append_value(1);
802                    inner_list_builder.append_value(true);
803
804                    inner_list_builder.finish();
805                }
806
807                {
808                    let mut inner_list_builder = inner_object_builder.new_list("g");
809                    inner_list_builder.append_value("tree");
810                    inner_list_builder.append_value(false);
811
812                    inner_list_builder.finish();
813                }
814
815                inner_object_builder.finish();
816            }
817
818            outer_object_builder.finish();
819        }
820
821        let (metadata, value) = builder.finish();
822
823        // note, object fields are now sorted lexicographically by field name
824        /*
825         {
826            "a": false,
827            "b": true,
828            "c": {
829                "b": "a",
830                "c": {
831                   "aa": "bb",
832                },
833                "d": {
834                    "cc": "dd"
835                }
836            },
837            "d": {
838               "e": 1,
839               "f": [1, true],
840               "g": ["tree", false],
841            }
842        }
843        */
844
845        let variant = Variant::try_new(&metadata, &value).unwrap();
846        let outer_object = variant.as_object().unwrap();
847
848        assert_eq!(outer_object.len(), 4);
849
850        assert_eq!(outer_object.field_name(0).unwrap(), "a");
851        assert_eq!(outer_object.field(0).unwrap(), Variant::from(false));
852
853        assert_eq!(outer_object.field_name(2).unwrap(), "c");
854
855        let inner_object_variant = outer_object.field(2).unwrap();
856        let inner_object = inner_object_variant.as_object().unwrap();
857
858        assert_eq!(inner_object.len(), 3);
859        assert_eq!(inner_object.field_name(0).unwrap(), "b");
860        assert_eq!(inner_object.field(0).unwrap(), Variant::from("a"));
861
862        let inner_iner_object_variant_c = inner_object.field(1).unwrap();
863        let inner_inner_object_c = inner_iner_object_variant_c.as_object().unwrap();
864        assert_eq!(inner_inner_object_c.len(), 1);
865        assert_eq!(inner_inner_object_c.field_name(0).unwrap(), "aa");
866        assert_eq!(inner_inner_object_c.field(0).unwrap(), Variant::from("bb"));
867
868        let inner_iner_object_variant_d = inner_object.field(2).unwrap();
869        let inner_inner_object_d = inner_iner_object_variant_d.as_object().unwrap();
870        assert_eq!(inner_inner_object_d.len(), 1);
871        assert_eq!(inner_inner_object_d.field_name(0).unwrap(), "cc");
872        assert_eq!(inner_inner_object_d.field(0).unwrap(), Variant::from("dd"));
873
874        assert_eq!(outer_object.field_name(1).unwrap(), "b");
875        assert_eq!(outer_object.field(1).unwrap(), Variant::from(true));
876
877        let out_object_variant_d = outer_object.field(3).unwrap();
878        let out_object_d = out_object_variant_d.as_object().unwrap();
879        assert_eq!(out_object_d.len(), 3);
880        assert_eq!("e", out_object_d.field_name(0).unwrap());
881        assert_eq!(Variant::from(1), out_object_d.field(0).unwrap());
882        assert_eq!("f", out_object_d.field_name(1).unwrap());
883
884        let first_inner_list_variant_f = out_object_d.field(1).unwrap();
885        let first_inner_list_f = first_inner_list_variant_f.as_list().unwrap();
886        assert_eq!(2, first_inner_list_f.len());
887        assert_eq!(Variant::from(1), first_inner_list_f.get(0).unwrap());
888        assert_eq!(Variant::from(true), first_inner_list_f.get(1).unwrap());
889
890        let second_inner_list_variant_g = out_object_d.field(2).unwrap();
891        let second_inner_list_g = second_inner_list_variant_g.as_list().unwrap();
892        assert_eq!(2, second_inner_list_g.len());
893        assert_eq!(Variant::from("tree"), second_inner_list_g.get(0).unwrap());
894        assert_eq!(Variant::from(false), second_inner_list_g.get(1).unwrap());
895    }
896
897    #[test]
898    fn test_object_without_unique_field_validation() {
899        let mut builder = VariantBuilder::new();
900
901        // Root object with duplicates
902        let mut obj = builder.new_object();
903        obj.insert("a", 1);
904        obj.insert("a", 2);
905        obj.finish();
906
907        // Deeply nested list structure with duplicates
908        let mut builder = VariantBuilder::new();
909        let mut outer_list = builder.new_list();
910        let mut inner_list = outer_list.new_list();
911        let mut nested_obj = inner_list.new_object();
912        nested_obj.insert("x", 1);
913        nested_obj.insert("x", 2);
914        nested_obj.new_list("x").with_value(3).finish();
915        nested_obj.new_object("x").with_field("y", 4).finish();
916        nested_obj.finish();
917        inner_list.finish();
918        outer_list.finish();
919
920        // Verify the nested object is built correctly -- the nested object "x" should have "won"
921        let (metadata, value) = builder.finish();
922        let variant = Variant::try_new(&metadata, &value).unwrap();
923        let outer_element = variant.get_list_element(0).unwrap();
924        let inner_element = outer_element.get_list_element(0).unwrap();
925        let outer_field = inner_element.get_object_field("x").unwrap();
926        let inner_field = outer_field.get_object_field("y").unwrap();
927        assert_eq!(inner_field, Variant::from(4));
928    }
929
930    #[test]
931    fn test_object_with_unique_field_validation() {
932        let mut builder = VariantBuilder::new().with_validate_unique_fields(true);
933
934        // Root-level object with duplicates
935        let result = builder
936            .new_object()
937            .with_field("a", 1)
938            .with_field("b", 2)
939            .try_with_field("a", 3);
940        assert_eq!(
941            result.unwrap_err().to_string(),
942            "Invalid argument error: Duplicate field name: a"
943        );
944
945        // Deeply nested list -> list -> object with duplicate
946        let mut outer_list = builder.new_list();
947        let mut inner_list = outer_list.new_list();
948        let mut object = inner_list.new_object().with_field("x", 1);
949        let nested_result = object.try_insert("x", 2);
950        assert_eq!(
951            nested_result.unwrap_err().to_string(),
952            "Invalid argument error: Duplicate field name: x"
953        );
954        let nested_result = object.try_new_list("x");
955        assert_eq!(
956            nested_result.unwrap_err().to_string(),
957            "Invalid argument error: Duplicate field name: x"
958        );
959
960        let nested_result = object.try_new_object("x");
961        assert_eq!(
962            nested_result.unwrap_err().to_string(),
963            "Invalid argument error: Duplicate field name: x"
964        );
965
966        drop(object);
967        inner_list.finish();
968        outer_list.finish();
969
970        // Valid object should succeed (fresh builder — one top-level value per VariantBuilder)
971        let mut builder = VariantBuilder::new().with_validate_unique_fields(true);
972        let mut list = builder.new_list();
973        let mut valid_obj = list.new_object();
974        valid_obj.insert("m", 1);
975        valid_obj.insert("n", 2);
976
977        valid_obj.finish();
978        list.finish();
979    }
980}