1mod reflection_generated;
18mod reflection_verifier;
19mod safe_buffer;
20mod r#struct;
21pub use crate::r#struct::Struct;
22pub use crate::reflection_generated::reflection;
23pub use crate::safe_buffer::SafeBuffer;
24
25use flatbuffers::{
26 emplace_scalar, read_scalar, EndianScalar, Follow, ForwardsUOffset, InvalidFlatbuffer,
27 SOffsetT, Table, UOffsetT, VOffsetT, Vector, SIZE_SOFFSET, SIZE_UOFFSET,
28};
29use reflection_generated::reflection::{BaseType, Field, Object, Schema};
30
31use core::mem::size_of;
32use num_traits::float::Float;
33use num_traits::int::PrimInt;
34use num_traits::FromPrimitive;
35use thiserror::Error;
36
37#[derive(Error, Debug, PartialEq)]
38pub enum FlatbufferError {
39 #[error(transparent)]
40 VerificationError(#[from] flatbuffers::InvalidFlatbuffer),
41 #[error("Failed to convert between data type {0} and field type {1}")]
42 FieldTypeMismatch(String, String),
43 #[error("Set field value not supported for non-populated or non-scalar fields")]
44 SetValueNotSupported,
45 #[error(transparent)]
46 ParseFloatError(#[from] std::num::ParseFloatError),
47 #[error(transparent)]
48 TryFromIntError(#[from] std::num::TryFromIntError),
49 #[error("Couldn't set string because cache vector is polluted")]
50 SetStringPolluted,
51 #[error("Invalid schema: Polluted buffer or the schema doesn't match the buffer.")]
52 InvalidSchema,
53 #[error("Type not supported: {0}")]
54 TypeNotSupported(String),
55 #[error("No type or invalid type found in union enum")]
56 InvalidUnionEnum,
57 #[error("Table or Struct doesn't belong to the buffer")]
58 InvalidTableOrStruct,
59 #[error("Field not found in the table schema")]
60 FieldNotFound,
61}
62
63pub type FlatbufferResult<T, E = FlatbufferError> = core::result::Result<T, E>;
64
65pub unsafe fn get_any_root(data: &[u8]) -> Table {
72 <ForwardsUOffset<Table>>::follow(data, 0)
73}
74
75pub unsafe fn get_field_integer<T: for<'a> Follow<'a, Inner = T> + PrimInt + FromPrimitive>(
81 table: &Table,
82 field: &Field,
83) -> FlatbufferResult<Option<T>> {
84 if size_of::<T>() != get_type_size(field.type_().base_type()) {
85 return Err(FlatbufferError::FieldTypeMismatch(
86 std::any::type_name::<T>().to_string(),
87 field
88 .type_()
89 .base_type()
90 .variant_name()
91 .unwrap_or_default()
92 .to_string(),
93 ));
94 }
95
96 let default = T::from_i64(field.default_integer());
97 Ok(table.get::<T>(field.offset(), default))
98}
99
100pub unsafe fn get_field_float<T: for<'a> Follow<'a, Inner = T> + Float>(
106 table: &Table,
107 field: &Field,
108) -> FlatbufferResult<Option<T>> {
109 if size_of::<T>() != get_type_size(field.type_().base_type()) {
110 return Err(FlatbufferError::FieldTypeMismatch(
111 std::any::type_name::<T>().to_string(),
112 field
113 .type_()
114 .base_type()
115 .variant_name()
116 .unwrap_or_default()
117 .to_string(),
118 ));
119 }
120
121 let default = T::from(field.default_real());
122 Ok(table.get::<T>(field.offset(), default))
123}
124
125pub unsafe fn get_field_string<'a>(
131 table: &Table<'a>,
132 field: &Field,
133) -> FlatbufferResult<Option<&'a str>> {
134 if field.type_().base_type() != BaseType::String {
135 return Err(FlatbufferError::FieldTypeMismatch(
136 String::from("String"),
137 field
138 .type_()
139 .base_type()
140 .variant_name()
141 .unwrap_or_default()
142 .to_string(),
143 ));
144 }
145
146 Ok(table.get::<ForwardsUOffset<&'a str>>(field.offset(), Some("")))
147}
148
149pub unsafe fn get_field_struct<'a>(
155 table: &Table<'a>,
156 field: &Field,
157) -> FlatbufferResult<Option<Struct<'a>>> {
158 if field.type_().base_type() != BaseType::Obj {
161 return Err(FlatbufferError::FieldTypeMismatch(
162 String::from("Obj"),
163 field
164 .type_()
165 .base_type()
166 .variant_name()
167 .unwrap_or_default()
168 .to_string(),
169 ));
170 }
171
172 Ok(table.get::<Struct>(field.offset(), None))
173}
174
175pub unsafe fn get_field_vector<'a, T: Follow<'a, Inner = T>>(
181 table: &Table<'a>,
182 field: &Field,
183) -> FlatbufferResult<Option<Vector<'a, T>>> {
184 if field.type_().base_type() != BaseType::Vector {
185 return Err(FlatbufferError::FieldTypeMismatch(
186 std::any::type_name::<T>().to_string(),
187 field
188 .type_()
189 .base_type()
190 .variant_name()
191 .unwrap_or_default()
192 .to_string(),
193 ));
194 }
195
196 Ok(table.get::<ForwardsUOffset<Vector<'a, T>>>(field.offset(), Some(Vector::<T>::default())))
197}
198
199pub unsafe fn get_field_table<'a>(
205 table: &Table<'a>,
206 field: &Field,
207) -> FlatbufferResult<Option<Table<'a>>> {
208 if field.type_().base_type() != BaseType::Obj {
209 return Err(FlatbufferError::FieldTypeMismatch(
210 String::from("Obj"),
211 field
212 .type_()
213 .base_type()
214 .variant_name()
215 .unwrap_or_default()
216 .to_string(),
217 ));
218 }
219
220 Ok(table.get::<ForwardsUOffset<Table<'a>>>(field.offset(), None))
221}
222
223pub unsafe fn get_any_field_integer(table: &Table, field: &Field) -> FlatbufferResult<i64> {
230 if let Some(field_loc) = get_field_loc(table, field) {
231 get_any_value_integer(field.type_().base_type(), table.buf(), field_loc)
232 } else {
233 Ok(field.default_integer())
234 }
235}
236
237pub unsafe fn get_any_field_float(table: &Table, field: &Field) -> FlatbufferResult<f64> {
243 if let Some(field_loc) = get_field_loc(table, field) {
244 get_any_value_float(field.type_().base_type(), table.buf(), field_loc)
245 } else {
246 Ok(field.default_real())
247 }
248}
249
250pub unsafe fn get_any_field_string(table: &Table, field: &Field, schema: &Schema) -> String {
256 if let Some(field_loc) = get_field_loc(table, field) {
257 get_any_value_string(
258 field.type_().base_type(),
259 table.buf(),
260 field_loc,
261 schema,
262 field.type_().index() as usize,
263 )
264 } else {
265 String::from("")
266 }
267}
268
269pub unsafe fn get_field_struct_in_struct<'a>(
275 st: &Struct<'a>,
276 field: &Field,
277) -> FlatbufferResult<Struct<'a>> {
278 if field.type_().base_type() != BaseType::Obj {
281 return Err(FlatbufferError::FieldTypeMismatch(
282 String::from("Obj"),
283 field
284 .type_()
285 .base_type()
286 .variant_name()
287 .unwrap_or_default()
288 .to_string(),
289 ));
290 }
291
292 Ok(st.get::<Struct>(field.offset() as usize))
293}
294
295pub unsafe fn get_any_field_integer_in_struct(st: &Struct, field: &Field) -> FlatbufferResult<i64> {
301 let field_loc = st.loc() + field.offset() as usize;
302
303 get_any_value_integer(field.type_().base_type(), st.buf(), field_loc)
304}
305
306pub unsafe fn get_any_field_float_in_struct(st: &Struct, field: &Field) -> FlatbufferResult<f64> {
312 let field_loc = st.loc() + field.offset() as usize;
313
314 get_any_value_float(field.type_().base_type(), st.buf(), field_loc)
315}
316
317pub unsafe fn get_any_field_string_in_struct(
323 st: &Struct,
324 field: &Field,
325 schema: &Schema,
326) -> String {
327 let field_loc = st.loc() + field.offset() as usize;
328
329 get_any_value_string(
330 field.type_().base_type(),
331 st.buf(),
332 field_loc,
333 schema,
334 field.type_().index() as usize,
335 )
336}
337
338pub unsafe fn set_any_field_integer(
344 buf: &mut [u8],
345 table_loc: usize,
346 field: &Field,
347 v: i64,
348) -> FlatbufferResult<()> {
349 let field_type = field.type_().base_type();
350 let table = Table::follow(buf, table_loc);
351
352 let Some(field_loc) = get_field_loc(&table, field) else {
353 return Err(FlatbufferError::SetValueNotSupported);
354 };
355
356 if !is_scalar(field_type) {
357 return Err(FlatbufferError::SetValueNotSupported);
358 }
359
360 set_any_value_integer(field_type, buf, field_loc, v)
361}
362
363pub unsafe fn set_any_field_float(
369 buf: &mut [u8],
370 table_loc: usize,
371 field: &Field,
372 v: f64,
373) -> FlatbufferResult<()> {
374 let field_type = field.type_().base_type();
375 let table = Table::follow(buf, table_loc);
376
377 let Some(field_loc) = get_field_loc(&table, field) else {
378 return Err(FlatbufferError::SetValueNotSupported);
379 };
380
381 if !is_scalar(field_type) {
382 return Err(FlatbufferError::SetValueNotSupported);
383 }
384
385 set_any_value_float(field_type, buf, field_loc, v)
386}
387
388pub unsafe fn set_any_field_string(
394 buf: &mut [u8],
395 table_loc: usize,
396 field: &Field,
397 v: &str,
398) -> FlatbufferResult<()> {
399 let field_type = field.type_().base_type();
400 let table = Table::follow(buf, table_loc);
401
402 let Some(field_loc) = get_field_loc(&table, field) else {
403 return Err(FlatbufferError::SetValueNotSupported);
404 };
405
406 if !is_scalar(field_type) {
407 return Err(FlatbufferError::SetValueNotSupported);
408 }
409
410 set_any_value_float(field_type, buf, field_loc, v.parse::<f64>()?)
411}
412
413pub unsafe fn set_field<T: EndianScalar>(
419 buf: &mut [u8],
420 table_loc: usize,
421 field: &Field,
422 v: T,
423) -> FlatbufferResult<()> {
424 let field_type = field.type_().base_type();
425 let table = Table::follow(buf, table_loc);
426
427 if !is_scalar(field_type) {
428 return Err(FlatbufferError::SetValueNotSupported);
429 }
430
431 if core::mem::size_of::<T>() != get_type_size(field_type) {
432 return Err(FlatbufferError::FieldTypeMismatch(
433 std::any::type_name::<T>().to_string(),
434 field_type.variant_name().unwrap_or_default().to_string(),
435 ));
436 }
437
438 let Some(field_loc) = get_field_loc(&table, field) else {
439 return Err(FlatbufferError::SetValueNotSupported);
440 };
441
442 if buf.len() < field_loc.saturating_add(get_type_size(field_type)) {
443 return Err(FlatbufferError::VerificationError(
444 InvalidFlatbuffer::RangeOutOfBounds {
445 range: core::ops::Range {
446 start: field_loc,
447 end: field_loc.saturating_add(get_type_size(field_type)),
448 },
449 error_trace: Default::default(),
450 },
451 ));
452 }
453
454 unsafe { Ok(emplace_scalar::<T>(&mut buf[field_loc..], v)) }
456}
457
458pub unsafe fn set_string(
464 buf: &mut Vec<u8>,
465 table_loc: usize,
466 field: &Field,
467 v: &str,
468 schema: &Schema,
469) -> FlatbufferResult<()> {
470 if v.is_empty() {
471 return Ok(());
472 }
473
474 let field_type = field.type_().base_type();
475 if field_type != BaseType::String {
476 return Err(FlatbufferError::FieldTypeMismatch(
477 String::from("String"),
478 field_type.variant_name().unwrap_or_default().to_string(),
479 ));
480 }
481
482 let table = Table::follow(buf, table_loc);
483
484 let Some(field_loc) = get_field_loc(&table, field) else {
485 return Err(FlatbufferError::SetValueNotSupported);
486 };
487
488 if buf.len() < field_loc + get_type_size(field_type) {
489 return Err(FlatbufferError::VerificationError(
490 InvalidFlatbuffer::RangeOutOfBounds {
491 range: core::ops::Range {
492 start: field_loc,
493 end: field_loc.saturating_add(get_type_size(field_type)),
494 },
495 error_trace: Default::default(),
496 },
497 ));
498 }
499
500 let string_loc = unsafe { deref_uoffset(buf, field_loc)? };
502 if buf.len() < string_loc.saturating_add(SIZE_UOFFSET) {
503 return Err(FlatbufferError::VerificationError(
504 InvalidFlatbuffer::RangeOutOfBounds {
505 range: core::ops::Range {
506 start: string_loc,
507 end: string_loc.saturating_add(SIZE_UOFFSET),
508 },
509 error_trace: Default::default(),
510 },
511 ));
512 }
513
514 let len_old = unsafe { read_uoffset(buf, string_loc) };
516 if buf.len()
517 < string_loc
518 .saturating_add(SIZE_UOFFSET)
519 .saturating_add(len_old.try_into()?)
520 {
521 return Err(FlatbufferError::VerificationError(
522 InvalidFlatbuffer::RangeOutOfBounds {
523 range: core::ops::Range {
524 start: string_loc,
525 end: string_loc
526 .saturating_add(SIZE_UOFFSET)
527 .saturating_add(len_old.try_into()?),
528 },
529 error_trace: Default::default(),
530 },
531 ));
532 }
533
534 let len_new = v.len();
535 let delta = len_new as isize - len_old as isize;
536 let mut bytes_to_insert = v.as_bytes().to_vec();
537
538 if delta != 0 {
539 let mask = (size_of::<core::ffi::c_long>() - 1) as isize;
543 let offset = (delta + mask) & !mask;
544 let mut visited_vec = vec![false; buf.len()];
545
546 if offset != 0 {
547 update_offset(
548 buf,
549 table_loc,
550 &mut visited_vec,
551 &schema.root_table().unwrap(),
552 schema,
553 string_loc,
554 offset,
555 )?;
556
557 emplace_scalar::<SOffsetT>(
559 &mut buf[string_loc..string_loc + SIZE_UOFFSET],
560 len_new.try_into()?,
561 );
562 }
563
564 bytes_to_insert.resize(bytes_to_insert.len() + (offset - delta) as usize, 0);
566 }
567
568 buf.splice(
570 string_loc + SIZE_SOFFSET..string_loc + SIZE_UOFFSET + usize::try_from(len_old)?,
571 bytes_to_insert,
572 );
573 Ok(())
574}
575
576fn get_type_size(base_type: BaseType) -> usize {
578 match base_type {
579 BaseType::UType | BaseType::Bool | BaseType::Byte | BaseType::UByte => 1,
580 BaseType::Short | BaseType::UShort => 2,
581 BaseType::Int
582 | BaseType::UInt
583 | BaseType::Float
584 | BaseType::String
585 | BaseType::Vector
586 | BaseType::Obj
587 | BaseType::Union => 4,
588 BaseType::Long | BaseType::ULong | BaseType::Double | BaseType::Vector64 => 8,
589 _ => 0,
590 }
591}
592
593unsafe fn get_field_loc(table: &Table, field: &Field) -> Option<usize> {
599 let field_offset = table.vtable().get(field.offset()) as usize;
600 if field_offset == 0 {
601 return None;
602 }
603
604 Some(table.loc() + field_offset)
605}
606
607unsafe fn get_any_value_integer(
613 base_type: BaseType,
614 buf: &[u8],
615 loc: usize,
616) -> FlatbufferResult<i64> {
617 match base_type {
618 BaseType::UType | BaseType::UByte => i64::from_u8(u8::follow(buf, loc)),
619 BaseType::Bool => bool::follow(buf, loc).try_into().ok(),
620 BaseType::Byte => i64::from_i8(i8::follow(buf, loc)),
621 BaseType::Short => i64::from_i16(i16::follow(buf, loc)),
622 BaseType::UShort => i64::from_u16(u16::follow(buf, loc)),
623 BaseType::Int => i64::from_i32(i32::follow(buf, loc)),
624 BaseType::UInt => i64::from_u32(u32::follow(buf, loc)),
625 BaseType::Long => Some(i64::follow(buf, loc)),
626 BaseType::ULong => i64::from_u64(u64::follow(buf, loc)),
627 BaseType::Float => i64::from_f32(f32::follow(buf, loc)),
628 BaseType::Double => i64::from_f64(f64::follow(buf, loc)),
629 BaseType::String => ForwardsUOffset::<&str>::follow(buf, loc)
630 .parse::<i64>()
631 .ok(),
632 _ => None, }
634 .ok_or(FlatbufferError::FieldTypeMismatch(
635 String::from("i64"),
636 base_type.variant_name().unwrap_or_default().to_string(),
637 ))
638}
639
640unsafe fn get_any_value_float(
646 base_type: BaseType,
647 buf: &[u8],
648 loc: usize,
649) -> FlatbufferResult<f64> {
650 match base_type {
651 BaseType::UType | BaseType::UByte => f64::from_u8(u8::follow(buf, loc)),
652 BaseType::Bool => bool::follow(buf, loc).try_into().ok(),
653 BaseType::Byte => f64::from_i8(i8::follow(buf, loc)),
654 BaseType::Short => f64::from_i16(i16::follow(buf, loc)),
655 BaseType::UShort => f64::from_u16(u16::follow(buf, loc)),
656 BaseType::Int => f64::from_i32(i32::follow(buf, loc)),
657 BaseType::UInt => f64::from_u32(u32::follow(buf, loc)),
658 BaseType::Long => f64::from_i64(i64::follow(buf, loc)),
659 BaseType::ULong => f64::from_u64(u64::follow(buf, loc)),
660 BaseType::Float => f64::from_f32(f32::follow(buf, loc)),
661 BaseType::Double => Some(f64::follow(buf, loc)),
662 BaseType::String => ForwardsUOffset::<&str>::follow(buf, loc)
663 .parse::<f64>()
664 .ok(),
665 _ => None,
666 }
667 .ok_or(FlatbufferError::FieldTypeMismatch(
668 String::from("f64"),
669 base_type.variant_name().unwrap_or_default().to_string(),
670 ))
671}
672
673unsafe fn get_any_value_string(
679 base_type: BaseType,
680 buf: &[u8],
681 loc: usize,
682 schema: &Schema,
683 type_index: usize,
684) -> String {
685 match base_type {
686 BaseType::Float | BaseType::Double => get_any_value_float(base_type, buf, loc)
687 .unwrap_or_default()
688 .to_string(),
689 BaseType::String => {
690 String::from_utf8_lossy(ForwardsUOffset::<&[u8]>::follow(buf, loc)).to_string()
691 }
692 BaseType::Obj => {
693 let object: Object = schema.objects().get(type_index);
697 let mut s = object.name().to_string();
698 s += " { ";
699 if object.is_struct() {
700 let st: Struct<'_> = Struct::follow(buf, loc);
701 for field in object.fields() {
702 let field_value = get_any_field_string_in_struct(&st, &field, schema);
703 s += field.name();
704 s += ": ";
705 s += field_value.as_str();
706 s += ", ";
707 }
708 } else {
709 let table = ForwardsUOffset::<Table>::follow(buf, loc);
710 for field in object.fields() {
711 if table.vtable().get(field.offset()) == 0 {
712 continue;
713 }
714 let mut field_value = get_any_field_string(&table, &field, schema);
715 if field.type_().base_type() == BaseType::String {
716 field_value = format!("{:?}", field_value.as_str());
718 }
719 s += field.name();
720 s += ": ";
721 s += field_value.as_str();
722 s += ", ";
723 }
724 }
725 s + "}"
726 }
727 BaseType::Vector => String::from("[(elements)]"), BaseType::Union => String::from("(union)"), _ => get_any_value_integer(base_type, buf, loc)
730 .unwrap_or_default()
731 .to_string(),
732 }
733}
734
735fn set_any_value_integer(
737 base_type: BaseType,
738 buf: &mut [u8],
739 field_loc: usize,
740 v: i64,
741) -> FlatbufferResult<()> {
742 if buf.len() < get_type_size(base_type) {
743 return Err(FlatbufferError::VerificationError(
744 InvalidFlatbuffer::RangeOutOfBounds {
745 range: core::ops::Range {
746 start: field_loc,
747 end: field_loc.saturating_add(get_type_size(base_type)),
748 },
749 error_trace: Default::default(),
750 },
751 ));
752 }
753 let buf = &mut buf[field_loc..];
754 let type_name = base_type.variant_name().unwrap_or_default().to_string();
755
756 macro_rules! try_emplace {
757 ($ty:ty, $value:expr) => {
758 if let Ok(v) = TryInto::<$ty>::try_into($value) {
759 unsafe { Ok(emplace_scalar::<$ty>(buf, v)) }
761 } else {
762 Err(FlatbufferError::FieldTypeMismatch(
763 String::from("i64"),
764 type_name,
765 ))
766 }
767 };
768 }
769
770 match base_type {
771 BaseType::UType | BaseType::UByte => {
772 try_emplace!(u8, v)
773 }
774 BaseType::Bool => {
775 unsafe { Ok(emplace_scalar::<bool>(buf, v != 0)) }
777 }
778 BaseType::Byte => {
779 try_emplace!(i8, v)
780 }
781 BaseType::Short => {
782 try_emplace!(i16, v)
783 }
784 BaseType::UShort => {
785 try_emplace!(u16, v)
786 }
787 BaseType::Int => {
788 try_emplace!(i32, v)
789 }
790 BaseType::UInt => {
791 try_emplace!(u32, v)
792 }
793 BaseType::Long => {
794 unsafe { Ok(emplace_scalar::<i64>(buf, v)) }
796 }
797 BaseType::ULong => {
798 try_emplace!(u64, v)
799 }
800 BaseType::Float => {
801 if let Some(value) = f32::from_i64(v) {
802 unsafe { Ok(emplace_scalar::<f32>(buf, value)) }
804 } else {
805 Err(FlatbufferError::FieldTypeMismatch(
806 String::from("i64"),
807 type_name,
808 ))
809 }
810 }
811 BaseType::Double => {
812 if let Some(value) = f64::from_i64(v) {
813 unsafe { Ok(emplace_scalar::<f64>(buf, value)) }
815 } else {
816 Err(FlatbufferError::FieldTypeMismatch(
817 String::from("i64"),
818 type_name,
819 ))
820 }
821 }
822 _ => Err(FlatbufferError::SetValueNotSupported),
823 }
824}
825
826fn set_any_value_float(
828 base_type: BaseType,
829 buf: &mut [u8],
830 field_loc: usize,
831 v: f64,
832) -> FlatbufferResult<()> {
833 if buf.len() < get_type_size(base_type) {
834 return Err(FlatbufferError::VerificationError(
835 InvalidFlatbuffer::RangeOutOfBounds {
836 range: core::ops::Range {
837 start: field_loc,
838 end: field_loc.saturating_add(get_type_size(base_type)),
839 },
840 error_trace: Default::default(),
841 },
842 ));
843 }
844 let buf = &mut buf[field_loc..];
845 let type_name = base_type.variant_name().unwrap_or_default().to_string();
846
847 match base_type {
848 BaseType::UType | BaseType::UByte => {
849 if let Some(value) = u8::from_f64(v) {
850 unsafe {
852 return Ok(emplace_scalar::<u8>(buf, value));
853 }
854 }
855 }
856 BaseType::Bool => {
857 unsafe {
859 return Ok(emplace_scalar::<bool>(buf, v != 0f64));
860 }
861 }
862 BaseType::Byte => {
863 if let Some(value) = i8::from_f64(v) {
864 unsafe {
866 return Ok(emplace_scalar::<i8>(buf, value));
867 }
868 }
869 }
870 BaseType::Short => {
871 if let Some(value) = i16::from_f64(v) {
872 unsafe {
874 return Ok(emplace_scalar::<i16>(buf, value));
875 }
876 }
877 }
878 BaseType::UShort => {
879 if let Some(value) = u16::from_f64(v) {
880 unsafe {
882 return Ok(emplace_scalar::<u16>(buf, value));
883 }
884 }
885 }
886 BaseType::Int => {
887 if let Some(value) = i32::from_f64(v) {
888 unsafe {
890 return Ok(emplace_scalar::<i32>(buf, value));
891 }
892 }
893 }
894 BaseType::UInt => {
895 if let Some(value) = u32::from_f64(v) {
896 unsafe {
898 return Ok(emplace_scalar::<u32>(buf, value));
899 }
900 }
901 }
902 BaseType::Long => {
903 if let Some(value) = i64::from_f64(v) {
904 unsafe {
906 return Ok(emplace_scalar::<i64>(buf, value));
907 }
908 }
909 }
910 BaseType::ULong => {
911 if let Some(value) = u64::from_f64(v) {
912 unsafe {
914 return Ok(emplace_scalar::<u64>(buf, value));
915 }
916 }
917 }
918 BaseType::Float => {
919 if let Some(value) = f32::from_f64(v) {
920 if value != f32::INFINITY {
922 unsafe {
924 return Ok(emplace_scalar::<f32>(buf, value));
925 }
926 }
927 }
928 }
929 BaseType::Double => {
930 unsafe {
932 return Ok(emplace_scalar::<f64>(buf, v));
933 }
934 }
935 _ => return Err(FlatbufferError::SetValueNotSupported),
936 }
937 return Err(FlatbufferError::FieldTypeMismatch(
938 String::from("f64"),
939 type_name,
940 ));
941}
942
943fn is_scalar(base_type: BaseType) -> bool {
944 return base_type <= BaseType::Double;
945}
946
947unsafe fn update_offset(
953 buf: &mut [u8],
954 table_loc: usize,
955 updated: &mut [bool],
956 object: &Object,
957 schema: &Schema,
958 insertion_loc: usize,
959 offset: isize,
960) -> FlatbufferResult<()> {
961 if updated.len() != buf.len() {
962 return Err(FlatbufferError::SetStringPolluted);
963 }
964
965 if updated[table_loc] {
966 return Ok(());
967 }
968
969 let slice = &mut buf[table_loc..table_loc + SIZE_SOFFSET];
970 let vtable_offset = isize::try_from(read_scalar::<SOffsetT>(slice))?;
971 let vtable_loc = (isize::try_from(table_loc)? - vtable_offset).try_into()?;
972
973 if insertion_loc <= table_loc {
974 if (vtable_loc..table_loc).contains(&insertion_loc) {
977 emplace_scalar::<SOffsetT>(slice, (vtable_offset + offset).try_into()?);
978 updated[table_loc] = true;
979 }
980
981 return Ok(());
984 }
985
986 for field in object.fields() {
987 let field_type = field.type_().base_type();
988 if is_scalar(field_type) {
989 continue;
990 }
991
992 let field_offset = VOffsetT::follow(buf, vtable_loc.saturating_add(field.offset().into()));
993 if field_offset == 0 {
994 continue;
995 }
996
997 let field_loc = table_loc + usize::from(field_offset);
998 if updated[field_loc] {
999 continue;
1000 }
1001
1002 if field_type == BaseType::Obj
1003 && schema
1004 .objects()
1005 .get(field.type_().index().try_into()?)
1006 .is_struct()
1007 {
1008 continue;
1009 }
1010
1011 let slice = &mut buf[field_loc..field_loc + SIZE_UOFFSET];
1013 let field_value_offset = read_scalar::<UOffsetT>(slice);
1014 let field_value_loc = field_loc.saturating_add(field_value_offset.try_into()?);
1015 if (field_loc..field_value_loc).contains(&insertion_loc) {
1016 emplace_scalar::<UOffsetT>(
1017 slice,
1018 (isize::try_from(field_value_offset)? + offset).try_into()?,
1019 );
1020 updated[field_loc] = true;
1021 }
1022
1023 match field_type {
1024 BaseType::Obj => {
1025 let field_obj = schema.objects().get(field.type_().index().try_into()?);
1026 update_offset(
1027 buf,
1028 field_value_loc,
1029 updated,
1030 &field_obj,
1031 schema,
1032 insertion_loc,
1033 offset,
1034 )?;
1035 }
1036 BaseType::Vector => {
1037 let elem_type = field.type_().element();
1038 if elem_type != BaseType::Obj || elem_type != BaseType::String {
1039 continue;
1040 }
1041 if elem_type == BaseType::Obj
1042 && schema
1043 .objects()
1044 .get(field.type_().index().try_into()?)
1045 .is_struct()
1046 {
1047 continue;
1048 }
1049 let vec_size = usize::try_from(read_uoffset(buf, field_value_loc))?;
1050 for index in 0..vec_size {
1051 let elem_loc = field_value_loc + SIZE_UOFFSET + index * SIZE_UOFFSET;
1052 if updated[elem_loc] {
1053 continue;
1054 }
1055 let slice = &mut buf[elem_loc..elem_loc + SIZE_UOFFSET];
1056 let elem_value_offset = read_scalar::<UOffsetT>(slice);
1057 let elem_value_loc = elem_loc.saturating_add(elem_value_offset.try_into()?);
1058 if (elem_loc..elem_value_loc).contains(&insertion_loc) {
1059 emplace_scalar::<UOffsetT>(
1060 slice,
1061 (isize::try_from(elem_value_offset)? + offset).try_into()?,
1062 );
1063 updated[elem_loc] = true;
1064 }
1065
1066 if elem_type == BaseType::Obj {
1067 let elem_obj = schema.objects().get(field.type_().index().try_into()?);
1068 update_offset(
1069 buf,
1070 elem_value_loc,
1071 updated,
1072 &elem_obj,
1073 schema,
1074 insertion_loc,
1075 offset,
1076 )?;
1077 }
1078 }
1079 }
1080 BaseType::Union => {
1081 let union_enum = schema.enums().get(field.type_().index().try_into()?);
1082 let union_type = object
1083 .fields()
1084 .lookup_by_key(field.name().to_string() + "_type", |field, key| {
1085 field.key_compare_with_value(key)
1086 })
1087 .unwrap();
1088 let union_type_loc = vtable_loc.saturating_add(union_type.offset().into());
1089 let union_type_offset = VOffsetT::follow(buf, union_type_loc);
1090 let union_type_value =
1091 u8::follow(buf, table_loc.saturating_add(union_type_offset.into()));
1092 let union_enum_value = union_enum
1093 .values()
1094 .lookup_by_key(union_type_value.into(), |value, key| {
1095 value.key_compare_with_value(*key)
1096 })
1097 .unwrap();
1098 let union_object = schema
1099 .objects()
1100 .get(union_enum_value.union_type().unwrap().index().try_into()?);
1101 update_offset(
1102 buf,
1103 field_value_loc,
1104 updated,
1105 &union_object,
1106 schema,
1107 insertion_loc,
1108 offset,
1109 )?;
1110 }
1111 _ => (),
1112 }
1113 }
1114
1115 if (table_loc..vtable_loc).contains(&insertion_loc) {
1117 let slice = &mut buf[table_loc..table_loc + SIZE_SOFFSET];
1118 emplace_scalar::<SOffsetT>(slice, (vtable_offset - offset).try_into()?);
1119 updated[table_loc] = true;
1120 }
1121 Ok(())
1122}
1123
1124unsafe fn deref_uoffset(buf: &[u8], field_loc: usize) -> FlatbufferResult<usize> {
1130 Ok(field_loc.saturating_add(read_uoffset(buf, field_loc).try_into()?))
1131}
1132
1133unsafe fn read_uoffset(buf: &[u8], loc: usize) -> UOffsetT {
1139 let slice = &buf[loc..loc + SIZE_UOFFSET];
1140 read_scalar::<UOffsetT>(slice)
1141}