diff --git a/swift/Sources/FlatBuffers/ByteBuffer.swift b/swift/Sources/FlatBuffers/ByteBuffer.swift index be629db4ad8..92778f41151 100644 --- a/swift/Sources/FlatBuffers/ByteBuffer.swift +++ b/swift/Sources/FlatBuffers/ByteBuffer.swift @@ -217,6 +217,22 @@ public struct ByteBuffer { _writerSize = capacity } + /// Constructor that creates a Flatbuffer from unsafe memory region by copying + /// the underlying data to a new pointer + /// + /// - Parameters: + /// - copyingMemoryBound: The unsafe memory region + /// - capacity: The size of the given memory region + @inline(__always) + public init( + copyingMemoryBound memory: UnsafeMutableRawPointer, + capacity: Int) + { + _storage = Storage(count: capacity, alignment: alignment) + _storage.copy(from: memory, count: capacity) + _writerSize = _storage.capacity + } + /// Creates a copy of the existing flatbuffer, by copying it to a different memory. /// - Parameters: /// - memory: Current memory of the buffer diff --git a/swift/Sources/FlatBuffers/FlatBufferBuilder.swift b/swift/Sources/FlatBuffers/FlatBufferBuilder.swift index 98cf863c4d3..95e9accdc9f 100644 --- a/swift/Sources/FlatBuffers/FlatBufferBuilder.swift +++ b/swift/Sources/FlatBuffers/FlatBufferBuilder.swift @@ -98,7 +98,7 @@ public struct FlatBufferBuilder { public var sizedBuffer: ByteBuffer { assert(finished, "Data shouldn't be called before finish()") return ByteBuffer( - assumingMemoryBound: _bb.memory.advanced(by: _bb.reader), + copyingMemoryBound: _bb.memory.advanced(by: _bb.reader), capacity: Int(_bb.size)) } diff --git a/tests/swift/tests/Tests/FlatBuffers.Test.SwiftTests/ByteBufferTests.swift b/tests/swift/tests/Tests/FlatBuffers.Test.SwiftTests/ByteBufferTests.swift new file mode 100644 index 00000000000..03ee2af1ffa --- /dev/null +++ b/tests/swift/tests/Tests/FlatBuffers.Test.SwiftTests/ByteBufferTests.swift @@ -0,0 +1,52 @@ +/* + * Copyright 2024 Google Inc. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import XCTest +@testable import FlatBuffers + +final class ByteBufferTests: XCTestCase { + func testCopyingMemory() { + let count = 100 + let ptr = UnsafeMutableRawPointer.allocate(byteCount: count, alignment: 1) + let byteBuffer = ByteBuffer(copyingMemoryBound: ptr, capacity: count) + XCTAssertNotEqual(byteBuffer.memory, ptr) + } + + func testSamePointer() { + let count = 100 + let ptr = UnsafeMutableRawPointer.allocate(byteCount: count, alignment: 1) + let byteBuffer = ByteBuffer(assumingMemoryBound: ptr, capacity: count) + XCTAssertEqual(byteBuffer.memory, ptr) + } + + func testSameDataPtr() { + let count = 100 + let ptr = Data(repeating: 0, count: count) + let byteBuffer = ByteBuffer(data: ptr) + ptr.withUnsafeBytes { ptr in + XCTAssertEqual(byteBuffer.memory, ptr.baseAddress) + } + } + + func testSameArrayPtr() { + let count = 100 + let ptr: [UInt8] = Array(repeating: 0, count: count) + let byteBuffer = ByteBuffer(bytes: ptr) + ptr.withUnsafeBytes { ptr in + XCTAssertEqual(byteBuffer.memory, ptr.baseAddress) + } + } +}