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