1 import Foundation
2 
3 public struct Table {
4     public private(set) var bb: ByteBuffer
5     public private(set) var postion: Int32
6 
7     public init(bb: ByteBuffer, position: Int32 = 0) {
8         guard isLitteEndian else {
9             fatalError("Reading/Writing a buffer in big endian machine is not supported on swift")
10         }
11         self.bb = bb
12         self.postion = position
13     }
14 
offsetnull15     public func offset(_ o: Int32) -> Int32 {
16         let vtable = postion - bb.read(def: Int32.self, position: Int(postion))
17         return o < bb.read(def: VOffset.self, position: Int(vtable)) ? Int32(bb.read(def: Int16.self, position: Int(vtable + o))) : 0
18     }
19 
indirectnull20     public func indirect(_ o: Int32) -> Int32 { return o + bb.read(def: Int32.self, position: Int(o)) }
21 
22     /// String reads from the buffer with respect to position of the current table.
23     /// - Parameter offset: Offset of the string
stringnull24     public func string(at offset: Int32) -> String? {
25         return directString(at: offset + postion)
26     }
27 
28     /// Direct string reads from the buffer disregarding the position of the table.
29     /// It would be preferable to use string unless the current position of the table is not needed
30     /// - Parameter offset: Offset of the string
directStringnull31     public func directString(at offset: Int32) -> String? {
32          var offset = offset
33          offset += bb.read(def: Int32.self, position: Int(offset))
34          let count = bb.read(def: Int32.self, position: Int(offset))
35          let position = offset + Int32(MemoryLayout<Int32>.size)
36          return bb.readString(at: position, count: count)
37     }
38 
39     /// Reads from the buffer with respect to the position in the table.
40     /// - Parameters:
41     ///   - type: Type of Scalar that needs to be read from the buffer
42     ///   - o: Offset of the Element
readBuffer<T: Scalar>null43     public func readBuffer<T: Scalar>(of type: T.Type, at o: Int32) -> T {
44         return directRead(of: T.self, offset: o + postion)
45     }
46 
47     /// Reads from the buffer disregarding the position of the table.
48     /// It would be used when reading from an
49     ///   ```
50     ///   let offset = __t.offset(10)
51     ///   //Only used when the we already know what is the
52     ///   // position in the table since __t.vector(at:)
53     ///   // returns the index with respect to the position
54     ///   __t.directRead(of: Byte.self,
55     ///                  offset: __t.vector(at: offset) + index * 1)
56     ///   ```
57     /// - Parameters:
58     ///   - type: Type of Scalar that needs to be read from the buffer
59     ///   - o: Offset of the Element
directRead<T: Scalar>null60     public func directRead<T: Scalar>(of type: T.Type, offset o: Int32) -> T {
61         let r = bb.read(def: T.self, position: Int(o))
62         return r
63     }
64 
union<T: FlatBufferObject>null65     public func union<T: FlatBufferObject>(_ o: Int32) -> T {
66         let o = o + postion
67         return directUnion(o)
68     }
69 
directUnion<T: FlatBufferObject>null70     public func directUnion<T: FlatBufferObject>(_ o: Int32) -> T {
71         return T.init(bb, o: o + bb.read(def: Int32.self, position: Int(o)))
72     }
73 
getVector<T>null74     public func getVector<T>(at off: Int32) -> [T]? {
75         let o = offset(off)
76         guard o != 0 else { return nil }
77         return bb.readSlice(index: vector(at: o), count: vector(count: o))
78     }
79 
80     /// Vector count gets the count of Elements within the array
81     /// - Parameter o: start offset of the vector
82     /// - returns: Count of elements
vectornull83     public func vector(count o: Int32) -> Int32 {
84         var o = o
85         o += postion
86         o += bb.read(def: Int32.self, position: Int(o))
87         return bb.read(def: Int32.self, position: Int(o))
88     }
89 
90     /// Vector start index in the buffer
91     /// - Parameter o:start offset of the vector
92     /// - returns: the start index of the vector
vectornull93     public func vector(at o: Int32) -> Int32 {
94         var o = o
95         o += postion
96         return o + bb.read(def: Int32.self, position: Int(o)) + 4
97     }
98 }
99 
100 extension Table {
101 
indirectnull102     static public func indirect(_ o: Int32, _ fbb: ByteBuffer) -> Int32 { return o + fbb.read(def: Int32.self, position: Int(o)) }
103 
offsetnull104     static public func offset(_ o: Int32, vOffset: Int32, fbb: ByteBuffer) -> Int32 {
105         let vTable = Int32(fbb.capacity) - o
106         return vTable + Int32(fbb.read(def: Int16.self, position: Int(vTable + vOffset - fbb.read(def: Int32.self, position: Int(vTable)))))
107     }
108 
comparenull109     static public func compare(_ off1: Int32, _ off2: Int32, fbb: ByteBuffer) -> Int32 {
110         let memorySize = Int32(MemoryLayout<Int32>.size)
111         let _off1 = off1 + fbb.read(def: Int32.self, position: Int(off1))
112         let _off2 = off2 + fbb.read(def: Int32.self, position: Int(off2))
113         let len1 = fbb.read(def: Int32.self, position: Int(_off1))
114         let len2 = fbb.read(def: Int32.self, position: Int(_off2))
115         let startPos1 = _off1 + memorySize
116         let startPos2 = _off2 + memorySize
117         let minValue = min(len1, len2)
118         for i in 0...minValue {
119             let b1 = fbb.read(def: Int8.self, position: Int(i + startPos1))
120             let b2 = fbb.read(def: Int8.self, position: Int(i + startPos2))
121             if b1 != b2 {
122                 return Int32(b2 - b1)
123             }
124         }
125         return len1 - len2
126     }
127 
comparenull128     static public func compare(_ off1: Int32, _ key: [Byte], fbb: ByteBuffer) -> Int32 {
129         let memorySize = Int32(MemoryLayout<Int32>.size)
130         let _off1 = off1 + fbb.read(def: Int32.self, position: Int(off1))
131         let len1 = fbb.read(def: Int32.self, position: Int(_off1))
132         let len2 = Int32(key.count)
133         let startPos1 = _off1 + memorySize
134         let minValue = min(len1, len2)
135         for i in 0..<minValue {
136             let b = fbb.read(def: Int8.self, position: Int(i + startPos1))
137             let byte = key[Int(i)]
138             if b != byte {
139                 return Int32(b - Int8(byte))
140             }
141         }
142         return len1 - len2
143     }
144 }
145