blob: 0f783bfebb907acead86e06aa492835963124749 [file] [log] [blame]
Austin Schuh272c6132020-11-14 16:37:52 -08001import Foundation
2
3public 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
15 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
20 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
24 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
31 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
43 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
60 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
65 public func union<T: FlatBufferObject>(_ o: Int32) -> T {
66 let o = o + postion
67 return directUnion(o)
68 }
69
70 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
74 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
83 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
93 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
100extension Table {
101
102 static public func indirect(_ o: Int32, _ fbb: ByteBuffer) -> Int32 { return o + fbb.read(def: Int32.self, position: Int(o)) }
103
104 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
109 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
128 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}