mirror of
https://github.com/Swiftgram/Telegram-iOS.git
synced 2026-05-05 12:07:28 +00:00
no message
This commit is contained in:
@@ -28,6 +28,7 @@
|
||||
D0D224F21B4D6ABD0085E26D /* Functions.swift in Sources */ = {isa = PBXBuildFile; fileRef = D0D224ED1B4D6ABD0085E26D /* Functions.swift */; };
|
||||
D0D224F31B4D6ABD0085E26D /* Query.swift in Sources */ = {isa = PBXBuildFile; fileRef = D0D224EE1B4D6ABD0085E26D /* Query.swift */; };
|
||||
D0D224F41B4D6ABD0085E26D /* Schema.swift in Sources */ = {isa = PBXBuildFile; fileRef = D0D224EF1B4D6ABD0085E26D /* Schema.swift */; };
|
||||
D0D225261B4D84930085E26D /* PeerView.swift in Sources */ = {isa = PBXBuildFile; fileRef = D0D225251B4D84930085E26D /* PeerView.swift */; };
|
||||
D0E3A7501B28A7E300A402D9 /* Postbox.h in Headers */ = {isa = PBXBuildFile; fileRef = D0E3A74F1B28A7E300A402D9 /* Postbox.h */; settings = {ATTRIBUTES = (Public, ); }; };
|
||||
D0E3A7561B28A7E300A402D9 /* Postbox.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = D0E3A74A1B28A7E300A402D9 /* Postbox.framework */; };
|
||||
D0E3A75D1B28A7E300A402D9 /* PostboxTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = D0E3A75C1B28A7E300A402D9 /* PostboxTests.swift */; };
|
||||
@@ -71,6 +72,7 @@
|
||||
D0D224ED1B4D6ABD0085E26D /* Functions.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = Functions.swift; path = submodules/sqlite.swift/SQLite/Functions.swift; sourceTree = SOURCE_ROOT; };
|
||||
D0D224EE1B4D6ABD0085E26D /* Query.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = Query.swift; path = submodules/sqlite.swift/SQLite/Query.swift; sourceTree = SOURCE_ROOT; };
|
||||
D0D224EF1B4D6ABD0085E26D /* Schema.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = Schema.swift; path = submodules/sqlite.swift/SQLite/Schema.swift; sourceTree = SOURCE_ROOT; };
|
||||
D0D225251B4D84930085E26D /* PeerView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = PeerView.swift; sourceTree = "<group>"; };
|
||||
D0E3A74A1B28A7E300A402D9 /* Postbox.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Postbox.framework; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
D0E3A74E1B28A7E300A402D9 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
|
||||
D0E3A74F1B28A7E300A402D9 /* Postbox.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = Postbox.h; sourceTree = "<group>"; };
|
||||
@@ -180,6 +182,7 @@
|
||||
D0E3A79D1B28B50400A402D9 /* Message.swift */,
|
||||
D0E3A7A11B28B7DC00A402D9 /* Media.swift */,
|
||||
D003E4E51B38DBDB00C22CBC /* MessageView.swift */,
|
||||
D0D225251B4D84930085E26D /* PeerView.swift */,
|
||||
D0E3A7811B28ADD000A402D9 /* Postbox.swift */,
|
||||
D0E3A74D1B28A7E300A402D9 /* Supporting Files */,
|
||||
);
|
||||
@@ -342,6 +345,7 @@
|
||||
D07516791B2EC90400AE42E0 /* SQLite-Bridging.m in Sources */,
|
||||
D0D224F21B4D6ABD0085E26D /* Functions.swift in Sources */,
|
||||
D07516711B2EC7FE00AE42E0 /* Statement.swift in Sources */,
|
||||
D0D225261B4D84930085E26D /* PeerView.swift in Sources */,
|
||||
D0E3A7841B28AE0900A402D9 /* Peer.swift in Sources */,
|
||||
D075166A1B2EC7FE00AE42E0 /* Database.swift in Sources */,
|
||||
D0D224F41B4D6ABD0085E26D /* Schema.swift in Sources */,
|
||||
|
||||
@@ -175,7 +175,6 @@ public final class MutableMessageView: Printable {
|
||||
}
|
||||
|
||||
self.later.removeAll(keepCapacity: true)
|
||||
|
||||
if anchorIndex + 1 < addedMessages.count {
|
||||
for namespace in self.namespaces {
|
||||
var i = anchorIndex + 1
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
import Foundation
|
||||
|
||||
public struct PeerId: Hashable, Printable {
|
||||
public struct PeerId: Hashable, Printable, Comparable {
|
||||
public typealias Namespace = Int32
|
||||
public typealias Id = Int32
|
||||
|
||||
let namespace: Namespace
|
||||
let id: Id
|
||||
public let namespace: Namespace
|
||||
public let id: Id
|
||||
|
||||
public init(namespace: Namespace, id: Id) {
|
||||
self.namespace = namespace
|
||||
@@ -53,6 +53,18 @@ public func ==(lhs: PeerId, rhs: PeerId) -> Bool {
|
||||
return lhs.id == rhs.id && lhs.namespace == rhs.namespace
|
||||
}
|
||||
|
||||
public func <(lhs: PeerId, rhs: PeerId) -> Bool {
|
||||
if lhs.namespace != rhs.namespace {
|
||||
return lhs.namespace < rhs.namespace
|
||||
}
|
||||
|
||||
if lhs.id != rhs.id {
|
||||
return lhs.id < rhs.id
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
||||
|
||||
public protocol Peer: Coding {
|
||||
var id: PeerId { get }
|
||||
}
|
||||
|
||||
278
Postbox/PeerView.swift
Normal file
278
Postbox/PeerView.swift
Normal file
@@ -0,0 +1,278 @@
|
||||
import Foundation
|
||||
|
||||
public class PeerViewEntry {
|
||||
public let peer: Peer
|
||||
public let message: Message
|
||||
|
||||
public init(peer: Peer, message: Message) {
|
||||
self.peer = peer
|
||||
self.message = message
|
||||
}
|
||||
}
|
||||
|
||||
public struct PeerViewEntryIndex: Equatable, Comparable {
|
||||
public let peerId: PeerId
|
||||
public let messageIndex: MessageIndex
|
||||
|
||||
public init(_ entry: PeerViewEntry) {
|
||||
self.peerId = entry.peer.id
|
||||
self.messageIndex = MessageIndex(entry.message)
|
||||
}
|
||||
|
||||
public init(peerId: PeerId, messageIndex: MessageIndex) {
|
||||
self.peerId = peerId
|
||||
self.messageIndex = messageIndex
|
||||
}
|
||||
|
||||
public func earlier() -> PeerViewEntryIndex {
|
||||
return PeerViewEntryIndex(peerId: self.peerId, messageIndex: MessageIndex(id: MessageId(peerId: self.messageIndex.id.peerId, namespace: self.messageIndex.id.namespace, id: self.messageIndex.id.id - 1), timestamp: self.messageIndex.timestamp))
|
||||
}
|
||||
|
||||
public func later() -> PeerViewEntryIndex {
|
||||
return PeerViewEntryIndex(peerId: self.peerId, messageIndex: MessageIndex(id: MessageId(peerId: self.messageIndex.id.peerId, namespace: self.messageIndex.id.namespace, id: self.messageIndex.id.id + 1), timestamp: self.messageIndex.timestamp))
|
||||
}
|
||||
}
|
||||
|
||||
public func ==(lhs: PeerViewEntryIndex, rhs: PeerViewEntryIndex) -> Bool {
|
||||
return lhs.peerId == rhs.peerId && lhs.messageIndex == rhs.messageIndex
|
||||
}
|
||||
|
||||
public func <(lhs: PeerViewEntryIndex, rhs: PeerViewEntryIndex) -> Bool {
|
||||
if lhs.messageIndex != rhs.messageIndex {
|
||||
return lhs.messageIndex < rhs.messageIndex
|
||||
}
|
||||
|
||||
return lhs.peerId < rhs.peerId
|
||||
}
|
||||
|
||||
public final class MutablePeerView: Printable {
|
||||
public struct RemoveContext {
|
||||
var invalidEarlier = false
|
||||
var invalidLater = false
|
||||
var removedEntries = false
|
||||
}
|
||||
|
||||
let tags: [Int32]
|
||||
let count: Int
|
||||
var earlier: PeerViewEntry?
|
||||
var later: PeerViewEntry?
|
||||
var entries: [PeerViewEntry]
|
||||
|
||||
public init(tags: [Int32], count: Int, earlier: PeerViewEntry?, entries: [PeerViewEntry], later: PeerViewEntry?) {
|
||||
self.tags = tags
|
||||
self.count = count
|
||||
self.earlier = earlier
|
||||
self.entries = entries
|
||||
self.later = later
|
||||
}
|
||||
|
||||
public func removeEntry(context: RemoveContext?, peerId: PeerId) -> RemoveContext {
|
||||
var invalidationContext = context ?? RemoveContext()
|
||||
|
||||
if let earlier = self.earlier {
|
||||
if peerId == earlier.peer.id {
|
||||
invalidationContext.invalidEarlier = true
|
||||
}
|
||||
}
|
||||
|
||||
if let later = self.later {
|
||||
if peerId == later.peer.id {
|
||||
invalidationContext.invalidLater = true
|
||||
}
|
||||
}
|
||||
|
||||
var i = 0
|
||||
while i < self.entries.count {
|
||||
if self.entries[i].peer.id == peerId {
|
||||
self.entries.removeAtIndex(i)
|
||||
invalidationContext.removedEntries = true
|
||||
break
|
||||
}
|
||||
i++
|
||||
}
|
||||
|
||||
return invalidationContext
|
||||
}
|
||||
|
||||
public func addEntry(entry: PeerViewEntry) {
|
||||
if self.entries.count == 0 {
|
||||
self.entries.append(entry)
|
||||
} else {
|
||||
var first = PeerViewEntryIndex(self.entries[self.entries.count - 1])
|
||||
var last = PeerViewEntryIndex(self.entries[0])
|
||||
|
||||
let index = PeerViewEntryIndex(entry)
|
||||
|
||||
var next: PeerViewEntryIndex?
|
||||
if let later = self.later {
|
||||
next = PeerViewEntryIndex(later)
|
||||
}
|
||||
|
||||
if index < last {
|
||||
let earlierEntry = self.earlier
|
||||
if earlierEntry == nil || PeerViewEntryIndex(earlierEntry!) < index {
|
||||
if self.entries.count < self.count {
|
||||
self.entries.insert(entry, atIndex: 0)
|
||||
} else {
|
||||
self.earlier = entry
|
||||
}
|
||||
}
|
||||
} else if index > first {
|
||||
if next != nil && index > next! {
|
||||
let laterEntry = self.later
|
||||
if laterEntry == nil || PeerViewEntryIndex(laterEntry!) > index {
|
||||
if self.entries.count < self.count {
|
||||
self.entries.append(entry)
|
||||
} else {
|
||||
self.later = entry
|
||||
}
|
||||
}
|
||||
} else {
|
||||
self.entries.append(entry)
|
||||
if self.entries.count > self.count {
|
||||
let earliest = self.entries[0]
|
||||
self.earlier = earliest
|
||||
self.entries.removeAtIndex(0)
|
||||
}
|
||||
}
|
||||
} else if index != last && index != first {
|
||||
var i = self.entries.count
|
||||
while i >= 1 {
|
||||
if PeerViewEntryIndex(self.entries[i - 1]) < index {
|
||||
break
|
||||
}
|
||||
i--
|
||||
}
|
||||
self.entries.insert(entry, atIndex: i)
|
||||
if self.entries.count > self.count {
|
||||
let earliest = self.entries[0]
|
||||
self.earlier = earliest
|
||||
self.entries.removeAtIndex(0)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public func complete(context: RemoveContext, fetchEarlier: (PeerViewEntryIndex?, Int) -> [PeerViewEntry], fetchLater: (PeerViewEntryIndex?, Int) -> [PeerViewEntry]) {
|
||||
if context.removedEntries && self.entries.count != self.count {
|
||||
var addedEntries: [PeerViewEntry] = []
|
||||
|
||||
var latestAnchor: PeerViewEntryIndex?
|
||||
|
||||
if self.entries.count != 0 {
|
||||
latestAnchor = PeerViewEntryIndex(self.entries[self.entries.count - 1])
|
||||
} else if let later = self.later {
|
||||
latestAnchor = PeerViewEntryIndex(later)
|
||||
}
|
||||
|
||||
if let later = self.later {
|
||||
addedEntries += fetchLater(PeerViewEntryIndex(later).earlier(), self.count)
|
||||
}
|
||||
if let earlier = self.earlier {
|
||||
addedEntries += fetchEarlier(PeerViewEntryIndex(earlier).later(), self.count)
|
||||
}
|
||||
|
||||
addedEntries += self.entries
|
||||
addedEntries.sort({ PeerViewEntryIndex($0) < PeerViewEntryIndex($1) })
|
||||
|
||||
var i = addedEntries.count - 1
|
||||
while i >= 1 {
|
||||
if PeerViewEntryIndex(addedEntries[i]) == PeerViewEntryIndex(addedEntries[i - 1]) {
|
||||
addedEntries.removeAtIndex(i)
|
||||
}
|
||||
i--
|
||||
}
|
||||
self.entries = []
|
||||
|
||||
var anchorIndex = addedEntries.count - 1
|
||||
if let latestAnchor = latestAnchor {
|
||||
var i = addedEntries.count - 1
|
||||
while i >= 0 {
|
||||
if PeerViewEntryIndex(addedEntries[i]) <= latestAnchor {
|
||||
anchorIndex = i
|
||||
break
|
||||
}
|
||||
i--
|
||||
}
|
||||
}
|
||||
|
||||
self.later = nil
|
||||
if anchorIndex + 1 < addedEntries.count {
|
||||
var i = anchorIndex + 1
|
||||
while i < addedEntries.count {
|
||||
self.later = addedEntries[i]
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
i = anchorIndex
|
||||
while i >= 0 && i > anchorIndex - self.count {
|
||||
self.entries.insert(addedEntries[i], atIndex: 0)
|
||||
i--
|
||||
}
|
||||
|
||||
self.earlier = nil
|
||||
if anchorIndex - self.count >= 0 {
|
||||
i = anchorIndex - self.count
|
||||
while i >= 0 {
|
||||
self.earlier = addedEntries[i]
|
||||
break
|
||||
}
|
||||
}
|
||||
} else {
|
||||
var earlyIndex: PeerViewEntryIndex?
|
||||
if self.entries.count != 0 {
|
||||
earlyIndex = PeerViewEntryIndex(self.entries[0])
|
||||
}
|
||||
|
||||
let earlierEntries = fetchEarlier(earlyIndex, 1)
|
||||
if earlierEntries.count == 0 {
|
||||
self.earlier = nil
|
||||
} else {
|
||||
self.earlier = earlierEntries[0]
|
||||
}
|
||||
|
||||
var lateIndex: PeerViewEntryIndex?
|
||||
if self.entries.count != 0 {
|
||||
lateIndex = PeerViewEntryIndex(self.entries[self.entries.count - 1])
|
||||
}
|
||||
|
||||
let laterEntries = fetchLater(lateIndex, 1)
|
||||
if laterEntries.count == 0 {
|
||||
self.later = nil
|
||||
} else {
|
||||
self.later = laterEntries[0]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public var description: String {
|
||||
var string = ""
|
||||
|
||||
if let earlier = self.earlier {
|
||||
string += "more("
|
||||
string += "(p \(earlier.peer.id.namespace):\(earlier.peer.id.id), m \(earlier.message.id.namespace):\(earlier.message.id.id)—\(earlier.message.timestamp)"
|
||||
string += ") "
|
||||
}
|
||||
|
||||
string += "["
|
||||
var first = true
|
||||
for entry in self.entries {
|
||||
if first {
|
||||
first = false
|
||||
} else {
|
||||
string += ", "
|
||||
}
|
||||
string += "(p \(entry.peer.id.namespace):\(entry.peer.id.id), m \(entry.message.id.namespace):\(entry.message.id.id)—\(entry.message.timestamp))"
|
||||
}
|
||||
string += "]"
|
||||
|
||||
if let later = self.later {
|
||||
string += " more("
|
||||
string += "(p \(later.peer.id.namespace):\(later.peer.id.id), m \(later.message.id.namespace):\(later.message.id.id)—\(later.message.timestamp)"
|
||||
string += ")"
|
||||
}
|
||||
|
||||
return string
|
||||
}
|
||||
}
|
||||
@@ -3,6 +3,8 @@ import Foundation
|
||||
import SwiftSignalKit
|
||||
|
||||
public final class Postbox {
|
||||
static let PeerTagGeneral = 0
|
||||
|
||||
public class Modifier {
|
||||
private unowned var postbox: Postbox
|
||||
|
||||
@@ -20,7 +22,6 @@ public final class Postbox {
|
||||
}
|
||||
|
||||
private let basePath: String
|
||||
private let ownerId: PeerId
|
||||
private let messageNamespaces: [MessageId.Namespace]
|
||||
|
||||
private let queue = SwiftSignalKit.Queue()
|
||||
@@ -28,9 +29,8 @@ public final class Postbox {
|
||||
|
||||
private var peerMessageViews: [PeerId : Bag<(MutableMessageView, Pipe<MessageView>)>] = [:]
|
||||
|
||||
public init(basePath: String, ownerId: PeerId, messageNamespaces: [MessageId.Namespace]) {
|
||||
public init(basePath: String, messageNamespaces: [MessageId.Namespace]) {
|
||||
self.basePath = basePath
|
||||
self.ownerId = ownerId
|
||||
self.messageNamespaces = messageNamespaces
|
||||
self.openDatabase()
|
||||
}
|
||||
@@ -51,17 +51,12 @@ public final class Postbox {
|
||||
}
|
||||
|
||||
private func createSchema() {
|
||||
self.database.transaction()
|
||||
|
||||
//state
|
||||
self.database.execute("CREATE TABLE state (key INTEGER PRIMARY KEY, data BLOB)")
|
||||
|
||||
//peer_messages
|
||||
self.database.execute("CREATE TABLE peer_messages (peerId INTEGER, namespace INTEGER, id INTEGER, data BLOB, associatedMediaIds BLOB, timestamp INTEGER, PRIMARY KEY(peerId, namespace, id))")
|
||||
|
||||
//peer_maxread
|
||||
self.database.execute("CREATE TABLE peer_maxread (peerId INTEGER, namespace INTEGER, id INTEGER)")
|
||||
|
||||
//peer_media
|
||||
self.database.execute("CREATE TABLE peer_media (peerId INTEGER, mediaNamespace INTEGER, messageNamespace INTEGER, messageId INTEGER, PRIMARY KEY (peerId, mediaNamespace, messageNamespace, messageId))")
|
||||
self.database.execute("CREATE INDEX peer_media_peerId_messageNamespace_messageId ON peer_media (peerId, messageNamespace, messageId)")
|
||||
@@ -72,21 +67,97 @@ public final class Postbox {
|
||||
//media_cleanup
|
||||
self.database.execute("CREATE TABLE media_cleanup (namespace INTEGER, id INTEGER, data BLOB, PRIMARY KEY(namespace, id))")
|
||||
|
||||
//messages_readstate
|
||||
self.database.execute("CREATE TABLE messages_readstate (peerId INTEGER, namespace INTEGER, maxUnreadIncomingId INTEGER, maxUnreadOutgoingId INTEGER, incomingUnreadCount INTEGER, PRIMARY KEY (peerId, namespace))")
|
||||
|
||||
//top_messages
|
||||
self.database.execute("CREATE TABLE top_messages (peerId INTEGER PRIMARY KEY, timestamp INTEGER)")
|
||||
//peer_entries
|
||||
self.database.execute("CREATE TABLE peer_entries (entry BLOB)")
|
||||
self.database.execute("CREATE INDEX peer_entries_entry on peer_entries (entry)")
|
||||
|
||||
//peers
|
||||
self.database.execute("CREATE TABLE peers (peerId INTEGER PRIMARY KEY, data BLOB)")
|
||||
}
|
||||
|
||||
public func _testBlobsPrepare(range: Int) {
|
||||
self.database.execute("CREATE TABLE test_blobs (number INTEGER, data BLOB)")
|
||||
self.database.execute("CREATE INDEX test_blobs_index_data ON test_blobs (data)")
|
||||
|
||||
//user_statuses
|
||||
self.database.execute("CREATE TABLE user_statuses (id INTEGER PRIMARY KEY, data BLOB)")
|
||||
self.database.transaction()
|
||||
let insert = self.database.prepare("INSERT INTO test_blobs (number, data) VALUES (?, ?)")
|
||||
|
||||
for i in 0 ..< range {
|
||||
var value = Int32(bigEndian: Int32(i))
|
||||
let blob = Blob(bytes: &value, length: 4)
|
||||
insert.run(Int64(i), blob)
|
||||
}
|
||||
self.database.commit()
|
||||
}
|
||||
|
||||
public func _testBlobsTest(range: Int) {
|
||||
let select = self.database.prepare("SELECT number FROM test_blobs WHERE data < ? ORDER BY data DESC LIMIT 1")
|
||||
|
||||
for i in 1 ..< 1000 {
|
||||
var value = 1 + Int32(arc4random_uniform(UInt32(range - 1)))
|
||||
var binary = Int32(bigEndian: value)
|
||||
var found = false
|
||||
for row in select.run(Blob(bytes: &binary, length: 4)) {
|
||||
found = true
|
||||
let selected = Int32(row[0] as! Int64)
|
||||
if selected != value - 1 {
|
||||
assertionFailure("invalid value \(selected) != \(value - 1)")
|
||||
}
|
||||
break
|
||||
}
|
||||
if !found {
|
||||
assertionFailure("value not found for \(value - 1)")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private class func peerViewEntryIndexForBlob(blob: Blob) -> PeerViewEntryIndex {
|
||||
let buffer = ReadBuffer(memory: UnsafeMutablePointer(blob.data.bytes), length: blob.data.length, freeWhenDone: false)
|
||||
var offset: Int = 0
|
||||
|
||||
var timestamp: Int32 = 0
|
||||
buffer.read(×tamp, offset: offset, length: 4)
|
||||
timestamp = Int32(bigEndian: timestamp)
|
||||
offset += 4
|
||||
|
||||
var namespace: Int32 = 0
|
||||
buffer.read(&namespace, offset: offset, length: 4)
|
||||
namespace = Int32(bigEndian: namespace)
|
||||
offset += 4
|
||||
|
||||
var id: Int32 = 0
|
||||
buffer.read(&id, offset: offset, length: 4)
|
||||
id = Int32(bigEndian: id)
|
||||
offset += 4
|
||||
|
||||
var peerIdRepresentation: Int64 = 0
|
||||
buffer.read(&peerIdRepresentation, offset: offset, length: 8)
|
||||
peerIdRepresentation = Int64(bigEndian: peerIdRepresentation)
|
||||
offset += 8
|
||||
|
||||
let peerId = PeerId(peerIdRepresentation)
|
||||
|
||||
return PeerViewEntryIndex(peerId: peerId, messageIndex: MessageIndex(id: MessageId(peerId:peerId, namespace: namespace, id: id), timestamp: timestamp))
|
||||
}
|
||||
|
||||
private class func blobForPeerViewEntryIndex(index: PeerViewEntryIndex) -> Blob {
|
||||
let buffer = WriteBuffer()
|
||||
|
||||
var timestamp = Int32(bigEndian: index.messageIndex.timestamp)
|
||||
buffer.write(×tamp, offset: 0, length: 4)
|
||||
|
||||
var namespace = Int32(bigEndian: index.messageIndex.id.namespace)
|
||||
buffer.write(&namespace, offset: 0, length: 4)
|
||||
|
||||
var id = Int32(bigEndian: index.messageIndex.id.id)
|
||||
buffer.write(&id, offset: 0, length: 4)
|
||||
|
||||
var peerIdRepresentation = Int64(bigEndian: index.peerId.toInt64())
|
||||
buffer.write(&peerIdRepresentation, offset: 0, length: 8)
|
||||
|
||||
return Blob(data: buffer.makeData())
|
||||
}
|
||||
|
||||
private class func messageIdsGroupedByNamespace(ids: [MessageId]) -> [MessageId.Namespace : [MessageId]] {
|
||||
var grouped: [MessageId.Namespace : [MessageId]] = [:]
|
||||
|
||||
|
||||
@@ -16,6 +16,22 @@ enum TestMediaNamespace: MediaId.Namespace {
|
||||
case Test = 0
|
||||
}
|
||||
|
||||
class TestPeer: Peer {
|
||||
var id: PeerId
|
||||
|
||||
init(id: PeerId) {
|
||||
self.id = id
|
||||
}
|
||||
|
||||
required init(decoder: Decoder) {
|
||||
self.id = PeerId(decoder.decodeInt64ForKey("id"))
|
||||
}
|
||||
|
||||
func encode(encoder: Encoder) {
|
||||
encoder.encodeInt64(self.id.toInt64(), forKey: "id")
|
||||
}
|
||||
}
|
||||
|
||||
class TestMessage: Message {
|
||||
var id: MessageId
|
||||
var authorId: PeerId
|
||||
@@ -97,7 +113,7 @@ class PostboxTests: XCTestCase {
|
||||
|
||||
let basePath = "/tmp/postboxtest"
|
||||
NSFileManager.defaultManager().removeItemAtPath(basePath, error: nil)
|
||||
let postbox = Postbox(basePath: basePath, ownerId: ownerId, messageNamespaces: [messageNamespace])
|
||||
let postbox = Postbox(basePath: basePath, messageNamespaces: [messageNamespace])
|
||||
postbox.modify { state in
|
||||
let testMedia = TestMedia(id: MediaId(namespace: TestMediaNamespace.Test.rawValue, id: 1))
|
||||
for i in 0 ..< 10 {
|
||||
@@ -586,7 +602,7 @@ class PostboxTests: XCTestCase {
|
||||
|
||||
let basePath = "/tmp/postboxtest"
|
||||
NSFileManager.defaultManager().removeItemAtPath(basePath, error: nil)
|
||||
let postbox = Postbox(basePath: basePath, ownerId: ownerId, messageNamespaces: [messageNamespace])
|
||||
let postbox = Postbox(basePath: basePath, messageNamespaces: [messageNamespace])
|
||||
|
||||
postbox.modify { state in
|
||||
let testMedia = TestMedia(id: MediaId(namespace: TestMediaNamespace.Test.rawValue, id: 1))
|
||||
@@ -626,7 +642,7 @@ class PostboxTests: XCTestCase {
|
||||
|
||||
let basePath = "/tmp/postboxtest"
|
||||
NSFileManager.defaultManager().removeItemAtPath(basePath, error: nil)
|
||||
let postbox = Postbox(basePath: basePath, ownerId: ownerId, messageNamespaces: [messageNamespaceCloud, messageNamespaceLocal])
|
||||
let postbox = Postbox(basePath: basePath, messageNamespaces: [messageNamespaceCloud, messageNamespaceLocal])
|
||||
|
||||
postbox.modify { state in
|
||||
let testMedia = TestMedia(id: MediaId(namespace: TestMediaNamespace.Test.rawValue, id: 1))
|
||||
@@ -660,4 +676,101 @@ class PostboxTests: XCTestCase {
|
||||
|
||||
postbox._sync()
|
||||
}
|
||||
|
||||
func testPeerView() {
|
||||
let view = MutablePeerView(tags: [], count: 3, earlier: nil, entries: [], later: nil)
|
||||
let messageNamespaceCloud = TestMessageNamespace.Cloud.rawValue
|
||||
let otherId = PeerId(namespace: TestPeerNamespace.User.rawValue, id: 2000)
|
||||
|
||||
var entries: [PeerViewEntry] = []
|
||||
|
||||
func print(entries: [PeerViewEntry]) {
|
||||
var string = ""
|
||||
string += "["
|
||||
var first = true
|
||||
for entry in entries {
|
||||
if first {
|
||||
first = false
|
||||
} else {
|
||||
string += ", "
|
||||
}
|
||||
string += "(p \(entry.peer.id.namespace):\(entry.peer.id.id), m \(entry.message.id.namespace):\(entry.message.id.id)—\(entry.message.timestamp))"
|
||||
}
|
||||
string += "]"
|
||||
println("\(string)")
|
||||
}
|
||||
|
||||
func add(entry: PeerViewEntry) {
|
||||
entries.append(entry)
|
||||
entries.sort({ PeerViewEntryIndex($0) < PeerViewEntryIndex($1) })
|
||||
|
||||
view.addEntry(entry)
|
||||
|
||||
println("\n\(view)")
|
||||
print(entries)
|
||||
}
|
||||
|
||||
func remove(peerId: PeerId, context: MutablePeerView.RemoveContext? = nil) -> MutablePeerView.RemoveContext {
|
||||
entries = entries.filter({ $0.peer.id != peerId })
|
||||
return view.removeEntry(context, peerId: peerId)
|
||||
}
|
||||
|
||||
func fetchEarlier(entries: [PeerViewEntry])(index: PeerViewEntryIndex?, count: Int) -> [PeerViewEntry] {
|
||||
var filtered: [PeerViewEntry] = []
|
||||
var i = entries.count - 1
|
||||
while i >= 0 && filtered.count < count {
|
||||
if index == nil || PeerViewEntryIndex(entries[i]) < index! {
|
||||
filtered.append(entries[i])
|
||||
}
|
||||
i--
|
||||
}
|
||||
|
||||
return filtered
|
||||
}
|
||||
|
||||
func fetchLater(entries: [PeerViewEntry])(index: PeerViewEntryIndex?, count: Int) -> [PeerViewEntry] {
|
||||
var filtered: [PeerViewEntry] = []
|
||||
var i = 0
|
||||
while i < entries.count && filtered.count < count {
|
||||
if index == nil || PeerViewEntryIndex(entries[i]) > index! {
|
||||
filtered.append(entries[i])
|
||||
}
|
||||
i++
|
||||
}
|
||||
|
||||
return filtered
|
||||
}
|
||||
|
||||
func complete(context: MutablePeerView.RemoveContext) {
|
||||
view.complete(context, fetchEarlier: fetchEarlier(entries), fetchLater: fetchLater(entries))
|
||||
}
|
||||
|
||||
println("\(view)")
|
||||
|
||||
for i in 1 ..< 10 {
|
||||
let messageId = MessageId(peerId: otherId, namespace: messageNamespaceCloud, id: Int32(i * 2 * 100))
|
||||
let message = TestMessage(id: messageId, authorId: otherId, date: Int32(i * 2 * 100), text: "\(i)", referencedMediaIds: [])
|
||||
|
||||
add(PeerViewEntry(peer: TestPeer(id: PeerId(namespace: TestPeerNamespace.User.rawValue, id: Int32(i * 2))), message: message))
|
||||
}
|
||||
|
||||
if true {
|
||||
let i = 15
|
||||
let messageId = MessageId(peerId: otherId, namespace: messageNamespaceCloud, id: Int32(i * 100))
|
||||
let message = TestMessage(id: messageId, authorId: otherId, date: Int32(i * 100), text: "\(i)", referencedMediaIds: [])
|
||||
|
||||
add(PeerViewEntry(peer: TestPeer(id: PeerId(namespace: TestPeerNamespace.User.rawValue, id: Int32(i))), message: message))
|
||||
}
|
||||
|
||||
if true {
|
||||
var context = remove(PeerId(namespace: TestPeerNamespace.User.rawValue, id: Int32(15)))
|
||||
context = remove(PeerId(namespace: TestPeerNamespace.User.rawValue, id: Int32(14)), context: context)
|
||||
context = remove(PeerId(namespace: TestPeerNamespace.User.rawValue, id: Int32(16)), context: context)
|
||||
context = remove(PeerId(namespace: TestPeerNamespace.User.rawValue, id: Int32(18)), context: context)
|
||||
println("\n\(view)")
|
||||
print(entries)
|
||||
complete(context)
|
||||
println("\(view)")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user