1 /* 2 * Copyright 2016 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 module flatbuffers.table; 18 19 import flatbuffers.exception; 20 import flatbuffers.bytebuffer; 21 public import std.typecons; 22 23 /// Mixin this template to all structs in the generated code derive , and add their own accessors. 24 mixin template Struct(ParentType) 25 { 26 /** 27 Create this Struct. 28 */ 29 static ParentType init_(size_t pos, ByteBuffer buffer) 30 { 31 return ParentType(buffer, pos); 32 } 33 34 private: // Variables. 35 /** 36 disable the constor. 37 */ 38 @disable this(); 39 this(ByteBuffer buffer, size_t pos) 40 { 41 this._buffer = buffer; 42 this._pos = pos; 43 } 44 45 ByteBuffer _buffer; 46 size_t _pos; 47 } 48 49 /// Mixin this template to all tables in the generated code derive , and add their own accessors. 50 mixin template Table(ParentType) 51 { 52 /** 53 Create this Struct as a Table. 54 */ 55 static ParentType init_(size_t pos, ByteBuffer buffer) 56 { 57 return ParentType(buffer, pos); 58 } 59 60 private: 61 ByteBuffer _buffer; 62 size_t _pos; 63 64 private: // Methods. 65 @disable this(); 66 this(ByteBuffer buffer, size_t pos) 67 { 68 this._buffer = buffer; 69 this._pos = pos; 70 } 71 72 /// Look up a field in the vtable, return an offset into the object, or 0 if the field is not present. 73 uint __offset(size_t vtableOffset) 74 { 75 auto vtable = _pos - _buffer.get!int(_pos); 76 return vtableOffset < _buffer.get!short(vtable) ? cast( 77 uint) _buffer.get!short(vtable + vtableOffset) : 0; 78 } 79 80 /// Retrieve the relative offset stored at "offset". 81 uint __indirect(size_t offset) 82 { 83 return cast(uint)(offset + _buffer.get!int(offset)); 84 } 85 86 /// Create a D string from UTF-8 data stored inside the flatbuffer. 87 string __string(size_t offset) 88 { 89 offset += _buffer.get!int(offset); 90 auto len = _buffer.get!uint(offset); 91 auto startPos = offset + uint.sizeof; 92 return cast(string) _buffer.data[startPos .. startPos + len]; 93 } 94 95 /// Get the length of a vector whose offset is stored at "offset" in this object. 96 uint __vector_len(size_t offset) 97 { 98 offset += _pos; 99 offset += _buffer.get!int(offset); 100 return _buffer.get!uint(offset); 101 } 102 103 /// Get the start of data of a vector whose offset is stored at "offset" in this object. 104 uint __dvector(size_t offset) 105 { 106 offset += _pos; 107 return cast(uint)(offset + _buffer.get!int(offset) + int.sizeof); // Data starts after the length. 108 } 109 110 /// Initialize any Table-derived type to point to the union at the given offset. 111 T __union(T)(size_t offset) 112 { 113 offset += _pos; 114 return T.init_((offset + _buffer.get!int(offset)), _buffer); 115 } 116 117 static bool __has_identifier(ByteBuffer bb, string ident) 118 { 119 import std.string; 120 121 if (ident.length != fileIdentifierLength) 122 throw new ArgumentException( 123 format("FlatBuffers: file identifier must be length %s.", fileIdentifierLength), 124 "ident"); 125 126 for (auto i = 0; i < fileIdentifierLength; i++) 127 { 128 if (ident[i] != cast(char) bb.get!byte(bb.position() + cast(uint)uint.sizeof + i)) 129 return false; 130 } 131 132 return true; 133 } 134 } 135 136 import std.traits; 137 138 /** 139 Iterator for the vector. 140 */ 141 struct Iterator(ParentType, ReturnType, string accessor) 142 { 143 static if (isScalarType!(ReturnType) || isSomeString!(ReturnType)) 144 alias ApplyType = ReturnType; 145 else 146 alias ApplyType = Nullable!ReturnType; 147 private: 148 ParentType parent; 149 int index; 150 public: 151 this(ParentType parent) 152 { 153 this.parent = parent; 154 } 155 156 @property int length() 157 { 158 mixin("return parent." ~ accessor ~ "Length;"); 159 } 160 161 @property bool empty() 162 { 163 return index == length; 164 } 165 166 @property ReturnType popFront() 167 { 168 mixin("return parent." ~ accessor ~ "(++index);"); 169 } 170 171 @property ReturnType front() 172 { 173 mixin("return parent." ~ accessor ~ "(index);"); 174 } 175 176 ReturnType opIndex(int index) 177 { 178 mixin("return parent." ~ accessor ~ "(index);"); 179 } 180 181 int opApply(int delegate(ApplyType) operations) 182 { 183 int result = 0; 184 for (int number = 0; number < length(); ++number) 185 { 186 static if (isScalarType!(ReturnType) || isSomeString!(ReturnType)) 187 result = operations(opIndex(number)); 188 else 189 mixin("result = operations(parent." ~ accessor ~ "(number));"); 190 if (result) 191 break; 192 } 193 return result; 194 } 195 196 int opApply(int delegate(int, ApplyType) operations) 197 { 198 int result = 0; 199 for (int number = 0; number < length(); ++number) 200 { 201 static if (isScalarType!(ReturnType) || isSomeString!(ReturnType)) 202 result = operations(number, opIndex(number)); 203 else 204 mixin("result = operations(number, parent." ~ accessor ~ "(number));"); 205 if (result) 206 break; 207 } 208 return result; 209 } 210 }