mirror of
https://github.com/Swiftgram/Telegram-iOS.git
synced 2025-06-16 05:55:20 +00:00
100 lines
3.2 KiB
Swift
100 lines
3.2 KiB
Swift
import Foundation
|
|
|
|
private func collectionId(_ peerId: PeerId) -> String {
|
|
return "p\(UInt64(bitPattern: peerId.toInt64()))"
|
|
}
|
|
|
|
private func itemId(_ messageId: MessageId) -> String {
|
|
return "p\(UInt64(bitPattern: messageId.peerId.toInt64()))a\(UInt32(bitPattern: messageId.namespace))b\(UInt32(bitPattern: messageId.id))"
|
|
}
|
|
|
|
private func messageTags(_ tags: MessageTags) -> String {
|
|
var result = ""
|
|
for tag in tags {
|
|
if !result.isEmpty {
|
|
result += " "
|
|
}
|
|
result += "t\(tag.rawValue)"
|
|
}
|
|
return result
|
|
}
|
|
|
|
private func parseMessageId(_ value: String) -> MessageId? {
|
|
if !value.hasPrefix("p") {
|
|
return nil
|
|
}
|
|
guard let aRange = value.range(of: "a") else {
|
|
return nil
|
|
}
|
|
guard let bRange = value.range(of: "b") else {
|
|
return nil
|
|
}
|
|
let pString = value[value.index(value.startIndex, offsetBy: 1) ..< aRange.lowerBound]
|
|
let nString = value[aRange.upperBound ..< bRange.lowerBound]
|
|
let iString = value[bRange.upperBound ..< value.endIndex]
|
|
|
|
guard let pValue = UInt64(pString) else {
|
|
return nil
|
|
}
|
|
guard let nValue = UInt32(nString) else {
|
|
return nil
|
|
}
|
|
guard let iValue = UInt32(iString) else {
|
|
return nil
|
|
}
|
|
|
|
return MessageId(peerId: PeerId(Int64(bitPattern: pValue)), namespace: Int32(bitPattern: nValue), id: Int32(bitPattern: iValue))
|
|
}
|
|
|
|
private let alphanumerics = CharacterSet.alphanumerics
|
|
|
|
final class MessageHistoryTextIndexTable {
|
|
static func tableSpec(_ id: Int32) -> ValueBoxFullTextTable {
|
|
return ValueBoxFullTextTable(id: id)
|
|
}
|
|
|
|
private let valueBox: ValueBox
|
|
private let table: ValueBoxFullTextTable
|
|
|
|
init(valueBox: ValueBox, table: ValueBoxFullTextTable) {
|
|
self.valueBox = valueBox
|
|
self.table = table
|
|
}
|
|
|
|
func add(messageId: MessageId, text: String, tags: MessageTags) {
|
|
self.valueBox.fullTextSet(self.table, collectionId: collectionId(messageId.peerId), itemId: itemId(messageId), contents: text, tags: messageTags(tags))
|
|
}
|
|
|
|
func remove(messageId: MessageId) {
|
|
self.valueBox.fullTextRemove(self.table, itemId: itemId(messageId), secure: true)
|
|
}
|
|
|
|
func search(peerId: PeerId?, text: String, tags: MessageTags?) -> [MessageId] {
|
|
var escapedText = String(text.map({ c in
|
|
var codeUnits: [UnicodeScalar] = []
|
|
for codeUnit in String(c).unicodeScalars {
|
|
codeUnits.append(codeUnit)
|
|
}
|
|
for codeUnit in codeUnits {
|
|
if !alphanumerics.contains(codeUnit) {
|
|
return " "
|
|
}
|
|
}
|
|
return c
|
|
}))
|
|
if !escapedText.isEmpty {
|
|
escapedText += "*"
|
|
}
|
|
var result: [MessageId] = []
|
|
self.valueBox.fullTextMatch(self.table, collectionId: peerId.flatMap { collectionId($0) }, query: escapedText, tags: tags.flatMap(messageTags), values: { _, itemId in
|
|
if let messageId = parseMessageId(itemId) {
|
|
result.append(messageId)
|
|
} else {
|
|
assertionFailure()
|
|
}
|
|
return true
|
|
})
|
|
return result
|
|
}
|
|
}
|