//===--- UnsafeRawBufferPointer.swift.gyb ---------------------*- swift -*-===// // // This source file is part of the Swift.org open source project // // Copyright (c) 2014 - 2025 Apple Inc. and the Swift project authors // Licensed under Apache License v2.0 with Runtime Library Exception // // See https://swift.org/LICENSE.txt for license information // See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors // //===----------------------------------------------------------------------===// %import gyb % for mutable in (True, False): % Self = 'UnsafeMutableRawBufferPointer' if mutable else 'UnsafeRawBufferPointer' % Mutable = 'Mutable' if mutable else '' /// A ${Mutable.lower()} nonowning collection interface to the bytes in a /// region of memory. /// /// You can use an `${Self}` instance in low-level operations to eliminate /// uniqueness checks and release mode bounds checks. Bounds checks are always /// performed in debug mode. /// % if mutable: /// An `${Self}` instance is a view of the raw bytes in a region of memory. /// Each byte in memory is viewed as a `UInt8` value independent of the type /// of values held in that memory. Reading from and writing to memory through /// a raw buffer are untyped operations. Accessing this collection's bytes /// does not bind the underlying memory to `UInt8`. /// /// In addition to its collection interface, an `${Self}` /// instance also supports the following methods provided by /// `UnsafeMutableRawPointer`, including bounds checks in debug mode: /// /// - `load(fromByteOffset:as:)` /// - `loadUnaligned(fromByteOffset:as:)` /// - `storeBytes(of:toByteOffset:as:)` /// - `copyMemory(from:)` % else: /// An `${Self}` instance is a view of the raw bytes in a region of memory. /// Each byte in memory is viewed as a `UInt8` value independent of the type /// of values held in that memory. Reading from memory through a raw buffer is /// an untyped operation. /// /// In addition to its collection interface, an `${Self}` /// instance also supports the `load(fromByteOffset:as:)` /// and `loadUnaligned(fromByteOffset:as:)` methods provided by /// `UnsafeRawPointer`, including bounds checks in debug mode. % end /// /// To access the underlying memory through typed operations, the memory must /// be bound to a trivial type. /// /// - Note: A *trivial type* can be copied bit for bit with no indirection /// or reference-counting operations. Generally, native Swift types that do /// not contain strong or weak references or other forms of indirection are /// trivial, as are imported C structs and enums. Copying memory that /// contains values of nontrivial types can only be done safely with a typed /// pointer. Copying bytes directly from nontrivial, in-memory values does /// not produce valid copies and can only be done by calling a C API, such as /// `memmove()`. /// /// ${Self} Semantics /// ================= /// /// An `${Self}` instance is a view into memory and does not own the memory /// that it references. Copying a variable or constant of type `${Self}` does /// not copy the underlying memory. However, initializing another collection /// with an `${Self}` instance copies bytes out of the referenced memory and /// into the new collection. /// /// The following example uses `someBytes`, an `${Self}` instance, to /// demonstrate the difference between assigning a buffer pointer and using a /// buffer pointer as the source for another collection's elements. Here, the /// assignment to `destBytes` creates a new, nonowning buffer pointer /// covering the first `n` bytes of the memory that `someBytes` /// references---nothing is copied: /// /// var destBytes = someBytes[0..= 0, "${Self} with negative count") _debugPrecondition(unsafe count == 0 || start != nil, "${Self} has a nil start and nonzero count") unsafe self.init(_uncheckedStart: start, count: count) } @safe @_transparent @_alwaysEmitIntoClient public init(_empty: ()) { unsafe _position = nil unsafe _end = nil } } @available(*, unavailable) extension Unsafe${Mutable}RawBufferPointer: Sendable {} %if not mutable: extension UnsafeRawBufferPointer { /// An iterator over the bytes viewed by a raw buffer pointer. @frozen @unsafe public struct Iterator { @usableFromInline internal var _position, _end: UnsafeRawPointer? @inlinable @_transparent internal init(_position: UnsafeRawPointer?, _end: UnsafeRawPointer?) { unsafe self._position = _position unsafe self._end = _end } } } @available(*, unavailable) extension UnsafeRawBufferPointer.Iterator: Sendable { } extension UnsafeRawBufferPointer.Iterator: @unsafe IteratorProtocol, @unsafe Sequence { /// Advances to the next byte and returns it, or `nil` if no next byte /// exists. /// /// Once `nil` has been returned, all subsequent calls return `nil`. /// /// - Returns: The next sequential byte in the raw buffer if another byte /// exists; otherwise, `nil`. @inlinable public mutating func next() -> UInt8? { guard let position = unsafe _position else { return nil } // We can do an unchecked unwrap here by borrowing invariants from the pointer. // For a validly constructed buffer pointer, the only way _end can be nil is // if _position is also nil. We checked that case above. // Thus, we can safely do an unchecked unwrap here. // We check these invariants in debug builds to defend against invalidly constructed // pointers. _debugPrecondition(unsafe _end != nil) let end = unsafe _end._unsafelyUnwrappedUnchecked if unsafe position == end { return nil } _debugPrecondition(unsafe position < end) let result = unsafe position.load(as: UInt8.self) // Validly constructed buffer pointers also have an _end that is strictly // greater than or equal to _position. // So we do not need to do checked arithmetic here as we cannot possibly overflow. unsafe _position = position + 1 return result } } %else: extension UnsafeMutableRawBufferPointer { public typealias Iterator = UnsafeRawBufferPointer.Iterator } %end extension Unsafe${Mutable}RawBufferPointer: @unsafe Sequence { public typealias SubSequence = Slice<${Self}> /// Returns an iterator over the bytes of this sequence. @inlinable public func makeIterator() -> Iterator { return unsafe Iterator(_position: _position, _end: _end) } /// Copies the elements of `self` to the memory at `destination.baseAddress`, /// stopping when either `self` or `destination` is exhausted. /// /// - Returns: an iterator over any remaining elements of `self` and the /// number of elements copied. @_alwaysEmitIntoClient public func _copyContents( initializing destination: UnsafeMutableBufferPointer ) -> (Iterator, UnsafeMutableBufferPointer.Index) { guard let s = unsafe _position, let e = unsafe _end, unsafe e > s, !destination.isEmpty else { return (unsafe makeIterator(), 0) } let destinationAddress = unsafe destination.baseAddress._unsafelyUnwrappedUnchecked let d = UnsafeMutableRawPointer(destinationAddress) let n = Swift.min(destination.count, unsafe s.distance(to: e)) unsafe d.copyMemory(from: s, byteCount: n) return (unsafe Iterator(_position: unsafe s.advanced(by: n), _end: e), n) } } extension Unsafe${Mutable}RawBufferPointer: @unsafe ${Mutable}Collection { // TODO: Specialize `index` and `formIndex` and // `_failEarlyRangeCheck` as in `UnsafeBufferPointer`. public typealias Element = UInt8 public typealias Index = Int public typealias Indices = Range /// Always zero, which is the index of the first byte in a nonempty buffer. @inlinable @safe public var startIndex: Index { return 0 } /// The "past the end" position---that is, the position one greater than the /// last valid subscript argument. /// /// The `endIndex` property of an `Unsafe${Mutable}RawBufferPointer` /// instance is always identical to `count`. @inlinable @safe public var endIndex: Index { return count } @inlinable @safe public var indices: Indices { // Not checked because init forbids negative count. return unsafe Indices(uncheckedBounds: (startIndex, endIndex)) } /// Accesses the byte at the given offset in the memory region as a `UInt8` /// value. /// /// - Parameter i: The offset of the byte to access. `i` must be in the range /// `0.. Element { get { _debugPrecondition(i >= 0) _debugPrecondition(i < endIndex) return unsafe _position._unsafelyUnwrappedUnchecked.load(fromByteOffset: i, as: UInt8.self) } % if mutable: nonmutating set { _debugPrecondition(i >= 0) _debugPrecondition(i < endIndex) unsafe _position._unsafelyUnwrappedUnchecked.storeBytes(of: newValue, toByteOffset: i, as: UInt8.self) } % end # mutable } /// Accesses the bytes in the specified memory region. /// /// - Parameter bounds: The range of byte offsets to access. The upper and /// lower bounds of the range must be in the range `0...count`. @inlinable public subscript(bounds: Range) -> SubSequence { get { _debugPrecondition(bounds.lowerBound >= startIndex) _debugPrecondition(bounds.upperBound <= endIndex) return unsafe Slice(base: self, bounds: bounds) } % if mutable: nonmutating set { _debugPrecondition(bounds.lowerBound >= startIndex) _debugPrecondition(bounds.upperBound <= endIndex) _debugPrecondition(unsafe bounds.count == newValue.count) if unsafe !newValue.isEmpty { unsafe (baseAddress! + bounds.lowerBound).copyMemory( from: newValue.base.baseAddress! + newValue.startIndex, byteCount: newValue.count) } } % end # mutable } % if mutable: /// Exchanges the byte values at the specified indices /// in this buffer's memory. /// /// Both parameters must be valid indices of the buffer, and not /// equal to `endIndex`. Passing the same index as both `i` and `j` has no /// effect. /// /// - Parameters: /// - i: The index of the first byte to swap. /// - j: The index of the second byte to swap. @inlinable public func swapAt(_ i: Int, _ j: Int) { guard i != j else { return } _debugPrecondition(i >= 0 && j >= 0) _debugPrecondition(i < endIndex && j < endIndex) let pi = unsafe (_position! + i) let pj = unsafe (_position! + j) let tmp = unsafe pi.load(fromByteOffset: 0, as: UInt8.self) unsafe pi.copyMemory(from: pj, byteCount: MemoryLayout.size) unsafe pj.storeBytes(of: tmp, toByteOffset: 0, as: UInt8.self) } % end # mutable /// The number of bytes in the buffer. /// /// If the `baseAddress` of this buffer is `nil`, the count is zero. However, /// a buffer can have a `count` of zero even with a non-`nil` base address. @inlinable @safe public var count: Int { if let pos = unsafe _position { // Unsafely unwrapped because init forbids end being nil if _position // isn't. _internalInvariant(unsafe _end != nil) return _assumeNonNegative(unsafe _end._unsafelyUnwrappedUnchecked - pos) } return 0 } } extension Unsafe${Mutable}RawBufferPointer: @unsafe RandomAccessCollection { } extension Unsafe${Mutable}RawBufferPointer { % if mutable: /// Allocates uninitialized memory with the specified size and alignment. /// /// You are in charge of managing the allocated memory. Be sure to deallocate /// any memory that you manually allocate. /// /// The allocated memory is not bound to any specific type and must be bound /// before performing any typed operations. If you are using the memory for /// a specific type, allocate memory using the /// `UnsafeMutablePointerBuffer.allocate(capacity:)` static method instead. /// /// - Parameters: /// - byteCount: The number of bytes to allocate. `byteCount` must not be /// negative. /// - alignment: The alignment of the new region of allocated memory, in /// bytes. `alignment` must be a whole power of 2. /// - Returns: A buffer pointer to a newly allocated region of memory aligned /// to `alignment`. @inlinable @safe public static func allocate( byteCount: Int, alignment: Int ) -> UnsafeMutableRawBufferPointer { let base = UnsafeMutableRawPointer.allocate( byteCount: byteCount, alignment: alignment) return unsafe UnsafeMutableRawBufferPointer(start: base, count: byteCount) } % end # mutable /// Deallocates the memory block previously allocated at this buffer pointer’s /// base address. /// /// This buffer pointer's `baseAddress` must be `nil` or a pointer to a memory /// block previously returned by a Swift allocation method. If `baseAddress` is /// `nil`, this function does nothing. Otherwise, the memory must not be initialized /// or `Pointee` must be a trivial type. This buffer pointer's byte `count` must /// be equal to the originally allocated size of the memory block. @inlinable public func deallocate() { unsafe _position?.deallocate() } /// Returns a new instance of the given type, read from the buffer pointer's /// raw memory at the specified byte offset. /// /// The memory at `offset` bytes from this buffer pointer's `baseAddress` /// must be properly aligned for accessing `T` and initialized to `T` or /// another type that is layout compatible with `T`. /// /// You can use this method to create new values from the buffer pointer's /// underlying bytes. The following example creates two new `Int32` /// instances from the memory referenced by the buffer pointer `someBytes`. /// The bytes for `a` are copied from the first four bytes of `someBytes`, /// and the bytes for `b` are copied from the next four bytes. /// /// let a = someBytes.load(as: Int32.self) /// let b = someBytes.load(fromByteOffset: 4, as: Int32.self) /// /// The memory to read for the new instance must not extend beyond the buffer /// pointer's memory region---that is, `offset + MemoryLayout.size` must /// be less than or equal to the buffer pointer's `count`. /// /// - Parameters: /// - offset: The offset, in bytes, into the buffer pointer's memory at /// which to begin reading data for the new instance. The buffer pointer /// plus `offset` must be properly aligned for accessing an instance of /// type `T`. The default is zero. /// - type: The type to use for the newly constructed instance. The memory /// must be initialized to a value of a type that is layout compatible /// with `type`. /// - Returns: A new instance of type `T`, copied from the buffer pointer's /// memory. @inlinable public func load(fromByteOffset offset: Int = 0, as type: T.Type) -> T { _debugPrecondition(offset >= 0, "${Self}.load with negative offset") _debugPrecondition(offset + MemoryLayout.size <= self.count, "${Self}.load out of bounds") return unsafe baseAddress!.load(fromByteOffset: offset, as: T.self) } // FIXME(NCG): Add a consuming analogue of `load`, like `move(fromByteOffset:as:_:)` (in the mutable variant) // FIXME(NCG): Add a borrow analogue of `load`, like `withBorrow(fromByteOffset:as:_:)` /// Returns a new instance of the given type, constructed from the raw memory /// at the specified offset. /// /// This function only supports loading trivial types. /// A trivial type does not contain any reference-counted property /// within its in-memory stored representation. /// The memory at `offset` bytes into the buffer must be laid out /// identically to the in-memory representation of `T`. /// /// You can use this method to create new values from the buffer pointer's /// underlying bytes. The following example creates two new `Int32` /// instances from the memory referenced by the buffer pointer `someBytes`. /// The bytes for `a` are copied from the first four bytes of `someBytes`, /// and the bytes for `b` are copied from the fourth through seventh bytes. /// /// let a = someBytes.loadUnaligned(as: Int32.self) /// let b = someBytes.loadUnaligned(fromByteOffset: 3, as: Int32.self) /// /// The memory to read for the new instance must not extend beyond the buffer /// pointer's memory region---that is, `offset + MemoryLayout.size` must /// be less than or equal to the buffer pointer's `count`. /// /// - Parameters: /// - offset: The offset, in bytes, into the buffer pointer's memory at /// which to begin reading data for the new instance. The default is zero. /// - type: The type to use for the newly constructed instance. The memory /// must be initialized to a value of a type that is layout compatible /// with `type`. /// - Returns: A new instance of type `T`, copied from the buffer pointer's /// memory. @_alwaysEmitIntoClient public func loadUnaligned( fromByteOffset offset: Int = 0, as type: T.Type ) -> T { _debugPrecondition(offset >= 0, "${Self}.load with negative offset") _debugPrecondition(offset + MemoryLayout.size <= self.count, "${Self}.load out of bounds") return unsafe baseAddress!.loadUnaligned(fromByteOffset: offset, as: T.self) } @_alwaysEmitIntoClient public func loadUnaligned( fromByteOffset offset: Int = 0, as type: T.Type ) -> T { _debugPrecondition(offset >= 0, "${Self}.load with negative offset") _debugPrecondition(offset + MemoryLayout.size <= self.count, "${Self}.load out of bounds") return unsafe baseAddress!.loadUnaligned(fromByteOffset: offset, as: T.self) } % if mutable: /// Stores a value's bytes into the buffer pointer's raw memory at the /// specified byte offset. /// /// The type `T` to be stored must be a trivial type. The memory must also be /// uninitialized, initialized to `T`, or initialized to another trivial /// type that is layout compatible with `T`. /// /// The memory written to must not extend beyond the buffer pointer's memory /// region---that is, `offset + MemoryLayout.size` must be less than or /// equal to the buffer pointer's `count`. /// /// After calling `storeBytes(of:toByteOffset:as:)`, the memory is /// initialized to the raw bytes of `value`. If the memory is bound to a /// type `U` that is layout compatible with `T`, then it contains a value of /// type `U`. Calling `storeBytes(of:toByteOffset:as:)` does not change the /// bound type of the memory. /// /// - Note: A trivial type can be copied with just a bit-for-bit copy without /// any indirection or reference-counting operations. Generally, native /// Swift types that do not contain strong or weak references or other /// forms of indirection are trivial, as are imported C structs and enums. /// /// If you need to store into memory a copy of a value of a type that isn't /// trivial, you cannot use the `storeBytes(of:toByteOffset:as:)` method. /// Instead, you must know either initialize the memory or, /// if you know the memory was already bound to `type`, assign to the memory. /// /// - Parameters: /// - value: The value to store as raw bytes. /// - offset: The offset in bytes into the buffer pointer's memory to begin /// writing bytes from the value. The default is zero. /// - type: The type to use for the newly constructed instance. The memory /// must be initialized to a value of a type that is layout compatible /// with `type`. @_alwaysEmitIntoClient // This custom silgen name is chosen to not interfere with the old ABI @_silgen_name("_swift_se0349_UnsafeMutableRawBufferPointer_storeBytes") public func storeBytes( of value: T, toByteOffset offset: Int = 0, as type: T.Type ) { _debugPrecondition(offset >= 0, "${Self}.storeBytes with negative offset") _debugPrecondition(offset + MemoryLayout.size <= self.count, "${Self}.storeBytes out of bounds") let pointer = unsafe baseAddress._unsafelyUnwrappedUnchecked unsafe pointer.storeBytes(of: value, toByteOffset: offset, as: T.self) } // This unavailable implementation uses the expected mangled name // of `storeBytes(of:toByteOffset:as:)`, and provides an entry point for // any binary linked against the stdlib binary for Swift 5.6 and older. @_spi(SwiftStdlibLegacyABI) @available(swift, obsoleted: 1) @_silgen_name("$sSw10storeBytes2of12toByteOffset2asyx_SixmtlF") @usableFromInline func _legacy_se0349_storeBytes( of value: T, toByteOffset offset: Int = 0, as type: T.Type ) { _debugPrecondition(offset >= 0, "${Self}.storeBytes with negative offset") _debugPrecondition(offset + MemoryLayout.size <= self.count, "${Self}.storeBytes out of bounds") unsafe baseAddress!._legacy_se0349_storeBytes_internal( of: value, toByteOffset: offset, as: T.self ) } /// Copies the bytes from the given buffer to this buffer's memory. /// /// If the `source.count` bytes of memory referenced by this buffer are bound /// to a type `T`, then `T` must be a trivial type, the underlying pointer /// must be properly aligned for accessing `T`, and `source.count` must be a /// multiple of `MemoryLayout.stride`. /// /// The memory referenced by `source` may overlap with the memory referenced /// by this buffer. /// /// After calling `copyMemory(from:)`, the first `source.count` bytes of /// memory referenced by this buffer are initialized to raw bytes. If the /// memory is bound to type `T`, then it contains values of type `T`. /// /// - Parameter source: A buffer of raw bytes. `source.count` must /// be less than or equal to this buffer's `count`. @inlinable public func copyMemory(from source: UnsafeRawBufferPointer) { _debugPrecondition(source.count <= self.count, "${Self}.copyMemory source has too many elements") if let baseAddress = baseAddress, let sourceAddress = source.baseAddress { unsafe baseAddress.copyMemory(from: sourceAddress, byteCount: source.count) } } /// Copies from a collection of `UInt8` into this buffer's memory. /// /// If the first `source.count` bytes of memory referenced by this buffer /// are bound to a type `T`, then `T` must be a trivial type, /// the underlying pointer must be properly aligned for accessing `T`, /// and `source.count` must be a multiple of `MemoryLayout.stride`. /// /// After calling `copyBytes(from:)`, the first `source.count` bytes of memory /// referenced by this buffer are initialized to raw bytes. If the memory is /// bound to type `T`, then it contains values of type `T`. /// /// - Parameter source: A collection of `UInt8` elements. `source.count` must /// be less than or equal to this buffer's `count`. @inlinable public func copyBytes( from source: C ) where C.Element == UInt8 { guard let position = unsafe _position else { return } if source.withContiguousStorageIfAvailable({ (buffer: UnsafeBufferPointer) -> Void in _debugPrecondition(source.count <= self.count, "${Self}.copyBytes source has too many elements") if let base = buffer.baseAddress { unsafe position.copyMemory(from: base, byteCount: buffer.count) } }) != nil { return } for (index, byteValue) in source.enumerated() { _debugPrecondition(index < self.count, "${Self}.copyBytes source has too many elements") unsafe position.storeBytes( of: byteValue, toByteOffset: index, as: UInt8.self) } } % end # mutable /// Creates a new buffer over the same memory as the given buffer. /// /// - Parameter bytes: The buffer to convert. @inlinable @_transparent @safe public init(_ bytes: UnsafeMutableRawBufferPointer) { unsafe self.init(start: bytes.baseAddress, count: bytes.count) } % if mutable: /// Creates a new mutable buffer over the same memory as the given buffer. /// /// - Parameter bytes: The buffer to convert. @inlinable @_transparent public init(mutating bytes: UnsafeRawBufferPointer) { unsafe self.init(start: UnsafeMutableRawPointer(mutating: bytes.baseAddress), count: bytes.count) } % else: /// Creates a new buffer over the same memory as the given buffer. /// /// - Parameter bytes: The buffer to convert. @inlinable @_transparent @safe public init(_ bytes: UnsafeRawBufferPointer) { unsafe self.init(start: bytes.baseAddress, count: bytes.count) } % end # !mutable /// Creates a raw buffer over the contiguous bytes in the given typed buffer. /// /// - Parameter buffer: The typed buffer to convert to a raw buffer. The /// buffer's type `T` must be a trivial type. @inlinable @_transparent @_preInverseGenerics @safe public init(_ buffer: UnsafeMutableBufferPointer) { unsafe self.init(start: buffer.baseAddress, count: buffer.count * MemoryLayout.stride) } % if not mutable: /// Creates a raw buffer over the contiguous bytes in the given typed buffer. /// /// - Parameter buffer: The typed buffer to convert to a raw buffer. The /// buffer's type `T` must be a trivial type. @inlinable @_transparent @_preInverseGenerics @safe public init(_ buffer: UnsafeBufferPointer) { unsafe self.init(start: buffer.baseAddress, count: buffer.count * MemoryLayout.stride) } % end # !mutable % if not mutable: /// Creates a raw buffer over the same memory as the given raw buffer slice, /// with the indices rebased to zero. /// /// The new buffer represents the same region of memory as the slice, but its /// indices start at zero instead of at the beginning of the slice in the /// original buffer. The following code creates `slice`, a slice covering /// part of an existing buffer instance, then rebases it into a new `rebased` /// buffer. /// /// let slice = buffer[n...] /// let rebased = UnsafeRawBufferPointer(rebasing: slice) /// /// After this code has executed, the following are true: /// /// - `rebased.startIndex == 0` /// - `rebased[0] == slice[n]` /// - `rebased[0] == buffer[n]` /// - `rebased.count == slice.count` /// /// - Parameter slice: The raw buffer slice to rebase. @inlinable @_transparent public init(rebasing slice: Slice) { // NOTE: `Slice` does not guarantee that its start/end indices are valid // in `base` -- it merely ensures that `startIndex <= endIndex`. // We need manually check that we aren't given an invalid slice, // or the resulting collection would allow access that was // out-of-bounds with respect to the original base buffer. // We only do this in debug builds to prevent a measurable performance // degradation wrt passing around pointers not wrapped in a BufferPointer // construct. _debugPrecondition( unsafe slice.startIndex >= 0 && slice.endIndex <= slice.base.count, "Invalid slice") let base = unsafe slice.base.baseAddress?.advanced(by: slice.startIndex) let count = unsafe slice.endIndex &- slice.startIndex unsafe self.init(start: base, count: count) } % end # !mutable /// Creates a raw buffer over the same memory as the given raw buffer slice, /// with the indices rebased to zero. /// /// The new buffer represents the same region of memory as the slice, but its /// indices start at zero instead of at the beginning of the slice in the /// original buffer. The following code creates `slice`, a slice covering /// part of an existing buffer instance, then rebases it into a new `rebased` /// buffer. /// /// let slice = buffer[n...] /// let rebased = UnsafeRawBufferPointer(rebasing: slice) /// /// After this code has executed, the following are true: /// /// - `rebased.startIndex == 0` /// - `rebased[0] == slice[n]` /// - `rebased[0] == buffer[n]` /// - `rebased.count == slice.count` /// /// - Parameter slice: The raw buffer slice to rebase. @inlinable @_transparent public init(rebasing slice: Slice) { let base = unsafe slice.base.baseAddress?.advanced(by: slice.startIndex) let count = unsafe slice.endIndex &- slice.startIndex unsafe self.init(start: base, count: count) } /// A pointer to the first byte of the buffer. /// /// If the `baseAddress` of this buffer is `nil`, the count is zero. However, /// a buffer can have a `count` of zero even with a non-`nil` base address. @inlinable @safe public var baseAddress: Unsafe${Mutable}RawPointer? { return unsafe _position } % if mutable: /// Initializes the memory referenced by this buffer with the given value, /// binds the memory to the value's type, and returns a typed buffer of the /// initialized memory. /// /// The memory referenced by this buffer must be uninitialized or /// initialized to a trivial type, and must be properly aligned for /// accessing `T`. /// /// After calling this method on a raw buffer with non-nil `baseAddress` `b`, /// the region starting at `b` and continuing up to /// `b + self.count - self.count % MemoryLayout.stride` is bound /// to type `T` and is initialized. If `T` is a nontrivial type, you must /// eventually deinitialize or move the values in this region to avoid leaks. /// If `baseAddress` is `nil`, this function does nothing /// and returns an empty buffer pointer. /// /// - Parameters: /// - type: The type to bind this buffer’s memory to. /// - repeatedValue: The instance to copy into memory. /// - Returns: A typed buffer of the memory referenced by this raw buffer. /// The typed buffer contains `self.count / MemoryLayout.stride` /// instances of `T`. @inlinable @discardableResult public func initializeMemory(as type: T.Type, repeating repeatedValue: T) -> UnsafeMutableBufferPointer { guard let base = unsafe _position else { return unsafe .init(start: nil, count: 0) } let count = (unsafe _end._unsafelyUnwrappedUnchecked-base) / MemoryLayout.stride let initialized = unsafe base.initializeMemory( as: type, repeating: repeatedValue, count: count ) return unsafe .init(start: initialized, count: count) } /// Initializes the buffer's memory with the given elements, binding the /// initialized memory to the elements' type. /// /// When calling the `initializeMemory(as:from:)` method on a buffer `b`, /// the memory referenced by `b` must be uninitialized or initialized to a /// trivial type, and must be properly aligned for accessing `S.Element`. /// The buffer must contain sufficient memory to accommodate /// `source.underestimatedCount`. /// /// This method initializes the buffer with elements from `source` until /// `source` is exhausted or, if `source` is a sequence but not a collection, /// the buffer has no more room for source's elements. After calling /// `initializeMemory(as:from:)`, the memory referenced by the returned /// `UnsafeMutableBufferPointer` instance is bound and initialized to type /// `S.Element`. This method does not change /// the binding state of the unused portion of `b`, if any. /// /// - Parameters: /// - type: The type of element to which this buffer's memory will be bound. /// - source: A sequence of elements with which to initialize the buffer. /// - Returns: An iterator to any elements of `source` that didn't fit in the /// buffer, and a typed buffer of the written elements. The returned /// buffer references memory starting at the same base address as this /// buffer. @inlinable public func initializeMemory( as type: S.Element.Type, from source: S ) -> (unwritten: S.Iterator, initialized: UnsafeMutableBufferPointer) { var it = source.makeIterator() var idx = startIndex let elementStride = MemoryLayout.stride // This has to be a debug precondition due to the cost of walking over some collections. _debugPrecondition(source.underestimatedCount <= (count / elementStride), "insufficient space to accommodate source.underestimatedCount elements") guard let base = baseAddress else { // this can be a precondition since only an invalid argument should be costly _precondition(source.underestimatedCount == 0, "no memory available to initialize from source") return (it, unsafe UnsafeMutableBufferPointer(start: nil, count: 0)) } _debugPrecondition( Int(bitPattern: base) & (MemoryLayout.alignment-1) == 0, "buffer base address must be properly aligned to access S.Element" ) _internalInvariant(unsafe _end != nil) for unsafe p in unsafe stride(from: base, // only advance to as far as the last element that will fit to: _end._unsafelyUnwrappedUnchecked - elementStride + 1, by: elementStride ) { // underflow is permitted -- e.g. a sequence into // the spare capacity of an Array buffer guard let x = it.next() else { break } unsafe p.initializeMemory(as: S.Element.self, repeating: x, count: 1) unsafe formIndex(&idx, offsetBy: elementStride) } return (it, unsafe UnsafeMutableBufferPointer( start: base.assumingMemoryBound(to: S.Element.self), count: idx / elementStride)) } /// Initializes the buffer's memory with every element of the source, /// binding the initialized memory to the elements' type. /// /// When calling the `initializeMemory(as:fromContentsOf:)` method, /// the memory referenced by the buffer must be uninitialized, or initialized /// to a trivial type. The buffer must reference enough memory to store /// `source.count` elements, and its `baseAddress` must be properly aligned /// for accessing `C.Element`. /// /// This method initializes the buffer with the contents of `source` /// until `source` is exhausted. /// After calling `initializeMemory(as:fromContentsOf:)`, the memory /// referenced by the returned `UnsafeMutableBufferPointer` instance is bound /// to the type `C.Element` and is initialized. This method does not change /// the binding state of the unused portion of the buffer, if any. /// /// - Note: The memory regions referenced by `source` and this buffer /// must not overlap. /// /// - Parameters: /// - type: The type of element to which this buffer's memory will be bound. /// - source: A collection of elements to be used to /// initialize the buffer's storage. /// - Returns: A typed buffer referencing the initialized elements. /// The returned buffer references memory starting at the same /// base address as this buffer, and its count is equal to `source.count` @_alwaysEmitIntoClient public func initializeMemory( as type: C.Element.Type, fromContentsOf source: C ) -> UnsafeMutableBufferPointer { let buffer: UnsafeMutableBufferPointer? unsafe buffer = source.withContiguousStorageIfAvailable { guard let sourceAddress = $0.baseAddress, !$0.isEmpty else { return unsafe .init(start: nil, count: 0) } _debugPrecondition( Int(bitPattern: baseAddress) & (MemoryLayout.alignment-1) == 0, "buffer base address must be properly aligned to access C.Element" ) _precondition( $0.count * MemoryLayout.stride <= self.count, "buffer cannot contain every element from source collection." ) let start = unsafe baseAddress.unsafelyUnwrapped.initializeMemory( as: C.Element.self, from: sourceAddress, count: $0.count ) return unsafe .init(start: start, count: $0.count) } if let buffer = unsafe buffer { return unsafe buffer } guard let base = baseAddress else { _precondition( source.isEmpty, "buffer cannot contain every element from source collection." ) return unsafe .init(start: nil, count: 0) } _internalInvariant(unsafe _end != nil) _debugPrecondition( Int(bitPattern: baseAddress) & (MemoryLayout.alignment-1) == 0, "buffer base address must be properly aligned to access C.Element" ) var iterator = source.makeIterator() var element = unsafe base var initialized = 0 let end = unsafe _end._unsafelyUnwrappedUnchecked - MemoryLayout.stride while unsafe element <= end { guard let value = iterator.next() else { return unsafe .init(start: .init(base._rawValue), count: initialized) } unsafe element.initializeMemory(as: C.Element.self, to: value) unsafe element = element.advanced(by: MemoryLayout.stride) initialized += 1 } _precondition( iterator.next() == nil, "buffer cannot contain every element from source collection." ) return unsafe .init(start: .init(base._rawValue), count: initialized) } /// Moves every element of an initialized source buffer into the /// uninitialized memory referenced by this buffer, leaving the source memory /// uninitialized and this buffer's memory initialized. /// /// When calling the `moveInitializeMemory(as:fromContentsOf:)` method, /// the memory referenced by the buffer must be uninitialized, or initialized /// to a trivial type. The buffer must reference enough memory to store /// `source.count` elements, and its `baseAddress` must be properly aligned /// for accessing `C.Element`. After the method returns, /// the memory referenced by the returned buffer is initialized and the /// memory region underlying `source` is uninitialized. /// /// This method initializes the buffer with the contents of `source` /// until `source` is exhausted. /// After calling `initializeMemory(as:fromContentsOf:)`, the memory /// referenced by the returned `UnsafeMutableBufferPointer` instance is bound /// to the type `T` and is initialized. This method does not change /// the binding state of the unused portion of the buffer, if any. /// /// - Note: The memory regions referenced by `source` and this buffer /// may overlap. /// /// - Parameters: /// - type: The type of element to which this buffer's memory will be bound. /// - source: A buffer referencing the values to copy. /// The memory region underlying `source` must be initialized. /// - Returns: A typed buffer referencing the initialized elements. /// The returned buffer references memory starting at the same /// base address as this buffer, and its count is equal to `source.count`. @discardableResult @_alwaysEmitIntoClient public func moveInitializeMemory( as type: T.Type, fromContentsOf source: UnsafeMutableBufferPointer ) -> UnsafeMutableBufferPointer { guard let sourceAddress = source.baseAddress, !source.isEmpty else { return unsafe .init(start: nil, count: 0) } _debugPrecondition( Int(bitPattern: baseAddress) & (MemoryLayout.alignment-1) == 0, "buffer base address must be properly aligned to access T" ) _precondition( source.count * MemoryLayout.stride <= self.count, "buffer cannot contain every element from source." ) let initialized = unsafe baseAddress.unsafelyUnwrapped.moveInitializeMemory( as: T.self, from: sourceAddress, count: source.count ) return unsafe .init(start: initialized, count: source.count) } /// Moves every element of an initialized source buffer slice into the /// uninitialized memory referenced by this buffer, leaving the source memory /// uninitialized and this buffer's memory initialized. /// /// When calling the `moveInitializeMemory(as:fromContentsOf:)` method, /// the memory referenced by the buffer must be uninitialized, or initialized /// to a trivial type. The buffer must reference enough memory to store /// `source.count` elements, and its `baseAddress` must be properly aligned /// for accessing `C.Element`. After the method returns, /// the memory referenced by the returned buffer is initialized and the /// memory region underlying `source` is uninitialized. /// /// This method initializes the buffer with the contents of `source` /// until `source` is exhausted. /// After calling `initializeMemory(as:fromContentsOf:)`, the memory /// referenced by the returned `UnsafeMutableBufferPointer` instance is bound /// to the type `T` and is initialized. This method does not change /// the binding state of the unused portion of the buffer, if any. /// /// - Note: The memory regions referenced by `source` and this buffer /// may overlap. /// /// - Parameters: /// - type: The type of element to which this buffer's memory will be bound. /// - source: A buffer referencing the values to copy. /// The memory region underlying `source` must be initialized. /// - Returns: A typed buffer referencing the initialized elements. /// The returned buffer references memory starting at the same /// base address as this buffer, and its count is equal to `source.count`. @discardableResult @_alwaysEmitIntoClient public func moveInitializeMemory( as type: T.Type, fromContentsOf source: Slice> ) -> UnsafeMutableBufferPointer { let rebased = unsafe UnsafeMutableBufferPointer(rebasing: source) return unsafe moveInitializeMemory(as: T.self, fromContentsOf: rebased) } % end # mutable /// Binds this buffer’s memory to the specified type and returns a typed /// buffer of the bound memory. /// /// Use the `bindMemory(to:)` method to bind the memory referenced /// by this buffer to the type `T`. The memory must be uninitialized or /// initialized to a type that is layout compatible with `T`. If the memory /// is uninitialized, it is still uninitialized after being bound to `T`. /// /// - Warning: A memory location may only be bound to one type at a time. The /// behavior of accessing memory as a type unrelated to its bound type is /// undefined. /// /// - Parameters: /// - type: The type `T` to bind the memory to. /// - Returns: A typed buffer of the newly bound memory. The memory in this /// region is bound to `T`, but has not been modified in any other way. /// The typed buffer references `self.count / MemoryLayout.stride` /// instances of `T`. @inlinable @_transparent @_preInverseGenerics @discardableResult public func bindMemory( to type: T.Type ) -> Unsafe${Mutable}BufferPointer { guard let base = unsafe _position else { return unsafe Unsafe${Mutable}BufferPointer(start: nil, count: 0) } let capacity = count / MemoryLayout.stride Builtin.bindMemory(base._rawValue, capacity._builtinWordValue, type) return unsafe Unsafe${Mutable}BufferPointer( start: Unsafe${Mutable}Pointer(base._rawValue), count: capacity) } /// Executes the given closure while temporarily binding the buffer to /// instances of type `T`. /// /// Use this method when you have a buffer to raw memory and you need /// to access that memory as instances of a given type `T`. Accessing /// memory as a type `T` requires that the memory be bound to that type. /// A memory location may only be bound to one type at a time, so accessing /// the same memory as an unrelated type without first rebinding the memory /// is undefined. /// /// Any instance of `T` within the re-bound region may be initialized or /// uninitialized. The memory underlying any individual instance of `T` /// must have the same initialization state (i.e. initialized or /// uninitialized.) Accessing a `T` whose underlying memory /// is in a mixed initialization state shall be undefined behaviour. /// /// If the byte count of the original buffer is not a multiple of /// the stride of `T`, then the re-bound buffer is shorter /// than the original buffer. /// /// After executing `body`, this method rebinds memory back to its original /// binding state. This can be unbound memory, or bound to a different type. /// /// - Note: The buffer's base address must match the /// alignment of `T` (as reported by `MemoryLayout.alignment`). /// That is, `Int(bitPattern: self.baseAddress) % MemoryLayout.alignment` /// must equal zero. /// /// - Note: A raw buffer may represent memory that has been bound to a type. /// If that is the case, then `T` must be layout compatible with the /// type to which the memory has been bound. This requirement does not /// apply if the raw buffer represents memory that has not been bound /// to any type. /// /// - Parameters: /// - type: The type to temporarily bind the memory referenced by this /// buffer. /// - body: A closure that takes a typed pointer to the /// same memory as this pointer, only bound to type `T`. The closure's /// pointer argument is valid only for the duration of the closure's /// execution. If `body` has a return value, that value is also used as /// the return value for the `withMemoryRebound(to:capacity:_:)` method. /// - buffer: The buffer temporarily bound to instances of `T`. /// - Returns: The return value, if any, of the `body` closure parameter. @_alwaysEmitIntoClient @_transparent public func withMemoryRebound( to type: T.Type, _ body: (_ buffer: Unsafe${Mutable}BufferPointer) throws(E) -> Result ) throws(E) -> Result { guard let s = unsafe _position else { return try unsafe body(.init(start: nil, count: 0)) } _debugPrecondition( Int(bitPattern: s) & (MemoryLayout.alignment-1) == 0, "baseAddress must be a properly aligned pointer for type T" ) // initializer ensures _end is nil only when _position is nil. _internalInvariant(unsafe _end != nil) let c = _assumeNonNegative(unsafe s.distance(to: _end._unsafelyUnwrappedUnchecked)) let n = c / MemoryLayout.stride let binding = Builtin.bindMemory(s._rawValue, n._builtinWordValue, T.self) defer { Builtin.rebindMemory(s._rawValue, binding) } return try unsafe body(.init(start: .init(s._rawValue), count: n)) } /// Returns a typed buffer to the memory referenced by this buffer, /// assuming that the memory is already bound to the specified type. /// /// Use this method when you have a raw buffer to memory that has already /// been bound to the specified type. The memory starting at this pointer /// must be bound to the type `T`. Accessing memory through the returned /// pointer is undefined if the memory has not been bound to `T`. To bind /// memory to `T`, use `bindMemory(to:capacity:)` instead of this method. /// /// - Note: The buffer's base address must match the /// alignment of `T` (as reported by `MemoryLayout.alignment`). /// That is, `Int(bitPattern: self.baseAddress) % MemoryLayout.alignment` /// must equal zero. /// /// - Parameter to: The type `T` that the memory has already been bound to. /// - Returns: A typed pointer to the same memory as this raw pointer. @_alwaysEmitIntoClient @_transparent public func assumingMemoryBound( to: T.Type ) -> Unsafe${Mutable}BufferPointer { guard let s = unsafe _position else { return unsafe .init(start: nil, count: 0) } // initializer ensures _end is nil only when _position is nil. _internalInvariant(unsafe _end != nil) let c = _assumeNonNegative(unsafe s.distance(to: _end._unsafelyUnwrappedUnchecked)) let n = c / MemoryLayout.stride return unsafe .init(start: .init(s._rawValue), count: n) } % if Mutable: @_alwaysEmitIntoClient @_transparent public func withContiguousMutableStorageIfAvailable( _ body: (inout UnsafeMutableBufferPointer) throws -> R ) rethrows -> R? { try unsafe withMemoryRebound(to: Element.self) { b in var buffer = unsafe b defer { _debugPrecondition( unsafe (b.baseAddress, b.count) == (buffer.baseAddress, buffer.count), "UnsafeMutableRawBufferPointer.withContiguousMutableStorageIfAvailable: replacing the buffer is not allowed" ) } return try unsafe body(&buffer) } } % end @_alwaysEmitIntoClient @_transparent public func withContiguousStorageIfAvailable( _ body: (UnsafeBufferPointer) throws -> R ) rethrows -> R? { try unsafe withMemoryRebound(to: Element.self) { try unsafe body(${ 'UnsafeBufferPointer($0)' if Mutable else '$0' }) } } } @available(SwiftCompatibilitySpan 5.0, *) @_originallyDefinedIn(module: "Swift;CompatibilitySpan", SwiftCompatibilitySpan 6.2) extension Unsafe${Mutable}RawBufferPointer { @unsafe @_alwaysEmitIntoClient public var bytes: RawSpan { @lifetime(borrow self) @_transparent get { unsafe RawSpan(_unsafeBytes: self) } } % if Mutable: @unsafe @_alwaysEmitIntoClient public var mutableBytes: MutableRawSpan { @lifetime(borrow self) @_transparent get { unsafe MutableRawSpan(_unsafeBytes: self) } } % end } @_unavailableInEmbedded extension Unsafe${Mutable}RawBufferPointer: CustomDebugStringConvertible { /// A textual representation of the buffer, suitable for debugging. @safe public var debugDescription: String { return "${Self}" + "(start: \(unsafe _position.map(String.init(describing:)) ?? "nil"), count: \(count))" } } extension ${Self} { @available(*, unavailable, message: "use 'Unsafe${Mutable}RawBufferPointer(rebasing:)' to convert a slice into a zero-based raw buffer.") public subscript(bounds: Range) -> ${Self} { get { return unsafe ${Self}(start: nil, count: 0) } % if mutable: nonmutating set {} % end # mutable } % if mutable: @available(*, unavailable, message: "use 'UnsafeRawBufferPointer(rebasing:)' to convert a slice into a zero-based raw buffer.") public subscript(bounds: Range) -> UnsafeRawBufferPointer { get { return unsafe UnsafeRawBufferPointer(start: nil, count: 0) } nonmutating set {} } % end # mutable } % end # for mutable /// Invokes the given closure with a mutable buffer pointer covering the raw /// bytes of the given argument. /// /// The buffer pointer argument to the `body` closure provides a collection /// interface to the raw bytes of `value`. The buffer is the size of the /// instance passed as `value` and does not include any remote storage. /// /// - Parameters: /// - value: An instance to temporarily access through a mutable raw buffer /// pointer. /// Note that the `inout` exclusivity rules mean that, like any other /// `inout` argument, `value` cannot be directly accessed by other code /// for the duration of `body`. Access must only occur through the pointer /// argument to `body` until `body` returns. /// - body: A closure that takes a raw buffer pointer to the bytes of `value` /// as its sole argument. If the closure has a return value, that value is /// also used as the return value of the `withUnsafeMutableBytes(of:_:)` /// function. The buffer pointer argument is valid only for the duration /// of the closure's execution. /// - Returns: The return value, if any, of the `body` closure. @_alwaysEmitIntoClient public func withUnsafeMutableBytes( of value: inout T, _ body: (UnsafeMutableRawBufferPointer) throws(E) -> Result ) throws(E) -> Result { let pointer = UnsafeMutableRawPointer(Builtin.addressof(&value)) return try unsafe body(unsafe .init(start: pointer, count: MemoryLayout.size)) } #if !$Embedded /// ABI: Historical withUnsafeMutableBytes(of:_:) rethrows, /// expressed as "throws", which is ABI-compatible with "rethrows". @_spi(SwiftStdlibLegacyABI) @available(swift, obsoleted: 1) @_silgen_name("$ss22withUnsafeMutableBytes2of_q_xz_q_SwKXEtKr0_lF") @usableFromInline func __abi_se0413_withUnsafeMutableBytes( of value: inout T, _ body: (UnsafeMutableRawBufferPointer) throws -> Result ) throws -> Result { return try unsafe withUnsafeMutablePointer(to: &value) { return try unsafe body(unsafe UnsafeMutableRawBufferPointer( start: $0, count: MemoryLayout.size)) } } #endif /// Invokes the given closure with a buffer pointer covering the raw bytes of /// the given argument. /// /// This function is similar to `withUnsafeMutableBytes`, except that it /// doesn't trigger stack protection for the pointer. @_alwaysEmitIntoClient public func _withUnprotectedUnsafeMutableBytes< T: ~Copyable, E: Error, Result: ~Copyable >( of value: inout T, _ body: (UnsafeMutableRawBufferPointer) throws(E) -> Result ) throws(E) -> Result { #if $BuiltinUnprotectedAddressOf let pointer = UnsafeMutableRawPointer(Builtin.unprotectedAddressOf(&value)) #else let pointer = UnsafeMutableRawPointer(Builtin.addressof(&value)) #endif return try unsafe body(unsafe .init(start: pointer, count: MemoryLayout.size)) } /// Invokes the given closure with a buffer pointer covering the raw bytes of /// the given argument. /// /// The buffer pointer argument to the `body` closure provides a collection /// interface to the raw bytes of `value`. The buffer is the size of the /// instance passed as `value` and does not include any remote storage. /// /// - Parameters: /// - value: An instance to temporarily access through a raw buffer pointer. /// Note that the `inout` exclusivity rules mean that, like any other /// `inout` argument, `value` cannot be directly accessed by other code /// for the duration of `body`. Access must only occur through the pointer /// argument to `body` until `body` returns. /// - body: A closure that takes a raw buffer pointer to the bytes of `value` /// as its sole argument. If the closure has a return value, that value is /// also used as the return value of the `withUnsafeBytes(of:_:)` /// function. The buffer pointer argument is valid only for the duration /// of the closure's execution. It is undefined behavior to attempt to /// mutate through the pointer by conversion to /// `UnsafeMutableRawBufferPointer` or any other mutable pointer type. /// If you want to mutate a value by writing through a pointer, use /// `withUnsafeMutableBytes(of:_:)` instead. /// - Returns: The return value, if any, of the `body` closure. @_alwaysEmitIntoClient public func withUnsafeBytes( of value: inout T, _ body: (UnsafeRawBufferPointer) throws(E) -> Result ) throws(E) -> Result { let address = UnsafeRawPointer(Builtin.addressof(&value)) return try unsafe body(unsafe .init(start: address, count: MemoryLayout.size)) } #if !$Embedded /// ABI: Historical withUnsafeBytes(of:_:) rethrows, /// expressed as "throws", which is ABI-compatible with "rethrows". @_spi(SwiftStdlibLegacyABI) @available(swift, obsoleted: 1) @_silgen_name("$ss15withUnsafeBytes2of_q_xz_q_SWKXEtKr0_lF") @usableFromInline func __abi_se0413_withUnsafeBytes( of value: inout T, _ body: (UnsafeRawBufferPointer) throws -> Result ) throws -> Result { return try unsafe withUnsafePointer(to: &value) { try unsafe body(unsafe UnsafeRawBufferPointer(start: $0, count: MemoryLayout.size)) } } #endif /// Invokes the given closure with a buffer pointer covering the raw bytes of /// the given argument. /// /// This function is similar to `withUnsafeBytes`, except that it /// doesn't trigger stack protection for the pointer. @_alwaysEmitIntoClient public func _withUnprotectedUnsafeBytes< T: ~Copyable, E: Error, Result: ~Copyable >( of value: inout T, _ body: (UnsafeRawBufferPointer) throws(E) -> Result ) throws(E) -> Result { #if $BuiltinUnprotectedAddressOf let p = UnsafeRawPointer(Builtin.unprotectedAddressOf(&value)) #else let p = UnsafeRawPointer(Builtin.addressof(&value)) #endif return try unsafe body(unsafe .init(start: p, count: MemoryLayout.size)) } /// Invokes the given closure with a buffer pointer covering the raw bytes of /// the given argument. /// /// The buffer pointer argument to the `body` closure provides a collection /// interface to the raw bytes of `value`. The buffer is the size of the /// instance passed as `value` and does not include any remote storage. /// /// - Parameters: /// - value: An instance to temporarily access through a raw buffer pointer. /// - body: A closure that takes a raw buffer pointer to the bytes of `value` /// as its sole argument. If the closure has a return value, that value is /// also used as the return value of the `withUnsafeBytes(of:_:)` /// function. The buffer pointer argument is valid only for the duration /// of the closure's execution. It is undefined behavior to attempt to /// mutate through the pointer by conversion to /// `UnsafeMutableRawBufferPointer` or any other mutable pointer type. /// If you want to mutate a value by writing through a pointer, use /// `withUnsafeMutableBytes(of:_:)` instead. /// - Returns: The return value, if any, of the `body` closure. @_alwaysEmitIntoClient public func withUnsafeBytes< T: ~Copyable, E: Error, Result: ~Copyable >( of value: borrowing T, _ body: (UnsafeRawBufferPointer) throws(E) -> Result ) throws(E) -> Result { let addr = UnsafeRawPointer(Builtin.addressOfBorrow(value)) return try unsafe body(unsafe .init(start: addr, count: MemoryLayout.size)) } #if !$Embedded /// ABI: Historical withUnsafeBytes(of:_:) rethrows, /// expressed as "throws", which is ABI-compatible with "rethrows". @_spi(SwiftStdlibLegacyABI) @available(swift, obsoleted: 1) @_silgen_name("$ss15withUnsafeBytes2of_q_x_q_SWKXEtKr0_lF") @usableFromInline func __abi_se0413_withUnsafeBytes( of value: T, _ body: (UnsafeRawBufferPointer) throws -> Result ) throws -> Result { let addr = UnsafeRawPointer(Builtin.addressOfBorrow(value)) let buffer = unsafe UnsafeRawBufferPointer(start: addr, count: MemoryLayout.size) return try unsafe body(buffer) } #endif /// Invokes the given closure with a buffer pointer covering the raw bytes of /// the given argument. /// /// This function is similar to `withUnsafeBytes`, except that it /// doesn't trigger stack protection for the pointer. @_alwaysEmitIntoClient public func _withUnprotectedUnsafeBytes< T: ~Copyable, E: Error, Result: ~Copyable >( of value: borrowing T, _ body: (UnsafeRawBufferPointer) throws(E) -> Result ) throws(E) -> Result { #if $BuiltinUnprotectedAddressOf let addr = UnsafeRawPointer(Builtin.unprotectedAddressOfBorrow(value)) #else let addr = UnsafeRawPointer(Builtin.addressOfBorrow(value)) #endif let buffer = unsafe UnsafeRawBufferPointer(start: addr, count: MemoryLayout.size) return try unsafe body(buffer) } // ${'Local Variables'}: // eval: (read-only-mode 1) // End: