// This source file is part of the Swift.org open source project
//
// Copyright (c) 2014 - 2016 Apple Inc. and the Swift project authors
// Licensed under Apache License v2.0 with Runtime Library Exception
//
// See http://swift.org/LICENSE.txt for license information
// See http://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
//


import CoreFoundation

extension Dictionary : _ObjectTypeBridgeable {
    public func _bridgeToObject() -> NSDictionary {
        let keyBuffer = UnsafeMutablePointer<NSObject>(allocatingCapacity: count)
        let valueBuffer = UnsafeMutablePointer<AnyObject>(allocatingCapacity: count)
        
        var idx = 0
        
        self.forEach {
            let key = _NSObjectRepresentableBridge($0.0)
            let value = _NSObjectRepresentableBridge($0.1)
            keyBuffer.advanced(by: idx).initialize(with: key)
            valueBuffer.advanced(by: idx).initialize(with: value)
            idx += 1
        }
        
        let dict = NSDictionary(objects: valueBuffer, forKeys: keyBuffer, count: count)
        
        keyBuffer.deinitialize(count: count)
        valueBuffer.deinitialize(count: count)
        keyBuffer.deallocateCapacity(count)
        valueBuffer.deallocateCapacity(count)

        return dict
    }
    
    public static func _forceBridgeFromObject(_ x: NSDictionary, result: inout Dictionary?) {
        var dict = [Key: Value]()
        var failedConversion = false
        
        if x.dynamicType == NSDictionary.self || x.dynamicType == NSMutableDictionary.self {
            x.enumerateKeysAndObjectsUsingBlock { key, value, stop in
                guard let key = key as? Key, let value = value as? Value else {
                    failedConversion = true
                    stop.pointee = true
                    return
                }
                dict[key] = value
            }
        } else if x.dynamicType == _NSCFDictionary.self {
            let cf = x._cfObject
            let cnt = CFDictionaryGetCount(cf)

            let keys = UnsafeMutablePointer<UnsafePointer<Void>?>(allocatingCapacity: cnt)
            let values = UnsafeMutablePointer<UnsafePointer<Void>?>(allocatingCapacity: cnt)
            
            CFDictionaryGetKeysAndValues(cf, keys, values)
            
            for idx in 0..<cnt {
                let key = unsafeBitCast(keys.advanced(by: idx).pointee!, to: AnyObject.self)
                let value = unsafeBitCast(values.advanced(by: idx).pointee!, to: AnyObject.self)
                guard let k = key as? Key, let v = value as? Value else {
                    failedConversion = true
                    break
                }
                dict[k] = v
            }
            keys.deinitialize(count: cnt)
            values.deinitialize(count: cnt)
            keys.deallocateCapacity(cnt)
            values.deallocateCapacity(cnt)
        }
        if !failedConversion {
            result = dict
        }
    }
    
    public static func _conditionallyBridgeFromObject(_ x: NSDictionary, result: inout Dictionary?) -> Bool {
        _forceBridgeFromObject(x, result: &result)
        return true
    }
}

public class NSDictionary : NSObject, NSCopying, NSMutableCopying, NSSecureCoding, NSCoding {
    private let _cfinfo = _CFInfo(typeID: CFDictionaryGetTypeID())
    internal var _storage = [NSObject: AnyObject]()
    
    public var count: Int {
        if self.dynamicType === NSDictionary.self || self.dynamicType === NSMutableDictionary.self {
            return _storage.count
        } else {
            NSRequiresConcreteImplementation()
        }
    }
    
    public func objectForKey(_ aKey: AnyObject) -> AnyObject? {
        if self.dynamicType === NSDictionary.self || self.dynamicType === NSMutableDictionary.self {
            return _storage[aKey as! NSObject]
        } else {
            NSRequiresConcreteImplementation()
        }
    }
    
    public func keyEnumerator() -> NSEnumerator {
        if self.dynamicType === NSDictionary.self || self.dynamicType === NSMutableDictionary.self {
            return NSGeneratorEnumerator(_storage.keys.makeIterator())
        } else {
            NSRequiresConcreteImplementation()
        }
    }
    
    public override convenience init() {
        self.init(objects: [], forKeys: [], count: 0)
    }
    
    public required init(objects: UnsafePointer<AnyObject>, forKeys keys: UnsafePointer<NSObject>, count cnt: Int) {
        for idx in 0..<cnt {
            let key = keys[idx].copy()
            let value = objects[idx]
            _storage[key as! NSObject] = value
        }
    }
    
