1 // Copyright 2019 Google LLC 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // https://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 use crate::builder::Builder; 16 use crate::private::Sealed; 17 use crate::{Blob, Buffer, IndirectFloat, IndirectInt, IndirectUInt}; 18 19 impl<B: Buffer> Sealed for Blob<B> {} 20 impl Sealed for () {} 21 22 // TODO: String interning 23 // TODO: Pushable for Map types? 24 25 /// Types that implement the Pushable trait can be written into a Flexbuffer. 26 /// 27 /// All Rust's standard numbers, `u8, u16, u32, u64, i8, i16, i32, i64, f32, f64`, 28 /// can all be pushed. They are `FlexBufferType::{UInt, Int, Float}`. 29 /// Flexbuffers chooses the smallest width that can represent the given number. 30 /// Strings can pe pushed, they become `FlexBufferType::String` and are stored 31 /// with both a length and null terminator. 32 /// 33 /// * For convenience and speed push typed vectors using rust arrays and slices. 34 /// Doing so will immediately serialize the data, skipping the `Builder`'s 35 /// internal cache. 36 /// 37 /// * Pushable cannot not be implemented by any downstream crates. 38 pub trait Pushable: Sealed + Sized { push_to_builder(self, _: &mut Builder)39 fn push_to_builder(self, _: &mut Builder) {} 40 } 41 42 impl Pushable for () { push_to_builder(self, builder: &mut Builder)43 fn push_to_builder(self, builder: &mut Builder) { 44 builder.push_null(); 45 } 46 } 47 48 impl<B: Buffer> Pushable for Blob<B> { push_to_builder(self, builder: &mut Builder)49 fn push_to_builder(self, builder: &mut Builder) { 50 builder.push_blob(&self.0); 51 } 52 } 53 54 macro_rules! forward_to_builder { 55 ($T: ty, $method: ident) => { 56 impl Sealed for $T {} 57 impl Pushable for $T { 58 fn push_to_builder(self, builder: &mut Builder) { 59 builder.$method(self); 60 } 61 } 62 }; 63 ($T: ty, $method: ident, $asT: ty) => { 64 impl Sealed for $T {} 65 impl Pushable for $T { 66 fn push_to_builder(self, builder: &mut Builder) { 67 builder.$method(self as $asT); 68 } 69 } 70 }; 71 } 72 forward_to_builder!(&str, push_str); 73 forward_to_builder!(bool, push_bool); 74 forward_to_builder!(u8, push_uint); 75 forward_to_builder!(u16, push_uint); 76 forward_to_builder!(u32, push_uint); 77 forward_to_builder!(u64, push_uint); 78 forward_to_builder!(i8, push_int); 79 forward_to_builder!(i16, push_int); 80 forward_to_builder!(i32, push_int); 81 forward_to_builder!(i64, push_int); 82 forward_to_builder!(f32, push_float); 83 forward_to_builder!(f64, push_float); 84 forward_to_builder!(&[u8], push_uints); 85 forward_to_builder!(&[u16], push_uints); 86 forward_to_builder!(&[u32], push_uints); 87 forward_to_builder!(&[u64], push_uints); 88 forward_to_builder!(&[i8], push_ints); 89 forward_to_builder!(&[i16], push_ints); 90 forward_to_builder!(&[i32], push_ints); 91 forward_to_builder!(&[i64], push_ints); 92 forward_to_builder!(&[f32], push_floats); 93 forward_to_builder!(&[f64], push_floats); 94 forward_to_builder!(&[bool], push_bools); 95 forward_to_builder!(&Vec<u8>, push_uints); 96 forward_to_builder!(&Vec<u16>, push_uints); 97 forward_to_builder!(&Vec<u32>, push_uints); 98 forward_to_builder!(&Vec<u64>, push_uints); 99 forward_to_builder!(&Vec<i8>, push_ints); 100 forward_to_builder!(&Vec<i16>, push_ints); 101 forward_to_builder!(&Vec<i32>, push_ints); 102 forward_to_builder!(&Vec<i64>, push_ints); 103 forward_to_builder!(&Vec<f32>, push_floats); 104 forward_to_builder!(&Vec<f64>, push_floats); 105 forward_to_builder!(&Vec<bool>, push_bools); 106 107 macro_rules! impl_indirects { 108 ($Indirect: ident, $method: ident) => { 109 impl Sealed for $Indirect {} 110 impl Pushable for $Indirect { 111 fn push_to_builder(self, builder: &mut Builder) { 112 builder.$method(self.0); 113 } 114 } 115 }; 116 } 117 impl_indirects!(IndirectInt, push_indirect_int); 118 impl_indirects!(IndirectUInt, push_indirect_uint); 119 impl_indirects!(IndirectFloat, push_indirect_float); 120 121 macro_rules! impl_arrays { 122 ($num: expr) => { 123 forward_to_builder!(&[u8; $num], push_uints, &[u8]); 124 forward_to_builder!(&[u16; $num], push_uints, &[u16]); 125 forward_to_builder!(&[u32; $num], push_uints, &[u32]); 126 forward_to_builder!(&[u64; $num], push_uints, &[u64]); 127 forward_to_builder!(&[i8; $num], push_ints, &[i8]); 128 forward_to_builder!(&[i16; $num], push_ints, &[i16]); 129 forward_to_builder!(&[i32; $num], push_ints, &[i32]); 130 forward_to_builder!(&[i64; $num], push_ints, &[i64]); 131 forward_to_builder!(&[f32; $num], push_floats, &[f32]); 132 forward_to_builder!(&[f64; $num], push_floats, &[f64]); 133 forward_to_builder!(&[bool; $num], push_bools, &[bool]); 134 }; 135 } 136 impl_arrays!(0); 137 impl_arrays!(1); 138 impl_arrays!(2); 139 impl_arrays!(3); 140 impl_arrays!(4); 141 impl_arrays!(5); 142 impl_arrays!(6); 143 // impl_arrays!(7); 144 // impl_arrays!(8); 145 // impl_arrays!(9); 146 // impl_arrays!(10); 147 // impl_arrays!(11); 148 // impl_arrays!(12); 149 // impl_arrays!(13); 150 // impl_arrays!(14); 151 // impl_arrays!(15); 152 // impl_arrays!(16); 153 // impl_arrays!(17); 154 // impl_arrays!(18); 155 // impl_arrays!(19); 156 // impl_arrays!(20); 157 // impl_arrays!(21); 158 // impl_arrays!(22); 159 // impl_arrays!(23); 160 // impl_arrays!(24); 161 // impl_arrays!(25); 162 // impl_arrays!(26); 163 // impl_arrays!(27); 164 // impl_arrays!(28); 165 // impl_arrays!(29); 166 // impl_arrays!(30); 167 // impl_arrays!(31); 168 // impl_arrays!(32); 169