String+extension.swift (3294B)
1 /* 2 * Copyright 2023 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 #if !os(WASI) 18 import Foundation 19 #else 20 import SwiftOverlayShims 21 #endif 22 23 extension String: Verifiable { 24 25 /// Verifies that the current value is which the bounds of the buffer, and if 26 /// the current `Value` is aligned properly 27 /// - Parameters: 28 /// - verifier: Verifier that hosts the buffer 29 /// - position: Current position within the buffer 30 /// - type: The type of the object to be verified 31 /// - Throws: Errors coming from `inBuffer`, `missingNullTerminator` and `outOfBounds` 32 public static func verify<T>( 33 _ verifier: inout Verifier, 34 at position: Int, 35 of type: T.Type) throws where T: Verifiable 36 { 37 38 let range = try String.verifyRange(&verifier, at: position, of: UInt8.self) 39 /// Safe &+ since we already check for overflow in verify range 40 let stringLen = range.start &+ range.count 41 42 if stringLen >= verifier.capacity { 43 throw FlatbuffersErrors.outOfBounds( 44 position: UInt(clamping: stringLen.magnitude), 45 end: verifier.capacity) 46 } 47 48 let isNullTerminated = verifier._buffer.read( 49 def: UInt8.self, 50 position: stringLen) == 0 51 52 if !verifier._options._ignoreMissingNullTerminators && !isNullTerminated { 53 let str = verifier._buffer.readString(at: range.start, count: range.count) 54 throw FlatbuffersErrors.missingNullTerminator( 55 position: position, 56 str: str) 57 } 58 } 59 } 60 61 extension String: FlatbuffersInitializable { 62 63 /// Initailizes a string from a Flatbuffers ByteBuffer 64 /// - Parameters: 65 /// - bb: ByteBuffer containing the readable string 66 /// - o: Current position 67 public init(_ bb: ByteBuffer, o: Int32) { 68 let v = Int(o) 69 let count = bb.read(def: Int32.self, position: v) 70 self = bb.readString( 71 at: MemoryLayout<Int32>.size + v, 72 count: Int(count)) ?? "" 73 } 74 } 75 76 extension String: ObjectAPIPacker { 77 78 public static func pack( 79 _ builder: inout FlatBufferBuilder, 80 obj: inout String?) -> Offset 81 { 82 guard var obj = obj else { return Offset() } 83 return pack(&builder, obj: &obj) 84 } 85 86 public static func pack( 87 _ builder: inout FlatBufferBuilder, 88 obj: inout String) -> Offset 89 { 90 builder.create(string: obj) 91 } 92 93 public mutating func unpack() -> String { 94 self 95 } 96 97 } 98 99 extension String: NativeObject { 100 101 public func serialize<T: ObjectAPIPacker>(type: T.Type) -> ByteBuffer 102 where T.T == Self 103 { 104 fatalError("serialize should never be called from string directly") 105 } 106 107 public func serialize<T: ObjectAPIPacker>( 108 builder: inout FlatBufferBuilder, 109 type: T.Type) -> ByteBuffer where T.T == Self 110 { 111 fatalError("serialize should never be called from string directly") 112 } 113 }