    public required convenience init?(coder aDecoder: NSCoder) {
        if !aDecoder.allowsKeyedCoding {
            var cnt: UInt32 = 0
            // We're stuck with (int) here (rather than unsigned int)
            // because that's the way the code was originally written, unless
            // we go to a new version of the class, which has its own problems.
            withUnsafeMutablePointer(&cnt) { (ptr: UnsafeMutablePointer<UInt32>) -> Void in
                aDecoder.decodeValueOfObjCType("i", at: UnsafeMutablePointer<Void>(ptr))
            }
            let keys = UnsafeMutablePointer<NSObject>(allocatingCapacity: Int(cnt))
            let objects = UnsafeMutablePointer<AnyObject>(allocatingCapacity: Int(cnt))
            for idx in 0..<cnt {
                keys.advanced(by: Int(idx)).initialize(with: aDecoder.decodeObject()! as! NSObject)
                objects.advanced(by: Int(idx)).initialize(with: aDecoder.decodeObject()!)
            }
            self.init(objects: UnsafePointer<AnyObject>(objects), forKeys: UnsafePointer<NSObject>(keys), count: Int(cnt))
            keys.deinitialize(count: Int(cnt))
            keys.deallocateCapacity(Int(cnt))
            objects.deinitialize(count: Int(cnt))
            objects.deallocateCapacity(Int(cnt))
            
        } else if aDecoder.dynamicType == NSKeyedUnarchiver.self || aDecoder.containsValueForKey("NS.objects") {
            let keys = aDecoder._decodeArrayOfObjectsForKey("NS.keys").map() { return $0 as! NSObject }
            let objects = aDecoder._decodeArrayOfObjectsForKey("NS.objects")
            self.init(objects: objects, forKeys: keys)
        } else {
            var objects = [AnyObject]()
            var keys = [NSObject]()
            var count = 0
            while let key = aDecoder.decodeObjectForKey("NS.key.\(count)"),
                let object = aDecoder.decodeObjectForKey("NS.object.\(count)") {
                    keys.append(key as! NSObject)
                    objects.append(object)
                    count += 1
            }
            self.init(objects: objects, forKeys: keys)
        }
    }
    
    public func encodeWithCoder(_ aCoder: NSCoder) {
        if let keyedArchiver = aCoder as? NSKeyedArchiver {
            keyedArchiver._encodeArrayOfObjects(self.allKeys._nsObject, forKey:"NS.keys")
            keyedArchiver._encodeArrayOfObjects(self.allValues._nsObject, forKey:"NS.objects")
        } else {
            NSUnimplemented()
        }
    }
    
    public static func supportsSecureCoding() -> Bool {
        return true
    }
    
    public override func copy() -> AnyObject {
        return copyWithZone(nil)
    }

    public func copyWithZone(_ zone: NSZone) -> AnyObject {
        if self.dynamicType === NSDictionary.self {
            // return self for immutable type
            return self
        } else if self.dynamicType === NSMutableDictionary.self {
            let dictionary = NSDictionary()
            dictionary._storage = self._storage
            return dictionary
        }
        return NSDictionary(objects: self.allValues, forKeys: self.allKeys.map({ $0 as! NSObject}))
    }

    public override func mutableCopy() -> AnyObject {
        return mutableCopyWithZone(nil)
    }

    public func mutableCopyWithZone(_ zone: NSZone) -> AnyObject {
        if self.dynamicType === NSDictionary.self || self.dynamicType === NSMutableDictionary.self {
            // always create and return an NSMutableDictionary
            let mutableDictionary = NSMutableDictionary()
            mutableDictionary._storage = self._storage
            return mutableDictionary
        }
        return NSMutableDictionary(objects: self.allValues, forKeys: self.allKeys.map({ $0 as! NSObject}))
    }

    public convenience init(object: AnyObject, forKey key: NSCopying) {
        self.init(objects: [object], forKeys: [key as! NSObject])
    }
    
//    public convenience init(dictionary otherDictionary: [NSObject : AnyObject]) {
//        self.init(dictionary: otherDictionary, copyItems: false)
//    }
    
//    public convenience init(dictionary otherDictionary: [NSObject : AnyObject], copyItems flag: Bool) {
//        var keys = Array<KeyType>()
//        var values = Array<AnyObject>()
//        for key in otherDictionary.keys {
//            keys.append(key)
//            var value = otherDictionary[key]
//            if flag {
//                if let val = value as? NSObject {
//                    value = val.copy()
//                }
//            }
//            values.append(value!)
//        }
//        self.init(objects: values, forKeys: keys)
//    }
    
