This commit is contained in:
Ali 2021-07-29 21:07:15 +02:00
parent d46c7b739d
commit e874fa92ff
15 changed files with 869 additions and 67 deletions

View File

@ -130,7 +130,7 @@ public enum ChatControllerInteractionNavigateToPeer {
case withBotStartPayload(ChatControllerInitialBotStart) case withBotStartPayload(ChatControllerInitialBotStart)
} }
public struct ChatTextInputState: PostboxCoding, Equatable { public struct ChatTextInputState: Codable, Equatable {
public let inputText: NSAttributedString public let inputText: NSAttributedString
public let selectionRange: Range<Int> public let selectionRange: Range<Int>
@ -154,27 +154,88 @@ public struct ChatTextInputState: PostboxCoding, Equatable {
self.selectionRange = length ..< length self.selectionRange = length ..< length
} }
public init(decoder: PostboxDecoder) { public init(from decoder: Decoder) throws {
self.inputText = ((decoder.decodeObjectForKey("at", decoder: { ChatTextInputStateText(decoder: $0) }) as? ChatTextInputStateText) ?? ChatTextInputStateText()).attributedText() let container = try decoder.container(keyedBy: StringCodingKey.self)
self.selectionRange = Int(decoder.decodeInt32ForKey("as0", orElse: 0)) ..< Int(decoder.decodeInt32ForKey("as1", orElse: 0)) self.inputText = ((try? container.decodeIfPresent(ChatTextInputStateText.self, forKey: "at")) ?? ChatTextInputStateText()).attributedText()
let rangeFrom = (try? container.decodeIfPresent(Int32.self, forKey: "as0")) ?? 0
let rangeTo = (try? container.decodeIfPresent(Int32.self, forKey: "as1")) ?? 0
if rangeFrom <= rangeTo {
self.selectionRange = Int(rangeFrom) ..< Int(rangeTo)
} else {
let length = self.inputText.length
self.selectionRange = length ..< length
}
} }
public func encode(_ encoder: PostboxEncoder) { public func encode(to encoder: Encoder) throws {
var container = encoder.container(keyedBy: StringCodingKey.self)
try container.encode(ChatTextInputStateText(attributedText: self.inputText), forKey: "at")
try container.encode(Int32(self.selectionRange.lowerBound), forKey: "as0")
try container.encode(Int32(self.selectionRange.upperBound), forKey: "as1")
}
/*public init(decoder: PostboxDecoder) {
self.inputText = ((decoder.decodeObjectForKey("at", decoder: { ChatTextInputStateText(decoder: $0) }) as? ChatTextInputStateText) ?? ChatTextInputStateText()).attributedText()
self.selectionRange = Int(decoder.decodeInt32ForKey("as0", orElse: 0)) ..< Int(decoder.decodeInt32ForKey("as1", orElse: 0))
}*/
/*public func encode(_ encoder: PostboxEncoder) {
encoder.encodeObject(ChatTextInputStateText(attributedText: self.inputText), forKey: "at") encoder.encodeObject(ChatTextInputStateText(attributedText: self.inputText), forKey: "at")
encoder.encodeInt32(Int32(self.selectionRange.lowerBound), forKey: "as0") encoder.encodeInt32(Int32(self.selectionRange.lowerBound), forKey: "as0")
encoder.encodeInt32(Int32(self.selectionRange.upperBound), forKey: "as1") encoder.encodeInt32(Int32(self.selectionRange.upperBound), forKey: "as1")
} }*/
} }
public enum ChatTextInputStateTextAttributeType: PostboxCoding, Equatable { public enum ChatTextInputStateTextAttributeType: Codable, Equatable {
case bold case bold
case italic case italic
case monospace case monospace
case textMention(EnginePeer.Id) case textMention(EnginePeer.Id)
case textUrl(String) case textUrl(String)
public init(decoder: PostboxDecoder) { public init(from decoder: Decoder) throws {
let container = try decoder.container(keyedBy: StringCodingKey.self)
switch (try? container.decodeIfPresent(Int32.self, forKey: "t")) ?? 0 {
case 0:
self = .bold
case 1:
self = .italic
case 2:
self = .monospace
case 3:
let peerId = (try? container.decode(Int64.self, forKey: "peerId")) ?? 0
self = .textMention(EnginePeer.Id(peerId))
case 4:
let url = (try? container.decode(String.self, forKey: "url")) ?? ""
self = .textUrl(url)
default:
assertionFailure()
self = .bold
}
}
public func encode(to encoder: Encoder) throws {
var container = encoder.container(keyedBy: StringCodingKey.self)
switch self {
case .bold:
try container.encode(0 as Int32, forKey: "t")
case .italic:
try container.encode(1 as Int32, forKey: "t")
case .monospace:
try container.encode(2 as Int32, forKey: "t")
case let .textMention(id):
try container.encode(3 as Int32, forKey: "t")
try container.encode(id.toInt64(), forKey: "peerId")
case let .textUrl(url):
try container.encode(4 as Int32, forKey: "t")
try container.encode(url, forKey: "url")
}
}
/*public init(decoder: PostboxDecoder) {
switch decoder.decodeInt32ForKey("t", orElse: 0) { switch decoder.decodeInt32ForKey("t", orElse: 0) {
case 0: case 0:
self = .bold self = .bold
@ -207,45 +268,10 @@ public enum ChatTextInputStateTextAttributeType: PostboxCoding, Equatable {
encoder.encodeInt32(4, forKey: "t") encoder.encodeInt32(4, forKey: "t")
encoder.encodeString(url, forKey: "url") encoder.encodeString(url, forKey: "url")
} }
} }*/
public static func ==(lhs: ChatTextInputStateTextAttributeType, rhs: ChatTextInputStateTextAttributeType) -> Bool {
switch lhs {
case .bold:
if case .bold = rhs {
return true
} else {
return false
}
case .italic:
if case .italic = rhs {
return true
} else {
return false
}
case .monospace:
if case .monospace = rhs {
return true
} else {
return false
}
case let .textMention(id):
if case .textMention(id) = rhs {
return true
} else {
return false
}
case let .textUrl(url):
if case .textUrl(url) = rhs {
return true
} else {
return false
}
}
}
} }
public struct ChatTextInputStateTextAttribute: PostboxCoding, Equatable { public struct ChatTextInputStateTextAttribute: Codable, Equatable {
public let type: ChatTextInputStateTextAttributeType public let type: ChatTextInputStateTextAttributeType
public let range: Range<Int> public let range: Range<Int>
@ -254,7 +280,25 @@ public struct ChatTextInputStateTextAttribute: PostboxCoding, Equatable {
self.range = range self.range = range
} }
public init(decoder: PostboxDecoder) { public init(from decoder: Decoder) throws {
let container = try decoder.container(keyedBy: StringCodingKey.self)
self.type = try container.decode(ChatTextInputStateTextAttributeType.self, forKey: "type")
let rangeFrom = (try? container.decodeIfPresent(Int32.self, forKey: "range0")) ?? 0
let rangeTo = (try? container.decodeIfPresent(Int32.self, forKey: "range1")) ?? 0
self.range = Int(rangeFrom) ..< Int(rangeTo)
}
public func encode(to encoder: Encoder) throws {
var container = encoder.container(keyedBy: StringCodingKey.self)
try container.encode(self.type, forKey: "type")
try container.encode(Int32(self.range.lowerBound), forKey: "range0")
try container.encode(Int32(self.range.upperBound), forKey: "range1")
}
/*public init(decoder: PostboxDecoder) {
self.type = decoder.decodeObjectForKey("type", decoder: { ChatTextInputStateTextAttributeType(decoder: $0) }) as! ChatTextInputStateTextAttributeType self.type = decoder.decodeObjectForKey("type", decoder: { ChatTextInputStateTextAttributeType(decoder: $0) }) as! ChatTextInputStateTextAttributeType
self.range = Int(decoder.decodeInt32ForKey("range0", orElse: 0)) ..< Int(decoder.decodeInt32ForKey("range1", orElse: 0)) self.range = Int(decoder.decodeInt32ForKey("range0", orElse: 0)) ..< Int(decoder.decodeInt32ForKey("range1", orElse: 0))
} }
@ -263,14 +307,14 @@ public struct ChatTextInputStateTextAttribute: PostboxCoding, Equatable {
encoder.encodeObject(self.type, forKey: "type") encoder.encodeObject(self.type, forKey: "type")
encoder.encodeInt32(Int32(self.range.lowerBound), forKey: "range0") encoder.encodeInt32(Int32(self.range.lowerBound), forKey: "range0")
encoder.encodeInt32(Int32(self.range.upperBound), forKey: "range1") encoder.encodeInt32(Int32(self.range.upperBound), forKey: "range1")
} }*/
public static func ==(lhs: ChatTextInputStateTextAttribute, rhs: ChatTextInputStateTextAttribute) -> Bool { public static func ==(lhs: ChatTextInputStateTextAttribute, rhs: ChatTextInputStateTextAttribute) -> Bool {
return lhs.type == rhs.type && lhs.range == rhs.range return lhs.type == rhs.type && lhs.range == rhs.range
} }
} }
public struct ChatTextInputStateText: PostboxCoding, Equatable { public struct ChatTextInputStateText: Codable, Equatable {
public let text: String public let text: String
public let attributes: [ChatTextInputStateTextAttribute] public let attributes: [ChatTextInputStateTextAttribute]
@ -305,7 +349,19 @@ public struct ChatTextInputStateText: PostboxCoding, Equatable {
self.attributes = parsedAttributes self.attributes = parsedAttributes
} }
public init(decoder: PostboxDecoder) { public init(from decoder: Decoder) throws {
let container = try decoder.container(keyedBy: StringCodingKey.self)
self.text = (try? container.decodeIfPresent(String.self, forKey: "text")) ?? ""
self.attributes = (try? container.decodeIfPresent([ChatTextInputStateTextAttribute].self, forKey: "attributes")) ?? []
}
public func encode(to encoder: Encoder) throws {
var container = encoder.container(keyedBy: StringCodingKey.self)
try container.encode(self.text, forKey: "text")
try container.encode(self.attributes, forKey: "attributes")
}
/*public init(decoder: PostboxDecoder) {
self.text = decoder.decodeStringForKey("text", orElse: "") self.text = decoder.decodeStringForKey("text", orElse: "")
self.attributes = decoder.decodeObjectArrayWithDecoderForKey("attributes") self.attributes = decoder.decodeObjectArrayWithDecoderForKey("attributes")
} }
@ -313,7 +369,7 @@ public struct ChatTextInputStateText: PostboxCoding, Equatable {
public func encode(_ encoder: PostboxEncoder) { public func encode(_ encoder: PostboxEncoder) {
encoder.encodeString(self.text, forKey: "text") encoder.encodeString(self.text, forKey: "text")
encoder.encodeObjectArray(self.attributes, forKey: "attributes") encoder.encodeObjectArray(self.attributes, forKey: "attributes")
} }*/
static public func ==(lhs: ChatTextInputStateText, rhs: ChatTextInputStateText) -> Bool { static public func ==(lhs: ChatTextInputStateText, rhs: ChatTextInputStateText) -> Bool {
return lhs.text == rhs.text && lhs.attributes == rhs.attributes return lhs.text == rhs.text && lhs.attributes == rhs.attributes
@ -360,7 +416,20 @@ public final class ChatEmbeddedInterfaceState: PeerChatListEmbeddedInterfaceStat
self.text = text self.text = text
} }
public init(decoder: PostboxDecoder) { public init(from decoder: Decoder) throws {
let container = try decoder.container(keyedBy: StringCodingKey.self)
self.timestamp = (try? container.decode(Int32.self, forKey: "d")) ?? 0
self.text = ((try? container.decodeIfPresent(ChatTextInputStateText.self, forKey: "at")) ?? ChatTextInputStateText()).attributedText()
}
public func encode(to encoder: Encoder) throws {
var container = encoder.container(keyedBy: StringCodingKey.self)
try container.encode(self.timestamp, forKey: "d")
try container.encode(ChatTextInputStateText(attributedText: self.text), forKey: "at")
}
/*public init(decoder: PostboxDecoder) {
self.timestamp = decoder.decodeInt32ForKey("d", orElse: 0) self.timestamp = decoder.decodeInt32ForKey("d", orElse: 0)
self.text = ((decoder.decodeObjectForKey("at", decoder: { ChatTextInputStateText(decoder: $0) }) as? ChatTextInputStateText) ?? ChatTextInputStateText()).attributedText() self.text = ((decoder.decodeObjectForKey("at", decoder: { ChatTextInputStateText(decoder: $0) }) as? ChatTextInputStateText) ?? ChatTextInputStateText()).attributedText()
} }
@ -368,7 +437,7 @@ public final class ChatEmbeddedInterfaceState: PeerChatListEmbeddedInterfaceStat
public func encode(_ encoder: PostboxEncoder) { public func encode(_ encoder: PostboxEncoder) {
encoder.encodeInt32(self.timestamp, forKey: "d") encoder.encodeInt32(self.timestamp, forKey: "d")
encoder.encodeObject(ChatTextInputStateText(attributedText: self.text), forKey: "at") encoder.encodeObject(ChatTextInputStateText(attributedText: self.text), forKey: "at")
} }*/
public func isEqual(to: PeerChatListEmbeddedInterfaceState) -> Bool { public func isEqual(to: PeerChatListEmbeddedInterfaceState) -> Bool {
if let to = to as? ChatEmbeddedInterfaceState { if let to = to as? ChatEmbeddedInterfaceState {

View File

@ -10,7 +10,7 @@ public enum ChatTextInputMediaRecordingButtonMode: Int32 {
case video = 1 case video = 1
} }
public struct ChatInterfaceSelectionState: PostboxCoding, Equatable { public struct ChatInterfaceSelectionState: Codable, Equatable {
public let selectedIds: Set<MessageId> public let selectedIds: Set<MessageId>
public static func ==(lhs: ChatInterfaceSelectionState, rhs: ChatInterfaceSelectionState) -> Bool { public static func ==(lhs: ChatInterfaceSelectionState, rhs: ChatInterfaceSelectionState) -> Bool {
@ -21,7 +21,27 @@ public struct ChatInterfaceSelectionState: PostboxCoding, Equatable {
self.selectedIds = selectedIds self.selectedIds = selectedIds
} }
public init(decoder: PostboxDecoder) { public init(from decoder: Decoder) throws {
let container = try decoder.container(keyedBy: StringCodingKey.self)
if let data = try? container.decodeIfPresent(Data.self, forKey: "i") {
self.selectedIds = Set(MessageId.decodeArrayFromBuffer(ReadBuffer(data: data)))
} else {
self.selectedIds = Set()
}
}
public func encode(to encoder: Encoder) throws {
var container = encoder.container(keyedBy: StringCodingKey.self)
let buffer = WriteBuffer()
MessageId.encodeArrayToBuffer(Array(selectedIds), buffer: buffer)
try container.encode(buffer.makeData(), forKey: "i")
}
/*public init(decoder: PostboxDecoder) {
if let data = decoder.decodeBytesForKeyNoCopy("i") { if let data = decoder.decodeBytesForKeyNoCopy("i") {
self.selectedIds = Set(MessageId.decodeArrayFromBuffer(data)) self.selectedIds = Set(MessageId.decodeArrayFromBuffer(data))
} else { } else {
@ -33,10 +53,10 @@ public struct ChatInterfaceSelectionState: PostboxCoding, Equatable {
let buffer = WriteBuffer() let buffer = WriteBuffer()
MessageId.encodeArrayToBuffer(Array(selectedIds), buffer: buffer) MessageId.encodeArrayToBuffer(Array(selectedIds), buffer: buffer)
encoder.encodeBytes(buffer, forKey: "i") encoder.encodeBytes(buffer, forKey: "i")
} }*/
} }
public struct ChatEditMessageState: PostboxCoding, Equatable { public struct ChatEditMessageState: Codable, Equatable {
public let messageId: MessageId public let messageId: MessageId
public let inputState: ChatTextInputState public let inputState: ChatTextInputState
public let disableUrlPreview: String? public let disableUrlPreview: String?
@ -49,7 +69,40 @@ public struct ChatEditMessageState: PostboxCoding, Equatable {
self.inputTextMaxLength = inputTextMaxLength self.inputTextMaxLength = inputTextMaxLength
} }
public init(decoder: PostboxDecoder) { public init(from decoder: Decoder) throws {
let container = try decoder.container(keyedBy: StringCodingKey.self)
self.messageId = MessageId(
peerId: PeerId((try? container.decode(Int64.self, forKey: "mp")) ?? 0),
namespace: (try? container.decode(Int32.self, forKey: "mn")) ?? 0,
id: (try? container.decode(Int32.self, forKey: "mi")) ?? 0
)
if let inputState = try? container.decode(ChatTextInputState.self, forKey: "is") {
self.inputState = inputState
} else {
self.inputState = ChatTextInputState()
}
self.disableUrlPreview = try? container.decodeIfPresent(String.self, forKey: "dup")
self.inputTextMaxLength = try? container.decodeIfPresent(Int32.self, forKey: "tl")
}
public func encode(to encoder: Encoder) throws {
var container = encoder.container(keyedBy: StringCodingKey.self)
try container.encode(self.messageId.peerId.toInt64(), forKey: "mp")
try container.encode(self.messageId.namespace, forKey: "mn")
try container.encode(self.messageId.id, forKey: "mi")
try container.encode(self.inputState, forKey: "is")
try container.encodeIfPresent(self.disableUrlPreview, forKey: "dup")
try container.encodeIfPresent(self.inputTextMaxLength, forKey: "tl")
}
/*public init(decoder: PostboxDecoder) {
self.messageId = MessageId(peerId: PeerId(decoder.decodeInt64ForKey("mp", orElse: 0)), namespace: decoder.decodeInt32ForKey("mn", orElse: 0), id: decoder.decodeInt32ForKey("mi", orElse: 0)) self.messageId = MessageId(peerId: PeerId(decoder.decodeInt64ForKey("mp", orElse: 0)), namespace: decoder.decodeInt32ForKey("mn", orElse: 0), id: decoder.decodeInt32ForKey("mi", orElse: 0))
if let inputState = decoder.decodeObjectForKey("is", decoder: { return ChatTextInputState(decoder: $0) }) as? ChatTextInputState { if let inputState = decoder.decodeObjectForKey("is", decoder: { return ChatTextInputState(decoder: $0) }) as? ChatTextInputState {
self.inputState = inputState self.inputState = inputState
@ -75,7 +128,7 @@ public struct ChatEditMessageState: PostboxCoding, Equatable {
} else { } else {
encoder.encodeNil(forKey: "ml") encoder.encodeNil(forKey: "ml")
} }
} }*/
public static func ==(lhs: ChatEditMessageState, rhs: ChatEditMessageState) -> Bool { public static func ==(lhs: ChatEditMessageState, rhs: ChatEditMessageState) -> Bool {
return lhs.messageId == rhs.messageId && lhs.inputState == rhs.inputState && lhs.disableUrlPreview == rhs.disableUrlPreview && lhs.inputTextMaxLength == rhs.inputTextMaxLength return lhs.messageId == rhs.messageId && lhs.inputState == rhs.inputState && lhs.disableUrlPreview == rhs.disableUrlPreview && lhs.inputTextMaxLength == rhs.inputTextMaxLength
@ -322,7 +375,7 @@ public final class ChatInterfaceState: SynchronizeableChatInterfaceState, Equata
public init(decoder: PostboxDecoder) { public init(decoder: PostboxDecoder) {
self.timestamp = decoder.decodeInt32ForKey("ts", orElse: 0) self.timestamp = decoder.decodeInt32ForKey("ts", orElse: 0)
if let inputState = decoder.decodeObjectForKey("is", decoder: { return ChatTextInputState(decoder: $0) }) as? ChatTextInputState { if let inputState = decoder.decode(ChatTextInputState.self, forKey: "is") {
self.composeInputState = inputState self.composeInputState = inputState
} else { } else {
self.composeInputState = ChatTextInputState() self.composeInputState = ChatTextInputState()
@ -345,12 +398,12 @@ public final class ChatInterfaceState: SynchronizeableChatInterfaceState, Equata
} else { } else {
self.forwardMessageIds = nil self.forwardMessageIds = nil
} }
if let editMessage = decoder.decodeObjectForKey("em", decoder: { ChatEditMessageState(decoder: $0) }) as? ChatEditMessageState { if let editMessage = decoder.decode(ChatEditMessageState.self, forKey: "em") {
self.editMessage = editMessage self.editMessage = editMessage
} else { } else {
self.editMessage = nil self.editMessage = nil
} }
if let selectionState = decoder.decodeObjectForKey("ss", decoder: { return ChatInterfaceSelectionState(decoder: $0) }) as? ChatInterfaceSelectionState { if let selectionState = decoder.decode(ChatInterfaceSelectionState.self, forKey: "ss") {
self.selectionState = selectionState self.selectionState = selectionState
} else { } else {
self.selectionState = nil self.selectionState = nil
@ -372,7 +425,7 @@ public final class ChatInterfaceState: SynchronizeableChatInterfaceState, Equata
public func encode(_ encoder: PostboxEncoder) { public func encode(_ encoder: PostboxEncoder) {
encoder.encodeInt32(self.timestamp, forKey: "ts") encoder.encodeInt32(self.timestamp, forKey: "ts")
encoder.encodeObject(self.composeInputState, forKey: "is") encoder.encode(self.composeInputState, forKey: "is")
if let composeDisableUrlPreview = self.composeDisableUrlPreview { if let composeDisableUrlPreview = self.composeDisableUrlPreview {
encoder.encodeString(composeDisableUrlPreview, forKey: "dup") encoder.encodeString(composeDisableUrlPreview, forKey: "dup")
} else { } else {
@ -395,12 +448,12 @@ public final class ChatInterfaceState: SynchronizeableChatInterfaceState, Equata
encoder.encodeNil(forKey: "fm") encoder.encodeNil(forKey: "fm")
} }
if let editMessage = self.editMessage { if let editMessage = self.editMessage {
encoder.encodeObject(editMessage, forKey: "em") encoder.encode(editMessage, forKey: "em")
} else { } else {
encoder.encodeNil(forKey: "em") encoder.encodeNil(forKey: "em")
} }
if let selectionState = self.selectionState { if let selectionState = self.selectionState {
encoder.encodeObject(selectionState, forKey: "ss") encoder.encode(selectionState, forKey: "ss")
} else { } else {
encoder.encodeNil(forKey: "ss") encoder.encodeNil(forKey: "ss")
} }

View File

@ -279,6 +279,12 @@ public final class PostboxEncoder {
self.buffer.write(&type, offset: 0, length: 1) self.buffer.write(&type, offset: 0, length: 1)
} }
public func encodeNil(forKey key: String) {
self.encodeKey(key)
var type: Int8 = ValueType.Nil.rawValue
self.buffer.write(&type, offset: 0, length: 1)
}
public func encodeInt32(_ value: Int32, forKey key: StaticString) { public func encodeInt32(_ value: Int32, forKey key: StaticString) {
self.encodeKey(key) self.encodeKey(key)
var type: Int8 = ValueType.Int32.rawValue var type: Int8 = ValueType.Int32.rawValue
@ -303,6 +309,14 @@ public final class PostboxEncoder {
self.buffer.write(&v, offset: 0, length: 8) self.buffer.write(&v, offset: 0, length: 8)
} }
public func encodeInt64(_ value: Int64, forKey key: String) {
self.encodeKey(key)
var type: Int8 = ValueType.Int64.rawValue
self.buffer.write(&type, offset: 0, length: 1)
var v = value
self.buffer.write(&v, offset: 0, length: 8)
}
public func encodeBool(_ value: Bool, forKey key: StaticString) { public func encodeBool(_ value: Bool, forKey key: StaticString) {
self.encodeKey(key) self.encodeKey(key)
var type: Int8 = ValueType.Bool.rawValue var type: Int8 = ValueType.Bool.rawValue
@ -311,6 +325,14 @@ public final class PostboxEncoder {
self.buffer.write(&v, offset: 0, length: 1) self.buffer.write(&v, offset: 0, length: 1)
} }
public func encodeBool(_ value: Bool, forKey key: String) {
self.encodeKey(key)
var type: Int8 = ValueType.Bool.rawValue
self.buffer.write(&type, offset: 0, length: 1)
var v: Int8 = value ? 1 : 0
self.buffer.write(&v, offset: 0, length: 1)
}
public func encodeDouble(_ value: Double, forKey key: StaticString) { public func encodeDouble(_ value: Double, forKey key: StaticString) {
self.encodeKey(key) self.encodeKey(key)
var type: Int8 = ValueType.Double.rawValue var type: Int8 = ValueType.Double.rawValue
@ -319,6 +341,14 @@ public final class PostboxEncoder {
self.buffer.write(&v, offset: 0, length: 8) self.buffer.write(&v, offset: 0, length: 8)
} }
public func encodeDouble(_ value: Double, forKey key: String) {
self.encodeKey(key)
var type: Int8 = ValueType.Double.rawValue
self.buffer.write(&type, offset: 0, length: 1)
var v = value
self.buffer.write(&v, offset: 0, length: 8)
}
public func encodeString(_ value: String, forKey key: StaticString) { public func encodeString(_ value: String, forKey key: StaticString) {
self.encodeKey(key) self.encodeKey(key)
var type: Int8 = ValueType.String.rawValue var type: Int8 = ValueType.String.rawValue
@ -333,6 +363,20 @@ public final class PostboxEncoder {
} }
} }
public func encodeString(_ value: String, forKey key: String) {
self.encodeKey(key)
var type: Int8 = ValueType.String.rawValue
self.buffer.write(&type, offset: 0, length: 1)
if let data = value.data(using: .utf8, allowLossyConversion: true) {
var length: Int32 = Int32(data.count)
self.buffer.write(&length, offset: 0, length: 4)
self.buffer.write(data)
} else {
var length: Int32 = 0
self.buffer.write(&length, offset: 0, length: 4)
}
}
public func encodeRootObject(_ value: PostboxCoding) { public func encodeRootObject(_ value: PostboxCoding) {
self.encodeObject(value, forKey: "_") self.encodeObject(value, forKey: "_")
} }
@ -598,6 +642,38 @@ public final class PostboxEncoder {
} }
} }
public func encode<T: Encodable>(_ value: T, forKey key: String) {
let innerEncoder = AdaptedPostboxEncoder()
guard let innerData = try? innerEncoder.encode(value) else {
return
}
self.encodeKey(key)
var t: Int8 = ValueType.Object.rawValue
self.buffer.write(&t, offset: 0, length: 1)
let string = "\(type(of: value))"
var typeHash: Int32 = murMurHashString32(string)
self.buffer.write(&typeHash, offset: 0, length: 4)
var length: Int32 = Int32(innerData.count)
self.buffer.write(&length, offset: 0, length: 4)
self.buffer.write(innerData)
}
public func encodeInnerObjectData(_ value: Data, forKey key: String) {
self.encodeKey(key)
var t: Int8 = ValueType.Object.rawValue
self.buffer.write(&t, offset: 0, length: 1)
var typeHash: Int32 = 0
self.buffer.write(&typeHash, offset: 0, length: 4)
var length: Int32 = Int32(value.count)
self.buffer.write(&length, offset: 0, length: 4)
self.buffer.write(value)
}
public let sharedWriteBuffer = WriteBuffer() public let sharedWriteBuffer = WriteBuffer()
} }
@ -718,6 +794,60 @@ public final class PostboxDecoder {
return false return false
} }
private class func positionOnKey(_ rawBytes: UnsafeRawPointer, offset: inout Int, maxOffset: Int, length: Int, key: String, valueType: ValueType?, consumeKey: Bool = true) -> Bool
{
let bytes = rawBytes.assumingMemoryBound(to: Int8.self)
let startOffset = offset
let keyData = key.data(using: .utf8)!
let keyLength: Int = keyData.count
while (offset < maxOffset) {
let keyOffset = offset
let readKeyLength = bytes[offset]
assert(readKeyLength >= 0)
offset += 1
offset += Int(readKeyLength)
let readValueType = bytes[offset]
offset += 1
if keyLength != Int(readKeyLength) {
skipValue(bytes, offset: &offset, length: length, valueType: ValueType(rawValue: readValueType)!)
continue
}
if keyData.withUnsafeBytes({ keyBytes -> Bool in
return memcmp(bytes + (offset - Int(readKeyLength) - 1), keyBytes.baseAddress!, keyLength) == 0
}) {
if let valueType = valueType {
if readValueType == valueType.rawValue {
return true
} else if readValueType == ValueType.Nil.rawValue {
return false
} else {
skipValue(bytes, offset: &offset, length: length, valueType: ValueType(rawValue: readValueType)!)
}
} else {
if !consumeKey {
offset = keyOffset
}
return true
}
} else {
skipValue(bytes, offset: &offset, length: length, valueType: ValueType(rawValue: readValueType)!)
}
}
if (startOffset != 0) {
offset = 0
return positionOnKey(bytes, offset: &offset, maxOffset: startOffset, length: length, key: key, valueType: valueType)
}
return false
}
private class func positionOnStringKey(_ rawBytes: UnsafeRawPointer, offset: inout Int, maxOffset: Int, length: Int, key: String, valueType: ValueType) -> Bool private class func positionOnStringKey(_ rawBytes: UnsafeRawPointer, offset: inout Int, maxOffset: Int, length: Int, key: String, valueType: ValueType) -> Bool
{ {
let bytes = rawBytes.assumingMemoryBound(to: Int8.self) let bytes = rawBytes.assumingMemoryBound(to: Int8.self)
@ -790,6 +920,22 @@ public final class PostboxDecoder {
return false return false
} }
public func containsKey(_ key: String) -> Bool {
if PostboxDecoder.positionOnKey(self.buffer.memory, offset: &self.offset, maxOffset: self.buffer.length, length: self.buffer.length, key: key, valueType: nil, consumeKey: false) {
return true
} else {
return false
}
}
public func decodeNilForKey(_ key: String) -> Bool {
if PostboxDecoder.positionOnKey(self.buffer.memory, offset: &self.offset, maxOffset: self.buffer.length, length: self.buffer.length, key: key, valueType: .Nil) {
return true
} else {
return false
}
}
public func decodeInt32ForKey(_ key: StaticString, orElse: Int32) -> Int32 { public func decodeInt32ForKey(_ key: StaticString, orElse: Int32) -> Int32 {
if PostboxDecoder.positionOnKey(self.buffer.memory, offset: &self.offset, maxOffset: self.buffer.length, length: self.buffer.length, key: key, valueType: .Int32) { if PostboxDecoder.positionOnKey(self.buffer.memory, offset: &self.offset, maxOffset: self.buffer.length, length: self.buffer.length, key: key, valueType: .Int32) {
var value: Int32 = 0 var value: Int32 = 0
@ -1520,4 +1666,38 @@ public final class PostboxDecoder {
return nil return nil
} }
} }
public func decodeDataForKey(_ key: String) -> Data? {
if PostboxDecoder.positionOnKey(self.buffer.memory, offset: &self.offset, maxOffset: self.buffer.length, length: self.buffer.length, key: key, valueType: .Bytes) {
var length: Int32 = 0
memcpy(&length, self.buffer.memory + self.offset, 4)
self.offset += 4 + Int(length)
var result = Data(count: Int(length))
result.withUnsafeMutableBytes { (bytes: UnsafeMutablePointer<Int8>) -> Void in
memcpy(bytes, self.buffer.memory.advanced(by: self.offset - Int(length)), Int(length))
}
return result
} else {
return nil
}
}
public func decode<T: Decodable>(_ type: T.Type, forKey key: String) -> T? {
if PostboxDecoder.positionOnKey(self.buffer.memory, offset: &self.offset, maxOffset: self.buffer.length, length: self.buffer.length, key: key, valueType: .Object) {
var typeHash: Int32 = 0
memcpy(&typeHash, self.buffer.memory + self.offset, 4)
self.offset += 4
var length: Int32 = 0
memcpy(&length, self.buffer.memory + self.offset, 4)
let innerBuffer = ReadBuffer(memory: self.buffer.memory + (self.offset + 4), length: Int(length), freeWhenDone: false)
let innerData = innerBuffer.makeData()
self.offset += 4 + Int(length)
return try? AdaptedPostboxDecoder().decode(T.self, from: innerData)
} else {
return nil
}
}
} }

View File

@ -1,5 +1,5 @@
public protocol PeerChatListEmbeddedInterfaceState: PostboxCoding { public protocol PeerChatListEmbeddedInterfaceState: Codable {
var timestamp: Int32 { get } var timestamp: Int32 { get }
func isEqual(to: PeerChatListEmbeddedInterfaceState) -> Bool func isEqual(to: PeerChatListEmbeddedInterfaceState) -> Bool

View File

@ -0,0 +1,47 @@
import Foundation
final public class AdaptedPostboxDecoder {
func decode<T>(_ type: T.Type, from data: Data) throws -> T where T : Decodable {
let decoder = _AdaptedPostboxDecoder(data: data)
return try T(from: decoder)
}
}
final class _AdaptedPostboxDecoder {
var codingPath: [CodingKey] = []
var userInfo: [CodingUserInfoKey : Any] = [:]
var container: AdaptedPostboxDecodingContainer?
fileprivate var data: Data
init(data: Data) {
self.data = data
}
}
extension _AdaptedPostboxDecoder: Decoder {
fileprivate func assertCanCreateContainer() {
precondition(self.container == nil)
}
func container<Key>(keyedBy type: Key.Type) -> KeyedDecodingContainer<Key> where Key : CodingKey {
assertCanCreateContainer()
let container = KeyedContainer<Key>(data: self.data, codingPath: self.codingPath, userInfo: self.userInfo)
self.container = container
return KeyedDecodingContainer(container)
}
func unkeyedContainer() -> UnkeyedDecodingContainer {
preconditionFailure()
}
func singleValueContainer() -> SingleValueDecodingContainer {
preconditionFailure()
}
}
protocol AdaptedPostboxDecodingContainer: AnyObject {
}

View File

@ -0,0 +1,83 @@
import Foundation
extension _AdaptedPostboxDecoder {
final class KeyedContainer<Key> where Key: CodingKey {
var codingPath: [CodingKey]
var userInfo: [CodingUserInfoKey: Any]
let decoder: PostboxDecoder
init(data: Data, codingPath: [CodingKey], userInfo: [CodingUserInfoKey : Any]) {
self.codingPath = codingPath
self.userInfo = userInfo
self.decoder = PostboxDecoder(buffer: MemoryBuffer(data: data))
}
}
}
extension _AdaptedPostboxDecoder.KeyedContainer: KeyedDecodingContainerProtocol {
var allKeys: [Key] {
preconditionFailure()
}
func contains(_ key: Key) -> Bool {
return self.decoder.containsKey(key.stringValue)
}
func decodeNil(forKey key: Key) throws -> Bool {
return self.decoder.decodeNilForKey(key.stringValue)
}
func decode<T>(_ type: T.Type, forKey key: Key) throws -> T where T : Decodable {
preconditionFailure()
}
func decode(_ type: Int32.Type, forKey key: Key) throws -> Int32 {
if let value = self.decoder.decodeOptionalInt32ForKey(key.stringValue) {
return value
} else {
throw DecodingError.keyNotFound(key, DecodingError.Context(codingPath: self.codingPath + [key], debugDescription: ""))
}
}
func decode(_ type: Int64.Type, forKey key: Key) throws -> Int32 {
if let value = self.decoder.decodeOptionalInt64ForKey(key.stringValue) {
return value
} else {
throw DecodingError.keyNotFound(key, DecodingError.Context(codingPath: self.codingPath + [key], debugDescription: ""))
}
}
func decode(_ type: Bool.Type, forKey key: Key) throws -> Int32 {
if let value = self.decoder.decodeOptionalBoolForKey(key.stringValue) {
return value
} else {
throw DecodingError.keyNotFound(key, DecodingError.Context(codingPath: self.codingPath + [key], debugDescription: ""))
}
}
func decode(_ type: String.Type, forKey key: Key) throws -> Int32 {
if let value = self.decoder.decodeOptionalStringForKey(key.stringValue) {
return value
} else {
throw DecodingError.keyNotFound(key, DecodingError.Context(codingPath: self.codingPath + [key], debugDescription: ""))
}
}
func nestedUnkeyedContainer(forKey key: Key) throws -> UnkeyedDecodingContainer {
preconditionFailure()
}
func nestedContainer<NestedKey>(keyedBy type: NestedKey.Type, forKey key: Key) throws -> KeyedDecodingContainer<NestedKey> where NestedKey : CodingKey {
preconditionFailure()
}
func superDecoder() throws -> Decoder {
preconditionFailure()
}
func superDecoder(forKey key: Key) throws -> Decoder {
preconditionFailure()
}
}
extension _AdaptedPostboxDecoder.KeyedContainer: AdaptedPostboxDecodingContainer {}

View File

@ -0,0 +1,82 @@
import Foundation
extension _AdaptedPostboxDecoder {
final class SingleValueContainer {
var codingPath: [CodingKey]
var userInfo: [CodingUserInfoKey: Any]
init(codingPath: [CodingKey], userInfo: [CodingUserInfoKey : Any]) {
self.codingPath = codingPath
self.userInfo = userInfo
}
}
}
extension _AdaptedPostboxDecoder.SingleValueContainer: SingleValueDecodingContainer {
func decodeNil() -> Bool {
preconditionFailure()
}
func decode(_ type: Bool.Type) throws -> Bool {
preconditionFailure()
}
func decode(_ type: String.Type) throws -> String {
preconditionFailure()
}
func decode(_ type: Double.Type) throws -> Double {
preconditionFailure()
}
func decode(_ type: Float.Type) throws -> Float {
preconditionFailure()
}
func decode(_ type: Int.Type) throws -> Int {
preconditionFailure()
}
func decode(_ type: Int8.Type) throws -> Int8 {
preconditionFailure()
}
func decode(_ type: Int16.Type) throws -> Int16 {
preconditionFailure()
}
func decode(_ type: Int32.Type) throws -> Int32 {
preconditionFailure()
}
func decode(_ type: Int64.Type) throws -> Int64 {
preconditionFailure()
}
func decode(_ type: UInt.Type) throws -> UInt {
preconditionFailure()
}
func decode(_ type: UInt8.Type) throws -> UInt8 {
preconditionFailure()
}
func decode(_ type: UInt16.Type) throws -> UInt16 {
preconditionFailure()
}
func decode(_ type: UInt32.Type) throws -> UInt32 {
preconditionFailure()
}
func decode(_ type: UInt64.Type) throws -> UInt64 {
preconditionFailure()
}
func decode<T>(_ type: T.Type) throws -> T where T : Decodable {
preconditionFailure()
}
}
extension _AdaptedPostboxDecoder.SingleValueContainer: AdaptedPostboxDecodingContainer {}

View File

@ -0,0 +1,15 @@
import Foundation
extension _AdaptedPostboxDecoder {
final class UnkeyedContainer {
var codingPath: [CodingKey]
var userInfo: [CodingUserInfoKey: Any]
init(data: Data, codingPath: [CodingKey], userInfo: [CodingUserInfoKey : Any]) {
self.codingPath = codingPath
self.userInfo = userInfo
}
}
}

View File

@ -0,0 +1,48 @@
import Foundation
public class AdaptedPostboxEncoder {
func encode(_ value: Encodable) throws -> Data {
let encoder = _AdaptedPostboxEncoder()
try value.encode(to: encoder)
return encoder.data
}
}
final class _AdaptedPostboxEncoder {
var codingPath: [CodingKey] = []
var userInfo: [CodingUserInfoKey : Any] = [:]
fileprivate var container: AdaptedPostboxEncodingContainer?
var data: Data {
return self.container!.makeData()
}
}
extension _AdaptedPostboxEncoder: Encoder {
fileprivate func assertCanCreateContainer() {
precondition(self.container == nil)
}
func container<Key>(keyedBy type: Key.Type) -> KeyedEncodingContainer<Key> where Key : CodingKey {
assertCanCreateContainer()
let container = KeyedContainer<Key>(codingPath: self.codingPath, userInfo: self.userInfo)
self.container = container
return KeyedEncodingContainer(container)
}
func unkeyedContainer() -> UnkeyedEncodingContainer {
preconditionFailure()
}
func singleValueContainer() -> SingleValueEncodingContainer {
preconditionFailure()
}
}
protocol AdaptedPostboxEncodingContainer: AnyObject {
func makeData() -> Data
}

View File

@ -0,0 +1,72 @@
import Foundation
extension _AdaptedPostboxEncoder {
final class KeyedContainer<Key> where Key: CodingKey {
var codingPath: [CodingKey]
var userInfo: [CodingUserInfoKey: Any]
let encoder: PostboxEncoder
init(codingPath: [CodingKey], userInfo: [CodingUserInfoKey : Any]) {
self.codingPath = codingPath
self.userInfo = userInfo
self.encoder = PostboxEncoder()
}
func makeData() -> Data {
return self.encoder.makeData()
}
}
}
extension _AdaptedPostboxEncoder.KeyedContainer: KeyedEncodingContainerProtocol {
func encode<T>(_ value: T, forKey key: Key) throws where T : Encodable {
let innerEncoder = _AdaptedPostboxEncoder()
try! value.encode(to: innerEncoder)
self.encoder.encodeInnerObjectData(innerEncoder.data, forKey: key.stringValue)
}
func encodeNil(forKey key: Key) throws {
self.encoder.encodeNil(forKey: key.stringValue)
}
func encode(_ value: Int32, forKey key: Key) throws {
self.encoder.encodeInt32(value, forKey: key.stringValue)
}
func encode(_ value: Int64, forKey key: Key) throws {
self.encoder.encodeInt64(value, forKey: key.stringValue)
}
func encode(_ value: Bool, forKey key: Key) throws {
self.encoder.encodeBool(value, forKey: key.stringValue)
}
func encode(_ value: Double, forKey key: Key) throws {
self.encoder.encodeDouble(value, forKey: key.stringValue)
}
func encode(_ value: String, forKey key: Key) throws {
self.encoder.encodeString(value, forKey: key.stringValue)
}
func nestedUnkeyedContainer(forKey key: Key) -> UnkeyedEncodingContainer {
preconditionFailure()
}
func nestedContainer<NestedKey>(keyedBy keyType: NestedKey.Type, forKey key: Key) -> KeyedEncodingContainer<NestedKey> where NestedKey : CodingKey {
preconditionFailure()
}
func superEncoder() -> Encoder {
preconditionFailure()
}
func superEncoder(forKey key: Key) -> Encoder {
preconditionFailure()
}
}
extension _AdaptedPostboxEncoder.KeyedContainer: AdaptedPostboxEncodingContainer {}

View File

@ -0,0 +1,85 @@
import Foundation
extension _AdaptedPostboxEncoder {
final class SingleValueContainer {
var codingPath: [CodingKey]
var userInfo: [CodingUserInfoKey: Any]
init(codingPath: [CodingKey], userInfo: [CodingUserInfoKey : Any]) {
self.codingPath = codingPath
self.userInfo = userInfo
}
}
}
extension _AdaptedPostboxEncoder.SingleValueContainer: SingleValueEncodingContainer {
func encodeNil() throws {
preconditionFailure()
}
func encode(_ value: Bool) throws {
preconditionFailure()
}
func encode(_ value: String) throws {
preconditionFailure()
}
func encode(_ value: Double) throws {
preconditionFailure()
}
func encode(_ value: Float) throws {
preconditionFailure()
}
func encode(_ value: Int) throws {
preconditionFailure()
}
func encode(_ value: Int8) throws {
preconditionFailure()
}
func encode(_ value: Int16) throws {
preconditionFailure()
}
func encode(_ value: Int32) throws {
preconditionFailure()
}
func encode(_ value: Int64) throws {
preconditionFailure()
}
func encode(_ value: UInt) throws {
preconditionFailure()
}
func encode(_ value: UInt8) throws {
preconditionFailure()
}
func encode(_ value: UInt16) throws {
preconditionFailure()
}
func encode(_ value: UInt32) throws {
preconditionFailure()
}
func encode(_ value: UInt64) throws {
preconditionFailure()
}
func encode<T>(_ value: T) throws where T : Encodable {
preconditionFailure()
}
}
extension _AdaptedPostboxEncoder.SingleValueContainer: AdaptedPostboxEncodingContainer {
func makeData() -> Data {
preconditionFailure()
}
}

View File

@ -0,0 +1,44 @@
import Foundation
extension _AdaptedPostboxEncoder {
final class UnkeyedContainer {
var codingPath: [CodingKey]
var userInfo: [CodingUserInfoKey: Any]
var count: Int {
preconditionFailure()
}
init(codingPath: [CodingKey], userInfo: [CodingUserInfoKey : Any]) {
self.codingPath = codingPath
self.userInfo = userInfo
}
}
}
extension _AdaptedPostboxEncoder.UnkeyedContainer: UnkeyedEncodingContainer {
func encodeNil() throws {
preconditionFailure()
}
func encode<T>(_ value: T) throws where T : Encodable {
preconditionFailure()
}
func nestedContainer<NestedKey>(keyedBy keyType: NestedKey.Type) -> KeyedEncodingContainer<NestedKey> where NestedKey : CodingKey {
preconditionFailure()
}
func nestedUnkeyedContainer() -> UnkeyedEncodingContainer {
preconditionFailure()
}
func superEncoder() -> Encoder {
preconditionFailure()
}
}
extension _AdaptedPostboxEncoder.UnkeyedContainer: AdaptedPostboxEncodingContainer {
func makeData() -> Data {
preconditionFailure()
}
}

View File

@ -0,0 +1 @@

View File

@ -0,0 +1,24 @@
public struct StringCodingKey: CodingKey, ExpressibleByStringLiteral {
public var stringValue: String
public init?(stringValue: String) {
self.stringValue = stringValue
}
public init(_ stringValue: String) {
self.stringValue = stringValue
}
public init(stringLiteral: String) {
self.stringValue = stringLiteral
}
public var intValue: Int? {
return nil
}
public init?(intValue: Int) {
return nil
}
}

View File

@ -16,7 +16,6 @@ import ChatInterfaceState
private var telegramUIDeclaredEncodables: Void = { private var telegramUIDeclaredEncodables: Void = {
declareEncodable(InAppNotificationSettings.self, f: { InAppNotificationSettings(decoder: $0) }) declareEncodable(InAppNotificationSettings.self, f: { InAppNotificationSettings(decoder: $0) })
declareEncodable(ChatInterfaceState.self, f: { ChatInterfaceState(decoder: $0) }) declareEncodable(ChatInterfaceState.self, f: { ChatInterfaceState(decoder: $0) })
declareEncodable(ChatEmbeddedInterfaceState.self, f: { ChatEmbeddedInterfaceState(decoder: $0) })
declareEncodable(VideoLibraryMediaResource.self, f: { VideoLibraryMediaResource(decoder: $0) }) declareEncodable(VideoLibraryMediaResource.self, f: { VideoLibraryMediaResource(decoder: $0) })
declareEncodable(LocalFileVideoMediaResource.self, f: { LocalFileVideoMediaResource(decoder: $0) }) declareEncodable(LocalFileVideoMediaResource.self, f: { LocalFileVideoMediaResource(decoder: $0) })
declareEncodable(LocalFileGifMediaResource.self, f: { LocalFileGifMediaResource(decoder: $0) }) declareEncodable(LocalFileGifMediaResource.self, f: { LocalFileGifMediaResource(decoder: $0) })