Swiftgram/submodules/Postbox/Sources/Utils/Decoder/AdaptedPostboxDecoder.swift
2021-09-13 20:40:09 +04:00

153 lines
4.4 KiB
Swift

import Foundation
final public class AdaptedPostboxDecoder {
enum ContentType {
case object
case int32Array
case int64Array
case objectArray
case stringArray
case dataArray
case objectDict
}
public final class RawObjectData: Decodable {
public let data: Data
public let typeHash: Int32
public init(data: Data, typeHash: Int32) {
self.data = data
self.typeHash = typeHash
}
public init(from decoder: Decoder) throws {
preconditionFailure()
}
}
public init() {
}
public func decode<T>(_ type: T.Type, from data: Data) throws -> T where T : Decodable {
return try self.decode(type, from: data, contentType: .object)
}
func decode<T>(_ type: T.Type, from data: Data, contentType: ContentType) throws -> T where T : Decodable {
if type == AdaptedPostboxDecoder.RawObjectData.self {
if case .object = contentType {
return AdaptedPostboxDecoder.RawObjectData(data: data, typeHash: 0) as! T
} else {
preconditionFailure()
}
}
let decoder = _AdaptedPostboxDecoder(data: data, contentType: contentType)
return try T(from: decoder)
}
}
extension AdaptedPostboxDecoder.ContentType {
init?(valueType: ObjectDataValueType) {
switch valueType {
case .Int32:
return nil
case .Int64:
return nil
case .Bool:
return nil
case .Double:
return nil
case .String:
return nil
case .Object:
self = .object
case .Int32Array:
self = .int32Array
case .Int64Array:
self = .int64Array
case .ObjectArray:
self = .objectArray
case .ObjectDictionary:
self = .objectDict
case .Bytes:
return nil
case .Nil:
return nil
case .StringArray:
self = .stringArray
case .BytesArray:
self = .dataArray
}
}
}
final class _AdaptedPostboxDecoder {
var codingPath: [CodingKey] = []
var userInfo: [CodingUserInfoKey : Any] = [:]
var container: AdaptedPostboxDecodingContainer?
fileprivate let data: Data
fileprivate let contentType: AdaptedPostboxDecoder.ContentType
init(data: Data, contentType: AdaptedPostboxDecoder.ContentType) {
self.data = data
self.contentType = contentType
}
}
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 {
assertCanCreateContainer()
let decoder = PostboxDecoder(buffer: MemoryBuffer(data: self.data))
var content: UnkeyedContainer.Content?
switch self.contentType {
case .object:
preconditionFailure()
case .int32Array:
content = .int32Array(decoder.decodeInt32ArrayRaw())
case .int64Array:
content = .int64Array(decoder.decodeInt64ArrayRaw())
case .objectArray:
content = .objectArray(decoder.decodeObjectDataArrayRaw())
case .stringArray:
content = .stringArray(decoder.decodeStringArrayRaw())
case .dataArray:
content = .dataArray(decoder.decodeBytesArrayRaw().map { $0.makeData() })
case .objectDict:
content = .objectDict(decoder.decodeObjectDataDictRaw())
}
if let content = content {
let container = UnkeyedContainer(data: self.data, codingPath: self.codingPath, userInfo: self.userInfo, content: content)
self.container = container
return container
} else {
preconditionFailure()
}
}
func singleValueContainer() -> SingleValueDecodingContainer {
preconditionFailure()
}
}
protocol AdaptedPostboxDecodingContainer: AnyObject {
}