    public convenience init(objects: [AnyObject], forKeys keys: [NSObject]) {
        let keyBuffer = UnsafeMutablePointer<NSObject>(allocatingCapacity: keys.count)
        keyBuffer.initializeFrom(keys)

        let valueBuffer = UnsafeMutablePointer<AnyObject>(allocatingCapacity: objects.count)
        valueBuffer.initializeFrom(objects)

        self.init(objects: valueBuffer, forKeys:keyBuffer, count: keys.count)
        
        keyBuffer.deinitialize(count: keys.count)
        valueBuffer.deinitialize(count: objects.count)
        keyBuffer.deallocateCapacity(keys.count)
        valueBuffer.deallocateCapacity(objects.count)
    }

    public override func isEqual(_ object: AnyObject?) -> Bool {
        guard let otherDictionary = object as? NSDictionary else {
            return false
        }
        return self.isEqualToDictionary(otherDictionary.bridge())
    }

    public override var hash: Int {
        return self.count
    }

    public var allKeys: [AnyObject] {
        if self.dynamicType === NSDictionary.self || self.dynamicType === NSMutableDictionary.self {
            return _storage.keys.map { $0 }
        } else {
            var keys = [AnyObject]()
            let enumerator = keyEnumerator()
            while let key = enumerator.nextObject() {
                keys.append(key)
            }
            return keys
        }
    }
    
    public var allValues: [AnyObject] {
        if self.dynamicType === NSDictionary.self || self.dynamicType === NSMutableDictionary.self {
            return _storage.values.map { $0 }
        } else {
            var values = [AnyObject]()
            let enumerator = keyEnumerator()
            while let key = enumerator.nextObject() {
                values.append(objectForKey(key)!)
            }
            return values
        }
    }
    
    /// Alternative pseudo funnel method for fastpath fetches from dictionaries
    /// - Experiment: This is a draft API currently under consideration for official import into Foundation
    /// - Note: Since this API is under consideration it may be either removed or revised in the near future
    public func getObjects(_ objects: inout [AnyObject], andKeys keys: inout [AnyObject], count: Int) {
        if self.dynamicType === NSDictionary.self || self.dynamicType === NSMutableDictionary.self {
            for (key, value) in _storage {
                keys.append(key)
                objects.append(value)
            }
        } else {
            
            let enumerator = keyEnumerator()
            while let key = enumerator.nextObject() {
                let value = objectForKey(key)!
                keys.append(key)
                objects.append(value)
            }
        }
    }
    
    public subscript (key: AnyObject) -> AnyObject? {
        return objectForKey(key)
    }
    
    
    public func allKeysForObject(_ anObject: AnyObject) -> [AnyObject] {
        var matching = Array<AnyObject>()
        enumerateKeysAndObjectsWithOptions([]) { key, value, _ in
            if value === anObject {
                matching.append(key)
            }
        }
        return matching
    }

    /// A string that represents the contents of the dictionary, formatted as
    /// a property list (read-only)
    ///
    /// If each key in the dictionary is an NSString object, the entries are
    /// listed in ascending order by key, otherwise the order in which the entries
    /// are listed is undefined. This property is intended to produce readable
    /// output for debugging purposes, not for serializing data. If you want to
    /// store dictionary data for later retrieval, see
    /// [Property List Programming Guide](https://developer.apple.com/library/mac/documentation/Cocoa/Conceptual/PropertyLists/Introduction/Introduction.html#//apple_ref/doc/uid/10000048i)
    /// and [Archives and Serializations Programming Guide](https://developer.apple.com/library/mac/documentation/Cocoa/Conceptual/Archiving/Archiving.html#//apple_ref/doc/uid/10000047i).
    public override var description: String {
        return descriptionWithLocale(nil)
    }

    public var descriptionInStringsFileFormat: String { NSUnimplemented() }

    /// Returns a string object that represents the contents of the dictionary,
    /// formatted as a property list.
    ///
    /// - parameter locale: An object that specifies options used for formatting
    ///   each of the dictionary’s keys and values; pass `nil` if you don’t
    ///   want them formatted.
    public func descriptionWithLocale(_ locale: AnyObject?) -> String {
        return descriptionWithLocale(locale, indent: 0)
    }

