//===----------------------------------------------------------------------===// // // This source file is part of the Swift.org open source project // // Copyright (c) 2021 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 // //===----------------------------------------------------------------------===// /// This file is copied from swift-collections and should not be modified here. /// Rather all changes should be made to swift-collections and copied back. import Swift @unsafe internal struct _UnsafeWrappedBuffer { internal let first: UnsafeBufferPointer internal let second: UnsafeBufferPointer? internal init( _ first: UnsafeBufferPointer, _ second: UnsafeBufferPointer? = nil ) { unsafe self.first = unsafe first unsafe self.second = unsafe second unsafe assert(first.count > 0 || second == nil) } internal init( start: UnsafePointer, count: Int ) { unsafe self.init(UnsafeBufferPointer(start: start, count: count)) } internal init( first start1: UnsafePointer, count count1: Int, second start2: UnsafePointer, count count2: Int ) { unsafe self.init(UnsafeBufferPointer(start: start1, count: count1), UnsafeBufferPointer(start: start2, count: count2)) } internal var count: Int { unsafe first.count + (second?.count ?? 0) } } @unsafe internal struct _UnsafeMutableWrappedBuffer { internal let first: UnsafeMutableBufferPointer internal let second: UnsafeMutableBufferPointer? internal init( _ first: UnsafeMutableBufferPointer, _ second: UnsafeMutableBufferPointer? = nil ) { unsafe self.first = unsafe first unsafe self.second = unsafe second?.count == 0 ? nil : second unsafe assert(first.count > 0 || second == nil) } internal init( start: UnsafeMutablePointer, count: Int ) { unsafe self.init(UnsafeMutableBufferPointer(start: start, count: count)) } internal init( first start1: UnsafeMutablePointer, count count1: Int, second start2: UnsafeMutablePointer, count count2: Int ) { unsafe self.init(UnsafeMutableBufferPointer(start: start1, count: count1), UnsafeMutableBufferPointer(start: start2, count: count2)) } internal init(mutating buffer: _UnsafeWrappedBuffer) { unsafe self.init(.init(mutating: buffer.first), buffer.second.map { unsafe .init(mutating: $0) }) } } extension _UnsafeMutableWrappedBuffer { internal var count: Int { unsafe first.count + (second?.count ?? 0) } internal func prefix(_ n: Int) -> Self { assert(n >= 0) if unsafe n >= self.count { return unsafe self } if unsafe n <= first.count { return unsafe Self(first.prefix(n)._rebased()) } return unsafe Self(first, second!.prefix(n - first.count)._rebased()) } internal func suffix(_ n: Int) -> Self { assert(n >= 0) if unsafe n >= self.count { return unsafe self } guard let second = unsafe second else { return unsafe Self(first.suffix(n)._rebased()) } if n <= second.count { return unsafe Self(second.suffix(n)._rebased()) } return unsafe Self(first.suffix(n - second.count)._rebased(), second) } } extension _UnsafeMutableWrappedBuffer { internal func deinitialize() { unsafe first._deinitializeAll() unsafe second?._deinitializeAll() } internal func initialize( fromPrefixOf iterator: inout I ) -> Int where I.Element == Element { var copied = 0 var gap = unsafe first var wrapped = false while true { if copied == gap.count { guard !wrapped, let second = unsafe second, second.count > 0 else { break } unsafe gap = unsafe second copied = 0 wrapped = true } guard let next = iterator.next() else { break } unsafe (gap.baseAddress! + copied).initialize(to: next) copied += 1 } return unsafe wrapped ? first.count + copied : copied } internal func initialize( fromSequencePrefix elements: __owned S ) -> (iterator: S.Iterator, count: Int) where S.Element == Element { guard unsafe second == nil || first.count >= elements.underestimatedCount else { var it = elements.makeIterator() let copied = unsafe initialize(fromPrefixOf: &it) return (it, copied) } // Note: Array._copyContents traps when not given enough space, so we // need to check if we have enough contiguous space available above. // // FIXME: Add support for segmented (a.k.a. piecewise contiguous) // collections to the stdlib. var (it, copied) = unsafe elements._copyContents(initializing: first) if unsafe copied == first.count, let second = unsafe second { var i = 0 while i < second.count { guard let next = it.next() else { break } unsafe (second.baseAddress! + i).initialize(to: next) i += 1 } copied += i } return (it, copied) } internal func initialize( from elements: __owned C ) where C.Element == Element { unsafe assert(self.count == elements.count) if let second = unsafe second { let wrap = unsafe elements.index(elements.startIndex, offsetBy: first.count) unsafe first._initialize(from: elements[..( from elements: C ) where C.Element == Element { unsafe assert(elements.count == self.count) unsafe deinitialize() unsafe initialize(from: elements) } }