mirror of
https://github.com/ichmagmaus111/ghostgram.git
synced 2026-11-15 19:36:54 +01:00
Ghostgram for iOS, rebuilt from scratch on Telegram iOS 13.0. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
184 lines
6.2 KiB
Swift
184 lines
6.2 KiB
Swift
import Foundation
|
|
|
|
extension _AdaptedPostboxDecoder {
|
|
final class UnkeyedContainer {
|
|
enum Content {
|
|
case int32Array([Int32])
|
|
case int64Array([Int64])
|
|
case objectArray([Data])
|
|
case stringArray([String])
|
|
case dataArray([Data])
|
|
case objectDict([(Data, Data)])
|
|
|
|
var count: Int {
|
|
switch self {
|
|
case let .int32Array(array):
|
|
return array.count
|
|
case let .int64Array(array):
|
|
return array.count
|
|
case let .objectArray(array):
|
|
return array.count
|
|
case let .stringArray(array):
|
|
return array.count
|
|
case let .dataArray(array):
|
|
return array.count
|
|
case let .objectDict(dict):
|
|
return dict.count * 2
|
|
}
|
|
}
|
|
}
|
|
|
|
let codingPath: [CodingKey]
|
|
let userInfo: [CodingUserInfoKey: Any]
|
|
let content: Content
|
|
/// Set when the array bytes could not be split into elements. `Decoder.unkeyedContainer()`
|
|
/// cannot throw, so the container is created anyway and every `decode` throws
|
|
/// `DecodingError.dataCorrupted`; `isAtEnd` stays false so `Array(from:)` reaches that throw
|
|
/// instead of returning an empty array.
|
|
let isCorrupted: Bool
|
|
|
|
var count: Int? {
|
|
if self.isCorrupted {
|
|
return nil
|
|
}
|
|
return self.content.count
|
|
}
|
|
|
|
var isAtEnd: Bool {
|
|
if self.isCorrupted {
|
|
return false
|
|
}
|
|
return self.currentIndex >= self.content.count
|
|
}
|
|
|
|
fileprivate var _currentIndex: Int = 0
|
|
|
|
var currentIndex: Int {
|
|
return self._currentIndex
|
|
}
|
|
|
|
init(data: Data, codingPath: [CodingKey], userInfo: [CodingUserInfoKey: Any], content: Content, isCorrupted: Bool = false) {
|
|
self.codingPath = codingPath
|
|
self.userInfo = userInfo
|
|
self.content = content
|
|
self.isCorrupted = isCorrupted
|
|
}
|
|
|
|
fileprivate func throwIfCorrupted() throws {
|
|
if self.isCorrupted {
|
|
throw DecodingError.dataCorrupted(DecodingError.Context(codingPath: self.codingPath, debugDescription: "Malformed object array"))
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
extension _AdaptedPostboxDecoder.UnkeyedContainer: UnkeyedDecodingContainer {
|
|
func decodeNil() throws -> Bool {
|
|
preconditionFailure()
|
|
}
|
|
|
|
func decode<T>(_ type: T.Type) throws -> T where T : Decodable {
|
|
try self.throwIfCorrupted()
|
|
if type == Data.self {
|
|
switch self.content {
|
|
case let .dataArray(array):
|
|
let index = self._currentIndex
|
|
self._currentIndex += 1
|
|
return array[index] as! T
|
|
default:
|
|
assertionFailure()
|
|
throw DecodingError.typeMismatch(Data.self, DecodingError.Context(codingPath: self.codingPath, debugDescription: ""))
|
|
}
|
|
} else {
|
|
switch self.content {
|
|
case let .objectArray(array):
|
|
let index = self._currentIndex
|
|
self._currentIndex += 1
|
|
|
|
let data = array[index]
|
|
return try AdaptedPostboxDecoder().decode(T.self, from: data)
|
|
case let .objectDict(dict):
|
|
let index = self._currentIndex
|
|
self._currentIndex += 1
|
|
|
|
let dataPair = dict[index / 2]
|
|
let data: Data
|
|
if index % 2 == 0 {
|
|
data = dataPair.0
|
|
} else {
|
|
data = dataPair.1
|
|
}
|
|
return try AdaptedPostboxDecoder().decode(T.self, from: data)
|
|
case let .int32Array(array):
|
|
let index = self._currentIndex
|
|
self._currentIndex += 1
|
|
|
|
return array[index] as! T
|
|
case let .int64Array(array):
|
|
let index = self._currentIndex
|
|
self._currentIndex += 1
|
|
|
|
return array[index] as! T
|
|
case let .stringArray(array):
|
|
let index = self._currentIndex
|
|
self._currentIndex += 1
|
|
|
|
return array[index] as! T
|
|
default:
|
|
assertionFailure()
|
|
throw DecodingError.typeMismatch(T.self, DecodingError.Context(codingPath: self.codingPath, debugDescription: ""))
|
|
}
|
|
}
|
|
}
|
|
|
|
func decode(_ type: Int32.Type) throws -> Int32 {
|
|
try self.throwIfCorrupted()
|
|
switch self.content {
|
|
case let .int32Array(array):
|
|
let index = self._currentIndex
|
|
self._currentIndex += 1
|
|
return array[index]
|
|
default:
|
|
throw DecodingError.typeMismatch(Int32.self, DecodingError.Context(codingPath: self.codingPath, debugDescription: ""))
|
|
}
|
|
}
|
|
|
|
func decode(_ type: Int64.Type) throws -> Int64 {
|
|
try self.throwIfCorrupted()
|
|
switch self.content {
|
|
case let .int64Array(array):
|
|
let index = self._currentIndex
|
|
self._currentIndex += 1
|
|
return array[index]
|
|
default:
|
|
throw DecodingError.typeMismatch(Int64.self, DecodingError.Context(codingPath: self.codingPath, debugDescription: ""))
|
|
}
|
|
}
|
|
|
|
func decode(_ type: String.Type) throws -> String {
|
|
try self.throwIfCorrupted()
|
|
switch self.content {
|
|
case let .stringArray(array):
|
|
let index = self._currentIndex
|
|
self._currentIndex += 1
|
|
return array[index]
|
|
default:
|
|
throw DecodingError.typeMismatch(String.self, DecodingError.Context(codingPath: self.codingPath, debugDescription: ""))
|
|
}
|
|
}
|
|
|
|
func nestedUnkeyedContainer() throws -> UnkeyedDecodingContainer {
|
|
preconditionFailure()
|
|
}
|
|
|
|
func nestedContainer<NestedKey>(keyedBy type: NestedKey.Type) throws -> KeyedDecodingContainer<NestedKey> where NestedKey : CodingKey {
|
|
preconditionFailure()
|
|
}
|
|
|
|
func superDecoder() throws -> Decoder {
|
|
preconditionFailure()
|
|
}
|
|
}
|
|
|
|
extension _AdaptedPostboxDecoder.UnkeyedContainer: AdaptedPostboxDecodingContainer {}
|