2015-09-30 00:00:26 +03:00
|
|
|
|
public enum Hash: Hashable {
|
|
|
|
|
case Sequence([Hash])
|
2015-09-30 17:42:43 +03:00
|
|
|
|
case Label(String)
|
2015-09-30 17:40:45 +03:00
|
|
|
|
case Raw(Int)
|
2015-09-30 00:00:26 +03:00
|
|
|
|
|
2015-09-30 17:44:48 +03:00
|
|
|
|
public init(_ label: String, _ hashes: Hash...) {
|
|
|
|
|
self = .Sequence([ Hash(label) ] + hashes)
|
2015-09-30 00:02:35 +03:00
|
|
|
|
}
|
|
|
|
|
|
2015-09-30 17:42:27 +03:00
|
|
|
|
public init(_ string: String) {
|
|
|
|
|
self = .Label(string)
|
|
|
|
|
}
|
|
|
|
|
|
2015-09-30 17:43:18 +03:00
|
|
|
|
public init(_ raw: Int) {
|
|
|
|
|
self = .Raw(raw)
|
|
|
|
|
}
|
|
|
|
|
|
2015-09-30 00:01:38 +03:00
|
|
|
|
public init<A: AlgebraicHashable>(_ hashable: A) {
|
|
|
|
|
self = hashable.hash
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public init<A: Hashable>(_ hashable: A) {
|
2015-09-30 17:40:28 +03:00
|
|
|
|
self = .Raw(hashable.hashValue)
|
2015-09-30 00:01:38 +03:00
|
|
|
|
}
|
|
|
|
|
|
2015-09-30 00:00:26 +03:00
|
|
|
|
|
2015-09-30 17:40:45 +03:00
|
|
|
|
public var hashValue: Int {
|
2015-09-30 00:00:26 +03:00
|
|
|
|
switch self {
|
|
|
|
|
case let .Sequence(s):
|
|
|
|
|
// Bob Jenkins’ one-at-a-time hash: https://en.wikipedia.org/wiki/Jenkins_hash_function
|
|
|
|
|
var hash = 0
|
|
|
|
|
for each in s {
|
|
|
|
|
hash += each.hashValue
|
|
|
|
|
hash += hash << 10
|
|
|
|
|
hash ^= hash >> 6
|
|
|
|
|
}
|
|
|
|
|
hash += hash << 3
|
|
|
|
|
hash ^= hash >> 11
|
|
|
|
|
hash += hash << 15
|
|
|
|
|
return hash
|
2015-09-30 17:42:27 +03:00
|
|
|
|
case let .Label(s):
|
2015-09-30 00:00:26 +03:00
|
|
|
|
return s.hashValue
|
2015-09-30 17:40:28 +03:00
|
|
|
|
case let .Raw(i):
|
2015-09-30 00:00:26 +03:00
|
|
|
|
return i.hashValue
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public func == (left: Hash, right: Hash) -> Bool {
|
|
|
|
|
switch (left, right) {
|
|
|
|
|
case let (.Sequence(a), .Sequence(b)):
|
|
|
|
|
return a == b
|
2015-09-30 17:42:27 +03:00
|
|
|
|
case let (.Label(a), .Label(b)):
|
2015-09-30 00:00:26 +03:00
|
|
|
|
return a == b
|
2015-09-30 17:40:28 +03:00
|
|
|
|
case let (.Raw(a), .Raw(b)):
|
2015-09-30 00:00:26 +03:00
|
|
|
|
return a == b
|
|
|
|
|
default:
|
|
|
|
|
return false
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2015-09-30 22:02:31 +03:00
|
|
|
|
public protocol AlgebraicHashable: Hashable {
|
2015-09-30 00:00:52 +03:00
|
|
|
|
var hash: Hash { get }
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
extension AlgebraicHashable {
|
|
|
|
|
public var hashValue: Int {
|
|
|
|
|
return hash.hashValue
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2015-09-30 00:02:01 +03:00
|
|
|
|
extension RawRepresentable where RawValue: Hashable {
|
|
|
|
|
public var hash: Hash {
|
|
|
|
|
return Hash(rawValue)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
extension RawRepresentable where RawValue: AlgebraicHashable {
|
|
|
|
|
public var hash: Hash {
|
|
|
|
|
return Hash(rawValue)
|
|
|
|
|
}
|
|
|
|
|
}
|