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