1*890232f2SAndroid Build Coastguard Worker /* 2*890232f2SAndroid Build Coastguard Worker * Copyright 2021 Google Inc. All rights reserved. 3*890232f2SAndroid Build Coastguard Worker * 4*890232f2SAndroid Build Coastguard Worker * Licensed under the Apache License, Version 2.0 (the "License"); 5*890232f2SAndroid Build Coastguard Worker * you may not use this file except in compliance with the License. 6*890232f2SAndroid Build Coastguard Worker * You may obtain a copy of the License at 7*890232f2SAndroid Build Coastguard Worker * 8*890232f2SAndroid Build Coastguard Worker * http://www.apache.org/licenses/LICENSE-2.0 9*890232f2SAndroid Build Coastguard Worker * 10*890232f2SAndroid Build Coastguard Worker * Unless required by applicable law or agreed to in writing, software 11*890232f2SAndroid Build Coastguard Worker * distributed under the License is distributed on an "AS IS" BASIS, 12*890232f2SAndroid Build Coastguard Worker * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13*890232f2SAndroid Build Coastguard Worker * See the License for the specific language governing permissions and 14*890232f2SAndroid Build Coastguard Worker * limitations under the License. 15*890232f2SAndroid Build Coastguard Worker */ 16*890232f2SAndroid Build Coastguard Worker 17*890232f2SAndroid Build Coastguard Worker #if !os(WASI) 18*890232f2SAndroid Build Coastguard Worker import Foundation 19*890232f2SAndroid Build Coastguard Worker #else 20*890232f2SAndroid Build Coastguard Worker import SwiftOverlayShims 21*890232f2SAndroid Build Coastguard Worker #endif 22*890232f2SAndroid Build Coastguard Worker 23*890232f2SAndroid Build Coastguard Worker extension String: Verifiable { 24*890232f2SAndroid Build Coastguard Worker 25*890232f2SAndroid Build Coastguard Worker /// Verifies that the current value is which the bounds of the buffer, and if 26*890232f2SAndroid Build Coastguard Worker /// the current `Value` is aligned properly 27*890232f2SAndroid Build Coastguard Worker /// - Parameters: 28*890232f2SAndroid Build Coastguard Worker /// - verifier: Verifier that hosts the buffer 29*890232f2SAndroid Build Coastguard Worker /// - position: Current position within the buffer 30*890232f2SAndroid Build Coastguard Worker /// - type: The type of the object to be verified 31*890232f2SAndroid Build Coastguard Worker /// - Throws: Errors coming from `inBuffer`, `missingNullTerminator` and `outOfBounds` 32*890232f2SAndroid Build Coastguard Worker public static func verify<T>( 33*890232f2SAndroid Build Coastguard Worker _ verifier: inout Verifier, 34*890232f2SAndroid Build Coastguard Worker at position: Int, 35*890232f2SAndroid Build Coastguard Worker of type: T.Type) throws where T: Verifiable 36*890232f2SAndroid Build Coastguard Worker { 37*890232f2SAndroid Build Coastguard Worker 38*890232f2SAndroid Build Coastguard Worker let range = try String.verifyRange(&verifier, at: position, of: UInt8.self) 39*890232f2SAndroid Build Coastguard Worker /// Safe &+ since we already check for overflow in verify range 40*890232f2SAndroid Build Coastguard Worker let stringLen = range.start &+ range.count 41*890232f2SAndroid Build Coastguard Worker 42*890232f2SAndroid Build Coastguard Worker if stringLen >= verifier.capacity { 43*890232f2SAndroid Build Coastguard Worker throw FlatbuffersErrors.outOfBounds( 44*890232f2SAndroid Build Coastguard Worker position: UInt(clamping: stringLen.magnitude), 45*890232f2SAndroid Build Coastguard Worker end: verifier.capacity) 46*890232f2SAndroid Build Coastguard Worker } 47*890232f2SAndroid Build Coastguard Worker 48*890232f2SAndroid Build Coastguard Worker let isNullTerminated = verifier._buffer.read( 49*890232f2SAndroid Build Coastguard Worker def: UInt8.self, 50*890232f2SAndroid Build Coastguard Worker position: stringLen) == 0 51*890232f2SAndroid Build Coastguard Worker 52*890232f2SAndroid Build Coastguard Worker if !verifier._options._ignoreMissingNullTerminators && !isNullTerminated { 53*890232f2SAndroid Build Coastguard Worker let str = verifier._buffer.readString(at: range.start, count: range.count) 54*890232f2SAndroid Build Coastguard Worker throw FlatbuffersErrors.missingNullTerminator( 55*890232f2SAndroid Build Coastguard Worker position: position, 56*890232f2SAndroid Build Coastguard Worker str: str) 57*890232f2SAndroid Build Coastguard Worker } 58*890232f2SAndroid Build Coastguard Worker } 59*890232f2SAndroid Build Coastguard Worker } 60*890232f2SAndroid Build Coastguard Worker 61*890232f2SAndroid Build Coastguard Worker extension String: FlatbuffersInitializable { 62*890232f2SAndroid Build Coastguard Worker 63*890232f2SAndroid Build Coastguard Worker /// Initailizes a string from a Flatbuffers ByteBuffer 64*890232f2SAndroid Build Coastguard Worker /// - Parameters: 65*890232f2SAndroid Build Coastguard Worker /// - bb: ByteBuffer containing the readable string 66*890232f2SAndroid Build Coastguard Worker /// - o: Current position 67*890232f2SAndroid Build Coastguard Worker public init(_ bb: ByteBuffer, o: Int32) { 68*890232f2SAndroid Build Coastguard Worker let v = Int(o) 69*890232f2SAndroid Build Coastguard Worker let count = bb.read(def: Int32.self, position: v) 70*890232f2SAndroid Build Coastguard Worker self = bb.readString( 71*890232f2SAndroid Build Coastguard Worker at: MemoryLayout<Int32>.size + v, 72*890232f2SAndroid Build Coastguard Worker count: Int(count)) ?? "" 73*890232f2SAndroid Build Coastguard Worker } 74*890232f2SAndroid Build Coastguard Worker } 75*890232f2SAndroid Build Coastguard Worker 76*890232f2SAndroid Build Coastguard Worker extension String: ObjectAPIPacker { 77*890232f2SAndroid Build Coastguard Worker 78*890232f2SAndroid Build Coastguard Worker public static func pack( 79*890232f2SAndroid Build Coastguard Worker _ builder: inout FlatBufferBuilder, 80*890232f2SAndroid Build Coastguard Worker obj: inout String?) -> Offset 81*890232f2SAndroid Build Coastguard Worker { 82*890232f2SAndroid Build Coastguard Worker guard var obj = obj else { return Offset() } 83*890232f2SAndroid Build Coastguard Worker return pack(&builder, obj: &obj) 84*890232f2SAndroid Build Coastguard Worker } 85*890232f2SAndroid Build Coastguard Worker 86*890232f2SAndroid Build Coastguard Worker public static func pack( 87*890232f2SAndroid Build Coastguard Worker _ builder: inout FlatBufferBuilder, 88*890232f2SAndroid Build Coastguard Worker obj: inout String) -> Offset 89*890232f2SAndroid Build Coastguard Worker { 90*890232f2SAndroid Build Coastguard Worker builder.create(string: obj) 91*890232f2SAndroid Build Coastguard Worker } 92*890232f2SAndroid Build Coastguard Worker unpacknull93*890232f2SAndroid Build Coastguard Worker public mutating func unpack() -> String { 94*890232f2SAndroid Build Coastguard Worker self 95*890232f2SAndroid Build Coastguard Worker } 96*890232f2SAndroid Build Coastguard Worker 97*890232f2SAndroid Build Coastguard Worker } 98*890232f2SAndroid Build Coastguard Worker 99*890232f2SAndroid Build Coastguard Worker extension String: NativeObject { 100*890232f2SAndroid Build Coastguard Worker serialize<T: ObjectAPIPacker>null101*890232f2SAndroid Build Coastguard Worker public func serialize<T: ObjectAPIPacker>(type: T.Type) -> ByteBuffer 102*890232f2SAndroid Build Coastguard Worker where T.T == Self 103*890232f2SAndroid Build Coastguard Worker { 104*890232f2SAndroid Build Coastguard Worker fatalError("serialize should never be called from string directly") 105*890232f2SAndroid Build Coastguard Worker } 106*890232f2SAndroid Build Coastguard Worker 107*890232f2SAndroid Build Coastguard Worker public func serialize<T: ObjectAPIPacker>( 108*890232f2SAndroid Build Coastguard Worker builder: inout FlatBufferBuilder, 109*890232f2SAndroid Build Coastguard Worker type: T.Type) -> ByteBuffer where T.T == Self 110*890232f2SAndroid Build Coastguard Worker { 111*890232f2SAndroid Build Coastguard Worker fatalError("serialize should never be called from string directly") 112*890232f2SAndroid Build Coastguard Worker } 113*890232f2SAndroid Build Coastguard Worker } 114