mirror of
https://github.com/Swiftgram/Telegram-iOS.git
synced 2025-06-16 05:55:20 +00:00
173 lines
7.3 KiB
Swift
173 lines
7.3 KiB
Swift
import Foundation
|
|
|
|
enum ItemCollectionInfosOperation {
|
|
case replaceInfos(ItemCollectionId.Namespace)
|
|
}
|
|
|
|
final class ItemCollectionInfoTable: Table {
|
|
static func tableSpec(_ id: Int32) -> ValueBoxTable {
|
|
return ValueBoxTable(id: id, keyType: .binary, compactValuesOnCreation: false)
|
|
}
|
|
|
|
private let sharedKey = ValueBoxKey(length: 4 + 4 + 8)
|
|
|
|
private var cachedInfos: [ItemCollectionId.Namespace: [(Int, ItemCollectionId, ItemCollectionInfo)]] = [:]
|
|
|
|
private func key(collectionId: ItemCollectionId, index: Int32) -> ValueBoxKey {
|
|
self.sharedKey.setInt32(0, value: collectionId.namespace)
|
|
self.sharedKey.setInt32(4, value: index)
|
|
self.sharedKey.setInt64(4 + 4, value: collectionId.id)
|
|
return self.sharedKey
|
|
}
|
|
|
|
private func lowerBound(namespace: ItemCollectionId.Namespace) -> ValueBoxKey {
|
|
let key = ValueBoxKey(length: 4)
|
|
key.setInt32(0, value: namespace)
|
|
return key
|
|
}
|
|
|
|
private func upperBound(namespace: ItemCollectionId.Namespace) -> ValueBoxKey {
|
|
let key = ValueBoxKey(length: 4)
|
|
key.setInt32(0, value: namespace)
|
|
return key.successor
|
|
}
|
|
|
|
|
|
func getInfos(namespace: ItemCollectionId.Namespace) -> [(Int, ItemCollectionId, ItemCollectionInfo)] {
|
|
if let cachedInfo = self.cachedInfos[namespace] {
|
|
return cachedInfo
|
|
} else {
|
|
var infos: [(Int, ItemCollectionId, ItemCollectionInfo)] = []
|
|
self.valueBox.range(self.table, start: self.lowerBound(namespace: namespace), end: self.upperBound(namespace: namespace), values: { key, value in
|
|
if let info = PostboxDecoder(buffer: value).decodeRootObject() as? ItemCollectionInfo {
|
|
infos.append((Int(key.getInt32(4)), ItemCollectionId(namespace: namespace, id: key.getInt64(4 + 4)), info))
|
|
}
|
|
return true
|
|
}, limit: 0)
|
|
self.cachedInfos[namespace] = infos
|
|
return infos
|
|
}
|
|
}
|
|
|
|
func getIds(namespace: ItemCollectionId.Namespace) -> [ItemCollectionId] {
|
|
if let cachedInfo = self.cachedInfos[namespace] {
|
|
return cachedInfo.map { $0.1 }
|
|
} else {
|
|
var ids: [ItemCollectionId] = []
|
|
self.valueBox.range(self.table, start: self.lowerBound(namespace: namespace), end: self.upperBound(namespace: namespace), keys: { key in
|
|
ids.append(ItemCollectionId(namespace: namespace, id: key.getInt64(4 + 4)))
|
|
return true
|
|
}, limit: 0)
|
|
return ids
|
|
}
|
|
}
|
|
|
|
func getIndex(id: ItemCollectionId) -> Int32? {
|
|
var index: Int32?
|
|
self.valueBox.range(self.table, start: self.lowerBound(namespace: id.namespace), end: self.upperBound(namespace: id.namespace), keys: { key in
|
|
let keyId = ItemCollectionId(namespace: id.namespace, id: key.getInt64(4 + 4))
|
|
if keyId == id {
|
|
index = key.getInt32(4)
|
|
return false
|
|
}
|
|
return true
|
|
}, limit: 0)
|
|
return index
|
|
}
|
|
|
|
func getInfo(id: ItemCollectionId) -> ItemCollectionInfo? {
|
|
var infoKey: ValueBoxKey?
|
|
self.valueBox.range(self.table, start: self.lowerBound(namespace: id.namespace), end: self.upperBound(namespace: id.namespace), keys: { key in
|
|
let keyId = ItemCollectionId(namespace: id.namespace, id: key.getInt64(4 + 4))
|
|
if keyId == id {
|
|
infoKey = key
|
|
return false
|
|
}
|
|
return true
|
|
}, limit: 0)
|
|
if let infoKey = infoKey, let value = self.valueBox.get(self.table, key: infoKey), let info = PostboxDecoder(buffer: value).decodeRootObject() as? ItemCollectionInfo {
|
|
return info
|
|
} else {
|
|
return nil
|
|
}
|
|
}
|
|
|
|
func lowerCollectionId(namespaceList: [ItemCollectionId.Namespace], collectionId: ItemCollectionId, index: Int32) -> (ItemCollectionId, Int32)? {
|
|
var currentNamespace = collectionId.namespace
|
|
var currentKey = self.key(collectionId: collectionId, index: index)
|
|
while true {
|
|
var resultCollectionIdAndIndex: (ItemCollectionId, Int32)?
|
|
self.valueBox.range(self.table, start: currentKey, end: self.lowerBound(namespace: currentNamespace), keys: { key in
|
|
resultCollectionIdAndIndex = (ItemCollectionId(namespace: currentNamespace, id: key.getInt64(4 + 4)), key.getInt32(4))
|
|
return true
|
|
}, limit: 1)
|
|
if let resultCollectionIdAndIndex = resultCollectionIdAndIndex {
|
|
return resultCollectionIdAndIndex
|
|
} else {
|
|
let index = namespaceList.firstIndex(of: currentNamespace)!
|
|
if index == 0 {
|
|
return nil
|
|
} else {
|
|
currentNamespace = namespaceList[index - 1]
|
|
currentKey = self.upperBound(namespace: currentNamespace)
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
func higherCollectionId(namespaceList: [ItemCollectionId.Namespace], collectionId: ItemCollectionId, index: Int32) -> (ItemCollectionId, Int32)? {
|
|
var currentNamespace = collectionId.namespace
|
|
var currentKey = self.key(collectionId: collectionId, index: index)
|
|
while true {
|
|
var resultCollectionIdAndIndex: (ItemCollectionId, Int32)?
|
|
self.valueBox.range(self.table, start: currentKey, end: self.upperBound(namespace: currentNamespace), keys: { key in
|
|
resultCollectionIdAndIndex = (ItemCollectionId(namespace: currentNamespace, id: key.getInt64(4 + 4)), key.getInt32(4))
|
|
return true
|
|
}, limit: 1)
|
|
if let resultCollectionIdAndIndex = resultCollectionIdAndIndex {
|
|
return resultCollectionIdAndIndex
|
|
} else {
|
|
let index = namespaceList.firstIndex(of: currentNamespace)!
|
|
if index == namespaceList.count - 1 {
|
|
return nil
|
|
} else {
|
|
currentNamespace = namespaceList[index + 1]
|
|
currentKey = self.lowerBound(namespace: currentNamespace)
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
func replaceInfos(namespace: ItemCollectionId.Namespace, infos: [(ItemCollectionId, ItemCollectionInfo)]) {
|
|
self.cachedInfos.removeAll()
|
|
|
|
var currentCollectionKeys: [ValueBoxKey] = []
|
|
self.valueBox.range(self.table, start: self.lowerBound(namespace: namespace), end: self.upperBound(namespace: namespace), keys: { key in
|
|
currentCollectionKeys.append(key)
|
|
return true
|
|
}, limit: 0)
|
|
|
|
for key in currentCollectionKeys {
|
|
self.valueBox.remove(self.table, key: key, secure: false)
|
|
}
|
|
|
|
var index: Int32 = 0
|
|
let sharedEncoder = PostboxEncoder()
|
|
for (id, info) in infos {
|
|
sharedEncoder.reset()
|
|
sharedEncoder.encodeRootObject(info)
|
|
withExtendedLifetime(sharedEncoder, {
|
|
self.valueBox.set(self.table, key: self.key(collectionId: id, index: index), value: sharedEncoder.readBufferNoCopy())
|
|
})
|
|
index += 1
|
|
}
|
|
}
|
|
|
|
override func clearMemoryCache() {
|
|
self.cachedInfos.removeAll()
|
|
}
|
|
|
|
override func beforeCommit() {
|
|
}
|
|
}
|