Swift 斯威夫特的BSON?

Swift 斯威夫特的BSON?,swift,bson,Swift,Bson,我的问题在这一点上是非常开放的,但我很好奇是否有人在Swift中为BSON实现了类似SwiftyJSON的东西 我发现这个项目有一些东西,但它似乎只是现有C库的包装器(在iOS方面对我没有任何好处)。我只是在尝试移植/扭曲SwiftyJSON,到目前为止,它的内部结构略高于我的学习曲线,似乎只是平台的JSONSerialization的包装 任何人也是如此 A) 意识到我的谷歌搜索还没有发现或者 B) 或者可以帮助我朝着正确的方向去设计这样的东西?(不想让别人为我工作) 旁白:为了避免“为什么不

我的问题在这一点上是非常开放的,但我很好奇是否有人在Swift中为BSON实现了类似SwiftyJSON的东西

我发现这个项目有一些东西,但它似乎只是现有C库的包装器(在iOS方面对我没有任何好处)。我只是在尝试移植/扭曲SwiftyJSON,到目前为止,它的内部结构略高于我的学习曲线,似乎只是平台的
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元素): 返回索引[UInt8]{ 切换自身{ 双格(let值): 返回BSON.toByteArray(值) 大小写字符串(let值): 让encoded=value.utf8 返回BSON.toByteArray(Int32(encoded.count+1))+encoded+[0] 案例文档(let字段): 变量主体:[UInt8]=[] 对于字段中的字段??[]{ body+=[field.element.bsonType] body+=field.name。