Renaming
This commit is contained in:
parent
321cea3ccd
commit
d0e9b2a1e3
|
@ -4,10 +4,10 @@
|
||||||
|
|
||||||
import Foundation
|
import Foundation
|
||||||
|
|
||||||
struct Bits {
|
struct BitArray {
|
||||||
let count: Int
|
let count: Int
|
||||||
|
|
||||||
private var bytes: [UInt8]
|
private var items: [UInt8]
|
||||||
|
|
||||||
init(count: Int) {
|
init(count: Int) {
|
||||||
self.count = count
|
self.count = count
|
||||||
|
@ -16,38 +16,38 @@ struct Bits {
|
||||||
|
|
||||||
byteCount += bitRemainder > 0 ? 1 : 0
|
byteCount += bitRemainder > 0 ? 1 : 0
|
||||||
|
|
||||||
bytes = [UInt8](repeating: 0, count: byteCount)
|
items = [UInt8](repeating: 0, count: byteCount)
|
||||||
}
|
}
|
||||||
|
|
||||||
init(bytes: [UInt8], count: Int) {
|
init(data: Data, count: Int) {
|
||||||
self.bytes = bytes
|
self.items = Array(data)
|
||||||
self.count = count
|
self.count = count
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
extension Bits {
|
extension BitArray {
|
||||||
var data: Data { Data(bytes) }
|
var data: Data { Data(items) }
|
||||||
|
|
||||||
subscript(index: Int) -> Bool {
|
subscript(index: Int) -> Bool {
|
||||||
get {
|
get {
|
||||||
let (byteCount, bitPosition) = index.quotientAndRemainder(dividingBy: Self.bitsInByte)
|
let (byteCount, bitPosition) = index.quotientAndRemainder(dividingBy: Self.bitsInByte)
|
||||||
|
|
||||||
return bytes[byteCount] & mask(index: bitPosition) > 0
|
return items[byteCount] & mask(index: bitPosition) > 0
|
||||||
}
|
}
|
||||||
|
|
||||||
set {
|
set {
|
||||||
let (byteCount, bitPosition) = index.quotientAndRemainder(dividingBy: Self.bitsInByte)
|
let (byteCount, bitPosition) = index.quotientAndRemainder(dividingBy: Self.bitsInByte)
|
||||||
|
|
||||||
if newValue {
|
if newValue {
|
||||||
bytes[byteCount] |= mask(index: bitPosition)
|
items[byteCount] |= mask(index: bitPosition)
|
||||||
} else {
|
} else {
|
||||||
bytes[byteCount] &= ~mask(index: bitPosition)
|
items[byteCount] &= ~mask(index: bitPosition)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private extension Bits {
|
private extension BitArray {
|
||||||
static let bitsInByte = 8
|
static let bitsInByte = 8
|
||||||
|
|
||||||
func mask(index: Int) -> UInt8 {
|
func mask(index: Int) -> UInt8 {
|
|
@ -8,14 +8,14 @@ import Foundation
|
||||||
|
|
||||||
struct BloomFilter {
|
struct BloomFilter {
|
||||||
let hashes: [Hash]
|
let hashes: [Hash]
|
||||||
let bitCount: Int
|
let bits: Int
|
||||||
|
|
||||||
private var bits: Bits
|
private var data: BitArray
|
||||||
|
|
||||||
init(hashes: [Hash], bitCount: Int) {
|
init(hashes: [Hash], bits: Int) {
|
||||||
self.hashes = hashes
|
self.hashes = hashes
|
||||||
self.bitCount = bitCount
|
self.bits = bits
|
||||||
bits = Bits(count: bitCount)
|
data = BitArray(count: bits)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -27,43 +27,42 @@ extension BloomFilter {
|
||||||
|
|
||||||
mutating func insert(_ newMember: String) {
|
mutating func insert(_ newMember: String) {
|
||||||
for index in indices(newMember) {
|
for index in indices(newMember) {
|
||||||
bits[index] = true
|
data[index] = true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func contains(_ member: String) -> Bool {
|
func contains(_ member: String) -> Bool {
|
||||||
indices(member).map { bits[$0] }.allSatisfy { $0 }
|
indices(member).map { data[$0] }.allSatisfy { $0 }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
extension BloomFilter: Codable {
|
extension BloomFilter: Codable {
|
||||||
enum CodingKeys: String, CodingKey {
|
enum CodingKeys: String, CodingKey {
|
||||||
case hashes
|
case hashes
|
||||||
case bitCount
|
case bits
|
||||||
case data
|
case data
|
||||||
}
|
}
|
||||||
|
|
||||||
init(from decoder: Decoder) throws {
|
init(from decoder: Decoder) throws {
|
||||||
let container = try decoder.container(keyedBy: CodingKeys.self)
|
let container = try decoder.container(keyedBy: CodingKeys.self)
|
||||||
let data = try container.decode(Data.self, forKey: .data)
|
|
||||||
|
|
||||||
hashes = try container.decode([Hash].self, forKey: .hashes)
|
hashes = try container.decode([Hash].self, forKey: .hashes)
|
||||||
bitCount = try container.decode(Int.self, forKey: .bitCount)
|
bits = try container.decode(Int.self, forKey: .bits)
|
||||||
bits = Bits(bytes: Array(data), count: bitCount)
|
data = BitArray(data: try container.decode(Data.self, forKey: .data), count: bits)
|
||||||
}
|
}
|
||||||
|
|
||||||
func encode(to encoder: Encoder) throws {
|
func encode(to encoder: Encoder) throws {
|
||||||
var container = encoder.container(keyedBy: CodingKeys.self)
|
var container = encoder.container(keyedBy: CodingKeys.self)
|
||||||
|
|
||||||
try container.encode(hashes, forKey: .hashes)
|
try container.encode(hashes, forKey: .hashes)
|
||||||
try container.encode(bitCount, forKey: .bitCount)
|
try container.encode(bits, forKey: .bits)
|
||||||
try container.encode(bits.data, forKey: .data)
|
try container.encode(data.data, forKey: .data)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private extension BloomFilter {
|
private extension BloomFilter {
|
||||||
func indices(_ string: String) -> [Int] {
|
func indices(_ string: String) -> [Int] {
|
||||||
hashes.map { abs($0.apply(string)) % bitCount }
|
hashes.map { abs($0.apply(string)) % bits }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -3,7 +3,7 @@ import XCTest
|
||||||
|
|
||||||
final class CodableBloomFilterTests: XCTestCase {
|
final class CodableBloomFilterTests: XCTestCase {
|
||||||
func testContains() {
|
func testContains() {
|
||||||
var sut = BloomFilter(hashes: [.djb2, .sdbm], bitCount: 1024)
|
var sut = BloomFilter(hashes: [.djb2, .sdbm], bits: 1024)
|
||||||
|
|
||||||
sut.insert("lol")
|
sut.insert("lol")
|
||||||
sut.insert("ok")
|
sut.insert("ok")
|
||||||
|
@ -15,8 +15,8 @@ final class CodableBloomFilterTests: XCTestCase {
|
||||||
}
|
}
|
||||||
|
|
||||||
func testCoding() throws {
|
func testCoding() throws {
|
||||||
var sut = BloomFilter(hashes: [.djb2, .sdbm], bitCount: 64)
|
var sut = BloomFilter(hashes: [.djb2, .sdbm], bits: 64)
|
||||||
let expectedSerialization = Data(#"{"bitCount":64,"data":"ABAAAAACAJA=","hashes":["djb2","sdbm"]}"#.utf8)
|
let expectedSerialization = Data(#"{"bits":64,"data":"ABAAAAACAJA=","hashes":["djb2","sdbm"]}"#.utf8)
|
||||||
|
|
||||||
sut.insert("lol")
|
sut.insert("lol")
|
||||||
sut.insert("ok")
|
sut.insert("ok")
|
||||||
|
|
Loading…
Reference in New Issue