Skip to content

Instantly share code, notes, and snippets.

@danielctull
Created January 10, 2020 11:49
Show Gist options
  • Save danielctull/fff429fbc04a1b8e7264b969f7f116ea to your computer and use it in GitHub Desktop.
Save danielctull/fff429fbc04a1b8e7264b969f7f116ea to your computer and use it in GitHub Desktop.
Trying to created nested property wrappers in Swift by conforming the property wrappers themselves to StringProtocol.
@propertyWrapper
struct B {
var wrappedValue: Int
}
@propertyWrapper
struct Clamp {
var wrappedValue: Int
}
struct C {
@Uppercased @Lowercased var foo = "HeelOLllo"
}
//func g() {
// var c = C()
// c.foo = 3
//}
@propertyWrapper
struct Lowercased<S: StringProtocol> {
private var text: S
var wrappedValue: S {
get { S(string: text.lowercased()) }
set { text = newValue }
}
init<AnyString: StringProtocol>(_ wrappedValue: AnyString) {
self.text = S(string: wrappedValue)
}
}
extension Lowercased: StringProtocol {
typealias UTF8View = S.UTF8View
typealias UTF16View = S.UTF16View
typealias UnicodeScalarView = S.UnicodeScalarView
var utf8: S.UTF8View { wrappedValue.utf8 }
var utf16: S.UTF16View { wrappedValue.utf16 }
var unicodeScalars: S.UnicodeScalarView { wrappedValue.unicodeScalars }
func lowercased() -> String { wrappedValue.lowercased() }
func uppercased() -> String { wrappedValue.uppercased() }
init(stringLiteral: String) {
self.init(S(string: stringLiteral))
}
init<C, Encoding>(decoding codeUnits: C, as sourceEncoding: Encoding.Type) where C : Collection, Encoding : _UnicodeEncoding, C.Element == Encoding.CodeUnit {
self.init(String(decoding: codeUnits, as: sourceEncoding))
}
init(cString nullTerminatedUTF8: UnsafePointer<CChar>) {
self.init(String(cString: nullTerminatedUTF8))
}
init<Encoding>(decodingCString nullTerminatedCodeUnits: UnsafePointer<Encoding.CodeUnit>, as sourceEncoding: Encoding.Type) where Encoding : _UnicodeEncoding {
self.init(String(decodingCString: nullTerminatedCodeUnits, as: sourceEncoding))
}
func withCString<Result>(_ body: (UnsafePointer<CChar>) throws -> Result) rethrows -> Result { try wrappedValue.withCString(body) }
func withCString<Result, Encoding>(encodedAs targetEncoding: Encoding.Type, _ body: (UnsafePointer<Encoding.CodeUnit>) throws -> Result) rethrows -> Result where Encoding : _UnicodeEncoding {
try wrappedValue.withCString(encodedAs: targetEncoding, body)
}
func index(before i: String.Index) -> String.Index { wrappedValue.index(before: i) }
func index(after i: String.Index) -> String.Index { wrappedValue.index(after: i) }
subscript(position: String.Index) -> Character { wrappedValue[position] }
var startIndex: String.Index { wrappedValue.startIndex }
var endIndex: String.Index { wrappedValue.endIndex }
var description: String { wrappedValue.description }
mutating func write(_ string: String) { text = S(string: string) }
func write<Target>(to target: inout Target) where Target : TextOutputStream {
wrappedValue.write(to: &target)
}
}
@propertyWrapper
struct Uppercased<S: StringProtocol> {
private var text: S
var wrappedValue: S {
get { S(string: text.uppercased()) }
set { text = newValue }
}
init<AnyString: StringProtocol>(_ wrappedValue: AnyString) {
self.text = S(string: wrappedValue)
}
}
extension Uppercased: StringProtocol {
typealias UTF8View = S.UTF8View
typealias UTF16View = S.UTF16View
typealias UnicodeScalarView = S.UnicodeScalarView
var utf8: S.UTF8View { wrappedValue.utf8 }
var utf16: S.UTF16View { wrappedValue.utf16 }
var unicodeScalars: S.UnicodeScalarView { wrappedValue.unicodeScalars }
func lowercased() -> String { wrappedValue.lowercased() }
func uppercased() -> String { wrappedValue.uppercased() }
init(stringLiteral: String) {
self.init(S(string: stringLiteral))
}
init<C, Encoding>(decoding codeUnits: C, as sourceEncoding: Encoding.Type) where C : Collection, Encoding : _UnicodeEncoding, C.Element == Encoding.CodeUnit {
self.init(String(decoding: codeUnits, as: sourceEncoding))
}
init(cString nullTerminatedUTF8: UnsafePointer<CChar>) {
self.init(String(cString: nullTerminatedUTF8))
}
init<Encoding>(decodingCString nullTerminatedCodeUnits: UnsafePointer<Encoding.CodeUnit>, as sourceEncoding: Encoding.Type) where Encoding : _UnicodeEncoding {
self.init(String(decodingCString: nullTerminatedCodeUnits, as: sourceEncoding))
}
func withCString<Result>(_ body: (UnsafePointer<CChar>) throws -> Result) rethrows -> Result { try wrappedValue.withCString(body) }
func withCString<Result, Encoding>(encodedAs targetEncoding: Encoding.Type, _ body: (UnsafePointer<Encoding.CodeUnit>) throws -> Result) rethrows -> Result where Encoding : _UnicodeEncoding {
try wrappedValue.withCString(encodedAs: targetEncoding, body)
}
func index(before i: String.Index) -> String.Index { wrappedValue.index(before: i) }
func index(after i: String.Index) -> String.Index { wrappedValue.index(after: i) }
subscript(position: String.Index) -> Character { wrappedValue[position] }
var startIndex: String.Index { wrappedValue.startIndex }
var endIndex: String.Index { wrappedValue.endIndex }
var description: String { wrappedValue.description }
mutating func write(_ string: String) { text = S(string: string) }
func write<Target>(to target: inout Target) where Target : TextOutputStream {
wrappedValue.write(to: &target)
}
}
extension StringProtocol {
init<AnyString: StringProtocol>(string: AnyString) {
var me = Self(stringLiteral: "")
string.withCString { me = Self.init(cString: $0) }
self = me
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment