mirror of
https://github.com/apple/swift.git
synced 2025-12-14 20:36:38 +01:00
1179 lines
55 KiB
Swift
1179 lines
55 KiB
Swift
//===----------------------------------------------------------*- swift -*-===//
|
||
//
|
||
// This source file is part of the Swift open source project
|
||
//
|
||
// Copyright (c) 2021 - 2024 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
|
||
//
|
||
//===----------------------------------------------------------------------===//
|
||
|
||
extension Slice where Base == UnsafeMutableRawBufferPointer {
|
||
|
||
/// Copies from a collection of `UInt8` into this buffer slice's memory.
|
||
///
|
||
/// If the first `source.count` bytes of memory referenced by
|
||
/// this buffer slice 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<T>.stride`.
|
||
///
|
||
/// After calling `copyBytes(from:)`, the first `source.count` bytes of memory
|
||
/// referenced by this buffer slice 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 slice's `count`.
|
||
@inlinable
|
||
@_alwaysEmitIntoClient
|
||
public func copyBytes<C: Collection>(
|
||
from source: C
|
||
) where C.Element == UInt8 {
|
||
let buffer = unsafe Base(rebasing: self)
|
||
unsafe buffer.copyBytes(from: source)
|
||
}
|
||
|
||
/// Initializes the memory referenced by this buffer slice 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 slice 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 slice referencing memory
|
||
/// starting at `b = base.baseAddress + startIndex`,
|
||
/// the region starting at `b` and continuing up to
|
||
/// `b + self.count - self.count % MemoryLayout<T>.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 `base.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<T>.stride`
|
||
/// instances of `T`.
|
||
@discardableResult
|
||
@inlinable
|
||
@_alwaysEmitIntoClient
|
||
public func initializeMemory<T>(
|
||
as type: T.Type, repeating repeatedValue: T
|
||
) -> UnsafeMutableBufferPointer<T> {
|
||
let buffer = unsafe Base(rebasing: self)
|
||
return unsafe buffer.initializeMemory(as: T.self, repeating: repeatedValue)
|
||
}
|
||
|
||
/// 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 slice,
|
||
/// the memory referenced by the slice 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 slice with elements from `source` until
|
||
/// `source` is exhausted or, if `source` is a sequence but not a collection,
|
||
/// the buffer slice 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`.
|
||
///
|
||
/// - 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
|
||
@_alwaysEmitIntoClient
|
||
public func initializeMemory<S: Sequence>(
|
||
as type: S.Element.Type, from source: S
|
||
) -> (unwritten: S.Iterator, initialized: UnsafeMutableBufferPointer<S.Element>) {
|
||
let buffer = unsafe Base(rebasing: self)
|
||
return unsafe buffer.initializeMemory(as: S.Element.self, from: source)
|
||
}
|
||
|
||
/// Initializes the buffer slice'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 slice must be uninitialized,
|
||
/// or initialized to a trivial type. The buffer slice must reference
|
||
/// enough memory to store `source.count` elements, and it
|
||
/// 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 of `C.Element` and is initialized. This method does not change
|
||
/// the binding state of the unused portion of the buffer slice, if any.
|
||
///
|
||
/// - 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 slice's storage.
|
||
/// - Returns: A typed buffer referencing the initialized elements.
|
||
/// The returned buffer references memory starting at the same
|
||
/// base address as this slice, and its count is equal to `source.count`
|
||
@inlinable
|
||
@_alwaysEmitIntoClient
|
||
public func initializeMemory<C: Collection>(
|
||
as type: C.Element.Type,
|
||
fromContentsOf source: C
|
||
) -> UnsafeMutableBufferPointer<C.Element> {
|
||
let buffer = unsafe Base(rebasing: self)
|
||
return unsafe buffer.initializeMemory(as: C.Element.self, fromContentsOf: source)
|
||
}
|
||
|
||
/// Moves every element of an initialized source buffer into the
|
||
/// uninitialized memory referenced by this buffer slice, leaving
|
||
/// the source memory uninitialized and this slice's memory initialized.
|
||
///
|
||
/// When calling the `moveInitializeMemory(as:fromContentsOf:)` method,
|
||
/// the memory referenced by the buffer slice must be uninitialized,
|
||
/// or initialized to a trivial type. The buffer slice must reference
|
||
/// enough memory to store `source.count` elements, and it 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 slice 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 of `T` and is initialized. This method does not change
|
||
/// the binding state of the unused portion of the buffer slice, if any.
|
||
///
|
||
/// - 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.
|
||
/// The memory regions referenced by `source` and this slice may overlap.
|
||
/// - Returns: A typed buffer referencing the initialized elements.
|
||
/// The returned buffer references memory starting at the same
|
||
/// base address as this slice, and its count is equal to `source.count`.
|
||
@discardableResult
|
||
@inlinable
|
||
@_alwaysEmitIntoClient
|
||
public func moveInitializeMemory<T: ~Copyable>(
|
||
as type: T.Type,
|
||
fromContentsOf source: UnsafeMutableBufferPointer<T>
|
||
) -> UnsafeMutableBufferPointer<T> {
|
||
let buffer = unsafe Base(rebasing: self)
|
||
return unsafe buffer.moveInitializeMemory(as: T.self, fromContentsOf: source)
|
||
}
|
||
|
||
/// Moves every element from an initialized source buffer slice into the
|
||
/// uninitialized memory referenced by this buffer slice, leaving
|
||
/// the source memory uninitialized and this slice's memory initialized.
|
||
///
|
||
/// When calling the `moveInitializeMemory(as:fromContentsOf:)` method,
|
||
/// the memory referenced by the buffer slice must be uninitialized,
|
||
/// or initialized to a trivial type. The buffer slice must reference
|
||
/// enough memory to store `source.count` elements, and it 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 slice 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 of `T` and is initialized. This method does not change
|
||
/// the binding state of the unused portion of the buffer slice, if any.
|
||
///
|
||
/// - 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.
|
||
/// The memory regions referenced by `source` and this buffer may overlap.
|
||
/// - Returns: A typed buffer referencing the initialized elements.
|
||
/// The returned buffer references memory starting at the same
|
||
/// base address as this slice, and its count is equal to `source.count`.
|
||
@discardableResult
|
||
@inlinable
|
||
@_alwaysEmitIntoClient
|
||
public func moveInitializeMemory<T>(
|
||
as type: T.Type,
|
||
fromContentsOf source: Slice<UnsafeMutableBufferPointer<T>>
|
||
) -> UnsafeMutableBufferPointer<T> {
|
||
let buffer = unsafe Base(rebasing: self)
|
||
return unsafe buffer.moveInitializeMemory(as: T.self, fromContentsOf: source)
|
||
}
|
||
|
||
/// Binds this buffer slice’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 slice 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<T>.stride`
|
||
/// instances of `T`.
|
||
@discardableResult
|
||
@inlinable
|
||
@_alwaysEmitIntoClient
|
||
public func bindMemory<T: ~Copyable>(
|
||
to type: T.Type
|
||
) -> UnsafeMutableBufferPointer<T> {
|
||
let buffer = unsafe Base(rebasing: self)
|
||
return unsafe buffer.bindMemory(to: T.self)
|
||
}
|
||
|
||
/// Executes the given closure while temporarily binding the buffer slice to
|
||
/// instances of type `T`.
|
||
///
|
||
/// Use this method when you have a buffer slice 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 slice 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 slice's start address must match the
|
||
/// alignment of `T` (as reported by `MemoryLayout<T>.alignment`). That is,
|
||
/// `Int(bitPattern: base.baseAddress+startIndex) % MemoryLayout<T>.alignment`
|
||
/// must equal zero.
|
||
///
|
||
/// - Note: A raw buffer slice 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 slice.
|
||
/// - 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.
|
||
@inlinable
|
||
@_alwaysEmitIntoClient
|
||
public func withMemoryRebound<T: ~Copyable, E: Error, Result: ~Copyable>(
|
||
to type: T.Type,
|
||
_ body: (UnsafeMutableBufferPointer<T>) throws(E) -> Result
|
||
) throws(E) -> Result {
|
||
let buffer = unsafe Base(rebasing: self)
|
||
return try unsafe buffer.withMemoryRebound(to: T.self, body)
|
||
}
|
||
|
||
/// Returns a typed buffer to the memory referenced by this buffer slice,
|
||
/// 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 slice's start address must match the
|
||
/// alignment of `T` (as reported by `MemoryLayout<T>.alignment`). That is,
|
||
/// `Int(bitPattern: base.baseAddress+startIndex) % MemoryLayout<T>.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.
|
||
@inlinable
|
||
@_alwaysEmitIntoClient
|
||
public func assumingMemoryBound<T: ~Copyable>(
|
||
to type: T.Type
|
||
) -> UnsafeMutableBufferPointer<T> {
|
||
let buffer = unsafe Base(rebasing: self)
|
||
return unsafe buffer.assumingMemoryBound(to: T.self)
|
||
}
|
||
|
||
/// Returns a new instance of the given type, read from the
|
||
/// specified offset into the buffer pointer slice's raw memory.
|
||
///
|
||
/// The memory at `offset` bytes into this buffer pointer slice
|
||
/// 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 underlying
|
||
/// buffer pointer's 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[0..<4].load(as: Int32.self)
|
||
/// let b = someBytes[4..<8].load(as: Int32.self)
|
||
///
|
||
/// The memory to read for the new instance must not extend beyond the
|
||
/// memory region represented by the buffer pointer slice---that is,
|
||
/// `offset + MemoryLayout<T>.size` must be less than or equal
|
||
/// to the slice's `count`.
|
||
///
|
||
/// - Parameters:
|
||
/// - offset: The offset into the slice's memory, in bytes, 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
|
||
/// slice's memory.
|
||
@inlinable
|
||
@_alwaysEmitIntoClient
|
||
public func load<T>(fromByteOffset offset: Int = 0, as type: T.Type) -> T {
|
||
let buffer = unsafe Base(rebasing: self)
|
||
return unsafe buffer.load(fromByteOffset: offset, as: T.self)
|
||
}
|
||
|
||
/// Returns a new instance of the given type, read from the
|
||
/// specified offset into the buffer pointer slice's raw memory.
|
||
///
|
||
/// 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 slice 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[..<4].loadUnaligned(as: Int32.self)
|
||
/// let b = someBytes[3...].loadUnaligned(as: Int32.self)
|
||
///
|
||
/// The memory to read for the new instance must not extend beyond the
|
||
/// memory region represented by the buffer pointer slice---that is,
|
||
/// `offset + MemoryLayout<T>.size` must be less than or equal
|
||
/// to the slice's `count`.
|
||
///
|
||
/// - Parameters:
|
||
/// - offset: The offset into the slice's memory, in bytes, 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.
|
||
@inlinable
|
||
@_alwaysEmitIntoClient
|
||
public func loadUnaligned<T : BitwiseCopyable>(
|
||
fromByteOffset offset: Int = 0,
|
||
as type: T.Type
|
||
) -> T {
|
||
let buffer = unsafe Base(rebasing: self)
|
||
return unsafe buffer.loadUnaligned(fromByteOffset: offset, as: T.self)
|
||
}
|
||
@inlinable
|
||
@_alwaysEmitIntoClient
|
||
public func loadUnaligned<T>(
|
||
fromByteOffset offset: Int = 0,
|
||
as type: T.Type
|
||
) -> T {
|
||
let buffer = unsafe Base(rebasing: self)
|
||
return unsafe buffer.loadUnaligned(fromByteOffset: offset, as: T.self)
|
||
}
|
||
|
||
/// Stores a value's bytes into the buffer pointer slice'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 memory region represented by the buffer pointer slice---that is,
|
||
/// `offset + MemoryLayout<T>.size` must be less than or equal
|
||
/// to the slice'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 slice'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`.
|
||
@inlinable
|
||
@_alwaysEmitIntoClient
|
||
public func storeBytes<T>(
|
||
of value: T, toByteOffset offset: Int = 0, as type: T.Type
|
||
) {
|
||
let buffer = unsafe Base(rebasing: self)
|
||
unsafe buffer.storeBytes(of: value, toByteOffset: offset, as: T.self)
|
||
}
|
||
}
|
||
|
||
extension Slice where Base == UnsafeRawBufferPointer {
|
||
|
||
/// Binds this buffer slice’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 slice 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<T>.stride`
|
||
/// instances of `T`.
|
||
@discardableResult
|
||
@inlinable
|
||
@_alwaysEmitIntoClient
|
||
public func bindMemory<T: ~Copyable>(
|
||
to type: T.Type
|
||
) -> UnsafeBufferPointer<T> {
|
||
let buffer = unsafe Base(rebasing: self)
|
||
return unsafe buffer.bindMemory(to: T.self)
|
||
}
|
||
|
||
/// Executes the given closure while temporarily binding the buffer slice to
|
||
/// instances of type `T`.
|
||
///
|
||
/// Use this method when you have a buffer slice 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 slice 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 slice's start address must match the
|
||
/// alignment of `T` (as reported by `MemoryLayout<T>.alignment`). That is,
|
||
/// `Int(bitPattern: base.baseAddress+startIndex) % MemoryLayout<T>.alignment`
|
||
/// must equal zero.
|
||
///
|
||
/// - Note: A raw buffer slice 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 slice.
|
||
/// - 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.
|
||
@inlinable
|
||
@_alwaysEmitIntoClient
|
||
public func withMemoryRebound<T: ~Copyable, E: Error, Result: ~Copyable>(
|
||
to type: T.Type,
|
||
_ body: (UnsafeBufferPointer<T>) throws(E) -> Result
|
||
) throws(E) -> Result {
|
||
let buffer = unsafe Base(rebasing: self)
|
||
return try unsafe buffer.withMemoryRebound(to: T.self, body)
|
||
}
|
||
|
||
/// Returns a typed buffer to the memory referenced by this buffer slice,
|
||
/// 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 slice's start address must match the
|
||
/// alignment of `T` (as reported by `MemoryLayout<T>.alignment`). That is,
|
||
/// `Int(bitPattern: base.baseAddress+startIndex) % MemoryLayout<T>.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.
|
||
@inlinable
|
||
@_alwaysEmitIntoClient
|
||
public func assumingMemoryBound<T: ~Copyable>(
|
||
to type: T.Type
|
||
) -> UnsafeBufferPointer<T> {
|
||
let buffer = unsafe Base(rebasing: self)
|
||
return unsafe buffer.assumingMemoryBound(to: T.self)
|
||
}
|
||
|
||
/// Returns a new instance of the given type, read from the
|
||
/// specified offset into the buffer pointer slice's raw memory.
|
||
///
|
||
/// The memory at `offset` bytes into this buffer pointer slice
|
||
/// 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 underlying
|
||
/// buffer pointer's 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[0..<4].load(as: Int32.self)
|
||
/// let b = someBytes[4..<8].load(as: Int32.self)
|
||
///
|
||
/// The memory to read for the new instance must not extend beyond the
|
||
/// memory region represented by the buffer pointer slice---that is,
|
||
/// `offset + MemoryLayout<T>.size` must be less than or equal
|
||
/// to the slice's `count`.
|
||
///
|
||
/// - Parameters:
|
||
/// - offset: The offset into the slice's memory, in bytes, 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
|
||
/// slice's memory.
|
||
@inlinable
|
||
@_alwaysEmitIntoClient
|
||
public func load<T>(fromByteOffset offset: Int = 0, as type: T.Type) -> T {
|
||
let buffer = unsafe Base(rebasing: self)
|
||
return unsafe buffer.load(fromByteOffset: offset, as: T.self)
|
||
}
|
||
|
||
/// Returns a new instance of the given type, read from the
|
||
/// specified offset into the buffer pointer slice's raw memory.
|
||
///
|
||
/// 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 slice 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[..<4].loadUnaligned(as: Int32.self)
|
||
/// let b = someBytes[3...].loadUnaligned(as: Int32.self)
|
||
///
|
||
/// The memory to read for the new instance must not extend beyond the
|
||
/// memory region represented by the buffer pointer slice---that is,
|
||
/// `offset + MemoryLayout<T>.size` must be less than or equal
|
||
/// to the slice's `count`.
|
||
///
|
||
/// - Parameters:
|
||
/// - offset: The offset into the slice's memory, in bytes, 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.
|
||
@inlinable
|
||
@_alwaysEmitIntoClient
|
||
public func loadUnaligned<T : BitwiseCopyable>(
|
||
fromByteOffset offset: Int = 0,
|
||
as type: T.Type
|
||
) -> T {
|
||
let buffer = unsafe Base(rebasing: self)
|
||
return unsafe buffer.loadUnaligned(fromByteOffset: offset, as: T.self)
|
||
}
|
||
@inlinable
|
||
@_alwaysEmitIntoClient
|
||
public func loadUnaligned<T>(
|
||
fromByteOffset offset: Int = 0,
|
||
as type: T.Type
|
||
) -> T {
|
||
let buffer = unsafe Base(rebasing: self)
|
||
return unsafe buffer.loadUnaligned(fromByteOffset: offset, as: T.self)
|
||
}
|
||
}
|
||
|
||
extension Slice {
|
||
/// Executes the given closure while temporarily binding the memory referenced
|
||
/// by this buffer slice to the given type.
|
||
///
|
||
/// Use this method when you have a buffer slice of memory bound to one type
|
||
/// and you need to access that memory as a buffer of another type. Accessing
|
||
/// memory as 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.
|
||
///
|
||
/// The number of instances of `T` referenced by the rebound buffer may be
|
||
/// different than the number of instances of `Element` referenced by the
|
||
/// original buffer slice. The number of instances of `T` will be calculated
|
||
/// at runtime.
|
||
///
|
||
/// Any instance of `T` within the re-bound region may be initialized or
|
||
/// uninitialized. Every instance of `Pointee` overlapping with a given
|
||
/// instance of `T` should have the same initialization state (i.e.
|
||
/// initialized or uninitialized.) Accessing a `T` whose underlying
|
||
/// `Pointee` storage is in a mixed initialization state shall be
|
||
/// undefined behaviour.
|
||
///
|
||
/// Because this range of memory is no longer bound to its `Element` type
|
||
/// while the `body` closure executes, do not access memory using the
|
||
/// original buffer slice from within `body`. Instead,
|
||
/// use the `body` closure's buffer argument to access the values
|
||
/// in memory as instances of type `T`.
|
||
///
|
||
/// After executing `body`, this method rebinds memory back to the original
|
||
/// `Element` type.
|
||
///
|
||
/// - Note: Only use this method to rebind the buffer slice's memory to a type
|
||
/// that is layout compatible with the currently bound `Element` type.
|
||
/// The stride of the temporary type (`T`) may be an integer multiple
|
||
/// or a whole fraction of `Element`'s stride.
|
||
/// To bind a region of memory to a type that does not match these
|
||
/// requirements, convert the buffer to a raw buffer and use the
|
||
/// `withMemoryRebound(to:)` method on the raw buffer.
|
||
/// If `T` and `Element` have different alignments, this buffer slice
|
||
/// must be aligned with the larger of the two alignments.
|
||
///
|
||
/// - Parameters:
|
||
/// - type: The type to temporarily bind the memory referenced by this
|
||
/// buffer slice. The type `T` must be layout compatible
|
||
/// with the pointer's `Element` type.
|
||
/// - body: A closure that takes a typed buffer to the
|
||
/// same memory as this buffer slice, only bound to type `T`. The buffer
|
||
/// parameter contains a number of complete instances of `T` based
|
||
/// on the capacity of the original buffer and the stride of `Element`.
|
||
/// The closure's buffer 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:_:)`
|
||
/// method.
|
||
/// - buffer: The buffer temporarily bound to `T`.
|
||
/// - Returns: The return value, if any, of the `body` closure parameter.
|
||
@inlinable
|
||
@_alwaysEmitIntoClient
|
||
public func withMemoryRebound<
|
||
T: ~Copyable, E: Error, Result: ~Copyable, Element
|
||
>(
|
||
to type: T.Type,
|
||
_ body: (UnsafeBufferPointer<T>) throws(E) -> Result
|
||
) throws(E) -> Result
|
||
where Base == UnsafeBufferPointer<Element>
|
||
{
|
||
let rebased = unsafe UnsafeBufferPointer<Element>(rebasing: self)
|
||
return try unsafe rebased.withMemoryRebound(to: T.self, body)
|
||
}
|
||
}
|
||
|
||
extension Slice {
|
||
|
||
/// Initializes every element in this buffer slice's memory to
|
||
/// a copy of the given value.
|
||
///
|
||
/// The destination memory must be uninitialized or the buffer's `Element`
|
||
/// must be a trivial type. After a call to `initialize(repeating:)`, the
|
||
/// entire region of memory referenced by this buffer slice is initialized.
|
||
///
|
||
/// - Parameter repeatedValue: The value with which to initialize this
|
||
/// buffer slice's memory.
|
||
@inlinable
|
||
@_alwaysEmitIntoClient
|
||
public func initialize<Element>(repeating repeatedValue: Element)
|
||
where Base == UnsafeMutableBufferPointer<Element> {
|
||
unsafe Base(rebasing: self).initialize(repeating: repeatedValue)
|
||
}
|
||
|
||
/// Initializes the buffer slice's memory with the given elements.
|
||
///
|
||
/// Prior to calling the `initialize(from:)` method on a buffer slice,
|
||
/// the memory it references must be uninitialized,
|
||
/// or the `Element` type must be a trivial type. After the call,
|
||
/// the memory referenced by the buffer slice up to, but not including,
|
||
/// the returned index is initialized.
|
||
/// The buffer slice must contain sufficient memory to accommodate
|
||
/// `source.underestimatedCount`.
|
||
///
|
||
/// The returned index is the position of the next uninitialized element
|
||
/// in the buffer slice, which is one past the last element written.
|
||
/// If `source` contains no elements, the returned index is equal to
|
||
/// the buffer's `startIndex`. If `source` contains an equal or greater number
|
||
/// of elements than the buffer slice can hold, the returned index is equal to
|
||
/// the buffer's `endIndex`.
|
||
///
|
||
/// - Parameter 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 an index to the next uninitialized element in the buffer.
|
||
@inlinable
|
||
@_alwaysEmitIntoClient
|
||
public func initialize<S>(
|
||
from source: S
|
||
) -> (unwritten: S.Iterator, index: Index)
|
||
where S: Sequence, Base == UnsafeMutableBufferPointer<S.Element> {
|
||
let buffer = unsafe Base(rebasing: self)
|
||
let (iterator, index) = unsafe buffer.initialize(from: source)
|
||
let distance = unsafe buffer.distance(from: buffer.startIndex, to: index)
|
||
return unsafe (iterator, startIndex.advanced(by: distance))
|
||
}
|
||
|
||
/// Initializes the buffer slice's memory with with
|
||
/// every element of the source.
|
||
///
|
||
/// Prior to calling the `initialize(fromContentsOf:)` method
|
||
/// on a buffer slice, the memory it references must be uninitialized,
|
||
/// or the `Element` type must be a trivial type. After the call,
|
||
/// the memory referenced by the buffer slice up to, but not including,
|
||
/// the returned index is initialized.
|
||
/// The buffer slice must reference enough memory to accommodate
|
||
/// `source.count` elements.
|
||
///
|
||
/// The returned index is the index of the next uninitialized element
|
||
/// in the buffer slice, one past the index of the last element written.
|
||
/// If `source` contains no elements, the returned index is equal to
|
||
/// the buffer slice's `startIndex`. If `source` contains as many elements
|
||
/// as the buffer slice can hold, the returned index is equal to
|
||
/// to the slice's `endIndex`.
|
||
///
|
||
/// - Precondition: `self.count` >= `source.count`
|
||
///
|
||
/// - Note: The memory regions referenced by `source` and this buffer slice
|
||
/// must not overlap.
|
||
///
|
||
/// - Parameter source: A collection of elements to be used to
|
||
/// initialize the buffer slice's storage.
|
||
/// - Returns: The index one past the last element of the buffer slice
|
||
/// initialized by this function.
|
||
@inlinable
|
||
@_alwaysEmitIntoClient
|
||
public func initialize<Element>(
|
||
fromContentsOf source: some Collection<Element>
|
||
) -> Index where Base == UnsafeMutableBufferPointer<Element> {
|
||
let buffer = unsafe Base(rebasing: self)
|
||
let index = unsafe buffer.initialize(fromContentsOf: source)
|
||
let distance = unsafe buffer.distance(from: buffer.startIndex, to: index)
|
||
return unsafe startIndex.advanced(by: distance)
|
||
}
|
||
|
||
/// Updates every element of this buffer slice's initialized memory.
|
||
///
|
||
/// The buffer slice’s memory must be initialized or its `Element`
|
||
/// must be a trivial type.
|
||
///
|
||
/// - Note: All buffer elements must already be initialized.
|
||
///
|
||
/// - Parameters:
|
||
/// - repeatedValue: The value used when updating this pointer's memory.
|
||
@inlinable
|
||
@_alwaysEmitIntoClient
|
||
public func update<Element>(repeating repeatedValue: Element)
|
||
where Base == UnsafeMutableBufferPointer<Element> {
|
||
unsafe Base(rebasing: self).update(repeating: repeatedValue)
|
||
}
|
||
|
||
/// Updates the buffer slice's initialized memory with the given elements.
|
||
///
|
||
/// The buffer slice's memory must be initialized or its `Element` type
|
||
/// must be a trivial type.
|
||
///
|
||
/// - Parameter source: A sequence of elements to be used to update
|
||
/// the contents of the buffer slice.
|
||
/// - Returns: An iterator to any elements of `source` that didn't fit in the
|
||
/// buffer slice, and the index one past the last updated element.
|
||
@inlinable
|
||
@_alwaysEmitIntoClient
|
||
public func update<S>(
|
||
from source: S
|
||
) -> (unwritten: S.Iterator, index: Index)
|
||
where S: Sequence, Base == UnsafeMutableBufferPointer<S.Element> {
|
||
let buffer = unsafe Base(rebasing: self)
|
||
let (iterator, index) = unsafe buffer.update(from: source)
|
||
let distance = unsafe buffer.distance(from: buffer.startIndex, to: index)
|
||
return unsafe (iterator, startIndex.advanced(by: distance))
|
||
}
|
||
|
||
/// Updates the buffer slice's initialized memory with
|
||
/// every element of the source.
|
||
///
|
||
/// Prior to calling the `update(fromContentsOf:)` method on a buffer
|
||
/// slice, the first `source.count` elements of the referenced memory must be
|
||
/// initialized, or the `Element` type must be a trivial type.
|
||
/// The buffer slice must reference enough initialized memory to accommodate
|
||
/// `source.count` elements.
|
||
///
|
||
/// The returned index is one past the index of the last element updated. If
|
||
/// `source` contains no elements, the returned index is the buffer slice's
|
||
/// `startIndex`. If `source` contains as many elements as the buffer slice
|
||
/// can hold, the returned index is the buffer slice's `endIndex`.
|
||
///
|
||
/// - Note: The memory regions referenced by `source` and this buffer slice
|
||
/// may overlap.
|
||
///
|
||
/// - Precondition: `self.count` >= `source.count`
|
||
///
|
||
/// - Parameter source: A collection of elements to be used to update
|
||
/// the buffer's contents.
|
||
/// - Returns: An index one past the index of the last element updated.
|
||
@inlinable
|
||
@_alwaysEmitIntoClient
|
||
public func update<Element>(
|
||
fromContentsOf source: some Collection<Element>
|
||
) -> Index where Base == UnsafeMutableBufferPointer<Element> {
|
||
let buffer = unsafe Base(rebasing: self)
|
||
let index = unsafe buffer.update(fromContentsOf: source)
|
||
let distance = unsafe buffer.distance(from: buffer.startIndex, to: index)
|
||
return unsafe startIndex.advanced(by: distance)
|
||
}
|
||
|
||
/// Moves every element of an initialized source buffer into the
|
||
/// uninitialized memory referenced by this buffer slice, leaving the
|
||
/// source memory uninitialized and this buffer slice's memory initialized.
|
||
///
|
||
/// Prior to calling the `moveInitialize(fromContentsOf:)` method on a
|
||
/// buffer slice, the memory it references must be uninitialized,
|
||
/// or its `Element` type must be a trivial type. After the call,
|
||
/// the memory referenced by the buffer slice up to, but not including,
|
||
/// the returned index is initialized. The memory referenced by
|
||
/// `source` is uninitialized after the function returns.
|
||
/// The buffer slice must reference enough memory to accommodate
|
||
/// `source.count` elements.
|
||
///
|
||
/// The returned index is the position of the next uninitialized element
|
||
/// in the buffer slice, one past the index of the last element written.
|
||
/// If `source` contains no elements, the returned index is equal to the
|
||
/// slice's `startIndex`. If `source` contains as many elements as the slice
|
||
/// can hold, the returned index is equal to the slice's `endIndex`.
|
||
///
|
||
/// - Note: The memory regions referenced by `source` and this buffer slice
|
||
/// may overlap.
|
||
///
|
||
/// - Precondition: `self.count` >= `source.count`
|
||
///
|
||
/// - Parameter source: A buffer containing the values to copy.
|
||
/// The memory region underlying `source` must be initialized.
|
||
/// - Returns: The index one past the last element of the buffer slice
|
||
/// initialized by this function.
|
||
@inlinable
|
||
@_alwaysEmitIntoClient
|
||
public func moveInitialize<Element>(
|
||
fromContentsOf source: UnsafeMutableBufferPointer<Element>
|
||
) -> Index where Base == UnsafeMutableBufferPointer<Element> {
|
||
let buffer = unsafe Base(rebasing: self)
|
||
let index = unsafe buffer.moveInitialize(fromContentsOf: source)
|
||
let distance = unsafe buffer.distance(from: buffer.startIndex, to: index)
|
||
return unsafe startIndex.advanced(by: distance)
|
||
}
|
||
|
||
/// Moves every element of an initialized source buffer slice into the
|
||
/// uninitialized memory referenced by this buffer slice, leaving the
|
||
/// source memory uninitialized and this buffer slice's memory initialized.
|
||
///
|
||
/// Prior to calling the `moveInitialize(fromContentsOf:)` method on a
|
||
/// buffer slice, the memory it references must be uninitialized,
|
||
/// or its `Element` type must be a trivial type. After the call,
|
||
/// the memory referenced by the buffer slice up to, but not including,
|
||
/// the returned index is initialized. The memory referenced by
|
||
/// `source` is uninitialized after the function returns.
|
||
/// The buffer slice must reference enough memory to accommodate
|
||
/// `source.count` elements.
|
||
///
|
||
/// The returned index is the position of the next uninitialized element
|
||
/// in the buffer slice, one past the index of the last element written.
|
||
/// If `source` contains no elements, the returned index is equal to the
|
||
/// slice's `startIndex`. If `source` contains as many elements as the slice
|
||
/// can hold, the returned index is equal to the slice's `endIndex`.
|
||
///
|
||
/// - Note: The memory regions referenced by `source` and this buffer slice
|
||
/// may overlap.
|
||
///
|
||
/// - Precondition: `self.count` >= `source.count`
|
||
///
|
||
/// - Parameter source: A buffer slice containing the values to copy.
|
||
/// The memory region underlying `source` must be initialized.
|
||
/// - Returns: The index one past the last element of the buffer slice
|
||
/// initialized by this function.
|
||
@inlinable
|
||
@_alwaysEmitIntoClient
|
||
public func moveInitialize<Element>(
|
||
fromContentsOf source: Slice<UnsafeMutableBufferPointer<Element>>
|
||
) -> Index where Base == UnsafeMutableBufferPointer<Element> {
|
||
let buffer = unsafe Base(rebasing: self)
|
||
let index = unsafe buffer.moveInitialize(fromContentsOf: source)
|
||
let distance = unsafe buffer.distance(from: buffer.startIndex, to: index)
|
||
return unsafe startIndex.advanced(by: distance)
|
||
}
|
||
|
||
/// Updates this buffer slice's initialized memory by
|
||
/// moving every element from the source buffer,
|
||
/// leaving the source memory uninitialized.
|
||
///
|
||
/// The region of memory starting at the beginning of this buffer slice and
|
||
/// covering `source.count` instances of its `Element` type must be
|
||
/// initialized, or its `Element` type must be a trivial type.
|
||
/// After calling `moveUpdate(fromContentsOf:)`,
|
||
/// the region of memory underlying `source` is uninitialized.
|
||
/// The buffer slice must reference enough initialized memory
|
||
/// to accommodate `source.count` elements.
|
||
///
|
||
/// The returned index is one past the index of the last element updated.
|
||
/// If `source` contains no elements, the returned index is equal to the
|
||
/// buffer's `startIndex`. If `source` contains as many elements as the buffer
|
||
/// slice can hold, the returned index is equal to the slice's `endIndex`.
|
||
///
|
||
/// - Note: The memory regions referenced by `source` and this buffer slice
|
||
/// must not overlap.
|
||
///
|
||
/// - Precondition: `self.count` >= `source.count`
|
||
///
|
||
/// - Parameter source: A buffer containing the values to move.
|
||
/// The memory region underlying `source` must be initialized.
|
||
/// - Returns: An index one past the index of the last element updated.
|
||
@inlinable
|
||
@_alwaysEmitIntoClient
|
||
public func moveUpdate<Element>(
|
||
fromContentsOf source: UnsafeMutableBufferPointer<Element>
|
||
) -> Index where Base == UnsafeMutableBufferPointer<Element> {
|
||
let buffer = unsafe Base(rebasing: self)
|
||
let index = unsafe buffer.moveUpdate(fromContentsOf: source)
|
||
let distance = unsafe buffer.distance(from: buffer.startIndex, to: index)
|
||
return unsafe startIndex.advanced(by: distance)
|
||
}
|
||
|
||
/// Updates this buffer slice's initialized memory initialized memory by
|
||
/// moving every element from the source buffer slice,
|
||
/// leaving the source memory uninitialized.
|
||
///
|
||
/// The region of memory starting at the beginning of this buffer slice and
|
||
/// covering `source.count` instances of its `Element` type must be
|
||
/// initialized, or its `Element` type must be a trivial type.
|
||
/// After calling `moveUpdate(fromContentsOf:)`,
|
||
/// the region of memory underlying `source` is uninitialized.
|
||
/// The buffer slice must reference enough initialized memory
|
||
/// to accommodate `source.count` elements.
|
||
///
|
||
/// The returned index is one past the index of the last element updated.
|
||
/// If `source` contains no elements, the returned index is equal to the
|
||
/// buffer's `startIndex`. If `source` contains as many elements as the buffer
|
||
/// slice can hold, the returned index is equal to the slice's `endIndex`.
|
||
///
|
||
/// - Note: The memory regions referenced by `source` and this buffer slice
|
||
/// must not overlap.
|
||
///
|
||
/// - Precondition: `self.count` >= `source.count`
|
||
///
|
||
/// - Parameter source: A buffer slice containing the values to move.
|
||
/// The memory region underlying `source` must be initialized.
|
||
/// - Returns: An index one past the index of the last element updated.
|
||
@inlinable
|
||
@_alwaysEmitIntoClient
|
||
public func moveUpdate<Element>(
|
||
fromContentsOf source: Slice<UnsafeMutableBufferPointer<Element>>
|
||
) -> Index where Base == UnsafeMutableBufferPointer<Element> {
|
||
let buffer = unsafe Base(rebasing: self)
|
||
let index = unsafe buffer.moveUpdate(fromContentsOf: source)
|
||
let distance = unsafe buffer.distance(from: buffer.startIndex, to: index)
|
||
return unsafe startIndex.advanced(by: distance)
|
||
}
|
||
|
||
/// Deinitializes every instance in this buffer slice.
|
||
///
|
||
/// The region of memory underlying this buffer slice must be fully
|
||
/// initialized. After calling `deinitialize(count:)`, the memory
|
||
/// is uninitialized, but still bound to the `Element` type.
|
||
///
|
||
/// - Note: All buffer elements must already be initialized.
|
||
///
|
||
/// - Returns: A raw buffer to the same range of memory as this buffer.
|
||
/// The range of memory is still bound to `Element`.
|
||
@discardableResult
|
||
@inlinable
|
||
@_alwaysEmitIntoClient
|
||
public func deinitialize<Element>() -> UnsafeMutableRawBufferPointer
|
||
where Base == UnsafeMutableBufferPointer<Element> {
|
||
unsafe Base(rebasing: self).deinitialize()
|
||
}
|
||
|
||
/// Initializes the element at `index` to the given value.
|
||
///
|
||
/// The memory underlying the destination element must be uninitialized,
|
||
/// or `Element` must be a trivial type. After a call to `initialize(to:)`,
|
||
/// the memory underlying this element of the buffer slice is initialized.
|
||
///
|
||
/// - Parameters:
|
||
/// - value: The value used to initialize the buffer element's memory.
|
||
/// - index: The index of the element to initialize
|
||
@inlinable
|
||
@_alwaysEmitIntoClient
|
||
public func initializeElement<Element>(at index: Int, to value: Element)
|
||
where Base == UnsafeMutableBufferPointer<Element> {
|
||
unsafe assert(startIndex <= index && index < endIndex)
|
||
unsafe base.baseAddress.unsafelyUnwrapped.advanced(by: index).initialize(to: value)
|
||
}
|
||
|
||
/// Retrieves and returns the element at `index`,
|
||
/// leaving that element's underlying memory uninitialized.
|
||
///
|
||
/// The memory underlying the element at `index` must be initialized.
|
||
/// After calling `moveElement(from:)`, the memory underlying this element
|
||
/// of the buffer slice is uninitialized, and still bound to type `Element`.
|
||
///
|
||
/// - Parameters:
|
||
/// - index: The index of the buffer element to retrieve and deinitialize.
|
||
/// - Returns: The instance referenced by this index in this buffer.
|
||
@inlinable
|
||
@_alwaysEmitIntoClient
|
||
public func moveElement<Element>(from index: Index) -> Element
|
||
where Base == UnsafeMutableBufferPointer<Element> {
|
||
unsafe assert(startIndex <= index && index < endIndex)
|
||
return unsafe base.baseAddress.unsafelyUnwrapped.advanced(by: index).move()
|
||
}
|
||
|
||
/// Deinitializes the memory underlying the element at `index`.
|
||
///
|
||
/// The memory underlying the element at `index` must be initialized.
|
||
/// After calling `deinitializeElement()`, the memory underlying this element
|
||
/// of the buffer slice is uninitialized, and still bound to type `Element`.
|
||
///
|
||
/// - Parameters:
|
||
/// - index: The index of the buffer element to deinitialize.
|
||
@inlinable
|
||
@_alwaysEmitIntoClient
|
||
public func deinitializeElement<Element>(at index: Base.Index)
|
||
where Base == UnsafeMutableBufferPointer<Element> {
|
||
unsafe assert(startIndex <= index && index < endIndex)
|
||
unsafe base.baseAddress.unsafelyUnwrapped.advanced(by: index).deinitialize(count: 1)
|
||
}
|
||
|
||
/// Executes the given closure while temporarily binding the memory referenced
|
||
/// by this buffer slice to the given type.
|
||
///
|
||
/// Use this method when you have a buffer slice of memory bound to one type
|
||
/// and you need to access that memory as a buffer of another type. Accessing
|
||
/// memory as 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.
|
||
///
|
||
/// The number of instances of `T` referenced by the rebound buffer may be
|
||
/// different than the number of instances of `Element` referenced by the
|
||
/// original buffer slice. The number of instances of `T` will be calculated
|
||
/// at runtime.
|
||
///
|
||
/// Any instance of `T` within the re-bound region may be initialized or
|
||
/// uninitialized. Every instance of `Pointee` overlapping with a given
|
||
/// instance of `T` should have the same initialization state (i.e.
|
||
/// initialized or uninitialized.) Accessing a `T` whose underlying
|
||
/// `Pointee` storage is in a mixed initialization state shall be
|
||
/// undefined behaviour.
|
||
///
|
||
/// Because this range of memory is no longer bound to its `Element` type
|
||
/// while the `body` closure executes, do not access memory using the
|
||
/// original buffer slice from within `body`. Instead,
|
||
/// use the `body` closure's buffer argument to access the values
|
||
/// in memory as instances of type `T`.
|
||
///
|
||
/// After executing `body`, this method rebinds memory back to the original
|
||
/// `Element` type.
|
||
///
|
||
/// - Note: Only use this method to rebind the buffer slice's memory to a type
|
||
/// that is layout compatible with the currently bound `Element` type.
|
||
/// The stride of the temporary type (`T`) may be an integer multiple
|
||
/// or a whole fraction of `Element`'s stride.
|
||
/// To bind a region of memory to a type that does not match these
|
||
/// requirements, convert the buffer slice to a raw buffer and use the
|
||
/// raw buffer's `withMemoryRebound(to:)` method.
|
||
/// If `T` and `Element` have different alignments, this buffer slice
|
||
/// must be aligned with the larger of the two alignments.
|
||
///
|
||
/// - Parameters:
|
||
/// - type: The type to temporarily bind the memory referenced by this
|
||
/// buffer slice. The type `T` must be layout compatible
|
||
/// with the pointer's `Element` type.
|
||
/// - body: A closure that takes a typed buffer to the
|
||
/// same memory as this buffer slice, only bound to type `T`. The buffer
|
||
/// parameter contains a number of complete instances of `T` based
|
||
/// on the capacity of the original buffer and the stride of `Element`.
|
||
/// The closure's buffer 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:_:)`
|
||
/// method.
|
||
/// - buffer: The buffer temporarily bound to `T`.
|
||
/// - Returns: The return value, if any, of the `body` closure parameter.
|
||
@inlinable
|
||
@_alwaysEmitIntoClient
|
||
public func withMemoryRebound<
|
||
T: ~Copyable, E: Error, Result: ~Copyable, Element
|
||
>(
|
||
to type: T.Type,
|
||
_ body: (UnsafeMutableBufferPointer<T>) throws(E) -> Result
|
||
) throws(E) -> Result
|
||
where Base == UnsafeMutableBufferPointer<Element>
|
||
{
|
||
try unsafe Base(rebasing: self).withMemoryRebound(to: T.self, body)
|
||
}
|
||
|
||
@inlinable
|
||
@_alwaysEmitIntoClient
|
||
public func withContiguousMutableStorageIfAvailable<R, Element>(
|
||
_ body: (_ buffer: inout UnsafeMutableBufferPointer<Element>) throws -> R
|
||
) rethrows -> R? where Base == UnsafeMutableBufferPointer<Element> {
|
||
try unsafe base.withContiguousStorageIfAvailable { buffer in
|
||
let start = unsafe base.baseAddress?.advanced(by: startIndex)
|
||
var slice = unsafe UnsafeMutableBufferPointer(start: start, count: count)
|
||
let (b,c) = (slice.baseAddress, slice.count)
|
||
defer {
|
||
unsafe _precondition(
|
||
slice.baseAddress == b && slice.count == c,
|
||
"withContiguousMutableStorageIfAvailable: replacing the buffer is not allowed")
|
||
}
|
||
return try unsafe body(&slice)
|
||
}
|
||
}
|
||
}
|