| // Copyright 2019 Google LLC |
| // |
| // Licensed under the Apache License, Version 2.0 (the "License"); |
| // you may not use this file except in compliance with the License. |
| // You may obtain a copy of the License at |
| // |
| // https://www.apache.org/licenses/LICENSE-2.0 |
| // |
| // Unless required by applicable law or agreed to in writing, software |
| // distributed under the License is distributed on an "AS IS" BASIS, |
| // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| // See the License for the specific language governing permissions and |
| // limitations under the License. |
| |
| use crate::builder::Builder; |
| use crate::private::Sealed; |
| use crate::{Blob, IndirectFloat, IndirectInt, IndirectUInt}; |
| |
| impl<'a> Sealed for Blob<'a> {} |
| impl Sealed for () {} |
| |
| // TODO: String interning |
| // TODO: Pushable for Map types? |
| |
| /// Types that implement the Pushable trait can be written into a Flexbuffer. |
| /// |
| /// All Rust's standard numbers, `u8, u16, u32, u64, i8, i16, i32, i64, f32, f64`, |
| /// can all be pushed. They are `FlexBufferType::{UInt, Int, Float}`. |
| /// Flexbuffers chooses the smallest width that can represent the given number. |
| /// Strings can pe pushed, they become `FlexBufferType::String` and are stored |
| /// with both a length and null terminator. |
| /// |
| /// * For convenience and speed push typed vectors using rust arrays and slices. |
| /// Doing so will immediately serialize the data, skipping the `Builder`'s |
| /// internal cache. |
| /// |
| /// * Pushable cannot not be implemented by any downstream crates. |
| pub trait Pushable: Sealed + Sized { |
| fn push_to_builder(self, _: &mut Builder) {} |
| } |
| |
| impl Pushable for () { |
| fn push_to_builder(self, builder: &mut Builder) { |
| builder.push_null(); |
| } |
| } |
| impl<'a> Pushable for Blob<'a> { |
| fn push_to_builder(self, builder: &mut Builder) { |
| builder.push_blob(self.0); |
| } |
| } |
| |
| macro_rules! forward_to_builder { |
| ($T: ty, $method: ident) => { |
| impl Sealed for $T {} |
| impl Pushable for $T { |
| fn push_to_builder(self, builder: &mut Builder) { |
| builder.$method(self); |
| } |
| } |
| }; |
| ($T: ty, $method: ident, $asT: ty) => { |
| impl Sealed for $T {} |
| impl Pushable for $T { |
| fn push_to_builder(self, builder: &mut Builder) { |
| builder.$method(self as $asT); |
| } |
| } |
| }; |
| } |
| forward_to_builder!(&str, push_str); |
| forward_to_builder!(bool, push_bool); |
| forward_to_builder!(u8, push_uint); |
| forward_to_builder!(u16, push_uint); |
| forward_to_builder!(u32, push_uint); |
| forward_to_builder!(u64, push_uint); |
| forward_to_builder!(i8, push_int); |
| forward_to_builder!(i16, push_int); |
| forward_to_builder!(i32, push_int); |
| forward_to_builder!(i64, push_int); |
| forward_to_builder!(f32, push_float); |
| forward_to_builder!(f64, push_float); |
| forward_to_builder!(&[u8], push_uints); |
| forward_to_builder!(&[u16], push_uints); |
| forward_to_builder!(&[u32], push_uints); |
| forward_to_builder!(&[u64], push_uints); |
| forward_to_builder!(&[i8], push_ints); |
| forward_to_builder!(&[i16], push_ints); |
| forward_to_builder!(&[i32], push_ints); |
| forward_to_builder!(&[i64], push_ints); |
| forward_to_builder!(&[f32], push_floats); |
| forward_to_builder!(&[f64], push_floats); |
| forward_to_builder!(&[bool], push_bools); |
| forward_to_builder!(&Vec<u8>, push_uints); |
| forward_to_builder!(&Vec<u16>, push_uints); |
| forward_to_builder!(&Vec<u32>, push_uints); |
| forward_to_builder!(&Vec<u64>, push_uints); |
| forward_to_builder!(&Vec<i8>, push_ints); |
| forward_to_builder!(&Vec<i16>, push_ints); |
| forward_to_builder!(&Vec<i32>, push_ints); |
| forward_to_builder!(&Vec<i64>, push_ints); |
| forward_to_builder!(&Vec<f32>, push_floats); |
| forward_to_builder!(&Vec<f64>, push_floats); |
| forward_to_builder!(&Vec<bool>, push_bools); |
| |
| macro_rules! impl_indirects { |
| ($Indirect: ident, $method: ident) => { |
| impl Sealed for $Indirect {} |
| impl Pushable for $Indirect { |
| fn push_to_builder(self, builder: &mut Builder) { |
| builder.$method(self.0); |
| } |
| } |
| }; |
| } |
| impl_indirects!(IndirectInt, push_indirect_int); |
| impl_indirects!(IndirectUInt, push_indirect_uint); |
| impl_indirects!(IndirectFloat, push_indirect_float); |
| |
| macro_rules! impl_arrays { |
| ($num: expr) => { |
| forward_to_builder!(&[u8; $num], push_uints, &[u8]); |
| forward_to_builder!(&[u16; $num], push_uints, &[u16]); |
| forward_to_builder!(&[u32; $num], push_uints, &[u32]); |
| forward_to_builder!(&[u64; $num], push_uints, &[u64]); |
| forward_to_builder!(&[i8; $num], push_ints, &[i8]); |
| forward_to_builder!(&[i16; $num], push_ints, &[i16]); |
| forward_to_builder!(&[i32; $num], push_ints, &[i32]); |
| forward_to_builder!(&[i64; $num], push_ints, &[i64]); |
| forward_to_builder!(&[f32; $num], push_floats, &[f32]); |
| forward_to_builder!(&[f64; $num], push_floats, &[f64]); |
| forward_to_builder!(&[bool; $num], push_bools, &[bool]); |
| }; |
| } |
| impl_arrays!(0); |
| impl_arrays!(1); |
| impl_arrays!(2); |
| impl_arrays!(3); |
| impl_arrays!(4); |
| impl_arrays!(5); |
| impl_arrays!(6); |
| // impl_arrays!(7); |
| // impl_arrays!(8); |
| // impl_arrays!(9); |
| // impl_arrays!(10); |
| // impl_arrays!(11); |
| // impl_arrays!(12); |
| // impl_arrays!(13); |
| // impl_arrays!(14); |
| // impl_arrays!(15); |
| // impl_arrays!(16); |
| // impl_arrays!(17); |
| // impl_arrays!(18); |
| // impl_arrays!(19); |
| // impl_arrays!(20); |
| // impl_arrays!(21); |
| // impl_arrays!(22); |
| // impl_arrays!(23); |
| // impl_arrays!(24); |
| // impl_arrays!(25); |
| // impl_arrays!(26); |
| // impl_arrays!(27); |
| // impl_arrays!(28); |
| // impl_arrays!(29); |
| // impl_arrays!(30); |
| // impl_arrays!(31); |
| // impl_arrays!(32); |