44// RUN: -enable-experimental-feature NoncopyableGenerics \
55// RUN: -enable-experimental-lifetime-dependence-inference \
66// RUN: -Xllvm -enable-lifetime-dependence-diagnostics
7+
8+ // REQUIRES: asserts
9+ // REQUIRES: swift_in_compiler
710// REQUIRES: noncopyable_generics
811
12+ // Incrementally testing https://github.pie.apple.com/guillaume-l/BufferView with lifetime dependence
13+
14+ // TODO: Use real Range
15+ public struct FakeRange < Bound> {
16+ public let lowerBound : Bound
17+ public let upperBound : Bound
18+ }
19+
20+ // TODO: Use real Optional
21+ public enum FakeOptional < T> {
22+ case none
23+ case some( T )
24+ }
25+
26+ public struct BufferViewIndex < Element> {
27+ let _rawValue : UnsafeRawPointer
28+
29+ internal init ( rawValue: UnsafeRawPointer ) {
30+ _rawValue = rawValue
31+ }
32+
33+ var isAligned : Bool {
34+ ( Int ( bitPattern: _rawValue) & ( MemoryLayout < Element > . alignment- 1 ) ) == 0
35+ }
36+ }
37+
38+ extension BufferViewIndex : Equatable { }
39+
40+ extension BufferViewIndex : Hashable { }
41+
42+ extension BufferViewIndex : Strideable {
43+ public typealias Stride = Int
44+
45+ public func distance( to other: BufferViewIndex ) -> Int {
46+ let bytes = _rawValue. distance ( to: other. _rawValue)
47+ let ( q, r) = bytes. quotientAndRemainder ( dividingBy: MemoryLayout< Element> . stride)
48+ precondition ( r == 0 )
49+ return q
50+ }
51+
52+ public func advanced( by n: Int ) -> BufferViewIndex {
53+ . init( rawValue: _rawValue. advanced ( by: n &* MemoryLayout< Element> . stride) )
54+ }
55+ }
56+
57+ extension BufferViewIndex : Comparable {
58+ public static func < ( lhs: BufferViewIndex , rhs: BufferViewIndex ) -> Bool {
59+ lhs. _rawValue < rhs. _rawValue
60+ }
61+ }
62+
963public struct BufferView < Element> : ~ Escapable {
10- public typealias Index = Int
11- public typealias Pointer = UnsafePointer < Element >
12- public let baseAddress : Pointer
64+ let start : BufferViewIndex < Element >
1365 public let count : Int
14-
15- // TODO: This should be a failable initializer
16- // Currently optional is Escapable, so we cant yet write it.
17- public init < Storage> ( unsafeBuffer: UnsafeBufferPointer < Element > ,
18- storage: borrowing Storage )
19- -> _borrow( storage) Self {
20- let baseAddress = unsafeBuffer. baseAddress!
21- self = BufferView < Element > ( baseAddress: baseAddress,
22- count: unsafeBuffer. count)
23- return self
24- }
25- // unsafe private API
66+ private var baseAddress : UnsafeRawPointer { start. _rawValue }
67+
68+ public init < Owner> (
69+ baseAddress: UnsafeRawPointer ,
70+ count: Int ,
71+ dependsOn owner: borrowing Owner
72+ ) {
73+ self . init (
74+ start: . init( rawValue: baseAddress) , count: count, dependsOn: owner
75+ )
76+ }
77+ init < Owner> (
78+ start index: BufferViewIndex < Element > ,
79+ count: Int ,
80+ dependsOn owner: borrowing Owner
81+ ) {
82+ precondition ( count >= 0 , " Count must not be negative " )
83+ if !_isPOD( Element . self) {
84+ precondition (
85+ index. isAligned,
86+ " baseAddress must be properly aligned for \( Element . self) "
87+ )
88+ }
89+ self . start = index
90+ self . count = count
91+ }
2692 @_unsafeNonescapableResult
27- init ( baseAddress: Pointer , count: Int ) {
93+ init ( start index: BufferViewIndex < Element > ,
94+ count: Int ) {
2895 precondition ( count >= 0 , " Count must not be negative " )
29- self . baseAddress = baseAddress
96+ if !_isPOD( Element . self) {
97+ precondition (
98+ index. isAligned,
99+ " baseAddress must be properly aligned for \( Element . self) "
100+ )
101+ }
102+ self . start = index
30103 self . count = count
31104 }
32- subscript ( _ index: Index) - > Element? {
33- if ( index < 0 || index >= count) {
34- return nil
105+ }
106+ // TODO: extend Collection, BidirectionalCollection, RandomAccessCollection {
107+ extension BufferView {
108+ public typealias Index = BufferViewIndex < Element >
109+ public typealias SubSequence = Self
110+
111+ public var startIndex : Index { start }
112+ public var endIndex : Index { start. advanced ( by: count) }
113+
114+ public subscript( position: Index ) -> Element {
115+ get {
116+ if _isPOD ( Element . self) {
117+ return position. _rawValue. loadUnaligned ( as: Element . self)
118+ }
119+ else {
120+ return position. _rawValue. load ( as: Element . self)
121+ }
122+ }
123+ }
124+
125+ public subscript( bounds: FakeRange < BufferViewIndex < Element > > ) -> Self {
126+ get {
127+ BufferView (
128+ start: bounds. lowerBound,
129+ count: bounds. upperBound. distance ( to: bounds. lowerBound) / MemoryLayout< Element> . stride
130+ )
35131 }
36- return baseAddress [ index]
37132 }
38133}
39134
@@ -47,14 +142,17 @@ extension Array {
47142 // rdar://123071321
48143 var view : BufferView < Element > {
49144 var _view : BufferView < Element > ?
50- withUnsafeBufferPointer {
51- _view = BufferView ( unsafeBuffer : $0, storage : self )
145+ withUnsafePointer ( to : self ) {
146+ _view = BufferView ( baseAddress : $0, count : self . count , dependsOn : self )
52147 }
53148 return _view!
54149 }
55150}
56151
57- public func array_view_element( a: [ Int ] , i: Int ) -> Int {
58- a. view [ i] !
152+ public func array_view_element( a: [ Int ] , i: BufferViewIndex < Int > ) -> Int {
153+ a. view [ i]
59154}
60155
156+ public func array_view_slice_element( a: [ Int ] , sliceIdx: FakeRange < BufferViewIndex < Int > > , Idx: BufferViewIndex < Int > ) -> Int {
157+ a. view [ sliceIdx] [ Idx]
158+ }
0 commit comments