lance_encoding/
format.rs

1// SPDX-License-Identifier: Apache-2.0
2// SPDX-FileCopyrightText: Copyright The Lance Authors
3
4/// Protobuf definitions for encodings
5///
6/// These are the messages used for describing encoding in the 2.0 format
7pub mod pb {
8    #![allow(clippy::all)]
9    #![allow(non_upper_case_globals)]
10    #![allow(non_camel_case_types)]
11    #![allow(non_snake_case)]
12    #![allow(unused)]
13    #![allow(improper_ctypes)]
14    #![allow(clippy::upper_case_acronyms)]
15    #![allow(clippy::use_self)]
16    include!(concat!(env!("OUT_DIR"), "/lance.encodings.rs"));
17}
18
19/// Protobuf definitions for encodings21
20///
21/// These are the messages used for describing encoding in the 2.1 format
22/// and any newer formats.
23pub mod pb21 {
24    #![allow(clippy::all)]
25    #![allow(non_upper_case_globals)]
26    #![allow(non_camel_case_types)]
27    #![allow(non_snake_case)]
28    #![allow(unused)]
29    #![allow(improper_ctypes)]
30    #![allow(clippy::upper_case_acronyms)]
31    #![allow(clippy::use_self)]
32    include!(concat!(env!("OUT_DIR"), "/lance.encodings21.rs"));
33}
34
35use pb::{
36    array_encoding::ArrayEncoding as ArrayEncodingEnum,
37    buffer::BufferType,
38    nullable::{AllNull, NoNull, Nullability, SomeNull},
39    ArrayEncoding, Binary, Bitpacked, BitpackedForNonNeg, Block, Dictionary, FixedSizeBinary,
40    FixedSizeList, Flat, Fsst, InlineBitpacking, Nullable, OutOfLineBitpacking, PackedStruct,
41    PackedStructFixedWidthMiniBlock, Rle, Variable,
42};
43
44use crate::{encodings::physical::block::CompressionConfig, repdef::DefinitionInterpretation};
45
46use self::pb::Constant;
47use lance_core::Result;
48
49// Utility functions for creating complex protobuf objects
50pub struct ProtobufUtils {}
51
52impl ProtobufUtils {
53    pub fn constant(value: Vec<u8>) -> ArrayEncoding {
54        ArrayEncoding {
55            array_encoding: Some(ArrayEncodingEnum::Constant(Constant {
56                value: value.into(),
57            })),
58        }
59    }
60
61    pub fn basic_all_null_encoding() -> ArrayEncoding {
62        ArrayEncoding {
63            array_encoding: Some(ArrayEncodingEnum::Nullable(Box::new(Nullable {
64                nullability: Some(Nullability::AllNulls(AllNull {})),
65            }))),
66        }
67    }
68
69    pub fn basic_some_null_encoding(
70        validity: ArrayEncoding,
71        values: ArrayEncoding,
72    ) -> ArrayEncoding {
73        ArrayEncoding {
74            array_encoding: Some(ArrayEncodingEnum::Nullable(Box::new(Nullable {
75                nullability: Some(Nullability::SomeNulls(Box::new(SomeNull {
76                    validity: Some(Box::new(validity)),
77                    values: Some(Box::new(values)),
78                }))),
79            }))),
80        }
81    }
82
83    pub fn basic_no_null_encoding(values: ArrayEncoding) -> ArrayEncoding {
84        ArrayEncoding {
85            array_encoding: Some(ArrayEncodingEnum::Nullable(Box::new(Nullable {
86                nullability: Some(Nullability::NoNulls(Box::new(NoNull {
87                    values: Some(Box::new(values)),
88                }))),
89            }))),
90        }
91    }
92
93    pub fn block(scheme: &str) -> ArrayEncoding {
94        ArrayEncoding {
95            array_encoding: Some(ArrayEncodingEnum::Block(Block {
96                scheme: scheme.to_string(),
97            })),
98        }
99    }
100
101    pub fn flat_encoding(
102        bits_per_value: u64,
103        buffer_index: u32,
104        compression: Option<CompressionConfig>,
105    ) -> ArrayEncoding {
106        ArrayEncoding {
107            array_encoding: Some(ArrayEncodingEnum::Flat(Flat {
108                bits_per_value,
109                buffer: Some(pb::Buffer {
110                    buffer_index,
111                    buffer_type: BufferType::Page as i32,
112                }),
113                compression: compression.map(|compression_config| pb::Compression {
114                    scheme: compression_config.scheme.to_string(),
115                    level: compression_config.level,
116                }),
117            })),
118        }
119    }
120
121    pub fn fsl_encoding(dimension: u64, items: ArrayEncoding, has_validity: bool) -> ArrayEncoding {
122        ArrayEncoding {
123            array_encoding: Some(ArrayEncodingEnum::FixedSizeList(Box::new(FixedSizeList {
124                dimension: dimension.try_into().unwrap(),
125                items: Some(Box::new(items)),
126                has_validity,
127            }))),
128        }
129    }
130
131    pub fn bitpacked_encoding(
132        compressed_bits_per_value: u64,
133        uncompressed_bits_per_value: u64,
134        buffer_index: u32,
135        signed: bool,
136    ) -> ArrayEncoding {
137        ArrayEncoding {
138            array_encoding: Some(ArrayEncodingEnum::Bitpacked(Bitpacked {
139                compressed_bits_per_value,
140                buffer: Some(pb::Buffer {
141                    buffer_index,
142                    buffer_type: BufferType::Page as i32,
143                }),
144                uncompressed_bits_per_value,
145                signed,
146            })),
147        }
148    }
149
150    pub fn bitpacked_for_non_neg_encoding(
151        compressed_bits_per_value: u64,
152        uncompressed_bits_per_value: u64,
153        buffer_index: u32,
154    ) -> ArrayEncoding {
155        ArrayEncoding {
156            array_encoding: Some(ArrayEncodingEnum::BitpackedForNonNeg(BitpackedForNonNeg {
157                compressed_bits_per_value,
158                buffer: Some(pb::Buffer {
159                    buffer_index,
160                    buffer_type: BufferType::Page as i32,
161                }),
162                uncompressed_bits_per_value,
163            })),
164        }
165    }
166    pub fn inline_bitpacking(uncompressed_bits_per_value: u64) -> ArrayEncoding {
167        ArrayEncoding {
168            array_encoding: Some(ArrayEncodingEnum::InlineBitpacking(InlineBitpacking {
169                uncompressed_bits_per_value,
170            })),
171        }
172    }
173    pub fn out_of_line_bitpacking(
174        uncompressed_bits_per_value: u64,
175        compressed_bits_per_value: u64,
176    ) -> ArrayEncoding {
177        ArrayEncoding {
178            array_encoding: Some(ArrayEncodingEnum::OutOfLineBitpacking(
179                OutOfLineBitpacking {
180                    uncompressed_bits_per_value,
181                    compressed_bits_per_value,
182                },
183            )),
184        }
185    }
186
187    pub fn variable(bits_per_offset: u8) -> ArrayEncoding {
188        ArrayEncoding {
189            array_encoding: Some(ArrayEncodingEnum::Variable(Variable {
190                bits_per_offset: bits_per_offset as u32,
191            })),
192        }
193    }
194
195    // Construct a `FsstMiniBlock` ArrayEncoding, the inner `binary_mini_block` encoding is actually
196    // not used and `FsstMiniBlockDecompressor` constructs a `binary_mini_block` in a `hard-coded` fashion.
197    // This can be an optimization later.
198    pub fn fsst(data: ArrayEncoding, symbol_table: Vec<u8>) -> ArrayEncoding {
199        ArrayEncoding {
200            array_encoding: Some(ArrayEncodingEnum::Fsst(Box::new(Fsst {
201                binary: Some(Box::new(data)),
202                symbol_table: symbol_table.into(),
203            }))),
204        }
205    }
206
207    pub fn rle(bits_per_value: u64) -> ArrayEncoding {
208        ArrayEncoding {
209            array_encoding: Some(ArrayEncodingEnum::Rle(Rle { bits_per_value })),
210        }
211    }
212
213    pub fn byte_stream_split(bits_per_value: u64) -> ArrayEncoding {
214        ArrayEncoding {
215            array_encoding: Some(ArrayEncodingEnum::ByteStreamSplit(pb::ByteStreamSplit {
216                bits_per_value,
217            })),
218        }
219    }
220
221    pub fn general_mini_block(
222        inner: ArrayEncoding,
223        compression: CompressionConfig,
224    ) -> ArrayEncoding {
225        ArrayEncoding {
226            array_encoding: Some(ArrayEncodingEnum::GeneralMiniBlock(Box::new(
227                pb::GeneralMiniBlock {
228                    inner: Some(Box::new(inner)),
229                    compression: Some(pb::Compression {
230                        scheme: compression.scheme.to_string(),
231                        level: compression.level,
232                    }),
233                },
234            ))),
235        }
236    }
237
238    pub fn packed_struct(
239        child_encodings: Vec<ArrayEncoding>,
240        packed_buffer_index: u32,
241    ) -> ArrayEncoding {
242        ArrayEncoding {
243            array_encoding: Some(ArrayEncodingEnum::PackedStruct(PackedStruct {
244                inner: child_encodings,
245                buffer: Some(pb::Buffer {
246                    buffer_index: packed_buffer_index,
247                    buffer_type: BufferType::Page as i32,
248                }),
249            })),
250        }
251    }
252
253    pub fn packed_struct_fixed_width_mini_block(
254        data: ArrayEncoding,
255        bits_per_values: Vec<u32>,
256    ) -> ArrayEncoding {
257        ArrayEncoding {
258            array_encoding: Some(ArrayEncodingEnum::PackedStructFixedWidthMiniBlock(
259                Box::new(PackedStructFixedWidthMiniBlock {
260                    flat: Some(Box::new(data)),
261                    bits_per_values,
262                }),
263            )),
264        }
265    }
266
267    pub fn binary(
268        indices_encoding: ArrayEncoding,
269        bytes_encoding: ArrayEncoding,
270        null_adjustment: u64,
271    ) -> ArrayEncoding {
272        ArrayEncoding {
273            array_encoding: Some(ArrayEncodingEnum::Binary(Box::new(Binary {
274                bytes: Some(Box::new(bytes_encoding)),
275                indices: Some(Box::new(indices_encoding)),
276                null_adjustment,
277            }))),
278        }
279    }
280
281    pub fn dict_encoding(
282        indices: ArrayEncoding,
283        items: ArrayEncoding,
284        num_items: u32,
285    ) -> ArrayEncoding {
286        ArrayEncoding {
287            array_encoding: Some(ArrayEncodingEnum::Dictionary(Box::new(Dictionary {
288                indices: Some(Box::new(indices)),
289                items: Some(Box::new(items)),
290                num_dictionary_items: num_items,
291            }))),
292        }
293    }
294
295    pub fn fixed_size_binary(data: ArrayEncoding, byte_width: u32) -> ArrayEncoding {
296        ArrayEncoding {
297            array_encoding: Some(ArrayEncodingEnum::FixedSizeBinary(Box::new(
298                FixedSizeBinary {
299                    bytes: Some(Box::new(data)),
300                    byte_width,
301                },
302            ))),
303        }
304    }
305}
306
307macro_rules! impl_common_protobuf_utils {
308    ($module:ident, $struct_name:ident) => {
309        pub struct $struct_name {}
310
311        impl $struct_name {
312            pub fn flat(
313                bits_per_value: u64,
314                values_compression: Option<crate::format::$module::BufferCompression>,
315            ) -> crate::format::$module::CompressiveEncoding {
316                crate::format::$module::CompressiveEncoding {
317                    compression: Some(
318                        crate::format::$module::compressive_encoding::Compression::Flat(
319                            crate::format::$module::Flat {
320                                bits_per_value,
321                                data: values_compression,
322                            },
323                        ),
324                    ),
325                }
326            }
327
328            pub fn constant(
329                value: Option<bytes::Bytes>,
330            ) -> crate::format::$module::CompressiveEncoding {
331                crate::format::$module::CompressiveEncoding {
332                    compression: Some(
333                        crate::format::$module::compressive_encoding::Compression::Constant(
334                            crate::format::$module::Constant { value },
335                        ),
336                    ),
337                }
338            }
339
340            pub fn fsl(
341                items_per_value: u64,
342                has_validity: bool,
343                values: crate::format::$module::CompressiveEncoding,
344            ) -> crate::format::$module::CompressiveEncoding {
345                crate::format::$module::CompressiveEncoding {
346                    compression: Some(
347                        crate::format::$module::compressive_encoding::Compression::FixedSizeList(
348                            Box::new(crate::format::$module::FixedSizeList {
349                                items_per_value,
350                                has_validity,
351                                values: Some(Box::new(values)),
352                            }),
353                        ),
354                    ),
355                }
356            }
357
358            pub fn variable(
359                offsets_desc: crate::format::$module::CompressiveEncoding,
360                values_compression: Option<crate::format::$module::BufferCompression>,
361            ) -> crate::format::$module::CompressiveEncoding {
362                crate::format::$module::CompressiveEncoding {
363                    compression: Some(
364                        crate::format::$module::compressive_encoding::Compression::Variable(
365                            Box::new(crate::format::$module::Variable {
366                                offsets: Some(Box::new(offsets_desc)),
367                                values: values_compression,
368                            }),
369                        ),
370                    ),
371                }
372            }
373
374            pub fn inline_bitpacking(
375                uncompressed_bits_per_value: u64,
376                values_compression: Option<crate::format::$module::BufferCompression>,
377            ) -> crate::format::$module::CompressiveEncoding {
378                crate::format::$module::CompressiveEncoding {
379                    compression: Some(
380                        crate::format::$module::compressive_encoding::Compression::InlineBitpacking(
381                            crate::format::$module::InlineBitpacking {
382                                uncompressed_bits_per_value,
383                                values: values_compression,
384                            },
385                        ),
386                    ),
387                }
388            }
389
390            pub fn out_of_line_bitpacking(
391                uncompressed_bits_per_value: u64,
392                values: crate::format::$module::CompressiveEncoding,
393            ) -> crate::format::$module::CompressiveEncoding {
394                crate::format::$module::CompressiveEncoding {
395                    compression: Some(
396                        crate::format::$module::compressive_encoding::Compression::OutOfLineBitpacking(
397                            Box::new(crate::format::$module::OutOfLineBitpacking {
398                                uncompressed_bits_per_value,
399                                values: Some(Box::new(values)),
400                            }),
401                        ),
402                    ),
403                }
404            }
405
406            pub fn buffer_compression(
407                compression: CompressionConfig,
408            ) -> Result<crate::format::$module::BufferCompression> {
409                Ok(crate::format::$module::BufferCompression {
410                    scheme: crate::format::$module::CompressionScheme::try_from(
411                        compression.scheme,
412                    )? as i32,
413                    level: compression.level,
414                })
415            }
416
417            pub fn wrapped(
418                compression: CompressionConfig,
419                values: crate::format::$module::CompressiveEncoding,
420            ) -> Result<crate::format::$module::CompressiveEncoding> {
421                Ok(crate::format::$module::CompressiveEncoding {
422                    compression: Some(
423                        crate::format::$module::compressive_encoding::Compression::General(
424                            Box::new(crate::format::$module::General {
425                                compression: Some(Self::buffer_compression(compression)?),
426                                values: Some(Box::new(values)),
427                            }),
428                        ),
429                    ),
430                })
431            }
432
433            pub fn rle(
434                values: crate::format::$module::CompressiveEncoding,
435                run_lengths: crate::format::$module::CompressiveEncoding,
436            ) -> crate::format::$module::CompressiveEncoding {
437                crate::format::$module::CompressiveEncoding {
438                    compression: Some(
439                        crate::format::$module::compressive_encoding::Compression::Rle(Box::new(
440                            crate::format::$module::Rle {
441                                values: Some(Box::new(values)),
442                                run_lengths: Some(Box::new(run_lengths)),
443                            },
444                        )),
445                    ),
446                }
447            }
448
449            pub fn byte_stream_split(
450                values: crate::format::$module::CompressiveEncoding,
451            ) -> crate::format::$module::CompressiveEncoding {
452                crate::format::$module::CompressiveEncoding {
453                    compression: Some(
454                        crate::format::$module::compressive_encoding::Compression::ByteStreamSplit(
455                            Box::new(crate::format::$module::ByteStreamSplit {
456                                values: Some(Box::new(values)),
457                            }),
458                        ),
459                    ),
460                }
461            }
462
463            pub fn fsst(
464                data: crate::format::$module::CompressiveEncoding,
465                symbol_table: Vec<u8>,
466            ) -> crate::format::$module::CompressiveEncoding {
467                crate::format::$module::CompressiveEncoding {
468                    compression: Some(
469                        crate::format::$module::compressive_encoding::Compression::Fsst(
470                            Box::new(crate::format::$module::Fsst {
471                                symbol_table: symbol_table.into(),
472                                values: Some(Box::new(data)),
473                            }),
474                        ),
475                    ),
476                }
477            }
478
479            fn def_inter_to_repdef_layer(def: DefinitionInterpretation) -> i32 {
480                match def {
481                    DefinitionInterpretation::AllValidItem => {
482                        crate::format::$module::RepDefLayer::RepdefAllValidItem as i32
483                    }
484                    DefinitionInterpretation::AllValidList => {
485                        crate::format::$module::RepDefLayer::RepdefAllValidList as i32
486                    }
487                    DefinitionInterpretation::NullableItem => {
488                        crate::format::$module::RepDefLayer::RepdefNullableItem as i32
489                    }
490                    DefinitionInterpretation::NullableList => {
491                        crate::format::$module::RepDefLayer::RepdefNullableList as i32
492                    }
493                    DefinitionInterpretation::EmptyableList => {
494                        crate::format::$module::RepDefLayer::RepdefEmptyableList as i32
495                    }
496                    DefinitionInterpretation::NullableAndEmptyableList => {
497                        crate::format::$module::RepDefLayer::RepdefNullAndEmptyList as i32
498                    }
499                }
500            }
501
502            pub fn repdef_layer_to_def_interp(
503                layer: i32,
504            ) -> DefinitionInterpretation {
505                let layer = crate::format::$module::RepDefLayer::try_from(layer).unwrap();
506                match layer {
507                    crate::format::$module::RepDefLayer::RepdefAllValidItem => {
508                        DefinitionInterpretation::AllValidItem
509                    }
510                    crate::format::$module::RepDefLayer::RepdefAllValidList => {
511                        DefinitionInterpretation::AllValidList
512                    }
513                    crate::format::$module::RepDefLayer::RepdefNullableItem => {
514                        DefinitionInterpretation::NullableItem
515                    }
516                    crate::format::$module::RepDefLayer::RepdefNullableList => {
517                        DefinitionInterpretation::NullableList
518                    }
519                    crate::format::$module::RepDefLayer::RepdefEmptyableList => {
520                        DefinitionInterpretation::EmptyableList
521                    }
522                    crate::format::$module::RepDefLayer::RepdefNullAndEmptyList => {
523                        DefinitionInterpretation::NullableAndEmptyableList
524                    }
525                    crate::format::$module::RepDefLayer::RepdefUnspecified => {
526                        panic!("Unspecified repdef layer")
527                    }
528                }
529            }
530
531            #[allow(clippy::too_many_arguments)]
532            pub fn miniblock_layout(
533                rep_encoding: Option<crate::format::$module::CompressiveEncoding>,
534                def_encoding: Option<crate::format::$module::CompressiveEncoding>,
535                value_encoding: crate::format::$module::CompressiveEncoding,
536                repetition_index_depth: u32,
537                num_buffers: u64,
538                dictionary_encoding: Option<(
539                    crate::format::$module::CompressiveEncoding,
540                    u64,
541                )>,
542                def_meaning: &[DefinitionInterpretation],
543                num_items: u64,
544            ) -> crate::format::$module::PageLayout {
545                assert!(!def_meaning.is_empty());
546                let (dictionary, num_dictionary_items) = dictionary_encoding
547                    .map(|(d, i)| (Some(d), i))
548                    .unwrap_or((None, 0));
549                crate::format::$module::PageLayout {
550                    layout: Some(
551                        crate::format::$module::page_layout::Layout::MiniBlockLayout(
552                            crate::format::$module::MiniBlockLayout {
553                                def_compression: def_encoding,
554                                rep_compression: rep_encoding,
555                                value_compression: Some(value_encoding),
556                                repetition_index_depth,
557                                num_buffers,
558                                dictionary,
559                                num_dictionary_items,
560                                layers: def_meaning
561                                    .iter()
562                                    .map(|&def| Self::def_inter_to_repdef_layer(def))
563                                    .collect(),
564                                num_items,
565                            },
566                        ),
567                    ),
568                }
569            }
570
571            fn full_zip_layout(
572                bits_rep: u8,
573                bits_def: u8,
574                details: crate::format::$module::full_zip_layout::Details,
575                value_encoding: crate::format::$module::CompressiveEncoding,
576                def_meaning: &[DefinitionInterpretation],
577                num_items: u32,
578                num_visible_items: u32,
579            ) -> crate::format::$module::PageLayout {
580                crate::format::$module::PageLayout {
581                    layout: Some(
582                        crate::format::$module::page_layout::Layout::FullZipLayout(
583                            crate::format::$module::FullZipLayout {
584                                bits_rep: bits_rep as u32,
585                                bits_def: bits_def as u32,
586                                details: Some(details),
587                                value_compression: Some(value_encoding),
588                                num_items,
589                                num_visible_items,
590                                layers: def_meaning
591                                    .iter()
592                                    .map(|&def| Self::def_inter_to_repdef_layer(def))
593                                    .collect(),
594                            },
595                        ),
596                    ),
597                }
598            }
599
600            pub fn fixed_full_zip_layout(
601                bits_rep: u8,
602                bits_def: u8,
603                bits_per_value: u32,
604                value_encoding: crate::format::$module::CompressiveEncoding,
605                def_meaning: &[DefinitionInterpretation],
606                num_items: u32,
607                num_visible_items: u32,
608            ) -> crate::format::$module::PageLayout {
609                Self::full_zip_layout(
610                    bits_rep,
611                    bits_def,
612                    crate::format::$module::full_zip_layout::Details::BitsPerValue(
613                        bits_per_value,
614                    ),
615                    value_encoding,
616                    def_meaning,
617                    num_items,
618                    num_visible_items,
619                )
620            }
621
622            pub fn variable_full_zip_layout(
623                bits_rep: u8,
624                bits_def: u8,
625                bits_per_offset: u32,
626                value_encoding: crate::format::$module::CompressiveEncoding,
627                def_meaning: &[DefinitionInterpretation],
628                num_items: u32,
629                num_visible_items: u32,
630            ) -> crate::format::$module::PageLayout {
631                Self::full_zip_layout(
632                    bits_rep,
633                    bits_def,
634                    crate::format::$module::full_zip_layout::Details::BitsPerOffset(
635                        bits_per_offset,
636                    ),
637                    value_encoding,
638                    def_meaning,
639                    num_items,
640                    num_visible_items,
641                )
642            }
643
644            pub fn blob_layout(
645                inner_layout: crate::format::$module::PageLayout,
646                def_meaning: &[DefinitionInterpretation],
647            ) -> crate::format::$module::PageLayout {
648                crate::format::$module::PageLayout {
649                    layout: Some(
650                        crate::format::$module::page_layout::Layout::BlobLayout(Box::new(
651                            crate::format::$module::BlobLayout {
652                                inner_layout: Some(Box::new(inner_layout)),
653                                layers: def_meaning
654                                    .iter()
655                                    .map(|&def| Self::def_inter_to_repdef_layer(def))
656                                    .collect(),
657                            },
658                        )),
659                    ),
660                }
661            }
662
663            pub fn all_null_layout(
664                def_meaning: &[DefinitionInterpretation],
665            ) -> crate::format::$module::PageLayout {
666                crate::format::$module::PageLayout {
667                    layout: Some(
668                        crate::format::$module::page_layout::Layout::AllNullLayout(
669                            crate::format::$module::AllNullLayout {
670                                layers: def_meaning
671                                    .iter()
672                                    .map(|&def| Self::def_inter_to_repdef_layer(def))
673                                    .collect(),
674                            },
675                        ),
676                    ),
677                }
678            }
679
680            pub fn simple_all_null_layout() -> crate::format::$module::PageLayout {
681                Self::all_null_layout(&[DefinitionInterpretation::NullableItem])
682            }
683        }
684    };
685}
686
687impl_common_protobuf_utils!(pb21, ProtobufUtils21);
688
689impl ProtobufUtils21 {
690    pub fn packed_struct(
691        values: crate::format::pb21::CompressiveEncoding,
692        bits_per_values: Vec<u64>,
693    ) -> crate::format::pb21::CompressiveEncoding {
694        crate::format::pb21::CompressiveEncoding {
695            compression: Some(
696                crate::format::pb21::compressive_encoding::Compression::PackedStruct(Box::new(
697                    crate::format::pb21::PackedStruct {
698                        bits_per_value: bits_per_values,
699                        values: Some(Box::new(values)),
700                    },
701                )),
702            ),
703        }
704    }
705
706    pub fn packed_struct_variable(
707        fields: Vec<crate::format::pb21::variable_packed_struct::FieldEncoding>,
708    ) -> crate::format::pb21::CompressiveEncoding {
709        crate::format::pb21::CompressiveEncoding {
710            compression: Some(
711                crate::format::pb21::compressive_encoding::Compression::VariablePackedStruct(
712                    crate::format::pb21::VariablePackedStruct { fields },
713                ),
714            ),
715        }
716    }
717
718    pub fn packed_struct_field_fixed(
719        value_encoding: crate::format::pb21::CompressiveEncoding,
720        bits_per_value: u64,
721    ) -> crate::format::pb21::variable_packed_struct::FieldEncoding {
722        crate::format::pb21::variable_packed_struct::FieldEncoding {
723            value: Some(value_encoding),
724            layout: Some(
725                crate::format::pb21::variable_packed_struct::field_encoding::Layout::BitsPerValue(
726                    bits_per_value,
727                ),
728            ),
729        }
730    }
731
732    pub fn packed_struct_field_variable(
733        value_encoding: crate::format::pb21::CompressiveEncoding,
734        bits_per_length: u64,
735    ) -> crate::format::pb21::variable_packed_struct::FieldEncoding {
736        crate::format::pb21::variable_packed_struct::FieldEncoding {
737            value: Some(value_encoding),
738            layout: Some(
739                crate::format::pb21::variable_packed_struct::field_encoding::Layout::BitsPerLength(
740                    bits_per_length,
741                ),
742            ),
743        }
744    }
745}