Permalink
59 lines (52 sloc) 2.79 KB
// swiftlint:disable file_length
fileprivate func combineHashes(_ hashes: [Int]) -> Int {
return hashes.reduce(0, combineHashValues)
}
fileprivate func combineHashValues(_ initial: Int, _ other: Int) -> Int {
#if arch(x86_64) || arch(arm64)
let magic: UInt = 0x9e3779b97f4a7c15
#elseif arch(i386) || arch(arm)
let magic: UInt = 0x9e3779b9
#endif
var lhs = UInt(bitPattern: initial)
let rhs = UInt(bitPattern: other)
lhs ^= rhs &+ magic &+ (lhs << 6) &+ (lhs >> 2)
return Int(bitPattern: lhs)
}
// MARK: - AutoHashable for classes, protocols, structs
{% for type in types.implementing.AutoHashable %}{% if not type.kind == "enum" %}
// MARK: - {{ type.name }} AutoHashable
extension {{ type.name }}{% if not type.kind == "protocol" %}: Hashable{% endif %} {
{% if type.supertype.based.Hashable or type.supertype.implements.AutoHashable %} THIS WONT COMPILE, WE DONT SUPPORT INHERITANCE for AutoHashable {% endif %}
{{ type.accessLevel }} var hashValue: Int {
return combineHashes([{% for variable in type.storedVariables %}{% if not variable.annotations.skipHashing %}{% if not variable.isOptional %}{{ variable.name }}.hashValue{% else %}{{ variable.name }}?.hashValue ?? 0{% endif %}, {% endif %}{% endfor %}0])
}
}
{% endif %}{% endfor %}
// MARK: - AutoHashable for Enums
{% for type in types.implementing.AutoHashable|enum %}
// MARK: - {{ type.name }} AutoHashable
extension {{ type.name }}: Hashable {
{{ type.accessLevel }} var hashValue: Int {
switch self {
{% for case in type.cases %}
{% if case.hasAssociatedValue %} case .{{ case.name }}(let data): {% else %} case .{{ case.name }}: {% endif %}
{% ifnot case.hasAssociatedValue %}
{% if type.computedVariables.count == 0 %}
return {{ forloop.counter }}.hashValue
{% else %}
return combineHashes([{{ forloop.counter }}, {% for variable in type.computedVariables %}{% if variable.annotations.includeInHashing %}, {{ variable.name }}.hashValue{% endif %}{% endfor %}])
{% endif %}
{% else %}
{% if case.associatedValues.count == 1 %}
return combineHashes([{{ forloop.counter }}, data.hashValue])
{% else %}
return combineHashes([{{ forloop.counter }}, {% for associated in case.associatedValues %}data.{{ associated.externalName }}.hashValue{% if not forloop.last %}, {% endif %}{% endfor %}{% for variable in type.computedVariables %}{% if variable.annotations.includeInHashing %}, {{ variable.name }}.hashValue{% endif %}{% endfor %}])
{% endif %}
{% endif %}
{% endfor %}
}
}
}
{% endfor %}
// MARK: -