Skip to content

Instantly share code, notes, and snippets.

@hisui
Last active August 29, 2015 14:14
Show Gist options
  • Save hisui/47f170a9e193168dc946 to your computer and use it in GitHub Desktop.
Save hisui/47f170a9e193168dc946 to your computer and use it in GitHub Desktop.
import Foundation
public class UDKey<T> {
let key: String
let map: BiMap<AnyObject, T>
public init(_ key: String, _ map: BiMap<AnyObject, T>) {
self.key = key
self.map = map
}
}
public class UserDefaults {
private let src: NSUserDefaults
public init(_ src: NSUserDefaults) {
self.src = src
}
public func get<T>(key: UDKey<T>) -> T? {
return src.objectForKey(key.key) >>== { key.map.AtoB($0) }
}
public func set<T>(key: UDKey<T>, _ value: T?) {
if let o = value {
src.setObject(key.map.BtoA(o), forKey: key.key)
}
else {
src.removeObjectForKey(key.key)
}
}
}
infix operator >>== { associativity left }
func >>== <A, B>(ma: A?, f: A -> B?) -> B? {
if let a = ma {
return f(a)
}
else {
return nil
}
}
func sequence<A>(a: [A?]) -> [A]? {
return reduce(a, .Some([])) { acc, e in acc >>== { x in map(e) { x + [$0] } } }
}
public class ClosureBiMap<A, B>: BiMap<A, B> {
let atob: A -> B?
let btoa: B -> A?
init(atob: A -> B?, btoa: B -> A?) {
self.atob = atob
self.btoa = btoa
}
public override func AtoB(a: A) -> B? { return atob(a) }
public override func BtoA(b: B) -> A? { return btoa(b) }
}
public class BiMap<A, B> {
public func AtoB(a: A) -> B? { assert(false, "abstract") }
public func BtoA(b: B) -> A? { assert(false, "abstract") }
public func compose<C>(rhs: BiMap<B, C>) -> BiMap<A, C> {
let lhs = self
return ClosureBiMap(
atob: { lhs.AtoB($0) >>== rhs.AtoB },
btoa: { rhs.BtoA($0) >>== lhs.BtoA })
}
}
public class Caster<T: AnyObject>: BiMap<AnyObject, T> {
override public func AtoB(o: AnyObject) -> T? {
return o as? T
}
override public func BtoA(o: T) -> AnyObject? {
return o
}
}
public class array<E>: BiMap<AnyObject, [E]> {
private let elem: BiMap<AnyObject, E>
public init(_ elem: BiMap<AnyObject, E>) {
self.elem = elem
}
override public func BtoA(a: [E]) -> AnyObject? {
return sequence(a.map { self.elem.BtoA($0) })
}
override public func AtoB(o: AnyObject) -> [E]? {
if let a = o as? [AnyObject] {
return sequence(a.map(elem.AtoB))
}
return nil
}
}
public class dictionary<K: Hashable, V>: BiMap<AnyObject, [K: V]> {
private let keyMap: BiMap<AnyObject, K>
private let valMap: BiMap<AnyObject, V>
public init(_ keyMap: BiMap<AnyObject, K>, _ valMap: BiMap<AnyObject, V>) {
self.keyMap = keyMap
self.valMap = valMap
}
override public func BtoA(value: [K: V]) -> AnyObject? {
var out = NSMutableDictionary()
for (k, v) in value {
if let k2: AnyObject = keyMap.BtoA(k) {
if let v2: AnyObject = valMap.BtoA(v) {
out.setObject(v2, forKey: k2 as NSCopying) // <(^_^;)
continue
}}
return nil
}
return out
}
override public func AtoB(o: AnyObject) -> [K: V]? {
if let dic = o as? NSDictionary {
var out = [K: V]()
for (k, v) in dic {
if let k2 = keyMap.AtoB(k) {
if let v2 = valMap.AtoB(v) {
out[k2] = v2
continue
}}
return nil
}
return out
}
return nil
}
}
public class coding<T: NSCoding>: BiMap<AnyObject, T> {
override public func BtoA(value: T) -> AnyObject? {
return NSKeyedArchiver.archivedDataWithRootObject(value)
}
override public func AtoB(o: AnyObject) -> T? {
return o as? NSData >>== { NSKeyedUnarchiver.unarchiveObjectWithData($0) as T? }
}
}
public let object = Caster<AnyObject>()
public let number = Caster<NSNumber>()
public let string = Caster<NSString>()
.compose(ClosureBiMap(
atob: { $0 as String },
btoa: { $0 as NSString }))
public let data = Caster<NSData>()
public let date = Caster<NSDate>()
public let integer = number
.compose(ClosureBiMap(
atob: { $0 as? Int },
btoa: { $0 as NSNumber }))
public let double = number
.compose(ClosureBiMap(
atob: { $0 as? Double },
btoa: { $0 as NSNumber }))
func optional<B>(map: BiMap<AnyObject, B>) -> BiMap<AnyObject, B?> {
return ClosureBiMap(
atob: { o in
switch (o) {
case _ as NSNull:
return .Some(nil)
default:
return map.AtoB(o)
}
},
btoa: {
if let o = $0 {
return map.BtoA(o)
}
else {
return NSNull()
}
})
}
func tuple<A, B>(a: BiMap<AnyObject, A>, b: BiMap<AnyObject, B>) -> BiMap<AnyObject, (A, B)> {
return array(object).compose(ClosureBiMap(
atob: { o in
if o.count == 2 {
if let a_ = a.AtoB(o[0]) {
if let b_ = b.AtoB(o[1]) {
return .Some((a_, b_))
}}
}
return nil
},
btoa: { sequence([a.BtoA($0.0), b.BtoA($0.1)]) }))
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment