Swift 斯威夫特的BSON?
我的问题在这一点上是非常开放的,但我很好奇是否有人在Swift中为BSON实现了类似SwiftyJSON的东西 我发现这个项目有一些东西,但它似乎只是现有C库的包装器(在iOS方面对我没有任何好处)。我只是在尝试移植/扭曲SwiftyJSON,到目前为止,它的内部结构略高于我的学习曲线,似乎只是平台的Swift 斯威夫特的BSON?,swift,bson,Swift,Bson,我的问题在这一点上是非常开放的,但我很好奇是否有人在Swift中为BSON实现了类似SwiftyJSON的东西 我发现这个项目有一些东西,但它似乎只是现有C库的包装器(在iOS方面对我没有任何好处)。我只是在尝试移植/扭曲SwiftyJSON,到目前为止,它的内部结构略高于我的学习曲线,似乎只是平台的JSONSerialization的包装 任何人也是如此 A) 意识到我的谷歌搜索还没有发现或者 B) 或者可以帮助我朝着正确的方向去设计这样的东西?(不想让别人为我工作) 旁白:为了避免“为什么不
JSONSerialization
的包装
任何人也是如此
A) 意识到我的谷歌搜索还没有发现或者
B) 或者可以帮助我朝着正确的方向去设计这样的东西?(不想让别人为我工作)
旁白:为了避免“为什么不直接使用json”的问题。。。这是因为我在另一边做了相当多的MongoDB,我使用了很多字符串和日期,为了便于结束,这些字符串和日期必须用JSON模糊地表示出来。。。最后我写了自己的。它不是所有BSON编码的完整解决方案,只是我正在使用的那些。找到如何使用Swift枚举的方法很有趣
import Foundation
extension GeneratorType {
mutating func next(n: Int) -> [Element] {
var result: [Element] = []
for _ in 1...n {
if let next = self.next() {
result.append(next)
} else {
break
}
}
return result
}
}
extension GeneratorType where Element:Comparable {
mutating func upTo(match:Element) -> [Element]? {
var result: [Element] = []
while let next = self.next() {
if next == match {
return result
}
else {
result.append(next)
}
}
return nil
}
}
extension String {
init?<S : SequenceType, C : UnicodeCodecType where S.Generator.Element == C.CodeUnit>
(codeUnits : S, inout codec : C) {
var str = ""
var generator = codeUnits.generate()
var done = false
while !done {
let r = codec.decode(&generator)
switch (r) {
case .EmptyInput:
done = true
case let .Result(val):
str.append(Character(val))
case .Error:
return nil
}
}
self = str
}
}
enum BSON {
static func toByteArray<T>(value: T) -> [UInt8] {
var io = value
return withUnsafePointer(&io) {
Array(UnsafeBufferPointer(start: UnsafePointer<UInt8>($0), count: sizeof(T)))
}
}
static func fromByteArray<T>(value: [UInt8], _: T.Type) -> T {
return value.withUnsafeBufferPointer {
return UnsafePointer<T>($0.baseAddress).memory
}
}
struct Field {
var name:String
var element:BSON
}
case double(Double)
case string(String)
case document([Field])
case array([BSON])
case binary([UInt8])
// case objectid((UInt8, UInt8, UInt8, UInt8, UInt8, UInt8, UInt8, UInt8, UInt8, UInt8, UInt8, UInt8))
case boolean(Bool)
case datetime(NSDate)
case null
case int32(Int32)
case int64(Int64)
init() {
self = .document([])
}
var bsonType:UInt8 {
switch self {
case .double: return 0x01
case .string: return 0x02
case .document: return 0x03
case .array: return 0x04
case .binary: return 0x05
// case .objectid: return 0x07
case .boolean: return 0x08
case .datetime: return 0x09
case .null: return 0x0A
case .int32: return 0x10
case .int64: return 0x12
}
}
subscript(key:String) -> BSON {
get {
switch self {
case .document (let fields):
for field in fields {
if field.name == key {
return field.element
}
}
return BSON.null
default:
return BSON.null
}
}
set(newValue) {
var newFields:[Field] = []
switch self {
case .document (let fields):
newFields = fields
var append = true
for (index, field) in newFields.enumerate() {
if field.name == key {
newFields[index].element = newValue
append = false
break
}
}
if append {
newFields.append(Field(name: key, element: newValue))
}
default:
newFields = [Field(name: key, element: newValue)]
}
self = .document(newFields)
}
}
subscript(index:Int) -> BSON {
get {
switch self {
case .array (let elements):
return index < elements.count ? elements[index] : BSON.null
default:
return BSON.null
}
}
set(newValue) {
switch self {
case .array (let elements):
if index < elements.count {
var newElements = elements
newElements[index] = newValue
self = .array(newElements)
}
default:
break
}
}
}
func encoded() -> [UInt8] {
switch self {
case double (let value):
return BSON.toByteArray(value)
case string (let value):
let encoded = value.utf8
return BSON.toByteArray(Int32(encoded.count + 1)) + encoded + [0]
case document (let fields):
var body:[UInt8] = []
for field in fields ?? [] {
body += [field.element.bsonType]
body += field.name.utf8
body += [0]
body += field.element.encoded()
}
body += [0]
return BSON.toByteArray(Int32(body.count + 4)) + body
case array (let elements):
var body:[UInt8] = []
for (index, element) in elements.enumerate() {
body += [element.bsonType]
body += String(index).utf8
body += [0]
body += element.encoded()
}
body += [0]
return BSON.toByteArray(Int32(body.count + 4)) + body
case binary (let bytes):
return BSON.toByteArray(Int32(bytes.count)) + [0x00] + bytes
// case objectid:
// return []
case boolean (let value):
return value ? [0x01] : [0x00]
case datetime (let value):
let since = Int64(value.timeIntervalSince1970 * 1000.0)
return BSON.toByteArray(since)
case null:
return []
case int32 (let value):
return BSON.toByteArray(value)
case int64 (let value):
return BSON.toByteArray(value)
}
}
static func decode(inout stream stream:IndexingGenerator<[UInt8]>, bsonType:UInt8 = 0x03) -> BSON {
switch bsonType {
case 0x01:
let bytes = stream.next(sizeof(Double))
return self.double(fromByteArray(bytes, Double.self))
case 0x02:
let _ = stream.next(sizeof(Int32)) // skip the count
if let buffer = stream.upTo(0) {
var codec = UTF8()
if let decoded = String(codeUnits: buffer, codec: &codec) {
return self.string(decoded)
}
}
fatalError("utf8 parse error!")
case 0x03:
var fields:[Field] = []
stream.next(sizeof(Int32)) // throw out size
while let bsonType = stream.next() {
if bsonType == 0 {
return self.document(fields)
}
if let buffer = stream.upTo(0) {
var codec = UTF8()
if let fieldName = String(codeUnits: buffer, codec: &codec) {
let element = BSON.decode(stream:&stream, bsonType: bsonType)
fields.append(Field(name: fieldName, element: element))
}
}
}
case 0x04:
var elements:[BSON] = []
stream.next(sizeof(Int32)) // throw out size
while let bsonType = stream.next() {
if bsonType == 0 {
return self.array(elements)
}
stream.upTo(0) // skip name
elements.append(BSON.decode(stream:&stream, bsonType: bsonType))
}
case 0x05:
let count = fromByteArray(stream.next(sizeof(Int32)), Int32.self)
assert(stream.next() == 0x00)
return self.binary(stream.next(Int(count)))
case 0x07:
break
case 0x08:
let value = stream.next()
return self.boolean(value == 0x01)
case 0x09:
let milliseconds = fromByteArray(stream.next(sizeof(Int64)), Int64.self)
let interval = NSTimeInterval(milliseconds) / 1000.0
return self.datetime(NSDate(timeIntervalSince1970: interval))
case 0x0A:
return self.null
case 0x10:
let value = fromByteArray(stream.next(sizeof(Int32)), Int32.self)
return self.int32(value)
case 0x12:
let value = fromByteArray(stream.next(sizeof(Int64)), Int64.self)
return self.int64(value)
default:
break
}
fatalError()
}
var document:BSON? {
switch self {
case .document:
return self
default:
return nil
}
}
var double:Double? {
switch self {
case .double (let value):
return value
default:
return nil
}
}
var int32:Int32? {
get {
switch self {
case .int32 (let value):
return value
default:
return nil
}
}
set {
if let newValue = newValue {
self = .int32(newValue)
}
else {
self = .null
}
}
}
var int64:Int64? {
switch self {
case .int64 (let value):
return value
default:
return nil
}
}
var boolean:Bool? {
switch self {
case .boolean (let value):
return value
default:
return nil
}
}
var binary:[UInt8]? {
switch self {
case .binary (let value):
return value
default:
return nil
}
}
var string:String? {
switch self {
case .string (let value):
return value
default:
return nil
}
}
var datetime:NSDate? {
switch self {
case .datetime (let value):
return value
default:
return nil
}
}
var array:[BSON]? {
switch self {
case .array (let elements):
return elements
default:
return nil
}
}
var isNull:Bool {
switch self {
case .null:
return true
default:
return false
}
}
var keyValues:[(String, BSON)] {
switch self {
case document (let fields):
return fields.map() { ($0.name, $0.element) }
default:
return []
}
}
}
extension BSON: Equatable {}
extension BSON.Field: Equatable {}
func == (a:BSON.Field, b:BSON.Field) -> Bool {
return a.name == b.name && a.element == b.element
}
func == (a:BSON, b:BSON) -> Bool {
switch (a, b) {
case (.double(let a), .double(let b)) where a == b: return true
case (.string(let a), .string(let b)) where a == b: return true
case (.document(let a), .document(let b)) where a == b: return true
case (.array(let a), .array(let b)) where a == b: return true
case (.binary(let a), .binary(let b)) where a == b: return true
case (.boolean(let a), .boolean(let b)) where a == b: return true
case (.datetime(let a), .datetime(let b)) where a.isEqualToDate(b): return true
case (.null, .null): return true
case (.int32(let a), .int32(let b)) where a == b: return true
case (.int64(let a), .int64(let b)) where a == b: return true
default: return false
}
}
protocol BSONConvertable {
var bson:BSON { get }
}
extension Int32: BSONConvertable {
var bson:BSON {
return BSON.int32(self)
}
}
extension Int64: BSONConvertable {
var bson:BSON {
return BSON.int64(self)
}
}
extension Int: BSONConvertable {
var bson:BSON {
let wide = self.toIntMax()
if Int32.min.toIntMax() <= wide && wide <= Int32.max.toIntMax() {
return BSON.int32(Int32(wide))
}
else {
return BSON.int64(Int64(wide))
}
}
}
extension Float:BSONConvertable {
var bson:BSON {
return Double(self).bson
}
}
extension Double:BSONConvertable {
var bson:BSON {
return BSON.double(self)
}
}
extension Bool:BSONConvertable {
var bson:BSON {
return BSON.boolean(self)
}
}
extension BSON:BSONConvertable {
var bson:BSON {
return self
}
}
extension NSDate:BSONConvertable {
var bson:BSON {
return BSON.datetime(self)
}
}
extension String:BSONConvertable {
var bson:BSON {
return BSON.string(self)
}
}
extension Array where Element:BSONConvertable {
var bson:BSON {
return BSON.array(self.map({$0.bson}))
}
}
<代码>导入基础
扩展生成器类型{
变异func next(n:Int)->[元素]{
变量结果:[元素]=[]
对于1…n中的uu{
如果let next=self.next(){
result.append(下一步)
}否则{
打破
}
}
返回结果
}
}
扩展生成器类型,其中元素:可比较{
将函数变为(匹配:元素)->[元素]{
变量结果:[元素]=[]
而let next=self.next(){
如果下一步==匹配{
返回结果
}
否则{
result.append(下一步)
}
}
归零
}
}
扩展字符串{
初始化?
(代码单位:S,输入/输出编解码器:C){
var str=“”
var生成器=codeUnits.generate()
var done=false
好啦!完成了{
设r=codec.decode(&generator)
开关(r){
案例.清空输入:
完成=正确
案例结果(val):
str.append(字符(val))
案例.错误:
归零
}
}
self=str
}
}
枚举BSON{
静态函数toByteArray(值:T)->[UInt8]{
var io=值
使用未安全指针返回(&io){
数组(UnsafeBufferPointer(开始:UnsafePointer($0),计数:sizeof(T)))
}
}
静态func fromByteArray(值:[UInt8],\uu:T.Type)->T{
返回值.withUnsafeBufferPointer{
返回未安全指针($0.baseAddress)。内存
}
}
结构域{
变量名称:String
var元素:BSON
}
双箱(双箱)
大小写字符串(字符串)
案例文档([字段])
案例数组([BSON])
大小写二进制([UInt8])
//案例对象((UInt8,UInt8,UInt8,UInt8,UInt8,UInt8,UInt8,UInt8,UInt8,UInt8,UInt8,UInt8))
大小写布尔(Bool)
案例日期时间(NSDate)
大小写空
案例int32(int32)
案例int64(int64)
init(){
self=.document([])
}
var bsonType:UInt8{
切换自身{
case.double:返回0x01
字符串:返回0x02
案例文档:返回0x03
大小写数组:返回0x04
大小写二进制:返回0x05
//case.objectid:返回0x07
大小写布尔值:返回0x08
案例.日期时间:返回0x09
大小写为空:返回0x0A
case.int32:返回0x10
case.int64:返回0x12
}
}
下标(键:字符串)->BSON{
得到{
切换自身{
案例文档(let字段):
一场接一场{
如果field.name==key{
返回字段.element
}
}
返回BSON.null
违约:
返回BSON.null
}
}
设置(新值){
var newFields:[字段]=[]
切换自身{
案例文档(let字段):
新字段=字段
var append=true
对于newFields.enumerate()中的(索引,字段){
如果field.name==key{
newFields[index]。元素=newValue
append=false
打破
}
}
如果追加{
追加(字段(名称:键,元素:newValue))
}
违约:
newFields=[字段(名称:键,元素:newValue)]
}
self=.document(新字段)
}
}
下标(索引:Int)->BSON{
得到{
切换自身{
case.array(let元素):
返回索引