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