Sources/TwitterApacheThrift/ThriftType.swift (120 lines of code) (raw):
// Copyright 2020 Twitter, Inc.
// Licensed under the Apache License, Version 2.0
// http://www.apache.org/licenses/LICENSE-2.0
//
// ThriftType.swift
// TwitterApacheThrift
//
// Created on 3/25/20.
// Copyright © 2020 Twitter, Inc. All rights reserved.
//
import Foundation
/// A mapping between Swift types and thrift type
///
/// - Note: Any type not listed is not supported
public enum ThriftType: UInt8 {
/// Thrift control type not mapped to swift type
case stop = 0
/// Thrift control type not mapped to swift type
case void = 1
/// A `bool` type
case bool = 2
/// Represented as a `UInt8`
case byte = 3
/// A `Double` type
case double = 4
/// A `Int16` type
case int16 = 6
/// A `Int32` type
case int32 = 8
/// A `Int64`
case int64 = 10
/// This type can be either a String or Data
/// it is determined based on the type in the model
case string = 11
/// A struct or a class depending on the model
case structure = 12
/// Represented as a dictionary
case map = 13
/// A `Set` type
case set = 14
/// Represented as an array
case list = 15
}
extension ThriftType {
var compactValue: UInt8 {
switch self {
case .stop: return 0
/// Thrift control type not mapped to swift type
case .void: return 1
/// A `bool` type when used in maps, lists, and sets.
/// False when used in structs.
case .bool: return 2
/// Represented as a `UInt8`
case .byte: return 3
/// A `Int16` type
case .int16: return 4
/// A `Int32` type
case .int32: return 5
/// A `Int64`
case .int64: return 6
/// A `Double` type
case .double: return 7
/// This type can be either a String or Data
/// it is determined based on the type in the model
case .string: return 8
/// Represented as an array
case .list: return 9
/// A `Set` type
case .set: return 10
/// Represented as a dictionary
case .map: return 11
/// A struct or a class depending on the model
case .structure: return 12
}
}
init(compactValue: UInt8) throws {
switch compactValue {
case 0: self = .stop
case 1: self = .void
case 2: self = .bool
case 3: self = .byte
case 4: self = .int16
case 5: self = .int32
case 6: self = .int64
case 7: self = .double
case 8: self = .string
case 9: self = .list
case 10: self = .set
case 11: self = .map
case 12: self = .structure
default:
throw ThriftDecoderError.unsupportedThriftType
}
}
}
extension ThriftType {
/// Creates a ThriftType from the a thrift value
/// - Parameter coreValue: The value from the thrift
/// - Throws: `ThriftDecoderError.unsupportedThriftType` if the type is not supported
init(coreValue: UInt8) throws {
guard let value = ThriftType(rawValue: coreValue) else {
throw ThriftDecoderError.unsupportedThriftType
}
self = value
}
}
extension ThriftType {
/// Maps a value to a thrift type
/// - Parameter value: The value to convert
/// - Throws: `ThriftEncoderError.unencodableType` when the type is not supported
/// - Returns: The thrift type of the value
static func type<T>(from value: T) throws -> ThriftType where T : Encodable {
return try type(from: T.self)
}
/// Maps a type to a thrift type
/// - Parameter value: The value to convert
/// - Throws: `ThriftEncoderError.unencodableType` when the type is not supported
/// - Returns: The thrift type of the value
static func type<T>(from value: T.Type) throws -> ThriftType where T : Encodable {
switch value {
case is Bool.Type:
return .bool
case is Data.Type:
return .string //Data is not an official thrift type but is the same format as string
case is Double.Type:
return .double
case is UInt8.Type:
return .byte
case is Int16.Type:
return .int16
case is Int32.Type:
return .int32
case is Int64.Type:
return .int64
case is String.Type:
return .string
case let v as ThriftEncodable.Type:
return try v.thriftType()
default:
throw ThriftEncoderError.unencodableType(type: value.self)
}
}
}
extension ThriftType {
/// Maps a value to a thrift type
/// - Parameter value: The value to convert
/// - Throws: `ThriftEncoderError.unencodableType` when the type is not supported
/// - Returns: The thrift type of the value
static func decodableType<T>(from value: T) throws -> ThriftType where T : Decodable {
return try decodableType(from: T.self)
}
/// Maps a type to a thrift type
/// - Parameter value: The value to convert
/// - Throws: `ThriftEncoderError.unencodableType` when the type is not supported
/// - Returns: The thrift type of the value
static func decodableType<T>(from value: T.Type) throws -> ThriftType where T : Decodable {
switch value {
case is Bool.Type:
return .bool
case is Data.Type:
return .string //Data is not an official thrift type but is the same format as string
case is Double.Type:
return .double
case is UInt8.Type:
return .byte
case is Int16.Type:
return .int16
case is Int32.Type:
return .int32
case is Int64.Type:
return .int64
case is String.Type:
return .string
case let v as ThriftEncodable.Type:
return try v.thriftType()
default:
throw ThriftDecoderError.undecodableType(type: value.self)
}
}
}