16
16
17
17
mod reflection_generated;
18
18
mod reflection_verifier;
19
- mod safe_buffer;
19
+ pub mod safe_buffer;
20
+ mod vector_of_any;
21
+ pub use vector_of_any:: VectorOfAny ;
20
22
mod r#struct;
21
23
pub use crate :: r#struct:: Struct ;
22
24
pub use crate :: reflection_generated:: reflection;
@@ -50,8 +52,12 @@ pub enum FlatbufferError {
50
52
SetStringPolluted ,
51
53
#[ error( "Invalid schema: Polluted buffer or the schema doesn't match the buffer." ) ]
52
54
InvalidSchema ,
53
- #[ error( "Type not supported: {0}" ) ]
54
- TypeNotSupported ( String ) ,
55
+ #[ error( "Unsupported table field type: {0:?}" ) ]
56
+ UnsupportedTableFieldType ( BaseType ) ,
57
+ #[ error( "Unsupported vector element type: {0:?}" ) ]
58
+ UnsupportedVectorElementType ( BaseType ) ,
59
+ #[ error( "Unsupported union element type: {0:?}" ) ]
60
+ UnsupportedUnionElementType ( BaseType ) ,
55
61
#[ error( "No type or invalid type found in union enum" ) ]
56
62
InvalidUnionEnum ,
57
63
#[ error( "Table or Struct doesn't belong to the buffer" ) ]
@@ -80,21 +86,17 @@ pub unsafe fn get_any_root(data: &[u8]) -> Table {
80
86
pub unsafe fn get_field_integer < T : for < ' a > Follow < ' a , Inner = T > + PrimInt + FromPrimitive > (
81
87
table : & Table ,
82
88
field : & Field ,
83
- ) -> FlatbufferResult < Option < T > > {
84
- if size_of :: < T > ( ) != get_type_size ( field. type_ ( ) . base_type ( ) ) {
85
- return Err ( FlatbufferError :: FieldTypeMismatch (
86
- std:: any:: type_name :: < T > ( ) . to_string ( ) ,
87
- field
88
- . type_ ( )
89
- . base_type ( )
90
- . variant_name ( )
91
- . unwrap_or_default ( )
92
- . to_string ( ) ,
93
- ) ) ;
94
- }
89
+ ) -> Option < T > {
90
+ debug_assert_eq ! (
91
+ size_of:: <T >( ) ,
92
+ get_type_size( field. type_( ) . base_type( ) ) ,
93
+ "Type size mismatch: {} vs {}" ,
94
+ std:: any:: type_name:: <T >( ) ,
95
+ field. type_( ) . base_type( ) . variant_name( ) . unwrap_or_default( )
96
+ ) ;
95
97
96
98
let default = T :: from_i64 ( field. default_integer ( ) ) ;
97
- Ok ( table. get :: < T > ( field. offset ( ) , default) )
99
+ table. get :: < T > ( field. offset ( ) , default)
98
100
}
99
101
100
102
/// Gets a floating point table field given its exact type. Returns default float value if the field is not set. Returns [None] if no default value is found. Returns error if the type doesn't match.
@@ -105,121 +107,98 @@ pub unsafe fn get_field_integer<T: for<'a> Follow<'a, Inner = T> + PrimInt + Fro
105
107
pub unsafe fn get_field_float < T : for < ' a > Follow < ' a , Inner = T > + Float > (
106
108
table : & Table ,
107
109
field : & Field ,
108
- ) -> FlatbufferResult < Option < T > > {
109
- if size_of :: < T > ( ) != get_type_size ( field. type_ ( ) . base_type ( ) ) {
110
- return Err ( FlatbufferError :: FieldTypeMismatch (
111
- std:: any:: type_name :: < T > ( ) . to_string ( ) ,
112
- field
113
- . type_ ( )
114
- . base_type ( )
115
- . variant_name ( )
116
- . unwrap_or_default ( )
117
- . to_string ( ) ,
118
- ) ) ;
119
- }
110
+ ) -> Option < T > {
111
+ debug_assert_eq ! (
112
+ size_of:: <T >( ) ,
113
+ get_type_size( field. type_( ) . base_type( ) ) ,
114
+ "Type size mismatch: {} vs {}" ,
115
+ std:: any:: type_name:: <T >( ) ,
116
+ field. type_( ) . base_type( ) . variant_name( ) . unwrap_or_default( )
117
+ ) ;
120
118
121
119
let default = T :: from ( field. default_real ( ) ) ;
122
- Ok ( table. get :: < T > ( field. offset ( ) , default) )
120
+ table. get :: < T > ( field. offset ( ) , default)
123
121
}
124
122
125
123
/// Gets a String table field given its exact type. Returns empty string if the field is not set. Returns [None] if no default value is found. Returns error if the type size doesn't match.
126
124
///
127
125
/// # Safety
128
126
///
129
127
/// The value of the corresponding slot must have type String
130
- pub unsafe fn get_field_string < ' a > (
131
- table : & Table < ' a > ,
132
- field : & Field ,
133
- ) -> FlatbufferResult < Option < & ' a str > > {
134
- if field. type_ ( ) . base_type ( ) != BaseType :: String {
135
- return Err ( FlatbufferError :: FieldTypeMismatch (
136
- String :: from ( "String" ) ,
137
- field
138
- . type_ ( )
139
- . base_type ( )
140
- . variant_name ( )
141
- . unwrap_or_default ( )
142
- . to_string ( ) ,
143
- ) ) ;
144
- }
145
-
146
- Ok ( table. get :: < ForwardsUOffset < & ' a str > > ( field. offset ( ) , Some ( "" ) ) )
128
+ pub unsafe fn get_field_string < ' a > ( table : & Table < ' a > , field : & Field ) -> & ' a str {
129
+ debug_assert_eq ! ( field. type_( ) . base_type( ) , BaseType :: String ) ;
130
+ table
131
+ . get :: < ForwardsUOffset < & ' a str > > ( field. offset ( ) , Some ( "" ) )
132
+ . unwrap ( )
147
133
}
148
134
149
- /// Gets a [Struct] table field given its exact type. Returns [None] if the field is not set. Returns error if the type doesn't match.
135
+ /// Gets a [Struct] table field given its exact type. Returns [None] if the field is not set.
150
136
///
151
137
/// # Safety
152
138
///
153
139
/// The value of the corresponding slot must have type Struct
154
- pub unsafe fn get_field_struct < ' a > (
155
- table : & Table < ' a > ,
156
- field : & Field ,
157
- ) -> FlatbufferResult < Option < Struct < ' a > > > {
140
+ pub unsafe fn get_field_struct < ' a > ( table : & Table < ' a > , field : & Field ) -> Option < Struct < ' a > > {
158
141
// TODO inherited from C++: This does NOT check if the field is a table or struct, but we'd need
159
142
// access to the schema to check the is_struct flag.
160
- if field. type_ ( ) . base_type ( ) != BaseType :: Obj {
161
- return Err ( FlatbufferError :: FieldTypeMismatch (
162
- String :: from ( "Obj" ) ,
163
- field
164
- . type_ ( )
165
- . base_type ( )
166
- . variant_name ( )
167
- . unwrap_or_default ( )
168
- . to_string ( ) ,
169
- ) ) ;
170
- }
143
+ debug_assert_eq ! ( field. type_( ) . base_type( ) , BaseType :: Obj ) ;
171
144
172
- Ok ( table. get :: < Struct > ( field. offset ( ) , None ) )
145
+ table. get :: < Struct > ( field. offset ( ) , None )
173
146
}
174
147
175
- /// Gets a Vector table field given its exact type. Returns empty vector if the field is not set. Returns error if the type doesn't match.
148
+ /// Get a vector table field, whose elements have type `T`.
149
+ ///
150
+ /// Returns an empty vector if the field is not set.
151
+ ///
152
+ /// Non-scalar values such as tables or strings are not stored inline. In such cases, you should use
153
+ /// `ForwardsUOffset`. So for example, use `T = ForwardsUOffset<Table<'a>>` for a vector of tables,
154
+ /// or `T = ForwardsUOffset<&'a str>` for a vector of strings.
176
155
///
177
156
/// # Safety
178
157
///
179
- /// The value of the corresponding slot must have type Vector
180
- pub unsafe fn get_field_vector < ' a , T : Follow < ' a , Inner = T > > (
158
+ /// The value of the corresponding slot must be a vector of elements of type `T` which are stored
159
+ /// inline.
160
+ pub unsafe fn get_field_vector < ' a , T : Follow < ' a > > (
181
161
table : & Table < ' a > ,
182
162
field : & Field ,
183
- ) -> FlatbufferResult < Option < Vector < ' a , T > > > {
184
- if field. type_ ( ) . base_type ( ) != BaseType :: Vector
185
- || core:: mem:: size_of :: < T > ( ) != get_type_size ( field. type_ ( ) . element ( ) )
186
- {
187
- return Err ( FlatbufferError :: FieldTypeMismatch (
188
- std:: any:: type_name :: < T > ( ) . to_string ( ) ,
189
- field
190
- . type_ ( )
191
- . base_type ( )
192
- . variant_name ( )
193
- . unwrap_or_default ( )
194
- . to_string ( ) ,
195
- ) ) ;
163
+ ) -> Vector < ' a , T > {
164
+ debug_assert_eq ! ( field. type_( ) . base_type( ) , BaseType :: Vector ) ;
165
+ if field. type_ ( ) . element ( ) != BaseType :: Obj {
166
+ // Skip this check in the case that it is a vector of structs, because the struct element's
167
+ // size cannot be checked on older schema versions without access to the schema.
168
+ debug_assert_eq ! (
169
+ core:: mem:: size_of:: <T >( ) ,
170
+ get_type_size( field. type_( ) . element( ) )
171
+ ) ;
196
172
}
197
173
198
- Ok ( table. get :: < ForwardsUOffset < Vector < ' a , T > > > ( field. offset ( ) , Some ( Vector :: < T > :: default ( ) ) ) )
174
+ table
175
+ . get :: < ForwardsUOffset < Vector < ' a , T > > > ( field. offset ( ) , Some ( Vector :: < T > :: default ( ) ) )
176
+ . unwrap ( )
199
177
}
200
178
201
- /// Gets a Table table field given its exact type. Returns [None] if the field is not set. Returns error if the type doesn't match.
179
+ /// Get a vector table field, whose elements have unknown type.
180
+ ///
181
+ /// Returns an empty vector if the field is not set.
182
+ ///
183
+ /// # Safety
184
+ ///
185
+ /// The value of the corresponding slot must be a vector of elements of type `T`.
186
+ pub unsafe fn get_field_vector_of_any < ' a > ( table : & Table < ' a > , field : & Field ) -> VectorOfAny < ' a > {
187
+ debug_assert_eq ! ( field. type_( ) . base_type( ) , BaseType :: Vector ) ;
188
+ table
189
+ . get :: < ForwardsUOffset < VectorOfAny < ' a > > > ( field. offset ( ) , Some ( VectorOfAny :: default ( ) ) )
190
+ . unwrap ( )
191
+ }
192
+
193
+ /// Gets a Table table field given its exact type. Returns [None] if the field is not set.
202
194
///
203
195
/// # Safety
204
196
///
205
197
/// The value of the corresponding slot must have type Table
206
- pub unsafe fn get_field_table < ' a > (
207
- table : & Table < ' a > ,
208
- field : & Field ,
209
- ) -> FlatbufferResult < Option < Table < ' a > > > {
210
- if field. type_ ( ) . base_type ( ) != BaseType :: Obj {
211
- return Err ( FlatbufferError :: FieldTypeMismatch (
212
- String :: from ( "Obj" ) ,
213
- field
214
- . type_ ( )
215
- . base_type ( )
216
- . variant_name ( )
217
- . unwrap_or_default ( )
218
- . to_string ( ) ,
219
- ) ) ;
220
- }
198
+ pub unsafe fn get_field_table < ' a > ( table : & Table < ' a > , field : & Field ) -> Option < Table < ' a > > {
199
+ debug_assert_eq ! ( field. type_( ) . base_type( ) , BaseType :: Obj ) ;
221
200
222
- Ok ( table. get :: < ForwardsUOffset < Table < ' a > > > ( field. offset ( ) , None ) )
201
+ table. get :: < ForwardsUOffset < Table < ' a > > > ( field. offset ( ) , None )
223
202
}
224
203
225
204
/// Returns the value of any table field as a 64-bit int, regardless of what type it is. Returns default integer if the field is not set or error if the value cannot be parsed as integer.
@@ -273,25 +252,12 @@ pub unsafe fn get_any_field_string(table: &Table, field: &Field, schema: &Schema
273
252
/// # Safety
274
253
///
275
254
/// The value of the corresponding slot must have type Struct.
276
- pub unsafe fn get_field_struct_in_struct < ' a > (
277
- st : & Struct < ' a > ,
278
- field : & Field ,
279
- ) -> FlatbufferResult < Struct < ' a > > {
255
+ pub unsafe fn get_field_struct_in_struct < ' a > ( st : & Struct < ' a > , field : & Field ) -> Struct < ' a > {
280
256
// TODO inherited from C++: This does NOT check if the field is a table or struct, but we'd need
281
257
// access to the schema to check the is_struct flag.
282
- if field. type_ ( ) . base_type ( ) != BaseType :: Obj {
283
- return Err ( FlatbufferError :: FieldTypeMismatch (
284
- String :: from ( "Obj" ) ,
285
- field
286
- . type_ ( )
287
- . base_type ( )
288
- . variant_name ( )
289
- . unwrap_or_default ( )
290
- . to_string ( ) ,
291
- ) ) ;
292
- }
258
+ debug_assert_eq ! ( field. type_( ) . base_type( ) , BaseType :: Obj ) ;
293
259
294
- Ok ( st. get :: < Struct > ( field. offset ( ) as usize ) )
260
+ st. get :: < Struct > ( field. offset ( ) as usize )
295
261
}
296
262
297
263
/// Returns the value of any struct field as a 64-bit int, regardless of what type it is. Returns error if the value cannot be parsed as integer.
@@ -576,7 +542,7 @@ pub unsafe fn set_string(
576
542
}
577
543
578
544
/// Returns the size of a scalar type in the `BaseType` enum. In the case of structs, returns the size of their offset (`UOffsetT`) in the buffer.
579
- fn get_type_size ( base_type : BaseType ) -> usize {
545
+ pub fn get_type_size ( base_type : BaseType ) -> usize {
580
546
match base_type {
581
547
BaseType :: UType | BaseType :: Bool | BaseType :: Byte | BaseType :: UByte => 1 ,
582
548
BaseType :: Short | BaseType :: UShort => 2 ,
0 commit comments