    /// Returns a string object that represents the contents of the dictionary,
    /// formatted as a property list.
    ///
    /// - parameter locale: An object that specifies options used for formatting
    ///   each of the dictionary’s keys and values; pass `nil` if you don’t
    ///   want them formatted.
    ///
    /// - parameter level: Specifies a level of indentation, to make the output
    ///   more readable: the indentation is (4 spaces) * level.
    ///
    /// - returns: A string object that represents the contents of the dictionary,
    ///   formatted as a property list.
    public func descriptionWithLocale(_ locale: AnyObject?, indent level: Int) -> String {
        if level > 100 { return "..." }

        var lines = [String]()
        let indentation = String(repeating: Character(" "), count: level * 4)
        lines.append(indentation + "{")

        for key in self.allKeys {
            var line = String(repeating: Character(" "), count: (level + 1) * 4)

            if key is NSArray {
                line += (key as! NSArray).descriptionWithLocale(locale, indent: level + 1)
            } else if key is NSDate {
                line += (key as! NSDate).descriptionWithLocale(locale)
            } else if key is NSDecimalNumber {
                line += (key as! NSDecimalNumber).description(withLocale: locale)
            } else if key is NSDictionary {
                line += (key as! NSDictionary).descriptionWithLocale(locale, indent: level + 1)
            } else if key is NSOrderedSet {
                line += (key as! NSOrderedSet).descriptionWithLocale(locale, indent: level + 1)
            } else if key is NSSet {
                line += (key as! NSSet).descriptionWithLocale(locale)
            } else {
                line += "\(key)"
            }

            line += " = "

            let object = objectForKey(key)!
            if object is NSArray {
                line += (object as! NSArray).descriptionWithLocale(locale, indent: level + 1)
            } else if object is NSDate {
                line += (object as! NSDate).descriptionWithLocale(locale)
            } else if object is NSDecimalNumber {
                line += (object as! NSDecimalNumber).description(withLocale: locale)
            } else if object is NSDictionary {
                line += (object as! NSDictionary).descriptionWithLocale(locale, indent: level + 1)
            } else if object is NSOrderedSet {
                line += (object as! NSOrderedSet).descriptionWithLocale(locale, indent: level + 1)
            } else if object is NSSet {
                line += (object as! NSSet).descriptionWithLocale(locale)
            } else {
                line += "\(object)"
            }

            line += ";"

            lines.append(line)
        }

        lines.append(indentation + "}")
        
        return lines.joined(separator: "\n")
    }

    public func isEqualToDictionary(_ otherDictionary: [NSObject : AnyObject]) -> Bool {
        if count != otherDictionary.count {
            return false
        }
        
        for key in keyEnumerator() {
            if let otherValue = otherDictionary[key as! NSObject] as? NSObject {
                let value = objectForKey(key as! NSObject)! as! NSObject
                if otherValue != value {
                    return false
                }
            } else {
                return false
            }
        }
        
        return true
    }
    
    public struct Iterator : IteratorProtocol {
        let dictionary : NSDictionary
        var keyGenerator : Array<AnyObject>.Iterator
        public mutating func next() -> (key: AnyObject, value: AnyObject)? {
            if let key = keyGenerator.next() {
                return (key, dictionary.objectForKey(key)!)
            } else {
                return nil
            }
        }
        init(_ dict : NSDictionary) {
            self.dictionary = dict
            self.keyGenerator = dict.allKeys.makeIterator()
        }
    }
    
    internal struct ObjectGenerator: IteratorProtocol {
        let dictionary : NSDictionary
        var keyGenerator : Array<AnyObject>.Iterator
        mutating func next() -> AnyObject? {
            if let key = keyGenerator.next() {
                return dictionary.objectForKey(key)!
            } else {
                return nil
            }
        }
        init(_ dict : NSDictionary) {
            self.dictionary = dict
            self.keyGenerator = dict.allKeys.makeIterator()
        }
    }

    public func objectEnumerator() -> NSEnumerator {
        return NSGeneratorEnumerator(ObjectGenerator(self))
    }
    
