Skip to main content

parquet_variant/
builder.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::decoder::{OffsetSizeBytes, VariantBasicType, VariantPrimitiveType};
18use crate::{
19    ShortString, Variant, VariantDecimal4, VariantDecimal8, VariantDecimal16, VariantList,
20    VariantMetadata, VariantObject,
21};
22use arrow_schema::ArrowError;
23use chrono::Timelike;
24use uuid::Uuid;
25
26mod list;
27mod metadata;
28mod object;
29
30pub use list::*;
31pub use metadata::*;
32pub use object::*;
33
34pub(crate) const BASIC_TYPE_BITS: u8 = 2;
35pub(crate) const UNIX_EPOCH_DATE: chrono::NaiveDate =
36    chrono::NaiveDate::from_ymd_opt(1970, 1, 1).unwrap();
37
38fn primitive_header(primitive_type: VariantPrimitiveType) -> u8 {
39    (primitive_type as u8) << 2 | VariantBasicType::Primitive as u8
40}
41
42fn short_string_header(len: usize) -> u8 {
43    (len as u8) << 2 | VariantBasicType::ShortString as u8
44}
45
46pub(crate) fn int_size(v: usize) -> OffsetSizeBytes {
47    match v {
48        0..=0xFF => OffsetSizeBytes::One,
49        0x100..=0xFFFF => OffsetSizeBytes::Two,
50        0x10000..=0xFFFFFF => OffsetSizeBytes::Three,
51        _ => OffsetSizeBytes::Four,
52    }
53}
54
55const ONE_TOP_LEVEL_VALUE_MSG: &str =
56    "VariantBuilder already contains a top-level variant value; only one is allowed";
57const EMPTY_BUILDER_MSG: &str =
58    "VariantBuilder is empty; append a top-level value before calling finish()";
59
60// Error/panic construction is kept out-of-line and cold so the per-call guards on the
61// builder hot paths stay small enough to inline as a single predictable branch.
62#[cold]
63#[inline(never)]
64fn top_level_value_panic() -> ! {
65    panic!("{ONE_TOP_LEVEL_VALUE_MSG}");
66}
67
68#[cold]
69#[inline(never)]
70fn top_level_value_error() -> ArrowError {
71    ArrowError::InvalidArgumentError(ONE_TOP_LEVEL_VALUE_MSG.into())
72}
73
74#[cold]
75#[inline(never)]
76fn empty_builder_error() -> ArrowError {
77    ArrowError::InvalidArgumentError(EMPTY_BUILDER_MSG.into())
78}
79
80/// Wrapper around a `Vec<u8>` that provides methods for appending
81/// primitive values, variant types, and metadata.
82///
83/// This is used internally by the builders to construct the
84/// the `value` field for [`Variant`] values.
85///
86/// You can reuse an existing `Vec<u8>` by using the `from` impl
87#[derive(Debug, Default)]
88pub struct ValueBuilder(Vec<u8>);
89
90impl ValueBuilder {
91    /// Construct a ValueBuffer that will write to a new underlying `Vec`
92    pub fn new() -> Self {
93        Default::default()
94    }
95}
96
97/// Macro to generate the match statement for each append_variant, try_append_variant, and
98/// append_variant_bytes -- they each have slightly different handling for object and list handling.
99macro_rules! variant_append_value {
100    ($builder:expr, $value:expr, $object_pat:pat => $object_arm:expr, $list_pat:pat => $list_arm:expr) => {
101        match $value {
102            Variant::Null => $builder.append_null(),
103            Variant::BooleanTrue => $builder.append_bool(true),
104            Variant::BooleanFalse => $builder.append_bool(false),
105            Variant::Int8(v) => $builder.append_int8(v),
106            Variant::Int16(v) => $builder.append_int16(v),
107            Variant::Int32(v) => $builder.append_int32(v),
108            Variant::Int64(v) => $builder.append_int64(v),
109            Variant::Date(v) => $builder.append_date(v),
110            Variant::Time(v) => $builder.append_time_micros(v),
111            Variant::TimestampMicros(v) => $builder.append_timestamp_micros(v),
112            Variant::TimestampNtzMicros(v) => $builder.append_timestamp_ntz_micros(v),
113            Variant::TimestampNanos(v) => $builder.append_timestamp_nanos(v),
114            Variant::TimestampNtzNanos(v) => $builder.append_timestamp_ntz_nanos(v),
115            Variant::Decimal4(decimal4) => $builder.append_decimal4(decimal4),
116            Variant::Decimal8(decimal8) => $builder.append_decimal8(decimal8),
117            Variant::Decimal16(decimal16) => $builder.append_decimal16(decimal16),
118            Variant::Float(v) => $builder.append_float(v),
119            Variant::Double(v) => $builder.append_double(v),
120            Variant::Binary(v) => $builder.append_binary(v),
121            Variant::String(s) => $builder.append_string(s),
122            Variant::ShortString(s) => $builder.append_short_string(s),
123            Variant::Uuid(v) => $builder.append_uuid(v),
124            $object_pat => $object_arm,
125            $list_pat => $list_arm,
126        }
127    };
128}
129
130impl ValueBuilder {
131    fn append_u8(&mut self, term: u8) {
132        self.0.push(term);
133    }
134
135    fn append_slice(&mut self, other: &[u8]) {
136        self.0.extend_from_slice(other);
137    }
138
139    fn append_primitive_header(&mut self, primitive_type: VariantPrimitiveType) {
140        self.0.push(primitive_header(primitive_type));
141    }
142
143    /// Returns the underlying buffer, consuming self
144    pub fn into_inner(self) -> Vec<u8> {
145        self.0
146    }
147
148    pub(crate) fn inner_mut(&mut self) -> &mut Vec<u8> {
149        &mut self.0
150    }
151
152    // Variant types below
153
154    fn append_null(&mut self) {
155        self.append_primitive_header(VariantPrimitiveType::Null);
156    }
157
158    fn append_bool(&mut self, value: bool) {
159        let primitive_type = if value {
160            VariantPrimitiveType::BooleanTrue
161        } else {
162            VariantPrimitiveType::BooleanFalse
163        };
164        self.append_primitive_header(primitive_type);
165    }
166
167    fn append_int8(&mut self, value: i8) {
168        self.append_primitive_header(VariantPrimitiveType::Int8);
169        self.append_u8(value as u8);
170    }
171
172    fn append_int16(&mut self, value: i16) {
173        self.append_primitive_header(VariantPrimitiveType::Int16);
174        self.append_slice(&value.to_le_bytes());
175    }
176
177    fn append_int32(&mut self, value: i32) {
178        self.append_primitive_header(VariantPrimitiveType::Int32);
179        self.append_slice(&value.to_le_bytes());
180    }
181
182    fn append_int64(&mut self, value: i64) {
183        self.append_primitive_header(VariantPrimitiveType::Int64);
184        self.append_slice(&value.to_le_bytes());
185    }
186
187    fn append_float(&mut self, value: f32) {
188        self.append_primitive_header(VariantPrimitiveType::Float);
189        self.append_slice(&value.to_le_bytes());
190    }
191
192    fn append_double(&mut self, value: f64) {
193        self.append_primitive_header(VariantPrimitiveType::Double);
194        self.append_slice(&value.to_le_bytes());
195    }
196
197    fn append_date(&mut self, value: chrono::NaiveDate) {
198        self.append_primitive_header(VariantPrimitiveType::Date);
199        let days_since_epoch = value.signed_duration_since(UNIX_EPOCH_DATE).num_days() as i32;
200        self.append_slice(&days_since_epoch.to_le_bytes());
201    }
202
203    fn append_timestamp_micros(&mut self, value: chrono::DateTime<chrono::Utc>) {
204        self.append_primitive_header(VariantPrimitiveType::TimestampMicros);
205        let micros = value.timestamp_micros();
206        self.append_slice(&micros.to_le_bytes());
207    }
208
209    fn append_timestamp_ntz_micros(&mut self, value: chrono::NaiveDateTime) {
210        self.append_primitive_header(VariantPrimitiveType::TimestampNtzMicros);
211        let micros = value.and_utc().timestamp_micros();
212        self.append_slice(&micros.to_le_bytes());
213    }
214
215    fn append_time_micros(&mut self, value: chrono::NaiveTime) {
216        self.append_primitive_header(VariantPrimitiveType::Time);
217        let micros_from_midnight = value.num_seconds_from_midnight() as u64 * 1_000_000
218            + value.nanosecond() as u64 / 1_000;
219        self.append_slice(&micros_from_midnight.to_le_bytes());
220    }
221
222    fn append_timestamp_nanos(&mut self, value: chrono::DateTime<chrono::Utc>) {
223        self.append_primitive_header(VariantPrimitiveType::TimestampNanos);
224        let nanos = value.timestamp_nanos_opt().unwrap();
225        self.append_slice(&nanos.to_le_bytes());
226    }
227
228    fn append_timestamp_ntz_nanos(&mut self, value: chrono::NaiveDateTime) {
229        self.append_primitive_header(VariantPrimitiveType::TimestampNtzNanos);
230        let nanos = value.and_utc().timestamp_nanos_opt().unwrap();
231        self.append_slice(&nanos.to_le_bytes());
232    }
233
234    fn append_uuid(&mut self, value: Uuid) {
235        self.append_primitive_header(VariantPrimitiveType::Uuid);
236        self.append_slice(&value.into_bytes());
237    }
238
239    fn append_decimal4(&mut self, decimal4: VariantDecimal4) {
240        self.append_primitive_header(VariantPrimitiveType::Decimal4);
241        self.append_u8(decimal4.scale());
242        self.append_slice(&decimal4.integer().to_le_bytes());
243    }
244
245    fn append_decimal8(&mut self, decimal8: VariantDecimal8) {
246        self.append_primitive_header(VariantPrimitiveType::Decimal8);
247        self.append_u8(decimal8.scale());
248        self.append_slice(&decimal8.integer().to_le_bytes());
249    }
250
251    fn append_decimal16(&mut self, decimal16: VariantDecimal16) {
252        self.append_primitive_header(VariantPrimitiveType::Decimal16);
253        self.append_u8(decimal16.scale());
254        self.append_slice(&decimal16.integer().to_le_bytes());
255    }
256
257    fn append_binary(&mut self, value: &[u8]) {
258        self.append_primitive_header(VariantPrimitiveType::Binary);
259        self.append_slice(&(value.len() as u32).to_le_bytes());
260        self.append_slice(value);
261    }
262
263    fn append_short_string(&mut self, value: ShortString) {
264        let inner = value.0;
265        self.append_u8(short_string_header(inner.len()));
266        self.append_slice(inner.as_bytes());
267    }
268
269    fn append_string(&mut self, value: &str) {
270        self.append_primitive_header(VariantPrimitiveType::String);
271        self.append_slice(&(value.len() as u32).to_le_bytes());
272        self.append_slice(value.as_bytes());
273    }
274
275    fn append_object<S: BuilderSpecificState>(state: ParentState<'_, S>, obj: VariantObject) {
276        let mut object_builder = ObjectBuilder::new(state, false);
277        object_builder.extend(obj.iter());
278        object_builder.finish();
279    }
280
281    fn try_append_object<S: BuilderSpecificState>(
282        state: ParentState<'_, S>,
283        obj: VariantObject,
284    ) -> Result<(), ArrowError> {
285        let mut object_builder = ObjectBuilder::new(state, false);
286
287        for res in obj.iter_try() {
288            let (field_name, value) = res?;
289            object_builder.try_insert(field_name, value)?;
290        }
291
292        object_builder.finish();
293        Ok(())
294    }
295
296    fn append_list<S: BuilderSpecificState>(state: ParentState<'_, S>, list: VariantList) {
297        let mut list_builder = ListBuilder::new(state, false);
298        list_builder.extend(list.iter());
299        list_builder.finish();
300    }
301
302    fn try_append_list<S: BuilderSpecificState>(
303        state: ParentState<'_, S>,
304        list: VariantList,
305    ) -> Result<(), ArrowError> {
306        let mut list_builder = ListBuilder::new(state, false);
307        for res in list.iter_try() {
308            let value = res?;
309            list_builder.try_append_value(value)?;
310        }
311
312        list_builder.finish();
313
314        Ok(())
315    }
316
317    /// Returns the current size of the underlying buffer
318    pub fn offset(&self) -> usize {
319        self.0.len()
320    }
321
322    /// Appends a variant to the builder.
323    ///
324    /// # Panics
325    ///
326    /// This method will panic if the variant contains duplicate field names in objects
327    /// when validation is enabled. For a fallible version, use [`ValueBuilder::try_append_variant`]
328    pub fn append_variant<S: BuilderSpecificState>(
329        mut state: ParentState<'_, S>,
330        variant: Variant<'_, '_>,
331    ) {
332        variant_append_value!(
333            state.value_builder(),
334            variant,
335            Variant::Object(obj) => return Self::append_object(state, obj),
336            Variant::List(list) => return Self::append_list(state, list)
337        );
338        state.finish();
339    }
340
341    /// Tries to append a variant to the provided [`ParentState`] instance.
342    ///
343    /// The attempt fails if the variant contains duplicate field names in objects when validation
344    /// is enabled.
345    pub fn try_append_variant<S: BuilderSpecificState>(
346        mut state: ParentState<'_, S>,
347        variant: Variant<'_, '_>,
348    ) -> Result<(), ArrowError> {
349        variant_append_value!(
350            state.value_builder(),
351            variant,
352            Variant::Object(obj) => return Self::try_append_object(state, obj),
353            Variant::List(list) => return Self::try_append_list(state, list)
354        );
355        state.finish();
356        Ok(())
357    }
358
359    /// Appends a variant to the buffer by copying raw bytes when possible.
360    ///
361    /// For objects and lists, this directly copies their underlying byte representation instead of
362    /// performing a logical copy and without touching the metadata builder. For other variant
363    /// types, this falls back to the standard append behavior.
364    ///
365    /// The caller must ensure that the metadata dictionary is already built and correct for
366    /// any objects or lists being appended.
367    pub fn append_variant_bytes<S: BuilderSpecificState>(
368        mut state: ParentState<'_, S>,
369        variant: Variant<'_, '_>,
370    ) {
371        let builder = state.value_builder();
372        variant_append_value!(
373            builder,
374            variant,
375            Variant::Object(obj) => builder.append_slice(obj.value),
376            Variant::List(list) => builder.append_slice(list.value)
377        );
378        state.finish();
379    }
380}
381
382/// A trait for managing state specific to different builder types.
383pub trait BuilderSpecificState: std::fmt::Debug {
384    /// Called by [`ParentState::finish`] to apply any pending builder-specific changes.
385    ///
386    /// The provided implementation does nothing by default.
387    ///
388    /// Parameters:
389    /// - `metadata_builder`: The metadata builder that was used
390    /// - `value_builder`: The value builder that was used
391    fn finish(
392        &mut self,
393        _metadata_builder: &mut dyn MetadataBuilder,
394        _value_builder: &mut ValueBuilder,
395    ) {
396    }
397
398    /// Called by [`ParentState::drop`] to revert any changes that were eagerly applied, if
399    /// [`ParentState::finish`] was never invoked.
400    ///
401    /// The provided implementation does nothing by default.
402    ///
403    /// The base [`ParentState`] will handle rolling back the value and metadata builders,
404    /// but builder-specific state may need to revert its own changes.
405    fn rollback(&mut self) {}
406}
407
408/// Empty no-op implementation for top-level variant building
409impl BuilderSpecificState for () {}
410
411/// Tracks information needed to correctly finalize a nested builder.
412///
413/// A child builder has no effect on its parent unless/until its `finalize` method is called, at
414/// which point the child appends the new value to the parent. As a (desirable) side effect,
415/// creating a parent state instance captures mutable references to a subset of the parent's fields,
416/// rendering the parent object completely unusable until the parent state goes out of scope. This
417/// ensures that at most one child builder can exist at a time.
418///
419/// The redundancy in `value_builder` and `metadata_builder` is because all the references come from
420/// the parent, and we cannot "split" a mutable reference across two objects (parent state and the
421/// child builder that uses it). So everything has to be here.
422#[derive(Debug)]
423pub struct ParentState<'a, S: BuilderSpecificState> {
424    pub(crate) value_builder: &'a mut ValueBuilder,
425    pub(crate) saved_value_builder_offset: usize,
426    pub(crate) metadata_builder: &'a mut dyn MetadataBuilder,
427    pub(crate) saved_metadata_builder_dict_size: usize,
428    pub(crate) builder_state: S,
429    pub(crate) finished: bool,
430}
431
432impl<'a, S: BuilderSpecificState> ParentState<'a, S> {
433    /// Creates a new ParentState instance. The value and metadata builder
434    /// state is checkpointed and will roll back on drop, unless [`Self::finish`] is called. The
435    /// builder-specific state is governed by its own `finish` and `rollback` calls.
436    pub fn new(
437        value_builder: &'a mut ValueBuilder,
438        metadata_builder: &'a mut dyn MetadataBuilder,
439        builder_state: S,
440    ) -> Self {
441        Self {
442            saved_value_builder_offset: value_builder.offset(),
443            value_builder,
444            saved_metadata_builder_dict_size: metadata_builder.num_field_names(),
445            metadata_builder,
446            builder_state,
447            finished: false,
448        }
449    }
450
451    /// Marks the insertion as having succeeded and invokes
452    /// [`BuilderSpecificState::finish`]. Internal state will no longer roll back on drop.
453    pub fn finish(&mut self) {
454        self.builder_state
455            .finish(self.metadata_builder, self.value_builder);
456        self.finished = true
457    }
458
459    // Rolls back value and metadata builder changes and invokes [`BuilderSpecificState::rollback`].
460    fn rollback(&mut self) {
461        if self.finished {
462            return;
463        }
464
465        self.value_builder
466            .inner_mut()
467            .truncate(self.saved_value_builder_offset);
468        self.metadata_builder
469            .truncate_field_names(self.saved_metadata_builder_dict_size);
470        self.builder_state.rollback();
471    }
472
473    // Useful because e.g. `let b = self.value_builder;` fails compilation.
474    pub(crate) fn value_builder(&mut self) -> &mut ValueBuilder {
475        self.value_builder
476    }
477
478    // Useful because e.g. `let b = self.metadata_builder;` fails compilation.
479    pub(crate) fn metadata_builder(&mut self) -> &mut dyn MetadataBuilder {
480        self.metadata_builder
481    }
482}
483
484impl<'a> ParentState<'a, ()> {
485    /// Creates a new instance suitable for a top-level variant builder
486    /// (e.g. [`VariantBuilder`]). The value and metadata builder state is checkpointed and will
487    /// roll back on drop, unless [`Self::finish`] is called.
488    pub fn variant(
489        value_builder: &'a mut ValueBuilder,
490        metadata_builder: &'a mut dyn MetadataBuilder,
491    ) -> Self {
492        Self::new(value_builder, metadata_builder, ())
493    }
494}
495
496/// Automatically rolls back any unfinished `ParentState`.
497impl<S: BuilderSpecificState> Drop for ParentState<'_, S> {
498    fn drop(&mut self) {
499        self.rollback()
500    }
501}
502
503/// Top level builder for [`Variant`] values
504///
505/// `VariantBuilder` builds a single, self-contained [`Variant`] value -- useful
506/// for one-off values and unit tests. To build an array (column) of variants,
507/// one per input row, use [`VariantArrayBuilder`] from the
508/// `parquet-variant-compute` crate rather than a `VariantBuilder` per row.
509///
510/// [`VariantArrayBuilder`]: https://docs.rs/parquet-variant-compute/latest/parquet_variant_compute/struct.VariantArrayBuilder.html
511///
512/// # Example: create a Primitive Int8
513/// ```
514/// # use parquet_variant::{Variant, VariantBuilder};
515/// let mut builder = VariantBuilder::new();
516/// builder.append_value(Variant::Int8(42));
517/// // Finish the builder to get the metadata and value
518/// let (metadata, value) = builder.finish();
519/// // use the Variant API to verify the result
520/// let variant = Variant::try_new(&metadata, &value).unwrap();
521/// assert_eq!(variant, Variant::Int8(42));
522/// ```
523///
524/// # Example: Create a [`Variant::Object`]
525///
526/// This example shows how to create an object with two fields:
527/// ```json
528/// {
529///  "first_name": "Jiaying",
530///  "last_name": "Li"
531/// }
532/// ```
533///
534/// ```
535/// # use parquet_variant::{Variant, VariantBuilder};
536/// let mut builder = VariantBuilder::new();
537/// // Create an object builder that will write fields to the object
538/// let mut object_builder = builder.new_object();
539/// object_builder.insert("first_name", "Jiaying");
540/// object_builder.insert("last_name", "Li");
541/// object_builder.finish(); // call finish to finalize the object
542/// // Finish the builder to get the metadata and value
543/// let (metadata, value) = builder.finish();
544/// // use the Variant API to verify the result
545/// let variant = Variant::try_new(&metadata, &value).unwrap();
546/// let variant_object = variant.as_object().unwrap();
547/// assert_eq!(
548///   variant_object.get("first_name"),
549///   Some(Variant::from("Jiaying"))
550/// );
551/// assert_eq!(
552///   variant_object.get("last_name"),
553///   Some(Variant::from("Li"))
554/// );
555/// ```
556///
557///
558/// You can also use the [`ObjectBuilder::with_field`] to add fields to the
559/// object
560/// ```
561/// # use parquet_variant::{Variant, VariantBuilder};
562/// // build the same object as above
563/// let mut builder = VariantBuilder::new();
564/// builder.new_object()
565///   .with_field("first_name", "Jiaying")
566///   .with_field("last_name", "Li")
567///   .finish();
568/// let (metadata, value) = builder.finish();
569/// let variant = Variant::try_new(&metadata, &value).unwrap();
570/// let variant_object = variant.as_object().unwrap();
571/// assert_eq!(
572///   variant_object.get("first_name"),
573///   Some(Variant::from("Jiaying"))
574/// );
575/// assert_eq!(
576///   variant_object.get("last_name"),
577///   Some(Variant::from("Li"))
578/// );
579/// ```
580/// # Example: Create a [`Variant::List`] (an Array)
581///
582/// This example shows how to create an array of integers: `[1, 2, 3]`.
583/// ```
584///  # use parquet_variant::{Variant, VariantBuilder};
585///  let mut builder = VariantBuilder::new();
586///  // Create a builder that will write elements to the list
587///  let mut list_builder = builder.new_list();
588///  list_builder.append_value(1i8);
589///  list_builder.append_value(2i8);
590///  list_builder.append_value(3i8);
591/// // call finish to finalize the list
592///  list_builder.finish();
593/// // Finish the builder to get the metadata and value
594/// let (metadata, value) = builder.finish();
595/// // use the Variant API to verify the result
596/// let variant = Variant::try_new(&metadata, &value).unwrap();
597/// let variant_list = variant.as_list().unwrap();
598/// // Verify the list contents
599/// assert_eq!(variant_list.get(0).unwrap(), Variant::Int8(1));
600/// assert_eq!(variant_list.get(1).unwrap(), Variant::Int8(2));
601/// assert_eq!(variant_list.get(2).unwrap(), Variant::Int8(3));
602/// ```
603///
604/// You can also use the [`ListBuilder::with_value`] to append values to the
605/// list.
606/// ```
607///  # use parquet_variant::{Variant, VariantBuilder};
608///  let mut builder = VariantBuilder::new();
609///  builder.new_list()
610///      .with_value(1i8)
611///      .with_value(2i8)
612///      .with_value(3i8)
613///      .finish();
614/// let (metadata, value) = builder.finish();
615/// let variant = Variant::try_new(&metadata, &value).unwrap();
616/// let variant_list = variant.as_list().unwrap();
617/// assert_eq!(variant_list.get(0).unwrap(), Variant::Int8(1));
618/// assert_eq!(variant_list.get(1).unwrap(), Variant::Int8(2));
619/// assert_eq!(variant_list.get(2).unwrap(), Variant::Int8(3));
620/// ```
621///
622/// # Example: [`Variant::List`] of  [`Variant::Object`]s
623///
624/// This example shows how to create an list of objects:
625/// ```json
626/// [
627///   {
628///      "id": 1,
629///      "type": "Cauliflower"
630///   },
631///   {
632///      "id": 2,
633///      "type": "Beets"
634///   }
635/// ]
636/// ```
637/// ```
638/// use parquet_variant::{Variant, VariantBuilder};
639/// let mut builder = VariantBuilder::new();
640///
641/// // Create a builder that will write elements to the list
642/// let mut list_builder = builder.new_list();
643///
644/// {
645///     let mut object_builder = list_builder.new_object();
646///     object_builder.insert("id", 1);
647///     object_builder.insert("type", "Cauliflower");
648///     object_builder.finish();
649/// }
650///
651/// {
652///     let mut object_builder = list_builder.new_object();
653///     object_builder.insert("id", 2);
654///     object_builder.insert("type", "Beets");
655///     object_builder.finish();
656/// }
657///
658/// list_builder.finish();
659/// // Finish the builder to get the metadata and value
660/// let (metadata, value) = builder.finish();
661/// // use the Variant API to verify the result
662/// let variant = Variant::try_new(&metadata, &value).unwrap();
663/// let variant_list = variant.as_list().unwrap();
664///
665///
666/// let obj1_variant = variant_list.get(0).unwrap();
667/// let obj1 = obj1_variant.as_object().unwrap();
668/// assert_eq!(
669///     obj1.get("id"),
670///     Some(Variant::from(1))
671/// );
672/// assert_eq!(
673///     obj1.get("type"),
674///     Some(Variant::from("Cauliflower"))
675/// );
676///
677/// let obj2_variant = variant_list.get(1).unwrap();
678/// let obj2 = obj2_variant.as_object().unwrap();
679///
680/// assert_eq!(
681///     obj2.get("id"),
682///     Some(Variant::from(2))
683/// );
684/// assert_eq!(
685///     obj2.get("type"),
686///     Some(Variant::from("Beets"))
687/// );
688///
689/// ```
690/// # Example: Unique Field Validation
691///
692/// This example shows how enabling unique field validation will cause an error
693/// if the same field is inserted more than once.
694/// ```
695/// # use parquet_variant::VariantBuilder;
696/// #
697/// let mut builder = VariantBuilder::new().with_validate_unique_fields(true);
698///
699/// // When validation is enabled, try_with_field will return an error
700/// let result = builder
701///     .new_object()
702///     .with_field("a", 1)
703///     .try_with_field("a", 2);
704/// assert!(result.is_err());
705/// ```
706///
707/// # Example: Sorted dictionaries
708///
709/// This example shows how to create a [`VariantBuilder`] with a pre-sorted field dictionary
710/// to improve field access performance when reading [`Variant`] objects.
711///
712/// You can use [`VariantBuilder::with_field_names`] to add multiple field names at once:
713/// ```
714/// use parquet_variant::{Variant, VariantBuilder};
715/// let mut builder = VariantBuilder::new()
716///     .with_field_names(["age", "name", "score"].into_iter());
717///
718/// let mut obj = builder.new_object();
719/// obj.insert("name", "Alice");
720/// obj.insert("age", 30);
721/// obj.insert("score", 95.5);
722/// obj.finish();
723///
724/// let (metadata, value) = builder.finish();
725/// let variant = Variant::try_new(&metadata, &value).unwrap();
726/// ```
727///
728/// Alternatively, you can use [`VariantBuilder::add_field_name`] to add field names one by one:
729/// ```
730/// use parquet_variant::{Variant, VariantBuilder};
731/// let mut builder = VariantBuilder::new();
732/// builder.add_field_name("age"); // field id = 0
733/// builder.add_field_name("name"); // field id = 1
734/// builder.add_field_name("score"); // field id = 2
735///
736/// let mut obj = builder.new_object();
737/// obj.insert("name", "Bob"); // field id = 3
738/// obj.insert("age", 25);
739/// obj.insert("score", 88.0);
740/// obj.finish();
741///
742/// let (metadata, value) = builder.finish();
743/// let variant = Variant::try_new(&metadata, &value).unwrap();
744/// ```
745#[derive(Default, Debug)]
746pub struct VariantBuilder {
747    value_builder: ValueBuilder,
748    metadata_builder: WritableMetadataBuilder,
749    validate_unique_fields: bool,
750}
751
752impl VariantBuilder {
753    /// Create a new VariantBuilder with new underlying buffers
754    pub fn new() -> Self {
755        Self {
756            value_builder: ValueBuilder::new(),
757            metadata_builder: WritableMetadataBuilder::default(),
758            validate_unique_fields: false,
759        }
760    }
761
762    /// Create a new VariantBuilder with pre-existing [`VariantMetadata`].
763    pub fn with_metadata(mut self, metadata: VariantMetadata) -> Self {
764        self.metadata_builder.extend(metadata.iter());
765
766        self
767    }
768
769    /// Enables validation of unique field keys in nested objects.
770    ///
771    /// This setting is propagated to all [`ObjectBuilder`]s created through this [`VariantBuilder`]
772    /// (including via any [`ListBuilder`]), and causes [`ObjectBuilder::finish()`] to return
773    /// an error if duplicate keys were inserted.
774    pub fn with_validate_unique_fields(mut self, validate_unique_fields: bool) -> Self {
775        self.validate_unique_fields = validate_unique_fields;
776        self
777    }
778
779    /// This method pre-populates the field name directory in the Variant metadata with
780    /// the specific field names, in order.
781    ///
782    /// You can use this to pre-populate a [`VariantBuilder`] with a sorted dictionary if you
783    /// know the field names beforehand. Sorted dictionaries can accelerate field access when
784    /// reading [`Variant`]s.
785    pub fn with_field_names<'a>(mut self, field_names: impl IntoIterator<Item = &'a str>) -> Self {
786        self.metadata_builder.extend(field_names);
787
788        self
789    }
790
791    /// Builder-style API for appending a value to the list and returning self to enable method chaining.
792    ///
793    /// # Panics
794    ///
795    /// This method will panic if the variant contains duplicate field names in objects
796    /// when validation is enabled. For a fallible version, use [`ListBuilder::try_with_value`].
797    pub fn with_value<'m, 'd, T: Into<Variant<'m, 'd>>>(mut self, value: T) -> Self {
798        self.append_value(value);
799        self
800    }
801
802    /// Builder-style API for appending a value to the list and returns self for method chaining.
803    ///
804    /// This is the fallible version of [`ListBuilder::with_value`].
805    pub fn try_with_value<'m, 'd, T: Into<Variant<'m, 'd>>>(
806        mut self,
807        value: T,
808    ) -> Result<Self, ArrowError> {
809        self.try_append_value(value)?;
810        Ok(self)
811    }
812
813    /// This method reserves capacity for field names in the Variant metadata,
814    /// which can improve performance when you know the approximate number of unique field
815    /// names that will be used across all objects in the [`Variant`].
816    pub fn reserve(&mut self, capacity: usize) {
817        self.metadata_builder.field_names.reserve(capacity);
818    }
819
820    /// Adds a single field name to the field name directory in the Variant metadata.
821    ///
822    /// This method does the same thing as [`VariantBuilder::with_field_names`] but adds one field name at a time.
823    pub fn add_field_name(&mut self, field_name: &str) {
824        self.metadata_builder.upsert_field_name(field_name);
825    }
826
827    /// Returns true if a top-level variant value has already been written to this builder.
828    ///
829    /// A [`VariantBuilder`] holds exactly one top-level variant value. Any committed top-level
830    /// value leaves bytes in the value buffer; a child builder dropped without `finish()` has
831    /// its bytes rolled back by [`ParentState`], so the offset is a faithful indicator.
832    #[inline]
833    fn has_top_level_value(&self) -> bool {
834        self.value_builder.offset() != 0
835    }
836
837    #[inline]
838    fn ensure_no_top_level_value(&self) {
839        if self.has_top_level_value() {
840            top_level_value_panic();
841        }
842    }
843
844    #[inline]
845    fn check_no_top_level_value(&self) -> Result<(), ArrowError> {
846        if self.has_top_level_value() {
847            return Err(top_level_value_error());
848        }
849        Ok(())
850    }
851
852    /// Create an [`ListBuilder`] for creating [`Variant::List`] values.
853    ///
854    /// See the examples on [`VariantBuilder`] for usage.
855    ///
856    /// # Panics
857    ///
858    /// Panics if a top-level variant value has already been written to this builder. For a
859    /// fallible version, use [`VariantBuilder::try_new_list`].
860    pub fn new_list(&mut self) -> ListBuilder<'_, ()> {
861        self.try_new_list().unwrap()
862    }
863
864    /// Create an [`ListBuilder`] for creating [`Variant::List`] values.
865    ///
866    /// Returns an error if a top-level variant value has already been written to this builder.
867    pub fn try_new_list(&mut self) -> Result<ListBuilder<'_, ()>, ArrowError> {
868        self.check_no_top_level_value()?;
869        let parent_state =
870            ParentState::variant(&mut self.value_builder, &mut self.metadata_builder);
871        Ok(ListBuilder::new(parent_state, self.validate_unique_fields))
872    }
873
874    /// Create an [`ObjectBuilder`] for creating [`Variant::Object`] values.
875    ///
876    /// See the examples on [`VariantBuilder`] for usage.
877    ///
878    /// # Panics
879    ///
880    /// Panics if a top-level variant value has already been written to this builder. For a
881    /// fallible version, use [`VariantBuilder::try_new_object`].
882    pub fn new_object(&mut self) -> ObjectBuilder<'_, ()> {
883        self.try_new_object().unwrap()
884    }
885
886    /// Create an [`ObjectBuilder`] for creating [`Variant::Object`] values.
887    ///
888    /// Returns an error if a top-level variant value has already been written to this builder.
889    pub fn try_new_object(&mut self) -> Result<ObjectBuilder<'_, ()>, ArrowError> {
890        self.check_no_top_level_value()?;
891        let parent_state =
892            ParentState::variant(&mut self.value_builder, &mut self.metadata_builder);
893        Ok(ObjectBuilder::new(
894            parent_state,
895            self.validate_unique_fields,
896        ))
897    }
898
899    /// Append a value to the builder.
900    ///
901    /// # Panics
902    ///
903    /// Panics if a top-level variant value has already been written to this builder, or if the
904    /// variant contains duplicate field names in objects when validation is enabled. For a
905    /// fallible version, use [`VariantBuilder::try_append_value`].
906    ///
907    /// # Example
908    /// ```
909    /// # use parquet_variant::{Variant, VariantBuilder};
910    /// let mut builder = VariantBuilder::new();
911    /// // most primitive types can be appended directly as they implement `Into<Variant>`
912    /// builder.append_value(42i8);
913    /// ```
914    pub fn append_value<'m, 'd, T: Into<Variant<'m, 'd>>>(&mut self, value: T) {
915        self.ensure_no_top_level_value();
916        let state = ParentState::variant(&mut self.value_builder, &mut self.metadata_builder);
917        ValueBuilder::append_variant(state, value.into())
918    }
919
920    /// Append a value to the builder.
921    ///
922    /// Returns an error if a top-level variant value has already been written to this builder.
923    pub fn try_append_value<'m, 'd, T: Into<Variant<'m, 'd>>>(
924        &mut self,
925        value: T,
926    ) -> Result<(), ArrowError> {
927        self.check_no_top_level_value()?;
928        let state = ParentState::variant(&mut self.value_builder, &mut self.metadata_builder);
929        ValueBuilder::try_append_variant(state, value.into())
930    }
931
932    /// Appends a variant value to the builder by copying raw bytes when possible.
933    ///
934    /// For objects and lists, this directly copies their underlying byte representation instead of
935    /// performing a logical copy and without touching the metadata builder. For other variant
936    /// types, this falls back to the standard append behavior.
937    ///
938    /// The caller must ensure that the metadata dictionary entries are already built and correct for
939    /// any objects or lists being appended.
940    ///
941    /// # Panics
942    ///
943    /// Panics if a top-level variant value has already been written to this builder. For a
944    /// fallible version, use [`VariantBuilder::try_append_value_bytes`].
945    pub fn append_value_bytes<'m, 'd>(&mut self, value: impl Into<Variant<'m, 'd>>) {
946        self.try_append_value_bytes(value).unwrap()
947    }
948
949    /// Tries to append a variant value to the builder by copying raw bytes when possible.
950    ///
951    /// This is the fallible version of [`VariantBuilder::append_value_bytes`]. Returns an error
952    /// if a top-level variant value has already been written to this builder.
953    pub fn try_append_value_bytes<'m, 'd>(
954        &mut self,
955        value: impl Into<Variant<'m, 'd>>,
956    ) -> Result<(), ArrowError> {
957        self.check_no_top_level_value()?;
958        let state = ParentState::variant(&mut self.value_builder, &mut self.metadata_builder);
959        ValueBuilder::append_variant_bytes(state, value.into());
960        Ok(())
961    }
962
963    /// Finish the builder and return the metadata and value buffers.
964    ///
965    /// # Panics
966    ///
967    /// Panics if no top-level variant value has been appended. For a fallible version, use
968    /// [`VariantBuilder::try_finish`].
969    pub fn finish(self) -> (Vec<u8>, Vec<u8>) {
970        self.try_finish().expect(EMPTY_BUILDER_MSG)
971    }
972
973    /// Finish the builder and return the metadata and value buffers.
974    ///
975    /// Returns an error if no top-level variant value has been appended.
976    pub fn try_finish(mut self) -> Result<(Vec<u8>, Vec<u8>), ArrowError> {
977        if !self.has_top_level_value() {
978            return Err(empty_builder_error());
979        }
980        self.metadata_builder.finish();
981        Ok((
982            self.metadata_builder.into_inner(),
983            self.value_builder.into_inner(),
984        ))
985    }
986}
987
988/// Extends [`VariantBuilder`] to help building nested [`Variant`]s
989///
990/// Allows users to append values to a [`VariantBuilder`], [`ListBuilder`] or
991/// [`ObjectBuilder`]. using the same interface.
992pub trait VariantBuilderExt {
993    /// The builder specific state used by nested builders
994    type State<'a>: BuilderSpecificState + 'a
995    where
996        Self: 'a;
997
998    /// Appends a NULL value to this builder. The semantics depend on the implementation, but will
999    /// often translate to appending a [`Variant::Null`] value.
1000    fn append_null(&mut self);
1001
1002    /// Appends a new variant value to this builder. See e.g. [`VariantBuilder::append_value`].
1003    fn append_value<'m, 'v>(&mut self, value: impl Into<Variant<'m, 'v>>);
1004
1005    /// Creates a nested list builder. See e.g. [`VariantBuilder::new_list`]. Panics if the nested
1006    /// builder cannot be created, see e.g. [`ObjectBuilder::new_list`].
1007    fn new_list(&mut self) -> ListBuilder<'_, Self::State<'_>> {
1008        self.try_new_list().unwrap()
1009    }
1010
1011    /// Creates a nested object builder. See e.g. [`VariantBuilder::new_object`]. Panics if the
1012    /// nested builder cannot be created, see e.g. [`ObjectBuilder::new_object`].
1013    fn new_object(&mut self) -> ObjectBuilder<'_, Self::State<'_>> {
1014        self.try_new_object().unwrap()
1015    }
1016
1017    /// Creates a nested list builder. See e.g. [`VariantBuilder::new_list`]. Returns an error if
1018    /// the nested builder cannot be created, see e.g. [`ObjectBuilder::try_new_list`].
1019    fn try_new_list(&mut self) -> Result<ListBuilder<'_, Self::State<'_>>, ArrowError>;
1020
1021    /// Creates a nested object builder. See e.g. [`VariantBuilder::new_object`]. Returns an error
1022    /// if the nested builder cannot be created, see e.g. [`ObjectBuilder::try_new_object`].
1023    fn try_new_object(&mut self) -> Result<ObjectBuilder<'_, Self::State<'_>>, ArrowError>;
1024}
1025
1026impl VariantBuilderExt for VariantBuilder {
1027    type State<'a>
1028        = ()
1029    where
1030        Self: 'a;
1031
1032    /// Variant values cannot encode NULL, only [`Variant::Null`]. This is different from the column
1033    /// that holds variant values being NULL at some positions.
1034    fn append_null(&mut self) {
1035        self.append_value(Variant::Null);
1036    }
1037    fn append_value<'m, 'v>(&mut self, value: impl Into<Variant<'m, 'v>>) {
1038        self.append_value(value);
1039    }
1040
1041    fn try_new_list(&mut self) -> Result<ListBuilder<'_, Self::State<'_>>, ArrowError> {
1042        self.try_new_list()
1043    }
1044
1045    fn try_new_object(&mut self) -> Result<ObjectBuilder<'_, Self::State<'_>>, ArrowError> {
1046        self.try_new_object()
1047    }
1048}
1049
1050#[cfg(test)]
1051mod tests {
1052    use crate::{VariantMetadata, builder::metadata::ReadOnlyMetadataBuilder};
1053
1054    use super::*;
1055    #[test]
1056    fn test_simple_usage() {
1057        test_variant_roundtrip((), Variant::Null);
1058        test_variant_roundtrip(true, Variant::BooleanTrue);
1059        test_variant_roundtrip(false, Variant::BooleanFalse);
1060        test_variant_roundtrip(42i8, Variant::Int8(42));
1061        test_variant_roundtrip(1234i16, Variant::Int16(1234));
1062        test_variant_roundtrip(123456i32, Variant::Int32(123456));
1063        test_variant_roundtrip(123456789i64, Variant::Int64(123456789));
1064        test_variant_roundtrip(1.5f32, Variant::Float(1.5));
1065        test_variant_roundtrip(2.5f64, Variant::Double(2.5));
1066        test_variant_roundtrip("hello", Variant::ShortString(ShortString("hello")));
1067
1068        // Test long string (> 63 bytes)
1069        let long_string = "This is a very long string that exceeds the short string limit of 63 bytes and should be encoded as a regular string type instead of a short string";
1070        test_variant_roundtrip(long_string, Variant::String(long_string));
1071
1072        // Test binary data
1073        let binary_data = b"binary data";
1074        test_variant_roundtrip(
1075            binary_data.as_slice(),
1076            Variant::Binary(binary_data.as_slice()),
1077        );
1078    }
1079
1080    /// Helper function to test that a value can be built and reconstructed correctly
1081    fn test_variant_roundtrip<'m, 'd, T: Into<Variant<'m, 'd>>>(input: T, expected: Variant) {
1082        let mut builder = VariantBuilder::new();
1083        builder.append_value(input);
1084        let (metadata, value) = builder.finish();
1085        let variant = Variant::try_new(&metadata, &value).unwrap_or_else(|_| {
1086            panic!("Failed to create variant from metadata and value: {metadata:?}, {value:?}")
1087        });
1088        assert_eq!(variant, expected);
1089    }
1090
1091    #[test]
1092    fn test_try_finish_empty_builder_errors() {
1093        let builder = VariantBuilder::new();
1094        let err = builder.try_finish().unwrap_err();
1095        assert!(err.to_string().contains("empty"), "unexpected error: {err}");
1096    }
1097
1098    #[test]
1099    #[should_panic(expected = "empty")]
1100    fn test_finish_empty_builder_panics() {
1101        let builder = VariantBuilder::new();
1102        let _ = builder.finish();
1103    }
1104
1105    #[test]
1106    fn test_try_append_value_after_value_errors() {
1107        let mut builder = VariantBuilder::new();
1108        builder.append_value(1i32);
1109        let err = builder.try_append_value(2i32).unwrap_err();
1110        assert!(
1111            err.to_string().contains("only one is allowed"),
1112            "unexpected error: {err}"
1113        );
1114    }
1115
1116    #[test]
1117    fn test_try_append_value_bytes_after_value_errors() {
1118        let mut builder = VariantBuilder::new();
1119        builder.append_value(1i32);
1120        let err = builder.try_append_value_bytes(2i32).unwrap_err();
1121        assert!(
1122            err.to_string().contains("only one is allowed"),
1123            "unexpected error: {err}"
1124        );
1125    }
1126
1127    #[test]
1128    fn test_try_new_list_after_value_errors() {
1129        let mut builder = VariantBuilder::new();
1130        builder.append_value(1i32);
1131        let err = builder.try_new_list().expect_err("expected error");
1132        assert!(
1133            err.to_string().contains("only one is allowed"),
1134            "unexpected error: {err}"
1135        );
1136    }
1137
1138    #[test]
1139    fn test_try_new_object_after_value_errors() {
1140        let mut builder = VariantBuilder::new();
1141        builder.append_value(1i32);
1142        let err = builder.try_new_object().expect_err("expected error");
1143        assert!(
1144            err.to_string().contains("only one is allowed"),
1145            "unexpected error: {err}"
1146        );
1147    }
1148
1149    #[test]
1150    #[should_panic(expected = "only one is allowed")]
1151    fn test_append_value_after_value_panics() {
1152        let mut builder = VariantBuilder::new();
1153        builder.append_value(1i32);
1154        builder.append_value(2i32);
1155    }
1156
1157    #[test]
1158    #[should_panic(expected = "only one is allowed")]
1159    fn test_append_value_bytes_after_value_panics() {
1160        let mut builder = VariantBuilder::new();
1161        builder.append_value(1i32);
1162        builder.append_value_bytes(2i32);
1163    }
1164
1165    #[test]
1166    #[should_panic(expected = "only one is allowed")]
1167    fn test_new_list_after_value_panics() {
1168        let mut builder = VariantBuilder::new();
1169        builder.append_value(1i32);
1170        let _ = builder.new_list();
1171    }
1172
1173    #[test]
1174    #[should_panic(expected = "only one is allowed")]
1175    fn test_new_object_after_value_panics() {
1176        let mut builder = VariantBuilder::new();
1177        builder.append_value(1i32);
1178        let _ = builder.new_object();
1179    }
1180
1181    #[test]
1182    fn test_nested_object_with_lists() {
1183        /*
1184        {
1185            "door 1": {
1186                "items": ["apple", false ]
1187            }
1188        }
1189
1190        */
1191
1192        let mut builder = VariantBuilder::new();
1193        {
1194            let mut outer_object_builder = builder.new_object();
1195            {
1196                let mut inner_object_builder = outer_object_builder.new_object("door 1");
1197
1198                // create inner_object_list
1199                inner_object_builder
1200                    .new_list("items")
1201                    .with_value("apple")
1202                    .with_value(false)
1203                    .finish();
1204
1205                inner_object_builder.finish();
1206            }
1207
1208            outer_object_builder.finish();
1209        }
1210
1211        let (metadata, value) = builder.finish();
1212        let variant = Variant::try_new(&metadata, &value).unwrap();
1213        let outer_object = variant.as_object().unwrap();
1214
1215        assert_eq!(outer_object.len(), 1);
1216        assert_eq!(outer_object.field_name(0).unwrap(), "door 1");
1217
1218        let inner_object_variant = outer_object.field(0).unwrap();
1219        let inner_object = inner_object_variant.as_object().unwrap();
1220
1221        assert_eq!(inner_object.len(), 1);
1222        assert_eq!(inner_object.field_name(0).unwrap(), "items");
1223
1224        let items_variant = inner_object.field(0).unwrap();
1225        let items_list = items_variant.as_list().unwrap();
1226
1227        assert_eq!(items_list.len(), 2);
1228        assert_eq!(items_list.get(0).unwrap(), Variant::from("apple"));
1229        assert_eq!(items_list.get(1).unwrap(), Variant::from(false));
1230    }
1231
1232    #[test]
1233    fn test_sorted_dictionary() {
1234        // check if variant metadatabuilders are equivalent from different ways of constructing them
1235        let mut variant1 = VariantBuilder::new().with_field_names(["b", "c", "d"]);
1236
1237        let mut variant2 = {
1238            let mut builder = VariantBuilder::new();
1239
1240            builder.add_field_name("b");
1241            builder.add_field_name("c");
1242            builder.add_field_name("d");
1243
1244            builder
1245        };
1246
1247        assert_eq!(
1248            variant1.metadata_builder.field_names,
1249            variant2.metadata_builder.field_names
1250        );
1251
1252        // check metadata builders say it's sorted
1253        assert!(variant1.metadata_builder.is_sorted);
1254        assert!(variant2.metadata_builder.is_sorted);
1255
1256        {
1257            // test the bad case and break the sort order
1258            variant2.add_field_name("a");
1259            assert!(!variant2.metadata_builder.is_sorted);
1260
1261            // per the spec, a variant must have a top-level value; try_finish() rejects empty
1262            let err = variant2.try_finish().unwrap_err();
1263            assert!(err.to_string().contains("empty"), "unexpected error: {err}");
1264        }
1265
1266        // write out variant1 and make sure the sorted flag is properly encoded
1267        variant1.append_value(false);
1268
1269        let (m, v) = variant1.finish();
1270        let res = Variant::try_new(&m, &v);
1271        assert!(res.is_ok());
1272
1273        let header = VariantMetadata::try_new(&m).unwrap();
1274        assert!(header.is_sorted());
1275    }
1276
1277    #[test]
1278    fn test_object_sorted_dictionary() {
1279        // predefine the list of field names
1280        let mut variant1 = VariantBuilder::new().with_field_names(["a", "b", "c"]);
1281        let mut obj = variant1.new_object();
1282
1283        obj.insert("c", true);
1284        obj.insert("a", false);
1285        obj.insert("b", ());
1286
1287        // verify the field ids are correctly
1288        let field_ids_by_insert_order = obj.fields.iter().map(|(&id, _)| id).collect::<Vec<_>>();
1289        assert_eq!(field_ids_by_insert_order, vec![2, 0, 1]);
1290
1291        // add a field name that wasn't pre-defined but doesn't break the sort order
1292        obj.insert("d", 2);
1293        obj.finish();
1294
1295        let (metadata, value) = variant1.finish();
1296        let variant = Variant::try_new(&metadata, &value).unwrap();
1297
1298        let metadata = VariantMetadata::try_new(&metadata).unwrap();
1299        assert!(metadata.is_sorted());
1300
1301        // verify object is sorted by field name order
1302        let object = variant.as_object().unwrap();
1303        let field_names = object
1304            .iter()
1305            .map(|(field_name, _)| field_name)
1306            .collect::<Vec<_>>();
1307
1308        assert_eq!(field_names, vec!["a", "b", "c", "d"]);
1309    }
1310
1311    #[test]
1312    fn test_object_not_sorted_dictionary() {
1313        // predefine the list of field names
1314        let mut variant1 = VariantBuilder::new().with_field_names(["b", "c", "d"]);
1315        let mut obj = variant1.new_object();
1316
1317        obj.insert("c", true);
1318        obj.insert("d", false);
1319        obj.insert("b", ());
1320
1321        // verify the field ids are correctly
1322        let field_ids_by_insert_order = obj.fields.iter().map(|(&id, _)| id).collect::<Vec<_>>();
1323        assert_eq!(field_ids_by_insert_order, vec![1, 2, 0]);
1324
1325        // add a field name that wasn't pre-defined but breaks the sort order
1326        obj.insert("a", 2);
1327        obj.finish();
1328
1329        let (metadata, value) = variant1.finish();
1330        let variant = Variant::try_new(&metadata, &value).unwrap();
1331
1332        let metadata = VariantMetadata::try_new(&metadata).unwrap();
1333        assert!(!metadata.is_sorted());
1334
1335        // verify object field names are sorted by field name order
1336        let object = variant.as_object().unwrap();
1337        let field_names = object
1338            .iter()
1339            .map(|(field_name, _)| field_name)
1340            .collect::<Vec<_>>();
1341
1342        assert_eq!(field_names, vec!["a", "b", "c", "d"]);
1343    }
1344
1345    #[test]
1346    fn test_building_sorted_dictionary() {
1347        let mut builder = VariantBuilder::new();
1348        assert!(!builder.metadata_builder.is_sorted);
1349        assert_eq!(builder.metadata_builder.num_field_names(), 0);
1350
1351        builder.add_field_name("a");
1352
1353        assert!(builder.metadata_builder.is_sorted);
1354        assert_eq!(builder.metadata_builder.num_field_names(), 1);
1355
1356        let builder = builder.with_field_names(["b", "c", "d"]);
1357
1358        assert!(builder.metadata_builder.is_sorted);
1359        assert_eq!(builder.metadata_builder.num_field_names(), 4);
1360
1361        let builder = builder.with_field_names(["z", "y"]);
1362        assert!(!builder.metadata_builder.is_sorted);
1363        assert_eq!(builder.metadata_builder.num_field_names(), 6);
1364    }
1365
1366    #[test]
1367    fn test_variant_builder_to_list_builder_no_finish() {
1368        // Create a list builder but never finish it
1369        let mut builder = VariantBuilder::new();
1370        let mut list_builder = builder.new_list();
1371        list_builder.append_value("hi");
1372        drop(list_builder);
1373
1374        builder.append_value(42i8);
1375
1376        // The original builder should be unchanged
1377        let (metadata, value) = builder.finish();
1378        let metadata = VariantMetadata::try_new(&metadata).unwrap();
1379        assert!(metadata.is_empty());
1380
1381        let variant = Variant::try_new_with_metadata(metadata, &value).unwrap();
1382        assert_eq!(variant, Variant::Int8(42));
1383    }
1384
1385    #[test]
1386    fn test_variant_builder_to_object_builder_no_finish() {
1387        // Create an object builder but never finish it
1388        let mut builder = VariantBuilder::new();
1389        let mut object_builder = builder.new_object();
1390        object_builder.insert("name", "unknown");
1391        drop(object_builder);
1392
1393        builder.append_value(42i8);
1394
1395        // The original builder should be unchanged
1396        let (metadata, value) = builder.finish();
1397        let metadata = VariantMetadata::try_new(&metadata).unwrap();
1398        assert!(metadata.is_empty()); // rolled back
1399
1400        let variant = Variant::try_new_with_metadata(metadata, &value).unwrap();
1401        assert_eq!(variant, Variant::Int8(42));
1402    }
1403
1404    #[test]
1405    fn test_list_builder_to_list_builder_inner_no_finish() {
1406        let mut builder = VariantBuilder::new();
1407        let mut list_builder = builder.new_list();
1408        list_builder.append_value(1i8);
1409
1410        // Create a nested list builder but never finish it
1411        let mut nested_list_builder = list_builder.new_list();
1412        nested_list_builder.append_value("hi");
1413        drop(nested_list_builder);
1414
1415        list_builder.append_value(2i8);
1416
1417        // The parent list should only contain the original values
1418        list_builder.finish();
1419        let (metadata, value) = builder.finish();
1420        let metadata = VariantMetadata::try_new(&metadata).unwrap();
1421        assert!(metadata.is_empty());
1422
1423        let variant = Variant::try_new_with_metadata(metadata, &value).unwrap();
1424        let list = variant.as_list().unwrap();
1425        assert_eq!(list.len(), 2);
1426        assert_eq!(list.get(0).unwrap(), Variant::Int8(1));
1427        assert_eq!(list.get(1).unwrap(), Variant::Int8(2));
1428    }
1429
1430    #[test]
1431    fn test_list_builder_to_list_builder_outer_no_finish() {
1432        let mut builder = VariantBuilder::new();
1433        let mut list_builder = builder.new_list();
1434        list_builder.append_value(1i8);
1435
1436        // Create a nested list builder and finish it
1437        let mut nested_list_builder = list_builder.new_list();
1438        nested_list_builder.append_value("hi");
1439        nested_list_builder.finish();
1440
1441        // Drop the outer list builder without finishing it
1442        drop(list_builder);
1443
1444        builder.append_value(2i8);
1445
1446        // Only the second attempt should appear in the final variant
1447        let (metadata, value) = builder.finish();
1448        let metadata = VariantMetadata::try_new(&metadata).unwrap();
1449        assert!(metadata.is_empty());
1450
1451        let variant = Variant::try_new_with_metadata(metadata, &value).unwrap();
1452        assert_eq!(variant, Variant::Int8(2));
1453    }
1454
1455    #[test]
1456    fn test_list_builder_to_object_builder_inner_no_finish() {
1457        let mut builder = VariantBuilder::new();
1458        let mut list_builder = builder.new_list();
1459        list_builder.append_value(1i8);
1460
1461        // Create a nested object builder but never finish it
1462        let mut nested_object_builder = list_builder.new_object();
1463        nested_object_builder.insert("name", "unknown");
1464        drop(nested_object_builder);
1465
1466        list_builder.append_value(2i8);
1467
1468        // The parent list should only contain the original values
1469        list_builder.finish();
1470        let (metadata, value) = builder.finish();
1471        let metadata = VariantMetadata::try_new(&metadata).unwrap();
1472        assert!(metadata.is_empty());
1473
1474        let variant = Variant::try_new_with_metadata(metadata, &value).unwrap();
1475        let list = variant.as_list().unwrap();
1476        assert_eq!(list.len(), 2);
1477        assert_eq!(list.get(0).unwrap(), Variant::Int8(1));
1478        assert_eq!(list.get(1).unwrap(), Variant::Int8(2));
1479    }
1480
1481    #[test]
1482    fn test_list_builder_to_object_builder_outer_no_finish() {
1483        let mut builder = VariantBuilder::new();
1484        let mut list_builder = builder.new_list();
1485        list_builder.append_value(1i8);
1486
1487        // Create a nested object builder and finish it
1488        let mut nested_object_builder = list_builder.new_object();
1489        nested_object_builder.insert("name", "unknown");
1490        nested_object_builder.finish();
1491
1492        // Drop the outer list builder without finishing it
1493        drop(list_builder);
1494
1495        builder.append_value(2i8);
1496
1497        // Only the second attempt should appear in the final variant
1498        let (metadata, value) = builder.finish();
1499        let metadata = VariantMetadata::try_new(&metadata).unwrap();
1500        assert!(metadata.is_empty()); // rolled back
1501
1502        let variant = Variant::try_new_with_metadata(metadata, &value).unwrap();
1503        assert_eq!(variant, Variant::Int8(2));
1504    }
1505
1506    #[test]
1507    fn test_object_builder_to_list_builder_inner_no_finish() {
1508        let mut builder = VariantBuilder::new();
1509        let mut object_builder = builder.new_object();
1510        object_builder.insert("first", 1i8);
1511
1512        // Create a nested list builder but never finish it
1513        let mut nested_list_builder = object_builder.new_list("nested");
1514        nested_list_builder.append_value("hi");
1515        drop(nested_list_builder);
1516
1517        object_builder.insert("second", 2i8);
1518
1519        // The parent object should only contain the original fields
1520        object_builder.finish();
1521        let (metadata, value) = builder.finish();
1522
1523        let metadata = VariantMetadata::try_new(&metadata).unwrap();
1524        assert_eq!(metadata.len(), 2);
1525        assert_eq!(&metadata[0], "first");
1526        assert_eq!(&metadata[1], "second");
1527
1528        let variant = Variant::try_new_with_metadata(metadata, &value).unwrap();
1529        let obj = variant.as_object().unwrap();
1530        assert_eq!(obj.len(), 2);
1531        assert_eq!(obj.get("first"), Some(Variant::Int8(1)));
1532        assert_eq!(obj.get("second"), Some(Variant::Int8(2)));
1533    }
1534
1535    #[test]
1536    fn test_object_builder_to_list_builder_outer_no_finish() {
1537        let mut builder = VariantBuilder::new();
1538        let mut object_builder = builder.new_object();
1539        object_builder.insert("first", 1i8);
1540
1541        // Create a nested list builder and finish it
1542        let mut nested_list_builder = object_builder.new_list("nested");
1543        nested_list_builder.append_value("hi");
1544        nested_list_builder.finish();
1545
1546        // Drop the outer object builder without finishing it
1547        drop(object_builder);
1548
1549        builder.append_value(2i8);
1550
1551        // Only the second attempt should appear in the final variant
1552        let (metadata, value) = builder.finish();
1553        let metadata = VariantMetadata::try_new(&metadata).unwrap();
1554        assert!(metadata.is_empty()); // rolled back
1555
1556        let variant = Variant::try_new_with_metadata(metadata, &value).unwrap();
1557        assert_eq!(variant, Variant::Int8(2));
1558    }
1559
1560    #[test]
1561    fn test_object_builder_to_object_builder_inner_no_finish() {
1562        let mut builder = VariantBuilder::new();
1563        let mut object_builder = builder.new_object();
1564        object_builder.insert("first", 1i8);
1565
1566        // Create a nested object builder but never finish it
1567        let mut nested_object_builder = object_builder.new_object("nested");
1568        nested_object_builder.insert("name", "unknown");
1569        drop(nested_object_builder);
1570
1571        object_builder.insert("second", 2i8);
1572
1573        // The parent object should only contain the original fields
1574        object_builder.finish();
1575        let (metadata, value) = builder.finish();
1576
1577        let metadata = VariantMetadata::try_new(&metadata).unwrap();
1578        assert_eq!(metadata.len(), 2); // the fields of nested_object_builder has been rolled back
1579        assert_eq!(&metadata[0], "first");
1580        assert_eq!(&metadata[1], "second");
1581
1582        let variant = Variant::try_new_with_metadata(metadata, &value).unwrap();
1583        let obj = variant.as_object().unwrap();
1584        assert_eq!(obj.len(), 2);
1585        assert_eq!(obj.get("first"), Some(Variant::Int8(1)));
1586        assert_eq!(obj.get("second"), Some(Variant::Int8(2)));
1587    }
1588
1589    #[test]
1590    fn test_object_builder_to_object_builder_outer_no_finish() {
1591        let mut builder = VariantBuilder::new();
1592        let mut object_builder = builder.new_object();
1593        object_builder.insert("first", 1i8);
1594
1595        // Create a nested object builder and finish it
1596        let mut nested_object_builder = object_builder.new_object("nested");
1597        nested_object_builder.insert("name", "unknown");
1598        nested_object_builder.finish();
1599
1600        // Drop the outer object builder without finishing it
1601        drop(object_builder);
1602
1603        builder.append_value(2i8);
1604
1605        // Only the second attempt should appear in the final variant
1606        let (metadata, value) = builder.finish();
1607        let metadata = VariantMetadata::try_new(&metadata).unwrap();
1608        assert_eq!(metadata.len(), 0); // rolled back
1609
1610        let variant = Variant::try_new_with_metadata(metadata, &value).unwrap();
1611        assert_eq!(variant, Variant::Int8(2));
1612    }
1613
1614    // Make sure that we can correctly build deeply nested objects even when some of the nested
1615    // builders don't finish.
1616    #[test]
1617    fn test_append_list_object_list_object() {
1618        // An infinite counter
1619        let mut counter = 0..;
1620        let mut take = move |i| (&mut counter).take(i).collect::<Vec<_>>();
1621        let mut builder = VariantBuilder::new();
1622        let skip = 5;
1623        {
1624            let mut list = builder.new_list();
1625            for i in take(4) {
1626                let mut object = list.new_object();
1627                for i in take(4) {
1628                    let field_name = format!("field{i}");
1629                    let mut list = object.new_list(&field_name);
1630                    for i in take(3) {
1631                        let mut object = list.new_object();
1632                        for i in take(3) {
1633                            if i % skip != 0 {
1634                                object.insert(&format!("field{i}"), i);
1635                            }
1636                        }
1637                        if i % skip != 0 {
1638                            object.finish();
1639                        }
1640                    }
1641                    if i % skip != 0 {
1642                        list.finish();
1643                    }
1644                }
1645                if i % skip != 0 {
1646                    object.finish();
1647                }
1648            }
1649            list.finish();
1650        }
1651        let (metadata, value) = builder.finish();
1652        let v1 = Variant::try_new(&metadata, &value).unwrap();
1653
1654        let (metadata, value) = VariantBuilder::new().with_value(v1.clone()).finish();
1655        let v2 = Variant::try_new(&metadata, &value).unwrap();
1656
1657        assert_eq!(format!("{v1:?}"), format!("{v2:?}"));
1658    }
1659
1660    #[test]
1661    fn test_append_variant_bytes_round_trip() {
1662        // Create a complex variant with the normal builder
1663        let mut builder = VariantBuilder::new();
1664        {
1665            let mut obj = builder.new_object();
1666            obj.insert("name", "Alice");
1667            obj.insert("age", 30i32);
1668            {
1669                let mut scores_list = obj.new_list("scores");
1670                scores_list.append_value(95i32);
1671                scores_list.append_value(87i32);
1672                scores_list.append_value(92i32);
1673                scores_list.finish();
1674            }
1675            {
1676                let mut address = obj.new_object("address");
1677                address.insert("street", "123 Main St");
1678                address.insert("city", "Anytown");
1679                address.finish();
1680            }
1681            obj.finish();
1682        }
1683        let (metadata, value1) = builder.finish();
1684        let variant1 = Variant::try_new(&metadata, &value1).unwrap();
1685
1686        // Copy using the new bytes API
1687        let metadata = VariantMetadata::new(&metadata);
1688        let mut metadata = ReadOnlyMetadataBuilder::new(&metadata);
1689        let mut builder2 = ValueBuilder::new();
1690        let state = ParentState::variant(&mut builder2, &mut metadata);
1691        ValueBuilder::append_variant_bytes(state, variant1);
1692        let value2 = builder2.into_inner();
1693
1694        // The bytes should be identical, we merely copied them across.
1695        assert_eq!(value1, value2);
1696    }
1697
1698    #[test]
1699    fn test_object_insert_bytes_subset() {
1700        // Create an original object, making sure to inject the field names we'll add later.
1701        let mut builder = VariantBuilder::new().with_field_names(["new_field", "another_field"]);
1702        {
1703            let mut obj = builder.new_object();
1704            obj.insert("field1", "value1");
1705            obj.insert("field2", 42i32);
1706            obj.insert("field3", true);
1707            obj.insert("field4", "value4");
1708            obj.finish();
1709        }
1710        let (metadata1, value1) = builder.finish();
1711        let original_variant = Variant::try_new(&metadata1, &value1).unwrap();
1712        let original_obj = original_variant.as_object().unwrap();
1713
1714        // Create a new object copying subset of fields interleaved with new ones
1715        let metadata2 = VariantMetadata::new(&metadata1);
1716        let mut metadata2 = ReadOnlyMetadataBuilder::new(&metadata2);
1717        let mut builder2 = ValueBuilder::new();
1718        let state = ParentState::variant(&mut builder2, &mut metadata2);
1719        {
1720            let mut obj = ObjectBuilder::new(state, true);
1721
1722            // Copy field1 using bytes API
1723            obj.insert_bytes("field1", original_obj.get("field1").unwrap());
1724
1725            // Add new field
1726            obj.insert("new_field", "new_value");
1727
1728            // Copy field3 using bytes API
1729            obj.insert_bytes("field3", original_obj.get("field3").unwrap());
1730
1731            // Add another new field
1732            obj.insert("another_field", 99i32);
1733
1734            // Copy field2 using bytes API
1735            obj.insert_bytes("field2", original_obj.get("field2").unwrap());
1736
1737            obj.finish();
1738        }
1739        let value2 = builder2.into_inner();
1740        let result_variant = Variant::try_new(&metadata1, &value2).unwrap();
1741        let result_obj = result_variant.as_object().unwrap();
1742
1743        // Verify the object contains expected fields
1744        assert_eq!(result_obj.len(), 5);
1745        assert_eq!(
1746            result_obj.get("field1").unwrap().as_string().unwrap(),
1747            "value1"
1748        );
1749        assert_eq!(result_obj.get("field2").unwrap().as_int32().unwrap(), 42);
1750        assert!(result_obj.get("field3").unwrap().as_boolean().unwrap());
1751        assert_eq!(
1752            result_obj.get("new_field").unwrap().as_string().unwrap(),
1753            "new_value"
1754        );
1755        assert_eq!(
1756            result_obj.get("another_field").unwrap().as_int32().unwrap(),
1757            99
1758        );
1759    }
1760
1761    #[test]
1762    fn test_complex_nested_filtering_injection() {
1763        // Create a complex nested structure: object -> list -> objects. Make sure to pre-register
1764        // the extra field names we'll need later while manipulating variant bytes.
1765        let mut builder = VariantBuilder::new().with_field_names([
1766            "active_count",
1767            "active_users",
1768            "computed_score",
1769            "processed_at",
1770            "status",
1771        ]);
1772
1773        {
1774            let mut root_obj = builder.new_object();
1775            root_obj.insert("metadata", "original");
1776
1777            {
1778                let mut users_list = root_obj.new_list("users");
1779
1780                // User 1
1781                {
1782                    let mut user1 = users_list.new_object();
1783                    user1.insert("id", 1i32);
1784                    user1.insert("name", "Alice");
1785                    user1.insert("active", true);
1786                    user1.finish();
1787                }
1788
1789                // User 2
1790                {
1791                    let mut user2 = users_list.new_object();
1792                    user2.insert("id", 2i32);
1793                    user2.insert("name", "Bob");
1794                    user2.insert("active", false);
1795                    user2.finish();
1796                }
1797
1798                // User 3
1799                {
1800                    let mut user3 = users_list.new_object();
1801                    user3.insert("id", 3i32);
1802                    user3.insert("name", "Charlie");
1803                    user3.insert("active", true);
1804                    user3.finish();
1805                }
1806
1807                users_list.finish();
1808            }
1809
1810            root_obj.insert("total_count", 3i32);
1811            root_obj.finish();
1812        }
1813        let (metadata1, value1) = builder.finish();
1814        let original_variant = Variant::try_new(&metadata1, &value1).unwrap();
1815        let original_obj = original_variant.as_object().unwrap();
1816        let original_users = original_obj.get("users").unwrap();
1817        let original_users = original_users.as_list().unwrap();
1818
1819        // Create filtered/modified version: only copy active users and inject new data
1820        let metadata2 = VariantMetadata::new(&metadata1);
1821        let mut metadata2 = ReadOnlyMetadataBuilder::new(&metadata2);
1822        let mut builder2 = ValueBuilder::new();
1823        let state = ParentState::variant(&mut builder2, &mut metadata2);
1824        {
1825            let mut root_obj = ObjectBuilder::new(state, true);
1826
1827            // Copy metadata using bytes API
1828            root_obj.insert_bytes("metadata", original_obj.get("metadata").unwrap());
1829
1830            // Add processing timestamp
1831            root_obj.insert("processed_at", "2024-01-01T00:00:00Z");
1832
1833            {
1834                let mut filtered_users = root_obj.new_list("active_users");
1835
1836                // Copy only active users and inject additional data
1837                for i in 0..original_users.len() {
1838                    let user = original_users.get(i).unwrap();
1839                    let user = user.as_object().unwrap();
1840                    if user.get("active").unwrap().as_boolean().unwrap() {
1841                        {
1842                            let mut new_user = filtered_users.new_object();
1843
1844                            // Copy existing fields using bytes API
1845                            new_user.insert_bytes("id", user.get("id").unwrap());
1846                            new_user.insert_bytes("name", user.get("name").unwrap());
1847
1848                            // Inject new computed field
1849                            let user_id = user.get("id").unwrap().as_int32().unwrap();
1850                            new_user.insert("computed_score", user_id * 10);
1851
1852                            // Add status transformation (don't copy the 'active' field)
1853                            new_user.insert("status", "verified");
1854
1855                            new_user.finish();
1856                        }
1857                    }
1858                }
1859
1860                // Inject a completely new user
1861                {
1862                    let mut new_user = filtered_users.new_object();
1863                    new_user.insert("id", 999i32);
1864                    new_user.insert("name", "System User");
1865                    new_user.insert("computed_score", 0i32);
1866                    new_user.insert("status", "system");
1867                    new_user.finish();
1868                }
1869
1870                filtered_users.finish();
1871            }
1872
1873            // Update count
1874            root_obj.insert("active_count", 3i32); // 2 active + 1 new
1875
1876            root_obj.finish();
1877        }
1878        let value2 = builder2.into_inner();
1879        let result_variant = Variant::try_new(&metadata1, &value2).unwrap();
1880        let result_obj = result_variant.as_object().unwrap();
1881
1882        // Verify the filtered/modified structure
1883        assert_eq!(
1884            result_obj.get("metadata").unwrap().as_string().unwrap(),
1885            "original"
1886        );
1887        assert_eq!(
1888            result_obj.get("processed_at").unwrap().as_string().unwrap(),
1889            "2024-01-01T00:00:00Z"
1890        );
1891        assert_eq!(
1892            result_obj.get("active_count").unwrap().as_int32().unwrap(),
1893            3
1894        );
1895
1896        let active_users = result_obj.get("active_users").unwrap();
1897        let active_users = active_users.as_list().unwrap();
1898        assert_eq!(active_users.len(), 3);
1899
1900        // Verify Alice (id=1, was active)
1901        let alice = active_users.get(0).unwrap();
1902        let alice = alice.as_object().unwrap();
1903        assert_eq!(alice.get("id").unwrap().as_int32().unwrap(), 1);
1904        assert_eq!(alice.get("name").unwrap().as_string().unwrap(), "Alice");
1905        assert_eq!(alice.get("computed_score").unwrap().as_int32().unwrap(), 10);
1906        assert_eq!(
1907            alice.get("status").unwrap().as_string().unwrap(),
1908            "verified"
1909        );
1910        assert!(alice.get("active").is_none()); // This field was not copied
1911
1912        // Verify Charlie (id=3, was active) - Bob (id=2) was not active so not included
1913        let charlie = active_users.get(1).unwrap();
1914        let charlie = charlie.as_object().unwrap();
1915        assert_eq!(charlie.get("id").unwrap().as_int32().unwrap(), 3);
1916        assert_eq!(charlie.get("name").unwrap().as_string().unwrap(), "Charlie");
1917        assert_eq!(
1918            charlie.get("computed_score").unwrap().as_int32().unwrap(),
1919            30
1920        );
1921        assert_eq!(
1922            charlie.get("status").unwrap().as_string().unwrap(),
1923            "verified"
1924        );
1925
1926        // Verify injected system user
1927        let system_user = active_users.get(2).unwrap();
1928        let system_user = system_user.as_object().unwrap();
1929        assert_eq!(system_user.get("id").unwrap().as_int32().unwrap(), 999);
1930        assert_eq!(
1931            system_user.get("name").unwrap().as_string().unwrap(),
1932            "System User"
1933        );
1934        assert_eq!(
1935            system_user
1936                .get("computed_score")
1937                .unwrap()
1938                .as_int32()
1939                .unwrap(),
1940            0
1941        );
1942        assert_eq!(
1943            system_user.get("status").unwrap().as_string().unwrap(),
1944            "system"
1945        );
1946    }
1947}