//===----------------------------------------------------------*- 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.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( 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.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.stride` /// instances of `T`. @discardableResult @inlinable @_alwaysEmitIntoClient public func initializeMemory( as type: T.Type, repeating repeatedValue: T ) -> UnsafeMutableBufferPointer { 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( as type: S.Element.Type, from source: S ) -> (unwritten: S.Iterator, initialized: UnsafeMutableBufferPointer) { 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( as type: C.Element.Type, fromContentsOf source: C ) -> UnsafeMutableBufferPointer { 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( as type: T.Type, fromContentsOf source: UnsafeMutableBufferPointer ) -> UnsafeMutableBufferPointer { 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( as type: T.Type, fromContentsOf source: Slice> ) -> UnsafeMutableBufferPointer { 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.stride` /// instances of `T`. @discardableResult @inlinable @_alwaysEmitIntoClient public func bindMemory( to type: T.Type ) -> UnsafeMutableBufferPointer { 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.alignment`). That is, /// `Int(bitPattern: base.baseAddress+startIndex) % MemoryLayout.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( to type: T.Type, _ body: (UnsafeMutableBufferPointer) 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.alignment`). That is, /// `Int(bitPattern: base.baseAddress+startIndex) % 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. @inlinable @_alwaysEmitIntoClient public func assumingMemoryBound( to type: T.Type ) -> UnsafeMutableBufferPointer { 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.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(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.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( 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( 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.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( 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.stride` /// instances of `T`. @discardableResult @inlinable @_alwaysEmitIntoClient public func bindMemory( to type: T.Type ) -> UnsafeBufferPointer { 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.alignment`). That is, /// `Int(bitPattern: base.baseAddress+startIndex) % MemoryLayout.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( to type: T.Type, _ body: (UnsafeBufferPointer) 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.alignment`). That is, /// `Int(bitPattern: base.baseAddress+startIndex) % 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. @inlinable @_alwaysEmitIntoClient public func assumingMemoryBound( to type: T.Type ) -> UnsafeBufferPointer { 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.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(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.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( 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( 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) throws(E) -> Result ) throws(E) -> Result where Base == UnsafeBufferPointer { let rebased = unsafe UnsafeBufferPointer(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(repeating repeatedValue: Element) where Base == UnsafeMutableBufferPointer { 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( from source: S ) -> (unwritten: S.Iterator, index: Index) where S: Sequence, Base == UnsafeMutableBufferPointer { 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( fromContentsOf source: some Collection ) -> Index where Base == UnsafeMutableBufferPointer { 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(repeating repeatedValue: Element) where Base == UnsafeMutableBufferPointer { 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( from source: S ) -> (unwritten: S.Iterator, index: Index) where S: Sequence, Base == UnsafeMutableBufferPointer { 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( fromContentsOf source: some Collection ) -> Index where Base == UnsafeMutableBufferPointer { 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( fromContentsOf source: UnsafeMutableBufferPointer ) -> Index where Base == UnsafeMutableBufferPointer { 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( fromContentsOf source: Slice> ) -> Index where Base == UnsafeMutableBufferPointer { 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( fromContentsOf source: UnsafeMutableBufferPointer ) -> Index where Base == UnsafeMutableBufferPointer { 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( fromContentsOf source: Slice> ) -> Index where Base == UnsafeMutableBufferPointer { 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() -> UnsafeMutableRawBufferPointer where Base == UnsafeMutableBufferPointer { 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(at index: Int, to value: Element) where Base == UnsafeMutableBufferPointer { 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(from index: Index) -> Element where Base == UnsafeMutableBufferPointer { 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(at index: Base.Index) where Base == UnsafeMutableBufferPointer { 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) throws(E) -> Result ) throws(E) -> Result where Base == UnsafeMutableBufferPointer { try unsafe Base(rebasing: self).withMemoryRebound(to: T.self, body) } @inlinable @_alwaysEmitIntoClient public func withContiguousMutableStorageIfAvailable( _ body: (_ buffer: inout UnsafeMutableBufferPointer) throws -> R ) rethrows -> R? where Base == UnsafeMutableBufferPointer { 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) } } }