4
4
// RUN: -enable-experimental-feature NoncopyableGenerics \
5
5
// RUN: -enable-experimental-lifetime-dependence-inference \
6
6
// RUN: -Xllvm -enable-lifetime-dependence-diagnostics
7
+
8
+ // REQUIRES: asserts
9
+ // REQUIRES: swift_in_compiler
7
10
// REQUIRES: noncopyable_generics
8
11
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
+
9
63
public 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 >
13
65
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
+ }
26
92
@_unsafeNonescapableResult
27
- init ( baseAddress: Pointer , count: Int ) {
93
+ init ( start index: BufferViewIndex < Element > ,
94
+ count: Int ) {
28
95
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
30
103
self . count = count
31
104
}
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
+ )
35
131
}
36
- return baseAddress [ index]
37
132
}
38
133
}
39
134
@@ -47,14 +142,17 @@ extension Array {
47
142
// rdar://123071321
48
143
var view : BufferView < Element > {
49
144
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 )
52
147
}
53
148
return _view!
54
149
}
55
150
}
56
151
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]
59
154
}
60
155
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