    public func objectsForKeys(_ keys: [NSObject], notFoundMarker marker: AnyObject) -> [AnyObject] {
        var objects = [AnyObject]()
        for key in keys {
            if let object = objectForKey(key) {
                objects.append(object)
            } else {
                objects.append(marker)
            }
        }
        return objects
    }
    
    public func writeToFile(_ path: String, atomically useAuxiliaryFile: Bool) -> Bool { NSUnimplemented() }
    public func writeToURL(_ url: NSURL, atomically: Bool) -> Bool { NSUnimplemented() } // the atomically flag is ignored if url of a type that cannot be written atomically.
    
    public func enumerateKeysAndObjectsUsingBlock(_ block: (NSObject, AnyObject, UnsafeMutablePointer<ObjCBool>) -> Void) {
        enumerateKeysAndObjectsWithOptions([], usingBlock: block)
    }

    public func enumerateKeysAndObjectsWithOptions(_ opts: NSEnumerationOptions, usingBlock block: (NSObject, AnyObject, UnsafeMutablePointer<ObjCBool>) -> Void) {
        let count = self.count
        var keys = [AnyObject]()
        var objects = [AnyObject]()
        getObjects(&objects, andKeys: &keys, count: count)
        var stop = ObjCBool(false)
        for idx in 0..<count {
            withUnsafeMutablePointer(&stop, { stop in
                block(keys[idx] as! NSObject, objects[idx], stop)
            })

            if stop {
                break
            }
        }
    }
    
    public func keysSortedByValueUsingComparator(_ cmptr: NSComparator) -> [AnyObject] {
        return keysSortedByValueWithOptions([], usingComparator: cmptr)
    }

    public func keysSortedByValueWithOptions(_ opts: NSSortOptions, usingComparator cmptr: NSComparator) -> [AnyObject] {
        let sorted = allKeys.sorted { lhs, rhs in
            return cmptr(lhs, rhs) == .orderedSame
        }
        return sorted
    }

    public func keysOfEntriesPassingTest(_ predicate: (AnyObject, AnyObject, UnsafeMutablePointer<ObjCBool>) -> Bool) -> Set<NSObject> {
        return keysOfEntriesWithOptions([], passingTest: predicate)
    }

    public func keysOfEntriesWithOptions(_ opts: NSEnumerationOptions, passingTest predicate: (AnyObject, AnyObject, UnsafeMutablePointer<ObjCBool>) -> Bool) -> Set<NSObject> {
        var matching = Set<NSObject>()
        enumerateKeysAndObjectsWithOptions(opts) { key, value, stop in
            if predicate(key, value, stop) {
                matching.insert(key)
            }
        }
        return matching
    }
    
    override public var _cfTypeID: CFTypeID {
        return CFDictionaryGetTypeID()
    }
    
    required public convenience init(dictionaryLiteral elements: (NSObject, AnyObject)...) {
        var keys = [NSObject]()
        var values = [AnyObject]()

        for (key, value) in elements {
            keys.append(key)
            values.append(value)
        }
        
        self.init(objects: values, forKeys: keys)
    }
}

extension NSDictionary : _CFBridgable, _SwiftBridgable {
    internal var _cfObject: CFDictionary { return unsafeBitCast(self, to: CFDictionary.self) }
    internal var _swiftObject: Dictionary<NSObject, AnyObject> {
        var dictionary: [NSObject: AnyObject]?
        Dictionary._forceBridgeFromObject(self, result: &dictionary)
        return dictionary!
    }
}

extension NSMutableDictionary {
    internal var _cfMutableObject: CFMutableDictionary { return unsafeBitCast(self, to: CFMutableDictionary.self) }
}

extension CFDictionary : _NSBridgable, _SwiftBridgable {
    internal var _nsObject: NSDictionary { return unsafeBitCast(self, to: NSDictionary.self) }
    internal var _swiftObject: [NSObject: AnyObject] { return _nsObject._swiftObject }
}

extension Dictionary : _NSBridgable, _CFBridgable {
    internal var _nsObject: NSDictionary { return _bridgeToObject() }
    internal var _cfObject: CFDictionary { return _nsObject._cfObject }
}

public class NSMutableDictionary : NSDictionary {
    
    public func removeObjectForKey(_ aKey: AnyObject) {
        if self.dynamicType === NSDictionary.self || self.dynamicType === NSMutableDictionary.self {
            if let key = aKey as? NSObject {
                _storage.removeValue(forKey: key)
            }
            
//            CFDictionaryRemoveValue(unsafeBitCast(self, CFMutableDictionaryRef.self), unsafeBitCast(aKey, UnsafePointer<Void>.self))
        } else {
            NSRequiresConcreteImplementation()
        }
    }
    
