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