1 #![no_std]
2
3 #[cfg(not(feature = "no_std"))]
4 extern crate std;
5
6 extern crate alloc;
7
8 extern crate array_init;
9 #[allow(dead_code, unused_imports)]
10 #[path = "../../arrays_test/mod.rs"]
11 mod arrays_test_generated;
12 use alloc::format;
13 use core::fmt::Debug;
14
15 use crate::arrays_test_generated::my_game::example::*;
16 extern crate quickcheck;
17 use array_init::array_init;
18 use core::mem::size_of;
19 use quickcheck::{Arbitrary, Gen};
20
create_serialized_example_with_generated_code(builder: &mut flatbuffers::FlatBufferBuilder)21 fn create_serialized_example_with_generated_code(builder: &mut flatbuffers::FlatBufferBuilder) {
22 let nested_struct1 = NestedStruct::new(
23 &[-1, 2],
24 TestEnum::A,
25 &[TestEnum::C, TestEnum::B],
26 &[0x1122334455667788, -0x1122334455667788],
27 );
28 let nested_struct2 = NestedStruct::new(
29 &[3, -4],
30 TestEnum::B,
31 &[TestEnum::B, TestEnum::A],
32 &[-0x1122334455667788, 0x1122334455667788],
33 );
34 let array_struct = ArrayStruct::new(
35 12.34,
36 &[1, 2, 3, 4, 5, 6, 7, 8, 9, 0xA, 0xB, 0xC, 0xD, 0xE, 0xF],
37 -127,
38 &[nested_struct1, nested_struct2],
39 1,
40 &[-0x8000000000000000, 0x7FFFFFFFFFFFFFFF],
41 );
42 // Test five makes sense when specified.
43 let ss = ArrayTable::create(
44 builder,
45 &ArrayTableArgs {
46 a: Some(&array_struct),
47 },
48 );
49 finish_array_table_buffer(builder, ss);
50 }
51
serialized_example_is_accessible_and_correct( bytes: &[u8], identifier_required: bool, size_prefixed: bool, )52 fn serialized_example_is_accessible_and_correct(
53 bytes: &[u8],
54 identifier_required: bool,
55 size_prefixed: bool,
56 ) {
57 if identifier_required {
58 let correct = if size_prefixed {
59 array_table_size_prefixed_buffer_has_identifier(bytes)
60 } else {
61 array_table_buffer_has_identifier(bytes)
62 };
63 assert_eq!(correct, true);
64 }
65
66 let array_table = if size_prefixed {
67 size_prefixed_root_as_array_table(bytes).unwrap()
68 } else {
69 root_as_array_table(bytes).unwrap()
70 };
71
72 let array_struct = array_table.a().unwrap();
73 assert_eq!(array_struct.a(), 12.34);
74 assert_eq!(array_struct.b().len(), 0xF);
75 assert_eq!(array_struct.b().iter().sum::<i32>(), 120);
76 assert_eq!(array_struct.c(), -127);
77
78 assert_eq!(array_struct.d().len(), 2);
79 let nested_struct1 = array_struct.d().get(0);
80 assert_eq!(nested_struct1.a().len(), 2);
81 assert_eq!(nested_struct1.a().iter().sum::<i32>(), 1);
82 assert_eq!(nested_struct1.b(), TestEnum::A);
83 assert_eq!(nested_struct1.c().len(), 2);
84 assert_eq!(nested_struct1.c().get(0), TestEnum::C);
85 assert_eq!(nested_struct1.c().get(1), TestEnum::B);
86 assert_eq!(nested_struct1.d().len(), 2);
87 assert_eq!(
88 [nested_struct1.d().get(0), nested_struct1.d().get(1)],
89 [0x1122334455667788, -0x1122334455667788]
90 );
91 let nested_struct2 = array_struct.d().get(1);
92 assert_eq!(nested_struct2.a().len(), 2);
93 assert_eq!(nested_struct2.a().iter().sum::<i32>(), -1);
94 assert_eq!(nested_struct2.b(), TestEnum::B);
95 assert_eq!(nested_struct2.c().len(), 2);
96 assert_eq!(nested_struct2.c().get(0), TestEnum::B);
97 assert_eq!(nested_struct2.c().get(1), TestEnum::A);
98 assert_eq!(nested_struct2.d().len(), 2);
99 let arr: [i64; 2] = nested_struct2.d().into();
100 assert_eq!(
101 arr,
102 [-0x1122334455667788, 0x1122334455667788]
103 );
104
105 assert_eq!(array_struct.e(), 1);
106 assert_eq!(array_struct.f().len(), 2);
107 assert_eq!(array_struct.f().get(0), -0x8000000000000000);
108 assert_eq!(array_struct.f().get(1), 0x7FFFFFFFFFFFFFFF);
109 }
110
111 #[test]
generated_code_creates_correct_example()112 fn generated_code_creates_correct_example() {
113 let mut b = flatbuffers::FlatBufferBuilder::new();
114 create_serialized_example_with_generated_code(&mut b);
115 let buf = b.finished_data();
116 serialized_example_is_accessible_and_correct(&buf[..], true, false);
117 }
118
119 #[test]
struct_netsted_struct_is_32_bytes()120 fn struct_netsted_struct_is_32_bytes() {
121 assert_eq!(32, ::core::mem::size_of::<NestedStruct>());
122 }
123
124 #[test]
struct_array_struct_is_160_bytes()125 fn struct_array_struct_is_160_bytes() {
126 assert_eq!(160, ::core::mem::size_of::<ArrayStruct>());
127 }
128
129 #[test]
test_object_api_reads_correctly()130 fn test_object_api_reads_correctly() {
131 let mut b = flatbuffers::FlatBufferBuilder::new();
132 create_serialized_example_with_generated_code(&mut b);
133
134 let array_table = root_as_array_table(b.finished_data()).unwrap().unpack();
135
136 let array_struct = array_table.a.unwrap();
137 assert_eq!(array_struct.a, 12.34);
138 assert_eq!(array_struct.b.len(), 0xF);
139 assert_eq!(array_struct.b.iter().sum::<i32>(), 120);
140 assert_eq!(array_struct.c, -127);
141
142 assert_eq!(array_struct.d.len(), 2);
143 let nested_struct1 = &array_struct.d[0];
144 assert_eq!(nested_struct1.a.len(), 2);
145 assert_eq!(nested_struct1.a.iter().sum::<i32>(), 1);
146 assert_eq!(nested_struct1.b, TestEnum::A);
147 assert_eq!(nested_struct1.c.len(), 2);
148 assert_eq!(nested_struct1.c[0], TestEnum::C);
149 assert_eq!(nested_struct1.c[1], TestEnum::B);
150 assert_eq!(nested_struct1.d.len(), 2);
151 assert_eq!(nested_struct1.d, [0x1122334455667788, -0x1122334455667788]);
152 let nested_struct2 = &array_struct.d[1];
153 assert_eq!(nested_struct2.a.len(), 2);
154 assert_eq!(nested_struct2.a.iter().sum::<i32>(), -1);
155 assert_eq!(nested_struct2.b, TestEnum::B);
156 assert_eq!(nested_struct2.c.len(), 2);
157 assert_eq!(nested_struct2.c[0], TestEnum::B);
158 assert_eq!(nested_struct2.c[1], TestEnum::A);
159 assert_eq!(nested_struct2.d.len(), 2);
160 assert_eq!(nested_struct2.d, [-0x1122334455667788, 0x1122334455667788]);
161
162 assert_eq!(array_struct.e, 1);
163 assert_eq!(array_struct.f.len(), 2);
164 assert_eq!(array_struct.f[0], -0x8000000000000000);
165 assert_eq!(array_struct.f[1], 0x7FFFFFFFFFFFFFFF);
166 }
167
168 #[test]
object_api_defaults()169 fn object_api_defaults() {
170 use arrays_test_generated::my_game::example::*;
171
172 assert_eq!(
173 NestedStructT::default(),
174 NestedStructT {
175 a: [0, 0],
176 b: TestEnum::default(),
177 c: [TestEnum::default(), TestEnum::default()],
178 d: [0, 0]
179 }
180 );
181
182 assert_eq!(
183 ArrayStructT::default(),
184 ArrayStructT {
185 a: 0.0,
186 b: [0; 0xF],
187 c: 0,
188 d: [NestedStructT::default(), NestedStructT::default()],
189 e: 0,
190 f: [0, 0]
191 }
192 );
193 }
194
195 #[test]
generated_code_debug_prints_correctly()196 fn generated_code_debug_prints_correctly() {
197 let b = &mut flatbuffers::FlatBufferBuilder::new();
198 create_serialized_example_with_generated_code(b);
199 let buf = b.finished_data();
200 let array_table = root_as_array_table(buf).unwrap();
201 assert_eq!(
202 format!("{:.5?}", &array_table),
203 "ArrayTable { a: Some(ArrayStruct { a: 12.34000, \
204 b: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15], \
205 c: -127, d: [NestedStruct { a: [-1, 2], b: A, c: [C, B], \
206 d: [1234605616436508552, -1234605616436508552] }, \
207 NestedStruct { a: [3, -4], b: B, c: [B, A], d: [-1234605616436508552, 1234605616436508552] }], \
208 e: 1, f: [-9223372036854775808, 9223372036854775807] }) }"
209 );
210 }
211
212 #[test]
213 #[should_panic]
assert_on_too_small_array_buf()214 fn assert_on_too_small_array_buf() {
215 let a = [0u8; 19];
216 flatbuffers::Array::<i32, 5>::new(&a);
217 }
218
219 #[test]
220 #[should_panic]
assert_on_too_big_array_buf()221 fn assert_on_too_big_array_buf() {
222 let a = [0u8; 21];
223 flatbuffers::Array::<i32, 5>::new(&a);
224 }
225
226 #[test]
227 #[cfg(target_endian = "little")]
verify_struct_array_alignment()228 fn verify_struct_array_alignment() {
229 let mut b = flatbuffers::FlatBufferBuilder::new();
230 create_serialized_example_with_generated_code(&mut b);
231 let buf = b.finished_data();
232 let array_table = root_as_array_table(buf).unwrap();
233 let array_struct = array_table.a().unwrap();
234 let struct_start_ptr = array_struct.0.as_ptr() as usize;
235 let b_start_ptr = array_struct.b().as_ptr() as usize;
236 let d_start_ptr = array_struct.d().as_ptr() as usize;
237 // The T type of b
238 let b_aln = ::core::mem::align_of::<i32>();
239 assert_eq!((b_start_ptr - struct_start_ptr) % b_aln, 0);
240 assert_eq!((d_start_ptr - b_start_ptr) % b_aln, 0);
241 assert_eq!((d_start_ptr - struct_start_ptr) % 8, 0);
242 }
243
244 #[derive(Clone, Debug)]
245 struct FakeArray<T, const N: usize>([T; N]);
246
247 impl<T: Arbitrary + Debug + PartialEq, const N: usize> Arbitrary for FakeArray<T, N> {
arbitrary<G: Gen>(g: &mut G) -> FakeArray<T, N>248 fn arbitrary<G: Gen>(g: &mut G) -> FakeArray<T, N> {
249 let x: [T; N] = array_init(|_| {
250 loop {
251 let generated_scalar = T::arbitrary(g);
252 // Verify that generated scalar is not Nan, which is not equals to itself,
253 // therefore we can't use it to validate input == output
254 if generated_scalar == generated_scalar { return generated_scalar }
255 }
256 });
257 FakeArray{0: x}
258 }
259 }
260
261 #[cfg(test)]
262 mod array_fuzz {
263 #[cfg(not(miri))] // slow.
264 extern crate quickcheck;
265 extern crate flatbuffers;
266 use self::flatbuffers::{Follow, Push};
267 use super::*;
268
269 const MAX_TESTS: u64 = 20;
270 const ARRAY_SIZE: usize = 29;
271
272 // This uses a macro because lifetimes for the trait-bounded function get too
273 // complicated.
274 macro_rules! impl_prop {
275 ($test_name:ident, $fn_name:ident, $ty:ident) => (
276 fn $fn_name(xs: FakeArray<$ty, ARRAY_SIZE>) {
277 let mut test_buf = [0 as u8; 1024];
278 flatbuffers::emplace_scalar_array(&mut test_buf, 0, &xs.0);
279 let arr: flatbuffers::Array<$ty, ARRAY_SIZE> = flatbuffers::Array::follow(&test_buf, 0);
280 let got: [$ty; ARRAY_SIZE] = arr.into();
281 assert_eq!(got, xs.0);
282 }
283 #[test]
284 fn $test_name() {
285 quickcheck::QuickCheck::new().max_tests(MAX_TESTS).quickcheck($fn_name as fn(FakeArray<$ty, ARRAY_SIZE>));
286 }
287 )
288 }
289
290 impl_prop!(test_bool, prop_bool, bool);
291 impl_prop!(test_u8, prop_u8, u8);
292 impl_prop!(test_i8, prop_i8, i8);
293 impl_prop!(test_u16, prop_u16, u16);
294 impl_prop!(test_u32, prop_u32, u32);
295 impl_prop!(test_u64, prop_u64, u64);
296 impl_prop!(test_i16, prop_i16, i16);
297 impl_prop!(test_i32, prop_i32, i32);
298 impl_prop!(test_i64, prop_i64, i64);
299 impl_prop!(test_f32, prop_f32, f32);
300 impl_prop!(test_f64, prop_f64, f64);
301
302 const NESTED_STRUCT_SIZE: usize = size_of::<NestedStruct>();
303
304 #[derive(Clone, Debug, PartialEq)]
305 struct NestedStructWrapper(NestedStruct);
306
307 impl Arbitrary for NestedStructWrapper {
arbitrary<G: Gen>(g: &mut G) -> NestedStructWrapper308 fn arbitrary<G: Gen>(g: &mut G) -> NestedStructWrapper {
309 let mut x = NestedStruct::default();
310 x.0 = FakeArray::<u8, NESTED_STRUCT_SIZE>::arbitrary(g).0;
311 NestedStructWrapper{0: x}
312 }
313 }
314
prop_struct(xs: FakeArray<NestedStructWrapper, ARRAY_SIZE>)315 fn prop_struct(xs: FakeArray<NestedStructWrapper, ARRAY_SIZE>) {
316 let mut test_buf = [0 as u8; 1024];
317 let native_struct_array: [&NestedStruct; ARRAY_SIZE] = array_init::from_iter(xs.0.iter().map(|x| &x.0)).unwrap();
318 for i in 0..ARRAY_SIZE {
319 let offset = i * NESTED_STRUCT_SIZE;
320 native_struct_array[i].push(&mut test_buf[offset..offset + NESTED_STRUCT_SIZE], &[]);
321 }
322 let arr: flatbuffers::Array<NestedStruct, ARRAY_SIZE> = flatbuffers::Array::follow(&test_buf, 0);
323 let got: [&NestedStruct; ARRAY_SIZE] = arr.into();
324 assert_eq!(got, native_struct_array);
325 }
326
327 #[test]
328 #[cfg(not(miri))] // slow.
test_struct()329 fn test_struct() {
330 quickcheck::QuickCheck::new().max_tests(MAX_TESTS).quickcheck(prop_struct as fn(FakeArray<NestedStructWrapper, ARRAY_SIZE>));
331 }
332 }
333