Swift 如何对不同的字节缓冲区类型进行抽象?(NSData[UInt8],&x2026;)
在Swift中访问字节缓冲区的方法有多种,最常用的方法可能是通过Swift 如何对不同的字节缓冲区类型进行抽象?(NSData[UInt8],&x2026;),swift,Swift,在Swift中访问字节缓冲区的方法有多种,最常用的方法可能是通过UnsafeBufferPointer,而实际的存储可以在NSData、[UInt8]、连续数组或其他地方 如果我在编写库代码,我希望它尽可能通用,并适应用户对字节缓冲区的选择,同时尽可能方便地使用。我当前的代码如下所示: import Foundation func stringFromUTF8Bytes(bytes: UnsafeBufferPointer<UInt8>) throws -> String {
UnsafeBufferPointer
,而实际的存储可以在NSData
、[UInt8]
、连续数组
或其他地方
如果我在编写库代码,我希望它尽可能通用,并适应用户对字节缓冲区的选择,同时尽可能方便地使用。我当前的代码如下所示:
import Foundation
func stringFromUTF8Bytes(bytes: UnsafeBufferPointer<UInt8>) throws -> String {
if let s = String(bytes: bytes, encoding: NSUTF8StringEncoding) {
return s
} else {
throw Error.StringEncodingFailure
}
}
func stringFromUTF8Bytes(bytes: ContiguousArray<UInt8>) throws -> String {
return try bytes.withUnsafeBufferPointer(stringFromUTF8Bytes)
}
func stringFromUTF8Bytes(bytes: [UInt8]) throws -> String {
return try bytes.withUnsafeBufferPointer(stringFromUTF8Bytes)
}
func stringFromUTF8Bytes(data: NSData) throws -> String {
return try data.withUnsafeBufferPointer(stringFromUTF8Bytes)
}
enum Error: ErrorType {
case StringEncodingFailure
}
但是我找不到一种方法来为泛型类型实现此协议,例如为[UInt8]
:
// error: constrained extension must be declared on the unspecialized generic type 'Array' with constraints specified by a 'where' clause
extension Array<UInt8>: BufferType { }
// error: same-type requirement makes generic parameter 'Element' non-generic
extension Array: BufferType where Element == UInt8 { }
//错误:必须在非专用泛型类型“Array”上声明受约束的扩展,并使用“where”子句指定的约束
扩展数组:缓冲类型{}
//错误:相同类型要求使泛型参数“Element”非泛型
扩展数组:BufferType,其中元素==UInt8{}
我的问题是:
- 是否有一种方法可以为例如
而不是像[UInt8]
这样的其他类型实现[NSWindowController]
协议缓冲类型
- 与第一点不同的是,允许任意数组真的有意义吗?我不这么认为,但也许我错过了什么
- 有没有更好的解决方案来解决我完全没有解决的问题(对不同的字节缓冲区类型进行抽象)
BufferType
协议,并约束协议的实际使用,而不是协议的实现。这类似于标准库中使用的SequenceType
protocol BufferType {
typealias Element
func withUnsafeBufferPointer<R>(@noescape body: (UnsafeBufferPointer<Element>) throws -> R) rethrows -> R
}
extension NSData: BufferType {
typealias Element = UInt8
func withUnsafeBufferPointer<R>(@noescape body: (UnsafeBufferPointer<UInt8>) throws -> R) rethrows -> R {
let bytesBufferPointer = UnsafeBufferPointer<UInt8>(start: UnsafePointer<UInt8>(bytes), count: length)
return try body(bytesBufferPointer)
}
}
extension UnsafeBufferPointer: BufferType {
func withUnsafeBufferPointer<R>(@noescape body: (UnsafeBufferPointer<Element>) throws -> R) rethrows -> R {
return try body(self)
}
}
extension Array: BufferType { }
extension ContiguousArray: BufferType { }
func stringFromUTF8BytesGeneric <BT: BufferType where BT.Element == UInt8> (bytes: BT) throws -> String {
switch(bytes.withUnsafeBufferPointer { String(bytes: $0, encoding: NSUTF8StringEncoding) }) {
case let .Some(str): return str
case .None: throw Error.StringEncodingFailure
}
}
// error: constrained extension must be declared on the unspecialized generic type 'Array' with constraints specified by a 'where' clause
extension Array<UInt8>: BufferType { }
// error: same-type requirement makes generic parameter 'Element' non-generic
extension Array: BufferType where Element == UInt8 { }
protocol BufferType {
typealias Element
func withUnsafeBufferPointer<R>(@noescape body: (UnsafeBufferPointer<Element>) throws -> R) rethrows -> R
}
extension NSData: BufferType {
typealias Element = UInt8
func withUnsafeBufferPointer<R>(@noescape body: (UnsafeBufferPointer<UInt8>) throws -> R) rethrows -> R {
let bytesBufferPointer = UnsafeBufferPointer<UInt8>(start: UnsafePointer<UInt8>(bytes), count: length)
return try body(bytesBufferPointer)
}
}
extension UnsafeBufferPointer: BufferType {
func withUnsafeBufferPointer<R>(@noescape body: (UnsafeBufferPointer<Element>) throws -> R) rethrows -> R {
return try body(self)
}
}
extension Array: BufferType { }
extension ContiguousArray: BufferType { }
func stringFromUTF8BytesGeneric <BT: BufferType where BT.Element == UInt8> (bytes: BT) throws -> String {
switch(bytes.withUnsafeBufferPointer { String(bytes: $0, encoding: NSUTF8StringEncoding) }) {
case let .Some(str): return str
case .None: throw Error.StringEncodingFailure
}
}
// both print "ABC"
print(try stringFromUTF8BytesGeneric([65, 66, 67]))
print(try stringFromUTF8BytesGeneric(ContiguousArray<UInt8>([65, 66, 67])))