@@ -419,6 +419,40 @@ public struct IndexingIterator<
419
419
internal var _position : Elements . Index
420
420
}
421
421
422
+ //===--- Contiguous Storage Access ----------------------------------------===//
423
+ //
424
+ // We're unsure which idiom will be best for users and implementors of
425
+ // Collections, and which, if any, will be more optimizable, so we have two
426
+ // schemes:
427
+ //
428
+ // 1. a contiguousStorage property that is an optional instance of
429
+ // ContiguousStorage (below)
430
+ //
431
+ // 2. a withUnsafeElementStorage(_ body: ... ) method whose body takes an
432
+ // optional UnsafeBufferPointer
433
+ //
434
+ // I can't figure out how to get the first one to support throwing closures.
435
+ // We may not know which one is best until we handle the mutable storage case.
436
+ //
437
+ // Note: this should be for access to *already existing* contiguous storage.
438
+ // Lazily-bridged Arrays will create that storage on demand, so the conformance
439
+ // is imperfect.
440
+ // ===----------------------------------------------------------------------===//
441
+ /// A type that grants access to a collection's contiguous storage.
442
+ public struct ContiguousStorage < Element> {
443
+ /// Invokes `body` on the contiguous storage and returns the result.
444
+ public func withUnsafeBufferPointer< R> (
445
+ _ body: ( UnsafeBufferPointer < Element > ) -> R
446
+ ) -> R {
447
+ var r : R !
448
+ accessor { p in
449
+ r = body ( p)
450
+ }
451
+ return r
452
+ }
453
+ let accessor : ( ( UnsafeBufferPointer < Element > ) -> Void ) -> Void
454
+ }
455
+
422
456
/// A sequence whose elements can be traversed multiple times,
423
457
/// nondestructively, and accessed by indexed subscript.
424
458
///
@@ -561,6 +595,32 @@ public protocol Collection : _Indexable, Sequence {
561
595
/// type.
562
596
associatedtype Iterator : IteratorProtocol = IndexingIterator < Self >
563
597
598
+ /// A type that provides access to sub-structure of the collection
599
+ associatedtype Segments : _Indexable = EmptyCollection < Self >
600
+ // where Segments : Collection, Segments.Iterator.Element : Collection,
601
+ // Segments.Iterator.Element.Iterator.Element == Iterator.Element
602
+
603
+ /// The collection's sub-structure, if any
604
+ ///
605
+ /// Anything for which a complete traversal can be most easily written using a
606
+ /// nested loop should provide segments.
607
+ var segments : Segments ? { get }
608
+
609
+ /// The collection's contiguous storage, if any
610
+ ///
611
+ /// Only non-nil if *all* of the collection's elements are stored contiguously
612
+ /// in memory. A collection can vend multiple segments, each vending its own
613
+ /// non-nil contiguousStorage, if there are multiple contiguous memory
614
+ /// regions.
615
+ ///
616
+ /// Note: a collection may choose to provide only `withUnsafeElementStorage`,
617
+ /// in which case a default for contiguousStorage will be provided.
618
+ var contiguousStorage : ContiguousStorage < Iterator . Element > ? { get }
619
+
620
+ func withUnsafeElementStorage< R> (
621
+ _ body: ( UnsafeBufferPointer < Iterator . Element > ? ) throws -> R
622
+ ) rethrows -> R
623
+
564
624
// FIXME(ABI)#179 (Type checker): Needed here so that the `Iterator` is properly deduced from
565
625
// a custom `makeIterator()` function. Otherwise we get an
566
626
// `IndexingIterator`. <rdar://problem/21539115>
@@ -1182,6 +1242,35 @@ extension Collection where SubSequence == Self {
1182
1242
}
1183
1243
}
1184
1244
1245
+ /// Default implementation of Segments for collections that don't expose any
1246
+ /// sub-structure.
1247
+ extension Collection where Segments == EmptyCollection < Self > {
1248
+ public var segments : Segments ? { return Segments ( ) }
1249
+ }
1250
+
1251
+ extension Collection {
1252
+ // Default implementation of contiguousStorage in terms of
1253
+ // withUnsafeElementStorage. This seems very unlikely to optimize well.
1254
+ public var contiguousStorage : ContiguousStorage < Iterator . Element > ? {
1255
+ // FIXME: The straightforward formulation using a closure doesn't work.
1256
+ // <rdar://30448445> Crash compiling CoreAudio
1257
+ func factory( p: UnsafeBufferPointer < Iterator . Element > ? )
1258
+ -> ContiguousStorage < Iterator . Element > ? {
1259
+ return p == nil ? nil : ContiguousStorage {
1260
+ ( body: ( UnsafeBufferPointer < Iterator . Element > ) -> Void ) in
1261
+ self . withUnsafeElementStorage { body ( $0!) }
1262
+ }
1263
+ }
1264
+ return withUnsafeElementStorage ( factory)
1265
+ }
1266
+
1267
+ public func withUnsafeElementStorage< R> (
1268
+ _ body: ( UnsafeBufferPointer < Iterator . Element > ? ) throws -> R
1269
+ ) rethrows -> R {
1270
+ return try body ( nil )
1271
+ }
1272
+ }
1273
+
1185
1274
/// Default implementations of core requirements
1186
1275
extension Collection {
1187
1276
/// A Boolean value indicating whether the collection is empty.
0 commit comments