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() { } }