// Copyright (c) 2026 Timofey Solomko // Licensed under MIT License // // See LICENSE for license information import Foundation infix operator <<< @inline(__always) fileprivate func <<< (num: UInt32, count: Int) -> UInt32 { // This implementation assumes without checking that `count` is in the 1...31 range. return (num << count) | (num >> (32 - count)) } enum XxHash32 { private static let prime1: UInt32 = 0x9E3779B1 private static let prime2: UInt32 = 0x85EBCA77 private static let prime3: UInt32 = 0xC2B2AE3D private static let prime4: UInt32 = 0x27D4EB2F private static let prime5: UInt32 = 0x165667B1 static func hash(data: Data, seed: UInt32 = 0) -> UInt32 { if data.count < 16 { return hashSmall(data, seed) } else { return hashBig(data, seed) } } @inline(__always) private static func hashSmall(_ data: Data, _ seed: UInt32) -> UInt32 { let acc = seed &+ prime5 return finalize(data, data.startIndex, acc) } @inline(__always) private static func hashBig(_ data: Data, _ seed: UInt32) -> UInt32 { var accs = [seed &+ prime1 &+ prime2, seed &+ prime2, seed &+ 0, seed &- prime1] var i = data.startIndex while data.endIndex - i >= 16 { // Loop over stripes. for j in 0..<4 { // Loop over lanes. var lane = 0 as UInt32 for k: UInt32 in 0..<4 { lane &+= UInt32(truncatingIfNeeded: data[i + j * 4 + k.toInt()]) << (k * 8) } accs[j] &+= lane &* prime2 accs[j] = accs[j] <<< 13 accs[j] &*= prime1 } i += 16 } let acc = (accs[0] <<< 1) &+ (accs[1] <<< 7) &+ (accs[2] <<< 12) &+ (accs[3] <<< 18) return finalize(data, i, acc) } private static func finalize(_ data: Data, _ ptr: Int, _ acc: UInt32) -> UInt32 { var acc = acc &+ UInt32(truncatingIfNeeded: data.count) var i = ptr while data.endIndex - i >= 4 { var lane = 0 as UInt32 for k: UInt32 in 0..<4 { lane &+= UInt32(truncatingIfNeeded: data[i]) << (k * 8) i += 1 } acc &+= lane &* prime3 acc = (acc <<< 17) &* prime4 } while data.endIndex - i >= 1 { let lane = UInt32(truncatingIfNeeded: data[i]) i += 1 acc &+= lane &* prime5 acc = (acc <<< 11) &* prime1 } acc ^= acc >> 15 acc &*= prime2 acc ^= acc >> 13 acc &*= prime3 acc ^= acc >> 16 return acc } }