1 /* 2 * Copyright 2018 Google Inc. All rights reserved. 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 use core::marker::PhantomData; 18 19 /// Follow is a trait that allows us to access FlatBuffers in a declarative, 20 /// type safe, and fast way. They compile down to almost no code (after 21 /// optimizations). Conceptually, Follow lifts the offset-based access 22 /// patterns of FlatBuffers data into the type system. This trait is used 23 /// pervasively at read time, to access tables, vtables, vectors, strings, and 24 /// all other data. At this time, Follow is not utilized much on the write 25 /// path. 26 /// 27 /// Writing a new Follow implementation primarily involves deciding whether 28 /// you want to return data (of the type Self::Inner) or do you want to 29 /// continue traversing the FlatBuffer. 30 pub trait Follow<'buf> { 31 type Inner; 32 /// # Safety 33 /// 34 /// `buf[loc..]` must contain a valid value of `Self` and anything it 35 /// transitively refers to by offset must also be valid follow(buf: &'buf [u8], loc: usize) -> Self::Inner36 unsafe fn follow(buf: &'buf [u8], loc: usize) -> Self::Inner; 37 } 38 39 /// FollowStart wraps a Follow impl in a struct type. This can make certain 40 /// programming patterns more ergonomic. 41 #[derive(Debug, Default)] 42 pub struct FollowStart<T>(PhantomData<T>); 43 impl<'a, T: Follow<'a> + 'a> FollowStart<T> { 44 #[inline] new() -> Self45 pub fn new() -> Self { 46 Self(PhantomData) 47 } 48 49 /// # Safety 50 /// 51 /// `buf[loc..]` must contain a valid value of `T` 52 #[inline] self_follow(&'a self, buf: &'a [u8], loc: usize) -> T::Inner53 pub unsafe fn self_follow(&'a self, buf: &'a [u8], loc: usize) -> T::Inner { 54 T::follow(buf, loc) 55 } 56 } 57 impl<'a, T: Follow<'a>> Follow<'a> for FollowStart<T> { 58 type Inner = T::Inner; 59 #[inline] follow(buf: &'a [u8], loc: usize) -> Self::Inner60 unsafe fn follow(buf: &'a [u8], loc: usize) -> Self::Inner { 61 T::follow(buf, loc) 62 } 63 } 64