Skip to content

Commit a29db9d

Browse files
author
Dave Abrahams
committed
Add AnyUnicode prototype
Beginnings of sussing out type erasure for string-ish things
1 parent 493cdfe commit a29db9d

File tree

1 file changed

+378
-0
lines changed

1 file changed

+378
-0
lines changed

test/Prototypes/AnyUnicode.swift

Lines changed: 378 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,378 @@
1+
//===--- AnyUnicode.swift -------------------------------------------------===//
2+
//
3+
// This source file is part of the Swift.org open source project
4+
//
5+
// Copyright (c) 2014 - 2017 Apple Inc. and the Swift project authors
6+
// Licensed under Apache License v2.0 with Runtime Library Exception
7+
//
8+
// See https://swift.org/LICENSE.txt for license information
9+
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
10+
//
11+
//===----------------------------------------------------------------------===//
12+
// RUN: rm -rf %t && mkdir -p %t && %gyb -DWORD_BITS=%target-ptrsize %s -o %t/out.swift
13+
// RUN: %line-directive %t/out.swift -- %target-build-swift %t/out.swift -o %t/a.out -Onone
14+
// RUN: %line-directive %t/out.swift -- %target-run %t/a.out
15+
16+
// REQUIRES: executable_test
17+
import StdlibUnittest
18+
19+
struct UnicodeIndex : Comparable {
20+
var offset: Int64
21+
static func == (l: UnicodeIndex, r: UnicodeIndex) -> Bool {
22+
return l.offset == r.offset
23+
}
24+
static func < (l: UnicodeIndex, r: UnicodeIndex) -> Bool {
25+
return l.offset < r.offset
26+
}
27+
}
28+
29+
protocol AnyCodeUnits_ {
30+
typealias IndexDistance = Int64
31+
typealias Index = Int64
32+
typealias Element = UInt32
33+
var startIndex: Index { get }
34+
var endIndex: Index { get }
35+
func index(after: Index) -> Index
36+
func index(before: Index) -> Index
37+
func index(_ i: Index, offsetBy: Int64) -> Index
38+
subscript(i: Index) -> Element { get }
39+
// subscript(r: Range<Index>) -> AnyCodeUnits { get }
40+
41+
func withUnsafeElementStorage<R>(
42+
_ body: (UnsafeBufferPointer<Element>?) throws -> R
43+
) rethrows -> R
44+
45+
var contiguousStorage : ContiguousStorage<Element>? { get }
46+
}
47+
48+
struct AnyCodeUnits : RandomAccessCollection, AnyCodeUnits_ {
49+
typealias IndexDistance = Int64
50+
typealias Index = Int64
51+
typealias Element = UInt32
52+
53+
let base: AnyCodeUnits_
54+
55+
// FIXME: associated type deduction seems to need a hint here.
56+
typealias Indices = DefaultRandomAccessIndices<AnyCodeUnits>
57+
var startIndex: Index { return base.startIndex }
58+
var endIndex: Index { return base.endIndex }
59+
func index(after i: Index) -> Index { return base.index(after: i) }
60+
func index(before i: Index) -> Index { return base.index(before: i) }
61+
func index(_ i: Index, offsetBy: Int64) -> Index { return base.index(i, offsetBy: i) }
62+
subscript(i: Index) -> Element { return base[i] }
63+
64+
public func withUnsafeElementStorage<R>(
65+
_ body: (UnsafeBufferPointer<Element>?) throws -> R
66+
) rethrows -> R { return try base.withUnsafeElementStorage(body) }
67+
68+
public var contiguousStorage : ContiguousStorage<Element>? {
69+
return base.contiguousStorage
70+
}
71+
}
72+
73+
/// Adapts any random access collection of unsigned integer to AnyCodeUnits_
74+
struct AnyCodeUnitsZeroExtender<
75+
Base: RandomAccessCollection
76+
> : RandomAccessCollection, AnyCodeUnits_
77+
where Base.Iterator.Element : UnsignedInteger {
78+
typealias IndexDistance = Int64
79+
typealias Index = Int64
80+
typealias Element = UInt32
81+
// FIXME: associated type deduction seems to need a hint here.
82+
typealias Indices = DefaultRandomAccessIndices<AnyCodeUnitsZeroExtender>
83+
84+
let base: Base
85+
86+
var startIndex: Index { return 0 }
87+
var endIndex: Index { return numericCast(base.count) }
88+
89+
func index(after i: Index) -> Index {
90+
return numericCast(
91+
base.offset(of: base.index(after: base.index(atOffset: i))))
92+
}
93+
94+
func index(before i: Index) -> Index {
95+
return numericCast(
96+
base.offset(of: base.index(before: base.index(atOffset: i))))
97+
}
98+
99+
func index(_ i: Index, offsetBy n: Int64) -> Index {
100+
return numericCast(
101+
base.offset(
102+
of: base.index(base.index(atOffset: i),
103+
offsetBy: numericCast(n))))
104+
}
105+
106+
subscript(i: Index) -> Element {
107+
return numericCast(base[base.index(atOffset: i)])
108+
}
109+
110+
public func withUnsafeElementStorage<R>(
111+
_ body: (UnsafeBufferPointer<Element>?) throws -> R
112+
) rethrows -> R {
113+
return try base.withUnsafeElementStorage { b in
114+
if let b1 = b {
115+
if let b2 = b1 as Any as? UnsafeBufferPointer<Element> {
116+
return try body(b2)
117+
}
118+
}
119+
return try body(nil)
120+
}
121+
}
122+
123+
public var contiguousStorage : ContiguousStorage<Element>? {
124+
if let b = base.contiguousStorage {
125+
return b as Any as? ContiguousStorage<Element>
126+
}
127+
return nil
128+
}
129+
}
130+
131+
protocol AnyUTF16_ {
132+
typealias IndexDistance = Int64
133+
typealias Index = UnicodeIndex
134+
typealias Element = UInt16
135+
var startIndex: Index { get }
136+
var endIndex: Index { get }
137+
func index(after: Index) -> Index
138+
func index(before: Index) -> Index
139+
subscript(i: Index) -> Element { get }
140+
141+
func withUnsafeElementStorage<R>(
142+
_ body: (UnsafeBufferPointer<Element>?) throws -> R
143+
) rethrows -> R
144+
145+
var contiguousStorage : ContiguousStorage<Element>? { get }
146+
}
147+
148+
struct AnyUTF16 : BidirectionalCollection, AnyUTF16_ {
149+
let base: AnyUTF16_
150+
typealias IndexDistance = Int64
151+
typealias Index = UnicodeIndex
152+
typealias Element = UInt16
153+
var startIndex: Index { return base.startIndex }
154+
var endIndex: Index { return base.endIndex }
155+
func index(after i: Index) -> Index { return base.index(after: i) }
156+
func index(before i: Index) -> Index { return base.index(before: i) }
157+
subscript(i: Index) -> Element { return base[i] }
158+
public func withUnsafeElementStorage<R>(
159+
_ body: (UnsafeBufferPointer<Element>?) throws -> R
160+
) rethrows -> R { return try base.withUnsafeElementStorage(body) }
161+
162+
public var contiguousStorage : ContiguousStorage<Element>? {
163+
return base.contiguousStorage
164+
}
165+
}
166+
167+
/// Adapts any bidirectional collection of unsigned integer to AnyUTF16_
168+
struct AnyUTF16ZeroExtender<
169+
Base: BidirectionalCollection
170+
> : BidirectionalCollection, AnyUTF16_
171+
where Base.Iterator.Element : UnsignedInteger {
172+
typealias IndexDistance = Int64
173+
typealias Index = UnicodeIndex
174+
typealias Element = UInt16
175+
176+
let base: Base
177+
178+
var startIndex: Index { return Index(offset: 0) }
179+
var endIndex: Index { return Index(offset: numericCast(base.count)) }
180+
181+
func index(after i: Index) -> Index {
182+
return Index(offset: numericCast(
183+
base.offset(of: base.index(after: base.index(atOffset: i.offset)))))
184+
}
185+
186+
func index(before i: Index) -> Index {
187+
return Index(offset: numericCast(
188+
base.offset(of: base.index(before: base.index(atOffset: i.offset)))))
189+
}
190+
191+
func index(_ i: Index, offsetBy n: Int64) -> Index {
192+
return Index(offset: numericCast(
193+
base.offset(
194+
of: base.index(base.index(atOffset: i.offset),
195+
offsetBy: numericCast(n)))))
196+
}
197+
198+
subscript(i: Index) -> Element {
199+
return numericCast(base[base.index(atOffset: i.offset)])
200+
}
201+
202+
public func withUnsafeElementStorage<R>(
203+
_ body: (UnsafeBufferPointer<Element>?) throws -> R
204+
) rethrows -> R {
205+
return try base.withUnsafeElementStorage { b in
206+
if let b1 = b {
207+
if let b2 = b1 as Any as? UnsafeBufferPointer<Element> {
208+
return try body(b2)
209+
}
210+
}
211+
return try body(nil)
212+
}
213+
}
214+
215+
public var contiguousStorage : ContiguousStorage<Element>? {
216+
if let b = base.contiguousStorage {
217+
return b as Any as? ContiguousStorage<Element>
218+
}
219+
return nil
220+
}
221+
}
222+
223+
protocol AnyUnicodeBidirectionalUInt32_ {
224+
typealias IndexDistance = Int64
225+
typealias Index = UnicodeIndex
226+
typealias Element = UInt32
227+
var startIndex: Index { get }
228+
var endIndex: Index { get }
229+
func index(after: Index) -> Index
230+
func index(before: Index) -> Index
231+
subscript(i: Index) -> Element { get }
232+
233+
func withUnsafeElementStorage<R>(
234+
_ body: (UnsafeBufferPointer<Element>?) throws -> R
235+
) rethrows -> R
236+
237+
var contiguousStorage : ContiguousStorage<Element>? { get }
238+
}
239+
240+
struct AnyUnicodeBidirectionalUInt32 : BidirectionalCollection, AnyUnicodeBidirectionalUInt32_ {
241+
let base: AnyUnicodeBidirectionalUInt32_
242+
typealias IndexDistance = Int64
243+
typealias Index = UnicodeIndex
244+
typealias Element = UInt32
245+
var startIndex: Index { return base.startIndex }
246+
var endIndex: Index { return base.endIndex }
247+
func index(after i: Index) -> Index { return base.index(after: i) }
248+
func index(before i: Index) -> Index { return base.index(before: i) }
249+
subscript(i: Index) -> Element { return base[i] }
250+
public func withUnsafeElementStorage<R>(
251+
_ body: (UnsafeBufferPointer<Element>?) throws -> R
252+
) rethrows -> R { return try base.withUnsafeElementStorage(body) }
253+
254+
public var contiguousStorage : ContiguousStorage<Element>? {
255+
return base.contiguousStorage
256+
}
257+
}
258+
259+
/// Adapts any bidirectional collection of unsigned integer to AnyUnicodeBidirectionalUInt32_
260+
struct AnyUnicodeBidirectionalUInt32ZeroExtender<
261+
Base: BidirectionalCollection
262+
> : BidirectionalCollection, AnyUnicodeBidirectionalUInt32_
263+
where Base.Iterator.Element : UnsignedInteger {
264+
typealias IndexDistance = Int64
265+
typealias Index = UnicodeIndex
266+
typealias Element = UInt32
267+
268+
let base: Base
269+
270+
var startIndex: Index { return Index(offset: 0) }
271+
var endIndex: Index { return Index(offset: numericCast(base.count)) }
272+
273+
func index(after i: Index) -> Index {
274+
return Index(offset: numericCast(
275+
base.offset(of: base.index(after: base.index(atOffset: i.offset)))))
276+
}
277+
278+
func index(before i: Index) -> Index {
279+
return Index(offset: numericCast(
280+
base.offset(of: base.index(before: base.index(atOffset: i.offset)))))
281+
}
282+
283+
func index(_ i: Index, offsetBy n: Int64) -> Index {
284+
return Index(offset: numericCast(
285+
base.offset(
286+
of: base.index(base.index(atOffset: i.offset),
287+
offsetBy: numericCast(n)))))
288+
}
289+
290+
subscript(i: Index) -> Element {
291+
return numericCast(base[base.index(atOffset: i.offset)])
292+
}
293+
294+
public func withUnsafeElementStorage<R>(
295+
_ body: (UnsafeBufferPointer<Element>?) throws -> R
296+
) rethrows -> R {
297+
return try base.withUnsafeElementStorage { b in
298+
if let b1 = b {
299+
if let b2 = b1 as Any as? UnsafeBufferPointer<Element> {
300+
return try body(b2)
301+
}
302+
}
303+
return try body(nil)
304+
}
305+
}
306+
307+
public var contiguousStorage : ContiguousStorage<Element>? {
308+
if let b = base.contiguousStorage {
309+
return b as Any as? ContiguousStorage<Element>
310+
}
311+
return nil
312+
}
313+
}
314+
315+
protocol AnyCharacters_ {
316+
typealias IndexDistance = Int64
317+
typealias Index = UnicodeIndex
318+
typealias Element = UInt32
319+
var startIndex: Index { get }
320+
var endIndex: Index { get }
321+
func index(after: Index) -> Index
322+
func index(before: Index) -> Index
323+
subscript(i: Index) -> Element { get }
324+
325+
func withUnsafeElementStorage<R>(
326+
_ body: (UnsafeBufferPointer<Element>?) throws -> R
327+
) rethrows -> R
328+
329+
var contiguousStorage : ContiguousStorage<Element>? { get }
330+
}
331+
332+
struct AnyCharacters : BidirectionalCollection, AnyCharacters_ {
333+
let base: AnyCharacters_
334+
typealias IndexDistance = Int64
335+
typealias Index = UnicodeIndex
336+
typealias Element = UInt32
337+
var startIndex: Index { return base.startIndex }
338+
var endIndex: Index { return base.endIndex }
339+
func index(after i: Index) -> Index { return base.index(after: i) }
340+
func index(before i: Index) -> Index { return base.index(before: i) }
341+
subscript(i: Index) -> Element { return base[i] }
342+
public func withUnsafeElementStorage<R>(
343+
_ body: (UnsafeBufferPointer<Element>?) throws -> R
344+
) rethrows -> R { return try base.withUnsafeElementStorage(body) }
345+
346+
public var contiguousStorage : ContiguousStorage<Element>? {
347+
return base.contiguousStorage
348+
}
349+
}
350+
351+
protocol AnyUnicode {
352+
var encoding: AnyUnicodeEncoding { get }
353+
var codeUnits: AnyCodeUnits { get }
354+
var utf16: AnyUTF16 { get }
355+
var utf32: AnyUnicodeBidirectionalUInt32 { get }
356+
// FIXME: Can this be Random Access? If all encodings use a single code unit
357+
// per ASCII character and can statelessly identify a code unit that
358+
// represents ASCII, then yes. Look into, e.g. shift-JIS.
359+
var extendedASCII : AnyUnicodeBidirectionalUInt32 { get }
360+
var characters : AnyCharacters { get }
361+
362+
func isASCII(scan: Bool/* = true */) -> Bool
363+
func isLatin1(scan: Bool/* = true */) -> Bool
364+
func isNormalizedNFC(scan: Bool/* = true*/) -> Bool
365+
func isNormalizedNFD(scan: Bool/* = true*/) -> Bool
366+
func isInFastCOrDForm(scan: Bool/* = true*/) -> Bool
367+
}
368+
369+
var suite = TestSuite("AnyUnicode")
370+
suite.test("basics") {
371+
let g : [UInt16] = Array(3...7)
372+
let h : [UInt8] = Array(3...7)
373+
var x = AnyUTF16ZeroExtender(base: g)
374+
var y = AnyUTF16ZeroExtender(base: h)
375+
expectTrue(x.elementsEqual(y))
376+
}
377+
378+
runAllTests()

0 commit comments

Comments
 (0)