diff --git a/parquet/Cargo.toml b/parquet/Cargo.toml index e02cb49874e6..48a4622d691e 100644 --- a/parquet/Cargo.toml +++ b/parquet/Cargo.toml @@ -73,6 +73,7 @@ tokio = { version = "1.0", optional = true, default-features = false, features = hashbrown = { version = "0.16", default-features = false } twox-hash = { version = "2.0", default-features = false, features = ["xxhash64"] } paste = { version = "1.0" } +flatbuffers = { version = "25.2.10", default-features = false, optional = true } half = { version = "2.1", default-features = false, features = ["num-traits"] } crc32fast = { version = "1.4.2", optional = true, default-features = false } simdutf8 = { workspace = true , optional = true } @@ -134,6 +135,8 @@ flate2-zlib-rs = ["flate2/zlib-rs"] variant_experimental = ["arrow", "parquet-variant", "parquet-variant-json", "parquet-variant-compute"] # Enable geospatial support geospatial = ["parquet-geospatial"] +# Enable FlatBuffers metadata support (experimental) +flatbuffers_metadata = ["dep:flatbuffers", "dep:crc32fast"] [[example]] @@ -270,5 +273,10 @@ name = "row_selection_cursor" harness = false required-features = ["arrow"] +[[bench]] +name = "metadata_flatbuf" +harness = false +required-features = ["arrow", "flatbuffers_metadata"] + [lib] bench = false diff --git a/parquet/benches/metadata_flatbuf.rs b/parquet/benches/metadata_flatbuf.rs new file mode 100644 index 000000000000..fc31afc7aae7 --- /dev/null +++ b/parquet/benches/metadata_flatbuf.rs @@ -0,0 +1,297 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the License for the +// specific language governing permissions and limitations +// under the License. + +//! Benchmarks comparing FlatBuffers vs Thrift metadata serialization. + +use std::hint::black_box; +use std::sync::Arc; + +use criterion::{BenchmarkId, Criterion, Throughput, criterion_group, criterion_main}; +use rand::Rng; + +use arrow::util::test_util::seedable_rng; +use parquet::basic::{Compression, Encoding, PageType, Type as PhysicalType}; +use parquet::file::metadata::flatbuf::{flatbuf_to_parquet_metadata, parquet_metadata_to_flatbuf}; +use parquet::file::metadata::{ + ColumnChunkMetaData, FileMetaData, PageEncodingStats, ParquetMetaData, ParquetMetaDataReader, + ParquetMetaDataWriter, RowGroupMetaData, +}; +use parquet::file::statistics::Statistics; +use parquet::file::writer::TrackedWrite; +use parquet::schema::parser::parse_message_type; +use parquet::schema::types::{ColumnDescPtr, ColumnDescriptor, ColumnPath, SchemaDescriptor}; + +/// Create test metadata with configurable number of columns and row groups +fn create_test_metadata(num_columns: usize, num_row_groups: usize) -> ParquetMetaData { + let mut rng = seedable_rng(); + + let mut column_desc_ptrs: Vec = Vec::with_capacity(num_columns); + let mut message_type = "message test_schema {".to_string(); + for i in 0..num_columns { + message_type.push_str(&format!("REQUIRED FLOAT col_{};", i)); + column_desc_ptrs.push(ColumnDescPtr::new(ColumnDescriptor::new( + Arc::new( + parquet::schema::types::Type::primitive_type_builder( + &format!("col_{}", i), + PhysicalType::FLOAT, + ) + .build() + .unwrap(), + ), + 0, + 0, + ColumnPath::new(vec![format!("col_{}", i)]), + ))); + } + message_type.push('}'); + + let schema_descr = parse_message_type(&message_type) + .map(|t| Arc::new(SchemaDescriptor::new(Arc::new(t)))) + .unwrap(); + + let stats = Statistics::float(Some(rng.random()), Some(rng.random()), None, Some(0), false); + + let row_groups = (0..num_row_groups) + .map(|i| { + let columns = (0..num_columns) + .map(|j| { + ColumnChunkMetaData::builder(column_desc_ptrs[j].clone()) + .set_encodings(vec![Encoding::PLAIN, Encoding::RLE_DICTIONARY]) + .set_compression(Compression::SNAPPY) + .set_num_values(rng.random_range(1..1000000)) + .set_total_compressed_size(rng.random_range(50000..5000000)) + .set_data_page_offset(rng.random_range(4..2000000000)) + .set_dictionary_page_offset(Some(rng.random_range(4..2000000000))) + .set_statistics(stats.clone()) + .set_page_encoding_stats(vec![ + PageEncodingStats { + page_type: PageType::DICTIONARY_PAGE, + encoding: Encoding::PLAIN, + count: 1, + }, + PageEncodingStats { + page_type: PageType::DATA_PAGE, + encoding: Encoding::RLE_DICTIONARY, + count: 10, + }, + ]) + .build() + .unwrap() + }) + .collect(); + + RowGroupMetaData::builder(schema_descr.clone()) + .set_column_metadata(columns) + .set_total_byte_size(rng.random_range(1..2000000000)) + .set_num_rows(rng.random_range(1..10000000000)) + .set_ordinal(i as i16) + .build() + .unwrap() + }) + .collect(); + + let file_metadata = FileMetaData::new( + 2, + rng.random_range(1..2000000000), + Some("parquet-rs benchmark".into()), + None, + schema_descr, + None, + ); + + ParquetMetaData::new(file_metadata, row_groups) +} + +/// Encode metadata using Thrift (current format) +fn encode_thrift(metadata: &ParquetMetaData) -> Vec { + let mut buffer = Vec::with_capacity(64 * 1024); + { + let buf = TrackedWrite::new(&mut buffer); + let writer = ParquetMetaDataWriter::new_with_tracked(buf, metadata); + writer.finish().unwrap(); + } + buffer +} + +/// Encode metadata using FlatBuffers +fn encode_flatbuf(metadata: &ParquetMetaData) -> Vec { + parquet_metadata_to_flatbuf(metadata) +} + +fn benchmark_serialization(c: &mut Criterion) { + let mut group = c.benchmark_group("metadata_serialization"); + + // Test different sizes: small (10 cols, 1 rg), medium (100 cols, 10 rgs), large (1000 cols, 10 rgs) + let configs = [ + ("small", 10, 1), + ("medium", 100, 10), + ("large", 1000, 10), + ("wide", 10000, 1), + ]; + + for (name, num_cols, num_rgs) in configs { + let metadata = create_test_metadata(num_cols, num_rgs); + + // Thrift encoding benchmark + group.throughput(Throughput::Elements(1)); + group.bench_with_input( + BenchmarkId::new("thrift_encode", name), + &metadata, + |b, meta| { + b.iter(|| { + black_box(encode_thrift(meta)); + }); + }, + ); + + // FlatBuffers encoding benchmark + group.bench_with_input( + BenchmarkId::new("flatbuf_encode", name), + &metadata, + |b, meta| { + b.iter(|| { + black_box(encode_flatbuf(meta)); + }); + }, + ); + + // Pre-encode for decoding benchmarks + let thrift_bytes = encode_thrift(&metadata); + let flatbuf_bytes = encode_flatbuf(&metadata); + + // Report sizes + println!( + "{}: Thrift size = {} bytes, FlatBuf size = {} bytes, ratio = {:.2}x", + name, + thrift_bytes.len(), + flatbuf_bytes.len(), + thrift_bytes.len() as f64 / flatbuf_bytes.len() as f64 + ); + + // Thrift decoding benchmark + group.bench_with_input( + BenchmarkId::new("thrift_decode", name), + &thrift_bytes, + |b, bytes| { + b.iter(|| { + black_box(ParquetMetaDataReader::decode_metadata(bytes).unwrap()); + }); + }, + ); + + // FlatBuffers decoding benchmark + let schema_descr = metadata.file_metadata().schema_descr_ptr(); + group.bench_with_input( + BenchmarkId::new("flatbuf_decode", name), + &(&flatbuf_bytes, schema_descr.clone()), + |b, (bytes, schema)| { + b.iter(|| { + black_box(flatbuf_to_parquet_metadata(bytes, schema.clone()).unwrap()); + }); + }, + ); + } + + group.finish(); +} + +fn benchmark_roundtrip(c: &mut Criterion) { + let mut group = c.benchmark_group("metadata_roundtrip"); + + let configs = [("medium", 100, 10), ("large", 1000, 10)]; + + for (name, num_cols, num_rgs) in configs { + let metadata = create_test_metadata(num_cols, num_rgs); + let schema_descr = metadata.file_metadata().schema_descr_ptr(); + + // Thrift roundtrip + group.bench_with_input( + BenchmarkId::new("thrift_roundtrip", name), + &metadata, + |b, meta| { + b.iter(|| { + let encoded = encode_thrift(meta); + black_box(ParquetMetaDataReader::decode_metadata(&encoded).unwrap()); + }); + }, + ); + + // FlatBuffers roundtrip + group.bench_with_input( + BenchmarkId::new("flatbuf_roundtrip", name), + &(&metadata, schema_descr.clone()), + |b, (meta, schema)| { + b.iter(|| { + let encoded = encode_flatbuf(meta); + black_box(flatbuf_to_parquet_metadata(&encoded, schema.clone()).unwrap()); + }); + }, + ); + } + + group.finish(); +} + +fn benchmark_size_comparison(c: &mut Criterion) { + let mut group = c.benchmark_group("metadata_size"); + + // Benchmark with increasing column counts to show scaling + let column_counts = [10, 50, 100, 500, 1000, 5000]; + + for num_cols in column_counts { + let metadata = create_test_metadata(num_cols, 5); + + let thrift_bytes = encode_thrift(&metadata); + let flatbuf_bytes = encode_flatbuf(&metadata); + + println!( + "Columns: {}, Thrift: {} bytes, FlatBuf: {} bytes, Ratio: {:.2}x", + num_cols, + thrift_bytes.len(), + flatbuf_bytes.len(), + thrift_bytes.len() as f64 / flatbuf_bytes.len() as f64 + ); + + // Just measure encoding time as a function of column count + group.throughput(Throughput::Elements(num_cols as u64)); + group.bench_with_input( + BenchmarkId::new("thrift", num_cols), + &metadata, + |b, meta| { + b.iter(|| black_box(encode_thrift(meta))); + }, + ); + + group.bench_with_input( + BenchmarkId::new("flatbuf", num_cols), + &metadata, + |b, meta| { + b.iter(|| black_box(encode_flatbuf(meta))); + }, + ); + } + + group.finish(); +} + +criterion_group!( + benches, + benchmark_serialization, + benchmark_roundtrip, + benchmark_size_comparison, +); +criterion_main!(benches); diff --git a/parquet/src/file/metadata/flatbuf/converter.rs b/parquet/src/file/metadata/flatbuf/converter.rs new file mode 100644 index 000000000000..29bfe02d642c --- /dev/null +++ b/parquet/src/file/metadata/flatbuf/converter.rs @@ -0,0 +1,1968 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the License for the +// specific language governing permissions and limitations +// under the License. + +//! Converter between Parquet metadata and FlatBuffers representation. +//! +//! This module provides functionality to convert Parquet metadata to/from +//! the FlatBuffers format defined in `parquet.fbs`. +//! +//! The FlatBuffers format packs statistics into integral fields for efficient +//! storage and zero-copy access. See [`pack_statistics`] and [`unpack_statistics`] +//! for the encoding scheme. +//! +//! Related: +//! - Design doc: +//! - C++ implementation: + +use std::sync::Arc; + +use flatbuffers::{FlatBufferBuilder, WIPOffset}; + +use crate::basic::{ColumnOrder, Compression, Encoding, LogicalType, Repetition, Type}; +use crate::data_type::{ByteArray, FixedLenByteArray, Int96}; +use crate::errors::{ParquetError, Result}; +use crate::file::metadata::{ + ColumnChunkMetaData, ColumnChunkMetaDataBuilder, FileMetaData, KeyValue, ParquetMetaData, + RowGroupMetaData, RowGroupMetaDataBuilder, SortingColumn, +}; +use crate::file::statistics::Statistics; +use crate::schema::types::{ColumnDescriptor, SchemaDescPtr, SchemaDescriptor, Type as SchemaType}; + +use super::parquet_generated::parquet::format as fb; + +/// Packed min/max statistics for FlatBuffers format +#[derive(Debug, Default, Clone)] +struct PackedStats { + lo4: u32, + lo8: u64, + hi8: u64, + len: i8, +} + +/// Min/max statistics with optional prefix for string types +#[derive(Debug, Default)] +struct MinMax { + min: PackedStats, + max: PackedStats, + prefix: String, +} + +/// Pack statistics into the FlatBuffers format based on physical type. +/// +/// Statistics are stored in integral types if their size is fixed: +/// - BOOLEAN: none +/// - INT32/FLOAT: lo4 (little-endian) +/// - INT64/DOUBLE: lo8 (little-endian) +/// - INT96: lo4+lo8 (little-endian) +/// - BYTE_ARRAY/FIXED_LEN_BYTE_ARRAY: prefix + lo8+hi8 (big-endian) +fn pack_statistics( + physical_type: Type, + min: &[u8], + is_min_exact: bool, + max: &[u8], + is_max_exact: bool, +) -> MinMax { + match physical_type { + Type::BOOLEAN => MinMax::default(), + Type::INT32 | Type::FLOAT => { + let load = |v: &[u8], is_exact: bool| -> PackedStats { + if v.len() >= 4 { + PackedStats { + lo4: u32::from_le_bytes(v[..4].try_into().unwrap()), + len: if is_exact { 4 } else { -4 }, + ..Default::default() + } + } else { + PackedStats::default() + } + }; + MinMax { + min: load(min, is_min_exact), + max: load(max, is_max_exact), + prefix: String::new(), + } + } + Type::INT64 | Type::DOUBLE => { + let load = |v: &[u8], is_exact: bool| -> PackedStats { + if v.len() >= 8 { + PackedStats { + lo8: u64::from_le_bytes(v[..8].try_into().unwrap()), + len: if is_exact { 8 } else { -8 }, + ..Default::default() + } + } else { + PackedStats::default() + } + }; + MinMax { + min: load(min, is_min_exact), + max: load(max, is_max_exact), + prefix: String::new(), + } + } + Type::INT96 => { + let load = |v: &[u8], is_exact: bool| -> PackedStats { + if v.len() >= 12 { + PackedStats { + lo4: u32::from_le_bytes(v[..4].try_into().unwrap()), + lo8: u64::from_le_bytes(v[4..12].try_into().unwrap()), + len: if is_exact { 12 } else { -12 }, + ..Default::default() + } + } else { + PackedStats::default() + } + }; + MinMax { + min: load(min, is_min_exact), + max: load(max, is_max_exact), + prefix: String::new(), + } + } + Type::FIXED_LEN_BYTE_ARRAY => { + // Special case for decimal16 + if min.len() == 16 && max.len() == 16 && is_min_exact && is_max_exact { + let load = |v: &[u8]| -> PackedStats { + PackedStats { + lo8: u64::from_be_bytes(v[8..16].try_into().unwrap()), + hi8: u64::from_be_bytes(v[0..8].try_into().unwrap()), + len: 16, + ..Default::default() + } + }; + return MinMax { + min: load(min), + max: load(max), + prefix: String::new(), + }; + } + pack_byte_array_stats(min, is_min_exact, max, is_max_exact) + } + Type::BYTE_ARRAY => pack_byte_array_stats(min, is_min_exact, max, is_max_exact), + } +} + +/// Pack byte array statistics with common prefix extraction +fn pack_byte_array_stats(min: &[u8], is_min_exact: bool, max: &[u8], is_max_exact: bool) -> MinMax { + // Find common prefix + let prefix_len = min + .iter() + .zip(max.iter()) + .take_while(|(a, b)| a == b) + .count(); + + let prefix = if prefix_len > 0 { + String::from_utf8_lossy(&max[..prefix_len]).to_string() + } else { + String::new() + }; + + let load = |v: &[u8], is_exact: bool, is_max: bool| -> PackedStats { + let suffix = &v[prefix_len..]; + if suffix.len() <= 4 { + let mut buf = [0u8; 4]; + buf[..suffix.len()].copy_from_slice(suffix); + PackedStats { + lo4: u32::from_be_bytes(buf), + len: if is_exact { + suffix.len() as i8 + } else { + -(suffix.len() as i8) + }, + ..Default::default() + } + } else { + // For longer values, we store the first 4 bytes adjusted + let first4 = u32::from_be_bytes(suffix[..4].try_into().unwrap()); + PackedStats { + lo4: if is_max { + first4.saturating_add(1) + } else { + first4.saturating_sub(1) + }, + len: -4, + ..Default::default() + } + } + }; + + MinMax { + min: load(min, is_min_exact, false), + max: load(max, is_max_exact, true), + prefix, + } +} + +/// Unpack statistics from FlatBuffers format back to byte arrays +fn unpack_statistics( + physical_type: Type, + packed: &MinMax, +) -> Option<(Vec, bool, Vec, bool)> { + match physical_type { + Type::BOOLEAN => None, + Type::INT32 | Type::FLOAT => { + let min = packed.min.lo4.to_le_bytes().to_vec(); + let max = packed.max.lo4.to_le_bytes().to_vec(); + Some((min, packed.min.len > 0, max, packed.max.len > 0)) + } + Type::INT64 | Type::DOUBLE => { + let min = packed.min.lo8.to_le_bytes().to_vec(); + let max = packed.max.lo8.to_le_bytes().to_vec(); + Some((min, packed.min.len > 0, max, packed.max.len > 0)) + } + Type::INT96 => { + let mut min = Vec::with_capacity(12); + min.extend_from_slice(&packed.min.lo4.to_le_bytes()); + min.extend_from_slice(&packed.min.lo8.to_le_bytes()); + let mut max = Vec::with_capacity(12); + max.extend_from_slice(&packed.max.lo4.to_le_bytes()); + max.extend_from_slice(&packed.max.lo8.to_le_bytes()); + Some((min, packed.min.len > 0, max, packed.max.len > 0)) + } + Type::BYTE_ARRAY | Type::FIXED_LEN_BYTE_ARRAY => { + let unpack = |p: &PackedStats, prefix: &str| -> (Vec, bool) { + let mut result = prefix.as_bytes().to_vec(); + if p.len == 16 { + // Decimal16 case + result.extend_from_slice(&p.hi8.to_be_bytes()); + result.extend_from_slice(&p.lo8.to_be_bytes()); + (result, true) + } else { + result.extend_from_slice( + &p.lo4.to_be_bytes()[..(p.len.unsigned_abs() as usize).min(4)], + ); + (result, p.len >= 0) + } + }; + let (min, min_exact) = unpack(&packed.min, &packed.prefix); + let (max, max_exact) = unpack(&packed.max, &packed.prefix); + Some((min, min_exact, max, max_exact)) + } + } +} + +/// Converts [`ParquetMetaData`] to the FlatBuffers wire format. +/// +/// This serializes the schema, row groups, column chunks, statistics, and +/// key-value metadata into a single FlatBuffer. The result can be embedded +/// into a Parquet footer via [`append_flatbuffer`]. +pub(super) struct ThriftToFlatBufferConverter<'a> { + metadata: &'a ParquetMetaData, + builder: FlatBufferBuilder<'a>, +} + +impl<'a> ThriftToFlatBufferConverter<'a> { + /// Create a new converter from [`ParquetMetaData`]. + pub fn new(metadata: &'a ParquetMetaData) -> Self { + Self { + metadata, + builder: FlatBufferBuilder::with_capacity(64 * 1024), + } + } + + /// Convert the metadata to FlatBuffers format and return the serialized bytes. + pub fn convert(mut self) -> Vec { + let file_metadata = self.metadata.file_metadata(); + let schema_descr = file_metadata.schema_descr(); + + // Build schema elements + let schema_offsets = self.build_schema(file_metadata); + let schema = self.builder.create_vector(&schema_offsets); + + // Build row groups + let row_group_offsets: Vec<_> = self + .metadata + .row_groups() + .iter() + .enumerate() + .map(|(rg_idx, rg)| self.build_row_group(rg, rg_idx, schema_descr)) + .collect(); + let row_groups = self.builder.create_vector(&row_group_offsets); + + // Build key-value metadata + let kv = file_metadata.key_value_metadata().map(|kvs| { + let kv_offsets: Vec<_> = kvs.iter().map(|kv| self.build_kv(kv)).collect(); + self.builder.create_vector(&kv_offsets) + }); + + // Build created_by + let created_by = file_metadata + .created_by() + .map(|s| self.builder.create_string(s)); + + // Build FileMetaData + let file_meta_data = fb::FileMetaData::create( + &mut self.builder, + &fb::FileMetaDataArgs { + version: file_metadata.version(), + schema: Some(schema), + num_rows: file_metadata.num_rows(), + row_groups: Some(row_groups), + kv, + created_by, + encryption_algorithm_type: fb::EncryptionAlgorithm::NONE, + encryption_algorithm: None, + footer_signing_key_metadata: None, + }, + ); + + self.builder.finish(file_meta_data, None); + self.builder.finished_data().to_vec() + } + + /// Build the flattened schema element vector from the schema descriptor. + fn build_schema( + &mut self, + file_metadata: &FileMetaData, + ) -> Vec>> { + let root_schema = file_metadata.schema_descr().root_schema(); + let column_orders = file_metadata + .column_orders() + .map(|orders| orders.as_slice()); + let mut elements = Vec::new(); + let mut leaf_idx = 0; + self.build_schema_element( + root_schema, + &mut elements, + true, + column_orders, + &mut leaf_idx, + ); + elements + } + + /// Recursively build a schema element and its children. + fn build_schema_element( + &mut self, + schema_type: &SchemaType, + elements: &mut Vec>>, + is_root: bool, + column_orders: Option<&[ColumnOrder]>, + leaf_idx: &mut usize, + ) { + let name = self.builder.create_string(schema_type.name()); + + let (physical_type, type_length) = match schema_type { + SchemaType::PrimitiveType { + physical_type, + type_length, + .. + } => ( + Some(convert_type_to_fb(*physical_type)), + if *type_length > 0 { + Some(*type_length) + } else { + None + }, + ), + SchemaType::GroupType { .. } => (None, None), + }; + + let repetition_type = if is_root { + fb::FieldRepetitionType::REQUIRED + } else { + convert_repetition_to_fb(schema_type.get_basic_info().repetition()) + }; + + let num_children = if schema_type.is_group() { + schema_type.get_fields().len() as i32 + } else { + 0 + }; + + let field_id_opt = if schema_type.get_basic_info().has_id() { + Some(schema_type.get_basic_info().id()) + } else { + None + }; + + // Build logical type if present + let (logical_type_type, logical_type) = + self.build_logical_type(schema_type.get_basic_info().logical_type_ref()); + + // Build column order for leaf nodes + let (column_order_type, column_order) = if !schema_type.is_group() { + // Preserve file metadata semantics by only writing type-defined order when present. + let column_order = column_orders + .and_then(|orders| orders.get(*leaf_idx)) + .copied() + .unwrap_or(ColumnOrder::UNDEFINED); + *leaf_idx += 1; + + if matches!(column_order, ColumnOrder::TYPE_DEFINED_ORDER(_)) { + ( + fb::ColumnOrder::TypeDefinedOrder, + Some(fb::Empty::create(&mut self.builder, &fb::EmptyArgs {}).as_union_value()), + ) + } else { + (fb::ColumnOrder::NONE, None) + } + } else { + (fb::ColumnOrder::NONE, None) + }; + + let element = fb::SchemaElement::create( + &mut self.builder, + &fb::SchemaElementArgs { + name: Some(name), + type_: physical_type, + repetition_type, + logical_type_type, + logical_type, + type_length, + num_children, + field_id: field_id_opt, + column_order_type, + column_order, + }, + ); + elements.push(element); + + // Recursively add children + if schema_type.is_group() { + for field in schema_type.get_fields() { + self.build_schema_element(field, elements, false, column_orders, leaf_idx); + } + } + } + + /// Convert a Parquet logical type to its FlatBuffer union representation. + fn build_logical_type( + &mut self, + logical_type: Option<&LogicalType>, + ) -> ( + fb::LogicalType, + Option>, + ) { + match logical_type { + None => (fb::LogicalType::NONE, None), + Some(lt) => match lt { + LogicalType::String => ( + fb::LogicalType::StringType, + Some(fb::Empty::create(&mut self.builder, &fb::EmptyArgs {}).as_union_value()), + ), + LogicalType::Map => ( + fb::LogicalType::MapType, + Some(fb::Empty::create(&mut self.builder, &fb::EmptyArgs {}).as_union_value()), + ), + LogicalType::List => ( + fb::LogicalType::ListType, + Some(fb::Empty::create(&mut self.builder, &fb::EmptyArgs {}).as_union_value()), + ), + LogicalType::Enum => ( + fb::LogicalType::EnumType, + Some(fb::Empty::create(&mut self.builder, &fb::EmptyArgs {}).as_union_value()), + ), + LogicalType::Decimal { precision, scale } => ( + fb::LogicalType::DecimalType, + Some( + fb::DecimalOptions::create( + &mut self.builder, + &fb::DecimalOptionsArgs { + precision: *precision, + scale: *scale, + }, + ) + .as_union_value(), + ), + ), + LogicalType::Date => ( + fb::LogicalType::DateType, + Some(fb::Empty::create(&mut self.builder, &fb::EmptyArgs {}).as_union_value()), + ), + LogicalType::Time { + is_adjusted_to_u_t_c, + unit, + } => ( + fb::LogicalType::TimeType, + Some( + fb::TimeOptions::create( + &mut self.builder, + &fb::TimeOptionsArgs { + is_adjusted_to_utc: *is_adjusted_to_u_t_c, + unit: convert_time_unit_to_fb(unit), + }, + ) + .as_union_value(), + ), + ), + LogicalType::Timestamp { + is_adjusted_to_u_t_c, + unit, + } => ( + fb::LogicalType::TimestampType, + Some( + fb::TimeOptions::create( + &mut self.builder, + &fb::TimeOptionsArgs { + is_adjusted_to_utc: *is_adjusted_to_u_t_c, + unit: convert_time_unit_to_fb(unit), + }, + ) + .as_union_value(), + ), + ), + LogicalType::Integer { + bit_width, + is_signed, + } => ( + fb::LogicalType::IntType, + Some( + fb::IntOptions::create( + &mut self.builder, + &fb::IntOptionsArgs { + bit_width: *bit_width, + is_signed: *is_signed, + }, + ) + .as_union_value(), + ), + ), + LogicalType::Unknown => ( + fb::LogicalType::NullType, + Some(fb::Empty::create(&mut self.builder, &fb::EmptyArgs {}).as_union_value()), + ), + LogicalType::Json => ( + fb::LogicalType::JsonType, + Some(fb::Empty::create(&mut self.builder, &fb::EmptyArgs {}).as_union_value()), + ), + LogicalType::Bson => ( + fb::LogicalType::BsonType, + Some(fb::Empty::create(&mut self.builder, &fb::EmptyArgs {}).as_union_value()), + ), + LogicalType::Uuid => ( + fb::LogicalType::UUIDType, + Some(fb::Empty::create(&mut self.builder, &fb::EmptyArgs {}).as_union_value()), + ), + LogicalType::Float16 => ( + fb::LogicalType::Float16Type, + Some(fb::Empty::create(&mut self.builder, &fb::EmptyArgs {}).as_union_value()), + ), + LogicalType::Variant { .. } => ( + fb::LogicalType::VariantType, + Some(fb::Empty::create(&mut self.builder, &fb::EmptyArgs {}).as_union_value()), + ), + LogicalType::Geometry { crs } => { + let crs_str = crs.as_ref().map(|s| self.builder.create_string(s)); + ( + fb::LogicalType::GeometryType, + Some( + fb::GeometryType::create( + &mut self.builder, + &fb::GeometryTypeArgs { crs: crs_str }, + ) + .as_union_value(), + ), + ) + } + LogicalType::Geography { crs, algorithm } => { + let crs_str = crs.as_ref().map(|s| self.builder.create_string(s)); + let algo = algorithm + .as_ref() + .map(|a| convert_edge_interpolation_to_fb(*a)) + .unwrap_or(fb::EdgeInterpolationAlgorithm::SPHERICAL); + ( + fb::LogicalType::GeographyType, + Some( + fb::GeographyType::create( + &mut self.builder, + &fb::GeographyTypeArgs { + crs: crs_str, + algorithm: algo, + }, + ) + .as_union_value(), + ), + ) + } + LogicalType::_Unknown { .. } => (fb::LogicalType::NONE, None), + }, + } + } + + /// Build a row group, including its column chunks and sorting columns. + fn build_row_group( + &mut self, + rg: &RowGroupMetaData, + _rg_idx: usize, + _schema_descr: &SchemaDescriptor, + ) -> WIPOffset> { + // Build column chunks + let column_offsets: Vec<_> = rg + .columns() + .iter() + .enumerate() + .map(|(col_idx, cc)| self.build_column_chunk(cc, rg, col_idx)) + .collect(); + let columns = self.builder.create_vector(&column_offsets); + + // Build sorting columns + let sorting_columns = rg.sorting_columns().map(|scs| { + let sc_offsets: Vec<_> = scs.iter().map(|sc| self.build_sorting_column(sc)).collect(); + self.builder.create_vector(&sc_offsets) + }); + + // Calculate total compressed size + let total_compressed_size: i64 = rg.columns().iter().map(|c| c.compressed_size()).sum(); + + fb::RowGroup::create( + &mut self.builder, + &fb::RowGroupArgs { + columns: Some(columns), + total_byte_size: rg.total_byte_size(), + num_rows: rg.num_rows(), + sorting_columns, + file_offset: rg.file_offset().unwrap_or(0), + total_compressed_size, + ordinal: rg.ordinal(), + }, + ) + } + + /// Build a column chunk with its metadata. + fn build_column_chunk( + &mut self, + cc: &ColumnChunkMetaData, + rg: &RowGroupMetaData, + _col_idx: usize, + ) -> WIPOffset> { + let meta_data = self.build_column_metadata(cc, rg); + + fb::ColumnChunk::create( + &mut self.builder, + &fb::ColumnChunkArgs { + meta_data: Some(meta_data), + crypto_metadata_type: fb::ColumnCryptoMetadata::NONE, + crypto_metadata: None, + encrypted_column_metadata: None, + }, + ) + } + + /// Build column metadata including compression, offsets, and packed statistics. + fn build_column_metadata( + &mut self, + cc: &ColumnChunkMetaData, + rg: &RowGroupMetaData, + ) -> WIPOffset> { + // Build key-value metadata if present + let key_value_metadata = None; // Column-level KV metadata not commonly used + + // Build statistics + let statistics = cc + .statistics() + .map(|stats| self.build_statistics(stats, cc.column_type())); + + // Determine if fully dictionary encoded + let is_fully_dict_encoded = cc.dictionary_page_offset().is_some() + && cc.page_encoding_stats_mask().is_some_and(|mask| { + mask.is_only(Encoding::PLAIN_DICTIONARY) || mask.is_only(Encoding::RLE_DICTIONARY) + }); + + // Only store num_values if different from row group num_rows + let num_values = if cc.num_values() != rg.num_rows() { + Some(cc.num_values()) + } else { + None + }; + + // Build bloom filter info if present + let bloom_filter = match (cc.bloom_filter_offset(), cc.bloom_filter_length()) { + (Some(offset), Some(length)) => Some(fb::BloomFilterInfo::create( + &mut self.builder, + &fb::BloomFilterInfoArgs { offset, length }, + )), + _ => None, + }; + + fb::ColumnMetadata::create( + &mut self.builder, + &fb::ColumnMetadataArgs { + codec: convert_compression_to_fb(cc.compression()), + num_values, + total_uncompressed_size: cc.uncompressed_size(), + total_compressed_size: cc.compressed_size(), + key_value_metadata, + data_page_offset: cc.data_page_offset(), + index_page_offset: cc.index_page_offset(), + dictionary_page_offset: cc.dictionary_page_offset(), + statistics, + is_fully_dict_encoded, + bloom_filter, + }, + ) + } + + /// Pack statistics into the FlatBuffer format using [`pack_statistics`]. + fn build_statistics( + &mut self, + stats: &Statistics, + physical_type: Type, + ) -> WIPOffset> { + let null_count = stats.null_count_opt().map(|n| n as i32); + + // Pack min/max values + let (min_stats, max_stats, prefix_str) = + if let (Some(min), Some(max)) = (stats.min_bytes_opt(), stats.max_bytes_opt()) { + let packed = pack_statistics( + physical_type, + min, + stats.min_is_exact(), + max, + stats.max_is_exact(), + ); + (Some(packed.min), Some(packed.max), packed.prefix) + } else { + (None, None, String::new()) + }; + + let prefix = if !prefix_str.is_empty() { + Some(self.builder.create_string(&prefix_str)) + } else { + None + }; + + fb::Statistics::create( + &mut self.builder, + &fb::StatisticsArgs { + null_count, + min_lo4: min_stats.as_ref().map(|s| s.lo4).unwrap_or(0), + min_lo8: min_stats.as_ref().map(|s| s.lo8).unwrap_or(0), + min_hi8: min_stats.as_ref().map(|s| s.hi8).unwrap_or(0), + min_len: min_stats.map(|s| s.len), + max_lo4: max_stats.as_ref().map(|s| s.lo4).unwrap_or(0), + max_lo8: max_stats.as_ref().map(|s| s.lo8).unwrap_or(0), + max_hi8: max_stats.as_ref().map(|s| s.hi8).unwrap_or(0), + max_len: max_stats.map(|s| s.len), + prefix, + }, + ) + } + + fn build_sorting_column(&mut self, sc: &SortingColumn) -> WIPOffset> { + fb::SortingColumn::create( + &mut self.builder, + &fb::SortingColumnArgs { + column_idx: sc.column_idx, + descending: sc.descending, + nulls_first: sc.nulls_first, + }, + ) + } + + fn build_kv(&mut self, kv: &KeyValue) -> WIPOffset> { + let key = self.builder.create_string(&kv.key); + let val = kv.value.as_ref().map(|v| self.builder.create_string(v)); + + fb::KeyValue::create( + &mut self.builder, + &fb::KeyValueArgs { + key: Some(key), + val, + }, + ) + } +} + +/// Converts FlatBuffers wire format back to [`ParquetMetaData`]. +/// +/// Requires a pre-existing [`SchemaDescPtr`] since the FlatBuffers format +/// relies on the schema to interpret column physical types and statistics. +pub(super) struct FlatBufferConverter; + +impl FlatBufferConverter { + /// Parse FlatBuffers bytes and reconstruct [`ParquetMetaData`]. + pub fn convert(buf: &[u8], schema_descr: SchemaDescPtr) -> Result { + let fb_meta = fb::root_as_file_meta_data(buf) + .map_err(|e| ParquetError::General(format!("Invalid FlatBuffer: {}", e)))?; + + let file_metadata = Self::convert_file_metadata(&fb_meta, schema_descr.clone())?; + let row_groups = Self::convert_row_groups(&fb_meta, schema_descr)?; + + Ok(ParquetMetaData::new(file_metadata, row_groups)) + } + + /// Convert file-level metadata (version, num_rows, created_by, key-value, column orders). + fn convert_file_metadata( + fb_meta: &fb::FileMetaData, + schema_descr: SchemaDescPtr, + ) -> Result { + let version = fb_meta.version(); + let num_rows = fb_meta.num_rows(); + + let created_by = fb_meta.created_by().map(|s| s.to_string()); + + let key_value_metadata = fb_meta.kv().map(|kvs| { + kvs.iter() + .map(|kv| KeyValue { + key: kv.key().unwrap_or("").to_string(), + value: kv.val().map(|v| v.to_string()), + }) + .collect() + }); + + // Extract column orders from schema elements + let column_orders = if let Some(schema) = fb_meta.schema() { + let leaf_nodes: Vec<_> = schema.iter().filter(|e| e.num_children() == 0).collect(); + if leaf_nodes.len() != schema_descr.num_columns() { + return Err(ParquetError::General( + "FlatBuffer column order length mismatch".to_string(), + )); + } + + if leaf_nodes + .iter() + .all(|e| e.column_order_type() != fb::ColumnOrder::TypeDefinedOrder) + { + None + } else { + Some( + leaf_nodes + .into_iter() + .zip(schema_descr.columns().iter()) + .map(|(e, column)| { + if e.column_order_type() == fb::ColumnOrder::TypeDefinedOrder { + let sort_order = ColumnOrder::sort_order_for_type( + column.logical_type_ref(), + column.converted_type(), + column.physical_type(), + ); + ColumnOrder::TYPE_DEFINED_ORDER(sort_order) + } else { + ColumnOrder::UNDEFINED + } + }) + .collect(), + ) + } + } else { + None + }; + + Ok(FileMetaData::new( + version, + num_rows, + created_by, + key_value_metadata, + schema_descr, + column_orders, + )) + } + + /// Convert all row groups from the FlatBuffer. + fn convert_row_groups( + fb_meta: &fb::FileMetaData, + schema_descr: SchemaDescPtr, + ) -> Result> { + let row_groups = fb_meta.row_groups().ok_or_else(|| { + ParquetError::General("FlatBuffer metadata missing row_groups".to_string()) + })?; + + row_groups + .iter() + .map(|rg| Self::convert_row_group(&rg, schema_descr.clone())) + .collect() + } + + /// Convert a single row group and its column chunks. + fn convert_row_group( + fb_rg: &fb::RowGroup, + schema_descr: SchemaDescPtr, + ) -> Result { + let columns = fb_rg.columns().ok_or_else(|| { + ParquetError::General("FlatBuffer row group missing columns".to_string()) + })?; + + let mut builder = RowGroupMetaDataBuilder::new(schema_descr.clone()) + .set_num_rows(fb_rg.num_rows()) + .set_total_byte_size(fb_rg.total_byte_size()); + + if fb_rg.file_offset() != 0 { + builder = builder.set_file_offset(fb_rg.file_offset()); + } + + if let Some(ordinal) = fb_rg.ordinal() { + builder = builder.set_ordinal(ordinal); + } + + // Convert sorting columns + if let Some(sorting_cols) = fb_rg.sorting_columns() { + let sorting: Vec<_> = sorting_cols + .iter() + .map(|sc| SortingColumn { + column_idx: sc.column_idx(), + descending: sc.descending(), + nulls_first: sc.nulls_first(), + }) + .collect(); + builder = builder.set_sorting_columns(Some(sorting)); + } + + // Convert column chunks + for (col_idx, fb_cc) in columns.iter().enumerate() { + let column_descr = schema_descr.column(col_idx); + let cc = Self::convert_column_chunk(&fb_cc, fb_rg, column_descr)?; + builder = builder.add_column_metadata(cc); + } + + builder.build() + } + + /// Convert a column chunk including compression, offsets, and statistics. + fn convert_column_chunk( + fb_cc: &fb::ColumnChunk, + fb_rg: &fb::RowGroup, + column_descr: Arc, + ) -> Result { + let fb_meta = fb_cc.meta_data().ok_or_else(|| { + ParquetError::General("FlatBuffer column chunk missing metadata".to_string()) + })?; + + let physical_type = column_descr.physical_type(); + let mut builder = ColumnChunkMetaDataBuilder::new(column_descr) + .set_compression(convert_compression_from_fb(fb_meta.codec())) + .set_num_values(fb_meta.num_values().unwrap_or(fb_rg.num_rows())) + .set_total_compressed_size(fb_meta.total_compressed_size()) + .set_total_uncompressed_size(fb_meta.total_uncompressed_size()) + .set_data_page_offset(fb_meta.data_page_offset()); + + if let Some(offset) = fb_meta.index_page_offset() { + builder = builder.set_index_page_offset(Some(offset)); + } + + if let Some(offset) = fb_meta.dictionary_page_offset() { + builder = builder.set_dictionary_page_offset(Some(offset)); + } + + if let Some(bloom_filter) = fb_meta.bloom_filter() { + builder = builder.set_bloom_filter_offset(Some(bloom_filter.offset())); + builder = builder.set_bloom_filter_length(Some(bloom_filter.length())); + } + + // Convert statistics + if let Some(fb_stats) = fb_meta.statistics() { + let stats = Self::convert_statistics(&fb_stats, physical_type)?; + if let Some(s) = stats { + builder = builder.set_statistics(s); + } + } + + builder.build() + } + + /// Unpack statistics from the FlatBuffer format into typed [`Statistics`]. + fn convert_statistics( + fb_stats: &fb::Statistics, + physical_type: Type, + ) -> Result> { + let null_count = fb_stats.null_count().map(|n| n as u64); + + // Unpack min/max values + let (min_bytes, min_exact, max_bytes, max_exact) = + if fb_stats.min_len().is_some() && fb_stats.max_len().is_some() { + let packed = MinMax { + min: PackedStats { + lo4: fb_stats.min_lo4(), + lo8: fb_stats.min_lo8(), + hi8: fb_stats.min_hi8(), + len: fb_stats.min_len().unwrap_or(0), + }, + max: PackedStats { + lo4: fb_stats.max_lo4(), + lo8: fb_stats.max_lo8(), + hi8: fb_stats.max_hi8(), + len: fb_stats.max_len().unwrap_or(0), + }, + prefix: fb_stats.prefix().unwrap_or("").to_string(), + }; + + match unpack_statistics(physical_type, &packed) { + Some((min, min_exact, max, max_exact)) => { + (Some(min), min_exact, Some(max), max_exact) + } + None => (None, false, None, false), + } + } else { + (None, false, None, false) + }; + + // Create statistics based on physical type + let stats = match physical_type { + Type::BOOLEAN => { + if let (Some(min), Some(max)) = (min_bytes.as_ref(), max_bytes.as_ref()) { + Statistics::boolean( + min.first().map(|&b| b != 0), + max.first().map(|&b| b != 0), + None, + null_count, + false, + ) + } else { + return Ok(None); + } + } + Type::INT32 => { + if let (Some(min), Some(max)) = (min_bytes.as_ref(), max_bytes.as_ref()) { + Statistics::int32( + Some(i32::from_le_bytes(min[..4].try_into().unwrap())), + Some(i32::from_le_bytes(max[..4].try_into().unwrap())), + None, + null_count, + false, + ) + } else { + return Ok(None); + } + } + Type::INT64 => { + if let (Some(min), Some(max)) = (min_bytes.as_ref(), max_bytes.as_ref()) { + Statistics::int64( + Some(i64::from_le_bytes(min[..8].try_into().unwrap())), + Some(i64::from_le_bytes(max[..8].try_into().unwrap())), + None, + null_count, + false, + ) + } else { + return Ok(None); + } + } + Type::FLOAT => { + if let (Some(min), Some(max)) = (min_bytes.as_ref(), max_bytes.as_ref()) { + Statistics::float( + Some(f32::from_le_bytes(min[..4].try_into().unwrap())), + Some(f32::from_le_bytes(max[..4].try_into().unwrap())), + None, + null_count, + false, + ) + } else { + return Ok(None); + } + } + Type::DOUBLE => { + if let (Some(min), Some(max)) = (min_bytes.as_ref(), max_bytes.as_ref()) { + Statistics::double( + Some(f64::from_le_bytes(min[..8].try_into().unwrap())), + Some(f64::from_le_bytes(max[..8].try_into().unwrap())), + None, + null_count, + false, + ) + } else { + return Ok(None); + } + } + Type::INT96 => { + if let (Some(min), Some(max)) = (min_bytes.as_ref(), max_bytes.as_ref()) { + if min.len() >= 12 && max.len() >= 12 { + let mut min_val = Int96::new(); + min_val.set_data( + u32::from_le_bytes(min[0..4].try_into().unwrap()), + u32::from_le_bytes(min[4..8].try_into().unwrap()), + u32::from_le_bytes(min[8..12].try_into().unwrap()), + ); + let mut max_val = Int96::new(); + max_val.set_data( + u32::from_le_bytes(max[0..4].try_into().unwrap()), + u32::from_le_bytes(max[4..8].try_into().unwrap()), + u32::from_le_bytes(max[8..12].try_into().unwrap()), + ); + Statistics::int96(Some(min_val), Some(max_val), None, null_count, false) + } else { + return Ok(None); + } + } else { + return Ok(None); + } + } + Type::BYTE_ARRAY => { + if let (Some(min), Some(max)) = (min_bytes, max_bytes) { + Statistics::byte_array( + Some(ByteArray::from(min)), + Some(ByteArray::from(max)), + None, + null_count, + false, + ) + } else { + return Ok(None); + } + } + Type::FIXED_LEN_BYTE_ARRAY => { + if let (Some(min), Some(max)) = (min_bytes, max_bytes) { + Statistics::fixed_len_byte_array( + Some(FixedLenByteArray::from(min)), + Some(FixedLenByteArray::from(max)), + None, + null_count, + false, + ) + } else { + return Ok(None); + } + } + }; + + Ok(Some(with_statistics_exactness(stats, min_exact, max_exact))) + } +} + +// Conversion helper functions + +fn with_statistics_exactness(stats: Statistics, min_exact: bool, max_exact: bool) -> Statistics { + match stats { + Statistics::Boolean(v) => { + Statistics::Boolean(v.with_min_is_exact(min_exact).with_max_is_exact(max_exact)) + } + Statistics::Int32(v) => { + Statistics::Int32(v.with_min_is_exact(min_exact).with_max_is_exact(max_exact)) + } + Statistics::Int64(v) => { + Statistics::Int64(v.with_min_is_exact(min_exact).with_max_is_exact(max_exact)) + } + Statistics::Int96(v) => { + Statistics::Int96(v.with_min_is_exact(min_exact).with_max_is_exact(max_exact)) + } + Statistics::Float(v) => { + Statistics::Float(v.with_min_is_exact(min_exact).with_max_is_exact(max_exact)) + } + Statistics::Double(v) => { + Statistics::Double(v.with_min_is_exact(min_exact).with_max_is_exact(max_exact)) + } + Statistics::ByteArray(v) => { + Statistics::ByteArray(v.with_min_is_exact(min_exact).with_max_is_exact(max_exact)) + } + Statistics::FixedLenByteArray(v) => { + Statistics::FixedLenByteArray(v.with_min_is_exact(min_exact).with_max_is_exact(max_exact)) + } + } +} + +fn convert_type_to_fb(t: Type) -> fb::Type { + match t { + Type::BOOLEAN => fb::Type::BOOLEAN, + Type::INT32 => fb::Type::INT32, + Type::INT64 => fb::Type::INT64, + Type::INT96 => fb::Type::INT96, + Type::FLOAT => fb::Type::FLOAT, + Type::DOUBLE => fb::Type::DOUBLE, + Type::BYTE_ARRAY => fb::Type::BYTE_ARRAY, + Type::FIXED_LEN_BYTE_ARRAY => fb::Type::FIXED_LEN_BYTE_ARRAY, + } +} + +#[cfg(test)] +fn convert_type_from_fb(t: fb::Type) -> Type { + match t { + fb::Type::BOOLEAN => Type::BOOLEAN, + fb::Type::INT32 => Type::INT32, + fb::Type::INT64 => Type::INT64, + fb::Type::INT96 => Type::INT96, + fb::Type::FLOAT => Type::FLOAT, + fb::Type::DOUBLE => Type::DOUBLE, + fb::Type::BYTE_ARRAY => Type::BYTE_ARRAY, + fb::Type::FIXED_LEN_BYTE_ARRAY => Type::FIXED_LEN_BYTE_ARRAY, + _ => Type::BYTE_ARRAY, // Default fallback + } +} + +fn convert_repetition_to_fb(r: Repetition) -> fb::FieldRepetitionType { + match r { + Repetition::REQUIRED => fb::FieldRepetitionType::REQUIRED, + Repetition::OPTIONAL => fb::FieldRepetitionType::OPTIONAL, + Repetition::REPEATED => fb::FieldRepetitionType::REPEATED, + } +} + +fn convert_compression_to_fb(c: Compression) -> fb::CompressionCodec { + match c { + Compression::UNCOMPRESSED => fb::CompressionCodec::UNCOMPRESSED, + Compression::SNAPPY => fb::CompressionCodec::SNAPPY, + Compression::GZIP(_) => fb::CompressionCodec::GZIP, + Compression::LZO => fb::CompressionCodec::LZO, + Compression::BROTLI(_) => fb::CompressionCodec::BROTLI, + Compression::ZSTD(_) => fb::CompressionCodec::ZSTD, + Compression::LZ4_RAW => fb::CompressionCodec::LZ4_RAW, + Compression::LZ4 => fb::CompressionCodec::LZ4_RAW, // LZ4 maps to LZ4_RAW + } +} + +fn convert_compression_from_fb(c: fb::CompressionCodec) -> Compression { + match c { + fb::CompressionCodec::UNCOMPRESSED => Compression::UNCOMPRESSED, + fb::CompressionCodec::SNAPPY => Compression::SNAPPY, + fb::CompressionCodec::GZIP => Compression::GZIP(Default::default()), + fb::CompressionCodec::LZO => Compression::LZO, + fb::CompressionCodec::BROTLI => Compression::BROTLI(Default::default()), + fb::CompressionCodec::ZSTD => Compression::ZSTD(Default::default()), + fb::CompressionCodec::LZ4_RAW => Compression::LZ4_RAW, + _ => Compression::UNCOMPRESSED, // Default fallback + } +} + +fn convert_time_unit_to_fb(unit: &crate::basic::TimeUnit) -> fb::TimeUnit { + match unit { + crate::basic::TimeUnit::MILLIS => fb::TimeUnit::MILLIS, + crate::basic::TimeUnit::MICROS => fb::TimeUnit::MICROS, + crate::basic::TimeUnit::NANOS => fb::TimeUnit::NANOS, + } +} + +fn convert_edge_interpolation_to_fb( + algo: crate::basic::EdgeInterpolationAlgorithm, +) -> fb::EdgeInterpolationAlgorithm { + match algo { + crate::basic::EdgeInterpolationAlgorithm::SPHERICAL => { + fb::EdgeInterpolationAlgorithm::SPHERICAL + } + crate::basic::EdgeInterpolationAlgorithm::VINCENTY => { + fb::EdgeInterpolationAlgorithm::VINCENTY + } + crate::basic::EdgeInterpolationAlgorithm::THOMAS => fb::EdgeInterpolationAlgorithm::THOMAS, + crate::basic::EdgeInterpolationAlgorithm::ANDOYER => { + fb::EdgeInterpolationAlgorithm::ANDOYER + } + crate::basic::EdgeInterpolationAlgorithm::KARNEY => fb::EdgeInterpolationAlgorithm::KARNEY, + crate::basic::EdgeInterpolationAlgorithm::_Unknown(_) => { + fb::EdgeInterpolationAlgorithm::SPHERICAL + } + } +} + +/// Convert ParquetMetaData to FlatBuffers format +pub fn parquet_metadata_to_flatbuf(metadata: &ParquetMetaData) -> Vec { + ThriftToFlatBufferConverter::new(metadata).convert() +} + +/// Convert FlatBuffers format back to ParquetMetaData +pub fn flatbuf_to_parquet_metadata( + buf: &[u8], + schema_descr: SchemaDescPtr, +) -> Result { + FlatBufferConverter::convert(buf, schema_descr) +} + +// ============================================================================ +// Thrift Extension Embedding +// ============================================================================ +// +// The FlatBuffer metadata can be embedded into the Thrift footer as a binary +// extension field (ID 32767) following the Parquet Binary Protocol Extensions: +// https://github.com/apache/parquet-format/blob/master/BinaryProtocolExtensions.md +// +// Extension format: +// +-------------------+------------+--------------------------------------+----------------+---------+--------------------------------+------+ +// | compress(flatbuf) | compressor | crc(compress(flatbuf) .. compressor) | compressed_len | raw_len | crc(compressed_len .. raw_len) | UUID | +// +-------------------+------------+--------------------------------------+----------------+---------+--------------------------------+------+ + +/// UUID marker for the FlatBuffer extension +const EXT_UUID: [u8; 16] = [ + 0xde, 0xad, 0xbe, 0xef, 0xde, 0xad, 0xbe, 0xef, 0xde, 0xad, 0xbe, 0xef, 0xde, 0xad, 0xbe, 0xef, +]; + +/// Minimum compression ratio to use compression (1.2x) +const MIN_COMPRESSION_RATIO: f64 = 1.2; + +/// Compression codec for the extension +#[repr(u8)] +#[derive(Clone, Copy, Debug, PartialEq)] +enum ExtCompressionCodec { + Uncompressed = 0, + Lz4Raw = 7, +} + +/// Pack a FlatBuffer with optional LZ4 compression and checksums. +/// +/// Returns the packed data in the extension format. +fn pack_flatbuffer(flatbuf: &[u8]) -> Vec { + // Try LZ4 compression + #[cfg(feature = "lz4")] + let (compressed, ext_codec) = { + use crate::compression::create_codec; + + let codec_impl = create_codec(Compression::LZ4_RAW, &Default::default()); + match codec_impl { + Ok(Some(mut codec)) => { + let mut compressed = Vec::new(); + match codec.compress(flatbuf, &mut compressed) { + Ok(()) => { + let ratio = flatbuf.len() as f64 / compressed.len() as f64; + if ratio >= MIN_COMPRESSION_RATIO { + (compressed, ExtCompressionCodec::Lz4Raw) + } else { + (flatbuf.to_vec(), ExtCompressionCodec::Uncompressed) + } + } + Err(_) => (flatbuf.to_vec(), ExtCompressionCodec::Uncompressed), + } + } + _ => (flatbuf.to_vec(), ExtCompressionCodec::Uncompressed), + } + }; + + #[cfg(not(feature = "lz4"))] + let (compressed, ext_codec) = (flatbuf.to_vec(), ExtCompressionCodec::Uncompressed); + + let compressed_len = compressed.len(); + let raw_len = flatbuf.len(); + + // Build the extension: compressed_data + compressor + crc32 + compressed_len + raw_len + len_crc32 + UUID + let mut out = Vec::with_capacity(compressed_len + 33); + out.extend_from_slice(&compressed); + out.push(ext_codec as u8); + + // CRC32 of (compressed_data .. compressor) + let data_crc = crc32fast::hash(&out); + out.extend_from_slice(&data_crc.to_le_bytes()); + + // compressed_len (4 bytes LE) + out.extend_from_slice(&(compressed_len as u32).to_le_bytes()); + + // raw_len (4 bytes LE) + out.extend_from_slice(&(raw_len as u32).to_le_bytes()); + + // CRC32 of (compressed_len .. raw_len) + let len_crc = crc32fast::hash(&out[out.len() - 8..]); + out.extend_from_slice(&len_crc.to_le_bytes()); + + // UUID marker + out.extend_from_slice(&EXT_UUID); + + out +} + +/// Write a ULEB128-encoded 64-bit value +fn write_uleb64(mut v: u64, out: &mut Vec) { + loop { + let byte = (v & 0x7F) as u8; + v >>= 7; + if v == 0 { + out.push(byte); + return; + } + out.push(byte | 0x80); + } +} + +/// Calculate ULEB128 encoded length of a 32-bit value +fn uleb32_len(v: u32) -> usize { + if v == 0 { + return 1; + } + let bits = 32 - v.leading_zeros(); + bits.div_ceil(7) as usize +} + +/// Append a FlatBuffer as an extended field to Thrift-serialized metadata. +/// +/// The FlatBuffer is compressed with LZ4, packed with checksums and metadata, +/// then appended as a Thrift binary field (ID 32767) followed by a stop field. +/// +/// # Arguments +/// * `flatbuffer` - The FlatBuffer data to append +/// * `thrift` - The Thrift-serialized metadata buffer to append to +pub fn append_flatbuffer(flatbuffer: &[u8], thrift: &mut Vec) { + let packed = pack_flatbuffer(flatbuffer); + + const FIELD_ID: u32 = 32767; + let header_size = 1 + uleb32_len(FIELD_ID) + uleb32_len(packed.len() as u32); + + let old_size = thrift.len(); + thrift.reserve(header_size + packed.len() + 1); + + // Write binary type indicator (0x08 in Thrift compact protocol) + thrift.push(0x08); + + // Write field ID as ULEB128 + write_uleb64(FIELD_ID as u64, thrift); + + // Write size as ULEB128 + write_uleb64(packed.len() as u64, thrift); + + // Copy the packed payload + thrift.extend_from_slice(&packed); + + // Add stop field + thrift.push(0x00); + + debug_assert_eq!(thrift.len(), old_size + header_size + packed.len() + 1); +} + +/// Result of extracting a FlatBuffer from a Parquet footer +#[derive(Debug)] +pub enum ExtractResult { + /// FlatBuffer was found and extracted + Found { + /// The extracted FlatBuffer data + flatbuffer: Vec, + /// The size of the extension in the footer (for trimming) + extension_size: usize, + }, + /// No FlatBuffer extension present + NotFound, + /// Buffer is too small, need at least this many bytes + NeedMoreBytes(usize), +} + +/// Extract a FlatBuffer from a Parquet file footer buffer. +/// +/// The buffer should contain the footer metadata ending with the Parquet magic bytes. +/// +/// # Arguments +/// * `buf` - Buffer containing the Parquet footer +/// +/// # Returns +/// * `ExtractResult::Found` if a FlatBuffer extension was found +/// * `ExtractResult::NotFound` if no extension present +/// * `ExtractResult::NeedMoreBytes` if the buffer is too small +pub fn extract_flatbuffer(buf: &[u8]) -> Result { + if buf.len() < 8 { + return Ok(ExtractResult::NeedMoreBytes(8)); + } + + // Check magic bytes + let magic = &buf[buf.len() - 4..]; + if magic != b"PAR1" { + if magic == b"PARE" { + return Err(ParquetError::NYI( + "FlatBuffer extraction doesn't support encrypted footer".to_string(), + )); + } + return Err(ParquetError::General( + "Invalid Parquet magic number".to_string(), + )); + } + + // Read metadata length + let md_len = u32::from_le_bytes(buf[buf.len() - 8..buf.len() - 4].try_into().unwrap()) as usize; + + if md_len < 34 { + return Ok(ExtractResult::NotFound); + } + + // Need at least 42 bytes: 34 (metadata3 trailer) + 8 (len + PAR1) + if buf.len() < 42 { + return Ok(ExtractResult::NeedMoreBytes(42)); + } + + // Check for UUID marker at the expected position + let trailer_start = buf.len() - 42; + let uuid_pos = trailer_start + 17; + if buf[uuid_pos..uuid_pos + 16] != EXT_UUID { + return Ok(ExtractResult::NotFound); + } + + // Parse extension trailer + let p = trailer_start; + let compressor = buf[p]; + let data_crc = u32::from_le_bytes(buf[p + 1..p + 5].try_into().unwrap()); + let compressed_len = u32::from_le_bytes(buf[p + 5..p + 9].try_into().unwrap()) as usize; + let raw_len = u32::from_le_bytes(buf[p + 9..p + 13].try_into().unwrap()) as usize; + let len_crc = u32::from_le_bytes(buf[p + 13..p + 17].try_into().unwrap()); + + // Verify length CRC + let expected_len_crc = crc32fast::hash(&buf[p + 5..p + 13]); + if len_crc != expected_len_crc { + return Err(ParquetError::General( + "FlatBuffer extension length CRC mismatch".to_string(), + )); + } + + // Check we have enough data for the compressed payload + if trailer_start < compressed_len || buf.len() < compressed_len + 42 { + return Ok(ExtractResult::NeedMoreBytes(compressed_len + 42)); + } + let data_start = trailer_start - compressed_len; + + // Verify data CRC (includes data + compressor byte) + let expected_data_crc = crc32fast::hash(&buf[data_start..p + 1]); + if data_crc != expected_data_crc { + return Err(ParquetError::General( + "FlatBuffer extension data CRC mismatch".to_string(), + )); + } + + // Decompress if needed + let decompressed = match compressor { + 0 => { + // Uncompressed + if compressed_len != raw_len { + return Err(ParquetError::General( + "Uncompressed extension length mismatch".to_string(), + )); + } + buf[data_start..data_start + compressed_len].to_vec() + } + 7 => { + // LZ4_RAW + #[cfg(feature = "lz4")] + { + use crate::compression::create_codec; + + let mut decompressed = Vec::new(); + let mut codec = create_codec(Compression::LZ4_RAW, &Default::default())? + .ok_or_else(|| ParquetError::General("LZ4 codec not available".to_string()))?; + let actual_len = codec.decompress( + &buf[data_start..data_start + compressed_len], + &mut decompressed, + Some(raw_len), + )?; + if actual_len != raw_len { + return Err(ParquetError::General(format!( + "LZ4 decompression size mismatch: expected {}, got {}", + raw_len, actual_len + ))); + } + decompressed + } + #[cfg(not(feature = "lz4"))] + { + return Err(ParquetError::General( + "LZ4 decompression not available (lz4 feature not enabled)".to_string(), + )); + } + } + _ => { + return Err(ParquetError::General(format!( + "Unsupported FlatBuffer compression codec: {}", + compressor + ))); + } + }; + + // Verify FlatBuffer + if fb::root_as_file_meta_data(&decompressed).is_err() { + return Err(ParquetError::General( + "FlatBuffer verification failed".to_string(), + )); + } + + Ok(ExtractResult::Found { + flatbuffer: decompressed, + extension_size: compressed_len + 42, + }) +} + +#[cfg(test)] +mod tests { + use super::*; + use crate::basic::{ColumnOrder, SortOrder, Type as PhysicalType}; + use crate::file::statistics::ValueStatistics; + use crate::schema::parser::parse_message_type; + + fn test_schema() -> SchemaDescPtr { + let schema_str = " + message test_schema { + REQUIRED INT32 id; + OPTIONAL BYTE_ARRAY name (UTF8); + REQUIRED INT64 timestamp; + } + "; + let schema = parse_message_type(schema_str).unwrap(); + Arc::new(SchemaDescriptor::new(Arc::new(schema))) + } + + #[test] + fn test_pack_unpack_int32_stats() { + let min = 42i32.to_le_bytes().to_vec(); + let max = 100i32.to_le_bytes().to_vec(); + + let packed = pack_statistics(PhysicalType::INT32, &min, true, &max, true); + + assert_eq!(packed.min.lo4, 42); + assert_eq!(packed.max.lo4, 100); + assert_eq!(packed.min.len, 4); + assert_eq!(packed.max.len, 4); + + let unpacked = unpack_statistics(PhysicalType::INT32, &packed).unwrap(); + assert_eq!(unpacked.0, min); + assert_eq!(unpacked.2, max); + } + + #[test] + fn test_pack_unpack_int64_stats() { + let min = 42i64.to_le_bytes().to_vec(); + let max = 100i64.to_le_bytes().to_vec(); + + let packed = pack_statistics(PhysicalType::INT64, &min, true, &max, true); + + assert_eq!(packed.min.lo8, 42); + assert_eq!(packed.max.lo8, 100); + assert_eq!(packed.min.len, 8); + assert_eq!(packed.max.len, 8); + + let unpacked = unpack_statistics(PhysicalType::INT64, &packed).unwrap(); + assert_eq!(unpacked.0, min); + assert_eq!(unpacked.2, max); + } + + #[test] + fn test_type_conversion() { + assert_eq!( + convert_type_from_fb(convert_type_to_fb(Type::BOOLEAN)), + Type::BOOLEAN + ); + assert_eq!( + convert_type_from_fb(convert_type_to_fb(Type::INT32)), + Type::INT32 + ); + assert_eq!( + convert_type_from_fb(convert_type_to_fb(Type::INT64)), + Type::INT64 + ); + assert_eq!( + convert_type_from_fb(convert_type_to_fb(Type::FLOAT)), + Type::FLOAT + ); + assert_eq!( + convert_type_from_fb(convert_type_to_fb(Type::DOUBLE)), + Type::DOUBLE + ); + } + + #[test] + fn test_compression_conversion() { + assert_eq!( + convert_compression_from_fb(convert_compression_to_fb(Compression::UNCOMPRESSED)), + Compression::UNCOMPRESSED + ); + assert_eq!( + convert_compression_from_fb(convert_compression_to_fb(Compression::SNAPPY)), + Compression::SNAPPY + ); + } + + #[test] + fn test_metadata_roundtrip() { + use crate::file::metadata::{ + ColumnChunkMetaDataBuilder, FileMetaData, ParquetMetaDataBuilder, + RowGroupMetaDataBuilder, + }; + + // Create a test schema + let schema_descr = test_schema(); + + // Build a simple FileMetaData + let file_meta = FileMetaData::new( + 2, // version + 1000, // num_rows + Some("test-created-by".to_string()), + Some(vec![KeyValue { + key: "test-key".to_string(), + value: Some("test-value".to_string()), + }]), + schema_descr.clone(), + None, // column_orders + ); + + // Build a row group with column chunks + let mut rg_builder = RowGroupMetaDataBuilder::new(schema_descr.clone()) + .set_num_rows(1000) + .set_total_byte_size(10000) + .set_ordinal(7); + + // Add column chunks for each column + for i in 0..schema_descr.num_columns() { + let col_descr = schema_descr.column(i); + let cc = ColumnChunkMetaDataBuilder::new(col_descr) + .set_compression(Compression::SNAPPY) + .set_num_values(1000) + .set_total_compressed_size(1000) + .set_total_uncompressed_size(2000) + .set_data_page_offset(1000 + (i as i64 * 1000)) + .build() + .unwrap(); + rg_builder = rg_builder.add_column_metadata(cc); + } + let row_group = rg_builder.build().unwrap(); + + // Create ParquetMetaData + let original_metadata = ParquetMetaDataBuilder::new(file_meta) + .add_row_group(row_group) + .build(); + + // Convert to FlatBuffers + let fb_bytes = parquet_metadata_to_flatbuf(&original_metadata); + + // Verify it was serialized + assert!(!fb_bytes.is_empty()); + + // Convert back from FlatBuffers + let converted_metadata = + flatbuf_to_parquet_metadata(&fb_bytes, schema_descr.clone()).unwrap(); + + // Verify basic metadata fields + assert_eq!( + original_metadata.file_metadata().version(), + converted_metadata.file_metadata().version() + ); + assert_eq!( + original_metadata.file_metadata().num_rows(), + converted_metadata.file_metadata().num_rows() + ); + assert_eq!( + original_metadata.file_metadata().created_by(), + converted_metadata.file_metadata().created_by() + ); + assert_eq!( + original_metadata.file_metadata().column_orders(), + converted_metadata.file_metadata().column_orders() + ); + + // Verify row group count + assert_eq!( + original_metadata.num_row_groups(), + converted_metadata.num_row_groups() + ); + + // Verify row group details + let orig_rg = original_metadata.row_group(0); + let conv_rg = converted_metadata.row_group(0); + assert_eq!(orig_rg.num_rows(), conv_rg.num_rows()); + assert_eq!(orig_rg.num_columns(), conv_rg.num_columns()); + assert_eq!(orig_rg.ordinal(), conv_rg.ordinal()); + + // Verify column chunk details + for i in 0..orig_rg.num_columns() { + let orig_cc = orig_rg.column(i); + let conv_cc = conv_rg.column(i); + assert_eq!(orig_cc.compression(), conv_cc.compression()); + assert_eq!(orig_cc.num_values(), conv_cc.num_values()); + assert_eq!(orig_cc.compressed_size(), conv_cc.compressed_size()); + assert_eq!(orig_cc.uncompressed_size(), conv_cc.uncompressed_size()); + assert_eq!(orig_cc.data_page_offset(), conv_cc.data_page_offset()); + } + } + + #[test] + fn test_metadata_roundtrip_with_column_orders() { + use crate::file::metadata::{ + ColumnChunkMetaDataBuilder, FileMetaData, ParquetMetaDataBuilder, + RowGroupMetaDataBuilder, + }; + + let schema_descr = test_schema(); + let file_meta = FileMetaData::new( + 2, + 1000, + Some("test-created-by".to_string()), + None, + schema_descr.clone(), + Some(vec![ + ColumnOrder::UNDEFINED, + ColumnOrder::TYPE_DEFINED_ORDER(SortOrder::UNSIGNED), + ColumnOrder::TYPE_DEFINED_ORDER(SortOrder::SIGNED), + ]), + ); + + let mut rg_builder = RowGroupMetaDataBuilder::new(schema_descr.clone()) + .set_num_rows(1000) + .set_total_byte_size(10000); + + for i in 0..schema_descr.num_columns() { + let col_descr = schema_descr.column(i); + let cc = ColumnChunkMetaDataBuilder::new(col_descr) + .set_compression(Compression::SNAPPY) + .set_num_values(1000) + .set_total_compressed_size(1000) + .set_total_uncompressed_size(2000) + .set_data_page_offset(1000 + (i as i64 * 1000)) + .build() + .unwrap(); + rg_builder = rg_builder.add_column_metadata(cc); + } + let row_group = rg_builder.build().unwrap(); + + let original_metadata = ParquetMetaDataBuilder::new(file_meta) + .add_row_group(row_group) + .build(); + + let fb_bytes = parquet_metadata_to_flatbuf(&original_metadata); + let converted_metadata = flatbuf_to_parquet_metadata(&fb_bytes, schema_descr).unwrap(); + + assert_eq!( + original_metadata.file_metadata().column_orders(), + converted_metadata.file_metadata().column_orders() + ); + assert_eq!( + converted_metadata.file_metadata().column_order(1), + ColumnOrder::TYPE_DEFINED_ORDER(SortOrder::UNSIGNED) + ); + } + + #[test] + fn test_metadata_roundtrip_preserves_stats_exactness() { + use crate::file::metadata::{ + ColumnChunkMetaDataBuilder, FileMetaData, ParquetMetaDataBuilder, + RowGroupMetaDataBuilder, + }; + + let schema_descr = test_schema(); + let file_meta = FileMetaData::new(2, 1000, None, None, schema_descr.clone(), None); + + let mut rg_builder = RowGroupMetaDataBuilder::new(schema_descr.clone()) + .set_num_rows(1000) + .set_total_byte_size(10000); + + for i in 0..schema_descr.num_columns() { + let col_descr = schema_descr.column(i); + let mut cc_builder = ColumnChunkMetaDataBuilder::new(col_descr) + .set_compression(Compression::SNAPPY) + .set_num_values(1000) + .set_total_compressed_size(1000) + .set_total_uncompressed_size(2000) + .set_data_page_offset(1000 + (i as i64 * 1000)); + + if i == 0 { + let stats = Statistics::Int32( + ValueStatistics::new(Some(10), Some(20), None, Some(0), true) + .with_min_is_exact(false) + .with_max_is_exact(true), + ); + cc_builder = cc_builder.set_statistics(stats); + } + + let cc = cc_builder.build().unwrap(); + rg_builder = rg_builder.add_column_metadata(cc); + } + let row_group = rg_builder.build().unwrap(); + + let original_metadata = ParquetMetaDataBuilder::new(file_meta) + .add_row_group(row_group) + .build(); + + let fb_bytes = parquet_metadata_to_flatbuf(&original_metadata); + let converted_metadata = flatbuf_to_parquet_metadata(&fb_bytes, schema_descr).unwrap(); + + let orig_stats = original_metadata.row_group(0).column(0).statistics().unwrap(); + let conv_stats = converted_metadata.row_group(0).column(0).statistics().unwrap(); + + assert_eq!(orig_stats.min_bytes_opt(), conv_stats.min_bytes_opt()); + assert_eq!(orig_stats.max_bytes_opt(), conv_stats.max_bytes_opt()); + assert_eq!(orig_stats.min_is_exact(), conv_stats.min_is_exact()); + assert_eq!(orig_stats.max_is_exact(), conv_stats.max_is_exact()); + } + + #[test] + fn test_pack_unpack_extension() { + // Create test data + let test_data = vec![0u8; 1000]; // Simple test buffer + + // Pack it + let packed = pack_flatbuffer(&test_data); + + // Verify the structure + assert!(packed.len() > 33); // At least: data + compressor + crc + len + len + crc + uuid + + // Check UUID is at the end + let uuid_start = packed.len() - 16; + assert_eq!(&packed[uuid_start..], &EXT_UUID); + } + + #[test] + fn test_append_flatbuffer() { + // Create a simple FlatBuffer + let fb_bytes = parquet_metadata_to_flatbuf(&create_test_metadata()); + + // Append to mock Thrift buffer + let mut thrift = vec![0x00]; // Mock thrift start + append_flatbuffer(&fb_bytes, &mut thrift); + + // Verify structure: original byte + header + packed + stop + assert!(thrift.len() > 1); + assert_eq!(thrift[thrift.len() - 1], 0x00); // Stop field + } + + #[test] + fn test_extract_flatbuffer_not_found() { + // Create a minimal valid Parquet footer without extension + let mut buf = vec![0u8; 12]; + buf[4..8].copy_from_slice(&4u32.to_le_bytes()); // md_len = 4 + buf[8..12].copy_from_slice(b"PAR1"); + + let result = extract_flatbuffer(&buf).unwrap(); + assert!(matches!(result, ExtractResult::NotFound)); + } + + #[test] + fn test_extract_flatbuffer_invalid_magic() { + let mut buf = vec![0u8; 12]; + buf[8..12].copy_from_slice(b"XXXX"); + + let result = extract_flatbuffer(&buf); + assert!(result.is_err()); + } + + #[test] + fn test_uleb_encoding() { + let mut out = Vec::new(); + + // Test small value + write_uleb64(127, &mut out); + assert_eq!(out, vec![127]); + + // Test value requiring two bytes + out.clear(); + write_uleb64(128, &mut out); + assert_eq!(out, vec![0x80, 0x01]); + + // Test larger value + out.clear(); + write_uleb64(16383, &mut out); + assert_eq!(out, vec![0xFF, 0x7F]); + } + + fn create_test_metadata() -> ParquetMetaData { + use crate::file::metadata::{ + ColumnChunkMetaDataBuilder, FileMetaData, ParquetMetaDataBuilder, + RowGroupMetaDataBuilder, + }; + + let schema_descr = test_schema(); + let file_meta = FileMetaData::new( + 2, + 100, + Some("test".to_string()), + None, + schema_descr.clone(), + None, + ); + + let mut rg_builder = RowGroupMetaDataBuilder::new(schema_descr.clone()) + .set_num_rows(100) + .set_total_byte_size(1000); + + for i in 0..schema_descr.num_columns() { + let col_descr = schema_descr.column(i); + let cc = ColumnChunkMetaDataBuilder::new(col_descr) + .set_compression(Compression::UNCOMPRESSED) + .set_num_values(100) + .set_total_compressed_size(100) + .set_total_uncompressed_size(100) + .set_data_page_offset(100 + (i as i64 * 100)) + .build() + .unwrap(); + rg_builder = rg_builder.add_column_metadata(cc); + } + let row_group = rg_builder.build().unwrap(); + + ParquetMetaDataBuilder::new(file_meta) + .add_row_group(row_group) + .build() + } +} diff --git a/parquet/src/file/metadata/flatbuf/mod.rs b/parquet/src/file/metadata/flatbuf/mod.rs new file mode 100644 index 000000000000..67dfe4b1d542 --- /dev/null +++ b/parquet/src/file/metadata/flatbuf/mod.rs @@ -0,0 +1,47 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the License for the +// specific language governing permissions and limitations +// under the License. + +//! FlatBuffers metadata support for Parquet files. +//! +//! This module provides an alternative, more efficient serialization format for +//! Parquet metadata using FlatBuffers instead of Thrift. +//! +//! The FlatBuffers format offers several advantages: +//! - Zero-copy deserialization +//! - Faster parsing than Thrift compact protocol +//! - Smaller metadata size in many cases +//! +//! # Usage +//! +//! This module is gated behind the `flatbuffers_metadata` feature flag. + +mod converter; + +#[allow( + unused_imports, + dead_code, + clippy::all, + missing_docs, + non_camel_case_types +)] +mod parquet_generated; + +pub use converter::{ + ExtractResult, append_flatbuffer, extract_flatbuffer, flatbuf_to_parquet_metadata, + parquet_metadata_to_flatbuf, +}; +pub use parquet_generated::parquet::format; diff --git a/parquet/src/file/metadata/flatbuf/parquet.fbs b/parquet/src/file/metadata/flatbuf/parquet.fbs new file mode 100644 index 000000000000..8406d5c0a90d --- /dev/null +++ b/parquet/src/file/metadata/flatbuf/parquet.fbs @@ -0,0 +1,604 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +namespace parquet.format; + +// The FlatBuffers footer preserves the same information as the Thrift Parquet footer, +// while removing duplicated fields, unused details, and inefficient encodings that +// waste space and memory. +// It can currently be attached as a footer extension, and may fully replace the +// Thrift footer in the future. +// +// Optimization notes: +// 1. Statistics use fixed-width integral types when possible; otherwise they are +// encoded as prefix + suffix. +// 2. ColumnChunk file_path and file_offset are removed since they are unused. +// 3. ColumnMetaData.encoding_stats are removed and replaced by +// ColumnMetaData.is_fully_dict_encoded. +// 4. ColumnMetaData.path_in_schema is removed since it can be derived from the schema. +// 5. ConvertedType is fully dropped as it is superseded by LogicalType. +// 6. Offset and column indexes are removed since they are small and their offsets +// alone take comparable space. + +/** + * Types supported by Parquet. These types are intended to be used in combination + * with the encodings to control the on disk storage format. + * For example INT16 is not included as a type since a good encoding of INT32 + * would handle this. + */ +enum Type : byte { + BOOLEAN = 0, + INT32 = 1, + INT64 = 2, + INT96 = 3, // deprecated, new Parquet writers should not write data in INT96 + FLOAT = 4, + DOUBLE = 5, + BYTE_ARRAY = 6, + FIXED_LEN_BYTE_ARRAY = 7, +} + +/** + * Representation of Schemas + */ +enum FieldRepetitionType : byte { + /** This field is required (can not be null) and each row has exactly 1 value. */ + REQUIRED = 0, + + /** The field is optional (can be null) and each row has 0 or 1 values. */ + OPTIONAL = 1, + + /** The field is repeated and can contain 0 or more values */ + REPEATED = 2, +} + +/** + * Encodings supported by Parquet. Not all encodings are valid for all types. These + * enums are also used to specify the encoding of definition and repetition levels. + * See the accompanying doc for the details of the more complicated encodings. + * Note: Match the thrift enum values so that we can cast between them. + */ +enum Encoding : byte { + /** Default encoding. + * BOOLEAN - 1 bit per value. 0 is false; 1 is true. + * INT32 - 4 bytes per value. Stored as little-endian. + * INT64 - 8 bytes per value. Stored as little-endian. + * FLOAT - 4 bytes per value. IEEE. Stored as little-endian. + * DOUBLE - 8 bytes per value. IEEE. Stored as little-endian. + * BYTE_ARRAY - 4 byte length stored as little endian, followed by bytes. + * FIXED_LEN_BYTE_ARRAY - Just the bytes. + */ + PLAIN = 0, + + /** Group VarInt encoding for INT32/INT64. + * This encoding is deprecated. It was never used + */ + // GROUP_VAR_INT = 1, + + /** + * Deprecated: Dictionary encoding. The values in the dictionary are encoded in the + * plain type. + * in a data page use RLE_DICTIONARY instead. + * in a Dictionary page use PLAIN instead + */ + PLAIN_DICTIONARY = 2, + + /** Group packed run length encoding. Usable for definition/repetition levels + * encoding and Booleans (on one bit: 0 is false; 1 is true.) + */ + RLE = 3, + + /** Bit packed encoding. This can only be used if the data has a known max + * width. Usable for definition/repetition levels encoding. + * This encoding is deprecated and is replaced by the RLE/bit-packing hybrid encoding. + */ + // BIT_PACKED = 4, + + /** Delta encoding for integers. This can be used for int columns and works best + * on sorted data + */ + DELTA_BINARY_PACKED = 5, + + /** Encoding for byte arrays to separate the length values and the data. The lengths + * are encoded using DELTA_BINARY_PACKED + */ + DELTA_LENGTH_BYTE_ARRAY = 6, + + /** Incremental-encoded byte array. Prefix lengths are encoded using DELTA_BINARY_PACKED. + * Suffixes are stored as delta length byte arrays. + */ + DELTA_BYTE_ARRAY = 7, + + /** Dictionary encoding: the ids are encoded using the RLE encoding + */ + RLE_DICTIONARY = 8, + + /** Encoding for fixed-width data (FLOAT, DOUBLE, INT32, INT64, FIXED_LEN_BYTE_ARRAY). + K byte-streams are created where K is the size in bytes of the data type. + The individual bytes of a value are scattered to the corresponding stream and + the streams are concatenated. + This itself does not reduce the size of the data but can lead to better compression + afterwards. + + Added in 2.8 for FLOAT and DOUBLE. + Support for INT32, INT64 and FIXED_LEN_BYTE_ARRAY added in 2.11. + */ + BYTE_STREAM_SPLIT = 9, +} + +/** + * Supported compression algorithms. + * + * Codecs added in format version X.Y can be read by readers based on X.Y and later. + * Codec support may vary between readers based on the format version and + * libraries available at runtime. + * + * See Compression.md for a detailed specification of these algorithms. + * Note: Match the thrift enum values so that we can cast between them. + */ +enum CompressionCodec : byte { + UNCOMPRESSED = 0, + SNAPPY = 1, + GZIP = 2, + LZO = 3, + BROTLI = 4, // Added in 2.4 + LZ4 = 5, // DEPRECATED (Added in 2.4) + ZSTD = 6, // Added in 2.4 + LZ4_RAW = 7, // Added in 2.9 +} + +/////////////////////////////////////////////////////////////////////////////////////////////////// +// Logical types. +/////////////////////////////////////////////////////////////////////////////////////////////////// + +table Empty {} + +/** + * Decimal logical type annotation + * + * Scale must be zero or a positive integer less than or equal to the precision. + * Precision must be a non-zero positive integer. + * + * To maintain forward-compatibility in v1, implementations using this logical + * type must also set scale and precision on the annotated SchemaElement. + * + * Allowed for physical types: INT32, INT64, FIXED_LEN_BYTE_ARRAY, and BYTE_ARRAY. + */ +table DecimalOptions { + precision: int; + scale: int; +} + +/** Time units for logical types */ +enum TimeUnit : byte { + MILLIS = 0, + MICROS = 1, + NANOS = 2, +} + +/** + * Timestamp logical type annotation + * + * Allowed for physical types: INT64 + */ +table TimeOptions { + is_adjusted_to_utc: bool; + unit: TimeUnit; +} + +/** + * Integer logical type annotation + * + * bitWidth must be 8, 16, 32, or 64. + * + * Allowed for physical types: INT32, INT64 + */ +table IntOptions { + bit_width: byte = 8; + is_signed: bool; +} + +/** + * Embedded Variant logical type annotation + */ +table VariantType { + // The version of the variant specification that the variant was + // written with. + specification_version: byte = null; +} + +/** Edge interpolation algorithm for Geography logical type */ +enum EdgeInterpolationAlgorithm : byte { + SPHERICAL = 0, + VINCENTY = 1, + THOMAS = 2, + ANDOYER = 3, + KARNEY = 4, +} + +/** + * Embedded Geometry logical type annotation + * + * Geospatial features in the Well-Known Binary (WKB) format and edges interpolation + * is always linear/planar. + * + * A custom CRS can be set by the crs field. If unset, it defaults to "OGC:CRS84", + * which means that the geometries must be stored in longitude, latitude based on + * the WGS84 datum. + * + * Allowed for physical type: BYTE_ARRAY. + * + * See Geospatial.md for details. + */ +table GeometryType { + crs: string; +} + +/** + * Embedded Geography logical type annotation + * + * Geospatial features in the WKB format with an explicit (non-linear/non-planar) + * edges interpolation algorithm. + * + * A custom geographic CRS can be set by the crs field, where longitudes are + * bound by [-180, 180] and latitudes are bound by [-90, 90]. If unset, the CRS + * defaults to "OGC:CRS84". + * + * An optional algorithm can be set to correctly interpret edges interpolation + * of the geometries. If unset, the algorithm defaults to SPHERICAL. + * + * Allowed for physical type: BYTE_ARRAY. + * + * See Geospatial.md for details. + */ +table GeographyType { + crs: string; + algorithm: EdgeInterpolationAlgorithm; +} + +/** + * LogicalType annotations to replace ConvertedType. + */ +union LogicalType { + StringType:Empty, + MapType:Empty, + ListType:Empty, + EnumType:Empty, + DecimalType:DecimalOptions, + DateType:Empty, + TimeType:TimeOptions, + TimestampType:TimeOptions, + IntType:IntOptions, + NullType:Empty, + JsonType:Empty, + BsonType:Empty, + UUIDType:Empty, + Float16Type:Empty, + VariantType:VariantType, + GeometryType:GeometryType, + GeographyType:GeographyType, +} + +table Statistics { + null_count: int = null; + // Store min/max values as fixed-width entities depending on the physical type. + // If min_len/max_len is present then the corresponding min/max value is present. + // + // - BOOLEAN: none + // - INT32/FLOAT: min_lo4/max_lo4 (little-endian, 4 bytes) + // - INT64/DOUBLE: min_lo8/max_lo8 (little-endian, 8 bytes) + // - INT96: lo4 contains the low 4 bytes, lo8 contains the high 8 bytes (little-endian, 12 bytes total) + // - FIXED_LEN_BYTE_ARRAY: + // - BYTE_ARRAY: + // prefix: the longest common prefix of min and max values + // lo8+hi8: zero-padded 16 bytes (big-endian) of the suffix after removing the prefix + // min_len/max_len: the length of the suffix of the original value after removing the prefix. + // If > 16 then the value stored in lo8+hi8 is a truncated approximation (inexact). + // If <= 16 then the value is exact. + // + // Example for BYTE_ARRAY with min="apple" and max="application": + // prefix = "appl" (longest common prefix) + // min suffix = "e" (1 byte), max suffix = "ication" (7 bytes) + // min_lo8 = big-endian encoding of "e" zero-padded to 16 bytes + // min_len = 1 (exact, since 1 <= 16) + // max_lo8 = big-endian encoding of "ication" zero-padded to 16 bytes + // max_len = 7 (exact, since 7 <= 16) + // + // Example for INT32 with min=42: + // min_lo4 = 0x2A000000 (42 in little-endian) + min_lo4: uint; + min_lo8: ulong; + min_hi8: ulong; + min_len: byte = null; + max_lo4: uint; + max_lo8: ulong; + max_hi8: ulong; + max_len: byte = null; + prefix: string; +} + +/** + * Bloom filter metadata for a column chunk. + */ +table BloomFilterInfo { + /** Byte offset from beginning of file to Bloom filter data. **/ + offset: long; + + /** Size of Bloom filter data including the serialized header, in bytes. + * Writers should write this field so readers can read the bloom filter + * in a single I/O. + */ + length: int; +} + +table AesGcmV1 { + /** AAD prefix **/ + aad_prefix: [byte]; + + /** Unique file identifier part of AAD suffix **/ + aad_file_unique: [byte]; + + /** In files encrypted with AAD prefix without storing it, + * readers must supply the prefix **/ + supply_aad_prefix: bool; +} + +table AesGcmCtrV1 { + /** AAD prefix **/ + aad_prefix: [byte]; + + /** Unique file identifier part of AAD suffix **/ + aad_file_unique: [byte]; + + /** In files encrypted with AAD prefix without storing it, + * readers must supply the prefix **/ + supply_aad_prefix: bool; +} + +union EncryptionAlgorithm { + AesGcmV1:AesGcmV1, + AesGcmCtrV1:AesGcmCtrV1, +} + +union ColumnOrder { + TypeDefinedOrder:Empty, +} + +/** + * Represents a element inside a schema definition. + * - if it is a group (inner node) then type is undefined and num_children is defined + * - if it is a primitive type (leaf) then type is defined and num_children is undefined + * the nodes are listed in depth first traversal order. + */ +table SchemaElement { + /** Name of the field in the schema */ + name: string; + + /** Data type for this field. Not set if the current element is a non-leaf node */ + type: Type = null; + + /** repetition of the field. The root of the schema does not have a repetition_type. + * All other nodes must have one */ + repetition_type: FieldRepetitionType; + + /** The logical type of this SchemaElement */ + logical_type: LogicalType; + + /** If type is FIXED_LEN_BYTE_ARRAY, this is the byte length of the values. + * Otherwise, if specified, this is the maximum bit length to store any of the values. + * (e.g. a low cardinality INT col could have this set to 3). Note that this is + * in the schema, and therefore fixed for the entire file. + */ + type_length: int = null; + + /** Nested fields. Since thrift does not support nested fields, + * the nesting is flattened to a single list by a depth-first traversal. + * The children count is used to construct the nested relationship. + * This field is not set when the element is a primitive type + */ + num_children: int = 0; + + /** When the original schema supports field ids, this will save the + * original field id in the parquet schema + */ + field_id: int = null; + column_order: ColumnOrder; // only present for leaf nodes +} + +enum PageType : byte { + DATA_PAGE = 0, + INDEX_PAGE = 1, + DICTIONARY_PAGE = 2, + DATA_PAGE_V2 = 3, +} + +table KeyValue { + key: string; + val: string; +} + +/** + * Description for column metadata + */ +table ColumnMetadata { + /** Compression codec **/ + codec: CompressionCodec; + + /** Number of values in this column, only present if not equal to rg.num_rows **/ + num_values: long = null; + + /** total byte size of all uncompressed pages in this column chunk (including the headers) **/ + total_uncompressed_size: long; + + /** total byte size of all compressed, and potentially encrypted, pages + * in this column chunk (including the headers) **/ + total_compressed_size: long; + + /** Optional key/value metadata **/ + key_value_metadata: [KeyValue]; + + /** Byte offset from beginning of file to first data page **/ + data_page_offset: long; + + /** Byte offset from beginning of file to root index page **/ + index_page_offset: long = null; + + /** Byte offset from the beginning of file to first (only) dictionary page **/ + dictionary_page_offset: long = null; + + /** optional statistics for this column chunk */ + statistics: Statistics; + + /** Indicates whether the column chunk pages are fully dictionary encoded. */ + is_fully_dict_encoded: bool; + + /** Optional Bloom filter information for this column chunk */ + bloom_filter: BloomFilterInfo; +} + +union ColumnCryptoMetadata { + EncryptionWithFooterKey:Empty, + EncryptionWithColumnKey:Empty, +} + +table ColumnChunk { + /** Column metadata for this chunk. + * Note: while marked as optional, this field is in fact required by most major + * Parquet implementations. As such, writers MUST populate this field. + **/ + meta_data: ColumnMetadata; + + /** Crypto metadata of encrypted columns **/ + crypto_metadata: ColumnCryptoMetadata; + + /** Encrypted column metadata for this chunk **/ + encrypted_column_metadata: [byte]; +} + +/** + * Sort order within a RowGroup of a leaf column + */ +table SortingColumn { + /** The ordinal position of the column (in this row group) **/ + column_idx: int; + + /** If true, indicates this column is sorted in descending order. **/ + descending: bool; + + /** If true, nulls will come before non-null values, otherwise, + * nulls go at the end. */ + nulls_first: bool; +} + +table RowGroup { + /** Metadata for each column chunk in this row group. + * This list must have the same order as the SchemaElement list in FileMetaData. + **/ + columns: [ColumnChunk]; + + /** Total byte size of all the uncompressed column data in this row group **/ + total_byte_size: long; + + /** Number of rows in this row group **/ + num_rows: long; + + /** If set, specifies a sort ordering of the rows in this RowGroup. + * The sorting columns can be a subset of all the columns. + */ + sorting_columns: [SortingColumn]; + + /** Byte offset from beginning of file to first page (data or dictionary) + * in this row group **/ + file_offset: long; + + /** Total byte size of all compressed (and potentially encrypted) column data + * in this row group **/ + total_compressed_size: long; + + /** Row group ordinal in the file **/ + ordinal: short = null; +} + +/** + * Crypto metadata for files with encrypted footer. + */ +table FileCryptoMetaData { + /** + * Encryption algorithm. This field is only used for files + * with encrypted footer. Files with plaintext footer store algorithm id + * inside footer (FileMetaData structure). + */ + encryption_algorithm: EncryptionAlgorithm; + + /** Retrieval metadata of key used for encryption of footer, + * and (possibly) columns **/ + key_metadata: [byte]; +} + +/** + * Description for file metadata + */ +table FileMetaData { + /** Version of this file + * + * As of December 2025, there is no agreed upon consensus of what constitutes + * version 2 of the file. For maximum compatibility with readers, writers should + * always populate "1" for version. For maximum compatibility with writers, + * readers should accept "1" and "2" interchangeably. All other versions are + * reserved for potential future use-cases. + */ + version: int; + + /** Parquet schema for this file. This schema contains metadata for all the columns. + * The schema is represented as a tree with a single root. The nodes of the tree + * are flattened to a list by doing a depth-first traversal. + * The column metadata contains the path in the schema for that column which can be + * used to map columns to nodes in the schema. + * The first element is the root **/ + schema: [SchemaElement]; + + /** Number of rows in this file **/ + num_rows: long; + + /** Row groups in this file **/ + row_groups: [RowGroup]; + + /** Optional key/value metadata **/ + kv: [KeyValue]; + + /** String for application that wrote this file. This should be in the format + * version (build ). + * e.g. impala version 1.0 (build 6cf94d29b2b7115df4de2c06e2ab4326d721eb55) + **/ + created_by: string; + + /** + * Encryption algorithm. This field is set only in encrypted files + * with plaintext footer. Files with encrypted footer store algorithm id + * in FileCryptoMetaData structure. + */ + encryption_algorithm: EncryptionAlgorithm; + + /** + * Retrieval metadata of key used for signing the footer. + * Used only in encrypted files with plaintext footer. + */ + footer_signing_key_metadata: [byte]; +} + +root_type FileMetaData; diff --git a/parquet/src/file/metadata/flatbuf/parquet_generated.rs b/parquet/src/file/metadata/flatbuf/parquet_generated.rs new file mode 100644 index 000000000000..8e0b52ae6efc --- /dev/null +++ b/parquet/src/file/metadata/flatbuf/parquet_generated.rs @@ -0,0 +1,5758 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the License for the +// specific language governing permissions and limitations +// under the License. + +// automatically generated by the FlatBuffers compiler, do not modify +// @generated +extern crate alloc; + +#[allow(unused_imports, dead_code)] +pub mod parquet { + + #[allow(unused_imports, dead_code)] + pub mod format { + + #[deprecated( + since = "2.0.0", + note = "Use associated constants instead. This will no longer be generated in 2021." + )] + pub const ENUM_MIN_TYPE: i8 = 0; + #[deprecated( + since = "2.0.0", + note = "Use associated constants instead. This will no longer be generated in 2021." + )] + pub const ENUM_MAX_TYPE: i8 = 7; + #[deprecated( + since = "2.0.0", + note = "Use associated constants instead. This will no longer be generated in 2021." + )] + #[allow(non_camel_case_types)] + pub const ENUM_VALUES_TYPE: [Type; 8] = [ + Type::BOOLEAN, + Type::INT32, + Type::INT64, + Type::INT96, + Type::FLOAT, + Type::DOUBLE, + Type::BYTE_ARRAY, + Type::FIXED_LEN_BYTE_ARRAY, + ]; + + #[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Default)] + #[repr(transparent)] + pub struct Type(pub i8); + #[allow(non_upper_case_globals)] + impl Type { + pub const BOOLEAN: Self = Self(0); + pub const INT32: Self = Self(1); + pub const INT64: Self = Self(2); + pub const INT96: Self = Self(3); + pub const FLOAT: Self = Self(4); + pub const DOUBLE: Self = Self(5); + pub const BYTE_ARRAY: Self = Self(6); + pub const FIXED_LEN_BYTE_ARRAY: Self = Self(7); + + pub const ENUM_MIN: i8 = 0; + pub const ENUM_MAX: i8 = 7; + pub const ENUM_VALUES: &'static [Self] = &[ + Self::BOOLEAN, + Self::INT32, + Self::INT64, + Self::INT96, + Self::FLOAT, + Self::DOUBLE, + Self::BYTE_ARRAY, + Self::FIXED_LEN_BYTE_ARRAY, + ]; + /// Returns the variant's name or "" if unknown. + pub fn variant_name(self) -> Option<&'static str> { + match self { + Self::BOOLEAN => Some("BOOLEAN"), + Self::INT32 => Some("INT32"), + Self::INT64 => Some("INT64"), + Self::INT96 => Some("INT96"), + Self::FLOAT => Some("FLOAT"), + Self::DOUBLE => Some("DOUBLE"), + Self::BYTE_ARRAY => Some("BYTE_ARRAY"), + Self::FIXED_LEN_BYTE_ARRAY => Some("FIXED_LEN_BYTE_ARRAY"), + _ => None, + } + } + } + impl ::core::fmt::Debug for Type { + fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { + if let Some(name) = self.variant_name() { + f.write_str(name) + } else { + f.write_fmt(format_args!("", self.0)) + } + } + } + impl<'a> ::flatbuffers::Follow<'a> for Type { + type Inner = Self; + #[inline] + unsafe fn follow(buf: &'a [u8], loc: usize) -> Self::Inner { + let b = unsafe { ::flatbuffers::read_scalar_at::(buf, loc) }; + Self(b) + } + } + + impl ::flatbuffers::Push for Type { + type Output = Type; + #[inline] + unsafe fn push(&self, dst: &mut [u8], _written_len: usize) { + unsafe { ::flatbuffers::emplace_scalar::(dst, self.0) }; + } + } + + impl ::flatbuffers::EndianScalar for Type { + type Scalar = i8; + #[inline] + fn to_little_endian(self) -> i8 { + self.0.to_le() + } + #[inline] + #[allow(clippy::wrong_self_convention)] + fn from_little_endian(v: i8) -> Self { + let b = i8::from_le(v); + Self(b) + } + } + + impl<'a> ::flatbuffers::Verifiable for Type { + #[inline] + fn run_verifier( + v: &mut ::flatbuffers::Verifier, + pos: usize, + ) -> Result<(), ::flatbuffers::InvalidFlatbuffer> { + i8::run_verifier(v, pos) + } + } + + impl ::flatbuffers::SimpleToVerifyInSlice for Type {} + #[deprecated( + since = "2.0.0", + note = "Use associated constants instead. This will no longer be generated in 2021." + )] + pub const ENUM_MIN_FIELD_REPETITION_TYPE: i8 = 0; + #[deprecated( + since = "2.0.0", + note = "Use associated constants instead. This will no longer be generated in 2021." + )] + pub const ENUM_MAX_FIELD_REPETITION_TYPE: i8 = 2; + #[deprecated( + since = "2.0.0", + note = "Use associated constants instead. This will no longer be generated in 2021." + )] + #[allow(non_camel_case_types)] + pub const ENUM_VALUES_FIELD_REPETITION_TYPE: [FieldRepetitionType; 3] = [ + FieldRepetitionType::REQUIRED, + FieldRepetitionType::OPTIONAL, + FieldRepetitionType::REPEATED, + ]; + + #[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Default)] + #[repr(transparent)] + pub struct FieldRepetitionType(pub i8); + #[allow(non_upper_case_globals)] + impl FieldRepetitionType { + pub const REQUIRED: Self = Self(0); + pub const OPTIONAL: Self = Self(1); + pub const REPEATED: Self = Self(2); + + pub const ENUM_MIN: i8 = 0; + pub const ENUM_MAX: i8 = 2; + pub const ENUM_VALUES: &'static [Self] = + &[Self::REQUIRED, Self::OPTIONAL, Self::REPEATED]; + /// Returns the variant's name or "" if unknown. + pub fn variant_name(self) -> Option<&'static str> { + match self { + Self::REQUIRED => Some("REQUIRED"), + Self::OPTIONAL => Some("OPTIONAL"), + Self::REPEATED => Some("REPEATED"), + _ => None, + } + } + } + impl ::core::fmt::Debug for FieldRepetitionType { + fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { + if let Some(name) = self.variant_name() { + f.write_str(name) + } else { + f.write_fmt(format_args!("", self.0)) + } + } + } + impl<'a> ::flatbuffers::Follow<'a> for FieldRepetitionType { + type Inner = Self; + #[inline] + unsafe fn follow(buf: &'a [u8], loc: usize) -> Self::Inner { + let b = unsafe { ::flatbuffers::read_scalar_at::(buf, loc) }; + Self(b) + } + } + + impl ::flatbuffers::Push for FieldRepetitionType { + type Output = FieldRepetitionType; + #[inline] + unsafe fn push(&self, dst: &mut [u8], _written_len: usize) { + unsafe { ::flatbuffers::emplace_scalar::(dst, self.0) }; + } + } + + impl ::flatbuffers::EndianScalar for FieldRepetitionType { + type Scalar = i8; + #[inline] + fn to_little_endian(self) -> i8 { + self.0.to_le() + } + #[inline] + #[allow(clippy::wrong_self_convention)] + fn from_little_endian(v: i8) -> Self { + let b = i8::from_le(v); + Self(b) + } + } + + impl<'a> ::flatbuffers::Verifiable for FieldRepetitionType { + #[inline] + fn run_verifier( + v: &mut ::flatbuffers::Verifier, + pos: usize, + ) -> Result<(), ::flatbuffers::InvalidFlatbuffer> { + i8::run_verifier(v, pos) + } + } + + impl ::flatbuffers::SimpleToVerifyInSlice for FieldRepetitionType {} + #[deprecated( + since = "2.0.0", + note = "Use associated constants instead. This will no longer be generated in 2021." + )] + pub const ENUM_MIN_ENCODING: i8 = 0; + #[deprecated( + since = "2.0.0", + note = "Use associated constants instead. This will no longer be generated in 2021." + )] + pub const ENUM_MAX_ENCODING: i8 = 9; + #[deprecated( + since = "2.0.0", + note = "Use associated constants instead. This will no longer be generated in 2021." + )] + #[allow(non_camel_case_types)] + pub const ENUM_VALUES_ENCODING: [Encoding; 8] = [ + Encoding::PLAIN, + Encoding::PLAIN_DICTIONARY, + Encoding::RLE, + Encoding::DELTA_BINARY_PACKED, + Encoding::DELTA_LENGTH_BYTE_ARRAY, + Encoding::DELTA_BYTE_ARRAY, + Encoding::RLE_DICTIONARY, + Encoding::BYTE_STREAM_SPLIT, + ]; + + #[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Default)] + #[repr(transparent)] + pub struct Encoding(pub i8); + #[allow(non_upper_case_globals)] + impl Encoding { + pub const PLAIN: Self = Self(0); + pub const PLAIN_DICTIONARY: Self = Self(2); + pub const RLE: Self = Self(3); + pub const DELTA_BINARY_PACKED: Self = Self(5); + pub const DELTA_LENGTH_BYTE_ARRAY: Self = Self(6); + pub const DELTA_BYTE_ARRAY: Self = Self(7); + pub const RLE_DICTIONARY: Self = Self(8); + pub const BYTE_STREAM_SPLIT: Self = Self(9); + + pub const ENUM_MIN: i8 = 0; + pub const ENUM_MAX: i8 = 9; + pub const ENUM_VALUES: &'static [Self] = &[ + Self::PLAIN, + Self::PLAIN_DICTIONARY, + Self::RLE, + Self::DELTA_BINARY_PACKED, + Self::DELTA_LENGTH_BYTE_ARRAY, + Self::DELTA_BYTE_ARRAY, + Self::RLE_DICTIONARY, + Self::BYTE_STREAM_SPLIT, + ]; + /// Returns the variant's name or "" if unknown. + pub fn variant_name(self) -> Option<&'static str> { + match self { + Self::PLAIN => Some("PLAIN"), + Self::PLAIN_DICTIONARY => Some("PLAIN_DICTIONARY"), + Self::RLE => Some("RLE"), + Self::DELTA_BINARY_PACKED => Some("DELTA_BINARY_PACKED"), + Self::DELTA_LENGTH_BYTE_ARRAY => Some("DELTA_LENGTH_BYTE_ARRAY"), + Self::DELTA_BYTE_ARRAY => Some("DELTA_BYTE_ARRAY"), + Self::RLE_DICTIONARY => Some("RLE_DICTIONARY"), + Self::BYTE_STREAM_SPLIT => Some("BYTE_STREAM_SPLIT"), + _ => None, + } + } + } + impl ::core::fmt::Debug for Encoding { + fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { + if let Some(name) = self.variant_name() { + f.write_str(name) + } else { + f.write_fmt(format_args!("", self.0)) + } + } + } + impl<'a> ::flatbuffers::Follow<'a> for Encoding { + type Inner = Self; + #[inline] + unsafe fn follow(buf: &'a [u8], loc: usize) -> Self::Inner { + let b = unsafe { ::flatbuffers::read_scalar_at::(buf, loc) }; + Self(b) + } + } + + impl ::flatbuffers::Push for Encoding { + type Output = Encoding; + #[inline] + unsafe fn push(&self, dst: &mut [u8], _written_len: usize) { + unsafe { ::flatbuffers::emplace_scalar::(dst, self.0) }; + } + } + + impl ::flatbuffers::EndianScalar for Encoding { + type Scalar = i8; + #[inline] + fn to_little_endian(self) -> i8 { + self.0.to_le() + } + #[inline] + #[allow(clippy::wrong_self_convention)] + fn from_little_endian(v: i8) -> Self { + let b = i8::from_le(v); + Self(b) + } + } + + impl<'a> ::flatbuffers::Verifiable for Encoding { + #[inline] + fn run_verifier( + v: &mut ::flatbuffers::Verifier, + pos: usize, + ) -> Result<(), ::flatbuffers::InvalidFlatbuffer> { + i8::run_verifier(v, pos) + } + } + + impl ::flatbuffers::SimpleToVerifyInSlice for Encoding {} + #[deprecated( + since = "2.0.0", + note = "Use associated constants instead. This will no longer be generated in 2021." + )] + pub const ENUM_MIN_COMPRESSION_CODEC: i8 = 0; + #[deprecated( + since = "2.0.0", + note = "Use associated constants instead. This will no longer be generated in 2021." + )] + pub const ENUM_MAX_COMPRESSION_CODEC: i8 = 7; + #[deprecated( + since = "2.0.0", + note = "Use associated constants instead. This will no longer be generated in 2021." + )] + #[allow(non_camel_case_types)] + pub const ENUM_VALUES_COMPRESSION_CODEC: [CompressionCodec; 8] = [ + CompressionCodec::UNCOMPRESSED, + CompressionCodec::SNAPPY, + CompressionCodec::GZIP, + CompressionCodec::LZO, + CompressionCodec::BROTLI, + CompressionCodec::LZ4, + CompressionCodec::ZSTD, + CompressionCodec::LZ4_RAW, + ]; + + #[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Default)] + #[repr(transparent)] + pub struct CompressionCodec(pub i8); + #[allow(non_upper_case_globals)] + impl CompressionCodec { + pub const UNCOMPRESSED: Self = Self(0); + pub const SNAPPY: Self = Self(1); + pub const GZIP: Self = Self(2); + pub const LZO: Self = Self(3); + pub const BROTLI: Self = Self(4); + pub const LZ4: Self = Self(5); + pub const ZSTD: Self = Self(6); + pub const LZ4_RAW: Self = Self(7); + + pub const ENUM_MIN: i8 = 0; + pub const ENUM_MAX: i8 = 7; + pub const ENUM_VALUES: &'static [Self] = &[ + Self::UNCOMPRESSED, + Self::SNAPPY, + Self::GZIP, + Self::LZO, + Self::BROTLI, + Self::LZ4, + Self::ZSTD, + Self::LZ4_RAW, + ]; + /// Returns the variant's name or "" if unknown. + pub fn variant_name(self) -> Option<&'static str> { + match self { + Self::UNCOMPRESSED => Some("UNCOMPRESSED"), + Self::SNAPPY => Some("SNAPPY"), + Self::GZIP => Some("GZIP"), + Self::LZO => Some("LZO"), + Self::BROTLI => Some("BROTLI"), + Self::LZ4 => Some("LZ4"), + Self::ZSTD => Some("ZSTD"), + Self::LZ4_RAW => Some("LZ4_RAW"), + _ => None, + } + } + } + impl ::core::fmt::Debug for CompressionCodec { + fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { + if let Some(name) = self.variant_name() { + f.write_str(name) + } else { + f.write_fmt(format_args!("", self.0)) + } + } + } + impl<'a> ::flatbuffers::Follow<'a> for CompressionCodec { + type Inner = Self; + #[inline] + unsafe fn follow(buf: &'a [u8], loc: usize) -> Self::Inner { + let b = unsafe { ::flatbuffers::read_scalar_at::(buf, loc) }; + Self(b) + } + } + + impl ::flatbuffers::Push for CompressionCodec { + type Output = CompressionCodec; + #[inline] + unsafe fn push(&self, dst: &mut [u8], _written_len: usize) { + unsafe { ::flatbuffers::emplace_scalar::(dst, self.0) }; + } + } + + impl ::flatbuffers::EndianScalar for CompressionCodec { + type Scalar = i8; + #[inline] + fn to_little_endian(self) -> i8 { + self.0.to_le() + } + #[inline] + #[allow(clippy::wrong_self_convention)] + fn from_little_endian(v: i8) -> Self { + let b = i8::from_le(v); + Self(b) + } + } + + impl<'a> ::flatbuffers::Verifiable for CompressionCodec { + #[inline] + fn run_verifier( + v: &mut ::flatbuffers::Verifier, + pos: usize, + ) -> Result<(), ::flatbuffers::InvalidFlatbuffer> { + i8::run_verifier(v, pos) + } + } + + impl ::flatbuffers::SimpleToVerifyInSlice for CompressionCodec {} + #[deprecated( + since = "2.0.0", + note = "Use associated constants instead. This will no longer be generated in 2021." + )] + pub const ENUM_MIN_TIME_UNIT: i8 = 0; + #[deprecated( + since = "2.0.0", + note = "Use associated constants instead. This will no longer be generated in 2021." + )] + pub const ENUM_MAX_TIME_UNIT: i8 = 2; + #[deprecated( + since = "2.0.0", + note = "Use associated constants instead. This will no longer be generated in 2021." + )] + #[allow(non_camel_case_types)] + pub const ENUM_VALUES_TIME_UNIT: [TimeUnit; 3] = + [TimeUnit::MILLIS, TimeUnit::MICROS, TimeUnit::NANOS]; + + #[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Default)] + #[repr(transparent)] + pub struct TimeUnit(pub i8); + #[allow(non_upper_case_globals)] + impl TimeUnit { + pub const MILLIS: Self = Self(0); + pub const MICROS: Self = Self(1); + pub const NANOS: Self = Self(2); + + pub const ENUM_MIN: i8 = 0; + pub const ENUM_MAX: i8 = 2; + pub const ENUM_VALUES: &'static [Self] = &[Self::MILLIS, Self::MICROS, Self::NANOS]; + /// Returns the variant's name or "" if unknown. + pub fn variant_name(self) -> Option<&'static str> { + match self { + Self::MILLIS => Some("MILLIS"), + Self::MICROS => Some("MICROS"), + Self::NANOS => Some("NANOS"), + _ => None, + } + } + } + impl ::core::fmt::Debug for TimeUnit { + fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { + if let Some(name) = self.variant_name() { + f.write_str(name) + } else { + f.write_fmt(format_args!("", self.0)) + } + } + } + impl<'a> ::flatbuffers::Follow<'a> for TimeUnit { + type Inner = Self; + #[inline] + unsafe fn follow(buf: &'a [u8], loc: usize) -> Self::Inner { + let b = unsafe { ::flatbuffers::read_scalar_at::(buf, loc) }; + Self(b) + } + } + + impl ::flatbuffers::Push for TimeUnit { + type Output = TimeUnit; + #[inline] + unsafe fn push(&self, dst: &mut [u8], _written_len: usize) { + unsafe { ::flatbuffers::emplace_scalar::(dst, self.0) }; + } + } + + impl ::flatbuffers::EndianScalar for TimeUnit { + type Scalar = i8; + #[inline] + fn to_little_endian(self) -> i8 { + self.0.to_le() + } + #[inline] + #[allow(clippy::wrong_self_convention)] + fn from_little_endian(v: i8) -> Self { + let b = i8::from_le(v); + Self(b) + } + } + + impl<'a> ::flatbuffers::Verifiable for TimeUnit { + #[inline] + fn run_verifier( + v: &mut ::flatbuffers::Verifier, + pos: usize, + ) -> Result<(), ::flatbuffers::InvalidFlatbuffer> { + i8::run_verifier(v, pos) + } + } + + impl ::flatbuffers::SimpleToVerifyInSlice for TimeUnit {} + #[deprecated( + since = "2.0.0", + note = "Use associated constants instead. This will no longer be generated in 2021." + )] + pub const ENUM_MIN_EDGE_INTERPOLATION_ALGORITHM: i8 = 0; + #[deprecated( + since = "2.0.0", + note = "Use associated constants instead. This will no longer be generated in 2021." + )] + pub const ENUM_MAX_EDGE_INTERPOLATION_ALGORITHM: i8 = 4; + #[deprecated( + since = "2.0.0", + note = "Use associated constants instead. This will no longer be generated in 2021." + )] + #[allow(non_camel_case_types)] + pub const ENUM_VALUES_EDGE_INTERPOLATION_ALGORITHM: [EdgeInterpolationAlgorithm; 5] = [ + EdgeInterpolationAlgorithm::SPHERICAL, + EdgeInterpolationAlgorithm::VINCENTY, + EdgeInterpolationAlgorithm::THOMAS, + EdgeInterpolationAlgorithm::ANDOYER, + EdgeInterpolationAlgorithm::KARNEY, + ]; + + #[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Default)] + #[repr(transparent)] + pub struct EdgeInterpolationAlgorithm(pub i8); + #[allow(non_upper_case_globals)] + impl EdgeInterpolationAlgorithm { + pub const SPHERICAL: Self = Self(0); + pub const VINCENTY: Self = Self(1); + pub const THOMAS: Self = Self(2); + pub const ANDOYER: Self = Self(3); + pub const KARNEY: Self = Self(4); + + pub const ENUM_MIN: i8 = 0; + pub const ENUM_MAX: i8 = 4; + pub const ENUM_VALUES: &'static [Self] = &[ + Self::SPHERICAL, + Self::VINCENTY, + Self::THOMAS, + Self::ANDOYER, + Self::KARNEY, + ]; + /// Returns the variant's name or "" if unknown. + pub fn variant_name(self) -> Option<&'static str> { + match self { + Self::SPHERICAL => Some("SPHERICAL"), + Self::VINCENTY => Some("VINCENTY"), + Self::THOMAS => Some("THOMAS"), + Self::ANDOYER => Some("ANDOYER"), + Self::KARNEY => Some("KARNEY"), + _ => None, + } + } + } + impl ::core::fmt::Debug for EdgeInterpolationAlgorithm { + fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { + if let Some(name) = self.variant_name() { + f.write_str(name) + } else { + f.write_fmt(format_args!("", self.0)) + } + } + } + impl<'a> ::flatbuffers::Follow<'a> for EdgeInterpolationAlgorithm { + type Inner = Self; + #[inline] + unsafe fn follow(buf: &'a [u8], loc: usize) -> Self::Inner { + let b = unsafe { ::flatbuffers::read_scalar_at::(buf, loc) }; + Self(b) + } + } + + impl ::flatbuffers::Push for EdgeInterpolationAlgorithm { + type Output = EdgeInterpolationAlgorithm; + #[inline] + unsafe fn push(&self, dst: &mut [u8], _written_len: usize) { + unsafe { ::flatbuffers::emplace_scalar::(dst, self.0) }; + } + } + + impl ::flatbuffers::EndianScalar for EdgeInterpolationAlgorithm { + type Scalar = i8; + #[inline] + fn to_little_endian(self) -> i8 { + self.0.to_le() + } + #[inline] + #[allow(clippy::wrong_self_convention)] + fn from_little_endian(v: i8) -> Self { + let b = i8::from_le(v); + Self(b) + } + } + + impl<'a> ::flatbuffers::Verifiable for EdgeInterpolationAlgorithm { + #[inline] + fn run_verifier( + v: &mut ::flatbuffers::Verifier, + pos: usize, + ) -> Result<(), ::flatbuffers::InvalidFlatbuffer> { + i8::run_verifier(v, pos) + } + } + + impl ::flatbuffers::SimpleToVerifyInSlice for EdgeInterpolationAlgorithm {} + #[deprecated( + since = "2.0.0", + note = "Use associated constants instead. This will no longer be generated in 2021." + )] + pub const ENUM_MIN_LOGICAL_TYPE: u8 = 0; + #[deprecated( + since = "2.0.0", + note = "Use associated constants instead. This will no longer be generated in 2021." + )] + pub const ENUM_MAX_LOGICAL_TYPE: u8 = 17; + #[deprecated( + since = "2.0.0", + note = "Use associated constants instead. This will no longer be generated in 2021." + )] + #[allow(non_camel_case_types)] + pub const ENUM_VALUES_LOGICAL_TYPE: [LogicalType; 18] = [ + LogicalType::NONE, + LogicalType::StringType, + LogicalType::MapType, + LogicalType::ListType, + LogicalType::EnumType, + LogicalType::DecimalType, + LogicalType::DateType, + LogicalType::TimeType, + LogicalType::TimestampType, + LogicalType::IntType, + LogicalType::NullType, + LogicalType::JsonType, + LogicalType::BsonType, + LogicalType::UUIDType, + LogicalType::Float16Type, + LogicalType::VariantType, + LogicalType::GeometryType, + LogicalType::GeographyType, + ]; + + #[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Default)] + #[repr(transparent)] + pub struct LogicalType(pub u8); + #[allow(non_upper_case_globals)] + impl LogicalType { + pub const NONE: Self = Self(0); + pub const StringType: Self = Self(1); + pub const MapType: Self = Self(2); + pub const ListType: Self = Self(3); + pub const EnumType: Self = Self(4); + pub const DecimalType: Self = Self(5); + pub const DateType: Self = Self(6); + pub const TimeType: Self = Self(7); + pub const TimestampType: Self = Self(8); + pub const IntType: Self = Self(9); + pub const NullType: Self = Self(10); + pub const JsonType: Self = Self(11); + pub const BsonType: Self = Self(12); + pub const UUIDType: Self = Self(13); + pub const Float16Type: Self = Self(14); + pub const VariantType: Self = Self(15); + pub const GeometryType: Self = Self(16); + pub const GeographyType: Self = Self(17); + + pub const ENUM_MIN: u8 = 0; + pub const ENUM_MAX: u8 = 17; + pub const ENUM_VALUES: &'static [Self] = &[ + Self::NONE, + Self::StringType, + Self::MapType, + Self::ListType, + Self::EnumType, + Self::DecimalType, + Self::DateType, + Self::TimeType, + Self::TimestampType, + Self::IntType, + Self::NullType, + Self::JsonType, + Self::BsonType, + Self::UUIDType, + Self::Float16Type, + Self::VariantType, + Self::GeometryType, + Self::GeographyType, + ]; + /// Returns the variant's name or "" if unknown. + pub fn variant_name(self) -> Option<&'static str> { + match self { + Self::NONE => Some("NONE"), + Self::StringType => Some("StringType"), + Self::MapType => Some("MapType"), + Self::ListType => Some("ListType"), + Self::EnumType => Some("EnumType"), + Self::DecimalType => Some("DecimalType"), + Self::DateType => Some("DateType"), + Self::TimeType => Some("TimeType"), + Self::TimestampType => Some("TimestampType"), + Self::IntType => Some("IntType"), + Self::NullType => Some("NullType"), + Self::JsonType => Some("JsonType"), + Self::BsonType => Some("BsonType"), + Self::UUIDType => Some("UUIDType"), + Self::Float16Type => Some("Float16Type"), + Self::VariantType => Some("VariantType"), + Self::GeometryType => Some("GeometryType"), + Self::GeographyType => Some("GeographyType"), + _ => None, + } + } + } + impl ::core::fmt::Debug for LogicalType { + fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { + if let Some(name) = self.variant_name() { + f.write_str(name) + } else { + f.write_fmt(format_args!("", self.0)) + } + } + } + impl<'a> ::flatbuffers::Follow<'a> for LogicalType { + type Inner = Self; + #[inline] + unsafe fn follow(buf: &'a [u8], loc: usize) -> Self::Inner { + let b = unsafe { ::flatbuffers::read_scalar_at::(buf, loc) }; + Self(b) + } + } + + impl ::flatbuffers::Push for LogicalType { + type Output = LogicalType; + #[inline] + unsafe fn push(&self, dst: &mut [u8], _written_len: usize) { + unsafe { ::flatbuffers::emplace_scalar::(dst, self.0) }; + } + } + + impl ::flatbuffers::EndianScalar for LogicalType { + type Scalar = u8; + #[inline] + fn to_little_endian(self) -> u8 { + self.0.to_le() + } + #[inline] + #[allow(clippy::wrong_self_convention)] + fn from_little_endian(v: u8) -> Self { + let b = u8::from_le(v); + Self(b) + } + } + + impl<'a> ::flatbuffers::Verifiable for LogicalType { + #[inline] + fn run_verifier( + v: &mut ::flatbuffers::Verifier, + pos: usize, + ) -> Result<(), ::flatbuffers::InvalidFlatbuffer> { + u8::run_verifier(v, pos) + } + } + + impl ::flatbuffers::SimpleToVerifyInSlice for LogicalType {} + pub struct LogicalTypeUnionTableOffset {} + + #[deprecated( + since = "2.0.0", + note = "Use associated constants instead. This will no longer be generated in 2021." + )] + pub const ENUM_MIN_ENCRYPTION_ALGORITHM: u8 = 0; + #[deprecated( + since = "2.0.0", + note = "Use associated constants instead. This will no longer be generated in 2021." + )] + pub const ENUM_MAX_ENCRYPTION_ALGORITHM: u8 = 2; + #[deprecated( + since = "2.0.0", + note = "Use associated constants instead. This will no longer be generated in 2021." + )] + #[allow(non_camel_case_types)] + pub const ENUM_VALUES_ENCRYPTION_ALGORITHM: [EncryptionAlgorithm; 3] = [ + EncryptionAlgorithm::NONE, + EncryptionAlgorithm::AesGcmV1, + EncryptionAlgorithm::AesGcmCtrV1, + ]; + + #[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Default)] + #[repr(transparent)] + pub struct EncryptionAlgorithm(pub u8); + #[allow(non_upper_case_globals)] + impl EncryptionAlgorithm { + pub const NONE: Self = Self(0); + pub const AesGcmV1: Self = Self(1); + pub const AesGcmCtrV1: Self = Self(2); + + pub const ENUM_MIN: u8 = 0; + pub const ENUM_MAX: u8 = 2; + pub const ENUM_VALUES: &'static [Self] = + &[Self::NONE, Self::AesGcmV1, Self::AesGcmCtrV1]; + /// Returns the variant's name or "" if unknown. + pub fn variant_name(self) -> Option<&'static str> { + match self { + Self::NONE => Some("NONE"), + Self::AesGcmV1 => Some("AesGcmV1"), + Self::AesGcmCtrV1 => Some("AesGcmCtrV1"), + _ => None, + } + } + } + impl ::core::fmt::Debug for EncryptionAlgorithm { + fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { + if let Some(name) = self.variant_name() { + f.write_str(name) + } else { + f.write_fmt(format_args!("", self.0)) + } + } + } + impl<'a> ::flatbuffers::Follow<'a> for EncryptionAlgorithm { + type Inner = Self; + #[inline] + unsafe fn follow(buf: &'a [u8], loc: usize) -> Self::Inner { + let b = unsafe { ::flatbuffers::read_scalar_at::(buf, loc) }; + Self(b) + } + } + + impl ::flatbuffers::Push for EncryptionAlgorithm { + type Output = EncryptionAlgorithm; + #[inline] + unsafe fn push(&self, dst: &mut [u8], _written_len: usize) { + unsafe { ::flatbuffers::emplace_scalar::(dst, self.0) }; + } + } + + impl ::flatbuffers::EndianScalar for EncryptionAlgorithm { + type Scalar = u8; + #[inline] + fn to_little_endian(self) -> u8 { + self.0.to_le() + } + #[inline] + #[allow(clippy::wrong_self_convention)] + fn from_little_endian(v: u8) -> Self { + let b = u8::from_le(v); + Self(b) + } + } + + impl<'a> ::flatbuffers::Verifiable for EncryptionAlgorithm { + #[inline] + fn run_verifier( + v: &mut ::flatbuffers::Verifier, + pos: usize, + ) -> Result<(), ::flatbuffers::InvalidFlatbuffer> { + u8::run_verifier(v, pos) + } + } + + impl ::flatbuffers::SimpleToVerifyInSlice for EncryptionAlgorithm {} + pub struct EncryptionAlgorithmUnionTableOffset {} + + #[deprecated( + since = "2.0.0", + note = "Use associated constants instead. This will no longer be generated in 2021." + )] + pub const ENUM_MIN_COLUMN_ORDER: u8 = 0; + #[deprecated( + since = "2.0.0", + note = "Use associated constants instead. This will no longer be generated in 2021." + )] + pub const ENUM_MAX_COLUMN_ORDER: u8 = 1; + #[deprecated( + since = "2.0.0", + note = "Use associated constants instead. This will no longer be generated in 2021." + )] + #[allow(non_camel_case_types)] + pub const ENUM_VALUES_COLUMN_ORDER: [ColumnOrder; 2] = + [ColumnOrder::NONE, ColumnOrder::TypeDefinedOrder]; + + #[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Default)] + #[repr(transparent)] + pub struct ColumnOrder(pub u8); + #[allow(non_upper_case_globals)] + impl ColumnOrder { + pub const NONE: Self = Self(0); + pub const TypeDefinedOrder: Self = Self(1); + + pub const ENUM_MIN: u8 = 0; + pub const ENUM_MAX: u8 = 1; + pub const ENUM_VALUES: &'static [Self] = &[Self::NONE, Self::TypeDefinedOrder]; + /// Returns the variant's name or "" if unknown. + pub fn variant_name(self) -> Option<&'static str> { + match self { + Self::NONE => Some("NONE"), + Self::TypeDefinedOrder => Some("TypeDefinedOrder"), + _ => None, + } + } + } + impl ::core::fmt::Debug for ColumnOrder { + fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { + if let Some(name) = self.variant_name() { + f.write_str(name) + } else { + f.write_fmt(format_args!("", self.0)) + } + } + } + impl<'a> ::flatbuffers::Follow<'a> for ColumnOrder { + type Inner = Self; + #[inline] + unsafe fn follow(buf: &'a [u8], loc: usize) -> Self::Inner { + let b = unsafe { ::flatbuffers::read_scalar_at::(buf, loc) }; + Self(b) + } + } + + impl ::flatbuffers::Push for ColumnOrder { + type Output = ColumnOrder; + #[inline] + unsafe fn push(&self, dst: &mut [u8], _written_len: usize) { + unsafe { ::flatbuffers::emplace_scalar::(dst, self.0) }; + } + } + + impl ::flatbuffers::EndianScalar for ColumnOrder { + type Scalar = u8; + #[inline] + fn to_little_endian(self) -> u8 { + self.0.to_le() + } + #[inline] + #[allow(clippy::wrong_self_convention)] + fn from_little_endian(v: u8) -> Self { + let b = u8::from_le(v); + Self(b) + } + } + + impl<'a> ::flatbuffers::Verifiable for ColumnOrder { + #[inline] + fn run_verifier( + v: &mut ::flatbuffers::Verifier, + pos: usize, + ) -> Result<(), ::flatbuffers::InvalidFlatbuffer> { + u8::run_verifier(v, pos) + } + } + + impl ::flatbuffers::SimpleToVerifyInSlice for ColumnOrder {} + pub struct ColumnOrderUnionTableOffset {} + + #[deprecated( + since = "2.0.0", + note = "Use associated constants instead. This will no longer be generated in 2021." + )] + pub const ENUM_MIN_PAGE_TYPE: i8 = 0; + #[deprecated( + since = "2.0.0", + note = "Use associated constants instead. This will no longer be generated in 2021." + )] + pub const ENUM_MAX_PAGE_TYPE: i8 = 3; + #[deprecated( + since = "2.0.0", + note = "Use associated constants instead. This will no longer be generated in 2021." + )] + #[allow(non_camel_case_types)] + pub const ENUM_VALUES_PAGE_TYPE: [PageType; 4] = [ + PageType::DATA_PAGE, + PageType::INDEX_PAGE, + PageType::DICTIONARY_PAGE, + PageType::DATA_PAGE_V2, + ]; + + #[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Default)] + #[repr(transparent)] + pub struct PageType(pub i8); + #[allow(non_upper_case_globals)] + impl PageType { + pub const DATA_PAGE: Self = Self(0); + pub const INDEX_PAGE: Self = Self(1); + pub const DICTIONARY_PAGE: Self = Self(2); + pub const DATA_PAGE_V2: Self = Self(3); + + pub const ENUM_MIN: i8 = 0; + pub const ENUM_MAX: i8 = 3; + pub const ENUM_VALUES: &'static [Self] = &[ + Self::DATA_PAGE, + Self::INDEX_PAGE, + Self::DICTIONARY_PAGE, + Self::DATA_PAGE_V2, + ]; + /// Returns the variant's name or "" if unknown. + pub fn variant_name(self) -> Option<&'static str> { + match self { + Self::DATA_PAGE => Some("DATA_PAGE"), + Self::INDEX_PAGE => Some("INDEX_PAGE"), + Self::DICTIONARY_PAGE => Some("DICTIONARY_PAGE"), + Self::DATA_PAGE_V2 => Some("DATA_PAGE_V2"), + _ => None, + } + } + } + impl ::core::fmt::Debug for PageType { + fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { + if let Some(name) = self.variant_name() { + f.write_str(name) + } else { + f.write_fmt(format_args!("", self.0)) + } + } + } + impl<'a> ::flatbuffers::Follow<'a> for PageType { + type Inner = Self; + #[inline] + unsafe fn follow(buf: &'a [u8], loc: usize) -> Self::Inner { + let b = unsafe { ::flatbuffers::read_scalar_at::(buf, loc) }; + Self(b) + } + } + + impl ::flatbuffers::Push for PageType { + type Output = PageType; + #[inline] + unsafe fn push(&self, dst: &mut [u8], _written_len: usize) { + unsafe { ::flatbuffers::emplace_scalar::(dst, self.0) }; + } + } + + impl ::flatbuffers::EndianScalar for PageType { + type Scalar = i8; + #[inline] + fn to_little_endian(self) -> i8 { + self.0.to_le() + } + #[inline] + #[allow(clippy::wrong_self_convention)] + fn from_little_endian(v: i8) -> Self { + let b = i8::from_le(v); + Self(b) + } + } + + impl<'a> ::flatbuffers::Verifiable for PageType { + #[inline] + fn run_verifier( + v: &mut ::flatbuffers::Verifier, + pos: usize, + ) -> Result<(), ::flatbuffers::InvalidFlatbuffer> { + i8::run_verifier(v, pos) + } + } + + impl ::flatbuffers::SimpleToVerifyInSlice for PageType {} + #[deprecated( + since = "2.0.0", + note = "Use associated constants instead. This will no longer be generated in 2021." + )] + pub const ENUM_MIN_COLUMN_CRYPTO_METADATA: u8 = 0; + #[deprecated( + since = "2.0.0", + note = "Use associated constants instead. This will no longer be generated in 2021." + )] + pub const ENUM_MAX_COLUMN_CRYPTO_METADATA: u8 = 2; + #[deprecated( + since = "2.0.0", + note = "Use associated constants instead. This will no longer be generated in 2021." + )] + #[allow(non_camel_case_types)] + pub const ENUM_VALUES_COLUMN_CRYPTO_METADATA: [ColumnCryptoMetadata; 3] = [ + ColumnCryptoMetadata::NONE, + ColumnCryptoMetadata::EncryptionWithFooterKey, + ColumnCryptoMetadata::EncryptionWithColumnKey, + ]; + + #[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Default)] + #[repr(transparent)] + pub struct ColumnCryptoMetadata(pub u8); + #[allow(non_upper_case_globals)] + impl ColumnCryptoMetadata { + pub const NONE: Self = Self(0); + pub const EncryptionWithFooterKey: Self = Self(1); + pub const EncryptionWithColumnKey: Self = Self(2); + + pub const ENUM_MIN: u8 = 0; + pub const ENUM_MAX: u8 = 2; + pub const ENUM_VALUES: &'static [Self] = &[ + Self::NONE, + Self::EncryptionWithFooterKey, + Self::EncryptionWithColumnKey, + ]; + /// Returns the variant's name or "" if unknown. + pub fn variant_name(self) -> Option<&'static str> { + match self { + Self::NONE => Some("NONE"), + Self::EncryptionWithFooterKey => Some("EncryptionWithFooterKey"), + Self::EncryptionWithColumnKey => Some("EncryptionWithColumnKey"), + _ => None, + } + } + } + impl ::core::fmt::Debug for ColumnCryptoMetadata { + fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { + if let Some(name) = self.variant_name() { + f.write_str(name) + } else { + f.write_fmt(format_args!("", self.0)) + } + } + } + impl<'a> ::flatbuffers::Follow<'a> for ColumnCryptoMetadata { + type Inner = Self; + #[inline] + unsafe fn follow(buf: &'a [u8], loc: usize) -> Self::Inner { + let b = unsafe { ::flatbuffers::read_scalar_at::(buf, loc) }; + Self(b) + } + } + + impl ::flatbuffers::Push for ColumnCryptoMetadata { + type Output = ColumnCryptoMetadata; + #[inline] + unsafe fn push(&self, dst: &mut [u8], _written_len: usize) { + unsafe { ::flatbuffers::emplace_scalar::(dst, self.0) }; + } + } + + impl ::flatbuffers::EndianScalar for ColumnCryptoMetadata { + type Scalar = u8; + #[inline] + fn to_little_endian(self) -> u8 { + self.0.to_le() + } + #[inline] + #[allow(clippy::wrong_self_convention)] + fn from_little_endian(v: u8) -> Self { + let b = u8::from_le(v); + Self(b) + } + } + + impl<'a> ::flatbuffers::Verifiable for ColumnCryptoMetadata { + #[inline] + fn run_verifier( + v: &mut ::flatbuffers::Verifier, + pos: usize, + ) -> Result<(), ::flatbuffers::InvalidFlatbuffer> { + u8::run_verifier(v, pos) + } + } + + impl ::flatbuffers::SimpleToVerifyInSlice for ColumnCryptoMetadata {} + pub struct ColumnCryptoMetadataUnionTableOffset {} + + pub enum EmptyOffset {} + #[derive(Copy, Clone, PartialEq)] + + /////////////////////////////////////////////////////////////////////////////////////////////////// + /////////////////////////////////////////////////////////////////////////////////////////////////// + pub struct Empty<'a> { + pub _tab: ::flatbuffers::Table<'a>, + } + + impl<'a> ::flatbuffers::Follow<'a> for Empty<'a> { + type Inner = Empty<'a>; + #[inline] + unsafe fn follow(buf: &'a [u8], loc: usize) -> Self::Inner { + Self { + _tab: unsafe { ::flatbuffers::Table::new(buf, loc) }, + } + } + } + + impl<'a> Empty<'a> { + #[inline] + pub unsafe fn init_from_table(table: ::flatbuffers::Table<'a>) -> Self { + Empty { _tab: table } + } + #[allow(unused_mut)] + pub fn create< + 'bldr: 'args, + 'args: 'mut_bldr, + 'mut_bldr, + A: ::flatbuffers::Allocator + 'bldr, + >( + _fbb: &'mut_bldr mut ::flatbuffers::FlatBufferBuilder<'bldr, A>, + _args: &'args EmptyArgs, + ) -> ::flatbuffers::WIPOffset> { + let mut builder = EmptyBuilder::new(_fbb); + builder.finish() + } + } + + impl ::flatbuffers::Verifiable for Empty<'_> { + #[inline] + fn run_verifier( + v: &mut ::flatbuffers::Verifier, + pos: usize, + ) -> Result<(), ::flatbuffers::InvalidFlatbuffer> { + v.visit_table(pos)?.finish(); + Ok(()) + } + } + pub struct EmptyArgs {} + impl<'a> Default for EmptyArgs { + #[inline] + fn default() -> Self { + EmptyArgs {} + } + } + + pub struct EmptyBuilder<'a: 'b, 'b, A: ::flatbuffers::Allocator + 'a> { + fbb_: &'b mut ::flatbuffers::FlatBufferBuilder<'a, A>, + start_: ::flatbuffers::WIPOffset<::flatbuffers::TableUnfinishedWIPOffset>, + } + impl<'a: 'b, 'b, A: ::flatbuffers::Allocator + 'a> EmptyBuilder<'a, 'b, A> { + #[inline] + pub fn new( + _fbb: &'b mut ::flatbuffers::FlatBufferBuilder<'a, A>, + ) -> EmptyBuilder<'a, 'b, A> { + let start = _fbb.start_table(); + EmptyBuilder { + fbb_: _fbb, + start_: start, + } + } + #[inline] + pub fn finish(self) -> ::flatbuffers::WIPOffset> { + let o = self.fbb_.end_table(self.start_); + ::flatbuffers::WIPOffset::new(o.value()) + } + } + + impl ::core::fmt::Debug for Empty<'_> { + fn fmt(&self, f: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result { + let mut ds = f.debug_struct("Empty"); + ds.finish() + } + } + pub enum DecimalOptionsOffset {} + #[derive(Copy, Clone, PartialEq)] + + pub struct DecimalOptions<'a> { + pub _tab: ::flatbuffers::Table<'a>, + } + + impl<'a> ::flatbuffers::Follow<'a> for DecimalOptions<'a> { + type Inner = DecimalOptions<'a>; + #[inline] + unsafe fn follow(buf: &'a [u8], loc: usize) -> Self::Inner { + Self { + _tab: unsafe { ::flatbuffers::Table::new(buf, loc) }, + } + } + } + + impl<'a> DecimalOptions<'a> { + pub const VT_PRECISION: ::flatbuffers::VOffsetT = 4; + pub const VT_SCALE: ::flatbuffers::VOffsetT = 6; + + #[inline] + pub unsafe fn init_from_table(table: ::flatbuffers::Table<'a>) -> Self { + DecimalOptions { _tab: table } + } + #[allow(unused_mut)] + pub fn create< + 'bldr: 'args, + 'args: 'mut_bldr, + 'mut_bldr, + A: ::flatbuffers::Allocator + 'bldr, + >( + _fbb: &'mut_bldr mut ::flatbuffers::FlatBufferBuilder<'bldr, A>, + args: &'args DecimalOptionsArgs, + ) -> ::flatbuffers::WIPOffset> { + let mut builder = DecimalOptionsBuilder::new(_fbb); + builder.add_scale(args.scale); + builder.add_precision(args.precision); + builder.finish() + } + + #[inline] + pub fn precision(&self) -> i32 { + // Safety: + // Created from valid Table for this object + // which contains a valid value in this slot + unsafe { + self._tab + .get::(DecimalOptions::VT_PRECISION, Some(0)) + .unwrap() + } + } + #[inline] + pub fn scale(&self) -> i32 { + // Safety: + // Created from valid Table for this object + // which contains a valid value in this slot + unsafe { + self._tab + .get::(DecimalOptions::VT_SCALE, Some(0)) + .unwrap() + } + } + } + + impl ::flatbuffers::Verifiable for DecimalOptions<'_> { + #[inline] + fn run_verifier( + v: &mut ::flatbuffers::Verifier, + pos: usize, + ) -> Result<(), ::flatbuffers::InvalidFlatbuffer> { + v.visit_table(pos)? + .visit_field::("precision", Self::VT_PRECISION, false)? + .visit_field::("scale", Self::VT_SCALE, false)? + .finish(); + Ok(()) + } + } + pub struct DecimalOptionsArgs { + pub precision: i32, + pub scale: i32, + } + impl<'a> Default for DecimalOptionsArgs { + #[inline] + fn default() -> Self { + DecimalOptionsArgs { + precision: 0, + scale: 0, + } + } + } + + pub struct DecimalOptionsBuilder<'a: 'b, 'b, A: ::flatbuffers::Allocator + 'a> { + fbb_: &'b mut ::flatbuffers::FlatBufferBuilder<'a, A>, + start_: ::flatbuffers::WIPOffset<::flatbuffers::TableUnfinishedWIPOffset>, + } + impl<'a: 'b, 'b, A: ::flatbuffers::Allocator + 'a> DecimalOptionsBuilder<'a, 'b, A> { + #[inline] + pub fn add_precision(&mut self, precision: i32) { + self.fbb_ + .push_slot::(DecimalOptions::VT_PRECISION, precision, 0); + } + #[inline] + pub fn add_scale(&mut self, scale: i32) { + self.fbb_ + .push_slot::(DecimalOptions::VT_SCALE, scale, 0); + } + #[inline] + pub fn new( + _fbb: &'b mut ::flatbuffers::FlatBufferBuilder<'a, A>, + ) -> DecimalOptionsBuilder<'a, 'b, A> { + let start = _fbb.start_table(); + DecimalOptionsBuilder { + fbb_: _fbb, + start_: start, + } + } + #[inline] + pub fn finish(self) -> ::flatbuffers::WIPOffset> { + let o = self.fbb_.end_table(self.start_); + ::flatbuffers::WIPOffset::new(o.value()) + } + } + + impl ::core::fmt::Debug for DecimalOptions<'_> { + fn fmt(&self, f: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result { + let mut ds = f.debug_struct("DecimalOptions"); + ds.field("precision", &self.precision()); + ds.field("scale", &self.scale()); + ds.finish() + } + } + pub enum TimeOptionsOffset {} + #[derive(Copy, Clone, PartialEq)] + + pub struct TimeOptions<'a> { + pub _tab: ::flatbuffers::Table<'a>, + } + + impl<'a> ::flatbuffers::Follow<'a> for TimeOptions<'a> { + type Inner = TimeOptions<'a>; + #[inline] + unsafe fn follow(buf: &'a [u8], loc: usize) -> Self::Inner { + Self { + _tab: unsafe { ::flatbuffers::Table::new(buf, loc) }, + } + } + } + + impl<'a> TimeOptions<'a> { + pub const VT_IS_ADJUSTED_TO_UTC: ::flatbuffers::VOffsetT = 4; + pub const VT_UNIT: ::flatbuffers::VOffsetT = 6; + + #[inline] + pub unsafe fn init_from_table(table: ::flatbuffers::Table<'a>) -> Self { + TimeOptions { _tab: table } + } + #[allow(unused_mut)] + pub fn create< + 'bldr: 'args, + 'args: 'mut_bldr, + 'mut_bldr, + A: ::flatbuffers::Allocator + 'bldr, + >( + _fbb: &'mut_bldr mut ::flatbuffers::FlatBufferBuilder<'bldr, A>, + args: &'args TimeOptionsArgs, + ) -> ::flatbuffers::WIPOffset> { + let mut builder = TimeOptionsBuilder::new(_fbb); + builder.add_unit(args.unit); + builder.add_is_adjusted_to_utc(args.is_adjusted_to_utc); + builder.finish() + } + + #[inline] + pub fn is_adjusted_to_utc(&self) -> bool { + // Safety: + // Created from valid Table for this object + // which contains a valid value in this slot + unsafe { + self._tab + .get::(TimeOptions::VT_IS_ADJUSTED_TO_UTC, Some(false)) + .unwrap() + } + } + #[inline] + pub fn unit(&self) -> TimeUnit { + // Safety: + // Created from valid Table for this object + // which contains a valid value in this slot + unsafe { + self._tab + .get::(TimeOptions::VT_UNIT, Some(TimeUnit::MILLIS)) + .unwrap() + } + } + } + + impl ::flatbuffers::Verifiable for TimeOptions<'_> { + #[inline] + fn run_verifier( + v: &mut ::flatbuffers::Verifier, + pos: usize, + ) -> Result<(), ::flatbuffers::InvalidFlatbuffer> { + v.visit_table(pos)? + .visit_field::("is_adjusted_to_utc", Self::VT_IS_ADJUSTED_TO_UTC, false)? + .visit_field::("unit", Self::VT_UNIT, false)? + .finish(); + Ok(()) + } + } + pub struct TimeOptionsArgs { + pub is_adjusted_to_utc: bool, + pub unit: TimeUnit, + } + impl<'a> Default for TimeOptionsArgs { + #[inline] + fn default() -> Self { + TimeOptionsArgs { + is_adjusted_to_utc: false, + unit: TimeUnit::MILLIS, + } + } + } + + pub struct TimeOptionsBuilder<'a: 'b, 'b, A: ::flatbuffers::Allocator + 'a> { + fbb_: &'b mut ::flatbuffers::FlatBufferBuilder<'a, A>, + start_: ::flatbuffers::WIPOffset<::flatbuffers::TableUnfinishedWIPOffset>, + } + impl<'a: 'b, 'b, A: ::flatbuffers::Allocator + 'a> TimeOptionsBuilder<'a, 'b, A> { + #[inline] + pub fn add_is_adjusted_to_utc(&mut self, is_adjusted_to_utc: bool) { + self.fbb_.push_slot::( + TimeOptions::VT_IS_ADJUSTED_TO_UTC, + is_adjusted_to_utc, + false, + ); + } + #[inline] + pub fn add_unit(&mut self, unit: TimeUnit) { + self.fbb_ + .push_slot::(TimeOptions::VT_UNIT, unit, TimeUnit::MILLIS); + } + #[inline] + pub fn new( + _fbb: &'b mut ::flatbuffers::FlatBufferBuilder<'a, A>, + ) -> TimeOptionsBuilder<'a, 'b, A> { + let start = _fbb.start_table(); + TimeOptionsBuilder { + fbb_: _fbb, + start_: start, + } + } + #[inline] + pub fn finish(self) -> ::flatbuffers::WIPOffset> { + let o = self.fbb_.end_table(self.start_); + ::flatbuffers::WIPOffset::new(o.value()) + } + } + + impl ::core::fmt::Debug for TimeOptions<'_> { + fn fmt(&self, f: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result { + let mut ds = f.debug_struct("TimeOptions"); + ds.field("is_adjusted_to_utc", &self.is_adjusted_to_utc()); + ds.field("unit", &self.unit()); + ds.finish() + } + } + pub enum IntOptionsOffset {} + #[derive(Copy, Clone, PartialEq)] + + pub struct IntOptions<'a> { + pub _tab: ::flatbuffers::Table<'a>, + } + + impl<'a> ::flatbuffers::Follow<'a> for IntOptions<'a> { + type Inner = IntOptions<'a>; + #[inline] + unsafe fn follow(buf: &'a [u8], loc: usize) -> Self::Inner { + Self { + _tab: unsafe { ::flatbuffers::Table::new(buf, loc) }, + } + } + } + + impl<'a> IntOptions<'a> { + pub const VT_BIT_WIDTH: ::flatbuffers::VOffsetT = 4; + pub const VT_IS_SIGNED: ::flatbuffers::VOffsetT = 6; + + #[inline] + pub unsafe fn init_from_table(table: ::flatbuffers::Table<'a>) -> Self { + IntOptions { _tab: table } + } + #[allow(unused_mut)] + pub fn create< + 'bldr: 'args, + 'args: 'mut_bldr, + 'mut_bldr, + A: ::flatbuffers::Allocator + 'bldr, + >( + _fbb: &'mut_bldr mut ::flatbuffers::FlatBufferBuilder<'bldr, A>, + args: &'args IntOptionsArgs, + ) -> ::flatbuffers::WIPOffset> { + let mut builder = IntOptionsBuilder::new(_fbb); + builder.add_is_signed(args.is_signed); + builder.add_bit_width(args.bit_width); + builder.finish() + } + + #[inline] + pub fn bit_width(&self) -> i8 { + // Safety: + // Created from valid Table for this object + // which contains a valid value in this slot + unsafe { + self._tab + .get::(IntOptions::VT_BIT_WIDTH, Some(8)) + .unwrap() + } + } + #[inline] + pub fn is_signed(&self) -> bool { + // Safety: + // Created from valid Table for this object + // which contains a valid value in this slot + unsafe { + self._tab + .get::(IntOptions::VT_IS_SIGNED, Some(false)) + .unwrap() + } + } + } + + impl ::flatbuffers::Verifiable for IntOptions<'_> { + #[inline] + fn run_verifier( + v: &mut ::flatbuffers::Verifier, + pos: usize, + ) -> Result<(), ::flatbuffers::InvalidFlatbuffer> { + v.visit_table(pos)? + .visit_field::("bit_width", Self::VT_BIT_WIDTH, false)? + .visit_field::("is_signed", Self::VT_IS_SIGNED, false)? + .finish(); + Ok(()) + } + } + pub struct IntOptionsArgs { + pub bit_width: i8, + pub is_signed: bool, + } + impl<'a> Default for IntOptionsArgs { + #[inline] + fn default() -> Self { + IntOptionsArgs { + bit_width: 8, + is_signed: false, + } + } + } + + pub struct IntOptionsBuilder<'a: 'b, 'b, A: ::flatbuffers::Allocator + 'a> { + fbb_: &'b mut ::flatbuffers::FlatBufferBuilder<'a, A>, + start_: ::flatbuffers::WIPOffset<::flatbuffers::TableUnfinishedWIPOffset>, + } + impl<'a: 'b, 'b, A: ::flatbuffers::Allocator + 'a> IntOptionsBuilder<'a, 'b, A> { + #[inline] + pub fn add_bit_width(&mut self, bit_width: i8) { + self.fbb_ + .push_slot::(IntOptions::VT_BIT_WIDTH, bit_width, 8); + } + #[inline] + pub fn add_is_signed(&mut self, is_signed: bool) { + self.fbb_ + .push_slot::(IntOptions::VT_IS_SIGNED, is_signed, false); + } + #[inline] + pub fn new( + _fbb: &'b mut ::flatbuffers::FlatBufferBuilder<'a, A>, + ) -> IntOptionsBuilder<'a, 'b, A> { + let start = _fbb.start_table(); + IntOptionsBuilder { + fbb_: _fbb, + start_: start, + } + } + #[inline] + pub fn finish(self) -> ::flatbuffers::WIPOffset> { + let o = self.fbb_.end_table(self.start_); + ::flatbuffers::WIPOffset::new(o.value()) + } + } + + impl ::core::fmt::Debug for IntOptions<'_> { + fn fmt(&self, f: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result { + let mut ds = f.debug_struct("IntOptions"); + ds.field("bit_width", &self.bit_width()); + ds.field("is_signed", &self.is_signed()); + ds.finish() + } + } + pub enum VariantTypeOffset {} + #[derive(Copy, Clone, PartialEq)] + + pub struct VariantType<'a> { + pub _tab: ::flatbuffers::Table<'a>, + } + + impl<'a> ::flatbuffers::Follow<'a> for VariantType<'a> { + type Inner = VariantType<'a>; + #[inline] + unsafe fn follow(buf: &'a [u8], loc: usize) -> Self::Inner { + Self { + _tab: unsafe { ::flatbuffers::Table::new(buf, loc) }, + } + } + } + + impl<'a> VariantType<'a> { + pub const VT_SPECIFICATION_VERSION: ::flatbuffers::VOffsetT = 4; + + #[inline] + pub unsafe fn init_from_table(table: ::flatbuffers::Table<'a>) -> Self { + VariantType { _tab: table } + } + #[allow(unused_mut)] + pub fn create< + 'bldr: 'args, + 'args: 'mut_bldr, + 'mut_bldr, + A: ::flatbuffers::Allocator + 'bldr, + >( + _fbb: &'mut_bldr mut ::flatbuffers::FlatBufferBuilder<'bldr, A>, + args: &'args VariantTypeArgs, + ) -> ::flatbuffers::WIPOffset> { + let mut builder = VariantTypeBuilder::new(_fbb); + if let Some(x) = args.specification_version { + builder.add_specification_version(x); + } + builder.finish() + } + + #[inline] + pub fn specification_version(&self) -> Option { + // Safety: + // Created from valid Table for this object + // which contains a valid value in this slot + unsafe { + self._tab + .get::(VariantType::VT_SPECIFICATION_VERSION, None) + } + } + } + + impl ::flatbuffers::Verifiable for VariantType<'_> { + #[inline] + fn run_verifier( + v: &mut ::flatbuffers::Verifier, + pos: usize, + ) -> Result<(), ::flatbuffers::InvalidFlatbuffer> { + v.visit_table(pos)? + .visit_field::( + "specification_version", + Self::VT_SPECIFICATION_VERSION, + false, + )? + .finish(); + Ok(()) + } + } + pub struct VariantTypeArgs { + pub specification_version: Option, + } + impl<'a> Default for VariantTypeArgs { + #[inline] + fn default() -> Self { + VariantTypeArgs { + specification_version: None, + } + } + } + + pub struct VariantTypeBuilder<'a: 'b, 'b, A: ::flatbuffers::Allocator + 'a> { + fbb_: &'b mut ::flatbuffers::FlatBufferBuilder<'a, A>, + start_: ::flatbuffers::WIPOffset<::flatbuffers::TableUnfinishedWIPOffset>, + } + impl<'a: 'b, 'b, A: ::flatbuffers::Allocator + 'a> VariantTypeBuilder<'a, 'b, A> { + #[inline] + pub fn add_specification_version(&mut self, specification_version: i8) { + self.fbb_.push_slot_always::( + VariantType::VT_SPECIFICATION_VERSION, + specification_version, + ); + } + #[inline] + pub fn new( + _fbb: &'b mut ::flatbuffers::FlatBufferBuilder<'a, A>, + ) -> VariantTypeBuilder<'a, 'b, A> { + let start = _fbb.start_table(); + VariantTypeBuilder { + fbb_: _fbb, + start_: start, + } + } + #[inline] + pub fn finish(self) -> ::flatbuffers::WIPOffset> { + let o = self.fbb_.end_table(self.start_); + ::flatbuffers::WIPOffset::new(o.value()) + } + } + + impl ::core::fmt::Debug for VariantType<'_> { + fn fmt(&self, f: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result { + let mut ds = f.debug_struct("VariantType"); + ds.field("specification_version", &self.specification_version()); + ds.finish() + } + } + pub enum GeometryTypeOffset {} + #[derive(Copy, Clone, PartialEq)] + + pub struct GeometryType<'a> { + pub _tab: ::flatbuffers::Table<'a>, + } + + impl<'a> ::flatbuffers::Follow<'a> for GeometryType<'a> { + type Inner = GeometryType<'a>; + #[inline] + unsafe fn follow(buf: &'a [u8], loc: usize) -> Self::Inner { + Self { + _tab: unsafe { ::flatbuffers::Table::new(buf, loc) }, + } + } + } + + impl<'a> GeometryType<'a> { + pub const VT_CRS: ::flatbuffers::VOffsetT = 4; + + #[inline] + pub unsafe fn init_from_table(table: ::flatbuffers::Table<'a>) -> Self { + GeometryType { _tab: table } + } + #[allow(unused_mut)] + pub fn create< + 'bldr: 'args, + 'args: 'mut_bldr, + 'mut_bldr, + A: ::flatbuffers::Allocator + 'bldr, + >( + _fbb: &'mut_bldr mut ::flatbuffers::FlatBufferBuilder<'bldr, A>, + args: &'args GeometryTypeArgs<'args>, + ) -> ::flatbuffers::WIPOffset> { + let mut builder = GeometryTypeBuilder::new(_fbb); + if let Some(x) = args.crs { + builder.add_crs(x); + } + builder.finish() + } + + #[inline] + pub fn crs(&self) -> Option<&'a str> { + // Safety: + // Created from valid Table for this object + // which contains a valid value in this slot + unsafe { + self._tab + .get::<::flatbuffers::ForwardsUOffset<&str>>(GeometryType::VT_CRS, None) + } + } + } + + impl ::flatbuffers::Verifiable for GeometryType<'_> { + #[inline] + fn run_verifier( + v: &mut ::flatbuffers::Verifier, + pos: usize, + ) -> Result<(), ::flatbuffers::InvalidFlatbuffer> { + v.visit_table(pos)? + .visit_field::<::flatbuffers::ForwardsUOffset<&str>>( + "crs", + Self::VT_CRS, + false, + )? + .finish(); + Ok(()) + } + } + pub struct GeometryTypeArgs<'a> { + pub crs: Option<::flatbuffers::WIPOffset<&'a str>>, + } + impl<'a> Default for GeometryTypeArgs<'a> { + #[inline] + fn default() -> Self { + GeometryTypeArgs { crs: None } + } + } + + pub struct GeometryTypeBuilder<'a: 'b, 'b, A: ::flatbuffers::Allocator + 'a> { + fbb_: &'b mut ::flatbuffers::FlatBufferBuilder<'a, A>, + start_: ::flatbuffers::WIPOffset<::flatbuffers::TableUnfinishedWIPOffset>, + } + impl<'a: 'b, 'b, A: ::flatbuffers::Allocator + 'a> GeometryTypeBuilder<'a, 'b, A> { + #[inline] + pub fn add_crs(&mut self, crs: ::flatbuffers::WIPOffset<&'b str>) { + self.fbb_ + .push_slot_always::<::flatbuffers::WIPOffset<_>>(GeometryType::VT_CRS, crs); + } + #[inline] + pub fn new( + _fbb: &'b mut ::flatbuffers::FlatBufferBuilder<'a, A>, + ) -> GeometryTypeBuilder<'a, 'b, A> { + let start = _fbb.start_table(); + GeometryTypeBuilder { + fbb_: _fbb, + start_: start, + } + } + #[inline] + pub fn finish(self) -> ::flatbuffers::WIPOffset> { + let o = self.fbb_.end_table(self.start_); + ::flatbuffers::WIPOffset::new(o.value()) + } + } + + impl ::core::fmt::Debug for GeometryType<'_> { + fn fmt(&self, f: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result { + let mut ds = f.debug_struct("GeometryType"); + ds.field("crs", &self.crs()); + ds.finish() + } + } + pub enum GeographyTypeOffset {} + #[derive(Copy, Clone, PartialEq)] + + pub struct GeographyType<'a> { + pub _tab: ::flatbuffers::Table<'a>, + } + + impl<'a> ::flatbuffers::Follow<'a> for GeographyType<'a> { + type Inner = GeographyType<'a>; + #[inline] + unsafe fn follow(buf: &'a [u8], loc: usize) -> Self::Inner { + Self { + _tab: unsafe { ::flatbuffers::Table::new(buf, loc) }, + } + } + } + + impl<'a> GeographyType<'a> { + pub const VT_CRS: ::flatbuffers::VOffsetT = 4; + pub const VT_ALGORITHM: ::flatbuffers::VOffsetT = 6; + + #[inline] + pub unsafe fn init_from_table(table: ::flatbuffers::Table<'a>) -> Self { + GeographyType { _tab: table } + } + #[allow(unused_mut)] + pub fn create< + 'bldr: 'args, + 'args: 'mut_bldr, + 'mut_bldr, + A: ::flatbuffers::Allocator + 'bldr, + >( + _fbb: &'mut_bldr mut ::flatbuffers::FlatBufferBuilder<'bldr, A>, + args: &'args GeographyTypeArgs<'args>, + ) -> ::flatbuffers::WIPOffset> { + let mut builder = GeographyTypeBuilder::new(_fbb); + if let Some(x) = args.crs { + builder.add_crs(x); + } + builder.add_algorithm(args.algorithm); + builder.finish() + } + + #[inline] + pub fn crs(&self) -> Option<&'a str> { + // Safety: + // Created from valid Table for this object + // which contains a valid value in this slot + unsafe { + self._tab + .get::<::flatbuffers::ForwardsUOffset<&str>>(GeographyType::VT_CRS, None) + } + } + #[inline] + pub fn algorithm(&self) -> EdgeInterpolationAlgorithm { + // Safety: + // Created from valid Table for this object + // which contains a valid value in this slot + unsafe { + self._tab + .get::( + GeographyType::VT_ALGORITHM, + Some(EdgeInterpolationAlgorithm::SPHERICAL), + ) + .unwrap() + } + } + } + + impl ::flatbuffers::Verifiable for GeographyType<'_> { + #[inline] + fn run_verifier( + v: &mut ::flatbuffers::Verifier, + pos: usize, + ) -> Result<(), ::flatbuffers::InvalidFlatbuffer> { + v.visit_table(pos)? + .visit_field::<::flatbuffers::ForwardsUOffset<&str>>( + "crs", + Self::VT_CRS, + false, + )? + .visit_field::( + "algorithm", + Self::VT_ALGORITHM, + false, + )? + .finish(); + Ok(()) + } + } + pub struct GeographyTypeArgs<'a> { + pub crs: Option<::flatbuffers::WIPOffset<&'a str>>, + pub algorithm: EdgeInterpolationAlgorithm, + } + impl<'a> Default for GeographyTypeArgs<'a> { + #[inline] + fn default() -> Self { + GeographyTypeArgs { + crs: None, + algorithm: EdgeInterpolationAlgorithm::SPHERICAL, + } + } + } + + pub struct GeographyTypeBuilder<'a: 'b, 'b, A: ::flatbuffers::Allocator + 'a> { + fbb_: &'b mut ::flatbuffers::FlatBufferBuilder<'a, A>, + start_: ::flatbuffers::WIPOffset<::flatbuffers::TableUnfinishedWIPOffset>, + } + impl<'a: 'b, 'b, A: ::flatbuffers::Allocator + 'a> GeographyTypeBuilder<'a, 'b, A> { + #[inline] + pub fn add_crs(&mut self, crs: ::flatbuffers::WIPOffset<&'b str>) { + self.fbb_ + .push_slot_always::<::flatbuffers::WIPOffset<_>>(GeographyType::VT_CRS, crs); + } + #[inline] + pub fn add_algorithm(&mut self, algorithm: EdgeInterpolationAlgorithm) { + self.fbb_.push_slot::( + GeographyType::VT_ALGORITHM, + algorithm, + EdgeInterpolationAlgorithm::SPHERICAL, + ); + } + #[inline] + pub fn new( + _fbb: &'b mut ::flatbuffers::FlatBufferBuilder<'a, A>, + ) -> GeographyTypeBuilder<'a, 'b, A> { + let start = _fbb.start_table(); + GeographyTypeBuilder { + fbb_: _fbb, + start_: start, + } + } + #[inline] + pub fn finish(self) -> ::flatbuffers::WIPOffset> { + let o = self.fbb_.end_table(self.start_); + ::flatbuffers::WIPOffset::new(o.value()) + } + } + + impl ::core::fmt::Debug for GeographyType<'_> { + fn fmt(&self, f: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result { + let mut ds = f.debug_struct("GeographyType"); + ds.field("crs", &self.crs()); + ds.field("algorithm", &self.algorithm()); + ds.finish() + } + } + pub enum StatisticsOffset {} + #[derive(Copy, Clone, PartialEq)] + + pub struct Statistics<'a> { + pub _tab: ::flatbuffers::Table<'a>, + } + + impl<'a> ::flatbuffers::Follow<'a> for Statistics<'a> { + type Inner = Statistics<'a>; + #[inline] + unsafe fn follow(buf: &'a [u8], loc: usize) -> Self::Inner { + Self { + _tab: unsafe { ::flatbuffers::Table::new(buf, loc) }, + } + } + } + + impl<'a> Statistics<'a> { + pub const VT_NULL_COUNT: ::flatbuffers::VOffsetT = 4; + pub const VT_MIN_LO4: ::flatbuffers::VOffsetT = 6; + pub const VT_MIN_LO8: ::flatbuffers::VOffsetT = 8; + pub const VT_MIN_HI8: ::flatbuffers::VOffsetT = 10; + pub const VT_MIN_LEN: ::flatbuffers::VOffsetT = 12; + pub const VT_MAX_LO4: ::flatbuffers::VOffsetT = 14; + pub const VT_MAX_LO8: ::flatbuffers::VOffsetT = 16; + pub const VT_MAX_HI8: ::flatbuffers::VOffsetT = 18; + pub const VT_MAX_LEN: ::flatbuffers::VOffsetT = 20; + pub const VT_PREFIX: ::flatbuffers::VOffsetT = 22; + + #[inline] + pub unsafe fn init_from_table(table: ::flatbuffers::Table<'a>) -> Self { + Statistics { _tab: table } + } + #[allow(unused_mut)] + pub fn create< + 'bldr: 'args, + 'args: 'mut_bldr, + 'mut_bldr, + A: ::flatbuffers::Allocator + 'bldr, + >( + _fbb: &'mut_bldr mut ::flatbuffers::FlatBufferBuilder<'bldr, A>, + args: &'args StatisticsArgs<'args>, + ) -> ::flatbuffers::WIPOffset> { + let mut builder = StatisticsBuilder::new(_fbb); + builder.add_max_hi8(args.max_hi8); + builder.add_max_lo8(args.max_lo8); + builder.add_min_hi8(args.min_hi8); + builder.add_min_lo8(args.min_lo8); + if let Some(x) = args.prefix { + builder.add_prefix(x); + } + builder.add_max_lo4(args.max_lo4); + builder.add_min_lo4(args.min_lo4); + if let Some(x) = args.null_count { + builder.add_null_count(x); + } + if let Some(x) = args.max_len { + builder.add_max_len(x); + } + if let Some(x) = args.min_len { + builder.add_min_len(x); + } + builder.finish() + } + + #[inline] + pub fn null_count(&self) -> Option { + // Safety: + // Created from valid Table for this object + // which contains a valid value in this slot + unsafe { self._tab.get::(Statistics::VT_NULL_COUNT, None) } + } + #[inline] + pub fn min_lo4(&self) -> u32 { + // Safety: + // Created from valid Table for this object + // which contains a valid value in this slot + unsafe { + self._tab + .get::(Statistics::VT_MIN_LO4, Some(0)) + .unwrap() + } + } + #[inline] + pub fn min_lo8(&self) -> u64 { + // Safety: + // Created from valid Table for this object + // which contains a valid value in this slot + unsafe { + self._tab + .get::(Statistics::VT_MIN_LO8, Some(0)) + .unwrap() + } + } + #[inline] + pub fn min_hi8(&self) -> u64 { + // Safety: + // Created from valid Table for this object + // which contains a valid value in this slot + unsafe { + self._tab + .get::(Statistics::VT_MIN_HI8, Some(0)) + .unwrap() + } + } + #[inline] + pub fn min_len(&self) -> Option { + // Safety: + // Created from valid Table for this object + // which contains a valid value in this slot + unsafe { self._tab.get::(Statistics::VT_MIN_LEN, None) } + } + #[inline] + pub fn max_lo4(&self) -> u32 { + // Safety: + // Created from valid Table for this object + // which contains a valid value in this slot + unsafe { + self._tab + .get::(Statistics::VT_MAX_LO4, Some(0)) + .unwrap() + } + } + #[inline] + pub fn max_lo8(&self) -> u64 { + // Safety: + // Created from valid Table for this object + // which contains a valid value in this slot + unsafe { + self._tab + .get::(Statistics::VT_MAX_LO8, Some(0)) + .unwrap() + } + } + #[inline] + pub fn max_hi8(&self) -> u64 { + // Safety: + // Created from valid Table for this object + // which contains a valid value in this slot + unsafe { + self._tab + .get::(Statistics::VT_MAX_HI8, Some(0)) + .unwrap() + } + } + #[inline] + pub fn max_len(&self) -> Option { + // Safety: + // Created from valid Table for this object + // which contains a valid value in this slot + unsafe { self._tab.get::(Statistics::VT_MAX_LEN, None) } + } + #[inline] + pub fn prefix(&self) -> Option<&'a str> { + // Safety: + // Created from valid Table for this object + // which contains a valid value in this slot + unsafe { + self._tab + .get::<::flatbuffers::ForwardsUOffset<&str>>(Statistics::VT_PREFIX, None) + } + } + } + + impl ::flatbuffers::Verifiable for Statistics<'_> { + #[inline] + fn run_verifier( + v: &mut ::flatbuffers::Verifier, + pos: usize, + ) -> Result<(), ::flatbuffers::InvalidFlatbuffer> { + v.visit_table(pos)? + .visit_field::("null_count", Self::VT_NULL_COUNT, false)? + .visit_field::("min_lo4", Self::VT_MIN_LO4, false)? + .visit_field::("min_lo8", Self::VT_MIN_LO8, false)? + .visit_field::("min_hi8", Self::VT_MIN_HI8, false)? + .visit_field::("min_len", Self::VT_MIN_LEN, false)? + .visit_field::("max_lo4", Self::VT_MAX_LO4, false)? + .visit_field::("max_lo8", Self::VT_MAX_LO8, false)? + .visit_field::("max_hi8", Self::VT_MAX_HI8, false)? + .visit_field::("max_len", Self::VT_MAX_LEN, false)? + .visit_field::<::flatbuffers::ForwardsUOffset<&str>>( + "prefix", + Self::VT_PREFIX, + false, + )? + .finish(); + Ok(()) + } + } + pub struct StatisticsArgs<'a> { + pub null_count: Option, + pub min_lo4: u32, + pub min_lo8: u64, + pub min_hi8: u64, + pub min_len: Option, + pub max_lo4: u32, + pub max_lo8: u64, + pub max_hi8: u64, + pub max_len: Option, + pub prefix: Option<::flatbuffers::WIPOffset<&'a str>>, + } + impl<'a> Default for StatisticsArgs<'a> { + #[inline] + fn default() -> Self { + StatisticsArgs { + null_count: None, + min_lo4: 0, + min_lo8: 0, + min_hi8: 0, + min_len: None, + max_lo4: 0, + max_lo8: 0, + max_hi8: 0, + max_len: None, + prefix: None, + } + } + } + + pub struct StatisticsBuilder<'a: 'b, 'b, A: ::flatbuffers::Allocator + 'a> { + fbb_: &'b mut ::flatbuffers::FlatBufferBuilder<'a, A>, + start_: ::flatbuffers::WIPOffset<::flatbuffers::TableUnfinishedWIPOffset>, + } + impl<'a: 'b, 'b, A: ::flatbuffers::Allocator + 'a> StatisticsBuilder<'a, 'b, A> { + #[inline] + pub fn add_null_count(&mut self, null_count: i32) { + self.fbb_ + .push_slot_always::(Statistics::VT_NULL_COUNT, null_count); + } + #[inline] + pub fn add_min_lo4(&mut self, min_lo4: u32) { + self.fbb_ + .push_slot::(Statistics::VT_MIN_LO4, min_lo4, 0); + } + #[inline] + pub fn add_min_lo8(&mut self, min_lo8: u64) { + self.fbb_ + .push_slot::(Statistics::VT_MIN_LO8, min_lo8, 0); + } + #[inline] + pub fn add_min_hi8(&mut self, min_hi8: u64) { + self.fbb_ + .push_slot::(Statistics::VT_MIN_HI8, min_hi8, 0); + } + #[inline] + pub fn add_min_len(&mut self, min_len: i8) { + self.fbb_ + .push_slot_always::(Statistics::VT_MIN_LEN, min_len); + } + #[inline] + pub fn add_max_lo4(&mut self, max_lo4: u32) { + self.fbb_ + .push_slot::(Statistics::VT_MAX_LO4, max_lo4, 0); + } + #[inline] + pub fn add_max_lo8(&mut self, max_lo8: u64) { + self.fbb_ + .push_slot::(Statistics::VT_MAX_LO8, max_lo8, 0); + } + #[inline] + pub fn add_max_hi8(&mut self, max_hi8: u64) { + self.fbb_ + .push_slot::(Statistics::VT_MAX_HI8, max_hi8, 0); + } + #[inline] + pub fn add_max_len(&mut self, max_len: i8) { + self.fbb_ + .push_slot_always::(Statistics::VT_MAX_LEN, max_len); + } + #[inline] + pub fn add_prefix(&mut self, prefix: ::flatbuffers::WIPOffset<&'b str>) { + self.fbb_ + .push_slot_always::<::flatbuffers::WIPOffset<_>>(Statistics::VT_PREFIX, prefix); + } + #[inline] + pub fn new( + _fbb: &'b mut ::flatbuffers::FlatBufferBuilder<'a, A>, + ) -> StatisticsBuilder<'a, 'b, A> { + let start = _fbb.start_table(); + StatisticsBuilder { + fbb_: _fbb, + start_: start, + } + } + #[inline] + pub fn finish(self) -> ::flatbuffers::WIPOffset> { + let o = self.fbb_.end_table(self.start_); + ::flatbuffers::WIPOffset::new(o.value()) + } + } + + impl ::core::fmt::Debug for Statistics<'_> { + fn fmt(&self, f: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result { + let mut ds = f.debug_struct("Statistics"); + ds.field("null_count", &self.null_count()); + ds.field("min_lo4", &self.min_lo4()); + ds.field("min_lo8", &self.min_lo8()); + ds.field("min_hi8", &self.min_hi8()); + ds.field("min_len", &self.min_len()); + ds.field("max_lo4", &self.max_lo4()); + ds.field("max_lo8", &self.max_lo8()); + ds.field("max_hi8", &self.max_hi8()); + ds.field("max_len", &self.max_len()); + ds.field("prefix", &self.prefix()); + ds.finish() + } + } + pub enum BloomFilterInfoOffset {} + #[derive(Copy, Clone, PartialEq)] + + pub struct BloomFilterInfo<'a> { + pub _tab: ::flatbuffers::Table<'a>, + } + + impl<'a> ::flatbuffers::Follow<'a> for BloomFilterInfo<'a> { + type Inner = BloomFilterInfo<'a>; + #[inline] + unsafe fn follow(buf: &'a [u8], loc: usize) -> Self::Inner { + Self { + _tab: unsafe { ::flatbuffers::Table::new(buf, loc) }, + } + } + } + + impl<'a> BloomFilterInfo<'a> { + pub const VT_OFFSET: ::flatbuffers::VOffsetT = 4; + pub const VT_LENGTH: ::flatbuffers::VOffsetT = 6; + + #[inline] + pub unsafe fn init_from_table(table: ::flatbuffers::Table<'a>) -> Self { + BloomFilterInfo { _tab: table } + } + #[allow(unused_mut)] + pub fn create< + 'bldr: 'args, + 'args: 'mut_bldr, + 'mut_bldr, + A: ::flatbuffers::Allocator + 'bldr, + >( + _fbb: &'mut_bldr mut ::flatbuffers::FlatBufferBuilder<'bldr, A>, + args: &'args BloomFilterInfoArgs, + ) -> ::flatbuffers::WIPOffset> { + let mut builder = BloomFilterInfoBuilder::new(_fbb); + builder.add_offset(args.offset); + builder.add_length(args.length); + builder.finish() + } + + #[inline] + pub fn offset(&self) -> i64 { + // Safety: + // Created from valid Table for this object + // which contains a valid value in this slot + unsafe { + self._tab + .get::(BloomFilterInfo::VT_OFFSET, Some(0)) + .unwrap() + } + } + #[inline] + pub fn length(&self) -> i32 { + // Safety: + // Created from valid Table for this object + // which contains a valid value in this slot + unsafe { + self._tab + .get::(BloomFilterInfo::VT_LENGTH, Some(0)) + .unwrap() + } + } + } + + impl ::flatbuffers::Verifiable for BloomFilterInfo<'_> { + #[inline] + fn run_verifier( + v: &mut ::flatbuffers::Verifier, + pos: usize, + ) -> Result<(), ::flatbuffers::InvalidFlatbuffer> { + v.visit_table(pos)? + .visit_field::("offset", Self::VT_OFFSET, false)? + .visit_field::("length", Self::VT_LENGTH, false)? + .finish(); + Ok(()) + } + } + pub struct BloomFilterInfoArgs { + pub offset: i64, + pub length: i32, + } + impl<'a> Default for BloomFilterInfoArgs { + #[inline] + fn default() -> Self { + BloomFilterInfoArgs { + offset: 0, + length: 0, + } + } + } + + pub struct BloomFilterInfoBuilder<'a: 'b, 'b, A: ::flatbuffers::Allocator + 'a> { + fbb_: &'b mut ::flatbuffers::FlatBufferBuilder<'a, A>, + start_: ::flatbuffers::WIPOffset<::flatbuffers::TableUnfinishedWIPOffset>, + } + impl<'a: 'b, 'b, A: ::flatbuffers::Allocator + 'a> BloomFilterInfoBuilder<'a, 'b, A> { + #[inline] + pub fn add_offset(&mut self, offset: i64) { + self.fbb_ + .push_slot::(BloomFilterInfo::VT_OFFSET, offset, 0); + } + #[inline] + pub fn add_length(&mut self, length: i32) { + self.fbb_ + .push_slot::(BloomFilterInfo::VT_LENGTH, length, 0); + } + #[inline] + pub fn new( + _fbb: &'b mut ::flatbuffers::FlatBufferBuilder<'a, A>, + ) -> BloomFilterInfoBuilder<'a, 'b, A> { + let start = _fbb.start_table(); + BloomFilterInfoBuilder { + fbb_: _fbb, + start_: start, + } + } + #[inline] + pub fn finish(self) -> ::flatbuffers::WIPOffset> { + let o = self.fbb_.end_table(self.start_); + ::flatbuffers::WIPOffset::new(o.value()) + } + } + + impl ::core::fmt::Debug for BloomFilterInfo<'_> { + fn fmt(&self, f: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result { + let mut ds = f.debug_struct("BloomFilterInfo"); + ds.field("offset", &self.offset()); + ds.field("length", &self.length()); + ds.finish() + } + } + pub enum AesGcmV1Offset {} + #[derive(Copy, Clone, PartialEq)] + + pub struct AesGcmV1<'a> { + pub _tab: ::flatbuffers::Table<'a>, + } + + impl<'a> ::flatbuffers::Follow<'a> for AesGcmV1<'a> { + type Inner = AesGcmV1<'a>; + #[inline] + unsafe fn follow(buf: &'a [u8], loc: usize) -> Self::Inner { + Self { + _tab: unsafe { ::flatbuffers::Table::new(buf, loc) }, + } + } + } + + impl<'a> AesGcmV1<'a> { + pub const VT_AAD_PREFIX: ::flatbuffers::VOffsetT = 4; + pub const VT_AAD_FILE_UNIQUE: ::flatbuffers::VOffsetT = 6; + pub const VT_SUPPLY_AAD_PREFIX: ::flatbuffers::VOffsetT = 8; + + #[inline] + pub unsafe fn init_from_table(table: ::flatbuffers::Table<'a>) -> Self { + AesGcmV1 { _tab: table } + } + #[allow(unused_mut)] + pub fn create< + 'bldr: 'args, + 'args: 'mut_bldr, + 'mut_bldr, + A: ::flatbuffers::Allocator + 'bldr, + >( + _fbb: &'mut_bldr mut ::flatbuffers::FlatBufferBuilder<'bldr, A>, + args: &'args AesGcmV1Args<'args>, + ) -> ::flatbuffers::WIPOffset> { + let mut builder = AesGcmV1Builder::new(_fbb); + if let Some(x) = args.aad_file_unique { + builder.add_aad_file_unique(x); + } + if let Some(x) = args.aad_prefix { + builder.add_aad_prefix(x); + } + builder.add_supply_aad_prefix(args.supply_aad_prefix); + builder.finish() + } + + #[inline] + pub fn aad_prefix(&self) -> Option<::flatbuffers::Vector<'a, i8>> { + // Safety: + // Created from valid Table for this object + // which contains a valid value in this slot + unsafe { + self._tab + .get::<::flatbuffers::ForwardsUOffset<::flatbuffers::Vector<'a, i8>>>( + AesGcmV1::VT_AAD_PREFIX, + None, + ) + } + } + #[inline] + pub fn aad_file_unique(&self) -> Option<::flatbuffers::Vector<'a, i8>> { + // Safety: + // Created from valid Table for this object + // which contains a valid value in this slot + unsafe { + self._tab + .get::<::flatbuffers::ForwardsUOffset<::flatbuffers::Vector<'a, i8>>>( + AesGcmV1::VT_AAD_FILE_UNIQUE, + None, + ) + } + } + #[inline] + pub fn supply_aad_prefix(&self) -> bool { + // Safety: + // Created from valid Table for this object + // which contains a valid value in this slot + unsafe { + self._tab + .get::(AesGcmV1::VT_SUPPLY_AAD_PREFIX, Some(false)) + .unwrap() + } + } + } + + impl ::flatbuffers::Verifiable for AesGcmV1<'_> { + #[inline] + fn run_verifier( + v: &mut ::flatbuffers::Verifier, + pos: usize, + ) -> Result<(), ::flatbuffers::InvalidFlatbuffer> { + v.visit_table(pos)? + .visit_field::<::flatbuffers::ForwardsUOffset<::flatbuffers::Vector<'_, i8>>>( + "aad_prefix", + Self::VT_AAD_PREFIX, + false, + )? + .visit_field::<::flatbuffers::ForwardsUOffset<::flatbuffers::Vector<'_, i8>>>( + "aad_file_unique", + Self::VT_AAD_FILE_UNIQUE, + false, + )? + .visit_field::("supply_aad_prefix", Self::VT_SUPPLY_AAD_PREFIX, false)? + .finish(); + Ok(()) + } + } + pub struct AesGcmV1Args<'a> { + pub aad_prefix: Option<::flatbuffers::WIPOffset<::flatbuffers::Vector<'a, i8>>>, + pub aad_file_unique: Option<::flatbuffers::WIPOffset<::flatbuffers::Vector<'a, i8>>>, + pub supply_aad_prefix: bool, + } + impl<'a> Default for AesGcmV1Args<'a> { + #[inline] + fn default() -> Self { + AesGcmV1Args { + aad_prefix: None, + aad_file_unique: None, + supply_aad_prefix: false, + } + } + } + + pub struct AesGcmV1Builder<'a: 'b, 'b, A: ::flatbuffers::Allocator + 'a> { + fbb_: &'b mut ::flatbuffers::FlatBufferBuilder<'a, A>, + start_: ::flatbuffers::WIPOffset<::flatbuffers::TableUnfinishedWIPOffset>, + } + impl<'a: 'b, 'b, A: ::flatbuffers::Allocator + 'a> AesGcmV1Builder<'a, 'b, A> { + #[inline] + pub fn add_aad_prefix( + &mut self, + aad_prefix: ::flatbuffers::WIPOffset<::flatbuffers::Vector<'b, i8>>, + ) { + self.fbb_.push_slot_always::<::flatbuffers::WIPOffset<_>>( + AesGcmV1::VT_AAD_PREFIX, + aad_prefix, + ); + } + #[inline] + pub fn add_aad_file_unique( + &mut self, + aad_file_unique: ::flatbuffers::WIPOffset<::flatbuffers::Vector<'b, i8>>, + ) { + self.fbb_.push_slot_always::<::flatbuffers::WIPOffset<_>>( + AesGcmV1::VT_AAD_FILE_UNIQUE, + aad_file_unique, + ); + } + #[inline] + pub fn add_supply_aad_prefix(&mut self, supply_aad_prefix: bool) { + self.fbb_.push_slot::( + AesGcmV1::VT_SUPPLY_AAD_PREFIX, + supply_aad_prefix, + false, + ); + } + #[inline] + pub fn new( + _fbb: &'b mut ::flatbuffers::FlatBufferBuilder<'a, A>, + ) -> AesGcmV1Builder<'a, 'b, A> { + let start = _fbb.start_table(); + AesGcmV1Builder { + fbb_: _fbb, + start_: start, + } + } + #[inline] + pub fn finish(self) -> ::flatbuffers::WIPOffset> { + let o = self.fbb_.end_table(self.start_); + ::flatbuffers::WIPOffset::new(o.value()) + } + } + + impl ::core::fmt::Debug for AesGcmV1<'_> { + fn fmt(&self, f: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result { + let mut ds = f.debug_struct("AesGcmV1"); + ds.field("aad_prefix", &self.aad_prefix()); + ds.field("aad_file_unique", &self.aad_file_unique()); + ds.field("supply_aad_prefix", &self.supply_aad_prefix()); + ds.finish() + } + } + pub enum AesGcmCtrV1Offset {} + #[derive(Copy, Clone, PartialEq)] + + pub struct AesGcmCtrV1<'a> { + pub _tab: ::flatbuffers::Table<'a>, + } + + impl<'a> ::flatbuffers::Follow<'a> for AesGcmCtrV1<'a> { + type Inner = AesGcmCtrV1<'a>; + #[inline] + unsafe fn follow(buf: &'a [u8], loc: usize) -> Self::Inner { + Self { + _tab: unsafe { ::flatbuffers::Table::new(buf, loc) }, + } + } + } + + impl<'a> AesGcmCtrV1<'a> { + pub const VT_AAD_PREFIX: ::flatbuffers::VOffsetT = 4; + pub const VT_AAD_FILE_UNIQUE: ::flatbuffers::VOffsetT = 6; + pub const VT_SUPPLY_AAD_PREFIX: ::flatbuffers::VOffsetT = 8; + + #[inline] + pub unsafe fn init_from_table(table: ::flatbuffers::Table<'a>) -> Self { + AesGcmCtrV1 { _tab: table } + } + #[allow(unused_mut)] + pub fn create< + 'bldr: 'args, + 'args: 'mut_bldr, + 'mut_bldr, + A: ::flatbuffers::Allocator + 'bldr, + >( + _fbb: &'mut_bldr mut ::flatbuffers::FlatBufferBuilder<'bldr, A>, + args: &'args AesGcmCtrV1Args<'args>, + ) -> ::flatbuffers::WIPOffset> { + let mut builder = AesGcmCtrV1Builder::new(_fbb); + if let Some(x) = args.aad_file_unique { + builder.add_aad_file_unique(x); + } + if let Some(x) = args.aad_prefix { + builder.add_aad_prefix(x); + } + builder.add_supply_aad_prefix(args.supply_aad_prefix); + builder.finish() + } + + #[inline] + pub fn aad_prefix(&self) -> Option<::flatbuffers::Vector<'a, i8>> { + // Safety: + // Created from valid Table for this object + // which contains a valid value in this slot + unsafe { + self._tab + .get::<::flatbuffers::ForwardsUOffset<::flatbuffers::Vector<'a, i8>>>( + AesGcmCtrV1::VT_AAD_PREFIX, + None, + ) + } + } + #[inline] + pub fn aad_file_unique(&self) -> Option<::flatbuffers::Vector<'a, i8>> { + // Safety: + // Created from valid Table for this object + // which contains a valid value in this slot + unsafe { + self._tab + .get::<::flatbuffers::ForwardsUOffset<::flatbuffers::Vector<'a, i8>>>( + AesGcmCtrV1::VT_AAD_FILE_UNIQUE, + None, + ) + } + } + #[inline] + pub fn supply_aad_prefix(&self) -> bool { + // Safety: + // Created from valid Table for this object + // which contains a valid value in this slot + unsafe { + self._tab + .get::(AesGcmCtrV1::VT_SUPPLY_AAD_PREFIX, Some(false)) + .unwrap() + } + } + } + + impl ::flatbuffers::Verifiable for AesGcmCtrV1<'_> { + #[inline] + fn run_verifier( + v: &mut ::flatbuffers::Verifier, + pos: usize, + ) -> Result<(), ::flatbuffers::InvalidFlatbuffer> { + v.visit_table(pos)? + .visit_field::<::flatbuffers::ForwardsUOffset<::flatbuffers::Vector<'_, i8>>>( + "aad_prefix", + Self::VT_AAD_PREFIX, + false, + )? + .visit_field::<::flatbuffers::ForwardsUOffset<::flatbuffers::Vector<'_, i8>>>( + "aad_file_unique", + Self::VT_AAD_FILE_UNIQUE, + false, + )? + .visit_field::("supply_aad_prefix", Self::VT_SUPPLY_AAD_PREFIX, false)? + .finish(); + Ok(()) + } + } + pub struct AesGcmCtrV1Args<'a> { + pub aad_prefix: Option<::flatbuffers::WIPOffset<::flatbuffers::Vector<'a, i8>>>, + pub aad_file_unique: Option<::flatbuffers::WIPOffset<::flatbuffers::Vector<'a, i8>>>, + pub supply_aad_prefix: bool, + } + impl<'a> Default for AesGcmCtrV1Args<'a> { + #[inline] + fn default() -> Self { + AesGcmCtrV1Args { + aad_prefix: None, + aad_file_unique: None, + supply_aad_prefix: false, + } + } + } + + pub struct AesGcmCtrV1Builder<'a: 'b, 'b, A: ::flatbuffers::Allocator + 'a> { + fbb_: &'b mut ::flatbuffers::FlatBufferBuilder<'a, A>, + start_: ::flatbuffers::WIPOffset<::flatbuffers::TableUnfinishedWIPOffset>, + } + impl<'a: 'b, 'b, A: ::flatbuffers::Allocator + 'a> AesGcmCtrV1Builder<'a, 'b, A> { + #[inline] + pub fn add_aad_prefix( + &mut self, + aad_prefix: ::flatbuffers::WIPOffset<::flatbuffers::Vector<'b, i8>>, + ) { + self.fbb_.push_slot_always::<::flatbuffers::WIPOffset<_>>( + AesGcmCtrV1::VT_AAD_PREFIX, + aad_prefix, + ); + } + #[inline] + pub fn add_aad_file_unique( + &mut self, + aad_file_unique: ::flatbuffers::WIPOffset<::flatbuffers::Vector<'b, i8>>, + ) { + self.fbb_.push_slot_always::<::flatbuffers::WIPOffset<_>>( + AesGcmCtrV1::VT_AAD_FILE_UNIQUE, + aad_file_unique, + ); + } + #[inline] + pub fn add_supply_aad_prefix(&mut self, supply_aad_prefix: bool) { + self.fbb_.push_slot::( + AesGcmCtrV1::VT_SUPPLY_AAD_PREFIX, + supply_aad_prefix, + false, + ); + } + #[inline] + pub fn new( + _fbb: &'b mut ::flatbuffers::FlatBufferBuilder<'a, A>, + ) -> AesGcmCtrV1Builder<'a, 'b, A> { + let start = _fbb.start_table(); + AesGcmCtrV1Builder { + fbb_: _fbb, + start_: start, + } + } + #[inline] + pub fn finish(self) -> ::flatbuffers::WIPOffset> { + let o = self.fbb_.end_table(self.start_); + ::flatbuffers::WIPOffset::new(o.value()) + } + } + + impl ::core::fmt::Debug for AesGcmCtrV1<'_> { + fn fmt(&self, f: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result { + let mut ds = f.debug_struct("AesGcmCtrV1"); + ds.field("aad_prefix", &self.aad_prefix()); + ds.field("aad_file_unique", &self.aad_file_unique()); + ds.field("supply_aad_prefix", &self.supply_aad_prefix()); + ds.finish() + } + } + pub enum SchemaElementOffset {} + #[derive(Copy, Clone, PartialEq)] + + pub struct SchemaElement<'a> { + pub _tab: ::flatbuffers::Table<'a>, + } + + impl<'a> ::flatbuffers::Follow<'a> for SchemaElement<'a> { + type Inner = SchemaElement<'a>; + #[inline] + unsafe fn follow(buf: &'a [u8], loc: usize) -> Self::Inner { + Self { + _tab: unsafe { ::flatbuffers::Table::new(buf, loc) }, + } + } + } + + impl<'a> SchemaElement<'a> { + pub const VT_NAME: ::flatbuffers::VOffsetT = 4; + pub const VT_TYPE_: ::flatbuffers::VOffsetT = 6; + pub const VT_REPETITION_TYPE: ::flatbuffers::VOffsetT = 8; + pub const VT_LOGICAL_TYPE_TYPE: ::flatbuffers::VOffsetT = 10; + pub const VT_LOGICAL_TYPE: ::flatbuffers::VOffsetT = 12; + pub const VT_TYPE_LENGTH: ::flatbuffers::VOffsetT = 14; + pub const VT_NUM_CHILDREN: ::flatbuffers::VOffsetT = 16; + pub const VT_FIELD_ID: ::flatbuffers::VOffsetT = 18; + pub const VT_COLUMN_ORDER_TYPE: ::flatbuffers::VOffsetT = 20; + pub const VT_COLUMN_ORDER: ::flatbuffers::VOffsetT = 22; + + #[inline] + pub unsafe fn init_from_table(table: ::flatbuffers::Table<'a>) -> Self { + SchemaElement { _tab: table } + } + #[allow(unused_mut)] + pub fn create< + 'bldr: 'args, + 'args: 'mut_bldr, + 'mut_bldr, + A: ::flatbuffers::Allocator + 'bldr, + >( + _fbb: &'mut_bldr mut ::flatbuffers::FlatBufferBuilder<'bldr, A>, + args: &'args SchemaElementArgs<'args>, + ) -> ::flatbuffers::WIPOffset> { + let mut builder = SchemaElementBuilder::new(_fbb); + if let Some(x) = args.column_order { + builder.add_column_order(x); + } + if let Some(x) = args.field_id { + builder.add_field_id(x); + } + builder.add_num_children(args.num_children); + if let Some(x) = args.type_length { + builder.add_type_length(x); + } + if let Some(x) = args.logical_type { + builder.add_logical_type(x); + } + if let Some(x) = args.name { + builder.add_name(x); + } + builder.add_column_order_type(args.column_order_type); + builder.add_logical_type_type(args.logical_type_type); + builder.add_repetition_type(args.repetition_type); + if let Some(x) = args.type_ { + builder.add_type_(x); + } + builder.finish() + } + + #[inline] + pub fn name(&self) -> Option<&'a str> { + // Safety: + // Created from valid Table for this object + // which contains a valid value in this slot + unsafe { + self._tab + .get::<::flatbuffers::ForwardsUOffset<&str>>(SchemaElement::VT_NAME, None) + } + } + #[inline] + pub fn type_(&self) -> Option { + // Safety: + // Created from valid Table for this object + // which contains a valid value in this slot + unsafe { self._tab.get::(SchemaElement::VT_TYPE_, None) } + } + #[inline] + pub fn repetition_type(&self) -> FieldRepetitionType { + // Safety: + // Created from valid Table for this object + // which contains a valid value in this slot + unsafe { + self._tab + .get::( + SchemaElement::VT_REPETITION_TYPE, + Some(FieldRepetitionType::REQUIRED), + ) + .unwrap() + } + } + #[inline] + pub fn logical_type_type(&self) -> LogicalType { + // Safety: + // Created from valid Table for this object + // which contains a valid value in this slot + unsafe { + self._tab + .get::( + SchemaElement::VT_LOGICAL_TYPE_TYPE, + Some(LogicalType::NONE), + ) + .unwrap() + } + } + #[inline] + pub fn logical_type(&self) -> Option<::flatbuffers::Table<'a>> { + // Safety: + // Created from valid Table for this object + // which contains a valid value in this slot + unsafe { + self._tab + .get::<::flatbuffers::ForwardsUOffset<::flatbuffers::Table<'a>>>( + SchemaElement::VT_LOGICAL_TYPE, + None, + ) + } + } + #[inline] + pub fn type_length(&self) -> Option { + // Safety: + // Created from valid Table for this object + // which contains a valid value in this slot + unsafe { self._tab.get::(SchemaElement::VT_TYPE_LENGTH, None) } + } + #[inline] + pub fn num_children(&self) -> i32 { + // Safety: + // Created from valid Table for this object + // which contains a valid value in this slot + unsafe { + self._tab + .get::(SchemaElement::VT_NUM_CHILDREN, Some(0)) + .unwrap() + } + } + #[inline] + pub fn field_id(&self) -> Option { + // Safety: + // Created from valid Table for this object + // which contains a valid value in this slot + unsafe { self._tab.get::(SchemaElement::VT_FIELD_ID, None) } + } + #[inline] + pub fn column_order_type(&self) -> ColumnOrder { + // Safety: + // Created from valid Table for this object + // which contains a valid value in this slot + unsafe { + self._tab + .get::( + SchemaElement::VT_COLUMN_ORDER_TYPE, + Some(ColumnOrder::NONE), + ) + .unwrap() + } + } + #[inline] + pub fn column_order(&self) -> Option<::flatbuffers::Table<'a>> { + // Safety: + // Created from valid Table for this object + // which contains a valid value in this slot + unsafe { + self._tab + .get::<::flatbuffers::ForwardsUOffset<::flatbuffers::Table<'a>>>( + SchemaElement::VT_COLUMN_ORDER, + None, + ) + } + } + #[inline] + #[allow(non_snake_case)] + pub fn logical_type_as_string_type(&self) -> Option> { + if self.logical_type_type() == LogicalType::StringType { + self.logical_type().map(|t| { + // Safety: + // Created from a valid Table for this object + // Which contains a valid union in this slot + unsafe { Empty::init_from_table(t) } + }) + } else { + None + } + } + + #[inline] + #[allow(non_snake_case)] + pub fn logical_type_as_map_type(&self) -> Option> { + if self.logical_type_type() == LogicalType::MapType { + self.logical_type().map(|t| { + // Safety: + // Created from a valid Table for this object + // Which contains a valid union in this slot + unsafe { Empty::init_from_table(t) } + }) + } else { + None + } + } + + #[inline] + #[allow(non_snake_case)] + pub fn logical_type_as_list_type(&self) -> Option> { + if self.logical_type_type() == LogicalType::ListType { + self.logical_type().map(|t| { + // Safety: + // Created from a valid Table for this object + // Which contains a valid union in this slot + unsafe { Empty::init_from_table(t) } + }) + } else { + None + } + } + + #[inline] + #[allow(non_snake_case)] + pub fn logical_type_as_enum_type(&self) -> Option> { + if self.logical_type_type() == LogicalType::EnumType { + self.logical_type().map(|t| { + // Safety: + // Created from a valid Table for this object + // Which contains a valid union in this slot + unsafe { Empty::init_from_table(t) } + }) + } else { + None + } + } + + #[inline] + #[allow(non_snake_case)] + pub fn logical_type_as_decimal_type(&self) -> Option> { + if self.logical_type_type() == LogicalType::DecimalType { + self.logical_type().map(|t| { + // Safety: + // Created from a valid Table for this object + // Which contains a valid union in this slot + unsafe { DecimalOptions::init_from_table(t) } + }) + } else { + None + } + } + + #[inline] + #[allow(non_snake_case)] + pub fn logical_type_as_date_type(&self) -> Option> { + if self.logical_type_type() == LogicalType::DateType { + self.logical_type().map(|t| { + // Safety: + // Created from a valid Table for this object + // Which contains a valid union in this slot + unsafe { Empty::init_from_table(t) } + }) + } else { + None + } + } + + #[inline] + #[allow(non_snake_case)] + pub fn logical_type_as_time_type(&self) -> Option> { + if self.logical_type_type() == LogicalType::TimeType { + self.logical_type().map(|t| { + // Safety: + // Created from a valid Table for this object + // Which contains a valid union in this slot + unsafe { TimeOptions::init_from_table(t) } + }) + } else { + None + } + } + + #[inline] + #[allow(non_snake_case)] + pub fn logical_type_as_timestamp_type(&self) -> Option> { + if self.logical_type_type() == LogicalType::TimestampType { + self.logical_type().map(|t| { + // Safety: + // Created from a valid Table for this object + // Which contains a valid union in this slot + unsafe { TimeOptions::init_from_table(t) } + }) + } else { + None + } + } + + #[inline] + #[allow(non_snake_case)] + pub fn logical_type_as_int_type(&self) -> Option> { + if self.logical_type_type() == LogicalType::IntType { + self.logical_type().map(|t| { + // Safety: + // Created from a valid Table for this object + // Which contains a valid union in this slot + unsafe { IntOptions::init_from_table(t) } + }) + } else { + None + } + } + + #[inline] + #[allow(non_snake_case)] + pub fn logical_type_as_null_type(&self) -> Option> { + if self.logical_type_type() == LogicalType::NullType { + self.logical_type().map(|t| { + // Safety: + // Created from a valid Table for this object + // Which contains a valid union in this slot + unsafe { Empty::init_from_table(t) } + }) + } else { + None + } + } + + #[inline] + #[allow(non_snake_case)] + pub fn logical_type_as_json_type(&self) -> Option> { + if self.logical_type_type() == LogicalType::JsonType { + self.logical_type().map(|t| { + // Safety: + // Created from a valid Table for this object + // Which contains a valid union in this slot + unsafe { Empty::init_from_table(t) } + }) + } else { + None + } + } + + #[inline] + #[allow(non_snake_case)] + pub fn logical_type_as_bson_type(&self) -> Option> { + if self.logical_type_type() == LogicalType::BsonType { + self.logical_type().map(|t| { + // Safety: + // Created from a valid Table for this object + // Which contains a valid union in this slot + unsafe { Empty::init_from_table(t) } + }) + } else { + None + } + } + + #[inline] + #[allow(non_snake_case)] + pub fn logical_type_as_uuidtype(&self) -> Option> { + if self.logical_type_type() == LogicalType::UUIDType { + self.logical_type().map(|t| { + // Safety: + // Created from a valid Table for this object + // Which contains a valid union in this slot + unsafe { Empty::init_from_table(t) } + }) + } else { + None + } + } + + #[inline] + #[allow(non_snake_case)] + pub fn logical_type_as_float_16_type(&self) -> Option> { + if self.logical_type_type() == LogicalType::Float16Type { + self.logical_type().map(|t| { + // Safety: + // Created from a valid Table for this object + // Which contains a valid union in this slot + unsafe { Empty::init_from_table(t) } + }) + } else { + None + } + } + + #[inline] + #[allow(non_snake_case)] + pub fn logical_type_as_variant_type(&self) -> Option> { + if self.logical_type_type() == LogicalType::VariantType { + self.logical_type().map(|t| { + // Safety: + // Created from a valid Table for this object + // Which contains a valid union in this slot + unsafe { VariantType::init_from_table(t) } + }) + } else { + None + } + } + + #[inline] + #[allow(non_snake_case)] + pub fn logical_type_as_geometry_type(&self) -> Option> { + if self.logical_type_type() == LogicalType::GeometryType { + self.logical_type().map(|t| { + // Safety: + // Created from a valid Table for this object + // Which contains a valid union in this slot + unsafe { GeometryType::init_from_table(t) } + }) + } else { + None + } + } + + #[inline] + #[allow(non_snake_case)] + pub fn logical_type_as_geography_type(&self) -> Option> { + if self.logical_type_type() == LogicalType::GeographyType { + self.logical_type().map(|t| { + // Safety: + // Created from a valid Table for this object + // Which contains a valid union in this slot + unsafe { GeographyType::init_from_table(t) } + }) + } else { + None + } + } + + #[inline] + #[allow(non_snake_case)] + pub fn column_order_as_type_defined_order(&self) -> Option> { + if self.column_order_type() == ColumnOrder::TypeDefinedOrder { + self.column_order().map(|t| { + // Safety: + // Created from a valid Table for this object + // Which contains a valid union in this slot + unsafe { Empty::init_from_table(t) } + }) + } else { + None + } + } + } + + impl ::flatbuffers::Verifiable for SchemaElement<'_> { + #[inline] + fn run_verifier( + v: &mut ::flatbuffers::Verifier, + pos: usize, + ) -> Result<(), ::flatbuffers::InvalidFlatbuffer> { + v.visit_table(pos)? + .visit_field::<::flatbuffers::ForwardsUOffset<&str>>("name", Self::VT_NAME, false)? + .visit_field::("type_", Self::VT_TYPE_, false)? + .visit_field::("repetition_type", Self::VT_REPETITION_TYPE, false)? + .visit_union::("logical_type_type", Self::VT_LOGICAL_TYPE_TYPE, "logical_type", Self::VT_LOGICAL_TYPE, false, |key, v, pos| { + match key { + LogicalType::StringType => v.verify_union_variant::<::flatbuffers::ForwardsUOffset>("LogicalType::StringType", pos), + LogicalType::MapType => v.verify_union_variant::<::flatbuffers::ForwardsUOffset>("LogicalType::MapType", pos), + LogicalType::ListType => v.verify_union_variant::<::flatbuffers::ForwardsUOffset>("LogicalType::ListType", pos), + LogicalType::EnumType => v.verify_union_variant::<::flatbuffers::ForwardsUOffset>("LogicalType::EnumType", pos), + LogicalType::DecimalType => v.verify_union_variant::<::flatbuffers::ForwardsUOffset>("LogicalType::DecimalType", pos), + LogicalType::DateType => v.verify_union_variant::<::flatbuffers::ForwardsUOffset>("LogicalType::DateType", pos), + LogicalType::TimeType => v.verify_union_variant::<::flatbuffers::ForwardsUOffset>("LogicalType::TimeType", pos), + LogicalType::TimestampType => v.verify_union_variant::<::flatbuffers::ForwardsUOffset>("LogicalType::TimestampType", pos), + LogicalType::IntType => v.verify_union_variant::<::flatbuffers::ForwardsUOffset>("LogicalType::IntType", pos), + LogicalType::NullType => v.verify_union_variant::<::flatbuffers::ForwardsUOffset>("LogicalType::NullType", pos), + LogicalType::JsonType => v.verify_union_variant::<::flatbuffers::ForwardsUOffset>("LogicalType::JsonType", pos), + LogicalType::BsonType => v.verify_union_variant::<::flatbuffers::ForwardsUOffset>("LogicalType::BsonType", pos), + LogicalType::UUIDType => v.verify_union_variant::<::flatbuffers::ForwardsUOffset>("LogicalType::UUIDType", pos), + LogicalType::Float16Type => v.verify_union_variant::<::flatbuffers::ForwardsUOffset>("LogicalType::Float16Type", pos), + LogicalType::VariantType => v.verify_union_variant::<::flatbuffers::ForwardsUOffset>("LogicalType::VariantType", pos), + LogicalType::GeometryType => v.verify_union_variant::<::flatbuffers::ForwardsUOffset>("LogicalType::GeometryType", pos), + LogicalType::GeographyType => v.verify_union_variant::<::flatbuffers::ForwardsUOffset>("LogicalType::GeographyType", pos), + _ => Ok(()), + } + })? + .visit_field::("type_length", Self::VT_TYPE_LENGTH, false)? + .visit_field::("num_children", Self::VT_NUM_CHILDREN, false)? + .visit_field::("field_id", Self::VT_FIELD_ID, false)? + .visit_union::("column_order_type", Self::VT_COLUMN_ORDER_TYPE, "column_order", Self::VT_COLUMN_ORDER, false, |key, v, pos| { + match key { + ColumnOrder::TypeDefinedOrder => v.verify_union_variant::<::flatbuffers::ForwardsUOffset>("ColumnOrder::TypeDefinedOrder", pos), + _ => Ok(()), + } + })? + .finish(); + Ok(()) + } + } + pub struct SchemaElementArgs<'a> { + pub name: Option<::flatbuffers::WIPOffset<&'a str>>, + pub type_: Option, + pub repetition_type: FieldRepetitionType, + pub logical_type_type: LogicalType, + pub logical_type: Option<::flatbuffers::WIPOffset<::flatbuffers::UnionWIPOffset>>, + pub type_length: Option, + pub num_children: i32, + pub field_id: Option, + pub column_order_type: ColumnOrder, + pub column_order: Option<::flatbuffers::WIPOffset<::flatbuffers::UnionWIPOffset>>, + } + impl<'a> Default for SchemaElementArgs<'a> { + #[inline] + fn default() -> Self { + SchemaElementArgs { + name: None, + type_: None, + repetition_type: FieldRepetitionType::REQUIRED, + logical_type_type: LogicalType::NONE, + logical_type: None, + type_length: None, + num_children: 0, + field_id: None, + column_order_type: ColumnOrder::NONE, + column_order: None, + } + } + } + + pub struct SchemaElementBuilder<'a: 'b, 'b, A: ::flatbuffers::Allocator + 'a> { + fbb_: &'b mut ::flatbuffers::FlatBufferBuilder<'a, A>, + start_: ::flatbuffers::WIPOffset<::flatbuffers::TableUnfinishedWIPOffset>, + } + impl<'a: 'b, 'b, A: ::flatbuffers::Allocator + 'a> SchemaElementBuilder<'a, 'b, A> { + #[inline] + pub fn add_name(&mut self, name: ::flatbuffers::WIPOffset<&'b str>) { + self.fbb_ + .push_slot_always::<::flatbuffers::WIPOffset<_>>(SchemaElement::VT_NAME, name); + } + #[inline] + pub fn add_type_(&mut self, type_: Type) { + self.fbb_ + .push_slot_always::(SchemaElement::VT_TYPE_, type_); + } + #[inline] + pub fn add_repetition_type(&mut self, repetition_type: FieldRepetitionType) { + self.fbb_.push_slot::( + SchemaElement::VT_REPETITION_TYPE, + repetition_type, + FieldRepetitionType::REQUIRED, + ); + } + #[inline] + pub fn add_logical_type_type(&mut self, logical_type_type: LogicalType) { + self.fbb_.push_slot::( + SchemaElement::VT_LOGICAL_TYPE_TYPE, + logical_type_type, + LogicalType::NONE, + ); + } + #[inline] + pub fn add_logical_type( + &mut self, + logical_type: ::flatbuffers::WIPOffset<::flatbuffers::UnionWIPOffset>, + ) { + self.fbb_.push_slot_always::<::flatbuffers::WIPOffset<_>>( + SchemaElement::VT_LOGICAL_TYPE, + logical_type, + ); + } + #[inline] + pub fn add_type_length(&mut self, type_length: i32) { + self.fbb_ + .push_slot_always::(SchemaElement::VT_TYPE_LENGTH, type_length); + } + #[inline] + pub fn add_num_children(&mut self, num_children: i32) { + self.fbb_ + .push_slot::(SchemaElement::VT_NUM_CHILDREN, num_children, 0); + } + #[inline] + pub fn add_field_id(&mut self, field_id: i32) { + self.fbb_ + .push_slot_always::(SchemaElement::VT_FIELD_ID, field_id); + } + #[inline] + pub fn add_column_order_type(&mut self, column_order_type: ColumnOrder) { + self.fbb_.push_slot::( + SchemaElement::VT_COLUMN_ORDER_TYPE, + column_order_type, + ColumnOrder::NONE, + ); + } + #[inline] + pub fn add_column_order( + &mut self, + column_order: ::flatbuffers::WIPOffset<::flatbuffers::UnionWIPOffset>, + ) { + self.fbb_.push_slot_always::<::flatbuffers::WIPOffset<_>>( + SchemaElement::VT_COLUMN_ORDER, + column_order, + ); + } + #[inline] + pub fn new( + _fbb: &'b mut ::flatbuffers::FlatBufferBuilder<'a, A>, + ) -> SchemaElementBuilder<'a, 'b, A> { + let start = _fbb.start_table(); + SchemaElementBuilder { + fbb_: _fbb, + start_: start, + } + } + #[inline] + pub fn finish(self) -> ::flatbuffers::WIPOffset> { + let o = self.fbb_.end_table(self.start_); + ::flatbuffers::WIPOffset::new(o.value()) + } + } + + impl ::core::fmt::Debug for SchemaElement<'_> { + fn fmt(&self, f: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result { + let mut ds = f.debug_struct("SchemaElement"); + ds.field("name", &self.name()); + ds.field("type_", &self.type_()); + ds.field("repetition_type", &self.repetition_type()); + ds.field("logical_type_type", &self.logical_type_type()); + match self.logical_type_type() { + LogicalType::StringType => { + if let Some(x) = self.logical_type_as_string_type() { + ds.field("logical_type", &x) + } else { + ds.field( + "logical_type", + &"InvalidFlatbuffer: Union discriminant does not match value.", + ) + } + } + LogicalType::MapType => { + if let Some(x) = self.logical_type_as_map_type() { + ds.field("logical_type", &x) + } else { + ds.field( + "logical_type", + &"InvalidFlatbuffer: Union discriminant does not match value.", + ) + } + } + LogicalType::ListType => { + if let Some(x) = self.logical_type_as_list_type() { + ds.field("logical_type", &x) + } else { + ds.field( + "logical_type", + &"InvalidFlatbuffer: Union discriminant does not match value.", + ) + } + } + LogicalType::EnumType => { + if let Some(x) = self.logical_type_as_enum_type() { + ds.field("logical_type", &x) + } else { + ds.field( + "logical_type", + &"InvalidFlatbuffer: Union discriminant does not match value.", + ) + } + } + LogicalType::DecimalType => { + if let Some(x) = self.logical_type_as_decimal_type() { + ds.field("logical_type", &x) + } else { + ds.field( + "logical_type", + &"InvalidFlatbuffer: Union discriminant does not match value.", + ) + } + } + LogicalType::DateType => { + if let Some(x) = self.logical_type_as_date_type() { + ds.field("logical_type", &x) + } else { + ds.field( + "logical_type", + &"InvalidFlatbuffer: Union discriminant does not match value.", + ) + } + } + LogicalType::TimeType => { + if let Some(x) = self.logical_type_as_time_type() { + ds.field("logical_type", &x) + } else { + ds.field( + "logical_type", + &"InvalidFlatbuffer: Union discriminant does not match value.", + ) + } + } + LogicalType::TimestampType => { + if let Some(x) = self.logical_type_as_timestamp_type() { + ds.field("logical_type", &x) + } else { + ds.field( + "logical_type", + &"InvalidFlatbuffer: Union discriminant does not match value.", + ) + } + } + LogicalType::IntType => { + if let Some(x) = self.logical_type_as_int_type() { + ds.field("logical_type", &x) + } else { + ds.field( + "logical_type", + &"InvalidFlatbuffer: Union discriminant does not match value.", + ) + } + } + LogicalType::NullType => { + if let Some(x) = self.logical_type_as_null_type() { + ds.field("logical_type", &x) + } else { + ds.field( + "logical_type", + &"InvalidFlatbuffer: Union discriminant does not match value.", + ) + } + } + LogicalType::JsonType => { + if let Some(x) = self.logical_type_as_json_type() { + ds.field("logical_type", &x) + } else { + ds.field( + "logical_type", + &"InvalidFlatbuffer: Union discriminant does not match value.", + ) + } + } + LogicalType::BsonType => { + if let Some(x) = self.logical_type_as_bson_type() { + ds.field("logical_type", &x) + } else { + ds.field( + "logical_type", + &"InvalidFlatbuffer: Union discriminant does not match value.", + ) + } + } + LogicalType::UUIDType => { + if let Some(x) = self.logical_type_as_uuidtype() { + ds.field("logical_type", &x) + } else { + ds.field( + "logical_type", + &"InvalidFlatbuffer: Union discriminant does not match value.", + ) + } + } + LogicalType::Float16Type => { + if let Some(x) = self.logical_type_as_float_16_type() { + ds.field("logical_type", &x) + } else { + ds.field( + "logical_type", + &"InvalidFlatbuffer: Union discriminant does not match value.", + ) + } + } + LogicalType::VariantType => { + if let Some(x) = self.logical_type_as_variant_type() { + ds.field("logical_type", &x) + } else { + ds.field( + "logical_type", + &"InvalidFlatbuffer: Union discriminant does not match value.", + ) + } + } + LogicalType::GeometryType => { + if let Some(x) = self.logical_type_as_geometry_type() { + ds.field("logical_type", &x) + } else { + ds.field( + "logical_type", + &"InvalidFlatbuffer: Union discriminant does not match value.", + ) + } + } + LogicalType::GeographyType => { + if let Some(x) = self.logical_type_as_geography_type() { + ds.field("logical_type", &x) + } else { + ds.field( + "logical_type", + &"InvalidFlatbuffer: Union discriminant does not match value.", + ) + } + } + _ => { + let x: Option<()> = None; + ds.field("logical_type", &x) + } + }; + ds.field("type_length", &self.type_length()); + ds.field("num_children", &self.num_children()); + ds.field("field_id", &self.field_id()); + ds.field("column_order_type", &self.column_order_type()); + match self.column_order_type() { + ColumnOrder::TypeDefinedOrder => { + if let Some(x) = self.column_order_as_type_defined_order() { + ds.field("column_order", &x) + } else { + ds.field( + "column_order", + &"InvalidFlatbuffer: Union discriminant does not match value.", + ) + } + } + _ => { + let x: Option<()> = None; + ds.field("column_order", &x) + } + }; + ds.finish() + } + } + pub enum KeyValueOffset {} + #[derive(Copy, Clone, PartialEq)] + + pub struct KeyValue<'a> { + pub _tab: ::flatbuffers::Table<'a>, + } + + impl<'a> ::flatbuffers::Follow<'a> for KeyValue<'a> { + type Inner = KeyValue<'a>; + #[inline] + unsafe fn follow(buf: &'a [u8], loc: usize) -> Self::Inner { + Self { + _tab: unsafe { ::flatbuffers::Table::new(buf, loc) }, + } + } + } + + impl<'a> KeyValue<'a> { + pub const VT_KEY: ::flatbuffers::VOffsetT = 4; + pub const VT_VAL: ::flatbuffers::VOffsetT = 6; + + #[inline] + pub unsafe fn init_from_table(table: ::flatbuffers::Table<'a>) -> Self { + KeyValue { _tab: table } + } + #[allow(unused_mut)] + pub fn create< + 'bldr: 'args, + 'args: 'mut_bldr, + 'mut_bldr, + A: ::flatbuffers::Allocator + 'bldr, + >( + _fbb: &'mut_bldr mut ::flatbuffers::FlatBufferBuilder<'bldr, A>, + args: &'args KeyValueArgs<'args>, + ) -> ::flatbuffers::WIPOffset> { + let mut builder = KeyValueBuilder::new(_fbb); + if let Some(x) = args.val { + builder.add_val(x); + } + if let Some(x) = args.key { + builder.add_key(x); + } + builder.finish() + } + + #[inline] + pub fn key(&self) -> Option<&'a str> { + // Safety: + // Created from valid Table for this object + // which contains a valid value in this slot + unsafe { + self._tab + .get::<::flatbuffers::ForwardsUOffset<&str>>(KeyValue::VT_KEY, None) + } + } + #[inline] + pub fn val(&self) -> Option<&'a str> { + // Safety: + // Created from valid Table for this object + // which contains a valid value in this slot + unsafe { + self._tab + .get::<::flatbuffers::ForwardsUOffset<&str>>(KeyValue::VT_VAL, None) + } + } + } + + impl ::flatbuffers::Verifiable for KeyValue<'_> { + #[inline] + fn run_verifier( + v: &mut ::flatbuffers::Verifier, + pos: usize, + ) -> Result<(), ::flatbuffers::InvalidFlatbuffer> { + v.visit_table(pos)? + .visit_field::<::flatbuffers::ForwardsUOffset<&str>>( + "key", + Self::VT_KEY, + false, + )? + .visit_field::<::flatbuffers::ForwardsUOffset<&str>>( + "val", + Self::VT_VAL, + false, + )? + .finish(); + Ok(()) + } + } + pub struct KeyValueArgs<'a> { + pub key: Option<::flatbuffers::WIPOffset<&'a str>>, + pub val: Option<::flatbuffers::WIPOffset<&'a str>>, + } + impl<'a> Default for KeyValueArgs<'a> { + #[inline] + fn default() -> Self { + KeyValueArgs { + key: None, + val: None, + } + } + } + + pub struct KeyValueBuilder<'a: 'b, 'b, A: ::flatbuffers::Allocator + 'a> { + fbb_: &'b mut ::flatbuffers::FlatBufferBuilder<'a, A>, + start_: ::flatbuffers::WIPOffset<::flatbuffers::TableUnfinishedWIPOffset>, + } + impl<'a: 'b, 'b, A: ::flatbuffers::Allocator + 'a> KeyValueBuilder<'a, 'b, A> { + #[inline] + pub fn add_key(&mut self, key: ::flatbuffers::WIPOffset<&'b str>) { + self.fbb_ + .push_slot_always::<::flatbuffers::WIPOffset<_>>(KeyValue::VT_KEY, key); + } + #[inline] + pub fn add_val(&mut self, val: ::flatbuffers::WIPOffset<&'b str>) { + self.fbb_ + .push_slot_always::<::flatbuffers::WIPOffset<_>>(KeyValue::VT_VAL, val); + } + #[inline] + pub fn new( + _fbb: &'b mut ::flatbuffers::FlatBufferBuilder<'a, A>, + ) -> KeyValueBuilder<'a, 'b, A> { + let start = _fbb.start_table(); + KeyValueBuilder { + fbb_: _fbb, + start_: start, + } + } + #[inline] + pub fn finish(self) -> ::flatbuffers::WIPOffset> { + let o = self.fbb_.end_table(self.start_); + ::flatbuffers::WIPOffset::new(o.value()) + } + } + + impl ::core::fmt::Debug for KeyValue<'_> { + fn fmt(&self, f: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result { + let mut ds = f.debug_struct("KeyValue"); + ds.field("key", &self.key()); + ds.field("val", &self.val()); + ds.finish() + } + } + pub enum ColumnMetadataOffset {} + #[derive(Copy, Clone, PartialEq)] + + pub struct ColumnMetadata<'a> { + pub _tab: ::flatbuffers::Table<'a>, + } + + impl<'a> ::flatbuffers::Follow<'a> for ColumnMetadata<'a> { + type Inner = ColumnMetadata<'a>; + #[inline] + unsafe fn follow(buf: &'a [u8], loc: usize) -> Self::Inner { + Self { + _tab: unsafe { ::flatbuffers::Table::new(buf, loc) }, + } + } + } + + impl<'a> ColumnMetadata<'a> { + pub const VT_CODEC: ::flatbuffers::VOffsetT = 4; + pub const VT_NUM_VALUES: ::flatbuffers::VOffsetT = 6; + pub const VT_TOTAL_UNCOMPRESSED_SIZE: ::flatbuffers::VOffsetT = 8; + pub const VT_TOTAL_COMPRESSED_SIZE: ::flatbuffers::VOffsetT = 10; + pub const VT_KEY_VALUE_METADATA: ::flatbuffers::VOffsetT = 12; + pub const VT_DATA_PAGE_OFFSET: ::flatbuffers::VOffsetT = 14; + pub const VT_INDEX_PAGE_OFFSET: ::flatbuffers::VOffsetT = 16; + pub const VT_DICTIONARY_PAGE_OFFSET: ::flatbuffers::VOffsetT = 18; + pub const VT_STATISTICS: ::flatbuffers::VOffsetT = 20; + pub const VT_IS_FULLY_DICT_ENCODED: ::flatbuffers::VOffsetT = 22; + pub const VT_BLOOM_FILTER: ::flatbuffers::VOffsetT = 24; + + #[inline] + pub unsafe fn init_from_table(table: ::flatbuffers::Table<'a>) -> Self { + ColumnMetadata { _tab: table } + } + #[allow(unused_mut)] + pub fn create< + 'bldr: 'args, + 'args: 'mut_bldr, + 'mut_bldr, + A: ::flatbuffers::Allocator + 'bldr, + >( + _fbb: &'mut_bldr mut ::flatbuffers::FlatBufferBuilder<'bldr, A>, + args: &'args ColumnMetadataArgs<'args>, + ) -> ::flatbuffers::WIPOffset> { + let mut builder = ColumnMetadataBuilder::new(_fbb); + if let Some(x) = args.dictionary_page_offset { + builder.add_dictionary_page_offset(x); + } + if let Some(x) = args.index_page_offset { + builder.add_index_page_offset(x); + } + builder.add_data_page_offset(args.data_page_offset); + builder.add_total_compressed_size(args.total_compressed_size); + builder.add_total_uncompressed_size(args.total_uncompressed_size); + if let Some(x) = args.num_values { + builder.add_num_values(x); + } + if let Some(x) = args.bloom_filter { + builder.add_bloom_filter(x); + } + if let Some(x) = args.statistics { + builder.add_statistics(x); + } + if let Some(x) = args.key_value_metadata { + builder.add_key_value_metadata(x); + } + builder.add_is_fully_dict_encoded(args.is_fully_dict_encoded); + builder.add_codec(args.codec); + builder.finish() + } + + #[inline] + pub fn codec(&self) -> CompressionCodec { + // Safety: + // Created from valid Table for this object + // which contains a valid value in this slot + unsafe { + self._tab + .get::( + ColumnMetadata::VT_CODEC, + Some(CompressionCodec::UNCOMPRESSED), + ) + .unwrap() + } + } + #[inline] + pub fn num_values(&self) -> Option { + // Safety: + // Created from valid Table for this object + // which contains a valid value in this slot + unsafe { self._tab.get::(ColumnMetadata::VT_NUM_VALUES, None) } + } + #[inline] + pub fn total_uncompressed_size(&self) -> i64 { + // Safety: + // Created from valid Table for this object + // which contains a valid value in this slot + unsafe { + self._tab + .get::(ColumnMetadata::VT_TOTAL_UNCOMPRESSED_SIZE, Some(0)) + .unwrap() + } + } + #[inline] + pub fn total_compressed_size(&self) -> i64 { + // Safety: + // Created from valid Table for this object + // which contains a valid value in this slot + unsafe { + self._tab + .get::(ColumnMetadata::VT_TOTAL_COMPRESSED_SIZE, Some(0)) + .unwrap() + } + } + #[inline] + pub fn key_value_metadata( + &self, + ) -> Option<::flatbuffers::Vector<'a, ::flatbuffers::ForwardsUOffset>>> + { + // Safety: + // Created from valid Table for this object + // which contains a valid value in this slot + unsafe { + self._tab.get::<::flatbuffers::ForwardsUOffset< + ::flatbuffers::Vector<'a, ::flatbuffers::ForwardsUOffset>, + >>(ColumnMetadata::VT_KEY_VALUE_METADATA, None) + } + } + #[inline] + pub fn data_page_offset(&self) -> i64 { + // Safety: + // Created from valid Table for this object + // which contains a valid value in this slot + unsafe { + self._tab + .get::(ColumnMetadata::VT_DATA_PAGE_OFFSET, Some(0)) + .unwrap() + } + } + #[inline] + pub fn index_page_offset(&self) -> Option { + // Safety: + // Created from valid Table for this object + // which contains a valid value in this slot + unsafe { + self._tab + .get::(ColumnMetadata::VT_INDEX_PAGE_OFFSET, None) + } + } + #[inline] + pub fn dictionary_page_offset(&self) -> Option { + // Safety: + // Created from valid Table for this object + // which contains a valid value in this slot + unsafe { + self._tab + .get::(ColumnMetadata::VT_DICTIONARY_PAGE_OFFSET, None) + } + } + #[inline] + pub fn statistics(&self) -> Option> { + // Safety: + // Created from valid Table for this object + // which contains a valid value in this slot + unsafe { + self._tab.get::<::flatbuffers::ForwardsUOffset>( + ColumnMetadata::VT_STATISTICS, + None, + ) + } + } + #[inline] + pub fn is_fully_dict_encoded(&self) -> bool { + // Safety: + // Created from valid Table for this object + // which contains a valid value in this slot + unsafe { + self._tab + .get::(ColumnMetadata::VT_IS_FULLY_DICT_ENCODED, Some(false)) + .unwrap() + } + } + #[inline] + pub fn bloom_filter(&self) -> Option> { + // Safety: + // Created from valid Table for this object + // which contains a valid value in this slot + unsafe { + self._tab + .get::<::flatbuffers::ForwardsUOffset>( + ColumnMetadata::VT_BLOOM_FILTER, + None, + ) + } + } + } + + impl ::flatbuffers::Verifiable for ColumnMetadata<'_> { + #[inline] + fn run_verifier( + v: &mut ::flatbuffers::Verifier, + pos: usize, + ) -> Result<(), ::flatbuffers::InvalidFlatbuffer> { + v.visit_table(pos)? + .visit_field::("codec", Self::VT_CODEC, false)? + .visit_field::("num_values", Self::VT_NUM_VALUES, false)? + .visit_field::( + "total_uncompressed_size", + Self::VT_TOTAL_UNCOMPRESSED_SIZE, + false, + )? + .visit_field::( + "total_compressed_size", + Self::VT_TOTAL_COMPRESSED_SIZE, + false, + )? + .visit_field::<::flatbuffers::ForwardsUOffset< + ::flatbuffers::Vector<'_, ::flatbuffers::ForwardsUOffset>, + >>("key_value_metadata", Self::VT_KEY_VALUE_METADATA, false)? + .visit_field::("data_page_offset", Self::VT_DATA_PAGE_OFFSET, false)? + .visit_field::("index_page_offset", Self::VT_INDEX_PAGE_OFFSET, false)? + .visit_field::( + "dictionary_page_offset", + Self::VT_DICTIONARY_PAGE_OFFSET, + false, + )? + .visit_field::<::flatbuffers::ForwardsUOffset>( + "statistics", + Self::VT_STATISTICS, + false, + )? + .visit_field::( + "is_fully_dict_encoded", + Self::VT_IS_FULLY_DICT_ENCODED, + false, + )? + .visit_field::<::flatbuffers::ForwardsUOffset>( + "bloom_filter", + Self::VT_BLOOM_FILTER, + false, + )? + .finish(); + Ok(()) + } + } + pub struct ColumnMetadataArgs<'a> { + pub codec: CompressionCodec, + pub num_values: Option, + pub total_uncompressed_size: i64, + pub total_compressed_size: i64, + pub key_value_metadata: Option< + ::flatbuffers::WIPOffset< + ::flatbuffers::Vector<'a, ::flatbuffers::ForwardsUOffset>>, + >, + >, + pub data_page_offset: i64, + pub index_page_offset: Option, + pub dictionary_page_offset: Option, + pub statistics: Option<::flatbuffers::WIPOffset>>, + pub is_fully_dict_encoded: bool, + pub bloom_filter: Option<::flatbuffers::WIPOffset>>, + } + impl<'a> Default for ColumnMetadataArgs<'a> { + #[inline] + fn default() -> Self { + ColumnMetadataArgs { + codec: CompressionCodec::UNCOMPRESSED, + num_values: None, + total_uncompressed_size: 0, + total_compressed_size: 0, + key_value_metadata: None, + data_page_offset: 0, + index_page_offset: None, + dictionary_page_offset: None, + statistics: None, + is_fully_dict_encoded: false, + bloom_filter: None, + } + } + } + + pub struct ColumnMetadataBuilder<'a: 'b, 'b, A: ::flatbuffers::Allocator + 'a> { + fbb_: &'b mut ::flatbuffers::FlatBufferBuilder<'a, A>, + start_: ::flatbuffers::WIPOffset<::flatbuffers::TableUnfinishedWIPOffset>, + } + impl<'a: 'b, 'b, A: ::flatbuffers::Allocator + 'a> ColumnMetadataBuilder<'a, 'b, A> { + #[inline] + pub fn add_codec(&mut self, codec: CompressionCodec) { + self.fbb_.push_slot::( + ColumnMetadata::VT_CODEC, + codec, + CompressionCodec::UNCOMPRESSED, + ); + } + #[inline] + pub fn add_num_values(&mut self, num_values: i64) { + self.fbb_ + .push_slot_always::(ColumnMetadata::VT_NUM_VALUES, num_values); + } + #[inline] + pub fn add_total_uncompressed_size(&mut self, total_uncompressed_size: i64) { + self.fbb_.push_slot::( + ColumnMetadata::VT_TOTAL_UNCOMPRESSED_SIZE, + total_uncompressed_size, + 0, + ); + } + #[inline] + pub fn add_total_compressed_size(&mut self, total_compressed_size: i64) { + self.fbb_.push_slot::( + ColumnMetadata::VT_TOTAL_COMPRESSED_SIZE, + total_compressed_size, + 0, + ); + } + #[inline] + pub fn add_key_value_metadata( + &mut self, + key_value_metadata: ::flatbuffers::WIPOffset< + ::flatbuffers::Vector<'b, ::flatbuffers::ForwardsUOffset>>, + >, + ) { + self.fbb_.push_slot_always::<::flatbuffers::WIPOffset<_>>( + ColumnMetadata::VT_KEY_VALUE_METADATA, + key_value_metadata, + ); + } + #[inline] + pub fn add_data_page_offset(&mut self, data_page_offset: i64) { + self.fbb_.push_slot::( + ColumnMetadata::VT_DATA_PAGE_OFFSET, + data_page_offset, + 0, + ); + } + #[inline] + pub fn add_index_page_offset(&mut self, index_page_offset: i64) { + self.fbb_.push_slot_always::( + ColumnMetadata::VT_INDEX_PAGE_OFFSET, + index_page_offset, + ); + } + #[inline] + pub fn add_dictionary_page_offset(&mut self, dictionary_page_offset: i64) { + self.fbb_.push_slot_always::( + ColumnMetadata::VT_DICTIONARY_PAGE_OFFSET, + dictionary_page_offset, + ); + } + #[inline] + pub fn add_statistics(&mut self, statistics: ::flatbuffers::WIPOffset>) { + self.fbb_ + .push_slot_always::<::flatbuffers::WIPOffset>( + ColumnMetadata::VT_STATISTICS, + statistics, + ); + } + #[inline] + pub fn add_is_fully_dict_encoded(&mut self, is_fully_dict_encoded: bool) { + self.fbb_.push_slot::( + ColumnMetadata::VT_IS_FULLY_DICT_ENCODED, + is_fully_dict_encoded, + false, + ); + } + #[inline] + pub fn add_bloom_filter( + &mut self, + bloom_filter: ::flatbuffers::WIPOffset>, + ) { + self.fbb_ + .push_slot_always::<::flatbuffers::WIPOffset>( + ColumnMetadata::VT_BLOOM_FILTER, + bloom_filter, + ); + } + #[inline] + pub fn new( + _fbb: &'b mut ::flatbuffers::FlatBufferBuilder<'a, A>, + ) -> ColumnMetadataBuilder<'a, 'b, A> { + let start = _fbb.start_table(); + ColumnMetadataBuilder { + fbb_: _fbb, + start_: start, + } + } + #[inline] + pub fn finish(self) -> ::flatbuffers::WIPOffset> { + let o = self.fbb_.end_table(self.start_); + ::flatbuffers::WIPOffset::new(o.value()) + } + } + + impl ::core::fmt::Debug for ColumnMetadata<'_> { + fn fmt(&self, f: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result { + let mut ds = f.debug_struct("ColumnMetadata"); + ds.field("codec", &self.codec()); + ds.field("num_values", &self.num_values()); + ds.field("total_uncompressed_size", &self.total_uncompressed_size()); + ds.field("total_compressed_size", &self.total_compressed_size()); + ds.field("key_value_metadata", &self.key_value_metadata()); + ds.field("data_page_offset", &self.data_page_offset()); + ds.field("index_page_offset", &self.index_page_offset()); + ds.field("dictionary_page_offset", &self.dictionary_page_offset()); + ds.field("statistics", &self.statistics()); + ds.field("is_fully_dict_encoded", &self.is_fully_dict_encoded()); + ds.field("bloom_filter", &self.bloom_filter()); + ds.finish() + } + } + pub enum ColumnChunkOffset {} + #[derive(Copy, Clone, PartialEq)] + + pub struct ColumnChunk<'a> { + pub _tab: ::flatbuffers::Table<'a>, + } + + impl<'a> ::flatbuffers::Follow<'a> for ColumnChunk<'a> { + type Inner = ColumnChunk<'a>; + #[inline] + unsafe fn follow(buf: &'a [u8], loc: usize) -> Self::Inner { + Self { + _tab: unsafe { ::flatbuffers::Table::new(buf, loc) }, + } + } + } + + impl<'a> ColumnChunk<'a> { + pub const VT_META_DATA: ::flatbuffers::VOffsetT = 4; + pub const VT_CRYPTO_METADATA_TYPE: ::flatbuffers::VOffsetT = 6; + pub const VT_CRYPTO_METADATA: ::flatbuffers::VOffsetT = 8; + pub const VT_ENCRYPTED_COLUMN_METADATA: ::flatbuffers::VOffsetT = 10; + + #[inline] + pub unsafe fn init_from_table(table: ::flatbuffers::Table<'a>) -> Self { + ColumnChunk { _tab: table } + } + #[allow(unused_mut)] + pub fn create< + 'bldr: 'args, + 'args: 'mut_bldr, + 'mut_bldr, + A: ::flatbuffers::Allocator + 'bldr, + >( + _fbb: &'mut_bldr mut ::flatbuffers::FlatBufferBuilder<'bldr, A>, + args: &'args ColumnChunkArgs<'args>, + ) -> ::flatbuffers::WIPOffset> { + let mut builder = ColumnChunkBuilder::new(_fbb); + if let Some(x) = args.encrypted_column_metadata { + builder.add_encrypted_column_metadata(x); + } + if let Some(x) = args.crypto_metadata { + builder.add_crypto_metadata(x); + } + if let Some(x) = args.meta_data { + builder.add_meta_data(x); + } + builder.add_crypto_metadata_type(args.crypto_metadata_type); + builder.finish() + } + + #[inline] + pub fn meta_data(&self) -> Option> { + // Safety: + // Created from valid Table for this object + // which contains a valid value in this slot + unsafe { + self._tab + .get::<::flatbuffers::ForwardsUOffset>( + ColumnChunk::VT_META_DATA, + None, + ) + } + } + #[inline] + pub fn crypto_metadata_type(&self) -> ColumnCryptoMetadata { + // Safety: + // Created from valid Table for this object + // which contains a valid value in this slot + unsafe { + self._tab + .get::( + ColumnChunk::VT_CRYPTO_METADATA_TYPE, + Some(ColumnCryptoMetadata::NONE), + ) + .unwrap() + } + } + #[inline] + pub fn crypto_metadata(&self) -> Option<::flatbuffers::Table<'a>> { + // Safety: + // Created from valid Table for this object + // which contains a valid value in this slot + unsafe { + self._tab + .get::<::flatbuffers::ForwardsUOffset<::flatbuffers::Table<'a>>>( + ColumnChunk::VT_CRYPTO_METADATA, + None, + ) + } + } + #[inline] + pub fn encrypted_column_metadata(&self) -> Option<::flatbuffers::Vector<'a, i8>> { + // Safety: + // Created from valid Table for this object + // which contains a valid value in this slot + unsafe { + self._tab + .get::<::flatbuffers::ForwardsUOffset<::flatbuffers::Vector<'a, i8>>>( + ColumnChunk::VT_ENCRYPTED_COLUMN_METADATA, + None, + ) + } + } + #[inline] + #[allow(non_snake_case)] + pub fn crypto_metadata_as_encryption_with_footer_key(&self) -> Option> { + if self.crypto_metadata_type() == ColumnCryptoMetadata::EncryptionWithFooterKey { + self.crypto_metadata().map(|t| { + // Safety: + // Created from a valid Table for this object + // Which contains a valid union in this slot + unsafe { Empty::init_from_table(t) } + }) + } else { + None + } + } + + #[inline] + #[allow(non_snake_case)] + pub fn crypto_metadata_as_encryption_with_column_key(&self) -> Option> { + if self.crypto_metadata_type() == ColumnCryptoMetadata::EncryptionWithColumnKey { + self.crypto_metadata().map(|t| { + // Safety: + // Created from a valid Table for this object + // Which contains a valid union in this slot + unsafe { Empty::init_from_table(t) } + }) + } else { + None + } + } + } + + impl ::flatbuffers::Verifiable for ColumnChunk<'_> { + #[inline] + fn run_verifier( + v: &mut ::flatbuffers::Verifier, + pos: usize, + ) -> Result<(), ::flatbuffers::InvalidFlatbuffer> { + v.visit_table(pos)? + .visit_field::<::flatbuffers::ForwardsUOffset>( + "meta_data", + Self::VT_META_DATA, + false, + )? + .visit_union::( + "crypto_metadata_type", + Self::VT_CRYPTO_METADATA_TYPE, + "crypto_metadata", + Self::VT_CRYPTO_METADATA, + false, + |key, v, pos| match key { + ColumnCryptoMetadata::EncryptionWithFooterKey => { + v.verify_union_variant::<::flatbuffers::ForwardsUOffset>( + "ColumnCryptoMetadata::EncryptionWithFooterKey", + pos, + ) + } + ColumnCryptoMetadata::EncryptionWithColumnKey => { + v.verify_union_variant::<::flatbuffers::ForwardsUOffset>( + "ColumnCryptoMetadata::EncryptionWithColumnKey", + pos, + ) + } + _ => Ok(()), + }, + )? + .visit_field::<::flatbuffers::ForwardsUOffset<::flatbuffers::Vector<'_, i8>>>( + "encrypted_column_metadata", + Self::VT_ENCRYPTED_COLUMN_METADATA, + false, + )? + .finish(); + Ok(()) + } + } + pub struct ColumnChunkArgs<'a> { + pub meta_data: Option<::flatbuffers::WIPOffset>>, + pub crypto_metadata_type: ColumnCryptoMetadata, + pub crypto_metadata: Option<::flatbuffers::WIPOffset<::flatbuffers::UnionWIPOffset>>, + pub encrypted_column_metadata: + Option<::flatbuffers::WIPOffset<::flatbuffers::Vector<'a, i8>>>, + } + impl<'a> Default for ColumnChunkArgs<'a> { + #[inline] + fn default() -> Self { + ColumnChunkArgs { + meta_data: None, + crypto_metadata_type: ColumnCryptoMetadata::NONE, + crypto_metadata: None, + encrypted_column_metadata: None, + } + } + } + + pub struct ColumnChunkBuilder<'a: 'b, 'b, A: ::flatbuffers::Allocator + 'a> { + fbb_: &'b mut ::flatbuffers::FlatBufferBuilder<'a, A>, + start_: ::flatbuffers::WIPOffset<::flatbuffers::TableUnfinishedWIPOffset>, + } + impl<'a: 'b, 'b, A: ::flatbuffers::Allocator + 'a> ColumnChunkBuilder<'a, 'b, A> { + #[inline] + pub fn add_meta_data( + &mut self, + meta_data: ::flatbuffers::WIPOffset>, + ) { + self.fbb_ + .push_slot_always::<::flatbuffers::WIPOffset>( + ColumnChunk::VT_META_DATA, + meta_data, + ); + } + #[inline] + pub fn add_crypto_metadata_type(&mut self, crypto_metadata_type: ColumnCryptoMetadata) { + self.fbb_.push_slot::( + ColumnChunk::VT_CRYPTO_METADATA_TYPE, + crypto_metadata_type, + ColumnCryptoMetadata::NONE, + ); + } + #[inline] + pub fn add_crypto_metadata( + &mut self, + crypto_metadata: ::flatbuffers::WIPOffset<::flatbuffers::UnionWIPOffset>, + ) { + self.fbb_.push_slot_always::<::flatbuffers::WIPOffset<_>>( + ColumnChunk::VT_CRYPTO_METADATA, + crypto_metadata, + ); + } + #[inline] + pub fn add_encrypted_column_metadata( + &mut self, + encrypted_column_metadata: ::flatbuffers::WIPOffset<::flatbuffers::Vector<'b, i8>>, + ) { + self.fbb_.push_slot_always::<::flatbuffers::WIPOffset<_>>( + ColumnChunk::VT_ENCRYPTED_COLUMN_METADATA, + encrypted_column_metadata, + ); + } + #[inline] + pub fn new( + _fbb: &'b mut ::flatbuffers::FlatBufferBuilder<'a, A>, + ) -> ColumnChunkBuilder<'a, 'b, A> { + let start = _fbb.start_table(); + ColumnChunkBuilder { + fbb_: _fbb, + start_: start, + } + } + #[inline] + pub fn finish(self) -> ::flatbuffers::WIPOffset> { + let o = self.fbb_.end_table(self.start_); + ::flatbuffers::WIPOffset::new(o.value()) + } + } + + impl ::core::fmt::Debug for ColumnChunk<'_> { + fn fmt(&self, f: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result { + let mut ds = f.debug_struct("ColumnChunk"); + ds.field("meta_data", &self.meta_data()); + ds.field("crypto_metadata_type", &self.crypto_metadata_type()); + match self.crypto_metadata_type() { + ColumnCryptoMetadata::EncryptionWithFooterKey => { + if let Some(x) = self.crypto_metadata_as_encryption_with_footer_key() { + ds.field("crypto_metadata", &x) + } else { + ds.field( + "crypto_metadata", + &"InvalidFlatbuffer: Union discriminant does not match value.", + ) + } + } + ColumnCryptoMetadata::EncryptionWithColumnKey => { + if let Some(x) = self.crypto_metadata_as_encryption_with_column_key() { + ds.field("crypto_metadata", &x) + } else { + ds.field( + "crypto_metadata", + &"InvalidFlatbuffer: Union discriminant does not match value.", + ) + } + } + _ => { + let x: Option<()> = None; + ds.field("crypto_metadata", &x) + } + }; + ds.field( + "encrypted_column_metadata", + &self.encrypted_column_metadata(), + ); + ds.finish() + } + } + pub enum SortingColumnOffset {} + #[derive(Copy, Clone, PartialEq)] + + pub struct SortingColumn<'a> { + pub _tab: ::flatbuffers::Table<'a>, + } + + impl<'a> ::flatbuffers::Follow<'a> for SortingColumn<'a> { + type Inner = SortingColumn<'a>; + #[inline] + unsafe fn follow(buf: &'a [u8], loc: usize) -> Self::Inner { + Self { + _tab: unsafe { ::flatbuffers::Table::new(buf, loc) }, + } + } + } + + impl<'a> SortingColumn<'a> { + pub const VT_COLUMN_IDX: ::flatbuffers::VOffsetT = 4; + pub const VT_DESCENDING: ::flatbuffers::VOffsetT = 6; + pub const VT_NULLS_FIRST: ::flatbuffers::VOffsetT = 8; + + #[inline] + pub unsafe fn init_from_table(table: ::flatbuffers::Table<'a>) -> Self { + SortingColumn { _tab: table } + } + #[allow(unused_mut)] + pub fn create< + 'bldr: 'args, + 'args: 'mut_bldr, + 'mut_bldr, + A: ::flatbuffers::Allocator + 'bldr, + >( + _fbb: &'mut_bldr mut ::flatbuffers::FlatBufferBuilder<'bldr, A>, + args: &'args SortingColumnArgs, + ) -> ::flatbuffers::WIPOffset> { + let mut builder = SortingColumnBuilder::new(_fbb); + builder.add_column_idx(args.column_idx); + builder.add_nulls_first(args.nulls_first); + builder.add_descending(args.descending); + builder.finish() + } + + #[inline] + pub fn column_idx(&self) -> i32 { + // Safety: + // Created from valid Table for this object + // which contains a valid value in this slot + unsafe { + self._tab + .get::(SortingColumn::VT_COLUMN_IDX, Some(0)) + .unwrap() + } + } + #[inline] + pub fn descending(&self) -> bool { + // Safety: + // Created from valid Table for this object + // which contains a valid value in this slot + unsafe { + self._tab + .get::(SortingColumn::VT_DESCENDING, Some(false)) + .unwrap() + } + } + #[inline] + pub fn nulls_first(&self) -> bool { + // Safety: + // Created from valid Table for this object + // which contains a valid value in this slot + unsafe { + self._tab + .get::(SortingColumn::VT_NULLS_FIRST, Some(false)) + .unwrap() + } + } + } + + impl ::flatbuffers::Verifiable for SortingColumn<'_> { + #[inline] + fn run_verifier( + v: &mut ::flatbuffers::Verifier, + pos: usize, + ) -> Result<(), ::flatbuffers::InvalidFlatbuffer> { + v.visit_table(pos)? + .visit_field::("column_idx", Self::VT_COLUMN_IDX, false)? + .visit_field::("descending", Self::VT_DESCENDING, false)? + .visit_field::("nulls_first", Self::VT_NULLS_FIRST, false)? + .finish(); + Ok(()) + } + } + pub struct SortingColumnArgs { + pub column_idx: i32, + pub descending: bool, + pub nulls_first: bool, + } + impl<'a> Default for SortingColumnArgs { + #[inline] + fn default() -> Self { + SortingColumnArgs { + column_idx: 0, + descending: false, + nulls_first: false, + } + } + } + + pub struct SortingColumnBuilder<'a: 'b, 'b, A: ::flatbuffers::Allocator + 'a> { + fbb_: &'b mut ::flatbuffers::FlatBufferBuilder<'a, A>, + start_: ::flatbuffers::WIPOffset<::flatbuffers::TableUnfinishedWIPOffset>, + } + impl<'a: 'b, 'b, A: ::flatbuffers::Allocator + 'a> SortingColumnBuilder<'a, 'b, A> { + #[inline] + pub fn add_column_idx(&mut self, column_idx: i32) { + self.fbb_ + .push_slot::(SortingColumn::VT_COLUMN_IDX, column_idx, 0); + } + #[inline] + pub fn add_descending(&mut self, descending: bool) { + self.fbb_ + .push_slot::(SortingColumn::VT_DESCENDING, descending, false); + } + #[inline] + pub fn add_nulls_first(&mut self, nulls_first: bool) { + self.fbb_ + .push_slot::(SortingColumn::VT_NULLS_FIRST, nulls_first, false); + } + #[inline] + pub fn new( + _fbb: &'b mut ::flatbuffers::FlatBufferBuilder<'a, A>, + ) -> SortingColumnBuilder<'a, 'b, A> { + let start = _fbb.start_table(); + SortingColumnBuilder { + fbb_: _fbb, + start_: start, + } + } + #[inline] + pub fn finish(self) -> ::flatbuffers::WIPOffset> { + let o = self.fbb_.end_table(self.start_); + ::flatbuffers::WIPOffset::new(o.value()) + } + } + + impl ::core::fmt::Debug for SortingColumn<'_> { + fn fmt(&self, f: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result { + let mut ds = f.debug_struct("SortingColumn"); + ds.field("column_idx", &self.column_idx()); + ds.field("descending", &self.descending()); + ds.field("nulls_first", &self.nulls_first()); + ds.finish() + } + } + pub enum RowGroupOffset {} + #[derive(Copy, Clone, PartialEq)] + + pub struct RowGroup<'a> { + pub _tab: ::flatbuffers::Table<'a>, + } + + impl<'a> ::flatbuffers::Follow<'a> for RowGroup<'a> { + type Inner = RowGroup<'a>; + #[inline] + unsafe fn follow(buf: &'a [u8], loc: usize) -> Self::Inner { + Self { + _tab: unsafe { ::flatbuffers::Table::new(buf, loc) }, + } + } + } + + impl<'a> RowGroup<'a> { + pub const VT_COLUMNS: ::flatbuffers::VOffsetT = 4; + pub const VT_TOTAL_BYTE_SIZE: ::flatbuffers::VOffsetT = 6; + pub const VT_NUM_ROWS: ::flatbuffers::VOffsetT = 8; + pub const VT_SORTING_COLUMNS: ::flatbuffers::VOffsetT = 10; + pub const VT_FILE_OFFSET: ::flatbuffers::VOffsetT = 12; + pub const VT_TOTAL_COMPRESSED_SIZE: ::flatbuffers::VOffsetT = 14; + pub const VT_ORDINAL: ::flatbuffers::VOffsetT = 16; + + #[inline] + pub unsafe fn init_from_table(table: ::flatbuffers::Table<'a>) -> Self { + RowGroup { _tab: table } + } + #[allow(unused_mut)] + pub fn create< + 'bldr: 'args, + 'args: 'mut_bldr, + 'mut_bldr, + A: ::flatbuffers::Allocator + 'bldr, + >( + _fbb: &'mut_bldr mut ::flatbuffers::FlatBufferBuilder<'bldr, A>, + args: &'args RowGroupArgs<'args>, + ) -> ::flatbuffers::WIPOffset> { + let mut builder = RowGroupBuilder::new(_fbb); + builder.add_total_compressed_size(args.total_compressed_size); + builder.add_file_offset(args.file_offset); + builder.add_num_rows(args.num_rows); + builder.add_total_byte_size(args.total_byte_size); + if let Some(x) = args.sorting_columns { + builder.add_sorting_columns(x); + } + if let Some(x) = args.columns { + builder.add_columns(x); + } + if let Some(x) = args.ordinal { + builder.add_ordinal(x); + } + builder.finish() + } + + #[inline] + pub fn columns( + &self, + ) -> Option<::flatbuffers::Vector<'a, ::flatbuffers::ForwardsUOffset>>> + { + // Safety: + // Created from valid Table for this object + // which contains a valid value in this slot + unsafe { + self._tab.get::<::flatbuffers::ForwardsUOffset< + ::flatbuffers::Vector<'a, ::flatbuffers::ForwardsUOffset>, + >>(RowGroup::VT_COLUMNS, None) + } + } + #[inline] + pub fn total_byte_size(&self) -> i64 { + // Safety: + // Created from valid Table for this object + // which contains a valid value in this slot + unsafe { + self._tab + .get::(RowGroup::VT_TOTAL_BYTE_SIZE, Some(0)) + .unwrap() + } + } + #[inline] + pub fn num_rows(&self) -> i64 { + // Safety: + // Created from valid Table for this object + // which contains a valid value in this slot + unsafe { + self._tab + .get::(RowGroup::VT_NUM_ROWS, Some(0)) + .unwrap() + } + } + #[inline] + pub fn sorting_columns( + &self, + ) -> Option<::flatbuffers::Vector<'a, ::flatbuffers::ForwardsUOffset>>> + { + // Safety: + // Created from valid Table for this object + // which contains a valid value in this slot + unsafe { + self._tab.get::<::flatbuffers::ForwardsUOffset< + ::flatbuffers::Vector<'a, ::flatbuffers::ForwardsUOffset>, + >>(RowGroup::VT_SORTING_COLUMNS, None) + } + } + #[inline] + pub fn file_offset(&self) -> i64 { + // Safety: + // Created from valid Table for this object + // which contains a valid value in this slot + unsafe { + self._tab + .get::(RowGroup::VT_FILE_OFFSET, Some(0)) + .unwrap() + } + } + #[inline] + pub fn total_compressed_size(&self) -> i64 { + // Safety: + // Created from valid Table for this object + // which contains a valid value in this slot + unsafe { + self._tab + .get::(RowGroup::VT_TOTAL_COMPRESSED_SIZE, Some(0)) + .unwrap() + } + } + #[inline] + pub fn ordinal(&self) -> Option { + // Safety: + // Created from valid Table for this object + // which contains a valid value in this slot + unsafe { self._tab.get::(RowGroup::VT_ORDINAL, None) } + } + } + + impl ::flatbuffers::Verifiable for RowGroup<'_> { + #[inline] + fn run_verifier( + v: &mut ::flatbuffers::Verifier, + pos: usize, + ) -> Result<(), ::flatbuffers::InvalidFlatbuffer> { + v.visit_table(pos)? + .visit_field::<::flatbuffers::ForwardsUOffset< + ::flatbuffers::Vector<'_, ::flatbuffers::ForwardsUOffset>, + >>("columns", Self::VT_COLUMNS, false)? + .visit_field::("total_byte_size", Self::VT_TOTAL_BYTE_SIZE, false)? + .visit_field::("num_rows", Self::VT_NUM_ROWS, false)? + .visit_field::<::flatbuffers::ForwardsUOffset< + ::flatbuffers::Vector<'_, ::flatbuffers::ForwardsUOffset>, + >>("sorting_columns", Self::VT_SORTING_COLUMNS, false)? + .visit_field::("file_offset", Self::VT_FILE_OFFSET, false)? + .visit_field::( + "total_compressed_size", + Self::VT_TOTAL_COMPRESSED_SIZE, + false, + )? + .visit_field::("ordinal", Self::VT_ORDINAL, false)? + .finish(); + Ok(()) + } + } + pub struct RowGroupArgs<'a> { + pub columns: Option< + ::flatbuffers::WIPOffset< + ::flatbuffers::Vector<'a, ::flatbuffers::ForwardsUOffset>>, + >, + >, + pub total_byte_size: i64, + pub num_rows: i64, + pub sorting_columns: Option< + ::flatbuffers::WIPOffset< + ::flatbuffers::Vector<'a, ::flatbuffers::ForwardsUOffset>>, + >, + >, + pub file_offset: i64, + pub total_compressed_size: i64, + pub ordinal: Option, + } + impl<'a> Default for RowGroupArgs<'a> { + #[inline] + fn default() -> Self { + RowGroupArgs { + columns: None, + total_byte_size: 0, + num_rows: 0, + sorting_columns: None, + file_offset: 0, + total_compressed_size: 0, + ordinal: None, + } + } + } + + pub struct RowGroupBuilder<'a: 'b, 'b, A: ::flatbuffers::Allocator + 'a> { + fbb_: &'b mut ::flatbuffers::FlatBufferBuilder<'a, A>, + start_: ::flatbuffers::WIPOffset<::flatbuffers::TableUnfinishedWIPOffset>, + } + impl<'a: 'b, 'b, A: ::flatbuffers::Allocator + 'a> RowGroupBuilder<'a, 'b, A> { + #[inline] + pub fn add_columns( + &mut self, + columns: ::flatbuffers::WIPOffset< + ::flatbuffers::Vector<'b, ::flatbuffers::ForwardsUOffset>>, + >, + ) { + self.fbb_ + .push_slot_always::<::flatbuffers::WIPOffset<_>>(RowGroup::VT_COLUMNS, columns); + } + #[inline] + pub fn add_total_byte_size(&mut self, total_byte_size: i64) { + self.fbb_ + .push_slot::(RowGroup::VT_TOTAL_BYTE_SIZE, total_byte_size, 0); + } + #[inline] + pub fn add_num_rows(&mut self, num_rows: i64) { + self.fbb_ + .push_slot::(RowGroup::VT_NUM_ROWS, num_rows, 0); + } + #[inline] + pub fn add_sorting_columns( + &mut self, + sorting_columns: ::flatbuffers::WIPOffset< + ::flatbuffers::Vector<'b, ::flatbuffers::ForwardsUOffset>>, + >, + ) { + self.fbb_.push_slot_always::<::flatbuffers::WIPOffset<_>>( + RowGroup::VT_SORTING_COLUMNS, + sorting_columns, + ); + } + #[inline] + pub fn add_file_offset(&mut self, file_offset: i64) { + self.fbb_ + .push_slot::(RowGroup::VT_FILE_OFFSET, file_offset, 0); + } + #[inline] + pub fn add_total_compressed_size(&mut self, total_compressed_size: i64) { + self.fbb_.push_slot::( + RowGroup::VT_TOTAL_COMPRESSED_SIZE, + total_compressed_size, + 0, + ); + } + #[inline] + pub fn add_ordinal(&mut self, ordinal: i16) { + self.fbb_ + .push_slot_always::(RowGroup::VT_ORDINAL, ordinal); + } + #[inline] + pub fn new( + _fbb: &'b mut ::flatbuffers::FlatBufferBuilder<'a, A>, + ) -> RowGroupBuilder<'a, 'b, A> { + let start = _fbb.start_table(); + RowGroupBuilder { + fbb_: _fbb, + start_: start, + } + } + #[inline] + pub fn finish(self) -> ::flatbuffers::WIPOffset> { + let o = self.fbb_.end_table(self.start_); + ::flatbuffers::WIPOffset::new(o.value()) + } + } + + impl ::core::fmt::Debug for RowGroup<'_> { + fn fmt(&self, f: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result { + let mut ds = f.debug_struct("RowGroup"); + ds.field("columns", &self.columns()); + ds.field("total_byte_size", &self.total_byte_size()); + ds.field("num_rows", &self.num_rows()); + ds.field("sorting_columns", &self.sorting_columns()); + ds.field("file_offset", &self.file_offset()); + ds.field("total_compressed_size", &self.total_compressed_size()); + ds.field("ordinal", &self.ordinal()); + ds.finish() + } + } + pub enum FileCryptoMetaDataOffset {} + #[derive(Copy, Clone, PartialEq)] + + pub struct FileCryptoMetaData<'a> { + pub _tab: ::flatbuffers::Table<'a>, + } + + impl<'a> ::flatbuffers::Follow<'a> for FileCryptoMetaData<'a> { + type Inner = FileCryptoMetaData<'a>; + #[inline] + unsafe fn follow(buf: &'a [u8], loc: usize) -> Self::Inner { + Self { + _tab: unsafe { ::flatbuffers::Table::new(buf, loc) }, + } + } + } + + impl<'a> FileCryptoMetaData<'a> { + pub const VT_ENCRYPTION_ALGORITHM_TYPE: ::flatbuffers::VOffsetT = 4; + pub const VT_ENCRYPTION_ALGORITHM: ::flatbuffers::VOffsetT = 6; + pub const VT_KEY_METADATA: ::flatbuffers::VOffsetT = 8; + + #[inline] + pub unsafe fn init_from_table(table: ::flatbuffers::Table<'a>) -> Self { + FileCryptoMetaData { _tab: table } + } + #[allow(unused_mut)] + pub fn create< + 'bldr: 'args, + 'args: 'mut_bldr, + 'mut_bldr, + A: ::flatbuffers::Allocator + 'bldr, + >( + _fbb: &'mut_bldr mut ::flatbuffers::FlatBufferBuilder<'bldr, A>, + args: &'args FileCryptoMetaDataArgs<'args>, + ) -> ::flatbuffers::WIPOffset> { + let mut builder = FileCryptoMetaDataBuilder::new(_fbb); + if let Some(x) = args.key_metadata { + builder.add_key_metadata(x); + } + if let Some(x) = args.encryption_algorithm { + builder.add_encryption_algorithm(x); + } + builder.add_encryption_algorithm_type(args.encryption_algorithm_type); + builder.finish() + } + + #[inline] + pub fn encryption_algorithm_type(&self) -> EncryptionAlgorithm { + // Safety: + // Created from valid Table for this object + // which contains a valid value in this slot + unsafe { + self._tab + .get::( + FileCryptoMetaData::VT_ENCRYPTION_ALGORITHM_TYPE, + Some(EncryptionAlgorithm::NONE), + ) + .unwrap() + } + } + #[inline] + pub fn encryption_algorithm(&self) -> Option<::flatbuffers::Table<'a>> { + // Safety: + // Created from valid Table for this object + // which contains a valid value in this slot + unsafe { + self._tab + .get::<::flatbuffers::ForwardsUOffset<::flatbuffers::Table<'a>>>( + FileCryptoMetaData::VT_ENCRYPTION_ALGORITHM, + None, + ) + } + } + #[inline] + pub fn key_metadata(&self) -> Option<::flatbuffers::Vector<'a, i8>> { + // Safety: + // Created from valid Table for this object + // which contains a valid value in this slot + unsafe { + self._tab + .get::<::flatbuffers::ForwardsUOffset<::flatbuffers::Vector<'a, i8>>>( + FileCryptoMetaData::VT_KEY_METADATA, + None, + ) + } + } + #[inline] + #[allow(non_snake_case)] + pub fn encryption_algorithm_as_aes_gcm_v1(&self) -> Option> { + if self.encryption_algorithm_type() == EncryptionAlgorithm::AesGcmV1 { + self.encryption_algorithm().map(|t| { + // Safety: + // Created from a valid Table for this object + // Which contains a valid union in this slot + unsafe { AesGcmV1::init_from_table(t) } + }) + } else { + None + } + } + + #[inline] + #[allow(non_snake_case)] + pub fn encryption_algorithm_as_aes_gcm_ctr_v1(&self) -> Option> { + if self.encryption_algorithm_type() == EncryptionAlgorithm::AesGcmCtrV1 { + self.encryption_algorithm().map(|t| { + // Safety: + // Created from a valid Table for this object + // Which contains a valid union in this slot + unsafe { AesGcmCtrV1::init_from_table(t) } + }) + } else { + None + } + } + } + + impl ::flatbuffers::Verifiable for FileCryptoMetaData<'_> { + #[inline] + fn run_verifier( + v: &mut ::flatbuffers::Verifier, + pos: usize, + ) -> Result<(), ::flatbuffers::InvalidFlatbuffer> { + v.visit_table(pos)? + .visit_union::("encryption_algorithm_type", Self::VT_ENCRYPTION_ALGORITHM_TYPE, "encryption_algorithm", Self::VT_ENCRYPTION_ALGORITHM, false, |key, v, pos| { + match key { + EncryptionAlgorithm::AesGcmV1 => v.verify_union_variant::<::flatbuffers::ForwardsUOffset>("EncryptionAlgorithm::AesGcmV1", pos), + EncryptionAlgorithm::AesGcmCtrV1 => v.verify_union_variant::<::flatbuffers::ForwardsUOffset>("EncryptionAlgorithm::AesGcmCtrV1", pos), + _ => Ok(()), + } + })? + .visit_field::<::flatbuffers::ForwardsUOffset<::flatbuffers::Vector<'_, i8>>>("key_metadata", Self::VT_KEY_METADATA, false)? + .finish(); + Ok(()) + } + } + pub struct FileCryptoMetaDataArgs<'a> { + pub encryption_algorithm_type: EncryptionAlgorithm, + pub encryption_algorithm: + Option<::flatbuffers::WIPOffset<::flatbuffers::UnionWIPOffset>>, + pub key_metadata: Option<::flatbuffers::WIPOffset<::flatbuffers::Vector<'a, i8>>>, + } + impl<'a> Default for FileCryptoMetaDataArgs<'a> { + #[inline] + fn default() -> Self { + FileCryptoMetaDataArgs { + encryption_algorithm_type: EncryptionAlgorithm::NONE, + encryption_algorithm: None, + key_metadata: None, + } + } + } + + pub struct FileCryptoMetaDataBuilder<'a: 'b, 'b, A: ::flatbuffers::Allocator + 'a> { + fbb_: &'b mut ::flatbuffers::FlatBufferBuilder<'a, A>, + start_: ::flatbuffers::WIPOffset<::flatbuffers::TableUnfinishedWIPOffset>, + } + impl<'a: 'b, 'b, A: ::flatbuffers::Allocator + 'a> FileCryptoMetaDataBuilder<'a, 'b, A> { + #[inline] + pub fn add_encryption_algorithm_type( + &mut self, + encryption_algorithm_type: EncryptionAlgorithm, + ) { + self.fbb_.push_slot::( + FileCryptoMetaData::VT_ENCRYPTION_ALGORITHM_TYPE, + encryption_algorithm_type, + EncryptionAlgorithm::NONE, + ); + } + #[inline] + pub fn add_encryption_algorithm( + &mut self, + encryption_algorithm: ::flatbuffers::WIPOffset<::flatbuffers::UnionWIPOffset>, + ) { + self.fbb_.push_slot_always::<::flatbuffers::WIPOffset<_>>( + FileCryptoMetaData::VT_ENCRYPTION_ALGORITHM, + encryption_algorithm, + ); + } + #[inline] + pub fn add_key_metadata( + &mut self, + key_metadata: ::flatbuffers::WIPOffset<::flatbuffers::Vector<'b, i8>>, + ) { + self.fbb_.push_slot_always::<::flatbuffers::WIPOffset<_>>( + FileCryptoMetaData::VT_KEY_METADATA, + key_metadata, + ); + } + #[inline] + pub fn new( + _fbb: &'b mut ::flatbuffers::FlatBufferBuilder<'a, A>, + ) -> FileCryptoMetaDataBuilder<'a, 'b, A> { + let start = _fbb.start_table(); + FileCryptoMetaDataBuilder { + fbb_: _fbb, + start_: start, + } + } + #[inline] + pub fn finish(self) -> ::flatbuffers::WIPOffset> { + let o = self.fbb_.end_table(self.start_); + ::flatbuffers::WIPOffset::new(o.value()) + } + } + + impl ::core::fmt::Debug for FileCryptoMetaData<'_> { + fn fmt(&self, f: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result { + let mut ds = f.debug_struct("FileCryptoMetaData"); + ds.field( + "encryption_algorithm_type", + &self.encryption_algorithm_type(), + ); + match self.encryption_algorithm_type() { + EncryptionAlgorithm::AesGcmV1 => { + if let Some(x) = self.encryption_algorithm_as_aes_gcm_v1() { + ds.field("encryption_algorithm", &x) + } else { + ds.field( + "encryption_algorithm", + &"InvalidFlatbuffer: Union discriminant does not match value.", + ) + } + } + EncryptionAlgorithm::AesGcmCtrV1 => { + if let Some(x) = self.encryption_algorithm_as_aes_gcm_ctr_v1() { + ds.field("encryption_algorithm", &x) + } else { + ds.field( + "encryption_algorithm", + &"InvalidFlatbuffer: Union discriminant does not match value.", + ) + } + } + _ => { + let x: Option<()> = None; + ds.field("encryption_algorithm", &x) + } + }; + ds.field("key_metadata", &self.key_metadata()); + ds.finish() + } + } + pub enum FileMetaDataOffset {} + #[derive(Copy, Clone, PartialEq)] + + pub struct FileMetaData<'a> { + pub _tab: ::flatbuffers::Table<'a>, + } + + impl<'a> ::flatbuffers::Follow<'a> for FileMetaData<'a> { + type Inner = FileMetaData<'a>; + #[inline] + unsafe fn follow(buf: &'a [u8], loc: usize) -> Self::Inner { + Self { + _tab: unsafe { ::flatbuffers::Table::new(buf, loc) }, + } + } + } + + impl<'a> FileMetaData<'a> { + pub const VT_VERSION: ::flatbuffers::VOffsetT = 4; + pub const VT_SCHEMA: ::flatbuffers::VOffsetT = 6; + pub const VT_NUM_ROWS: ::flatbuffers::VOffsetT = 8; + pub const VT_ROW_GROUPS: ::flatbuffers::VOffsetT = 10; + pub const VT_KV: ::flatbuffers::VOffsetT = 12; + pub const VT_CREATED_BY: ::flatbuffers::VOffsetT = 14; + pub const VT_ENCRYPTION_ALGORITHM_TYPE: ::flatbuffers::VOffsetT = 16; + pub const VT_ENCRYPTION_ALGORITHM: ::flatbuffers::VOffsetT = 18; + pub const VT_FOOTER_SIGNING_KEY_METADATA: ::flatbuffers::VOffsetT = 20; + + #[inline] + pub unsafe fn init_from_table(table: ::flatbuffers::Table<'a>) -> Self { + FileMetaData { _tab: table } + } + #[allow(unused_mut)] + pub fn create< + 'bldr: 'args, + 'args: 'mut_bldr, + 'mut_bldr, + A: ::flatbuffers::Allocator + 'bldr, + >( + _fbb: &'mut_bldr mut ::flatbuffers::FlatBufferBuilder<'bldr, A>, + args: &'args FileMetaDataArgs<'args>, + ) -> ::flatbuffers::WIPOffset> { + let mut builder = FileMetaDataBuilder::new(_fbb); + builder.add_num_rows(args.num_rows); + if let Some(x) = args.footer_signing_key_metadata { + builder.add_footer_signing_key_metadata(x); + } + if let Some(x) = args.encryption_algorithm { + builder.add_encryption_algorithm(x); + } + if let Some(x) = args.created_by { + builder.add_created_by(x); + } + if let Some(x) = args.kv { + builder.add_kv(x); + } + if let Some(x) = args.row_groups { + builder.add_row_groups(x); + } + if let Some(x) = args.schema { + builder.add_schema(x); + } + builder.add_version(args.version); + builder.add_encryption_algorithm_type(args.encryption_algorithm_type); + builder.finish() + } + + #[inline] + pub fn version(&self) -> i32 { + // Safety: + // Created from valid Table for this object + // which contains a valid value in this slot + unsafe { + self._tab + .get::(FileMetaData::VT_VERSION, Some(0)) + .unwrap() + } + } + #[inline] + pub fn schema( + &self, + ) -> Option<::flatbuffers::Vector<'a, ::flatbuffers::ForwardsUOffset>>> + { + // Safety: + // Created from valid Table for this object + // which contains a valid value in this slot + unsafe { + self._tab.get::<::flatbuffers::ForwardsUOffset< + ::flatbuffers::Vector<'a, ::flatbuffers::ForwardsUOffset>, + >>(FileMetaData::VT_SCHEMA, None) + } + } + #[inline] + pub fn num_rows(&self) -> i64 { + // Safety: + // Created from valid Table for this object + // which contains a valid value in this slot + unsafe { + self._tab + .get::(FileMetaData::VT_NUM_ROWS, Some(0)) + .unwrap() + } + } + #[inline] + pub fn row_groups( + &self, + ) -> Option<::flatbuffers::Vector<'a, ::flatbuffers::ForwardsUOffset>>> + { + // Safety: + // Created from valid Table for this object + // which contains a valid value in this slot + unsafe { + self._tab.get::<::flatbuffers::ForwardsUOffset< + ::flatbuffers::Vector<'a, ::flatbuffers::ForwardsUOffset>, + >>(FileMetaData::VT_ROW_GROUPS, None) + } + } + #[inline] + pub fn kv( + &self, + ) -> Option<::flatbuffers::Vector<'a, ::flatbuffers::ForwardsUOffset>>> + { + // Safety: + // Created from valid Table for this object + // which contains a valid value in this slot + unsafe { + self._tab.get::<::flatbuffers::ForwardsUOffset< + ::flatbuffers::Vector<'a, ::flatbuffers::ForwardsUOffset>, + >>(FileMetaData::VT_KV, None) + } + } + #[inline] + pub fn created_by(&self) -> Option<&'a str> { + // Safety: + // Created from valid Table for this object + // which contains a valid value in this slot + unsafe { + self._tab.get::<::flatbuffers::ForwardsUOffset<&str>>( + FileMetaData::VT_CREATED_BY, + None, + ) + } + } + #[inline] + pub fn encryption_algorithm_type(&self) -> EncryptionAlgorithm { + // Safety: + // Created from valid Table for this object + // which contains a valid value in this slot + unsafe { + self._tab + .get::( + FileMetaData::VT_ENCRYPTION_ALGORITHM_TYPE, + Some(EncryptionAlgorithm::NONE), + ) + .unwrap() + } + } + #[inline] + pub fn encryption_algorithm(&self) -> Option<::flatbuffers::Table<'a>> { + // Safety: + // Created from valid Table for this object + // which contains a valid value in this slot + unsafe { + self._tab + .get::<::flatbuffers::ForwardsUOffset<::flatbuffers::Table<'a>>>( + FileMetaData::VT_ENCRYPTION_ALGORITHM, + None, + ) + } + } + #[inline] + pub fn footer_signing_key_metadata(&self) -> Option<::flatbuffers::Vector<'a, i8>> { + // Safety: + // Created from valid Table for this object + // which contains a valid value in this slot + unsafe { + self._tab + .get::<::flatbuffers::ForwardsUOffset<::flatbuffers::Vector<'a, i8>>>( + FileMetaData::VT_FOOTER_SIGNING_KEY_METADATA, + None, + ) + } + } + #[inline] + #[allow(non_snake_case)] + pub fn encryption_algorithm_as_aes_gcm_v1(&self) -> Option> { + if self.encryption_algorithm_type() == EncryptionAlgorithm::AesGcmV1 { + self.encryption_algorithm().map(|t| { + // Safety: + // Created from a valid Table for this object + // Which contains a valid union in this slot + unsafe { AesGcmV1::init_from_table(t) } + }) + } else { + None + } + } + + #[inline] + #[allow(non_snake_case)] + pub fn encryption_algorithm_as_aes_gcm_ctr_v1(&self) -> Option> { + if self.encryption_algorithm_type() == EncryptionAlgorithm::AesGcmCtrV1 { + self.encryption_algorithm().map(|t| { + // Safety: + // Created from a valid Table for this object + // Which contains a valid union in this slot + unsafe { AesGcmCtrV1::init_from_table(t) } + }) + } else { + None + } + } + } + + impl ::flatbuffers::Verifiable for FileMetaData<'_> { + #[inline] + fn run_verifier( + v: &mut ::flatbuffers::Verifier, + pos: usize, + ) -> Result<(), ::flatbuffers::InvalidFlatbuffer> { + v.visit_table(pos)? + .visit_field::("version", Self::VT_VERSION, false)? + .visit_field::<::flatbuffers::ForwardsUOffset<::flatbuffers::Vector<'_, ::flatbuffers::ForwardsUOffset>>>("schema", Self::VT_SCHEMA, false)? + .visit_field::("num_rows", Self::VT_NUM_ROWS, false)? + .visit_field::<::flatbuffers::ForwardsUOffset<::flatbuffers::Vector<'_, ::flatbuffers::ForwardsUOffset>>>("row_groups", Self::VT_ROW_GROUPS, false)? + .visit_field::<::flatbuffers::ForwardsUOffset<::flatbuffers::Vector<'_, ::flatbuffers::ForwardsUOffset>>>("kv", Self::VT_KV, false)? + .visit_field::<::flatbuffers::ForwardsUOffset<&str>>("created_by", Self::VT_CREATED_BY, false)? + .visit_union::("encryption_algorithm_type", Self::VT_ENCRYPTION_ALGORITHM_TYPE, "encryption_algorithm", Self::VT_ENCRYPTION_ALGORITHM, false, |key, v, pos| { + match key { + EncryptionAlgorithm::AesGcmV1 => v.verify_union_variant::<::flatbuffers::ForwardsUOffset>("EncryptionAlgorithm::AesGcmV1", pos), + EncryptionAlgorithm::AesGcmCtrV1 => v.verify_union_variant::<::flatbuffers::ForwardsUOffset>("EncryptionAlgorithm::AesGcmCtrV1", pos), + _ => Ok(()), + } + })? + .visit_field::<::flatbuffers::ForwardsUOffset<::flatbuffers::Vector<'_, i8>>>("footer_signing_key_metadata", Self::VT_FOOTER_SIGNING_KEY_METADATA, false)? + .finish(); + Ok(()) + } + } + pub struct FileMetaDataArgs<'a> { + pub version: i32, + pub schema: Option< + ::flatbuffers::WIPOffset< + ::flatbuffers::Vector<'a, ::flatbuffers::ForwardsUOffset>>, + >, + >, + pub num_rows: i64, + pub row_groups: Option< + ::flatbuffers::WIPOffset< + ::flatbuffers::Vector<'a, ::flatbuffers::ForwardsUOffset>>, + >, + >, + pub kv: Option< + ::flatbuffers::WIPOffset< + ::flatbuffers::Vector<'a, ::flatbuffers::ForwardsUOffset>>, + >, + >, + pub created_by: Option<::flatbuffers::WIPOffset<&'a str>>, + pub encryption_algorithm_type: EncryptionAlgorithm, + pub encryption_algorithm: + Option<::flatbuffers::WIPOffset<::flatbuffers::UnionWIPOffset>>, + pub footer_signing_key_metadata: + Option<::flatbuffers::WIPOffset<::flatbuffers::Vector<'a, i8>>>, + } + impl<'a> Default for FileMetaDataArgs<'a> { + #[inline] + fn default() -> Self { + FileMetaDataArgs { + version: 0, + schema: None, + num_rows: 0, + row_groups: None, + kv: None, + created_by: None, + encryption_algorithm_type: EncryptionAlgorithm::NONE, + encryption_algorithm: None, + footer_signing_key_metadata: None, + } + } + } + + pub struct FileMetaDataBuilder<'a: 'b, 'b, A: ::flatbuffers::Allocator + 'a> { + fbb_: &'b mut ::flatbuffers::FlatBufferBuilder<'a, A>, + start_: ::flatbuffers::WIPOffset<::flatbuffers::TableUnfinishedWIPOffset>, + } + impl<'a: 'b, 'b, A: ::flatbuffers::Allocator + 'a> FileMetaDataBuilder<'a, 'b, A> { + #[inline] + pub fn add_version(&mut self, version: i32) { + self.fbb_ + .push_slot::(FileMetaData::VT_VERSION, version, 0); + } + #[inline] + pub fn add_schema( + &mut self, + schema: ::flatbuffers::WIPOffset< + ::flatbuffers::Vector<'b, ::flatbuffers::ForwardsUOffset>>, + >, + ) { + self.fbb_.push_slot_always::<::flatbuffers::WIPOffset<_>>( + FileMetaData::VT_SCHEMA, + schema, + ); + } + #[inline] + pub fn add_num_rows(&mut self, num_rows: i64) { + self.fbb_ + .push_slot::(FileMetaData::VT_NUM_ROWS, num_rows, 0); + } + #[inline] + pub fn add_row_groups( + &mut self, + row_groups: ::flatbuffers::WIPOffset< + ::flatbuffers::Vector<'b, ::flatbuffers::ForwardsUOffset>>, + >, + ) { + self.fbb_.push_slot_always::<::flatbuffers::WIPOffset<_>>( + FileMetaData::VT_ROW_GROUPS, + row_groups, + ); + } + #[inline] + pub fn add_kv( + &mut self, + kv: ::flatbuffers::WIPOffset< + ::flatbuffers::Vector<'b, ::flatbuffers::ForwardsUOffset>>, + >, + ) { + self.fbb_ + .push_slot_always::<::flatbuffers::WIPOffset<_>>(FileMetaData::VT_KV, kv); + } + #[inline] + pub fn add_created_by(&mut self, created_by: ::flatbuffers::WIPOffset<&'b str>) { + self.fbb_.push_slot_always::<::flatbuffers::WIPOffset<_>>( + FileMetaData::VT_CREATED_BY, + created_by, + ); + } + #[inline] + pub fn add_encryption_algorithm_type( + &mut self, + encryption_algorithm_type: EncryptionAlgorithm, + ) { + self.fbb_.push_slot::( + FileMetaData::VT_ENCRYPTION_ALGORITHM_TYPE, + encryption_algorithm_type, + EncryptionAlgorithm::NONE, + ); + } + #[inline] + pub fn add_encryption_algorithm( + &mut self, + encryption_algorithm: ::flatbuffers::WIPOffset<::flatbuffers::UnionWIPOffset>, + ) { + self.fbb_.push_slot_always::<::flatbuffers::WIPOffset<_>>( + FileMetaData::VT_ENCRYPTION_ALGORITHM, + encryption_algorithm, + ); + } + #[inline] + pub fn add_footer_signing_key_metadata( + &mut self, + footer_signing_key_metadata: ::flatbuffers::WIPOffset< + ::flatbuffers::Vector<'b, i8>, + >, + ) { + self.fbb_.push_slot_always::<::flatbuffers::WIPOffset<_>>( + FileMetaData::VT_FOOTER_SIGNING_KEY_METADATA, + footer_signing_key_metadata, + ); + } + #[inline] + pub fn new( + _fbb: &'b mut ::flatbuffers::FlatBufferBuilder<'a, A>, + ) -> FileMetaDataBuilder<'a, 'b, A> { + let start = _fbb.start_table(); + FileMetaDataBuilder { + fbb_: _fbb, + start_: start, + } + } + #[inline] + pub fn finish(self) -> ::flatbuffers::WIPOffset> { + let o = self.fbb_.end_table(self.start_); + ::flatbuffers::WIPOffset::new(o.value()) + } + } + + impl ::core::fmt::Debug for FileMetaData<'_> { + fn fmt(&self, f: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result { + let mut ds = f.debug_struct("FileMetaData"); + ds.field("version", &self.version()); + ds.field("schema", &self.schema()); + ds.field("num_rows", &self.num_rows()); + ds.field("row_groups", &self.row_groups()); + ds.field("kv", &self.kv()); + ds.field("created_by", &self.created_by()); + ds.field( + "encryption_algorithm_type", + &self.encryption_algorithm_type(), + ); + match self.encryption_algorithm_type() { + EncryptionAlgorithm::AesGcmV1 => { + if let Some(x) = self.encryption_algorithm_as_aes_gcm_v1() { + ds.field("encryption_algorithm", &x) + } else { + ds.field( + "encryption_algorithm", + &"InvalidFlatbuffer: Union discriminant does not match value.", + ) + } + } + EncryptionAlgorithm::AesGcmCtrV1 => { + if let Some(x) = self.encryption_algorithm_as_aes_gcm_ctr_v1() { + ds.field("encryption_algorithm", &x) + } else { + ds.field( + "encryption_algorithm", + &"InvalidFlatbuffer: Union discriminant does not match value.", + ) + } + } + _ => { + let x: Option<()> = None; + ds.field("encryption_algorithm", &x) + } + }; + ds.field( + "footer_signing_key_metadata", + &self.footer_signing_key_metadata(), + ); + ds.finish() + } + } + #[inline] + /// Verifies that a buffer of bytes contains a `FileMetaData` + /// and returns it. + /// Note that verification is still experimental and may not + /// catch every error, or be maximally performant. For the + /// previous, unchecked, behavior use + /// `root_as_file_meta_data_unchecked`. + pub fn root_as_file_meta_data( + buf: &[u8], + ) -> Result, ::flatbuffers::InvalidFlatbuffer> { + ::flatbuffers::root::(buf) + } + #[inline] + /// Verifies that a buffer of bytes contains a size prefixed + /// `FileMetaData` and returns it. + /// Note that verification is still experimental and may not + /// catch every error, or be maximally performant. For the + /// previous, unchecked, behavior use + /// `size_prefixed_root_as_file_meta_data_unchecked`. + pub fn size_prefixed_root_as_file_meta_data( + buf: &[u8], + ) -> Result, ::flatbuffers::InvalidFlatbuffer> { + ::flatbuffers::size_prefixed_root::(buf) + } + #[inline] + /// Verifies, with the given options, that a buffer of bytes + /// contains a `FileMetaData` and returns it. + /// Note that verification is still experimental and may not + /// catch every error, or be maximally performant. For the + /// previous, unchecked, behavior use + /// `root_as_file_meta_data_unchecked`. + pub fn root_as_file_meta_data_with_opts<'b, 'o>( + opts: &'o ::flatbuffers::VerifierOptions, + buf: &'b [u8], + ) -> Result, ::flatbuffers::InvalidFlatbuffer> { + ::flatbuffers::root_with_opts::>(opts, buf) + } + #[inline] + /// Verifies, with the given verifier options, that a buffer of + /// bytes contains a size prefixed `FileMetaData` and returns + /// it. Note that verification is still experimental and may not + /// catch every error, or be maximally performant. For the + /// previous, unchecked, behavior use + /// `root_as_file_meta_data_unchecked`. + pub fn size_prefixed_root_as_file_meta_data_with_opts<'b, 'o>( + opts: &'o ::flatbuffers::VerifierOptions, + buf: &'b [u8], + ) -> Result, ::flatbuffers::InvalidFlatbuffer> { + ::flatbuffers::size_prefixed_root_with_opts::>(opts, buf) + } + #[inline] + /// Assumes, without verification, that a buffer of bytes contains a FileMetaData and returns it. + /// # Safety + /// Callers must trust the given bytes do indeed contain a valid `FileMetaData`. + pub unsafe fn root_as_file_meta_data_unchecked(buf: &[u8]) -> FileMetaData<'_> { + unsafe { ::flatbuffers::root_unchecked::(buf) } + } + #[inline] + /// Assumes, without verification, that a buffer of bytes contains a size prefixed FileMetaData and returns it. + /// # Safety + /// Callers must trust the given bytes do indeed contain a valid size prefixed `FileMetaData`. + pub unsafe fn size_prefixed_root_as_file_meta_data_unchecked( + buf: &[u8], + ) -> FileMetaData<'_> { + unsafe { ::flatbuffers::size_prefixed_root_unchecked::(buf) } + } + #[inline] + pub fn finish_file_meta_data_buffer<'a, 'b, A: ::flatbuffers::Allocator + 'a>( + fbb: &'b mut ::flatbuffers::FlatBufferBuilder<'a, A>, + root: ::flatbuffers::WIPOffset>, + ) { + fbb.finish(root, None); + } + + #[inline] + pub fn finish_size_prefixed_file_meta_data_buffer< + 'a, + 'b, + A: ::flatbuffers::Allocator + 'a, + >( + fbb: &'b mut ::flatbuffers::FlatBufferBuilder<'a, A>, + root: ::flatbuffers::WIPOffset>, + ) { + fbb.finish_size_prefixed(root, None); + } + } // pub mod format +} // pub mod parquet diff --git a/parquet/src/file/metadata/mod.rs b/parquet/src/file/metadata/mod.rs index 9304b6c25a2b..82a3cd7d2532 100644 --- a/parquet/src/file/metadata/mod.rs +++ b/parquet/src/file/metadata/mod.rs @@ -95,6 +95,9 @@ pub(crate) mod reader; pub(crate) mod thrift; mod writer; +#[cfg(feature = "flatbuffers_metadata")] +pub mod flatbuf; + use crate::basic::{EncodingMask, PageType}; #[cfg(feature = "encryption")] use crate::encryption::decrypt::FileDecryptor;