This commit is contained in:
Justin Mazzocchi 2020-09-05 17:32:43 -07:00
parent 9c3010fe29
commit e731bdb1e3
No known key found for this signature in database
GPG key ID: E223E6937AAFB01C
2 changed files with 15 additions and 15 deletions

View file

@ -8,26 +8,26 @@ import Foundation
public struct BloomFilter<T: DeterministicallyHashable> { public struct BloomFilter<T: DeterministicallyHashable> {
public let hashers: [DeterministicHasher] public let hashers: [DeterministicHasher]
public let bits: Int public let bitCount: Int
private var data: BitArray private var bitArray: BitArray
public init(hashes: [DeterministicHasher], bits: Int) { public init(hashers: [DeterministicHasher], bits: Int) {
self.hashers = hashes self.hashers = hashers
self.bits = bits bitCount = bits
data = BitArray(count: bits) bitArray = BitArray(count: bits)
} }
} }
public extension BloomFilter { public extension BloomFilter {
mutating func insert(_ newMember: T) { mutating func insert(_ newMember: T) {
for index in indices(newMember) { for index in indices(newMember) {
data[index] = true bitArray[index] = true
} }
} }
func contains(_ member: T) -> Bool { func contains(_ member: T) -> Bool {
indices(member).map { data[$0] }.allSatisfy { $0 } indices(member).map { bitArray[$0] }.allSatisfy { $0 }
} }
} }
@ -42,21 +42,21 @@ extension BloomFilter: Codable {
let container = try decoder.container(keyedBy: CodingKeys.self) let container = try decoder.container(keyedBy: CodingKeys.self)
hashers = try container.decode([DeterministicHasher].self, forKey: .hashers) hashers = try container.decode([DeterministicHasher].self, forKey: .hashers)
bits = try container.decode(Int.self, forKey: .bits) bitCount = try container.decode(Int.self, forKey: .bits)
data = BitArray(data: try container.decode(Data.self, forKey: .data), count: bits) bitArray = BitArray(data: try container.decode(Data.self, forKey: .data), count: bitCount)
} }
public func encode(to encoder: Encoder) throws { public func encode(to encoder: Encoder) throws {
var container = encoder.container(keyedBy: CodingKeys.self) var container = encoder.container(keyedBy: CodingKeys.self)
try container.encode(hashers, forKey: .hashers) try container.encode(hashers, forKey: .hashers)
try container.encode(bits, forKey: .bits) try container.encode(bitCount, forKey: .bits)
try container.encode(data.data, forKey: .data) try container.encode(bitArray.data, forKey: .data)
} }
} }
private extension BloomFilter { private extension BloomFilter {
func indices(_ member: T) -> [Int] { func indices(_ member: T) -> [Int] {
hashers.map { abs($0.apply(member)) % bits } hashers.map { abs($0.apply(member)) % bitCount }
} }
} }

View file

@ -3,7 +3,7 @@ import XCTest
final class CodableBloomFilterTests: XCTestCase { final class CodableBloomFilterTests: XCTestCase {
func testContains() { func testContains() {
var sut = BloomFilter<String>(hashes: [.djb2, .sdbm], bits: 1024) var sut = BloomFilter<String>(hashers: [.djb2, .sdbm], bits: 1024)
sut.insert("lol") sut.insert("lol")
sut.insert("ok") sut.insert("ok")
@ -15,7 +15,7 @@ final class CodableBloomFilterTests: XCTestCase {
} }
func testCoding() throws { func testCoding() throws {
var sut = BloomFilter<String>(hashes: [.djb2, .sdbm], bits: 64) var sut = BloomFilter<String>(hashers: [.djb2, .sdbm], bits: 64)
let expectedSerialization = Data(#"{"bits":64,"data":"ABAAAAACAJA=","hashers":["djb2","sdbm"]}"#.utf8) let expectedSerialization = Data(#"{"bits":64,"data":"ABAAAAACAJA=","hashers":["djb2","sdbm"]}"#.utf8)
sut.insert("lol") sut.insert("lol")