Austin Schuh | e89fa2d | 2019-08-14 20:24:23 -0700 | [diff] [blame^] | 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 std::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<'a> { |
| 31 | type Inner; |
| 32 | fn follow(buf: &'a [u8], loc: usize) -> Self::Inner; |
| 33 | } |
| 34 | |
| 35 | /// Execute a follow as a top-level function. |
| 36 | #[allow(dead_code)] |
| 37 | #[inline] |
| 38 | pub fn lifted_follow<'a, T: Follow<'a>>(buf: &'a [u8], loc: usize) -> T::Inner { |
| 39 | T::follow(buf, loc) |
| 40 | } |
| 41 | |
| 42 | /// FollowStart wraps a Follow impl in a struct type. This can make certain |
| 43 | /// programming patterns more ergonomic. |
| 44 | #[derive(Debug)] |
| 45 | pub struct FollowStart<T>(PhantomData<T>); |
| 46 | impl<'a, T: Follow<'a> + 'a> FollowStart<T> { |
| 47 | #[inline] |
| 48 | pub fn new() -> Self { |
| 49 | Self { 0: PhantomData } |
| 50 | } |
| 51 | #[inline] |
| 52 | pub fn self_follow(&'a self, buf: &'a [u8], loc: usize) -> T::Inner { |
| 53 | T::follow(buf, loc) |
| 54 | } |
| 55 | } |
| 56 | impl<'a, T: Follow<'a>> Follow<'a> for FollowStart<T> { |
| 57 | type Inner = T::Inner; |
| 58 | #[inline] |
| 59 | fn follow(buf: &'a [u8], loc: usize) -> Self::Inner { |
| 60 | T::follow(buf, loc) |
| 61 | } |
| 62 | } |