Signal-iOS/SignalMessaging/utils/Searcher.swift
Evan Hahn 29c0ddf60e Fix violations of SwiftLint's attributes rule
_I recommend reviewing this with whitespace changes disabled._

Most of these were `@objc` being on the same line, which I fixed with [a
silly script][1]—probably could've used `sed` if I were wiser. The rest
were manual fixes.

See [the SwiftLint documentation for this rule][0].

[0]: https://realm.github.io/SwiftLint/attributes.html
[1]: https://gist.github.com/EvanHahn-Signal/d353c93fa269c82b96baca0a1086521f
2022-05-14 09:07:42 -05:00

56 lines
1.7 KiB
Swift

//
// Copyright (c) 2022 Open Whisper Systems. All rights reserved.
//
import Foundation
// ObjC compatible searcher
@objc
class AnySearcher: NSObject {
private let searcher: Searcher<AnyObject>
public init(indexer: @escaping (AnyObject, SDSAnyReadTransaction) -> String ) {
searcher = Searcher(indexer: indexer)
super.init()
}
@objc(item:doesMatchQuery:transaction:)
public func matches(item: AnyObject, query: String, transaction: SDSAnyReadTransaction) -> Bool {
return searcher.matches(item: item, query: query, transaction: transaction)
}
}
// A generic searching class, configurable with an indexing block
public class Searcher<T> {
private let indexer: (T, SDSAnyReadTransaction) -> String
public init(indexer: @escaping (T, SDSAnyReadTransaction) -> String) {
self.indexer = indexer
}
public func matches(item: T, query: String, transaction: SDSAnyReadTransaction) -> Bool {
let itemString = normalize(string: indexer(item, transaction))
return stem(string: query).allSatisfy { queryStem in
return itemString.contains(queryStem)
}
}
private func stem(string: String) -> [String] {
var normalized = normalize(string: string)
// Remove any phone number formatting from the search terms
let nonformattingScalars = normalized.unicodeScalars.lazy.filter {
!CharacterSet.punctuationCharacters.contains($0)
}
normalized = String(String.UnicodeScalarView(nonformattingScalars))
return normalized.components(separatedBy: .whitespacesAndNewlines)
}
private func normalize(string: String) -> String {
return string.lowercased().trimmingCharacters(in: .whitespacesAndNewlines)
}
}