1use arrow_buffer::Buffer;
8use arrow_schema::*;
9use core::panic;
10use flatbuffers::{
11 FlatBufferBuilder, ForwardsUOffset, UnionWIPOffset, Vector, Verifiable, Verifier,
12 VerifierOptions, WIPOffset,
13};
14use std::collections::HashMap;
15use std::fmt::{Debug, Formatter};
16use std::sync::Arc;
17
18use crate::writer::DictionaryTracker;
19use crate::{CONTINUATION_MARKER, KeyValue, Message};
20use DataType::*;
21
22#[derive(Debug)]
53pub struct IpcSchemaEncoder<'a> {
54 dictionary_tracker: Option<&'a mut DictionaryTracker>,
55}
56
57impl Default for IpcSchemaEncoder<'_> {
58 fn default() -> Self {
59 Self::new()
60 }
61}
62
63impl<'a> IpcSchemaEncoder<'a> {
64 pub fn new() -> IpcSchemaEncoder<'a> {
66 IpcSchemaEncoder {
67 dictionary_tracker: None,
68 }
69 }
70
71 pub fn with_dictionary_tracker(
73 mut self,
74 dictionary_tracker: &'a mut DictionaryTracker,
75 ) -> Self {
76 self.dictionary_tracker = Some(dictionary_tracker);
77 self
78 }
79
80 pub fn schema_to_fb<'b>(&mut self, schema: &Schema) -> FlatBufferBuilder<'b> {
84 let mut fbb = FlatBufferBuilder::new();
85
86 let root = self.schema_to_fb_offset(&mut fbb, schema);
87
88 fbb.finish(root, None);
89
90 fbb
91 }
92
93 pub fn schema_to_fb_offset<'b>(
95 &mut self,
96 fbb: &mut FlatBufferBuilder<'b>,
97 schema: &Schema,
98 ) -> WIPOffset<crate::Schema<'b>> {
99 let fields = schema
100 .fields()
101 .iter()
102 .map(|field| build_field(fbb, &mut self.dictionary_tracker, field))
103 .collect::<Vec<_>>();
104 let fb_field_list = fbb.create_vector(&fields);
105
106 let fb_metadata_list =
107 (!schema.metadata().is_empty()).then(|| metadata_to_fb(fbb, schema.metadata()));
108
109 let mut builder = crate::SchemaBuilder::new(fbb);
110 builder.add_fields(fb_field_list);
111 if let Some(fb_metadata_list) = fb_metadata_list {
112 builder.add_custom_metadata(fb_metadata_list);
113 }
114 builder.finish()
115 }
116}
117
118pub fn metadata_to_fb<'a>(
120 fbb: &mut FlatBufferBuilder<'a>,
121 metadata: &Metadata,
122) -> WIPOffset<Vector<'a, ForwardsUOffset<KeyValue<'a>>>> {
123 let custom_metadata = metadata
125 .iter()
126 .map(|(k, v)| {
127 let fb_key_name = fbb.create_string(k);
128 let fb_val_name = fbb.create_string(v);
129
130 let mut kv_builder = crate::KeyValueBuilder::new(fbb);
131 kv_builder.add_key(fb_key_name);
132 kv_builder.add_value(fb_val_name);
133 kv_builder.finish()
134 })
135 .collect::<Vec<_>>();
136 fbb.create_vector(&custom_metadata)
137}
138
139pub fn schema_to_fb_offset<'a>(
141 fbb: &mut FlatBufferBuilder<'a>,
142 schema: &Schema,
143) -> WIPOffset<crate::Schema<'a>> {
144 IpcSchemaEncoder::new().schema_to_fb_offset(fbb, schema)
145}
146
147impl From<crate::Field<'_>> for Field {
152 fn from(field: crate::Field) -> Field {
153 try_field_from(field).expect("invalid IPC field")
154 }
155}
156
157fn try_field_from(field: crate::Field) -> Result<Field, ArrowError> {
159 let arrow_field = if let Some(dictionary) = field.dictionary() {
160 #[expect(deprecated)]
161 Field::new_dict(
162 field.name().unwrap_or_default(),
163 get_data_type(field, true)?,
164 field.nullable(),
165 dictionary.id(),
166 dictionary.isOrdered(),
167 )
168 } else {
169 Field::new(
170 field.name().unwrap_or_default(),
171 get_data_type(field, true)?,
172 field.nullable(),
173 )
174 };
175
176 let mut metadata_map = HashMap::default();
177 if let Some(list) = field.custom_metadata() {
178 for kv in list {
179 if let (Some(k), Some(v)) = (kv.key(), kv.value()) {
180 metadata_map.insert(k.to_string(), v.to_string());
181 }
182 }
183 }
184
185 Ok(arrow_field.with_metadata(metadata_map))
186}
187
188#[deprecated(since = "60.0.0", note = "Use `try_fb_to_schema` instead")]
190pub fn fb_to_schema(fb: crate::Schema) -> Schema {
191 try_fb_to_schema(fb).expect("invalid IPC schema")
192}
193
194pub fn try_fb_to_schema(fb: crate::Schema) -> Result<Schema, ArrowError> {
199 let mut fields: Vec<Field> = vec![];
200 let c_fields = fb
201 .fields()
202 .ok_or_else(|| ArrowError::ParseError("IPC schema has no fields".to_string()))?;
203 let len = c_fields.len();
204 for i in 0..len {
205 let c_field: crate::Field = c_fields.get(i);
206 match c_field.type_type() {
207 crate::Type::Decimal if fb.endianness() == crate::Endianness::Big => {
208 return Err(ArrowError::ParseError(
209 "Big Endian is not supported for Decimal!".to_string(),
210 ));
211 }
212 _ => (),
213 }
214 fields.push(try_field_from(c_field)?);
215 }
216
217 let mut metadata: HashMap<String, String> = HashMap::default();
218 if let Some(md_fields) = fb.custom_metadata() {
219 let len = md_fields.len();
220 for i in 0..len {
221 let kv = md_fields.get(i);
222 let k_str = kv.key();
223 let v_str = kv.value();
224 if let Some(k) = k_str
225 && let Some(v) = v_str
226 {
227 metadata.insert(k.to_string(), v.to_string());
228 }
229 }
230 }
231 Ok(Schema::new_with_metadata(fields, metadata))
232}
233
234pub fn try_schema_from_flatbuffer_bytes(bytes: &[u8]) -> Result<Schema, ArrowError> {
236 if let Ok(ipc) = crate::root_as_message(bytes) {
237 if let Some(schema) = ipc.header_as_schema() {
238 try_fb_to_schema(schema)
239 } else {
240 Err(ArrowError::ParseError(
241 "Unable to get head as schema".to_string(),
242 ))
243 }
244 } else {
245 Err(ArrowError::ParseError(
246 "Unable to get root as message".to_string(),
247 ))
248 }
249}
250
251pub fn try_schema_from_ipc_buffer(buffer: &[u8]) -> Result<Schema, ArrowError> {
253 if buffer.len() < 4 {
263 return Err(ArrowError::ParseError(
264 "The buffer length is less than 4 and missing the continuation marker or length of buffer".to_string()
265 ));
266 }
267
268 let rest = if buffer[..4] == CONTINUATION_MARKER {
269 &buffer[4..]
270 } else {
271 buffer
272 };
273 let Some((len, buffer)) = rest.split_first_chunk::<4>() else {
274 return Err(ArrowError::ParseError(
275 "The buffer length is less than 8 and missing the length of buffer".to_string(),
276 ));
277 };
278
279 let len = i32::from_le_bytes(*len);
280 if len < 0 {
281 return Err(ArrowError::ParseError(format!(
282 "The encapsulated message's reported length is negative ({len})"
283 )));
284 }
285
286 if buffer.len() < len as usize {
287 let actual_len = buffer.len();
288 return Err(ArrowError::ParseError(format!(
289 "The buffer length ({actual_len}) is less than the encapsulated message's reported length ({len})"
290 )));
291 }
292
293 let msg = crate::root_as_message(buffer)
294 .map_err(|err| ArrowError::ParseError(format!("Unable to get root as message: {err:?}")))?;
295 let ipc_schema = msg.header_as_schema().ok_or_else(|| {
296 ArrowError::ParseError("Unable to convert flight info to a schema".to_string())
297 })?;
298 try_fb_to_schema(ipc_schema)
299}
300
301pub(crate) fn get_data_type(
303 field: crate::Field,
304 may_be_dictionary: bool,
305) -> Result<DataType, ArrowError> {
306 fn type_err(what: &str) -> ArrowError {
310 ArrowError::ParseError(format!("IPC schema field is missing its {what} type"))
311 }
312
313 if let Some(dictionary) = field.dictionary()
314 && may_be_dictionary
315 {
316 let int = dictionary
317 .indexType()
318 .ok_or_else(|| type_err("dictionary index"))?;
319 let index_type = match (int.bitWidth(), int.is_signed()) {
320 (8, true) => DataType::Int8,
321 (8, false) => DataType::UInt8,
322 (16, true) => DataType::Int16,
323 (16, false) => DataType::UInt16,
324 (32, true) => DataType::Int32,
325 (32, false) => DataType::UInt32,
326 (64, true) => DataType::Int64,
327 (64, false) => DataType::UInt64,
328 _ => {
329 return Err(ArrowError::ParseError(format!(
330 "Index type with bit width of {} and signed of {} not supported",
331 int.bitWidth(),
332 int.is_signed()
333 )));
334 }
335 };
336 return Ok(DataType::Dictionary(
337 Box::new(index_type),
338 Box::new(get_data_type(field, false)?),
339 ));
340 }
341
342 let data_type = match field.type_type() {
343 crate::Type::Null => DataType::Null,
344 crate::Type::Bool => DataType::Boolean,
345 crate::Type::Int => {
346 let int = field.type_as_int().ok_or_else(|| type_err("int"))?;
347 match (int.bitWidth(), int.is_signed()) {
348 (8, true) => DataType::Int8,
349 (8, false) => DataType::UInt8,
350 (16, true) => DataType::Int16,
351 (16, false) => DataType::UInt16,
352 (32, true) => DataType::Int32,
353 (32, false) => DataType::UInt32,
354 (64, true) => DataType::Int64,
355 (64, false) => DataType::UInt64,
356 z => {
357 return Err(ArrowError::ParseError(format!(
358 "Int type with bit width of {} and signed of {} not supported",
359 z.0, z.1
360 )));
361 }
362 }
363 }
364 crate::Type::Binary => DataType::Binary,
365 crate::Type::BinaryView => DataType::BinaryView,
366 crate::Type::LargeBinary => DataType::LargeBinary,
367 crate::Type::Utf8 => DataType::Utf8,
368 crate::Type::Utf8View => DataType::Utf8View,
369 crate::Type::LargeUtf8 => DataType::LargeUtf8,
370 crate::Type::FixedSizeBinary => {
371 let fsb = field
372 .type_as_fixed_size_binary()
373 .ok_or_else(|| type_err("fixed size binary"))?;
374 let byte_width = fsb.byteWidth();
375 if byte_width < 0 {
376 return Err(ArrowError::ParseError(format!(
377 "FixedSizeBinary byte width must be non-negative, got {byte_width}"
378 )));
379 }
380 DataType::FixedSizeBinary(byte_width)
381 }
382 crate::Type::FloatingPoint => {
383 let float = field
384 .type_as_floating_point()
385 .ok_or_else(|| type_err("floating point"))?;
386 match float.precision() {
387 crate::Precision::HALF => DataType::Float16,
388 crate::Precision::SINGLE => DataType::Float32,
389 crate::Precision::DOUBLE => DataType::Float64,
390 z => {
391 return Err(ArrowError::ParseError(format!(
392 "FloatingPoint type with precision of {z:?} not supported"
393 )));
394 }
395 }
396 }
397 crate::Type::Date => {
398 let date = field.type_as_date().ok_or_else(|| type_err("date"))?;
399 match date.unit() {
400 crate::DateUnit::DAY => DataType::Date32,
401 crate::DateUnit::MILLISECOND => DataType::Date64,
402 z => {
403 return Err(ArrowError::ParseError(format!(
404 "Date type with unit of {z:?} not supported"
405 )));
406 }
407 }
408 }
409 crate::Type::Time => {
410 let time = field.type_as_time().ok_or_else(|| type_err("time"))?;
411 match (time.bitWidth(), time.unit()) {
412 (32, crate::TimeUnit::SECOND) => DataType::Time32(TimeUnit::Second),
413 (32, crate::TimeUnit::MILLISECOND) => DataType::Time32(TimeUnit::Millisecond),
414 (64, crate::TimeUnit::MICROSECOND) => DataType::Time64(TimeUnit::Microsecond),
415 (64, crate::TimeUnit::NANOSECOND) => DataType::Time64(TimeUnit::Nanosecond),
416 z => {
417 return Err(ArrowError::ParseError(format!(
418 "Time type with bit width of {} and unit of {:?} not supported",
419 z.0, z.1
420 )));
421 }
422 }
423 }
424 crate::Type::Timestamp => {
425 let timestamp = field
426 .type_as_timestamp()
427 .ok_or_else(|| type_err("timestamp"))?;
428 let timezone: Option<_> = timestamp.timezone().map(|tz| tz.into());
429 match timestamp.unit() {
430 crate::TimeUnit::SECOND => DataType::Timestamp(TimeUnit::Second, timezone),
431 crate::TimeUnit::MILLISECOND => {
432 DataType::Timestamp(TimeUnit::Millisecond, timezone)
433 }
434 crate::TimeUnit::MICROSECOND => {
435 DataType::Timestamp(TimeUnit::Microsecond, timezone)
436 }
437 crate::TimeUnit::NANOSECOND => DataType::Timestamp(TimeUnit::Nanosecond, timezone),
438 z => {
439 return Err(ArrowError::ParseError(format!(
440 "Timestamp type with unit of {z:?} not supported"
441 )));
442 }
443 }
444 }
445 crate::Type::Interval => {
446 let interval = field
447 .type_as_interval()
448 .ok_or_else(|| type_err("interval"))?;
449 match interval.unit() {
450 crate::IntervalUnit::YEAR_MONTH => DataType::Interval(IntervalUnit::YearMonth),
451 crate::IntervalUnit::DAY_TIME => DataType::Interval(IntervalUnit::DayTime),
452 crate::IntervalUnit::MONTH_DAY_NANO => {
453 DataType::Interval(IntervalUnit::MonthDayNano)
454 }
455 z => {
456 return Err(ArrowError::ParseError(format!(
457 "Interval type with unit of {z:?} unsupported"
458 )));
459 }
460 }
461 }
462 crate::Type::Duration => {
463 let duration = field
464 .type_as_duration()
465 .ok_or_else(|| type_err("duration"))?;
466 match duration.unit() {
467 crate::TimeUnit::SECOND => DataType::Duration(TimeUnit::Second),
468 crate::TimeUnit::MILLISECOND => DataType::Duration(TimeUnit::Millisecond),
469 crate::TimeUnit::MICROSECOND => DataType::Duration(TimeUnit::Microsecond),
470 crate::TimeUnit::NANOSECOND => DataType::Duration(TimeUnit::Nanosecond),
471 z => {
472 return Err(ArrowError::ParseError(format!(
473 "Duration type with unit of {z:?} unsupported"
474 )));
475 }
476 }
477 }
478 crate::Type::List => {
479 let child = single_child(&field, "list")?;
480 DataType::List(Arc::new(try_field_from(child)?))
481 }
482 crate::Type::LargeList => {
483 let child = single_child(&field, "large list")?;
484 DataType::LargeList(Arc::new(try_field_from(child)?))
485 }
486 crate::Type::ListView => {
487 let child = single_child(&field, "listview")?;
488 DataType::ListView(Arc::new(try_field_from(child)?))
489 }
490 crate::Type::LargeListView => {
491 let child = single_child(&field, "large listview")?;
492 DataType::LargeListView(Arc::new(try_field_from(child)?))
493 }
494 crate::Type::FixedSizeList => {
495 let child = single_child(&field, "list")?;
496 let fsl = field
497 .type_as_fixed_size_list()
498 .ok_or_else(|| type_err("fixed size list"))?;
499 DataType::FixedSizeList(Arc::new(try_field_from(child)?), fsl.listSize())
500 }
501 crate::Type::Struct_ => {
502 let fields = match field.children() {
503 Some(children) => children
504 .iter()
505 .map(try_field_from)
506 .collect::<Result<Vec<_>, _>>()?
507 .into(),
508 None => Fields::empty(),
509 };
510 DataType::Struct(fields)
511 }
512 crate::Type::RunEndEncoded => {
513 let children = field
514 .children()
515 .ok_or_else(|| ArrowError::ParseError("IPC list has no children".to_string()))?;
516 if children.len() != 2 {
517 return Err(ArrowError::ParseError(format!(
518 "RunEndEncoded type should have exactly two children. Found {}",
519 children.len()
520 )));
521 }
522 let run_ends_field = try_field_from(children.get(0))?;
523 let values_field = try_field_from(children.get(1))?;
524 DataType::RunEndEncoded(Arc::new(run_ends_field), Arc::new(values_field))
525 }
526 crate::Type::Map => {
527 let map = field.type_as_map().ok_or_else(|| type_err("map"))?;
528 let child = single_child(&field, "map")?;
529 DataType::Map(Arc::new(try_field_from(child)?), map.keysSorted())
530 }
531 crate::Type::Decimal => {
532 let fsb = field.type_as_decimal().ok_or_else(|| type_err("decimal"))?;
533 let bit_width = fsb.bitWidth();
534 let precision: u8 = fsb.precision().try_into().map_err(|_| {
535 ArrowError::ParseError(format!("Invalid decimal precision {}", fsb.precision()))
536 })?;
537 let scale: i8 = fsb.scale().try_into().map_err(|_| {
538 ArrowError::ParseError(format!("Invalid decimal scale {}", fsb.scale()))
539 })?;
540 match bit_width {
541 32 => DataType::Decimal32(precision, scale),
542 64 => DataType::Decimal64(precision, scale),
543 128 => DataType::Decimal128(precision, scale),
544 256 => DataType::Decimal256(precision, scale),
545 _ => {
546 return Err(ArrowError::ParseError(format!(
547 "Unexpected decimal bit width {bit_width}"
548 )));
549 }
550 }
551 }
552 crate::Type::Union => {
553 let union = field.type_as_union().ok_or_else(|| type_err("union"))?;
554
555 let union_mode = match union.mode() {
556 crate::UnionMode::Dense => UnionMode::Dense,
557 crate::UnionMode::Sparse => UnionMode::Sparse,
558 mode => {
559 return Err(ArrowError::ParseError(format!(
560 "Unexpected union mode: {mode:?}"
561 )));
562 }
563 };
564
565 let mut fields = vec![];
566 if let Some(children) = field.children() {
567 for i in 0..children.len() {
568 fields.push(try_field_from(children.get(i))?);
569 }
570 }
571
572 let fields = match union.typeIds() {
573 None => UnionFields::try_from_fields(fields)?,
574 Some(ids) => UnionFields::try_new(ids.iter().map(|i| i as i8), fields)?,
575 };
576
577 DataType::Union(fields, union_mode)
578 }
579 t => return Err(ArrowError::ParseError(format!("Type {t:?} not supported"))),
580 };
581 Ok(data_type)
582}
583
584fn single_child<'a>(field: &crate::Field<'a>, kind: &str) -> Result<crate::Field<'a>, ArrowError> {
587 let children = field
588 .children()
589 .ok_or_else(|| ArrowError::ParseError(format!("IPC {kind} has no children")))?;
590 if children.len() != 1 {
591 return Err(ArrowError::ParseError(format!(
592 "expect a {kind} to have one child"
593 )));
594 }
595 Ok(children.get(0))
596}
597
598pub(crate) struct FBFieldType<'b> {
599 pub(crate) type_type: crate::Type,
600 pub(crate) type_: WIPOffset<UnionWIPOffset>,
601 pub(crate) children: Option<WIPOffset<Vector<'b, ForwardsUOffset<crate::Field<'b>>>>>,
602}
603
604pub(crate) fn build_field<'a>(
606 fbb: &mut FlatBufferBuilder<'a>,
607 dictionary_tracker: &mut Option<&mut DictionaryTracker>,
608 field: &Field,
609) -> WIPOffset<crate::Field<'a>> {
610 let fb_metadata = if field.metadata().is_empty() {
612 None
613 } else {
614 Some(metadata_to_fb(fbb, field.metadata()))
615 };
616
617 let fb_field_name = fbb.create_string(field.name().as_str());
618 let field_type = get_fb_field_type(field.data_type(), dictionary_tracker, fbb);
619
620 let fb_dictionary = if let Dictionary(index_type, _) = field.data_type() {
621 match dictionary_tracker {
622 Some(tracker) => Some(get_fb_dictionary(
623 index_type,
624 tracker.next_dict_id(),
625 field
626 .dict_is_ordered()
627 .expect("All Dictionary types have `dict_is_ordered`"),
628 fbb,
629 )),
630 None => panic!("IPC must no longer be used without dictionary tracker"),
631 }
632 } else {
633 None
634 };
635
636 let mut field_builder = crate::FieldBuilder::new(fbb);
637 field_builder.add_name(fb_field_name);
638 if let Some(dictionary) = fb_dictionary {
639 field_builder.add_dictionary(dictionary)
640 }
641 field_builder.add_type_type(field_type.type_type);
642 field_builder.add_nullable(field.is_nullable());
643 match field_type.children {
644 None => {}
645 Some(children) => field_builder.add_children(children),
646 }
647 field_builder.add_type_(field_type.type_);
648
649 if let Some(fb_metadata) = fb_metadata {
650 field_builder.add_custom_metadata(fb_metadata);
651 }
652
653 field_builder.finish()
654}
655
656pub(crate) fn get_fb_field_type<'a>(
658 data_type: &DataType,
659 dictionary_tracker: &mut Option<&mut DictionaryTracker>,
660 fbb: &mut FlatBufferBuilder<'a>,
661) -> FBFieldType<'a> {
662 let empty_fields: Vec<WIPOffset<crate::Field>> = vec![];
665 match data_type {
666 Null => FBFieldType {
667 type_type: crate::Type::Null,
668 type_: crate::NullBuilder::new(fbb).finish().as_union_value(),
669 children: Some(fbb.create_vector(&empty_fields[..])),
670 },
671 Boolean => FBFieldType {
672 type_type: crate::Type::Bool,
673 type_: crate::BoolBuilder::new(fbb).finish().as_union_value(),
674 children: Some(fbb.create_vector(&empty_fields[..])),
675 },
676 UInt8 | UInt16 | UInt32 | UInt64 => {
677 let children = fbb.create_vector(&empty_fields[..]);
678 let mut builder = crate::IntBuilder::new(fbb);
679 builder.add_is_signed(false);
680 match data_type {
681 UInt8 => builder.add_bitWidth(8),
682 UInt16 => builder.add_bitWidth(16),
683 UInt32 => builder.add_bitWidth(32),
684 UInt64 => builder.add_bitWidth(64),
685 _ => {}
686 }
687 FBFieldType {
688 type_type: crate::Type::Int,
689 type_: builder.finish().as_union_value(),
690 children: Some(children),
691 }
692 }
693 Int8 | Int16 | Int32 | Int64 => {
694 let children = fbb.create_vector(&empty_fields[..]);
695 let mut builder = crate::IntBuilder::new(fbb);
696 builder.add_is_signed(true);
697 match data_type {
698 Int8 => builder.add_bitWidth(8),
699 Int16 => builder.add_bitWidth(16),
700 Int32 => builder.add_bitWidth(32),
701 Int64 => builder.add_bitWidth(64),
702 _ => {}
703 }
704 FBFieldType {
705 type_type: crate::Type::Int,
706 type_: builder.finish().as_union_value(),
707 children: Some(children),
708 }
709 }
710 Float16 | Float32 | Float64 => {
711 let children = fbb.create_vector(&empty_fields[..]);
712 let mut builder = crate::FloatingPointBuilder::new(fbb);
713 match data_type {
714 Float16 => builder.add_precision(crate::Precision::HALF),
715 Float32 => builder.add_precision(crate::Precision::SINGLE),
716 Float64 => builder.add_precision(crate::Precision::DOUBLE),
717 _ => {}
718 }
719 FBFieldType {
720 type_type: crate::Type::FloatingPoint,
721 type_: builder.finish().as_union_value(),
722 children: Some(children),
723 }
724 }
725 Binary => FBFieldType {
726 type_type: crate::Type::Binary,
727 type_: crate::BinaryBuilder::new(fbb).finish().as_union_value(),
728 children: Some(fbb.create_vector(&empty_fields[..])),
729 },
730 LargeBinary => FBFieldType {
731 type_type: crate::Type::LargeBinary,
732 type_: crate::LargeBinaryBuilder::new(fbb)
733 .finish()
734 .as_union_value(),
735 children: Some(fbb.create_vector(&empty_fields[..])),
736 },
737 BinaryView => FBFieldType {
738 type_type: crate::Type::BinaryView,
739 type_: crate::BinaryViewBuilder::new(fbb).finish().as_union_value(),
740 children: Some(fbb.create_vector(&empty_fields[..])),
741 },
742 Utf8View => FBFieldType {
743 type_type: crate::Type::Utf8View,
744 type_: crate::Utf8ViewBuilder::new(fbb).finish().as_union_value(),
745 children: Some(fbb.create_vector(&empty_fields[..])),
746 },
747 Utf8 => FBFieldType {
748 type_type: crate::Type::Utf8,
749 type_: crate::Utf8Builder::new(fbb).finish().as_union_value(),
750 children: Some(fbb.create_vector(&empty_fields[..])),
751 },
752 LargeUtf8 => FBFieldType {
753 type_type: crate::Type::LargeUtf8,
754 type_: crate::LargeUtf8Builder::new(fbb).finish().as_union_value(),
755 children: Some(fbb.create_vector(&empty_fields[..])),
756 },
757 FixedSizeBinary(len) => {
758 let mut builder = crate::FixedSizeBinaryBuilder::new(fbb);
759 builder.add_byteWidth(*len);
760 FBFieldType {
761 type_type: crate::Type::FixedSizeBinary,
762 type_: builder.finish().as_union_value(),
763 children: Some(fbb.create_vector(&empty_fields[..])),
764 }
765 }
766 Date32 => {
767 let mut builder = crate::DateBuilder::new(fbb);
768 builder.add_unit(crate::DateUnit::DAY);
769 FBFieldType {
770 type_type: crate::Type::Date,
771 type_: builder.finish().as_union_value(),
772 children: Some(fbb.create_vector(&empty_fields[..])),
773 }
774 }
775 Date64 => {
776 let mut builder = crate::DateBuilder::new(fbb);
777 builder.add_unit(crate::DateUnit::MILLISECOND);
778 FBFieldType {
779 type_type: crate::Type::Date,
780 type_: builder.finish().as_union_value(),
781 children: Some(fbb.create_vector(&empty_fields[..])),
782 }
783 }
784 Time32(unit) | Time64(unit) => {
785 let mut builder = crate::TimeBuilder::new(fbb);
786 match unit {
787 TimeUnit::Second => {
788 builder.add_bitWidth(32);
789 builder.add_unit(crate::TimeUnit::SECOND);
790 }
791 TimeUnit::Millisecond => {
792 builder.add_bitWidth(32);
793 builder.add_unit(crate::TimeUnit::MILLISECOND);
794 }
795 TimeUnit::Microsecond => {
796 builder.add_bitWidth(64);
797 builder.add_unit(crate::TimeUnit::MICROSECOND);
798 }
799 TimeUnit::Nanosecond => {
800 builder.add_bitWidth(64);
801 builder.add_unit(crate::TimeUnit::NANOSECOND);
802 }
803 }
804 FBFieldType {
805 type_type: crate::Type::Time,
806 type_: builder.finish().as_union_value(),
807 children: Some(fbb.create_vector(&empty_fields[..])),
808 }
809 }
810 Timestamp(unit, tz) => {
811 let tz = tz.as_deref().unwrap_or_default();
812 let tz_str = fbb.create_string(tz);
813 let mut builder = crate::TimestampBuilder::new(fbb);
814 let time_unit = match unit {
815 TimeUnit::Second => crate::TimeUnit::SECOND,
816 TimeUnit::Millisecond => crate::TimeUnit::MILLISECOND,
817 TimeUnit::Microsecond => crate::TimeUnit::MICROSECOND,
818 TimeUnit::Nanosecond => crate::TimeUnit::NANOSECOND,
819 };
820 builder.add_unit(time_unit);
821 if !tz.is_empty() {
822 builder.add_timezone(tz_str);
823 }
824 FBFieldType {
825 type_type: crate::Type::Timestamp,
826 type_: builder.finish().as_union_value(),
827 children: Some(fbb.create_vector(&empty_fields[..])),
828 }
829 }
830 Interval(unit) => {
831 let mut builder = crate::IntervalBuilder::new(fbb);
832 let interval_unit = match unit {
833 IntervalUnit::YearMonth => crate::IntervalUnit::YEAR_MONTH,
834 IntervalUnit::DayTime => crate::IntervalUnit::DAY_TIME,
835 IntervalUnit::MonthDayNano => crate::IntervalUnit::MONTH_DAY_NANO,
836 };
837 builder.add_unit(interval_unit);
838 FBFieldType {
839 type_type: crate::Type::Interval,
840 type_: builder.finish().as_union_value(),
841 children: Some(fbb.create_vector(&empty_fields[..])),
842 }
843 }
844 Duration(unit) => {
845 let mut builder = crate::DurationBuilder::new(fbb);
846 let time_unit = match unit {
847 TimeUnit::Second => crate::TimeUnit::SECOND,
848 TimeUnit::Millisecond => crate::TimeUnit::MILLISECOND,
849 TimeUnit::Microsecond => crate::TimeUnit::MICROSECOND,
850 TimeUnit::Nanosecond => crate::TimeUnit::NANOSECOND,
851 };
852 builder.add_unit(time_unit);
853 FBFieldType {
854 type_type: crate::Type::Duration,
855 type_: builder.finish().as_union_value(),
856 children: Some(fbb.create_vector(&empty_fields[..])),
857 }
858 }
859 List(list_type) => {
860 let child = build_field(fbb, dictionary_tracker, list_type);
861 FBFieldType {
862 type_type: crate::Type::List,
863 type_: crate::ListBuilder::new(fbb).finish().as_union_value(),
864 children: Some(fbb.create_vector(&[child])),
865 }
866 }
867 ListView(list_type) => {
868 let child = build_field(fbb, dictionary_tracker, list_type);
869 FBFieldType {
870 type_type: crate::Type::ListView,
871 type_: crate::ListViewBuilder::new(fbb).finish().as_union_value(),
872 children: Some(fbb.create_vector(&[child])),
873 }
874 }
875 LargeListView(list_type) => {
876 let child = build_field(fbb, dictionary_tracker, list_type);
877 FBFieldType {
878 type_type: crate::Type::LargeListView,
879 type_: crate::LargeListViewBuilder::new(fbb)
880 .finish()
881 .as_union_value(),
882 children: Some(fbb.create_vector(&[child])),
883 }
884 }
885 LargeList(list_type) => {
886 let child = build_field(fbb, dictionary_tracker, list_type);
887 FBFieldType {
888 type_type: crate::Type::LargeList,
889 type_: crate::LargeListBuilder::new(fbb).finish().as_union_value(),
890 children: Some(fbb.create_vector(&[child])),
891 }
892 }
893 FixedSizeList(list_type, len) => {
894 let child = build_field(fbb, dictionary_tracker, list_type);
895 let mut builder = crate::FixedSizeListBuilder::new(fbb);
896 builder.add_listSize(*len);
897 FBFieldType {
898 type_type: crate::Type::FixedSizeList,
899 type_: builder.finish().as_union_value(),
900 children: Some(fbb.create_vector(&[child])),
901 }
902 }
903 Struct(fields) => {
904 let mut children = vec![];
906 for field in fields {
907 children.push(build_field(fbb, dictionary_tracker, field));
908 }
909 FBFieldType {
910 type_type: crate::Type::Struct_,
911 type_: crate::Struct_Builder::new(fbb).finish().as_union_value(),
912 children: Some(fbb.create_vector(&children[..])),
913 }
914 }
915 RunEndEncoded(run_ends, values) => {
916 let run_ends_field = build_field(fbb, dictionary_tracker, run_ends);
917 let values_field = build_field(fbb, dictionary_tracker, values);
918 let children = [run_ends_field, values_field];
919 FBFieldType {
920 type_type: crate::Type::RunEndEncoded,
921 type_: crate::RunEndEncodedBuilder::new(fbb)
922 .finish()
923 .as_union_value(),
924 children: Some(fbb.create_vector(&children[..])),
925 }
926 }
927 Map(map_field, keys_sorted) => {
928 let child = build_field(fbb, dictionary_tracker, map_field);
929 let mut field_type = crate::MapBuilder::new(fbb);
930 field_type.add_keysSorted(*keys_sorted);
931 FBFieldType {
932 type_type: crate::Type::Map,
933 type_: field_type.finish().as_union_value(),
934 children: Some(fbb.create_vector(&[child])),
935 }
936 }
937 Dictionary(_, value_type) => {
938 get_fb_field_type(value_type, dictionary_tracker, fbb)
942 }
943 Decimal32(precision, scale) => {
944 let mut builder = crate::DecimalBuilder::new(fbb);
945 builder.add_precision(*precision as i32);
946 builder.add_scale(*scale as i32);
947 builder.add_bitWidth(32);
948 FBFieldType {
949 type_type: crate::Type::Decimal,
950 type_: builder.finish().as_union_value(),
951 children: Some(fbb.create_vector(&empty_fields[..])),
952 }
953 }
954 Decimal64(precision, scale) => {
955 let mut builder = crate::DecimalBuilder::new(fbb);
956 builder.add_precision(*precision as i32);
957 builder.add_scale(*scale as i32);
958 builder.add_bitWidth(64);
959 FBFieldType {
960 type_type: crate::Type::Decimal,
961 type_: builder.finish().as_union_value(),
962 children: Some(fbb.create_vector(&empty_fields[..])),
963 }
964 }
965 Decimal128(precision, scale) => {
966 let mut builder = crate::DecimalBuilder::new(fbb);
967 builder.add_precision(*precision as i32);
968 builder.add_scale(*scale as i32);
969 builder.add_bitWidth(128);
970 FBFieldType {
971 type_type: crate::Type::Decimal,
972 type_: builder.finish().as_union_value(),
973 children: Some(fbb.create_vector(&empty_fields[..])),
974 }
975 }
976 Decimal256(precision, scale) => {
977 let mut builder = crate::DecimalBuilder::new(fbb);
978 builder.add_precision(*precision as i32);
979 builder.add_scale(*scale as i32);
980 builder.add_bitWidth(256);
981 FBFieldType {
982 type_type: crate::Type::Decimal,
983 type_: builder.finish().as_union_value(),
984 children: Some(fbb.create_vector(&empty_fields[..])),
985 }
986 }
987 Union(fields, mode) => {
988 let mut children = vec![];
989 for (_, field) in fields.iter() {
990 children.push(build_field(fbb, dictionary_tracker, field));
991 }
992
993 let union_mode = match mode {
994 UnionMode::Sparse => crate::UnionMode::Sparse,
995 UnionMode::Dense => crate::UnionMode::Dense,
996 };
997
998 let fbb_type_ids =
999 fbb.create_vector(&fields.iter().map(|(t, _)| t as i32).collect::<Vec<_>>());
1000 let mut builder = crate::UnionBuilder::new(fbb);
1001 builder.add_mode(union_mode);
1002 builder.add_typeIds(fbb_type_ids);
1003
1004 FBFieldType {
1005 type_type: crate::Type::Union,
1006 type_: builder.finish().as_union_value(),
1007 children: Some(fbb.create_vector(&children[..])),
1008 }
1009 }
1010 }
1011}
1012
1013pub(crate) fn get_fb_dictionary<'a>(
1015 index_type: &DataType,
1016 dict_id: i64,
1017 dict_is_ordered: bool,
1018 fbb: &mut FlatBufferBuilder<'a>,
1019) -> WIPOffset<crate::DictionaryEncoding<'a>> {
1020 let mut index_builder = crate::IntBuilder::new(fbb);
1023
1024 match *index_type {
1025 Int8 | Int16 | Int32 | Int64 => index_builder.add_is_signed(true),
1026 UInt8 | UInt16 | UInt32 | UInt64 => index_builder.add_is_signed(false),
1027 _ => {}
1028 }
1029
1030 match *index_type {
1031 Int8 | UInt8 => index_builder.add_bitWidth(8),
1032 Int16 | UInt16 => index_builder.add_bitWidth(16),
1033 Int32 | UInt32 => index_builder.add_bitWidth(32),
1034 Int64 | UInt64 => index_builder.add_bitWidth(64),
1035 _ => {}
1036 }
1037
1038 let index_builder = index_builder.finish();
1039
1040 let mut builder = crate::DictionaryEncodingBuilder::new(fbb);
1041 builder.add_id(dict_id);
1042 builder.add_indexType(index_builder);
1043 builder.add_isOrdered(dict_is_ordered);
1044
1045 builder.finish()
1046}
1047
1048#[derive(Clone)]
1060pub struct MessageBuffer(Buffer);
1061
1062impl Debug for MessageBuffer {
1063 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
1064 self.as_ref().fmt(f)
1065 }
1066}
1067
1068impl MessageBuffer {
1069 pub fn try_new(buf: Buffer) -> Result<Self, ArrowError> {
1071 let opts = VerifierOptions::default();
1072 let mut v = Verifier::new(&opts, &buf);
1073 <ForwardsUOffset<Message>>::run_verifier(&mut v, 0).map_err(|err| {
1074 ArrowError::ParseError(format!("Unable to get root as message: {err:?}"))
1075 })?;
1076 Ok(Self(buf))
1077 }
1078
1079 #[inline]
1081 pub fn as_ref(&self) -> Message<'_> {
1082 unsafe { crate::root_as_message_unchecked(&self.0) }
1084 }
1085}
1086
1087#[cfg(test)]
1088mod tests {
1089 use super::*;
1090
1091 fn schema_bytes_without_fields() -> Vec<u8> {
1095 let mut fbb = FlatBufferBuilder::new();
1096 let schema = crate::SchemaBuilder::new(&mut fbb).finish();
1098 fbb.finish(schema, None);
1099 fbb.finished_data().to_vec()
1100 }
1101
1102 fn assert_single_field_schema_is_err<'a>(
1105 mut fbb: FlatBufferBuilder<'a>,
1106 field: WIPOffset<crate::Field<'a>>,
1107 ) {
1108 let fields = fbb.create_vector(&[field]);
1109 let schema = {
1110 let mut b = crate::SchemaBuilder::new(&mut fbb);
1111 b.add_fields(fields);
1112 b.finish()
1113 };
1114 fbb.finish(schema, None);
1115 let fb = crate::root_as_schema(fbb.finished_data()).expect("verifier should accept");
1116 assert!(try_fb_to_schema(fb).is_err());
1117 }
1118
1119 #[test]
1120 fn try_fb_to_schema_missing_fields_is_err() {
1121 let bytes = schema_bytes_without_fields();
1122 let fb = crate::root_as_schema(&bytes).expect("verifier should accept");
1124 assert!(try_fb_to_schema(fb).is_err());
1126 }
1127
1128 #[test]
1129 fn try_fb_to_schema_unknown_float_precision_is_err() {
1130 let mut fbb = FlatBufferBuilder::new();
1131 let name = fbb.create_string("f");
1132 let float = {
1133 let mut b = crate::FloatingPointBuilder::new(&mut fbb);
1134 b.add_precision(crate::Precision(99));
1136 b.finish()
1137 };
1138 let field = {
1139 let mut b = crate::FieldBuilder::new(&mut fbb);
1140 b.add_name(name);
1141 b.add_type_type(crate::Type::FloatingPoint);
1142 b.add_type_(float.as_union_value());
1143 b.finish()
1144 };
1145 assert_single_field_schema_is_err(fbb, field);
1146 }
1147
1148 #[test]
1149 fn try_fb_to_schema_negative_fixed_size_binary_width_is_err() {
1150 let mut fbb = FlatBufferBuilder::new();
1151 let fsb =
1152 crate::FixedSizeBinary::create(&mut fbb, &crate::FixedSizeBinaryArgs { byteWidth: -1 });
1153 let field = crate::Field::create(
1154 &mut fbb,
1155 &crate::FieldArgs {
1156 type_type: crate::Type::FixedSizeBinary,
1157 type_: Some(fsb.as_union_value()),
1158 ..Default::default()
1159 },
1160 );
1161 assert_single_field_schema_is_err(fbb, field);
1162 }
1163
1164 #[test]
1165 fn try_fb_to_schema_type_none_is_err() {
1166 let mut fbb = FlatBufferBuilder::new();
1167 let name = fbb.create_string("f");
1168 let field = {
1169 let mut b = crate::FieldBuilder::new(&mut fbb);
1170 b.add_name(name);
1171 b.finish()
1173 };
1174 assert_single_field_schema_is_err(fbb, field);
1175 }
1176
1177 #[test]
1178 fn try_fb_to_schema_union_without_type_ids_too_many_fields_is_err() {
1179 let mut fbb = FlatBufferBuilder::new();
1180 let null = crate::Null::create(&mut fbb, &crate::NullArgs::default());
1181 let child = crate::Field::create(
1182 &mut fbb,
1183 &crate::FieldArgs {
1184 type_type: crate::Type::Null,
1185 type_: Some(null.as_union_value()),
1186 ..Default::default()
1187 },
1188 );
1189 let children = fbb.create_vector(&[child; 129]);
1190 let union = crate::Union::create(&mut fbb, &crate::UnionArgs::default());
1191 let field = crate::Field::create(
1192 &mut fbb,
1193 &crate::FieldArgs {
1194 type_type: crate::Type::Union,
1195 type_: Some(union.as_union_value()),
1196 children: Some(children),
1197 ..Default::default()
1198 },
1199 );
1200 assert_single_field_schema_is_err(fbb, field);
1201 }
1202
1203 #[test]
1204 fn convert_schema_round_trip() {
1205 let md = HashMap::from([("Key".to_string(), "value".to_string())]);
1206 let field_md = HashMap::from([("k".to_string(), "v".to_string())]);
1207 let schema = Schema::new_with_metadata(
1208 vec![
1209 Field::new("uint8", DataType::UInt8, false).with_metadata(field_md),
1210 Field::new("uint16", DataType::UInt16, true),
1211 Field::new("uint32", DataType::UInt32, false),
1212 Field::new("uint64", DataType::UInt64, true),
1213 Field::new("int8", DataType::Int8, true),
1214 Field::new("int16", DataType::Int16, false),
1215 Field::new("int32", DataType::Int32, true),
1216 Field::new("int64", DataType::Int64, false),
1217 Field::new("float16", DataType::Float16, true),
1218 Field::new("float32", DataType::Float32, false),
1219 Field::new("float64", DataType::Float64, true),
1220 Field::new("null", DataType::Null, false),
1221 Field::new("bool", DataType::Boolean, false),
1222 Field::new("date32", DataType::Date32, false),
1223 Field::new("date64", DataType::Date64, true),
1224 Field::new("time32[s]", DataType::Time32(TimeUnit::Second), true),
1225 Field::new("time32[ms]", DataType::Time32(TimeUnit::Millisecond), false),
1226 Field::new("time64[us]", DataType::Time64(TimeUnit::Microsecond), false),
1227 Field::new("time64[ns]", DataType::Time64(TimeUnit::Nanosecond), true),
1228 Field::new(
1229 "timestamp[s]",
1230 DataType::Timestamp(TimeUnit::Second, None),
1231 false,
1232 ),
1233 Field::new(
1234 "timestamp[ms]",
1235 DataType::Timestamp(TimeUnit::Millisecond, None),
1236 true,
1237 ),
1238 Field::new(
1239 "timestamp[us]",
1240 DataType::Timestamp(TimeUnit::Microsecond, Some("Africa/Johannesburg".into())),
1241 false,
1242 ),
1243 Field::new(
1244 "timestamp[ns]",
1245 DataType::Timestamp(TimeUnit::Nanosecond, None),
1246 true,
1247 ),
1248 Field::new(
1249 "interval[ym]",
1250 DataType::Interval(IntervalUnit::YearMonth),
1251 true,
1252 ),
1253 Field::new(
1254 "interval[dt]",
1255 DataType::Interval(IntervalUnit::DayTime),
1256 true,
1257 ),
1258 Field::new(
1259 "interval[mdn]",
1260 DataType::Interval(IntervalUnit::MonthDayNano),
1261 true,
1262 ),
1263 Field::new("utf8", DataType::Utf8, false),
1264 Field::new("utf8_view", DataType::Utf8View, false),
1265 Field::new("binary", DataType::Binary, false),
1266 Field::new("binary_view", DataType::BinaryView, false),
1267 Field::new_list(
1268 "list[u8]",
1269 Field::new_list_field(DataType::UInt8, false),
1270 true,
1271 ),
1272 Field::new_fixed_size_list(
1273 "fixed_size_list[u8]",
1274 Field::new_list_field(DataType::UInt8, false),
1275 2,
1276 true,
1277 ),
1278 Field::new_list(
1279 "list[struct<float32, int32, bool>]",
1280 Field::new_struct(
1281 "struct",
1282 vec![
1283 Field::new("float32", UInt8, false),
1284 Field::new("int32", Int32, true),
1285 Field::new("bool", Boolean, true),
1286 ],
1287 true,
1288 ),
1289 false,
1290 ),
1291 Field::new_struct(
1292 "struct<dictionary<int32, utf8>>",
1293 vec![Field::new(
1294 "dictionary<int32, utf8>",
1295 Dictionary(Box::new(DataType::Int32), Box::new(DataType::Utf8)),
1296 false,
1297 )],
1298 false,
1299 ),
1300 Field::new_struct(
1301 "struct<int64, list[struct<date32, list[struct<>]>]>",
1302 vec![
1303 Field::new("int64", DataType::Int64, true),
1304 Field::new_list(
1305 "list[struct<date32, list[struct<>]>]",
1306 Field::new_struct(
1307 "struct",
1308 vec![
1309 Field::new("date32", DataType::Date32, true),
1310 Field::new_list(
1311 "list[struct<>]",
1312 Field::new(
1313 "struct",
1314 DataType::Struct(Fields::empty()),
1315 false,
1316 ),
1317 false,
1318 ),
1319 ],
1320 false,
1321 ),
1322 false,
1323 ),
1324 ],
1325 false,
1326 ),
1327 Field::new_union(
1328 "union<int64, list[union<date32, list[union<>]>]>",
1329 vec![0, 1],
1330 vec![
1331 Field::new("int64", DataType::Int64, true),
1332 Field::new_list(
1333 "list[union<date32, list[union<>]>]",
1334 Field::new_union(
1335 "union<date32, list[union<>]>",
1336 vec![0, 1],
1337 vec![
1338 Field::new("date32", DataType::Date32, true),
1339 Field::new_list(
1340 "list[union<>]",
1341 Field::new(
1342 "union",
1343 DataType::Union(
1344 UnionFields::empty(),
1345 UnionMode::Sparse,
1346 ),
1347 false,
1348 ),
1349 false,
1350 ),
1351 ],
1352 UnionMode::Dense,
1353 ),
1354 false,
1355 ),
1356 ],
1357 UnionMode::Sparse,
1358 ),
1359 Field::new("struct<>", DataType::Struct(Fields::empty()), true),
1360 Field::new(
1361 "union<>",
1362 DataType::Union(UnionFields::empty(), UnionMode::Dense),
1363 true,
1364 ),
1365 Field::new(
1366 "union<>",
1367 DataType::Union(UnionFields::empty(), UnionMode::Sparse),
1368 true,
1369 ),
1370 Field::new(
1371 "union<int32, utf8>",
1372 DataType::Union(
1373 UnionFields::try_new(
1374 vec![2, 3], vec![
1376 Field::new("int32", DataType::Int32, true),
1377 Field::new("utf8", DataType::Utf8, true),
1378 ],
1379 )
1380 .unwrap(),
1381 UnionMode::Dense,
1382 ),
1383 true,
1384 ),
1385 #[expect(deprecated)]
1386 Field::new_dict(
1387 "dictionary<int32, utf8>",
1388 DataType::Dictionary(Box::new(DataType::Int32), Box::new(DataType::Utf8)),
1389 true,
1390 123,
1391 true,
1392 ),
1393 #[expect(deprecated)]
1394 Field::new_dict(
1395 "dictionary<uint8, uint32>",
1396 DataType::Dictionary(Box::new(DataType::UInt8), Box::new(DataType::UInt32)),
1397 true,
1398 123,
1399 true,
1400 ),
1401 Field::new("decimal<usize, usize>", DataType::Decimal128(10, 6), false),
1402 ],
1403 md,
1404 );
1405
1406 let mut dictionary_tracker = DictionaryTracker::new(true);
1407 let fb = IpcSchemaEncoder::new()
1408 .with_dictionary_tracker(&mut dictionary_tracker)
1409 .schema_to_fb(&schema);
1410
1411 let ipc = crate::root_as_schema(fb.finished_data()).unwrap();
1413 let schema2 = try_fb_to_schema(ipc).unwrap();
1414 assert_eq!(schema, schema2);
1415 }
1416
1417 #[test]
1418 fn schema_from_bytes() {
1419 let bytes: Vec<u8> = vec![
1429 16, 0, 0, 0, 0, 0, 10, 0, 12, 0, 6, 0, 5, 0, 8, 0, 10, 0, 0, 0, 0, 1, 4, 0, 12, 0, 0,
1430 0, 8, 0, 8, 0, 0, 0, 4, 0, 8, 0, 0, 0, 4, 0, 0, 0, 1, 0, 0, 0, 20, 0, 0, 0, 16, 0, 20,
1431 0, 8, 0, 0, 0, 7, 0, 12, 0, 0, 0, 16, 0, 16, 0, 0, 0, 0, 0, 0, 2, 16, 0, 0, 0, 32, 0,
1432 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 6, 0, 0, 0, 102, 105, 101, 108, 100, 49, 0, 0, 0, 0, 6,
1433 0, 8, 0, 4, 0, 6, 0, 0, 0, 32, 0, 0, 0,
1434 ];
1435 let ipc = crate::root_as_message(&bytes).unwrap();
1436 let schema = ipc.header_as_schema().unwrap();
1437
1438 let data_gen = crate::writer::IpcDataGenerator::default();
1440 let mut dictionary_tracker = DictionaryTracker::new(true);
1441 let arrow_schema = Schema::new(vec![Field::new("field1", DataType::UInt32, false)]);
1442 let bytes = data_gen
1443 .schema_to_bytes_with_dictionary_tracker(
1444 &arrow_schema,
1445 &mut dictionary_tracker,
1446 &crate::writer::IpcWriteOptions::default(),
1447 )
1448 .ipc_message;
1449
1450 let ipc2 = crate::root_as_message(&bytes).unwrap();
1451 let schema2 = ipc2.header_as_schema().unwrap();
1452
1453 assert!(schema.custom_metadata().is_none());
1455 assert!(schema2.custom_metadata().is_none());
1456 assert_eq!(schema.endianness(), schema2.endianness());
1457 assert!(schema.features().is_none());
1458 assert!(schema2.features().is_none());
1459 assert_eq!(
1460 try_fb_to_schema(schema).unwrap(),
1461 try_fb_to_schema(schema2).unwrap()
1462 );
1463
1464 assert_eq!(ipc.version(), ipc2.version());
1465 assert_eq!(ipc.header_type(), ipc2.header_type());
1466 assert_eq!(ipc.bodyLength(), ipc2.bodyLength());
1467 assert!(ipc.custom_metadata().is_none());
1468 assert!(ipc2.custom_metadata().is_none());
1469 }
1470}