    public func setObject(_ anObject: AnyObject, forKey aKey: NSObject) {
        if self.dynamicType === NSDictionary.self || self.dynamicType === NSMutableDictionary.self {
            _storage[aKey] = anObject
//            CFDictionarySetValue(unsafeBitCast(self, CFMutableDictionaryRef.self), unsafeBitCast(aKey, UnsafePointer<Void>.self), unsafeBitCast(anObject, UnsafePointer<Void>.self))
        } else {
            NSRequiresConcreteImplementation()
        }
    }
    
    public convenience required init() {
        self.init(capacity: 0)
    }
    
    public convenience init(capacity numItems: Int) {
        self.init(objects: [], forKeys: [], count: 0)
    }
    
    public required init(objects: UnsafePointer<AnyObject>, forKeys keys: UnsafePointer<NSObject>, count cnt: Int) {
        super.init(objects: objects, forKeys: keys, count: cnt)
    }
    
    public convenience init?(contentsOfFile path: String) { NSUnimplemented() }
    public convenience init?(contentsOfURL url: NSURL) { NSUnimplemented() }

}

extension NSMutableDictionary {
    
    public func addEntriesFromDictionary(_ otherDictionary: [NSObject : AnyObject]) {
        for (key, obj) in otherDictionary {
            setObject(obj, forKey: key)
        }
    }
    
    public func removeAllObjects() {
        if self.dynamicType === NSDictionary.self || self.dynamicType === NSMutableDictionary.self {
            _storage.removeAll()
//            CFDictionaryRemoveAllValues(unsafeBitCast(self, CFMutableDictionaryRef.self))
        } else {
            for key in allKeys {
                removeObjectForKey(key)
            }
        }
    }
    
    public func removeObjectsForKeys(_ keyArray: [AnyObject]) {
        for key in keyArray {
            removeObjectForKey(key)
        }
    }
    
    public func setDictionary(_ otherDictionary: [NSObject : AnyObject]) {
        if self.dynamicType === NSDictionary.self || self.dynamicType === NSMutableDictionary.self {
            _storage = otherDictionary
        } else {
            removeAllObjects()
            for (key, obj) in otherDictionary {
                setObject(obj, forKey: key)
            }
        }
    }
    
    public subscript (key: NSObject) -> AnyObject? {
        get {
            return objectForKey(key)
        }
        set {
            if let val = newValue {
                setObject(val, forKey: key)
            } else {
                removeObjectForKey(key)
            }
        }
    }
}

extension NSDictionary : Sequence {
    public func makeIterator() -> Iterator {
        return Iterator(self)
    }
}

// MARK - Shared Key Sets

extension NSDictionary {
    
    /*  Use this method to create a key set to pass to +dictionaryWithSharedKeySet:.
    The keys are copied from the array and must be copyable.
    If the array parameter is nil or not an NSArray, an exception is thrown.
    If the array of keys is empty, an empty key set is returned.
    The array of keys may contain duplicates, which are ignored (it is undefined which object of each duplicate pair is used).
    As for any usage of hashing, is recommended that the keys have a well-distributed implementation of -hash, and the hash codes must satisfy the hash/isEqual: invariant.
    Keys with duplicate hash codes are allowed, but will cause lower performance and increase memory usage.
    */
    public class func sharedKeySetForKeys(_ keys: [NSCopying]) -> AnyObject { NSUnimplemented() }
}

extension NSMutableDictionary {
    
    /*  Create a mutable dictionary which is optimized for dealing with a known set of keys.
    Keys that are not in the key set can still be set into the dictionary, but that usage is not optimal.
    As with any dictionary, the keys must be copyable.
    If keyset is nil, an exception is thrown.
    If keyset is not an object returned by +sharedKeySetForKeys:, an exception is thrown.
    */
    public convenience init(sharedKeySet keyset: AnyObject) { NSUnimplemented() }
}

extension NSDictionary : DictionaryLiteralConvertible { }

extension Dictionary : Bridgeable {
    public func bridge() -> NSDictionary { return _nsObject }
}

extension NSDictionary : Bridgeable {
    public func bridge() -> [NSObject: AnyObject] { return _swiftObject }
}
