1 /*
2 *
3 * Copyright 2018 Google Inc. All rights reserved.
4 *
5 * Licensed under the Apache License, Version 2.0 (the "License");
6 * you may not use this file except in compliance with the License.
7 * You may obtain a copy of the License at
8 *
9 * http://www.apache.org/licenses/LICENSE-2.0
10 *
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
16 */
17
18 #![no_std]
19
20 #[cfg(not(feature = "no_std"))]
21 extern crate std;
22 #[cfg(not(feature = "no_std"))]
23 use alloc::vec::Vec;
24
25 #[macro_use]
26 extern crate alloc;
27
28 use alloc::string::String;
29
30 #[cfg(feature = "no_std")]
31 #[global_allocator]
32 static ALLOCATOR: libc_alloc::LibcAlloc = libc_alloc::LibcAlloc;
33
34 #[macro_use]
35 #[cfg(not(miri))] // slow.
36 extern crate quickcheck;
37 extern crate flatbuffers;
38 extern crate flexbuffers;
39 extern crate rand;
40 extern crate serde;
41 #[macro_use]
42 extern crate serde_derive;
43 #[cfg(not(miri))] // slow.
44 #[macro_use]
45 extern crate quickcheck_derive;
46
47 mod flexbuffers_tests;
48 mod more_defaults_test;
49 mod optional_scalars_test;
50
51 #[allow(dead_code, unused_imports, clippy::all)]
52 #[path = "../../include_test1/mod.rs"]
53 pub mod include_test1_generated;
54
55 #[allow(dead_code, unused_imports, clippy::all)]
56 #[path = "../../include_test2/mod.rs"]
57 pub mod include_test2_generated;
58
59 #[allow(dead_code, unused_imports, clippy::all)]
60 #[path = "../../namespace_test/mod.rs"]
61 pub mod namespace_test_generated;
62
63 #[allow(dead_code, unused_imports, clippy::all)]
64 #[path = "../../monster_test/mod.rs"]
65 mod monster_test_generated;
66 pub use monster_test_generated::my_game;
67
68 #[allow(dead_code, unused_imports, clippy::all)]
69 #[path = "../../optional_scalars/mod.rs"]
70 mod optional_scalars_generated;
71
72 #[allow(dead_code, unused_imports, clippy::all)]
73 #[path = "../../arrays_test/mod.rs"]
74 mod arrays_test_generated;
75
76 // We use incorrect casing to test keywords.
77 #[allow(dead_code, unused_imports, non_camel_case_types, non_snake_case)]
78 #[path = "../../keyword_test/mod.rs"]
79 mod keyword_test_generated;
80
81 // Test rust namer, should not cause compiling issues
82 #[allow(dead_code, unused_imports, clippy::all)]
83 #[path = "../../rust_namer_test/mod.rs"]
84 mod rust_namer_test;
85
86 #[rustfmt::skip] // TODO: Use standard rust formatting and remove dead code.
87 #[allow(dead_code)]
88 mod flatbuffers_tests {
89 use super::*;
90
91 // Include simple random number generator to ensure results will be the
92 // same across platforms.
93 // http://en.wikipedia.org/wiki/Park%E2%80%93Miller_random_number_generator
94 struct LCG(u64);
95 impl LCG {
new() -> Self96 fn new() -> Self {
97 LCG { 0: 48271 }
98 }
next(&mut self) -> u6499 fn next(&mut self) -> u64 {
100 let old = self.0;
101 self.0 = (self.0 * 279470273u64) % 4294967291u64;
102 old
103 }
reset(&mut self)104 fn reset(&mut self) {
105 self.0 = 48271
106 }
107 }
108
109 // test helper macro to return an error if two expressions are not equal
110 macro_rules! check_eq {
111 ($field_call:expr, $want:expr) => (
112 if $field_call == $want {
113 Ok(())
114 } else {
115 Err(stringify!($field_call))
116 }
117 )
118 }
119
120 #[test]
macro_check_eq()121 fn macro_check_eq() {
122 assert!(check_eq!(1, 1).is_ok());
123 assert!(check_eq!(1, 2).is_err());
124 }
125
126 // test helper macro to return an error if two expressions are equal
127 macro_rules! check_is_some {
128 ($field_call:expr) => (
129 if $field_call.is_some() {
130 Ok(())
131 } else {
132 Err(stringify!($field_call))
133 }
134 )
135 }
136
137 #[test]
macro_check_is_some()138 fn macro_check_is_some() {
139 let some: Option<usize> = Some(0);
140 let none: Option<usize> = None;
141 assert!(check_is_some!(some).is_ok());
142 assert!(check_is_some!(none).is_err());
143 }
144
145 #[test]
object_api_defaults()146 fn object_api_defaults() {
147 use my_game::example::*;
148 assert_eq!(
149 Vec3T::default(), Vec3T {
150 x: 0.0,
151 y: 0.0,
152 z: 0.0,
153 test1: 0.0,
154 test2: Color::empty(),
155 test3: TestT {
156 a: 0,
157 b: 0
158 }
159 });
160 let mut default_without_nan = MonsterT::default();
161 default_without_nan.nan_default = 0.0;
162 assert_eq!(
163 default_without_nan,
164 MonsterT {
165 pos: None,
166 hp: 100,
167 mana: 150,
168 name: String::new(), // required string => default is empty string.
169 color: Color::Blue,
170 inventory: None,
171 testarrayoftables: None,
172 testarrayofstring: None,
173 testarrayofstring2: None,
174 testarrayofbools: None,
175 testarrayofsortedstruct: None,
176 enemy: None,
177 test: AnyT::NONE,
178 test4: None,
179 test5: None,
180 testnestedflatbuffer: None,
181 testempty: None,
182 testbool: false,
183 testhashs32_fnv1: 0,
184 testhashu32_fnv1: 0,
185 testhashs64_fnv1: 0,
186 testhashu64_fnv1: 0,
187 testhashs32_fnv1a: 0,
188 testhashu32_fnv1a: 0,
189 testhashs64_fnv1a: 0,
190 testhashu64_fnv1a: 0,
191 testf: 3.14159,
192 testf2: 3.0,
193 testf3: 0.0,
194 flex: None,
195 vector_of_longs: None,
196 vector_of_doubles: None,
197 parent_namespace_test: None,
198 vector_of_referrables: None,
199 single_weak_reference: 0,
200 vector_of_weak_references: None,
201 vector_of_strong_referrables: None,
202 co_owning_reference: 0,
203 vector_of_co_owning_references: None,
204 non_owning_reference: 0,
205 vector_of_non_owning_references: None,
206 any_unique: AnyUniqueAliasesT::NONE,
207 any_ambiguous: AnyAmbiguousAliasesT::NONE,
208 vector_of_enums: None,
209 signed_enum: Race::None,
210 testrequirednestedflatbuffer: None, // despite the name, it is not required.
211 scalar_key_sorted_tables: None,
212 native_inline: None,
213 long_enum_non_enum_default: Default::default(),
214 long_enum_normal_default: LongEnum::LongOne,
215 nan_default: 0.0,
216 inf_default: f32::INFINITY,
217 positive_inf_default: f32::INFINITY,
218 infinity_default: f32::INFINITY,
219 positive_infinity_default: f32::INFINITY,
220 negative_inf_default: f32::NEG_INFINITY,
221 negative_infinity_default: f32::NEG_INFINITY,
222 double_inf_default: f64::INFINITY,
223 }
224 );
225 }
226
create_serialized_example_with_generated_code(builder: &mut flatbuffers::FlatBufferBuilder)227 fn create_serialized_example_with_generated_code(builder: &mut flatbuffers::FlatBufferBuilder) {
228 let mon = {
229 let s0 = builder.create_string("test1");
230 let s1 = builder.create_string("test2");
231 let fred_name = builder.create_string("Fred");
232
233 // can't inline creation of this Vec3 because we refer to it by reference, so it must live
234 // long enough to be used by MonsterArgs.
235 let pos = my_game::example::Vec3::new(1.0, 2.0, 3.0, 3.0, my_game::example::Color::Green, &my_game::example::Test::new(5i16, 6i8));
236
237 let args = my_game::example::MonsterArgs{
238 hp: 80,
239 mana: 150,
240 name: Some(builder.create_string("MyMonster")),
241 pos: Some(&pos),
242 test_type: my_game::example::Any::Monster,
243 test: Some(my_game::example::Monster::create(builder, &my_game::example::MonsterArgs{
244 name: Some(fred_name),
245 ..Default::default()
246 }).as_union_value()),
247 inventory: Some(builder.create_vector(&[0u8, 1, 2, 3, 4])),
248 test4: Some(builder.create_vector(&[my_game::example::Test::new(10, 20),
249 my_game::example::Test::new(30, 40)])),
250 testarrayofstring: Some(builder.create_vector(&[s0, s1])),
251 ..Default::default()
252 };
253 my_game::example::Monster::create(builder, &args)
254 };
255 my_game::example::finish_monster_buffer(builder, mon);
256 }
257
create_serialized_example_with_library_code(builder: &mut flatbuffers::FlatBufferBuilder)258 fn create_serialized_example_with_library_code(builder: &mut flatbuffers::FlatBufferBuilder) {
259 let nested_union_mon = {
260 let name = builder.create_string("Fred");
261 let table_start = builder.start_table();
262 builder.push_slot_always(my_game::example::Monster::VT_NAME, name);
263 builder.end_table(table_start)
264 };
265 let pos = my_game::example::Vec3::new(1.0, 2.0, 3.0, 3.0, my_game::example::Color::Green, &my_game::example::Test::new(5i16, 6i8));
266 let inv = builder.create_vector(&[0u8, 1, 2, 3, 4]);
267
268 let test4 = builder.create_vector(&[my_game::example::Test::new(10, 20),
269 my_game::example::Test::new(30, 40)][..]);
270
271 let name = builder.create_string("MyMonster");
272
273 let test1 = builder.create_string("test1");
274 let test2 = builder.create_string("test2");
275
276 let testarrayofstring = builder.create_vector(&[test1, test2]);
277
278 // begin building
279
280 let table_start = builder.start_table();
281 builder.push_slot(my_game::example::Monster::VT_HP, 80i16, 100);
282 builder.push_slot_always(my_game::example::Monster::VT_NAME, name);
283 builder.push_slot_always(my_game::example::Monster::VT_POS, &pos);
284 builder.push_slot(my_game::example::Monster::VT_TEST_TYPE, my_game::example::Any::Monster, my_game::example::Any::NONE);
285 builder.push_slot_always(my_game::example::Monster::VT_TEST, nested_union_mon);
286 builder.push_slot_always(my_game::example::Monster::VT_INVENTORY, inv);
287 builder.push_slot_always(my_game::example::Monster::VT_TEST4, test4);
288 builder.push_slot_always(my_game::example::Monster::VT_TESTARRAYOFSTRING, testarrayofstring);
289 let root = builder.end_table(table_start);
290 builder.finish(root, Some(my_game::example::MONSTER_IDENTIFIER));
291 }
292
serialized_example_is_accessible_and_correct(bytes: &[u8], identifier_required: bool, size_prefixed: bool) -> Result<(), &'static str>293 fn serialized_example_is_accessible_and_correct(bytes: &[u8], identifier_required: bool, size_prefixed: bool) -> Result<(), &'static str> {
294
295 if identifier_required {
296 let correct = if size_prefixed {
297 my_game::example::monster_size_prefixed_buffer_has_identifier(bytes)
298 } else {
299 my_game::example::monster_buffer_has_identifier(bytes)
300 };
301 check_eq!(correct, true)?;
302 }
303
304 let m = if size_prefixed {
305 my_game::example::size_prefixed_root_as_monster(bytes).unwrap()
306 } else {
307 my_game::example::root_as_monster(bytes).unwrap()
308 };
309
310 check_eq!(m.hp(), 80)?;
311 check_eq!(m.mana(), 150)?;
312 check_eq!(m.name(), "MyMonster")?;
313
314 let pos = m.pos().unwrap();
315 check_eq!(pos.x(), 1.0f32)?;
316 check_eq!(pos.y(), 2.0f32)?;
317 check_eq!(pos.z(), 3.0f32)?;
318 check_eq!(pos.test1(), 3.0f64)?;
319 check_eq!(pos.test2(), my_game::example::Color::Green)?;
320
321 let pos_test3 = pos.test3();
322 check_eq!(pos_test3.a(), 5i16)?;
323 check_eq!(pos_test3.b(), 6i8)?;
324
325 check_eq!(m.test_type(), my_game::example::Any::Monster)?;
326 check_is_some!(m.test())?;
327 let table2 = m.test().unwrap();
328 let monster2 = unsafe { my_game::example::Monster::init_from_table(table2) };
329
330 check_eq!(monster2.name(), "Fred")?;
331
332 check_is_some!(m.inventory())?;
333 let inv = m.inventory().unwrap();
334 check_eq!(inv.len(), 5)?;
335 check_eq!(inv.iter().sum::<u8>(), 10u8)?;
336 check_eq!(inv.iter().rev().sum::<u8>(), 10u8)?;
337
338 check_is_some!(m.test4())?;
339 let test4 = m.test4().unwrap();
340 check_eq!(test4.len(), 2)?;
341 check_eq!(test4.get(0).a() as i32 + test4.get(0).b() as i32 +
342 test4.get(1).a() as i32 + test4.get(1).b() as i32, 100)?;
343
344 check_is_some!(m.testarrayofstring())?;
345 let testarrayofstring = m.testarrayofstring().unwrap();
346 check_eq!(testarrayofstring.len(), 2)?;
347 check_eq!(testarrayofstring.get(0), "test1")?;
348 check_eq!(testarrayofstring.get(1), "test2")?;
349
350 Ok(())
351 }
352
353 #[test]
test_object_api_reads_correctly() -> Result<(), &'static str>354 fn test_object_api_reads_correctly() -> Result<(), &'static str>{
355 let mut fbb = flatbuffers::FlatBufferBuilder::new();
356 create_serialized_example_with_library_code(&mut fbb);
357
358 let m = my_game::example::root_as_monster(fbb.finished_data()).unwrap().unpack();
359
360 check_eq!(m.hp, 80)?;
361 check_eq!(m.mana, 150)?;
362 check_eq!(m.name, "MyMonster")?;
363
364 let pos = m.pos.as_ref().unwrap();
365 check_eq!(pos.x, 1.0f32)?;
366 check_eq!(pos.y, 2.0f32)?;
367 check_eq!(pos.z, 3.0f32)?;
368 check_eq!(pos.test1, 3.0f64)?;
369 check_eq!(pos.test2, my_game::example::Color::Green)?;
370
371 let pos_test3 = &pos.test3;
372 check_eq!(pos_test3.a, 5i16)?;
373 check_eq!(pos_test3.b, 6i8)?;
374
375 let monster2 = m.test.as_monster().unwrap();
376 check_eq!(monster2.name, "Fred")?;
377
378 let inv = m.inventory.as_ref().unwrap();
379 check_eq!(inv.len(), 5)?;
380 check_eq!(inv.iter().sum::<u8>(), 10u8)?;
381 check_eq!(inv.iter().rev().sum::<u8>(), 10u8)?;
382
383 let test4 = m.test4.as_ref().unwrap();
384 check_eq!(test4.len(), 2)?;
385 check_eq!(test4[0].a as i32 + test4[0].b as i32 +
386 test4[1].a as i32 + test4[1].b as i32, 100)?;
387
388 let testarrayofstring = m.testarrayofstring.as_ref().unwrap();
389 check_eq!(testarrayofstring.len(), 2)?;
390 check_eq!(testarrayofstring[0], "test1")?;
391 check_eq!(testarrayofstring[1], "test2")?;
392 Ok(())
393 }
394
395
396
397 // Disabled due to Windows CI limitations.
398 // #[test]
399 // fn builder_initializes_with_maximum_buffer_size() {
400 // flatbuffers::FlatBufferBuilder::with_capacity(flatbuffers::FLATBUFFERS_MAX_BUFFER_SIZE);
401 // }
402
403 #[should_panic]
404 #[test]
builder_abort_with_greater_than_maximum_buffer_size()405 fn builder_abort_with_greater_than_maximum_buffer_size() {
406 flatbuffers::FlatBufferBuilder::with_capacity(flatbuffers::FLATBUFFERS_MAX_BUFFER_SIZE+1);
407 }
408
409 #[test]
builder_collapses_into_vec()410 fn builder_collapses_into_vec() {
411 let mut b = flatbuffers::FlatBufferBuilder::new();
412 create_serialized_example_with_generated_code(&mut b);
413 let (backing_buf, head) = b.collapse();
414 serialized_example_is_accessible_and_correct(&backing_buf[head..], true, false).unwrap();
415 }
416
417 #[test]
418 #[cfg(not(miri))] // slow.
verifier_one_byte_errors_do_not_crash()419 fn verifier_one_byte_errors_do_not_crash() {
420 let mut b = flatbuffers::FlatBufferBuilder::new();
421 create_serialized_example_with_library_code(&mut b);
422 let mut badbuf = b.finished_data().to_vec();
423 // If the verifier says a buffer is okay then using it won't cause a crash.
424 // We use write_fmt since Debug visits all the fields - but there's no need to store anything.
425 struct ForgetfulWriter;
426 use core::fmt::Write;
427 impl Write for ForgetfulWriter {
428 fn write_str(&mut self, _: &str) -> Result<(), core::fmt::Error> {
429 Ok(())
430 }
431 }
432 let mut w = ForgetfulWriter;
433 for d in 1..=255u8 {
434 for i in 0..badbuf.len() {
435 let orig = badbuf[i];
436 badbuf[i] = badbuf[i].wrapping_add(d);
437 if let Ok(m) = flatbuffers::root::<my_game::example::Monster>(&badbuf) {
438 w.write_fmt(format_args!("{:?}", m)).unwrap()
439 }
440 badbuf[i] = orig;
441 }
442 }
443 }
444 #[test]
445 #[cfg(not(miri))] // slow.
verifier_too_many_tables()446 fn verifier_too_many_tables() {
447 use my_game::example::*;
448 let b = &mut flatbuffers::FlatBufferBuilder::new();
449 let r = Referrable::create(b, &ReferrableArgs { id: 42 });
450 let rs = b.create_vector(&vec![r; 500]);
451 let name = Some(b.create_string("foo"));
452 let m = Monster::create(b, &MonsterArgs {
453 vector_of_referrables: Some(rs),
454 name, // required field.
455 ..Default::default()
456 });
457 b.finish(m, None);
458
459 let data = b.finished_data();
460 let mut opts = flatbuffers::VerifierOptions::default();
461
462 opts.max_tables = 500;
463 let res = flatbuffers::root_with_opts::<Monster>(&opts, data);
464 assert_eq!(res.unwrap_err(), flatbuffers::InvalidFlatbuffer::TooManyTables);
465
466 opts.max_tables += 2;
467 assert!(flatbuffers::root_with_opts::<Monster>(&opts, data).is_ok());
468 }
469 #[test]
470 #[cfg(not(miri))] // slow.
verifier_apparent_size_too_large()471 fn verifier_apparent_size_too_large() {
472 use my_game::example::*;
473 let b = &mut flatbuffers::FlatBufferBuilder::new();
474 let name = Some(b.create_string("foo"));
475 // String amplification attack.
476 let s = b.create_string(&(core::iter::repeat("X").take(1000).collect::<String>()));
477 let testarrayofstring = Some(b.create_vector(&vec![s; 1000]));
478 let m = Monster::create(b, &MonsterArgs {
479 testarrayofstring,
480 name, // required field.
481 ..Default::default()
482 });
483 b.finish(m, None);
484 let data = b.finished_data();
485 assert!(data.len() < 5200); // est 4000 for the vector + 1000 for the string + 200 overhead.
486 let mut opts = flatbuffers::VerifierOptions::default();
487 opts.max_apparent_size = 1_000_000;
488
489 let res = flatbuffers::root_with_opts::<Monster>(&opts, data);
490 assert_eq!(res.unwrap_err(), flatbuffers::InvalidFlatbuffer::ApparentSizeTooLarge);
491
492 opts.max_apparent_size += 20_000;
493 assert!(flatbuffers::root_with_opts::<Monster>(&opts, data).is_ok());
494 }
495 #[test]
verifier_in_too_deep()496 fn verifier_in_too_deep() {
497 use my_game::example::*;
498 let b = &mut flatbuffers::FlatBufferBuilder::new();
499 let name = Some(b.create_string("foo"));
500 let mut prev_monster = None;
501 for _ in 0..11 {
502 prev_monster = Some(Monster::create(b, &MonsterArgs {
503 enemy: prev_monster,
504 name, // required field.
505 ..Default::default()
506 }));
507 };
508 b.finish(prev_monster.unwrap(), None);
509 let mut opts = flatbuffers::VerifierOptions::default();
510 opts.max_depth = 10;
511
512 let data = b.finished_data();
513 let res = flatbuffers::root_with_opts::<Monster>(&opts, data);
514 assert_eq!(res.unwrap_err(), flatbuffers::InvalidFlatbuffer::DepthLimitReached);
515
516 opts.max_depth += 1;
517 assert!(flatbuffers::root_with_opts::<Monster>(&opts, data).is_ok());
518 }
519
520 #[cfg(test)]
521 mod generated_constants {
522 extern crate flatbuffers;
523 use super::my_game;
524
525 #[test]
monster_identifier()526 fn monster_identifier() {
527 assert_eq!("MONS", my_game::example::MONSTER_IDENTIFIER);
528 }
529
530 #[test]
monster_file_extension()531 fn monster_file_extension() {
532 assert_eq!("mon", my_game::example::MONSTER_EXTENSION);
533 }
534
535 #[test]
enum_constants_are_public()536 fn enum_constants_are_public() {
537 assert_eq!(-1, my_game::example::Race::ENUM_MIN);
538 assert_eq!(2, my_game::example::Race::ENUM_MAX);
539 assert_eq!(my_game::example::Race::ENUM_VALUES, [
540 my_game::example::Race::None,
541 my_game::example::Race::Human,
542 my_game::example::Race::Dwarf,
543 my_game::example::Race::Elf,
544 ]);
545
546 assert_eq!(0, my_game::example::Any::ENUM_MIN);
547 assert_eq!(3, my_game::example::Any::ENUM_MAX);
548 assert_eq!(my_game::example::Any::ENUM_VALUES, [
549 my_game::example::Any::NONE,
550 my_game::example::Any::Monster,
551 my_game::example::Any::TestSimpleTableWithEnum,
552 my_game::example::Any::MyGame_Example2_Monster,
553 ]);
554
555 assert_eq!(0, my_game::example::AnyUniqueAliases::ENUM_MIN);
556 assert_eq!(3, my_game::example::AnyUniqueAliases::ENUM_MAX);
557 assert_eq!(my_game::example::AnyUniqueAliases::ENUM_VALUES, [
558 my_game::example::AnyUniqueAliases::NONE,
559 my_game::example::AnyUniqueAliases::M,
560 my_game::example::AnyUniqueAliases::TS,
561 my_game::example::AnyUniqueAliases::M2,
562 ]);
563
564 assert_eq!(0, my_game::example::AnyAmbiguousAliases::ENUM_MIN);
565 assert_eq!(3, my_game::example::AnyAmbiguousAliases::ENUM_MAX);
566 assert_eq!(my_game::example::AnyAmbiguousAliases::ENUM_VALUES, [
567 my_game::example::AnyAmbiguousAliases::NONE,
568 my_game::example::AnyAmbiguousAliases::M1,
569 my_game::example::AnyAmbiguousAliases::M2,
570 my_game::example::AnyAmbiguousAliases::M3,
571 ]);
572 }
573 }
574
575 #[cfg(not(feature = "no_std"))]
576 #[cfg(test)]
577 mod lifetime_correctness {
578 extern crate flatbuffers;
579
580 use core::mem;
581
582 use super::my_game;
583 use super::load_file;
584
585 #[test]
table_get_field_from_static_buffer_1()586 fn table_get_field_from_static_buffer_1() {
587 let buf = load_file("../monsterdata_test.mon").expect("missing monsterdata_test.mon");
588 // create 'static slice
589 let slice: &[u8] = &buf;
590 let slice: &'static [u8] = unsafe { mem::transmute(slice) };
591 // make sure values retrieved from the 'static buffer are themselves 'static
592 let monster: my_game::example::Monster<'static> = my_game::example::root_as_monster(slice).unwrap();
593 // this line should compile:
594 let name: Option<&'static str> = unsafe { monster._tab.get::<flatbuffers::ForwardsUOffset<&str>>(my_game::example::Monster::VT_NAME, None) };
595 assert_eq!(name, Some("MyMonster"));
596 }
597
598 #[test]
table_get_field_from_static_buffer_2()599 fn table_get_field_from_static_buffer_2() {
600 static DATA: [u8; 4] = [0, 0, 0, 0]; // some binary data
601 let table: flatbuffers::Table<'static> = unsafe { flatbuffers::Table::new(&DATA, 0) };
602 // this line should compile:
603 unsafe { table.get::<&'static str>(0, None) };
604 }
605
606 #[test]
table_object_self_lifetime_in_closure()607 fn table_object_self_lifetime_in_closure() {
608 // This test is designed to ensure that lifetimes for temporary intermediate tables aren't inflated beyond where the need to be.
609 let buf = load_file("../monsterdata_test.mon").expect("missing monsterdata_test.mon");
610 let monster = my_game::example::root_as_monster(&buf).unwrap();
611 let enemy: Option<my_game::example::Monster> = monster.enemy();
612 // This line won't compile if "self" is required to live for the lifetime of buf above as the borrow disappears at the end of the closure.
613 let enemy_of_my_enemy = enemy.map(|e| {
614 // enemy (the Option) is consumed, and the enum's value is taken as a temporary (e) at the start of the closure
615 let name = e.name();
616 // ... the temporary dies here, so for this to compile name's lifetime must not be tied to the temporary
617 name
618 // If this test fails the error would be "`e` dropped here while still borrowed"
619 });
620 assert_eq!(enemy_of_my_enemy, Some("Fred"));
621 }
622 }
623
624 #[cfg(test)]
625 mod roundtrip_generated_code {
626 extern crate flatbuffers;
627
628 use alloc::vec::Vec;
629
630 use super::my_game;
631
build_mon<'a, 'b>(builder: &'a mut flatbuffers::FlatBufferBuilder, args: &'b my_game::example::MonsterArgs) -> my_game::example::Monster<'a>632 fn build_mon<'a, 'b>(builder: &'a mut flatbuffers::FlatBufferBuilder, args: &'b my_game::example::MonsterArgs) -> my_game::example::Monster<'a> {
633 let mon = my_game::example::Monster::create(builder, &args);
634 my_game::example::finish_monster_buffer(builder, mon);
635 my_game::example::root_as_monster(builder.finished_data()).unwrap()
636 }
637
638 #[test]
scalar_store()639 fn scalar_store() {
640 let mut b = flatbuffers::FlatBufferBuilder::new();
641 let name = b.create_string("foo");
642 let m = build_mon(&mut b, &my_game::example::MonsterArgs{hp: 123, name: Some(name), ..Default::default()});
643 assert_eq!(m.hp(), 123);
644 }
645 #[test]
scalar_default()646 fn scalar_default() {
647 let mut b = flatbuffers::FlatBufferBuilder::new();
648 let name = b.create_string("foo");
649 let m = build_mon(&mut b, &my_game::example::MonsterArgs{name: Some(name), ..Default::default()});
650 assert_eq!(m.hp(), 100);
651 }
652 #[test]
string_store()653 fn string_store() {
654 let mut b = flatbuffers::FlatBufferBuilder::new();
655 let name = b.create_string("foobar");
656 let m = build_mon(&mut b, &my_game::example::MonsterArgs{name: Some(name), ..Default::default()});
657 assert_eq!(m.name(), "foobar");
658 }
659 #[test]
struct_store()660 fn struct_store() {
661 let mut b = flatbuffers::FlatBufferBuilder::new();
662 let name = b.create_string("foo");
663 let m = build_mon(&mut b, &my_game::example::MonsterArgs{
664 name: Some(name),
665 pos: Some(&my_game::example::Vec3::new(1.0, 2.0, 3.0, 4.0,
666 my_game::example::Color::Green,
667 &my_game::example::Test::new(98, 99))),
668 ..Default::default()
669 });
670 assert_eq!(m.pos(), Some(&my_game::example::Vec3::new(1.0, 2.0, 3.0, 4.0,
671 my_game::example::Color::Green,
672 &my_game::example::Test::new(98, 99))));
673 }
674 #[test]
struct_default()675 fn struct_default() {
676 let mut b = flatbuffers::FlatBufferBuilder::new();
677 let name = b.create_string("foo");
678 let m = build_mon(&mut b, &my_game::example::MonsterArgs{name: Some(name), ..Default::default()});
679 assert_eq!(m.pos(), None);
680 }
681 #[test]
enum_store()682 fn enum_store() {
683 let mut b = flatbuffers::FlatBufferBuilder::new();
684 let name = b.create_string("foo");
685 let m = build_mon(&mut b, &my_game::example::MonsterArgs{name: Some(name), color: my_game::example::Color::Red, ..Default::default()});
686 assert_eq!(m.color(), my_game::example::Color::Red);
687 }
688 #[test]
enum_default()689 fn enum_default() {
690 let mut b = flatbuffers::FlatBufferBuilder::new();
691 let name = b.create_string("foo");
692 let m = build_mon(&mut b, &my_game::example::MonsterArgs{name: Some(name), ..Default::default()});
693 assert_eq!(m.color(), my_game::example::Color::Blue);
694 }
695 #[test]
union_store()696 fn union_store() {
697 let b = &mut flatbuffers::FlatBufferBuilder::new();
698 {
699 let name_inner = b.create_string("foo");
700 let name_outer = b.create_string("bar");
701
702 let inner = my_game::example::Monster::create(b, &my_game::example::MonsterArgs{
703 name: Some(name_inner),
704 ..Default::default()
705 });
706 let outer = my_game::example::Monster::create(b, &my_game::example::MonsterArgs{
707 name: Some(name_outer),
708 test_type: my_game::example::Any::Monster,
709 test: Some(inner.as_union_value()),
710 ..Default::default()
711 });
712 my_game::example::finish_monster_buffer(b, outer);
713 }
714
715 let mon = my_game::example::root_as_monster(b.finished_data()).unwrap();
716 assert_eq!(mon.name(), "bar");
717 assert_eq!(mon.test_type(), my_game::example::Any::Monster);
718 let name = unsafe { my_game::example::Monster::init_from_table(mon.test().unwrap()).name() };
719 assert_eq!(name, "foo");
720 assert_eq!(mon.test_as_monster().unwrap().name(), "foo");
721 assert_eq!(mon.test_as_test_simple_table_with_enum(), None);
722 assert_eq!(mon.test_as_my_game_example_2_monster(), None);
723 }
724 #[test]
union_default()725 fn union_default() {
726 let mut b = flatbuffers::FlatBufferBuilder::new();
727 let name = b.create_string("foo");
728 let m = build_mon(&mut b, &my_game::example::MonsterArgs{name: Some(name), ..Default::default()});
729 assert_eq!(m.test_type(), my_game::example::Any::NONE);
730 assert_eq!(m.test(), None);
731 }
732 #[test]
table_full_namespace_store()733 fn table_full_namespace_store() {
734 let b = &mut flatbuffers::FlatBufferBuilder::new();
735 {
736 let name_inner = b.create_string("foo");
737 let name_outer = b.create_string("bar");
738
739 let inner = my_game::example::Monster::create(b, &my_game::example::MonsterArgs{
740 name: Some(name_inner),
741 ..Default::default()
742 });
743 let outer = my_game::example::Monster::create(b, &my_game::example::MonsterArgs{
744 name: Some(name_outer),
745 enemy: Some(inner),
746 ..Default::default()
747 });
748 my_game::example::finish_monster_buffer(b, outer);
749 }
750
751 let mon = my_game::example::root_as_monster(b.finished_data()).unwrap();
752 assert_eq!(mon.name(), "bar");
753 assert_eq!(mon.enemy().unwrap().name(), "foo");
754 }
755 #[test]
table_full_namespace_default()756 fn table_full_namespace_default() {
757 let mut b = flatbuffers::FlatBufferBuilder::new();
758 let name = b.create_string("foo");
759 let m = build_mon(&mut b, &my_game::example::MonsterArgs{name: Some(name), ..Default::default()});
760 assert_eq!(m.enemy(), None);
761 }
762 #[test]
table_store()763 fn table_store() {
764 let b = &mut flatbuffers::FlatBufferBuilder::new();
765 {
766 let id_inner = b.create_string("foo");
767 let name_outer = b.create_string("bar");
768
769 let inner = my_game::example::Stat::create(b, &my_game::example::StatArgs{
770 id: Some(id_inner),
771 ..Default::default()
772 });
773 let outer = my_game::example::Monster::create(b, &my_game::example::MonsterArgs{
774 name: Some(name_outer),
775 testempty: Some(inner),
776 ..Default::default()
777 });
778 my_game::example::finish_monster_buffer(b, outer);
779 }
780
781 let mon = my_game::example::root_as_monster(b.finished_data()).unwrap();
782 assert_eq!(mon.name(), "bar");
783 assert_eq!(mon.testempty().unwrap().id(), Some("foo"));
784 }
785 #[test]
table_default()786 fn table_default() {
787 let mut b = flatbuffers::FlatBufferBuilder::new();
788 let name = b.create_string("foo");
789 let m = build_mon(&mut b, &my_game::example::MonsterArgs{name: Some(name), ..Default::default()});
790 assert_eq!(m.testempty(), None);
791 }
792 #[test]
nested_flatbuffer_store()793 fn nested_flatbuffer_store() {
794 let b0 = {
795 let mut b0 = flatbuffers::FlatBufferBuilder::new();
796 let args = my_game::example::MonsterArgs{
797 hp: 123,
798 name: Some(b0.create_string("foobar")),
799 ..Default::default()
800 };
801 let mon = my_game::example::Monster::create(&mut b0, &args);
802 my_game::example::finish_monster_buffer(&mut b0, mon);
803 b0
804 };
805
806 let b1 = {
807 let mut b1 = flatbuffers::FlatBufferBuilder::new();
808 let args = my_game::example::MonsterArgs{
809 testnestedflatbuffer: Some(b1.create_vector(b0.finished_data())),
810 name: Some(b1.create_string("foo")),
811 ..Default::default()
812 };
813 let mon = my_game::example::Monster::create(&mut b1, &args);
814 my_game::example::finish_monster_buffer(&mut b1, mon);
815 b1
816 };
817
818 let m = my_game::example::root_as_monster(b1.finished_data()).unwrap();
819
820 assert!(m.testnestedflatbuffer().is_some());
821 assert_eq!(m.testnestedflatbuffer().unwrap().bytes(), b0.finished_data());
822
823 let m2_a = my_game::example::root_as_monster(m.testnestedflatbuffer().unwrap().bytes()).unwrap();
824 assert_eq!(m2_a.hp(), 123);
825 assert_eq!(m2_a.name(), "foobar");
826
827 assert!(m.testnestedflatbuffer_nested_flatbuffer().is_some());
828 let m2_b = m.testnestedflatbuffer_nested_flatbuffer().unwrap();
829
830 assert_eq!(m2_b.hp(), 123);
831 assert_eq!(m2_b.name(), "foobar");
832 }
833 #[test]
nested_flatbuffer_default()834 fn nested_flatbuffer_default() {
835 let mut b = flatbuffers::FlatBufferBuilder::new();
836 let name = b.create_string("foo");
837 let m = build_mon(&mut b, &my_game::example::MonsterArgs{name: Some(name), ..Default::default()});
838 assert!(m.testnestedflatbuffer().is_none());
839 }
840 #[test]
vector_of_string_store_helper_build()841 fn vector_of_string_store_helper_build() {
842 let mut b = flatbuffers::FlatBufferBuilder::new();
843 let strings = &[b.create_string("foobar"), b.create_string("baz")];
844 let v = b.create_vector(strings);
845 let name = b.create_string("foo");
846 let m = build_mon(&mut b, &my_game::example::MonsterArgs{
847 name: Some(name),
848 testarrayofstring: Some(v), ..Default::default()});
849 assert_eq!(m.testarrayofstring().unwrap().len(), 2);
850 assert_eq!(m.testarrayofstring().unwrap().get(0), "foobar");
851 assert_eq!(m.testarrayofstring().unwrap().get(1), "baz");
852
853 let rust_vec_inst = m.testarrayofstring().unwrap();
854 let rust_vec_iter_collect = rust_vec_inst.iter().collect::<Vec<_>>();
855 assert_eq!(rust_vec_iter_collect.len(), 2);
856 assert_eq!(rust_vec_iter_collect[0], "foobar");
857 assert_eq!(rust_vec_iter_collect[1], "baz");
858
859 let rust_vec_iter_rev_collect = rust_vec_inst.iter().rev().collect::<Vec<_>>();
860 assert_eq!(rust_vec_iter_rev_collect.len(), 2);
861 assert_eq!(rust_vec_iter_rev_collect[1], "foobar");
862 assert_eq!(rust_vec_iter_rev_collect[0], "baz");
863
864 }
865 #[test]
vector_of_string_store_manual_build()866 fn vector_of_string_store_manual_build() {
867 let mut b = flatbuffers::FlatBufferBuilder::new();
868 let s0 = b.create_string("foobar");
869 let s1 = b.create_string("baz");
870 let v = b.create_vector(&[s0, s1]);
871 let name = b.create_string("foo");
872 let m = build_mon(&mut b, &my_game::example::MonsterArgs{
873 name: Some(name),
874 testarrayofstring: Some(v), ..Default::default()});
875 assert_eq!(m.testarrayofstring().unwrap().len(), 2);
876 assert_eq!(m.testarrayofstring().unwrap().get(0), "foobar");
877 assert_eq!(m.testarrayofstring().unwrap().get(1), "baz");
878
879 let rust_vec_inst = m.testarrayofstring().unwrap();
880 let rust_vec_iter_collect = rust_vec_inst.iter().collect::<Vec<_>>();
881 assert_eq!(rust_vec_iter_collect.len(), 2);
882 assert_eq!(rust_vec_iter_collect[0], "foobar");
883 assert_eq!(rust_vec_iter_collect[1], "baz");
884
885 let rust_vec_iter_rev_collect = rust_vec_inst.iter().rev().collect::<Vec<_>>();
886 assert_eq!(rust_vec_iter_rev_collect.len(), 2);
887 assert_eq!(rust_vec_iter_rev_collect[0], "baz");
888 assert_eq!(rust_vec_iter_rev_collect[1], "foobar");
889 }
890 #[test]
vector_of_ubyte_store()891 fn vector_of_ubyte_store() {
892 let mut b = flatbuffers::FlatBufferBuilder::new();
893 let v = b.create_vector(&[123u8, 234u8][..]);
894 let name = b.create_string("foo");
895 let m = build_mon(&mut b, &my_game::example::MonsterArgs{
896 name: Some(name),
897 inventory: Some(v), ..Default::default()
898 });
899 assert_eq!(m.inventory().unwrap().bytes(), &[123, 234]);
900 }
901 #[test]
vector_of_bool_store()902 fn vector_of_bool_store() {
903 let mut b = flatbuffers::FlatBufferBuilder::new();
904 let v = b.create_vector(&[false, true, false, true][..]);
905 let name = b.create_string("foo");
906 let m = build_mon(&mut b, &my_game::example::MonsterArgs{
907 name: Some(name),
908 testarrayofbools: Some(v), ..Default::default()});
909
910 let rust_vec_inst = m.testarrayofbools().unwrap();
911 let rust_vec_iter_collect = rust_vec_inst.iter().collect::<Vec<_>>();
912 assert_eq!(&rust_vec_iter_collect, &[false, true, false, true]);
913
914 let rust_vec_iter_rev_collect = rust_vec_inst.iter().rev().collect::<Vec<_>>();
915 assert_eq!(&rust_vec_iter_rev_collect, &[true, false, true, false]);
916 }
917 #[test]
vector_of_f64_store()918 fn vector_of_f64_store() {
919 let mut b = flatbuffers::FlatBufferBuilder::new();
920 let v = b.create_vector(&[3.14159265359f64][..]);
921 let name = b.create_string("foo");
922 let m = build_mon(&mut b, &my_game::example::MonsterArgs{
923 name: Some(name),
924 vector_of_doubles: Some(v), ..Default::default()});
925 assert_eq!(m.vector_of_doubles().unwrap().len(), 1);
926 assert_eq!(m.vector_of_doubles().unwrap().get(0), 3.14159265359f64);
927
928 let rust_vec_inst = m.vector_of_doubles().unwrap();
929 let rust_vec_iter_collect = rust_vec_inst.iter().collect::<Vec<_>>();
930 assert_eq!(rust_vec_iter_collect.len(), 1);
931 assert_eq!(rust_vec_iter_collect[0], 3.14159265359f64);
932
933 let rust_vec_iter_rev_collect = rust_vec_inst.iter().rev().collect::<Vec<_>>();
934 assert_eq!(rust_vec_iter_rev_collect.len(), 1);
935 assert_eq!(rust_vec_iter_rev_collect[0], 3.14159265359f64);
936 }
937 #[test]
vector_of_struct_store()938 fn vector_of_struct_store() {
939 let mut b = flatbuffers::FlatBufferBuilder::new();
940 let v = b.create_vector(&[my_game::example::Test::new(127, -128), my_game::example::Test::new(3, 123)][..]);
941 let name = b.create_string("foo");
942 let m = build_mon(&mut b, &my_game::example::MonsterArgs{
943 name: Some(name),
944 test4: Some(v), ..Default::default()});
945
946 let rust_vec_inst = m.test4().unwrap();
947 let rust_vec_iter_collect = rust_vec_inst.iter().collect::<Vec<_>>();
948 assert_eq!(rust_vec_iter_collect, &[&my_game::example::Test::new(127, -128), &my_game::example::Test::new(3, 123)][..]);
949
950 let rust_vec_iter_rev_collect = rust_vec_inst.iter().rev().collect::<Vec<_>>();
951 assert_eq!(rust_vec_iter_rev_collect, &[&my_game::example::Test::new(3, 123), &my_game::example::Test::new(127, -128)][..]);
952 }
953 #[test]
vector_of_struct_store_with_type_inference()954 fn vector_of_struct_store_with_type_inference() {
955 let mut b = flatbuffers::FlatBufferBuilder::new();
956 let v = b.create_vector(&[my_game::example::Test::new(127, -128),
957 my_game::example::Test::new(3, 123),
958 my_game::example::Test::new(100, 101)]);
959 let name = b.create_string("foo");
960 let m = build_mon(&mut b, &my_game::example::MonsterArgs{
961 name: Some(name),
962 test4: Some(v), ..Default::default()});
963 let vals: Vec<_> = m.test4().unwrap().iter().collect::<Vec<_>>();
964 assert_eq!(vals, vec![&my_game::example::Test::new(127, -128), &my_game::example::Test::new(3, 123), &my_game::example::Test::new(100, 101)]);
965 }
966 #[test]
vector_of_enums_store()967 fn vector_of_enums_store() {
968 let mut b = flatbuffers::FlatBufferBuilder::new();
969 let v = b.create_vector::<my_game::example::Color>(&[my_game::example::Color::Red, my_game::example::Color::Green][..]);
970 let name = b.create_string("foo");
971 let m = build_mon(&mut b, &my_game::example::MonsterArgs{
972 name: Some(name),
973 vector_of_enums: Some(v), ..Default::default()});
974 assert_eq!(m.vector_of_enums().unwrap().len(), 2);
975 assert_eq!(m.vector_of_enums().unwrap().get(0), my_game::example::Color::Red);
976 assert_eq!(m.vector_of_enums().unwrap().get(1), my_game::example::Color::Green);
977 }
978 #[test]
vector_of_table_store()979 fn vector_of_table_store() {
980 let b = &mut flatbuffers::FlatBufferBuilder::new();
981 let t0 = {
982 let name = b.create_string("foo");
983 let args = my_game::example::MonsterArgs{hp: 55, name: Some(name), ..Default::default()};
984 my_game::example::Monster::create(b, &args)
985 };
986 let t1 = {
987 let name = b.create_string("bar");
988 let args = my_game::example::MonsterArgs{name: Some(name), ..Default::default()};
989 my_game::example::Monster::create(b, &args)
990 };
991 let v = b.create_vector(&[t0, t1][..]);
992 let name = b.create_string("foo");
993 let m = build_mon(b, &my_game::example::MonsterArgs{
994 name: Some(name),
995 testarrayoftables: Some(v), ..Default::default()});
996 assert_eq!(m.testarrayoftables().unwrap().len(), 2);
997 assert_eq!(m.testarrayoftables().unwrap().get(0).hp(), 55);
998 assert_eq!(m.testarrayoftables().unwrap().get(0).name(), "foo");
999 assert_eq!(m.testarrayoftables().unwrap().get(1).hp(), 100);
1000 assert_eq!(m.testarrayoftables().unwrap().get(1).name(), "bar");
1001
1002 let rust_vec_inst = m.testarrayoftables().unwrap();
1003 let rust_vec_iter_collect = rust_vec_inst.iter().collect::<Vec<_>>();
1004 assert_eq!(rust_vec_iter_collect.len(), 2);
1005 assert_eq!(rust_vec_iter_collect[0].hp(), 55);
1006 assert_eq!(rust_vec_iter_collect[0].name(), "foo");
1007 assert_eq!(rust_vec_iter_collect[1].hp(), 100);
1008 assert_eq!(rust_vec_iter_collect[1].name(), "bar");
1009
1010 let rust_vec_iter_rev_collect = rust_vec_inst.iter().rev().collect::<Vec<_>>();
1011 assert_eq!(rust_vec_iter_rev_collect.len(), 2);
1012 assert_eq!(rust_vec_iter_rev_collect[0].hp(), 100);
1013 assert_eq!(rust_vec_iter_rev_collect[0].name(), "bar");
1014 assert_eq!(rust_vec_iter_rev_collect[1].hp(), 55);
1015 assert_eq!(rust_vec_iter_rev_collect[1].name(), "foo");
1016 }
1017 }
1018
1019 #[cfg(test)]
1020 mod generated_code_alignment_and_padding {
1021 extern crate flatbuffers;
1022 use super::my_game;
1023
1024 #[test]
enum_color_is_1_byte()1025 fn enum_color_is_1_byte() {
1026 assert_eq!(1, ::core::mem::size_of::<my_game::example::Color>());
1027 }
1028
1029 #[test]
union_any_is_1_byte()1030 fn union_any_is_1_byte() {
1031 assert_eq!(1, ::core::mem::size_of::<my_game::example::Any>());
1032 }
1033
1034 #[test]
union_any_is_aligned_to_1()1035 fn union_any_is_aligned_to_1() {
1036 assert_eq!(1, ::core::mem::align_of::<my_game::example::Any>());
1037 }
1038 #[test]
struct_test_is_4_bytes()1039 fn struct_test_is_4_bytes() {
1040 assert_eq!(4, ::core::mem::size_of::<my_game::example::Test>());
1041 }
1042 #[test]
struct_vec3_is_32_bytes()1043 fn struct_vec3_is_32_bytes() {
1044 assert_eq!(32, ::core::mem::size_of::<my_game::example::Vec3>());
1045 }
1046
1047 #[test]
struct_vec3_is_written_with_correct_alignment_in_table()1048 fn struct_vec3_is_written_with_correct_alignment_in_table() {
1049 let b = &mut flatbuffers::FlatBufferBuilder::new();
1050 {
1051 let name = b.create_string("foo");
1052 let mon = my_game::example::Monster::create(b, &my_game::example::MonsterArgs{
1053 name: Some(name),
1054 pos: Some(&my_game::example::Vec3::new(1.0, 2.0, 3.0, 4.0,
1055 my_game::example::Color::Green,
1056 &my_game::example::Test::new(98, 99))),
1057 ..Default::default()});
1058 my_game::example::finish_monster_buffer(b, mon);
1059 }
1060 let buf = b.finished_data();
1061 let mon = my_game::example::root_as_monster(buf).unwrap();
1062 let vec3 = mon.pos().unwrap();
1063
1064 let start_ptr = buf.as_ptr() as usize;
1065 let vec3_ptr = vec3 as *const my_game::example::Vec3 as usize;
1066
1067 assert!(vec3_ptr > start_ptr);
1068 // Vec3 is aligned to 8 wrt the flatbuffer.
1069 assert_eq!((vec3_ptr - start_ptr) % 8, 0);
1070 }
1071
1072 #[test]
struct_ability_is_8_bytes()1073 fn struct_ability_is_8_bytes() {
1074 assert_eq!(8, ::core::mem::size_of::<my_game::example::Ability>());
1075 }
1076
1077 #[test]
struct_ability_is_written_with_correct_alignment_in_table_vector()1078 fn struct_ability_is_written_with_correct_alignment_in_table_vector() {
1079 let b = &mut flatbuffers::FlatBufferBuilder::new();
1080 {
1081 let name = b.create_string("foo");
1082 let v = b.create_vector(&[my_game::example::Ability::new(1, 2),
1083 my_game::example::Ability::new(3, 4),
1084 my_game::example::Ability::new(5, 6)]);
1085 let mon = my_game::example::Monster::create(b, &my_game::example::MonsterArgs{
1086 name: Some(name),
1087 testarrayofsortedstruct: Some(v),
1088 ..Default::default()});
1089 my_game::example::finish_monster_buffer(b, mon);
1090 }
1091 let buf = b.finished_data();
1092 let mon = my_game::example::root_as_monster(buf).unwrap();
1093 let abilities = mon.testarrayofsortedstruct().unwrap();
1094
1095 let start_ptr = buf.as_ptr() as usize;
1096 for a in abilities.iter() {
1097 let a_ptr = a as *const my_game::example::Ability as usize;
1098 assert!(a_ptr > start_ptr);
1099 let aln = ::core::mem::align_of::<my_game::example::Ability>();
1100 assert_eq!((a_ptr - start_ptr) % aln, 0);
1101 }
1102 for a in abilities.iter().rev() {
1103 let a_ptr = a as *const my_game::example::Ability as usize;
1104 assert!(a_ptr > start_ptr);
1105 // Vec3 is aligned to 8 wrt the flatbuffer.
1106 assert_eq!((a_ptr - start_ptr) % 8, 0);
1107 }
1108 }
1109 }
1110
1111 #[cfg(not(miri))]
1112 quickcheck! {
1113 fn struct_of_structs(
1114 a_id: u32,
1115 a_distance: u32,
1116 b_a: i16,
1117 b_b: i8,
1118 c_id: u32,
1119 c_distance: u32
1120 ) -> bool {
1121 use my_game::example::*;
1122 let mut sos = StructOfStructs::default();
1123 let mut a = Ability::default();
1124 a.set_id(a_id);
1125 a.set_distance(a_distance);
1126 let mut b = Test::default();
1127 b.set_a(b_a);
1128 b.set_b(b_b);
1129 let mut c = Ability::default();
1130 c.set_id(c_id);
1131 c.set_distance(c_distance);
1132 sos.set_a(&a);
1133 sos.set_b(&b);
1134 sos.set_c(&c);
1135
1136 sos.a().id() == a_id &&
1137 sos.a().distance() == a_distance &&
1138 sos.b().a() == b_a &&
1139 sos.b().b() == b_b &&
1140 sos.c().id() == c_id &&
1141 sos.c().distance() == c_distance
1142 }
1143 }
1144
1145 #[cfg(not(miri))] // slow.
1146 #[cfg(test)]
1147 mod roundtrip_vectors {
1148
1149 #[cfg(test)]
1150 mod scalar {
1151 extern crate quickcheck;
1152 extern crate flatbuffers;
1153
1154 use alloc::vec::Vec;
1155
1156 const N: u64 = 20;
1157
prop<T>(xs: Vec<T>) where T: for<'a> flatbuffers::Follow<'a, Inner = T> + flatbuffers::EndianScalar + flatbuffers::Push + ::core::fmt::Debug,1158 fn prop<T>(xs: Vec<T>)
1159 where
1160 T: for<'a> flatbuffers::Follow<'a, Inner = T>
1161 + flatbuffers::EndianScalar
1162 + flatbuffers::Push
1163 + ::core::fmt::Debug,
1164 {
1165 use flatbuffers::Follow;
1166
1167 let mut b = flatbuffers::FlatBufferBuilder::new();
1168 b.start_vector::<T>(xs.len());
1169 for i in (0..xs.len()).rev() {
1170 b.push::<T>(xs[i]);
1171 }
1172 let vecend = b.end_vector::<T>(xs.len());
1173 b.finish_minimal(vecend);
1174
1175 let buf = b.finished_data();
1176
1177 let got = unsafe { <flatbuffers::ForwardsUOffset<flatbuffers::Vector<T>>>::follow(&buf[..], 0) };
1178 let mut result_vec: Vec<T> = Vec::with_capacity(got.len());
1179 for i in 0..got.len() {
1180 result_vec.push(got.get(i));
1181 }
1182 assert_eq!(result_vec, xs);
1183
1184 let rust_vec_iter = got.iter().collect::<Vec<T>>();
1185 assert_eq!(rust_vec_iter, xs);
1186
1187 let mut rust_vec_rev_iter = got.iter().rev().collect::<Vec<T>>();
1188 rust_vec_rev_iter.reverse();
1189 assert_eq!(rust_vec_rev_iter, xs);
1190 }
1191
1192 #[test]
easy_u8()1193 fn easy_u8() {
1194 prop::<u8>(vec![]);
1195 prop::<u8>(vec![1u8]);
1196 prop::<u8>(vec![1u8, 2u8]);
1197 prop::<u8>(vec![1u8, 2u8, 3u8]);
1198 prop::<u8>(vec![1u8, 2u8, 3u8, 4u8]);
1199 }
1200
1201 #[test]
fuzz_bool()1202 fn fuzz_bool() { quickcheck::QuickCheck::new().max_tests(N).quickcheck(prop::<bool> as fn(Vec<_>)); }
1203 #[test]
fuzz_u8()1204 fn fuzz_u8() { quickcheck::QuickCheck::new().max_tests(N).quickcheck(prop::<u8> as fn(Vec<_>)); }
1205 #[test]
fuzz_i8()1206 fn fuzz_i8() { quickcheck::QuickCheck::new().max_tests(N).quickcheck(prop::<i8> as fn(Vec<_>)); }
1207 #[test]
fuzz_u16()1208 fn fuzz_u16() { quickcheck::QuickCheck::new().max_tests(N).quickcheck(prop::<u16> as fn(Vec<_>)); }
1209 #[test]
fuzz_i16()1210 fn fuzz_i16() { quickcheck::QuickCheck::new().max_tests(N).quickcheck(prop::<i16> as fn(Vec<_>)); }
1211 #[test]
fuzz_u32()1212 fn fuzz_u32() { quickcheck::QuickCheck::new().max_tests(N).quickcheck(prop::<u32> as fn(Vec<_>)); }
1213 #[test]
fuzz_i32()1214 fn fuzz_i32() { quickcheck::QuickCheck::new().max_tests(N).quickcheck(prop::<i32> as fn(Vec<_>)); }
1215 #[test]
fuzz_u64()1216 fn fuzz_u64() { quickcheck::QuickCheck::new().max_tests(N).quickcheck(prop::<u64> as fn(Vec<_>)); }
1217 #[test]
fuzz_i64()1218 fn fuzz_i64() { quickcheck::QuickCheck::new().max_tests(N).quickcheck(prop::<i64> as fn(Vec<_>)); }
1219 #[test]
fuzz_f32()1220 fn fuzz_f32() { quickcheck::QuickCheck::new().max_tests(N).quickcheck(prop::<f32> as fn(Vec<_>)); }
1221 #[test]
fuzz_f64()1222 fn fuzz_f64() { quickcheck::QuickCheck::new().max_tests(N).quickcheck(prop::<f64> as fn(Vec<_>)); }
1223 }
1224
1225 #[cfg(test)]
1226 mod string_manual_build {
1227 #[cfg(not(miri))] // slow.
1228 extern crate quickcheck;
1229 extern crate flatbuffers;
1230
1231 use alloc::string::String;
1232 use alloc::vec::Vec;
1233
prop(xs: Vec<String>)1234 fn prop(xs: Vec<String>) {
1235 use flatbuffers::Follow;
1236
1237 let mut b = flatbuffers::FlatBufferBuilder::new();
1238 let mut offsets = Vec::new();
1239 for s in xs.iter().rev() {
1240 offsets.push(b.create_string(s.as_str()));
1241 }
1242
1243 b.start_vector::<flatbuffers::WIPOffset<&str>>(xs.len());
1244 for &i in offsets.iter() {
1245 b.push(i);
1246 }
1247 let vecend = b.end_vector::<flatbuffers::WIPOffset<&str>>(xs.len());
1248
1249 b.finish_minimal(vecend);
1250
1251 let buf = b.finished_data();
1252 let got = unsafe { <flatbuffers::ForwardsUOffset<flatbuffers::Vector<flatbuffers::ForwardsUOffset<&str>>>>::follow(buf, 0) };
1253
1254 assert_eq!(got.len(), xs.len());
1255 for i in 0..xs.len() {
1256 assert_eq!(got.get(i), &xs[i][..]);
1257 }
1258 }
1259
1260 #[test]
fuzz()1261 fn fuzz() {
1262 quickcheck::QuickCheck::new().max_tests(20).quickcheck(prop as fn(Vec<_>));
1263 }
1264 }
1265
1266 #[cfg(test)]
1267 mod string_helper_build {
1268 #[cfg(not(miri))] // slow.
1269 extern crate quickcheck;
1270 extern crate flatbuffers;
1271
1272 use alloc::string::String;
1273 use alloc::vec::Vec;
1274
prop(input: Vec<String>)1275 fn prop(input: Vec<String>) {
1276 use flatbuffers::Follow;
1277
1278 let mut b = flatbuffers::FlatBufferBuilder::new();
1279 let xs: Vec<_> = input.iter().map(|s: &String| b.create_string(s)).collect();
1280 let vecend = b.create_vector(&xs);
1281
1282 b.finish_minimal(vecend);
1283
1284 let buf = b.finished_data();
1285 let got = unsafe { <flatbuffers::ForwardsUOffset<flatbuffers::Vector<flatbuffers::ForwardsUOffset<&str>>>>::follow(buf, 0) };
1286
1287 assert_eq!(got.len(), xs.len());
1288 for (idx, s) in input.iter().enumerate() {
1289 assert_eq!(got.get(idx), s);
1290 }
1291 }
1292
1293 #[test]
fuzz()1294 fn fuzz() {
1295 quickcheck::QuickCheck::new().max_tests(100).quickcheck(prop as fn(Vec<_>));
1296 }
1297 }
1298
1299 #[cfg(test)]
1300 mod ubyte {
1301 #[cfg(not(miri))] // slow.
1302 extern crate quickcheck;
1303 extern crate flatbuffers;
1304
1305 use alloc::vec::Vec;
1306
1307 #[cfg(not(miri))] // slow.
1308 #[test]
fuzz_manual_build()1309 fn fuzz_manual_build() {
1310 fn prop(vec: Vec<u8>) {
1311 let xs = &vec[..];
1312
1313 let mut b1 = flatbuffers::FlatBufferBuilder::new();
1314 b1.start_vector::<u8>(xs.len());
1315
1316 for i in (0..xs.len()).rev() {
1317 b1.push(xs[i]);
1318 }
1319 b1.end_vector::<u8>(xs.len());
1320
1321 let mut b2 = flatbuffers::FlatBufferBuilder::new();
1322 b2.create_vector(xs);
1323 assert_eq!(b1.unfinished_data(), b2.unfinished_data());
1324 }
1325 quickcheck::QuickCheck::new().max_tests(100).quickcheck(prop as fn(Vec<_>));
1326 }
1327 }
1328 }
1329
1330 #[cfg(test)]
1331 mod framing_format {
1332 extern crate flatbuffers;
1333
1334 use super::my_game;
1335
1336 #[test]
test_size_prefixed_buffer()1337 fn test_size_prefixed_buffer() {
1338 // Create size prefixed buffer.
1339 let mut b = flatbuffers::FlatBufferBuilder::new();
1340 let args = &my_game::example::MonsterArgs{
1341 mana: 200,
1342 hp: 300,
1343 name: Some(b.create_string("bob")),
1344 ..Default::default()
1345 };
1346 let mon = my_game::example::Monster::create(&mut b, &args);
1347 b.finish_size_prefixed(mon, None);
1348
1349 // Access it.
1350 let buf = b.finished_data();
1351 let m = flatbuffers::size_prefixed_root::<my_game::example::Monster>(buf).unwrap();
1352 assert_eq!(m.mana(), 200);
1353 assert_eq!(m.hp(), 300);
1354 assert_eq!(m.name(), "bob");
1355 }
1356 }
1357
1358 #[cfg(not(feature = "no_std"))]
1359 #[cfg(test)]
1360 mod roundtrip_table {
1361 use alloc::string::String;
1362 use alloc::vec::Vec;
1363 use std::collections::HashMap;
1364
1365 extern crate flatbuffers;
1366 #[cfg(not(miri))] // slow.
1367 extern crate quickcheck;
1368
1369 use super::LCG;
1370
1371 #[test]
1372 #[cfg(not(miri))] // slow.
table_of_mixed_scalars_fuzz()1373 fn table_of_mixed_scalars_fuzz() {
1374 // Values we're testing against: chosen to ensure no bits get chopped
1375 // off anywhere, and also be different from eachother.
1376 let bool_val: bool = true;
1377 let char_val: i8 = -127; // 0x81
1378 let uchar_val: u8 = 0xFF;
1379 let short_val: i16 = -32222; // 0x8222;
1380 let ushort_val: u16 = 0xFEEE;
1381 let int_val: i32 = unsafe { ::core::mem::transmute(0x83333333u32) };
1382 let uint_val: u32 = 0xFDDDDDDD;
1383 let long_val: i64 = unsafe { ::core::mem::transmute(0x8444444444444444u64) }; // TODO: byte literal?
1384 let ulong_val: u64 = 0xFCCCCCCCCCCCCCCCu64;
1385 let float_val: f32 = 3.14159;
1386 let double_val: f64 = 3.14159265359;
1387
1388 let test_value_types_max: isize = 11;
1389 let max_fields_per_object: flatbuffers::VOffsetT = 100;
1390 let num_fuzz_objects: isize = 1000; // The higher, the more thorough :)
1391
1392 let mut builder = flatbuffers::FlatBufferBuilder::new();
1393 let mut lcg = LCG::new();
1394
1395 let mut objects: Vec<flatbuffers::UOffsetT> = vec![0; num_fuzz_objects as usize];
1396
1397 // Generate num_fuzz_objects random objects each consisting of
1398 // fields_per_object fields, each of a random type.
1399 for i in 0..(num_fuzz_objects as usize) {
1400 let fields_per_object = (lcg.next() % (max_fields_per_object as u64)) as flatbuffers::VOffsetT;
1401 let start = builder.start_table();
1402
1403 for j in 0..fields_per_object {
1404 let choice = lcg.next() % (test_value_types_max as u64);
1405
1406 let f = flatbuffers::field_index_to_field_offset(j);
1407
1408 match choice {
1409 0 => {builder.push_slot::<bool>(f, bool_val, false);}
1410 1 => {builder.push_slot::<i8>(f, char_val, 0);}
1411 2 => {builder.push_slot::<u8>(f, uchar_val, 0);}
1412 3 => {builder.push_slot::<i16>(f, short_val, 0);}
1413 4 => {builder.push_slot::<u16>(f, ushort_val, 0);}
1414 5 => {builder.push_slot::<i32>(f, int_val, 0);}
1415 6 => {builder.push_slot::<u32>(f, uint_val, 0);}
1416 7 => {builder.push_slot::<i64>(f, long_val, 0);}
1417 8 => {builder.push_slot::<u64>(f, ulong_val, 0);}
1418 9 => {builder.push_slot::<f32>(f, float_val, 0.0);}
1419 10 => {builder.push_slot::<f64>(f, double_val, 0.0);}
1420 _ => { panic!("unknown choice: {}", choice); }
1421 }
1422 }
1423 objects[i] = builder.end_table(start).value();
1424 }
1425
1426 // Do some bookkeeping to generate stats on fuzzes:
1427 let mut stats: HashMap<u64, u64> = HashMap::new();
1428 let mut values_generated: u64 = 0;
1429
1430 // Embrace PRNG determinism:
1431 lcg.reset();
1432
1433 // Test that all objects we generated are readable and return the
1434 // expected values. We generate random objects in the same order
1435 // so this is deterministic:
1436 for i in 0..(num_fuzz_objects as usize) {
1437 let table = {
1438 let buf = builder.unfinished_data();
1439 let loc = buf.len() as flatbuffers::UOffsetT - objects[i];
1440 unsafe { flatbuffers::Table::new(buf, loc as usize) }
1441 };
1442
1443 let fields_per_object = (lcg.next() % (max_fields_per_object as u64)) as flatbuffers::VOffsetT;
1444 for j in 0..fields_per_object {
1445 let choice = lcg.next() % (test_value_types_max as u64);
1446
1447 *stats.entry(choice).or_insert(0) += 1;
1448 values_generated += 1;
1449
1450 let f = flatbuffers::field_index_to_field_offset(j);
1451
1452 unsafe {
1453 match choice {
1454 0 => { assert_eq!(bool_val, table.get::<bool>(f, Some(false)).unwrap()); }
1455 1 => { assert_eq!(char_val, table.get::<i8>(f, Some(0)).unwrap()); }
1456 2 => { assert_eq!(uchar_val, table.get::<u8>(f, Some(0)).unwrap()); }
1457 3 => { assert_eq!(short_val, table.get::<i16>(f, Some(0)).unwrap()); }
1458 4 => { assert_eq!(ushort_val, table.get::<u16>(f, Some(0)).unwrap()); }
1459 5 => { assert_eq!(int_val, table.get::<i32>(f, Some(0)).unwrap()); }
1460 6 => { assert_eq!(uint_val, table.get::<u32>(f, Some(0)).unwrap()); }
1461 7 => { assert_eq!(long_val, table.get::<i64>(f, Some(0)).unwrap()); }
1462 8 => { assert_eq!(ulong_val, table.get::<u64>(f, Some(0)).unwrap()); }
1463 9 => { assert_eq!(float_val, table.get::<f32>(f, Some(0.0)).unwrap()); }
1464 10 => { assert_eq!(double_val, table.get::<f64>(f, Some(0.0)).unwrap()); }
1465 _ => { panic!("unknown choice: {}", choice); }
1466 }
1467 }
1468 }
1469 }
1470
1471 // Assert that we tested all the fuzz cases enough:
1472 let min_tests_per_choice = 1000;
1473 assert!(values_generated > 0);
1474 assert!(min_tests_per_choice > 0);
1475 for i in 0..test_value_types_max as u64 {
1476 assert!(stats[&i] >= min_tests_per_choice, "inadequately-tested fuzz case: {}", i);
1477 }
1478 }
1479
1480 #[test]
1481 #[cfg(not(miri))] // slow.
table_of_byte_strings_fuzz()1482 fn table_of_byte_strings_fuzz() {
1483 fn prop(vec: Vec<Vec<u8>>) {
1484 use flatbuffers::field_index_to_field_offset as fi2fo;
1485 use flatbuffers::Follow;
1486
1487 let xs = &vec[..];
1488
1489 // build
1490 let mut b = flatbuffers::FlatBufferBuilder::new();
1491 let str_offsets: Vec<flatbuffers::WIPOffset<_>> = xs.iter().map(|s| b.create_byte_string(&s[..])).collect();
1492 let table_start = b.start_table();
1493
1494 for i in 0..xs.len() {
1495 b.push_slot_always(fi2fo(i as flatbuffers::VOffsetT), str_offsets[i]);
1496 }
1497 let root = b.end_table(table_start);
1498 b.finish_minimal(root);
1499
1500 // use
1501 let buf = b.finished_data();
1502 let tab = unsafe { <flatbuffers::ForwardsUOffset<flatbuffers::Table>>::follow(buf, 0) };
1503
1504 for i in 0..xs.len() {
1505 let v = unsafe { tab.get::<flatbuffers::ForwardsUOffset<flatbuffers::Vector<u8>>>(fi2fo(i as flatbuffers::VOffsetT), None) };
1506 assert!(v.is_some());
1507 let v2 = v.unwrap();
1508 assert_eq!(v2.bytes(), &xs[i]);
1509 }
1510 }
1511 prop(vec![vec![1,2,3]]);
1512
1513 let n = 20;
1514 quickcheck::QuickCheck::new().max_tests(n).quickcheck(prop as fn(Vec<_>));
1515 }
1516
1517 #[test]
1518 #[cfg(not(miri))] // slow.
fuzz_table_of_strings()1519 fn fuzz_table_of_strings() {
1520 fn prop(vec: Vec<String>) {
1521 use flatbuffers::field_index_to_field_offset as fi2fo;
1522 use flatbuffers::Follow;
1523
1524 let xs = &vec[..];
1525
1526 // build
1527 let mut b = flatbuffers::FlatBufferBuilder::new();
1528 let str_offsets: Vec<flatbuffers::WIPOffset<_>> = xs.iter().map(|s| b.create_string(&s[..])).collect();
1529 let table_start = b.start_table();
1530
1531 for i in 0..xs.len() {
1532 b.push_slot_always(fi2fo(i as flatbuffers::VOffsetT), str_offsets[i]);
1533 }
1534 let root = b.end_table(table_start);
1535 b.finish_minimal(root);
1536
1537 // use
1538 let buf = b.finished_data();
1539 let tab = unsafe { <flatbuffers::ForwardsUOffset<flatbuffers::Table>>::follow(buf, 0) };
1540
1541 for i in 0..xs.len() {
1542 let v = unsafe { tab.get::<flatbuffers::ForwardsUOffset<&str>>(fi2fo(i as flatbuffers::VOffsetT), None) };
1543 assert_eq!(v, Some(&xs[i][..]));
1544 }
1545 }
1546 let n = 20;
1547 quickcheck::QuickCheck::new().max_tests(n).quickcheck(prop as fn(Vec<String>));
1548 }
1549
1550 #[cfg(not(miri))] // slow.
1551 mod table_of_vectors_of_scalars {
1552
1553 use alloc::vec::Vec;
1554
1555 extern crate flatbuffers;
1556 #[cfg(not(miri))] // slow.
1557 extern crate quickcheck;
1558
1559 const N: u64 = 20;
1560
prop<T>(vecs: Vec<Vec<T>>) where T: for<'a> flatbuffers::Follow<'a, Inner = T> + flatbuffers::EndianScalar + flatbuffers::Push + ::core::fmt::Debug,1561 fn prop<T>(vecs: Vec<Vec<T>>)
1562 where
1563 T: for<'a> flatbuffers::Follow<'a, Inner = T>
1564 + flatbuffers::EndianScalar
1565 + flatbuffers::Push
1566 + ::core::fmt::Debug,
1567 {
1568 use flatbuffers::field_index_to_field_offset as fi2fo;
1569 use flatbuffers::Follow;
1570
1571 // build
1572 let mut b = flatbuffers::FlatBufferBuilder::new();
1573 let mut offs = vec![];
1574 for vec in &vecs {
1575 b.start_vector::<T>(vec.len());
1576
1577 let xs = &vec[..];
1578 for i in (0..xs.len()).rev() {
1579 b.push::<T>(xs[i]);
1580 }
1581 let vecend = b.end_vector::<T>(xs.len());
1582 offs.push(vecend);
1583 }
1584
1585 let table_start = b.start_table();
1586
1587 for i in 0..vecs.len() {
1588 b.push_slot_always(fi2fo(i as flatbuffers::VOffsetT), offs[i]);
1589 }
1590 let root = b.end_table(table_start);
1591 b.finish_minimal(root);
1592
1593 // use
1594 let buf = b.finished_data();
1595 let tab = unsafe { <flatbuffers::ForwardsUOffset<flatbuffers::Table>>::follow(buf, 0) };
1596
1597 for i in 0..vecs.len() {
1598 let got = unsafe { tab.get::<flatbuffers::ForwardsUOffset<flatbuffers::Vector<T>>>(fi2fo(i as flatbuffers::VOffsetT), None) };
1599 assert!(got.is_some());
1600 let got2 = got.unwrap();
1601 let mut got3: Vec<T> = Vec::with_capacity(got2.len());
1602 for i in 0..got2.len() {
1603 got3.push(got2.get(i));
1604 }
1605 assert_eq!(vecs[i], got3);
1606 }
1607 }
1608
1609 #[test]
fuzz_bool()1610 fn fuzz_bool() { quickcheck::QuickCheck::new().max_tests(N).quickcheck(prop as fn(Vec<Vec<bool>>)); }
1611
1612 #[test]
fuzz_u8()1613 fn fuzz_u8() { quickcheck::QuickCheck::new().max_tests(N).quickcheck(prop as fn(Vec<Vec<u8>>)); }
1614 #[test]
fuzz_u16()1615 fn fuzz_u16() { quickcheck::QuickCheck::new().max_tests(N).quickcheck(prop as fn(Vec<Vec<u16>>)); }
1616 #[test]
fuzz_u32()1617 fn fuzz_u32() { quickcheck::QuickCheck::new().max_tests(N).quickcheck(prop as fn(Vec<Vec<u32>>)); }
1618 #[test]
fuzz_u64()1619 fn fuzz_u64() { quickcheck::QuickCheck::new().max_tests(N).quickcheck(prop as fn(Vec<Vec<u64>>)); }
1620
1621 #[test]
fuzz_i8()1622 fn fuzz_i8() { quickcheck::QuickCheck::new().max_tests(N).quickcheck(prop as fn(Vec<Vec<u8>>)); }
1623 #[test]
fuzz_i16()1624 fn fuzz_i16() { quickcheck::QuickCheck::new().max_tests(N).quickcheck(prop as fn(Vec<Vec<u16>>)); }
1625 #[test]
fuzz_i32()1626 fn fuzz_i32() { quickcheck::QuickCheck::new().max_tests(N).quickcheck(prop as fn(Vec<Vec<u32>>)); }
1627 #[test]
fuzz_i64()1628 fn fuzz_i64() { quickcheck::QuickCheck::new().max_tests(N).quickcheck(prop as fn(Vec<Vec<u64>>)); }
1629
1630 #[test]
fuzz_f32()1631 fn fuzz_f32() { quickcheck::QuickCheck::new().max_tests(N).quickcheck(prop as fn(Vec<Vec<f32>>)); }
1632 #[test]
fuzz_f64()1633 fn fuzz_f64() { quickcheck::QuickCheck::new().max_tests(N).quickcheck(prop as fn(Vec<Vec<f64>>)); }
1634 }
1635 }
1636
1637 #[cfg(not(miri))] // slow.
1638 #[cfg(test)]
1639 mod roundtrip_scalars {
1640 extern crate flatbuffers;
1641 #[cfg(not(miri))] // slow.
1642 extern crate quickcheck;
1643
1644 const N: u64 = 1000;
1645
prop<T: PartialEq + ::core::fmt::Debug + Copy + flatbuffers::EndianScalar>(x: T)1646 fn prop<T: PartialEq + ::core::fmt::Debug + Copy + flatbuffers::EndianScalar>(x: T) {
1647 let mut buf = vec![0u8; ::core::mem::size_of::<T>()];
1648 let y = unsafe {
1649 flatbuffers::emplace_scalar(&mut buf[..], x);
1650 flatbuffers::read_scalar(&buf[..])
1651 };
1652 assert_eq!(x, y);
1653 }
1654
1655 #[test]
fuzz_bool()1656 fn fuzz_bool() { quickcheck::QuickCheck::new().max_tests(N).quickcheck(prop::<bool> as fn(_)); }
1657 #[test]
fuzz_u8()1658 fn fuzz_u8() { quickcheck::QuickCheck::new().max_tests(N).quickcheck(prop::<u8> as fn(_)); }
1659 #[test]
fuzz_i8()1660 fn fuzz_i8() { quickcheck::QuickCheck::new().max_tests(N).quickcheck(prop::<i8> as fn(_)); }
1661
1662 #[test]
fuzz_u16()1663 fn fuzz_u16() { quickcheck::QuickCheck::new().max_tests(N).quickcheck(prop::<u16> as fn(_)); }
1664 #[test]
fuzz_i16()1665 fn fuzz_i16() { quickcheck::QuickCheck::new().max_tests(N).quickcheck(prop::<i16> as fn(_)); }
1666
1667 #[test]
fuzz_u32()1668 fn fuzz_u32() { quickcheck::QuickCheck::new().max_tests(N).quickcheck(prop::<u32> as fn(_)); }
1669 #[test]
fuzz_i32()1670 fn fuzz_i32() { quickcheck::QuickCheck::new().max_tests(N).quickcheck(prop::<i32> as fn(_)); }
1671
1672 #[test]
fuzz_u64()1673 fn fuzz_u64() { quickcheck::QuickCheck::new().max_tests(N).quickcheck(prop::<u64> as fn(_)); }
1674 #[test]
fuzz_i64()1675 fn fuzz_i64() { quickcheck::QuickCheck::new().max_tests(N).quickcheck(prop::<i64> as fn(_)); }
1676
1677 #[test]
fuzz_f32()1678 fn fuzz_f32() { quickcheck::QuickCheck::new().max_tests(N).quickcheck(prop::<f32> as fn(_)); }
1679 #[test]
fuzz_f64()1680 fn fuzz_f64() { quickcheck::QuickCheck::new().max_tests(N).quickcheck(prop::<f64> as fn(_)); }
1681 }
1682
1683 #[cfg(test)]
1684 #[cfg(not(miri))] // slow.
1685 mod roundtrip_push_follow_scalars {
1686 extern crate flatbuffers;
1687 #[cfg(not(miri))] // slow.
1688 extern crate quickcheck;
1689
1690 use flatbuffers::Push;
1691
1692 const N: u64 = 1000;
1693
1694 // This uses a macro because lifetimes for a trait-bounded function get too
1695 // complicated.
1696 macro_rules! impl_prop {
1697 ($fn_name:ident, $ty:ident) => (
1698 fn $fn_name(x: $ty) {
1699 let mut buf = vec![0u8; ::core::mem::size_of::<$ty>()];
1700 unsafe { x.push(&mut buf[..], 0) };
1701 let fs: flatbuffers::FollowStart<$ty> = flatbuffers::FollowStart::new();
1702 assert_eq!(unsafe { fs.self_follow(&buf[..], 0) }, x);
1703 }
1704 )
1705 }
1706
1707 impl_prop!(prop_bool, bool);
1708 impl_prop!(prop_u8, u8);
1709 impl_prop!(prop_i8, i8);
1710 impl_prop!(prop_u16, u16);
1711 impl_prop!(prop_i16, i16);
1712 impl_prop!(prop_u32, u32);
1713 impl_prop!(prop_i32, i32);
1714 impl_prop!(prop_u64, u64);
1715 impl_prop!(prop_i64, i64);
1716 impl_prop!(prop_f32, f32);
1717 impl_prop!(prop_f64, f64);
1718
1719 #[test]
fuzz_bool()1720 fn fuzz_bool() { quickcheck::QuickCheck::new().max_tests(N).quickcheck(prop_bool as fn(bool)); }
1721 #[test]
fuzz_u8()1722 fn fuzz_u8() { quickcheck::QuickCheck::new().max_tests(N).quickcheck(prop_u8 as fn(u8)); }
1723 #[test]
fuzz_i8()1724 fn fuzz_i8() { quickcheck::QuickCheck::new().max_tests(N).quickcheck(prop_i8 as fn(i8)); }
1725 #[test]
fuzz_u16()1726 fn fuzz_u16() { quickcheck::QuickCheck::new().max_tests(N).quickcheck(prop_u16 as fn(u16)); }
1727 #[test]
fuzz_i16()1728 fn fuzz_i16() { quickcheck::QuickCheck::new().max_tests(N).quickcheck(prop_i16 as fn(i16)); }
1729 #[test]
fuzz_u32()1730 fn fuzz_u32() { quickcheck::QuickCheck::new().max_tests(N).quickcheck(prop_u32 as fn(u32)); }
1731 #[test]
fuzz_i32()1732 fn fuzz_i32() { quickcheck::QuickCheck::new().max_tests(N).quickcheck(prop_i32 as fn(i32)); }
1733 #[test]
fuzz_u64()1734 fn fuzz_u64() { quickcheck::QuickCheck::new().max_tests(N).quickcheck(prop_u64 as fn(u64)); }
1735 #[test]
fuzz_i64()1736 fn fuzz_i64() { quickcheck::QuickCheck::new().max_tests(N).quickcheck(prop_i64 as fn(i64)); }
1737 #[test]
fuzz_f32()1738 fn fuzz_f32() { quickcheck::QuickCheck::new().max_tests(N).quickcheck(prop_f32 as fn(f32)); }
1739 #[test]
fuzz_f64()1740 fn fuzz_f64() { quickcheck::QuickCheck::new().max_tests(N).quickcheck(prop_f64 as fn(f64)); }
1741 }
1742
1743
1744 #[cfg(test)]
1745 mod write_and_read_examples {
1746 extern crate flatbuffers;
1747
1748 use super::create_serialized_example_with_library_code;
1749 use super::create_serialized_example_with_generated_code;
1750 use super::serialized_example_is_accessible_and_correct;
1751
1752 #[test]
generated_code_creates_correct_example()1753 fn generated_code_creates_correct_example() {
1754 let b = &mut flatbuffers::FlatBufferBuilder::new();
1755 create_serialized_example_with_generated_code(b);
1756 let buf = b.finished_data();
1757 serialized_example_is_accessible_and_correct(&buf[..], true, false).unwrap();
1758 }
1759
1760 #[test]
generated_code_debug_prints_correctly()1761 fn generated_code_debug_prints_correctly() {
1762 let b = &mut flatbuffers::FlatBufferBuilder::new();
1763 create_serialized_example_with_generated_code(b);
1764 let buf = b.finished_data();
1765 serialized_example_is_accessible_and_correct(&buf, true, false).unwrap();
1766 let m = super::my_game::example::root_as_monster(buf).unwrap();
1767 assert_eq!(
1768 format!("{:.5?}", &m),
1769 "Monster { pos: Some(Vec3 { x: 1.00000, y: 2.00000, z: 3.00000, \
1770 test1: 3.00000, test2: Color(Green), test3: Test { a: 5, b: 6 } \
1771 }), mana: 150, hp: 80, name: \"MyMonster\", inventory: Some([0, 1, \
1772 2, 3, 4]), color: Color(Blue), test_type: Monster, test: Monster { \
1773 pos: None, mana: 150, hp: 100, name: \"Fred\", inventory: None, \
1774 color: Color(Blue), test_type: NONE, test: None, test4: None, \
1775 testarrayofstring: None, testarrayoftables: None, enemy: None, \
1776 testnestedflatbuffer: None, testempty: None, testbool: false, \
1777 testhashs32_fnv1: 0, testhashu32_fnv1: 0, testhashs64_fnv1: 0, \
1778 testhashu64_fnv1: 0, testhashs32_fnv1a: 0, testhashu32_fnv1a: 0, \
1779 testhashs64_fnv1a: 0, testhashu64_fnv1a: 0, testarrayofbools: \
1780 None, testf: 3.14159, testf2: 3.00000, testf3: 0.00000, \
1781 testarrayofstring2: None, testarrayofsortedstruct: None, flex: \
1782 None, test5: None, vector_of_longs: None, vector_of_doubles: None, \
1783 parent_namespace_test: None, vector_of_referrables: None, \
1784 single_weak_reference: 0, vector_of_weak_references: None, \
1785 vector_of_strong_referrables: None, co_owning_reference: 0, \
1786 vector_of_co_owning_references: None, non_owning_reference: 0, \
1787 vector_of_non_owning_references: None, any_unique_type: NONE, \
1788 any_unique: None, any_ambiguous_type: NONE, any_ambiguous: None, \
1789 vector_of_enums: None, signed_enum: None, \
1790 testrequirednestedflatbuffer: None, scalar_key_sorted_tables: \
1791 None, native_inline: None, long_enum_non_enum_default: \
1792 LongEnum(0x0), long_enum_normal_default: LongEnum(LongOne), \
1793 nan_default: NaN, inf_default: inf, positive_inf_default: inf, \
1794 infinity_default: inf, positive_infinity_default: inf, \
1795 negative_inf_default: -inf, negative_infinity_default: -inf, \
1796 double_inf_default: inf }, test4: Some([Test { a: 10, b: 20 }, \
1797 Test { a: 30, b: 40 }]), testarrayofstring: Some([\"test1\", \
1798 \"test2\"]), testarrayoftables: None, enemy: None, \
1799 testnestedflatbuffer: None, testempty: None, testbool: false, \
1800 testhashs32_fnv1: 0, testhashu32_fnv1: 0, testhashs64_fnv1: 0, \
1801 testhashu64_fnv1: 0, testhashs32_fnv1a: 0, testhashu32_fnv1a: 0, \
1802 testhashs64_fnv1a: 0, testhashu64_fnv1a: 0, testarrayofbools: \
1803 None, testf: 3.14159, testf2: 3.00000, testf3: 0.00000, \
1804 testarrayofstring2: None, testarrayofsortedstruct: None, flex: \
1805 None, test5: None, vector_of_longs: None, vector_of_doubles: None, \
1806 parent_namespace_test: None, vector_of_referrables: None, \
1807 single_weak_reference: 0, vector_of_weak_references: None, \
1808 vector_of_strong_referrables: None, co_owning_reference: 0, \
1809 vector_of_co_owning_references: None, non_owning_reference: 0, \
1810 vector_of_non_owning_references: None, any_unique_type: NONE, \
1811 any_unique: None, any_ambiguous_type: NONE, any_ambiguous: None, \
1812 vector_of_enums: None, signed_enum: None, \
1813 testrequirednestedflatbuffer: None, scalar_key_sorted_tables: \
1814 None, native_inline: None, long_enum_non_enum_default: \
1815 LongEnum(0x0), long_enum_normal_default: LongEnum(LongOne), \
1816 nan_default: NaN, inf_default: inf, positive_inf_default: inf, \
1817 infinity_default: inf, positive_infinity_default: inf, \
1818 negative_inf_default: -inf, negative_infinity_default: -inf, \
1819 double_inf_default: inf }"
1820 );
1821 }
1822
1823 #[test]
1824 #[cfg(not(miri))] // slow.
generated_code_creates_correct_example_repeatedly_with_reset()1825 fn generated_code_creates_correct_example_repeatedly_with_reset() {
1826 let b = &mut flatbuffers::FlatBufferBuilder::new();
1827 for _ in 0..100 {
1828 create_serialized_example_with_generated_code(b);
1829 {
1830 let buf = b.finished_data();
1831 serialized_example_is_accessible_and_correct(&buf[..], true, false).unwrap();
1832 }
1833 b.reset();
1834 }
1835 }
1836
1837 #[test]
library_code_creates_correct_example()1838 fn library_code_creates_correct_example() {
1839 let b = &mut flatbuffers::FlatBufferBuilder::new();
1840 create_serialized_example_with_library_code(b);
1841 let buf = b.finished_data();
1842 serialized_example_is_accessible_and_correct(&buf[..], true, false).unwrap();
1843 }
1844
1845 #[test]
1846 #[cfg(not(miri))] // slow.
library_code_creates_correct_example_repeatedly_with_reset()1847 fn library_code_creates_correct_example_repeatedly_with_reset() {
1848 let b = &mut flatbuffers::FlatBufferBuilder::new();
1849 for _ in 0..100 {
1850 create_serialized_example_with_library_code(b);
1851 {
1852 let buf = b.finished_data();
1853 serialized_example_is_accessible_and_correct(&buf[..], true, false).unwrap();
1854 }
1855 b.reset();
1856 }
1857 }
1858 }
1859
1860 #[cfg(not(feature = "no_std"))]
1861 #[cfg(test)]
1862 mod read_examples_from_other_language_ports {
1863 extern crate flatbuffers;
1864
1865 use std::println;
1866
1867 use super::load_file;
1868 use super::serialized_example_is_accessible_and_correct;
1869
1870 #[test]
gold_cpp_example_data_is_accessible_and_correct()1871 fn gold_cpp_example_data_is_accessible_and_correct() {
1872 let buf = load_file("../monsterdata_test.mon").expect("missing monsterdata_test.mon");
1873 serialized_example_is_accessible_and_correct(&buf[..], true, false).unwrap();
1874 }
1875 #[test]
java_wire_example_data_is_accessible_and_correct()1876 fn java_wire_example_data_is_accessible_and_correct() {
1877 let buf = load_file("../monsterdata_java_wire.mon");
1878 if buf.is_err() {
1879 println!("skipping java wire test because it is not present");
1880 return;
1881 }
1882 let buf = buf.unwrap();
1883 serialized_example_is_accessible_and_correct(&buf[..], true, false).unwrap();
1884 }
1885 #[test]
java_wire_size_prefixed_example_data_is_accessible_and_correct()1886 fn java_wire_size_prefixed_example_data_is_accessible_and_correct() {
1887 let buf = load_file("../monsterdata_java_wire_sp.mon");
1888 if buf.is_err() {
1889 println!("skipping java wire test because it is not present");
1890 return;
1891 }
1892 let buf = buf.unwrap();
1893 serialized_example_is_accessible_and_correct(&buf[..], true, true).unwrap();
1894 }
1895 }
1896
1897 #[cfg(test)]
1898 mod generated_code_asserts {
1899 extern crate flatbuffers;
1900
1901 use super::my_game;
1902
1903 #[test]
1904 #[should_panic]
monster_builder_fails_when_name_is_missing()1905 fn monster_builder_fails_when_name_is_missing() {
1906 let b = &mut flatbuffers::FlatBufferBuilder::new();
1907 my_game::example::Monster::create(b, &my_game::example::MonsterArgs{..Default::default()});
1908 }
1909 }
1910
1911 #[cfg(test)]
1912 mod generated_key_comparisons {
1913 extern crate flatbuffers;
1914
1915 use super::my_game;
1916
1917 #[test]
struct_ability_key_compare_less_than()1918 fn struct_ability_key_compare_less_than() {
1919 let a = my_game::example::Ability::new(1, 2);
1920 let b = my_game::example::Ability::new(2, 1);
1921 let c = my_game::example::Ability::new(3, 3);
1922
1923 assert_eq!(a.key_compare_less_than(&a), false);
1924 assert_eq!(b.key_compare_less_than(&b), false);
1925 assert_eq!(c.key_compare_less_than(&c), false);
1926
1927 assert_eq!(a.key_compare_less_than(&b), true);
1928 assert_eq!(a.key_compare_less_than(&c), true);
1929
1930 assert_eq!(b.key_compare_less_than(&a), false);
1931 assert_eq!(b.key_compare_less_than(&c), true);
1932
1933 assert_eq!(c.key_compare_less_than(&a), false);
1934 assert_eq!(c.key_compare_less_than(&b), false);
1935 }
1936
1937 #[test]
struct_key_compare_with_value()1938 fn struct_key_compare_with_value() {
1939 let a = my_game::example::Ability::new(1, 2);
1940
1941 assert_eq!(a.key_compare_with_value(0), ::core::cmp::Ordering::Greater);
1942 assert_eq!(a.key_compare_with_value(1), ::core::cmp::Ordering::Equal);
1943 assert_eq!(a.key_compare_with_value(2), ::core::cmp::Ordering::Less);
1944 }
1945
1946 #[test]
struct_key_compare_less_than()1947 fn struct_key_compare_less_than() {
1948 let a = my_game::example::Ability::new(1, 2);
1949 let b = my_game::example::Ability::new(2, 1);
1950 let c = my_game::example::Ability::new(3, 3);
1951
1952 assert_eq!(a.key_compare_less_than(&a), false);
1953 assert_eq!(b.key_compare_less_than(&b), false);
1954 assert_eq!(c.key_compare_less_than(&c), false);
1955
1956 assert_eq!(a.key_compare_less_than(&b), true);
1957 assert_eq!(a.key_compare_less_than(&c), true);
1958
1959 assert_eq!(b.key_compare_less_than(&a), false);
1960 assert_eq!(b.key_compare_less_than(&c), true);
1961
1962 assert_eq!(c.key_compare_less_than(&a), false);
1963 assert_eq!(c.key_compare_less_than(&b), false);
1964 }
1965
1966 #[test]
table_key_compare_with_value()1967 fn table_key_compare_with_value() {
1968 // setup
1969 let builder = &mut flatbuffers::FlatBufferBuilder::new();
1970 super::create_serialized_example_with_library_code(builder);
1971 let buf = builder.finished_data();
1972 let a = my_game::example::root_as_monster(buf).unwrap();
1973
1974 // preconditions
1975 assert_eq!(a.name(), "MyMonster");
1976
1977 assert_eq!(a.key_compare_with_value("AAA"), ::core::cmp::Ordering::Greater);
1978 assert_eq!(a.key_compare_with_value("MyMonster"), ::core::cmp::Ordering::Equal);
1979 assert_eq!(a.key_compare_with_value("ZZZ"), ::core::cmp::Ordering::Less);
1980 }
1981
1982 #[test]
table_key_compare_less_than()1983 fn table_key_compare_less_than() {
1984 // setup
1985 let builder = &mut flatbuffers::FlatBufferBuilder::new();
1986 super::create_serialized_example_with_library_code(builder);
1987 let buf = builder.finished_data();
1988 let a = my_game::example::root_as_monster(buf).unwrap();
1989 let b = a.test_as_monster().unwrap();
1990
1991 // preconditions
1992 assert_eq!(a.name(), "MyMonster");
1993 assert_eq!(b.name(), "Fred");
1994
1995 assert_eq!(a.key_compare_less_than(&a), false);
1996 assert_eq!(a.key_compare_less_than(&b), false);
1997
1998 assert_eq!(b.key_compare_less_than(&a), true);
1999 assert_eq!(b.key_compare_less_than(&b), false);
2000 }
2001 }
2002
2003 #[cfg(test)]
2004 mod included_schema_generated_code {
2005
2006 #[test]
2007 #[allow(unused_imports)]
namespace_test_mod_is_importable()2008 fn namespace_test_mod_is_importable() {
2009 use super::namespace_test_generated::{
2010 namespace_a,
2011 namespace_a::namespace_b,
2012 namespace_c,
2013 };
2014
2015 }
2016 }
2017
2018 #[cfg(test)]
2019 mod builder_asserts {
2020 extern crate flatbuffers;
2021
2022 #[test]
2023 #[should_panic]
end_table_should_panic_when_not_in_table()2024 fn end_table_should_panic_when_not_in_table() {
2025 let mut b = flatbuffers::FlatBufferBuilder::new();
2026 b.end_table(flatbuffers::WIPOffset::new(0));
2027 }
2028
2029 #[test]
2030 #[should_panic]
create_string_should_panic_when_in_table()2031 fn create_string_should_panic_when_in_table() {
2032 let mut b = flatbuffers::FlatBufferBuilder::new();
2033 b.start_table();
2034 b.create_string("foo");
2035 }
2036
2037 #[test]
2038 #[should_panic]
create_byte_string_should_panic_when_in_table()2039 fn create_byte_string_should_panic_when_in_table() {
2040 let mut b = flatbuffers::FlatBufferBuilder::new();
2041 b.start_table();
2042 b.create_byte_string(b"foo");
2043 }
2044
2045 #[test]
2046 #[should_panic]
push_struct_slot_should_panic_when_not_in_table()2047 fn push_struct_slot_should_panic_when_not_in_table() {
2048 #[derive(Copy, Clone, Debug, PartialEq)]
2049 #[repr(C, packed)]
2050 struct foo { }
2051 impl<'b> flatbuffers::Push for &'b foo {
2052 type Output = foo;
2053 unsafe fn push<'a>(&'a self, _dst: &'a mut [u8], _written_len: usize) { }
2054 }
2055 let mut b = flatbuffers::FlatBufferBuilder::new();
2056 b.push_slot_always(0, &foo{});
2057 }
2058
2059 #[test]
2060 #[should_panic]
finished_bytes_should_panic_when_table_is_not_finished()2061 fn finished_bytes_should_panic_when_table_is_not_finished() {
2062 let mut b = flatbuffers::FlatBufferBuilder::new();
2063 b.start_table();
2064 b.finished_data();
2065 }
2066
2067 #[test]
2068 #[should_panic]
required_panics_when_field_not_set()2069 fn required_panics_when_field_not_set() {
2070 let mut b = flatbuffers::FlatBufferBuilder::new();
2071 let start = b.start_table();
2072 let o = b.end_table(start);
2073 b.required(o, 4 /* byte offset to first field */, "test field");
2074 }
2075 }
2076
2077 #[cfg(test)]
2078 mod follow_impls {
2079 extern crate flatbuffers;
2080 use flatbuffers::Follow;
2081 use flatbuffers::field_index_to_field_offset as fi2fo;
2082
2083 use alloc::vec::Vec;
2084
2085 // Define a test struct to use in a few tests. This replicates the work that the code generator
2086 // would normally do when defining a FlatBuffer struct. For reference, compare the following
2087 // `FooStruct` code with the code generated for the `Vec3` struct in
2088 // `../../monster_test/mod.rs`.
2089 use flatbuffers::EndianScalar;
2090 #[derive(Copy, Clone, Debug, PartialEq)]
2091 #[repr(C, packed)]
2092 struct FooStruct {
2093 a: i8,
2094 b: u8,
2095 c: i16,
2096 }
2097 impl FooStruct {
new(_a: i8, _b: u8, _c: i16) -> Self2098 fn new(_a: i8, _b: u8, _c: i16) -> Self {
2099 FooStruct {
2100 a: _a.to_little_endian(),
2101 b: _b.to_little_endian(),
2102 c: _c.to_little_endian(),
2103 }
2104 }
2105 }
2106 impl<'a> flatbuffers::Follow<'a> for FooStruct {
2107 type Inner = &'a FooStruct;
2108 #[inline(always)]
follow(buf: &'a [u8], loc: usize) -> Self::Inner2109 unsafe fn follow(buf: &'a [u8], loc: usize) -> Self::Inner {
2110 <&'a FooStruct>::follow(buf, loc)
2111 }
2112 }
2113 impl<'a> flatbuffers::Follow<'a> for &'a FooStruct {
2114 type Inner = &'a FooStruct;
2115 #[inline(always)]
follow(buf: &'a [u8], loc: usize) -> Self::Inner2116 unsafe fn follow(buf: &'a [u8], loc: usize) -> Self::Inner {
2117 flatbuffers::follow_cast_ref::<FooStruct>(buf, loc)
2118 }
2119 }
2120
2121 #[test]
to_u8()2122 fn to_u8() {
2123 let vec: Vec<u8> = vec![255, 3];
2124 let fs: flatbuffers::FollowStart<u8> = flatbuffers::FollowStart::new();
2125 assert_eq!(unsafe { fs.self_follow(&vec[..], 1) }, 3);
2126 }
2127
2128 #[test]
to_u16()2129 fn to_u16() {
2130 let vec: Vec<u8> = vec![255, 255, 3, 4];
2131 let fs: flatbuffers::FollowStart<u16> = flatbuffers::FollowStart::new();
2132 assert_eq!(unsafe { fs.self_follow(&vec[..], 2) }, 1027);
2133 }
2134
2135 #[test]
to_f32()2136 fn to_f32() {
2137 let vec: Vec<u8> = vec![255, 255, 255, 255, /* start of value */ 208, 15, 73, 64];
2138 let fs: flatbuffers::FollowStart<f32> = flatbuffers::FollowStart::new();
2139 assert_eq!(unsafe { fs.self_follow(&vec[..], 4) }, 3.14159);
2140 }
2141
2142 #[test]
to_string()2143 fn to_string() {
2144 let vec: Vec<u8> = vec![255,255,255,255, 3, 0, 0, 0, 'f' as u8, 'o' as u8, 'o' as u8, 0];
2145 let off: flatbuffers::FollowStart<&str> = flatbuffers::FollowStart::new();
2146 assert_eq!(unsafe { off.self_follow(&vec[..], 4) }, "foo");
2147 }
2148
2149 #[test]
to_byte_slice()2150 fn to_byte_slice() {
2151 let vec: Vec<u8> = vec![255, 255, 255, 255, 4, 0, 0, 0, 1, 2, 3, 4];
2152 let off: flatbuffers::FollowStart<flatbuffers::Vector<u8>> = flatbuffers::FollowStart::new();
2153 assert_eq!(unsafe { off.self_follow(&vec[..], 4).bytes() }, &[1, 2, 3, 4][..]);
2154 }
2155
2156 #[test]
to_vector_of_u16()2157 fn to_vector_of_u16() {
2158 let vec: Vec<u8> = vec![255, 255, 255, 255, 2, 0, 0, 0, 1, 2, 3, 4];
2159 let off: flatbuffers::FollowStart<flatbuffers::Vector<u16>> = flatbuffers::FollowStart::new();
2160 assert_eq!(unsafe { off.self_follow(&vec[..], 4).len() }, 2);
2161 assert_eq!(unsafe { off.self_follow(&vec[..], 4).get(0) }, 513);
2162 assert_eq!(unsafe { off.self_follow(&vec[..], 4).get(1) }, 1027);
2163 }
2164
2165 #[test]
to_struct()2166 fn to_struct() {
2167 let vec: Vec<u8> = vec![255, 255, 255, 255, 1, 2, 3, 4];
2168 let off: flatbuffers::FollowStart<&FooStruct> = flatbuffers::FollowStart::new();
2169 assert_eq!(unsafe { *off.self_follow(&vec[..], 4) }, FooStruct::new(1, 2, 1027));
2170 }
2171
2172 #[test]
to_vector_of_offset_to_string_elements()2173 fn to_vector_of_offset_to_string_elements() {
2174 let buf: Vec<u8> = vec![/* vec len */ 1, 0, 0, 0, /* offset to string */ 4, 0, 0, 0, /* str length */ 3, 0, 0, 0, 'f' as u8, 'o' as u8, 'o' as u8, 0];
2175 let s: flatbuffers::FollowStart<flatbuffers::Vector<flatbuffers::ForwardsUOffset<&str>>> = flatbuffers::FollowStart::new();
2176 assert_eq!(unsafe {s.self_follow(&buf[..], 0).len() }, 1);
2177 assert_eq!(unsafe { s.self_follow(&buf[..], 0).get(0) }, "foo");
2178 }
2179
2180 #[test]
to_vector_of_struct_elements()2181 fn to_vector_of_struct_elements() {
2182 let buf: Vec<u8> = vec![1, 0, 0, 0, /* struct data */ 1, 2, 3, 4];
2183 let fs: flatbuffers::FollowStart<flatbuffers::Vector<FooStruct>> = flatbuffers::FollowStart::new();
2184 assert_eq!(unsafe { fs.self_follow(&buf[..], 0).len() }, 1);
2185 assert_eq!(unsafe { fs.self_follow(&buf[..], 0).get(0) }, &FooStruct::new(1, 2, 1027));
2186 }
2187
2188 #[test]
to_root_to_empty_table()2189 fn to_root_to_empty_table() {
2190 let buf: Vec<u8> = vec![
2191 12, 0, 0, 0, // offset to root table
2192 // enter vtable
2193 4, 0, // vtable len
2194 0, 0, // inline size
2195 255, 255, 255, 255, // canary
2196 // enter table
2197 8, 0, 0, 0, // vtable location
2198 ];
2199 unsafe {
2200 let fs: flatbuffers::FollowStart<flatbuffers::ForwardsUOffset<flatbuffers::Table>> = flatbuffers::FollowStart::new();
2201 assert_eq!(fs.self_follow(&buf[..], 0), flatbuffers::Table::new(&buf[..], 12));
2202 }
2203 }
2204
2205 #[test]
to_root_table_get_slot_scalar_u8()2206 fn to_root_table_get_slot_scalar_u8() {
2207 let buf: Vec<u8> = vec![
2208 14, 0, 0, 0, // offset to root table
2209 // enter vtable
2210 6, 0, // vtable len
2211 2, 0, // inline size
2212 5, 0, // value loc
2213 255, 255, 255, 255, // canary
2214 // enter table
2215 10, 0, 0, 0, // vtable location
2216 0, 99 // value (with padding)
2217 ];
2218 unsafe {
2219 let fs: flatbuffers::FollowStart<flatbuffers::ForwardsUOffset<flatbuffers::Table>> = flatbuffers::FollowStart::new();
2220 let tab = fs.self_follow(&buf[..], 0);
2221 assert_eq!(tab.get::<u8>(fi2fo(0), Some(123)), Some(99));
2222 }
2223 }
2224
2225 #[test]
to_root_to_table_get_slot_scalar_u8_default_via_vtable_len()2226 fn to_root_to_table_get_slot_scalar_u8_default_via_vtable_len() {
2227 let buf: Vec<u8> = vec![
2228 12, 0, 0, 0, // offset to root table
2229 // enter vtable
2230 4, 0, // vtable len
2231 2, 0, // inline size
2232 255, 255, 255, 255, // canary
2233 // enter table
2234 8, 0, 0, 0, // vtable location
2235 ];
2236 unsafe {
2237 let fs: flatbuffers::FollowStart<flatbuffers::ForwardsUOffset<flatbuffers::Table>> = flatbuffers::FollowStart::new();
2238 let tab = fs.self_follow(&buf[..], 0);
2239 assert_eq!(tab.get::<u8>(fi2fo(0), Some(123)), Some(123));
2240 }
2241 }
2242
2243 #[test]
to_root_to_table_get_slot_scalar_u8_default_via_vtable_zero()2244 fn to_root_to_table_get_slot_scalar_u8_default_via_vtable_zero() {
2245 let buf: Vec<u8> = vec![
2246 14, 0, 0, 0, // offset to root table
2247 // enter vtable
2248 6, 0, // vtable len
2249 2, 0, // inline size
2250 0, 0, // zero means use the default value
2251 255, 255, 255, 255, // canary
2252 // enter table
2253 10, 0, 0, 0, // vtable location
2254 ];
2255 unsafe {
2256 let fs: flatbuffers::FollowStart<flatbuffers::ForwardsUOffset<flatbuffers::Table>> = flatbuffers::FollowStart::new();
2257 let tab = fs.self_follow(&buf[..], 0);
2258 assert_eq!(tab.get::<u8>(fi2fo(0), Some(123)), Some(123));
2259 }
2260 }
2261
2262 #[test]
to_root_to_table_get_slot_string_multiple_types()2263 fn to_root_to_table_get_slot_string_multiple_types() {
2264 let buf: Vec<u8> = vec![
2265 14, 0, 0, 0, // offset to root table
2266 // enter vtable
2267 6, 0, // vtable len
2268 2, 0, // inline size
2269 4, 0, // value loc
2270 255, 255, 255, 255, // canary
2271 // enter table
2272 10, 0, 0, 0, // vtable location
2273 8, 0, 0, 0, // offset to string
2274 // leave table
2275 255, 255, 255, 255, // canary
2276 // enter string
2277 3, 0, 0, 0, 109, 111, 111, 0 // string length and contents
2278 ];
2279 unsafe {
2280 let tab = <flatbuffers::ForwardsUOffset<flatbuffers::Table>>::follow(&buf[..], 0);
2281 assert_eq!(tab.get::<flatbuffers::ForwardsUOffset<&str>>(fi2fo(0), None), Some("moo"));
2282 let byte_vec = tab.get::<flatbuffers::ForwardsUOffset<flatbuffers::Vector<u8>>>(fi2fo(0), None).unwrap().bytes();
2283 assert_eq!(byte_vec, &vec![109, 111, 111][..]);
2284 let v = tab.get::<flatbuffers::ForwardsUOffset<flatbuffers::Vector<u8>>>(fi2fo(0), None).unwrap();
2285 assert_eq!(v.len(), 3);
2286 assert_eq!(v.get(0), 109);
2287 assert_eq!(v.get(1), 111);
2288 assert_eq!(v.get(2), 111);
2289 }
2290 }
2291
2292 #[test]
to_root_to_table_get_slot_string_multiple_types_default_via_vtable_len()2293 fn to_root_to_table_get_slot_string_multiple_types_default_via_vtable_len() {
2294 let buf: Vec<u8> = vec![
2295 12, 0, 0, 0, // offset to root table
2296 // enter vtable
2297 4, 0, // vtable len
2298 4, 0, // table inline len
2299 255, 255, 255, 255, // canary
2300 // enter table
2301 8, 0, 0, 0, // vtable location
2302 ];
2303
2304 unsafe {
2305 let tab = <flatbuffers::ForwardsUOffset<flatbuffers::Table>>::follow(&buf[..], 0);
2306 assert_eq!(tab.get::<flatbuffers::ForwardsUOffset<&str>>(fi2fo(0), Some("abc")), Some("abc"));
2307 #[cfg(target_endian = "little")]
2308 {
2309 assert_eq!(tab.get::<flatbuffers::ForwardsUOffset<&[u8]>>(fi2fo(0), Some(&vec![70, 71, 72][..])), Some(&vec![70, 71, 72][..]));
2310 }
2311
2312 let default_vec_buf: Vec<u8> = vec![3, 0, 0, 0, 70, 71, 72, 0];
2313 let default_vec = flatbuffers::Vector::new(&default_vec_buf[..], 0);
2314 let v = tab.get::<flatbuffers::ForwardsUOffset<flatbuffers::Vector<u8>>>(fi2fo(0), Some(default_vec)).unwrap();
2315 assert_eq!(v.len(), 3);
2316 assert_eq!(v.get(0), 70);
2317 assert_eq!(v.get(1), 71);
2318 assert_eq!(v.get(2), 72);
2319 }
2320 }
2321
2322 #[test]
to_root_to_table_get_slot_string_multiple_types_default_via_vtable_zero()2323 fn to_root_to_table_get_slot_string_multiple_types_default_via_vtable_zero() {
2324 let buf: Vec<u8> = vec![
2325 14, 0, 0, 0, // offset to root table
2326 // enter vtable
2327 6, 0, // vtable len
2328 2, 0, // inline size
2329 0, 0, // value loc
2330 255, 255, 255, 255, // canary
2331 // enter table
2332 10, 0, 0, 0, // vtable location
2333 ];
2334 unsafe {
2335 let tab = <flatbuffers::ForwardsUOffset<flatbuffers::Table>>::follow(&buf[..], 0);
2336 assert_eq!(tab.get::<flatbuffers::ForwardsUOffset<&str>>(fi2fo(0), Some("abc")), Some("abc"));
2337 #[cfg(target_endian = "little")]
2338 {
2339 assert_eq!(tab.get::<flatbuffers::ForwardsUOffset<&[u8]>>(fi2fo(0), Some(&vec![70, 71, 72][..])), Some(&vec![70, 71, 72][..]));
2340 }
2341
2342 let default_vec_buf: Vec<u8> = vec![3, 0, 0, 0, 70, 71, 72, 0];
2343 let default_vec = flatbuffers::Vector::new(&default_vec_buf[..], 0);
2344 let v = tab.get::<flatbuffers::ForwardsUOffset<flatbuffers::Vector<u8>>>(fi2fo(0), Some(default_vec)).unwrap();
2345 assert_eq!(v.len(), 3);
2346 assert_eq!(v.get(0), 70);
2347 assert_eq!(v.get(1), 71);
2348 assert_eq!(v.get(2), 72);
2349 }
2350 }
2351 }
2352
2353 #[cfg(test)]
2354 mod push_impls {
2355 extern crate flatbuffers;
2356
2357 use super::my_game;
2358
check<'a>(b: &'a flatbuffers::FlatBufferBuilder, want: &'a [u8])2359 fn check<'a>(b: &'a flatbuffers::FlatBufferBuilder, want: &'a [u8]) {
2360 let got = b.unfinished_data();
2361 assert_eq!(want, got);
2362 }
2363
2364 #[test]
push_u8()2365 fn push_u8() {
2366 let mut b = flatbuffers::FlatBufferBuilder::new();
2367 b.push(123u8);
2368 check(&b, &[123]);
2369 }
2370
2371 #[test]
push_u64()2372 fn push_u64() {
2373 let mut b = flatbuffers::FlatBufferBuilder::new();
2374 b.push(0x12345678);
2375 check(&b, &[0x78, 0x56, 0x34, 0x12]);
2376 }
2377
2378 #[test]
push_f64()2379 fn push_f64() {
2380 let mut b = flatbuffers::FlatBufferBuilder::new();
2381 b.push(3.14159265359f64);
2382 check(&b, &[234, 46, 68, 84, 251, 33, 9, 64]);
2383 }
2384
2385 #[test]
push_generated_struct()2386 fn push_generated_struct() {
2387 let mut b = flatbuffers::FlatBufferBuilder::new();
2388 b.push(my_game::example::Test::new(10, 20));
2389 check(&b, &[10, 0, 20, 0]);
2390 }
2391
2392 #[test]
push_u8_vector_with_offset_with_alignment()2393 fn push_u8_vector_with_offset_with_alignment() {
2394 let mut b = flatbuffers::FlatBufferBuilder::new();
2395 let off = b.create_vector(&[1u8, 2, 3, 4, 5, 6, 7, 8, 9][..]);
2396 b.push(off);
2397 check(&b, &[/* loc */ 4, 0, 0, 0, /* len */ 9, 0, 0, 0, /* val */ 1, 2, 3, 4, 5, 6, 7, 8, 9, /* padding */ 0, 0, 0]);
2398 }
2399
2400 #[test]
push_u8_u16_alignment()2401 fn push_u8_u16_alignment() {
2402 let mut b = flatbuffers::FlatBufferBuilder::new();
2403 b.push(1u8);
2404 b.push(2u16);
2405 check(&b, &[2, 0, 0, 1]);
2406 }
2407
2408 #[test]
push_u8_u32_alignment()2409 fn push_u8_u32_alignment() {
2410 let mut b = flatbuffers::FlatBufferBuilder::new();
2411 b.push(1u8);
2412 b.push(2u32);
2413 check(&b, &[2, 0, 0, 0, 0, 0, 0, 1]);
2414 }
2415
2416 #[test]
push_u8_u64_alignment()2417 fn push_u8_u64_alignment() {
2418 let mut b = flatbuffers::FlatBufferBuilder::new();
2419 b.push(1u8);
2420 b.push(2u64);
2421 check(&b, &[2, 0, 0, 0,
2422 0, 0, 0, 0,
2423 0, 0, 0, 0,
2424 0, 0, 0, 1]);
2425 }
2426
2427 #[test]
push_u8_generated_struct_alignment()2428 fn push_u8_generated_struct_alignment() {
2429 let mut b = flatbuffers::FlatBufferBuilder::new();
2430 b.push(1u8);
2431 b.push(my_game::example::Test::new(10, 20));
2432 check(&b, &[10, 0, 20, 0, 0, 1]);
2433 }
2434 }
2435
2436 #[cfg(test)]
2437 mod vtable_deduplication {
2438 extern crate flatbuffers;
2439 use flatbuffers::field_index_to_field_offset as fi2fo;
2440
check<'a>(b: &'a flatbuffers::FlatBufferBuilder, want: &'a [u8])2441 fn check<'a>(b: &'a flatbuffers::FlatBufferBuilder, want: &'a [u8]) {
2442 let got = b.unfinished_data();
2443 assert_eq!(want, got);
2444 }
2445
2446 #[test]
one_empty_table()2447 fn one_empty_table() {
2448 let mut b = flatbuffers::FlatBufferBuilder::new();
2449 let start0 = b.start_table();
2450 b.end_table(start0);
2451 check(&b, &[
2452 4, 0, // vtable size in bytes
2453 4, 0, // object inline data in bytes
2454
2455 4, 0, 0, 0, // backwards offset to vtable
2456 ]);
2457 }
2458
2459 #[test]
two_empty_tables_are_deduplicated()2460 fn two_empty_tables_are_deduplicated() {
2461 let mut b = flatbuffers::FlatBufferBuilder::new();
2462 let start0 = b.start_table();
2463 b.end_table(start0);
2464 let start1 = b.start_table();
2465 b.end_table(start1);
2466 check(&b, &[
2467 252, 255, 255, 255, // forwards offset to vtable
2468
2469 4, 0, // vtable size in bytes
2470 4, 0, // object inline data in bytes
2471
2472 4, 0, 0, 0, // backwards offset to vtable
2473 ]);
2474 }
2475
2476 #[test]
two_tables_with_two_conveniently_sized_inline_elements_are_deduplicated()2477 fn two_tables_with_two_conveniently_sized_inline_elements_are_deduplicated() {
2478 let mut b = flatbuffers::FlatBufferBuilder::new();
2479 let start0 = b.start_table();
2480 b.push_slot::<u64>(fi2fo(0), 100, 0);
2481 b.push_slot::<u32>(fi2fo(1), 101, 0);
2482 b.end_table(start0);
2483 let start1 = b.start_table();
2484 b.push_slot::<u64>(fi2fo(0), 200, 0);
2485 b.push_slot::<u32>(fi2fo(1), 201, 0);
2486 b.end_table(start1);
2487 check(&b, &[
2488 240, 255, 255, 255, // forwards offset to vtable
2489
2490 201, 0, 0, 0, // value #1
2491 200, 0, 0, 0, 0, 0, 0, 0, // value #0
2492
2493 8, 0, // vtable size in bytes
2494 16, 0, // object inline data in bytes
2495 8, 0, // offset in object for value #0
2496 4, 0, // offset in object for value #1
2497
2498 8, 0, 0, 0, // backwards offset to vtable
2499 101, 0, 0, 0, // value #1
2500 100, 0, 0, 0, 0, 0, 0, 0 // value #0
2501 ]);
2502 }
2503
2504 #[cfg(not(miri))] // slow.
2505 #[test]
many_identical_tables_use_few_vtables()2506 fn many_identical_tables_use_few_vtables() {
2507 let mut b = flatbuffers::FlatBufferBuilder::new();
2508 for _ in 0..1000 {
2509 let start = b.start_table();
2510 b.push_slot::<u8>(fi2fo(0), 100, 0);
2511 b.push_slot::<u32>(fi2fo(1), 101, 0);
2512 b.end_table(start);
2513 }
2514 assert!(b.num_written_vtables() <= 10);
2515 }
2516 }
2517
2518 #[cfg(test)]
2519 mod byte_layouts {
2520 extern crate flatbuffers;
2521 use flatbuffers::field_index_to_field_offset as fi2fo;
2522
check<'a>(b: &'a flatbuffers::FlatBufferBuilder, want: &'a [u8])2523 fn check<'a>(b: &'a flatbuffers::FlatBufferBuilder, want: &'a [u8]) {
2524 let got = b.unfinished_data();
2525 assert_eq!(want, got);
2526 }
2527
2528 #[test]
layout_01_basic_numbers()2529 fn layout_01_basic_numbers() {
2530 let mut b = flatbuffers::FlatBufferBuilder::new();
2531 b.push(true);
2532 check(&b, &[1]);
2533 b.push(-127i8);
2534 check(&b, &[129, 1]);
2535 b.push(255u8);
2536 check(&b, &[255, 129, 1]);
2537 b.push(-32222i16);
2538 check(&b, &[0x22, 0x82, 0, 255, 129, 1]); // first pad
2539 b.push(0xFEEEu16);
2540 check(&b, &[0xEE, 0xFE, 0x22, 0x82, 0, 255, 129, 1]); // no pad this time
2541 b.push(-53687092i32);
2542 check(&b, &[204, 204, 204, 252, 0xEE, 0xFE, 0x22, 0x82, 0, 255, 129, 1]);
2543 b.push(0x98765432u32);
2544 check(&b, &[0x32, 0x54, 0x76, 0x98, 204, 204, 204, 252, 0xEE, 0xFE, 0x22, 0x82, 0, 255, 129, 1]);
2545 }
2546
2547 #[test]
layout_01b_bigger_numbers()2548 fn layout_01b_bigger_numbers() {
2549 let mut b = flatbuffers::FlatBufferBuilder::new();
2550 b.push(0x1122334455667788u64);
2551 check(&b, &[0x88, 0x77, 0x66, 0x55, 0x44, 0x33, 0x22, 0x11]);
2552 }
2553
2554 #[test]
layout_02_1xbyte_vector()2555 fn layout_02_1xbyte_vector() {
2556 let mut b = flatbuffers::FlatBufferBuilder::new();
2557 check(&b, &[]);
2558 b.start_vector::<u8>(1);
2559 check(&b, &[0, 0, 0]); // align to 4bytes
2560 b.push(1u8);
2561 check(&b, &[1, 0, 0, 0]);
2562 b.end_vector::<u8>(1);
2563 check(&b, &[1, 0, 0, 0, 1, 0, 0, 0]); // padding
2564 }
2565
2566 #[test]
layout_03_2xbyte_vector()2567 fn layout_03_2xbyte_vector() {
2568 let mut b = flatbuffers::FlatBufferBuilder::new();
2569 b.start_vector::<u8>(2);
2570 check(&b, &[0, 0]); // align to 4bytes
2571 b.push(1u8);
2572 check(&b, &[1, 0, 0]);
2573 b.push(2u8);
2574 check(&b, &[2, 1, 0, 0]);
2575 b.end_vector::<u8>(2);
2576 check(&b, &[2, 0, 0, 0, 2, 1, 0, 0]); // padding
2577 }
2578
2579 #[test]
layout_03b_11xbyte_vector_matches_builder_size()2580 fn layout_03b_11xbyte_vector_matches_builder_size() {
2581 let mut b = flatbuffers::FlatBufferBuilder::with_capacity(12);
2582 b.start_vector::<u8>(8);
2583
2584 let mut gold = vec![0u8; 0];
2585 check(&b, &gold[..]);
2586
2587 for i in 1u8..=8 {
2588 b.push(i);
2589 gold.insert(0, i);
2590 check(&b, &gold[..]);
2591 }
2592 b.end_vector::<u8>(8);
2593 let want = vec![8u8, 0, 0, 0, 8, 7, 6, 5, 4, 3, 2, 1];
2594 check(&b, &want[..]);
2595 }
2596 #[test]
layout_04_1xuint16_vector()2597 fn layout_04_1xuint16_vector() {
2598 let mut b = flatbuffers::FlatBufferBuilder::new();
2599 b.start_vector::<u16>(1);
2600 check(&b, &[0, 0]); // align to 4bytes
2601 b.push(1u16);
2602 check(&b, &[1, 0, 0, 0]);
2603 b.end_vector::<u16>(1);
2604 check(&b, &[1, 0, 0, 0, 1, 0, 0, 0]); // padding
2605 }
2606
2607 #[test]
layout_05_2xuint16_vector()2608 fn layout_05_2xuint16_vector() {
2609 let mut b = flatbuffers::FlatBufferBuilder::new();
2610 let _off = b.start_vector::<u16>(2);
2611 check(&b, &[]); // align to 4bytes
2612 b.push(0xABCDu16);
2613 check(&b, &[0xCD, 0xAB]);
2614 b.push(0xDCBAu16);
2615 check(&b, &[0xBA, 0xDC, 0xCD, 0xAB]);
2616 b.end_vector::<u16>(2);
2617 check(&b, &[2, 0, 0, 0, 0xBA, 0xDC, 0xCD, 0xAB]);
2618 }
2619
2620 #[test]
layout_06_create_string()2621 fn layout_06_create_string() {
2622 let mut b = flatbuffers::FlatBufferBuilder::new();
2623 let off0 = b.create_string("foo");
2624 assert_eq!(8, off0.value());
2625 check(&b, b"\x03\x00\x00\x00foo\x00"); // 0-terminated, no pad
2626 let off1 = b.create_string("moop");
2627 assert_eq!(20, off1.value());
2628 check(&b, b"\x04\x00\x00\x00moop\x00\x00\x00\x00\
2629 \x03\x00\x00\x00foo\x00"); // 0-terminated, 3-byte pad
2630 }
2631
2632 #[test]
layout_06b_create_string_unicode()2633 fn layout_06b_create_string_unicode() {
2634 let mut b = flatbuffers::FlatBufferBuilder::new();
2635 // These characters are chinese from blog.golang.org/strings
2636 // We use escape codes here so that editors without unicode support
2637 // aren't bothered:
2638 let uni_str = "\u{65e5}\u{672c}\u{8a9e}";
2639 let off0 = b.create_string(uni_str);
2640 assert_eq!(16, off0.value());
2641 check(&b, &[9, 0, 0, 0, 230, 151, 165, 230, 156, 172, 232, 170, 158, 0, // null-terminated, 2-byte pad
2642 0, 0]);
2643 }
2644
2645 #[test]
layout_06c_create_byte_string()2646 fn layout_06c_create_byte_string() {
2647 let mut b = flatbuffers::FlatBufferBuilder::new();
2648 let off0 = b.create_byte_string(b"foo");
2649 assert_eq!(8, off0.value());
2650 check(&b, b"\x03\x00\x00\x00foo\x00"); // 0-terminated, no pad
2651 let off1 = b.create_byte_string(b"moop");
2652 assert_eq!(20, off1.value());
2653 check(&b, b"\x04\x00\x00\x00moop\x00\x00\x00\x00\
2654 \x03\x00\x00\x00foo\x00"); // 0-terminated, 3-byte pad
2655 }
2656
2657 #[test]
layout_07_empty_vtable()2658 fn layout_07_empty_vtable() {
2659 let mut b = flatbuffers::FlatBufferBuilder::new();
2660 let off0 = b.start_table();
2661 check(&b, &[]);
2662 b.end_table(off0);
2663 check(&b, &[4, 0, // vtable length
2664 4, 0, // length of table including vtable offset
2665 4, 0, 0, 0]); // offset for start of vtable
2666 }
2667
2668 #[test]
layout_08_vtable_with_one_true_bool()2669 fn layout_08_vtable_with_one_true_bool() {
2670 let mut b = flatbuffers::FlatBufferBuilder::new();
2671 check(&b, &[]);
2672 let off0 = b.start_table();
2673 assert_eq!(0, off0.value());
2674 check(&b, &[]);
2675 b.push_slot(fi2fo(0), true, false);
2676 check(&b, &[1]);
2677 let off1 = b.end_table(off0);
2678 assert_eq!(8, off1.value());
2679 check(&b, &[
2680 6, 0, // vtable bytes
2681 8, 0, // length of object including vtable offset
2682 7, 0, // start of bool value
2683 6, 0, 0, 0, // offset for start of vtable (int32)
2684 0, 0, 0, // padded to 4 bytes
2685 1, // bool value
2686 ]);
2687 }
2688
2689 #[test]
layout_09_vtable_with_one_default_bool()2690 fn layout_09_vtable_with_one_default_bool() {
2691 let mut b = flatbuffers::FlatBufferBuilder::new();
2692 check(&b, &[]);
2693 let off = b.start_table();
2694 check(&b, &[]);
2695 b.push_slot(fi2fo(0), false, false);
2696 b.end_table(off);
2697 check(&b, &[
2698 4, 0, // vtable bytes
2699 4, 0, // end of object from here
2700 // entry 1 is zero and not stored.
2701 4, 0, 0, 0, // offset for start of vtable (int32)
2702 ]);
2703 }
2704
2705 #[test]
layout_09b_vtable_with_one_default_bool_force_defaults()2706 fn layout_09b_vtable_with_one_default_bool_force_defaults() {
2707 let mut b = flatbuffers::FlatBufferBuilder::new();
2708 check(&b, &[]);
2709 let off = b.start_table();
2710 check(&b, &[]);
2711 b.force_defaults(true);
2712 b.push_slot(fi2fo(0), false, false);
2713 b.end_table(off);
2714 check(&b, &[
2715 6, 0, // vtable bytes
2716 8, 0, // length of object including vtable offset
2717 7, 0, // start of bool value
2718 6, 0, 0, 0, // offset for start of vtable (int32)
2719 0, 0, 0, // padded to 4 bytes
2720 0, // bool value
2721 ]);
2722 }
2723
2724 #[test]
layout_10_vtable_with_one_int16()2725 fn layout_10_vtable_with_one_int16() {
2726 let mut b = flatbuffers::FlatBufferBuilder::new();
2727 check(&b, &[]);
2728 let off = b.start_table();
2729 b.push_slot(fi2fo(0), 0x789Ai16, 0);
2730 b.end_table(off);
2731 check(&b, &[
2732 6, 0, // vtable bytes
2733 8, 0, // end of object from here
2734 6, 0, // offset to value
2735 6, 0, 0, 0, // offset for start of vtable (int32)
2736 0, 0, // padding to 4 bytes
2737 0x9A, 0x78,
2738 ]);
2739 }
2740
2741 #[test]
layout_11_vtable_with_two_int16()2742 fn layout_11_vtable_with_two_int16() {
2743 let mut b = flatbuffers::FlatBufferBuilder::new();
2744 let off = b.start_table();
2745 b.push_slot(fi2fo(0), 0x3456i16, 0);
2746 b.push_slot(fi2fo(1), 0x789Ai16, 0);
2747 b.end_table(off);
2748 check(&b, &[
2749 8, 0, // vtable bytes
2750 8, 0, // end of object from here
2751 6, 0, // offset to value 0
2752 4, 0, // offset to value 1
2753 8, 0, 0, 0, // offset for start of vtable (int32)
2754 0x9A, 0x78, // value 1
2755 0x56, 0x34, // value 0
2756 ]);
2757 }
2758
2759 #[test]
layout_12_vtable_with_int16_and_bool()2760 fn layout_12_vtable_with_int16_and_bool() {
2761 let mut b = flatbuffers::FlatBufferBuilder::new();
2762 let off = b.start_table();
2763 b.push_slot(fi2fo(0), 0x3456i16, 0);
2764 b.push_slot(fi2fo(1), true, false);
2765 b.end_table(off);
2766 check(&b, &[
2767 8, 0, // vtable bytes
2768 8, 0, // end of object from here
2769 6, 0, // offset to value 0
2770 5, 0, // offset to value 1
2771 8, 0, 0, 0, // offset for start of vtable (int32)
2772 0, // padding
2773 1, // value 1
2774 0x56, 0x34, // value 0
2775 ]);
2776 }
2777
2778 #[test]
layout_12b_vtable_with_empty_vector()2779 fn layout_12b_vtable_with_empty_vector() {
2780 let mut b = flatbuffers::FlatBufferBuilder::new();
2781 b.start_vector::<u8>(0);
2782 let vecend = b.end_vector::<u8>(0);
2783 let off = b.start_table();
2784 b.push_slot_always(fi2fo(0), vecend);
2785 b.end_table(off);
2786 check(&b, &[
2787 6, 0, // vtable bytes
2788 8, 0,
2789 4, 0, // offset to vector offset
2790 6, 0, 0, 0, // offset for start of vtable (int32)
2791 4, 0, 0, 0,
2792 0, 0, 0, 0, // length of vector (not in struct)
2793 ]);
2794 }
2795
2796 #[test]
layout_12c_vtable_with_empty_vector_of_byte_and_some_scalars()2797 fn layout_12c_vtable_with_empty_vector_of_byte_and_some_scalars() {
2798 let mut b = flatbuffers::FlatBufferBuilder::new();
2799 b.start_vector::<u8>(0);
2800 let vecend = b.end_vector::<u8>(0);
2801 let off = b.start_table();
2802 b.push_slot::<i16>(fi2fo(0), 55i16, 0);
2803 b.push_slot_always::<flatbuffers::WIPOffset<_>>(fi2fo(1), vecend);
2804 b.end_table(off);
2805 check(&b, &[
2806 8, 0, // vtable bytes
2807 12, 0,
2808 10, 0, // offset to value 0
2809 4, 0, // offset to vector offset
2810 8, 0, 0, 0, // vtable loc
2811 8, 0, 0, 0, // value 1
2812 0, 0, 55, 0, // value 0
2813
2814 0, 0, 0, 0, // length of vector (not in struct)
2815 ]);
2816 }
2817 #[test]
layout_13_vtable_with_1_int16_and_2_vector_of_i16()2818 fn layout_13_vtable_with_1_int16_and_2_vector_of_i16() {
2819 let mut b = flatbuffers::FlatBufferBuilder::new();
2820 b.start_vector::<i16>(2);
2821 b.push(0x1234i16);
2822 b.push(0x5678i16);
2823 let vecend = b.end_vector::<i16>(2);
2824 let off = b.start_table();
2825 b.push_slot_always(fi2fo(1), vecend);
2826 b.push_slot(fi2fo(0), 55i16, 0);
2827 b.end_table(off);
2828 check(&b, &[
2829 8, 0, // vtable bytes
2830 12, 0, // length of object
2831 6, 0, // start of value 0 from end of vtable
2832 8, 0, // start of value 1 from end of buffer
2833 8, 0, 0, 0, // offset for start of vtable (int32)
2834 0, 0, // padding
2835 55, 0, // value 0
2836 4, 0, 0, 0, // vector position from here
2837 2, 0, 0, 0, // length of vector (uint32)
2838 0x78, 0x56, // vector value 1
2839 0x34, 0x12, // vector value 0
2840 ]);
2841 }
2842 #[test]
layout_14_vtable_with_1_struct_of_int8_and_int16_and_int32()2843 fn layout_14_vtable_with_1_struct_of_int8_and_int16_and_int32() {
2844 #[derive(Copy, Clone, Debug, Eq, PartialEq)]
2845 #[repr(C, packed)]
2846 struct foo {
2847 a: i32,
2848 _pad0: [u8; 2],
2849 b: i16,
2850 _pad1: [u8; 3],
2851 c: i8,
2852 _pad2: [u8; 4],
2853 }
2854 assert_eq!(::core::mem::size_of::<foo>(), 16);
2855 impl<'b> flatbuffers::Push for &'b foo {
2856 type Output = foo;
2857 unsafe fn push<'a>(&'a self, dst: &'a mut [u8], _written_len: usize) {
2858 let src = ::core::slice::from_raw_parts(*self as *const foo as *const u8, ::core::mem::size_of::<foo>());
2859 dst.copy_from_slice(src);
2860 }
2861 }
2862
2863 let mut b = flatbuffers::FlatBufferBuilder::new();
2864 let off = b.start_table();
2865 let x = foo{a: 0x12345678i32.to_le(), _pad0: [0,0], b: 0x1234i16.to_le(), _pad1: [0, 0, 0], c: 0x12i8.to_le(), _pad2: [0, 0, 0, 0]};
2866 b.push_slot_always(fi2fo(0), &x);
2867 b.end_table(off);
2868 check(&b, &[
2869 6, 0, // vtable bytes
2870 20, 0, // end of object from here
2871 4, 0, // start of struct from here
2872 6, 0, 0, 0, // offset for start of vtable (int32)
2873
2874 0x78, 0x56, 0x34, 0x12, // value a
2875 0, 0, // padding
2876 0x34, 0x12, // value b
2877 0, 0, 0, // padding
2878 0x12, // value c
2879 0, 0, 0, 0, // padding
2880 ]);
2881 }
2882 #[test]
layout_15_vtable_with_1_vector_of_4_int8()2883 fn layout_15_vtable_with_1_vector_of_4_int8() {
2884 let mut b = flatbuffers::FlatBufferBuilder::new();
2885 b.start_vector::<i8>(4);
2886 b.push(33i8);
2887 b.push(44i8);
2888 b.push(55i8);
2889 b.push(66i8);
2890 let vecend = b.end_vector::<i8>(4);
2891 let off = b.start_table();
2892 b.push_slot_always(fi2fo(0), vecend);
2893 b.end_table(off);
2894 check(&b, &[
2895 6, 0, // vtable bytes
2896 8, 0,
2897 4, 0, // offset of vector offset
2898 6, 0, 0, 0, // offset for start of vtable (int32)
2899 4, 0, 0, 0, // vector start offset
2900
2901 4, 0, 0, 0, // vector length
2902 66, // vector value 1,1
2903 55, // vector value 1,0
2904 44, // vector value 0,1
2905 33, // vector value 0,0
2906 ]);
2907 }
2908
2909 #[test]
layout_16_table_with_some_elements()2910 fn layout_16_table_with_some_elements() {
2911 let mut b = flatbuffers::FlatBufferBuilder::new();
2912 let off = b.start_table();
2913 b.push_slot(fi2fo(0), 33i8, 0);
2914 b.push_slot(fi2fo(1), 66i16, 0);
2915 let off2 = b.end_table(off);
2916 b.finish_minimal(off2);
2917
2918 check(&b, &[
2919 12, 0, 0, 0, // root of table: points to vtable offset
2920
2921 8, 0, // vtable bytes
2922 8, 0, // end of object from here
2923 7, 0, // start of value 0
2924 4, 0, // start of value 1
2925
2926 8, 0, 0, 0, // offset for start of vtable (int32)
2927
2928 66, 0, // value 1
2929 0, // padding
2930 33, // value 0
2931 ]);
2932 }
2933
2934 #[test]
layout_17_one_unfinished_table_and_one_finished_table()2935 fn layout_17_one_unfinished_table_and_one_finished_table() {
2936 let mut b = flatbuffers::FlatBufferBuilder::new();
2937 {
2938 let off = b.start_table();
2939 b.push_slot(fi2fo(0), 33i8, 0);
2940 b.push_slot(fi2fo(1), 44i8, 0);
2941 b.end_table(off);
2942 }
2943
2944 {
2945 let off = b.start_table();
2946 b.push_slot(fi2fo(0), 55i8, 0);
2947 b.push_slot(fi2fo(1), 66i8, 0);
2948 b.push_slot(fi2fo(2), 77i8, 0);
2949 let off2 = b.end_table(off);
2950 b.finish_minimal(off2);
2951 }
2952
2953 check(&b, &[
2954 16, 0, 0, 0, // root of table: points to object
2955 0, 0, // padding
2956
2957 10, 0, // vtable bytes
2958 8, 0, // size of object
2959 7, 0, // start of value 0
2960 6, 0, // start of value 1
2961 5, 0, // start of value 2
2962 10, 0, 0, 0, // offset for start of vtable (int32)
2963 0, // padding
2964 77, // value 2
2965 66, // value 1
2966 55, // value 0
2967
2968 //12, 0, 0, 0, // root of table: points to object
2969
2970 8, 0, // vtable bytes
2971 8, 0, // size of object
2972 7, 0, // start of value 0
2973 6, 0, // start of value 1
2974 8, 0, 0, 0, // offset for start of vtable (int32)
2975 0, 0, // padding
2976 44, // value 1
2977 33, // value 0
2978 ]);
2979 }
2980
2981 #[test]
layout_18_a_bunch_of_bools()2982 fn layout_18_a_bunch_of_bools() {
2983 let mut b = flatbuffers::FlatBufferBuilder::new();
2984 let off = b.start_table();
2985 b.push_slot(fi2fo(0), true, false);
2986 b.push_slot(fi2fo(1), true, false);
2987 b.push_slot(fi2fo(2), true, false);
2988 b.push_slot(fi2fo(3), true, false);
2989 b.push_slot(fi2fo(4), true, false);
2990 b.push_slot(fi2fo(5), true, false);
2991 b.push_slot(fi2fo(6), true, false);
2992 b.push_slot(fi2fo(7), true, false);
2993 let off2 = b.end_table(off);
2994 b.finish_minimal(off2);
2995
2996 check(&b, &[
2997 24, 0, 0, 0, // root of table: points to vtable offset
2998
2999 20, 0, // vtable bytes
3000 12, 0, // size of object
3001 11, 0, // start of value 0
3002 10, 0, // start of value 1
3003 9, 0, // start of value 2
3004 8, 0, // start of value 3
3005 7, 0, // start of value 4
3006 6, 0, // start of value 5
3007 5, 0, // start of value 6
3008 4, 0, // start of value 7
3009 20, 0, 0, 0, // vtable offset
3010
3011 1, // value 7
3012 1, // value 6
3013 1, // value 5
3014 1, // value 4
3015 1, // value 3
3016 1, // value 2
3017 1, // value 1
3018 1, // value 0
3019 ]);
3020 }
3021
3022 #[test]
layout_19_three_bools()3023 fn layout_19_three_bools() {
3024 let mut b = flatbuffers::FlatBufferBuilder::new();
3025 let off = b.start_table();
3026 b.push_slot(fi2fo(0), true, false);
3027 b.push_slot(fi2fo(1), true, false);
3028 b.push_slot(fi2fo(2), true, false);
3029 let off2 = b.end_table(off);
3030 b.finish_minimal(off2);
3031
3032 check(&b, &[
3033 16, 0, 0, 0, // root of table: points to vtable offset
3034
3035 0, 0, // padding
3036
3037 10, 0, // vtable bytes
3038 8, 0, // size of object
3039 7, 0, // start of value 0
3040 6, 0, // start of value 1
3041 5, 0, // start of value 2
3042 10, 0, 0, 0, // vtable offset from here
3043
3044 0, // padding
3045 1, // value 2
3046 1, // value 1
3047 1, // value 0
3048 ]);
3049 }
3050
3051 #[test]
layout_20_some_floats()3052 fn layout_20_some_floats() {
3053 let mut b = flatbuffers::FlatBufferBuilder::new();
3054 let off = b.start_table();
3055 b.push_slot(fi2fo(0), 1.0f32, 0.0);
3056 b.end_table(off);
3057
3058 check(&b, &[
3059 6, 0, // vtable bytes
3060 8, 0, // size of object
3061 4, 0, // start of value 0
3062 6, 0, 0, 0, // vtable offset
3063
3064 0, 0, 128, 63, // value 0
3065 ]);
3066 }
3067
3068 #[test]
layout_21_vtable_defaults()3069 fn layout_21_vtable_defaults() {
3070 let mut b = flatbuffers::FlatBufferBuilder::new();
3071 let off = b.start_table();
3072 b.push_slot::<i8>(fi2fo(0), 1, 1);
3073 b.push_slot::<i8>(fi2fo(1), 3, 2);
3074 b.push_slot::<i8>(fi2fo(2), 3, 3);
3075 b.end_table(off);
3076 check(&b, &[
3077 8, 0, // vtable size in bytes
3078 8, 0, // object inline data in bytes
3079 0, 0, // entry 1/3: 0 => default
3080 7, 0, // entry 2/3: 7 => table start + 7 bytes
3081 // entry 3/3: not present => default
3082 8, 0, 0, 0,
3083 0, 0, 0,
3084 3,
3085 ]);
3086 }
3087
3088 #[test]
layout_22_root()3089 fn layout_22_root() {
3090 let mut b = flatbuffers::FlatBufferBuilder::new();
3091 let off = b.start_table();
3092 // skipped: b.push_slot_scalar::<i16>(0, 1, 1);
3093 b.push_slot::<i16>(fi2fo(1), 3, 2);
3094 b.push_slot::<i16>(fi2fo(2), 3, 3);
3095 let table_end = b.end_table(off);
3096 b.finish_minimal(table_end);
3097 check(&b, &[
3098 12, 0, 0, 0, // root
3099
3100 8, 0, // vtable size in bytes
3101 8, 0, // object inline data in bytes
3102 0, 0, // entry 1/3: 0 => default
3103 6, 0, // entry 2/3: 6 => table start + 6 bytes
3104 // entry 3/3: not present => default
3105 8, 0, 0, 0, // size of table data in bytes
3106 0, 0, // padding
3107 3, 0, // value 2/3
3108 ]);
3109 }
3110 #[test]
layout_23_varied_slots_and_root()3111 fn layout_23_varied_slots_and_root() {
3112 let mut b = flatbuffers::FlatBufferBuilder::new();
3113 let off = b.start_table();
3114 b.push_slot::<i16>(fi2fo(0), 1, 0);
3115 b.push_slot::<u8>(fi2fo(1), 2, 0);
3116 b.push_slot::<f32>(fi2fo(2), 3.0, 0.0);
3117 let table_end = b.end_table(off);
3118 b.finish_minimal(table_end);
3119 check(&b, &[
3120 16, 0, 0, 0, // root
3121 0, 0, // padding
3122 10, 0, // vtable bytes
3123 12, 0, // object inline data size
3124 10, 0, // offset to value #1 (i16)
3125 9, 0, // offset to value #2 (u8)
3126 4, 0, // offset to value #3 (f32)
3127 10, 0, // offset to vtable
3128 0, 0, // padding
3129 0, 0, 64, 64, // value #3 => 3.0 (float32)
3130 0, 2, // value #1 => 2 (u8)
3131 1, 0, // value #0 => 1 (int16)
3132 ]);
3133 }
3134 }
3135
3136 #[cfg(test)]
3137 mod copy_clone_traits {
3138
3139 use alloc::vec::Vec;
3140
3141 #[test]
follow_types_implement_copy_and_clone()3142 fn follow_types_implement_copy_and_clone() {
3143 static_assertions::assert_impl_all!(flatbuffers::WIPOffset<u32>: Copy, Clone);
3144 static_assertions::assert_impl_all!(flatbuffers::WIPOffset<Vec<u32>>: Copy, Clone);
3145
3146 static_assertions::assert_impl_all!(flatbuffers::ForwardsUOffset<u32>: Copy, Clone);
3147 static_assertions::assert_impl_all!(flatbuffers::ForwardsUOffset<Vec<u32>>: Copy, Clone);
3148
3149 static_assertions::assert_impl_all!(flatbuffers::Vector<'static, u32>: Copy, Clone);
3150 static_assertions::assert_impl_all!(flatbuffers::Vector<'static, Vec<u32>>: Copy, Clone);
3151 }
3152 }
3153
3154 #[cfg(test)]
3155 mod fully_qualified_name {
3156 #[test]
fully_qualified_name_generated()3157 fn fully_qualified_name_generated() {
3158 assert!(check_eq!(super::my_game::example::Monster::get_fully_qualified_name(), "MyGame.Example.Monster").is_ok());
3159 assert!(check_eq!(super::my_game::example_2::Monster::get_fully_qualified_name(), "MyGame.Example2.Monster").is_ok());
3160
3161 assert!(check_eq!(super::my_game::example::Vec3::get_fully_qualified_name(), "MyGame.Example.Vec3").is_ok());
3162 assert!(check_eq!(super::my_game::example::Ability::get_fully_qualified_name(), "MyGame.Example.Ability").is_ok());
3163 }
3164 }
3165
3166 // this is not technically a test, but we want to always keep this generated
3167 // file up-to-date, and the simplest way to do that is to make sure that when
3168 // tests are run, the file is generated.
3169 #[cfg(not(feature = "no_std"))]
3170 #[test]
write_example_wire_data_to_file()3171 fn write_example_wire_data_to_file() {
3172 let b = &mut flatbuffers::FlatBufferBuilder::new();
3173 create_serialized_example_with_generated_code(b);
3174
3175 use ::std::io::Write;
3176 let mut f = std::fs::File::create("../monsterdata_rust_wire.mon").unwrap();
3177 f.write_all(b.finished_data()).unwrap();
3178 }
3179
3180 #[cfg(not(feature = "no_std"))]
load_file(filename: &str) -> Result<Vec<u8>, std::io::Error>3181 fn load_file(filename: &str) -> Result<Vec<u8>, std::io::Error> {
3182 use std::io::Read;
3183 let mut f = std::fs::File::open(filename)?;
3184 let mut buf = Vec::new();
3185 f.read_to_end(&mut buf)?;
3186 Ok(buf)
3187 }
3188
3189 #[test]
test_shared_strings()3190 fn test_shared_strings() {
3191 let mut builder = flatbuffers::FlatBufferBuilder::new();
3192 let offset1 = builder.create_shared_string("welcome to flatbuffers!!");
3193 let offset2 = builder.create_shared_string("welcome");
3194 let offset3 = builder.create_shared_string("welcome to flatbuffers!!");
3195 assert_ne!(offset2.value(), offset3.value());
3196 assert_eq!(offset1.value(), offset3.value());
3197 builder.reset();
3198 let offset4 = builder.create_shared_string("welcome");
3199 let offset5 = builder.create_shared_string("welcome to flatbuffers!!");
3200 assert_ne!(offset2.value(), offset4.value());
3201 assert_ne!(offset5.value(), offset1.value());
3202 builder.reset();
3203
3204 // Checks if the shared string function would always work with
3205 // an object in between the writes
3206 let name = builder.create_shared_string("foo");
3207 let enemy = my_game::example::Monster::create(&mut builder, &my_game::example::MonsterArgs {
3208 name: Some(name),
3209 ..Default::default()
3210 });
3211 let secondary_name = builder.create_shared_string("foo");
3212 assert_eq!(name.value(), secondary_name.value());
3213
3214 // Builds a new monster object and embeds enemy into it so we can verify
3215 // that shared strings are working.
3216 let args = my_game::example::MonsterArgs {
3217 name: Some(secondary_name),
3218 enemy: Some(enemy),
3219 testarrayofstring: Some(builder.create_vector(&[name, secondary_name])),
3220 ..Default::default()
3221 };
3222 // Building secondary monster
3223 let main_monster = my_game::example::Monster::create(&mut builder, &args);
3224 builder.finish(main_monster, None);
3225 let monster = my_game::example::root_as_monster(builder.finished_data()).unwrap();
3226
3227 // Checks if the embedded object (Enemy) name is foo
3228 assert_eq!(monster.enemy().unwrap().name(), "foo");
3229 let string_vector = monster.testarrayofstring().unwrap();
3230 // Check if the vector will have the same string
3231 assert_eq!(string_vector.get(0), "foo");
3232 assert_eq!(string_vector.get(1), "foo");
3233 }
3234
3235 }
3236