Swiftgram/submodules/Postbox/Sources/StoryStatesTable.swift
2023-07-07 02:03:11 +04:00

167 lines
5.0 KiB
Swift

import Foundation
public struct StoredStoryPeerState: Equatable {
public var entry: CodableEntry
public var maxSeenId: Int32
public init(entry: CodableEntry, maxSeenId: Int32) {
self.entry = entry
self.maxSeenId = maxSeenId
}
}
private extension StoredStoryPeerState {
init?(buffer: MemoryBuffer) {
let readBuffer = ReadBuffer(memoryBufferNoCopy: buffer)
var version: UInt8 = 0
readBuffer.read(&version, offset: 0, length: 1)
if version != 100 {
return nil
}
var entryLength: Int32 = 0
readBuffer.read(&entryLength, offset: 0, length: 4)
if entryLength < 0 || readBuffer.offset + Int(entryLength) > readBuffer.length {
return nil
}
self.entry = CodableEntry(data: readBuffer.readData(length: Int(entryLength)))
var maxSeenId: Int32 = 0
readBuffer.read(&maxSeenId, offset: 0, length: 4)
self.maxSeenId = maxSeenId
}
func serialize(buffer: WriteBuffer) {
var version: UInt8 = 100
buffer.write(&version, length: 1)
var entryLength: Int32 = Int32(self.entry.data.count)
buffer.write(&entryLength, length: 4)
buffer.write(self.entry.data)
var maxSeenId: Int32 = self.maxSeenId
buffer.write(&maxSeenId, length: 4)
}
}
final class StoryGeneralStatesTable: Table {
enum Event {
case set(Key)
}
enum Key: Hashable {
case local
case subscriptions(PostboxStorySubscriptionsKey)
init?(key: ValueBoxKey) {
switch key.getUInt8(0) {
case 0:
self = .local
case 1:
if key.length != 1 + 4 {
return nil
}
guard let subscriptionsKey = PostboxStorySubscriptionsKey(rawValue: key.getInt32(1)) else {
return nil
}
self = .subscriptions(subscriptionsKey)
default:
assertionFailure()
self = .subscriptions(.hidden)
}
}
func asKey() -> ValueBoxKey {
switch self {
case .local:
let key = ValueBoxKey(length: 1)
key.setUInt8(0, value: 0)
return key
case let .subscriptions(subscriptionsKey):
let key = ValueBoxKey(length: 1 + 4)
key.setUInt8(0, value: 1)
key.setInt32(1, value: subscriptionsKey.rawValue)
return key
}
}
}
static func tableSpec(_ id: Int32) -> ValueBoxTable {
return ValueBoxTable(id: id, keyType: .binary, compactValuesOnCreation: false)
}
func get(key: Key) -> CodableEntry? {
return self.valueBox.get(self.table, key: key.asKey()).flatMap { CodableEntry(data: $0.makeData()) }
}
func set(key: Key, value: CodableEntry?, events: inout [Event]) {
if let value = value {
self.valueBox.set(self.table, key: key.asKey(), value: MemoryBuffer(data: value.data))
} else {
self.valueBox.remove(self.table, key: key.asKey(), secure: true)
}
events.append(.set(key))
}
override func clearMemoryCache() {
}
override func beforeCommit() {
}
}
final class StoryPeerStatesTable: Table {
enum Event {
case set(Key)
}
enum Key: Hashable {
case peer(PeerId)
init?(key: ValueBoxKey) {
switch key.getUInt8(0) {
case 0:
self = .peer(PeerId(key.getInt64(1)))
default:
assertionFailure()
self = .peer(PeerId(namespace: PeerId.Namespace._internalFromInt32Value(0), id: ._internalFromInt64Value(0)))
}
}
func asKey() -> ValueBoxKey {
switch self {
case let .peer(peerId):
let key = ValueBoxKey(length: 1 + 8)
key.setUInt8(0, value: 2)
key.setInt64(1, value: peerId.toInt64())
return key
}
}
}
static func tableSpec(_ id: Int32) -> ValueBoxTable {
return ValueBoxTable(id: id, keyType: .binary, compactValuesOnCreation: false)
}
func get(key: Key) -> StoredStoryPeerState? {
return self.valueBox.get(self.table, key: key.asKey()).flatMap { StoredStoryPeerState(buffer: $0) }
}
func set(key: Key, value: StoredStoryPeerState?, events: inout [Event]) {
if let value = value {
let buffer = WriteBuffer()
value.serialize(buffer: buffer)
self.valueBox.set(self.table, key: key.asKey(), value: buffer.readBufferNoCopy())
} else {
self.valueBox.remove(self.table, key: key.asKey(), secure: true)
}
events.append(.set(key))
}
override func clearMemoryCache() {
}
override func beforeCommit() {
}
}