Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
275 changes: 267 additions & 8 deletions extension/apple/ExecuTorch/Exported/ExecuTorch+Value.swift
Original file line number Diff line number Diff line change
Expand Up @@ -8,14 +8,6 @@

@_exported import ExecuTorch

/// A protocol that provides a uniform way to convert different Swift types
/// into a `Value`.
@available(*, deprecated, message: "This API is experimental.")
public protocol ValueConvertible {
/// Converts the instance into a `Value`.
func asValue() -> Value
}

@available(*, deprecated, message: "This API is experimental.")
public extension Value {
/// Creates a `Value` instance encapsulating a `Tensor`.
Expand All @@ -41,6 +33,52 @@ public extension Value {
}
}

/// A protocol that provides a uniform way to convert different Swift types
/// into a `Value`.
@available(*, deprecated, message: "This API is experimental.")
public protocol ValueConvertible {
/// Converts the instance into a `Value`.
func asValue() -> Value
}

/// A protocol that provides a uniform way to create an instance from a `Value`.
@available(*, deprecated, message: "This API is experimental.")
public protocol ValueConstructible {
/// Constructs the instance from a `Value`.
static func from(_ value: Value) throws -> Self
}

@available(*, deprecated, message: "This API is experimental.")
public extension ValueConstructible {
/// Sugar on top of `decode(from:)`
init(_ value: Value) throws {
self = try Self.from(value)
}
}

/// A protocol that provides a uniform way to create an instance from an array of `Value`.
@available(*, deprecated, message: "This API is experimental.")
public protocol ValueSequenceConstructible {
/// Constructs the instance from a `Value` array.
static func from(_ values: [Value]) throws -> Self
}

@available(*, deprecated, message: "This API is experimental.")
extension ValueSequenceConstructible where Self: ValueConstructible {
public static func from(_ values: [Value]) throws -> Self {
guard values.count == 1 else { throw Error(code: .invalidType) }
return try Self.from(values[0])
}
}

@available(*, deprecated, message: "This API is experimental.")
public extension ValueSequenceConstructible {
/// Sugar on top of `decode(from:)`
init(_ values: [Value]) throws {
self = try Self.from(values)
}
}

// MARK: - ValueConvertible Conformances

@available(*, deprecated, message: "This API is experimental.")
Expand Down Expand Up @@ -150,3 +188,224 @@ extension UInt: ValueConvertible {
/// Converts the `UInt` into a `Value`.
public func asValue() -> Value { Value(NSNumber(value: self)) }
}

// MARK: - ValueConstructible Conformances

@available(*, deprecated, message: "This API is experimental.")
extension Value: ValueConstructible, ValueSequenceConstructible {
public static func from(_ value: Value) throws -> Self {
value as! Self
}
}

@available(*, deprecated, message: "This API is experimental.")
extension AnyTensor: ValueConstructible, ValueSequenceConstructible {
public static func from(_ value: Value) throws -> Self {
guard let tensor = value.anyTensor else {
throw Error(code: .invalidType, description: "Value is not a tensor")
}
return tensor as! Self
}
}

@available(*, deprecated, message: "This API is experimental.")
extension Tensor: ValueConstructible, ValueSequenceConstructible {
public static func from(_ value: Value) throws -> Self {
guard let anyTensor = value.anyTensor else {
throw Error(code: .invalidType, description: "Value is not a tensor")
}
guard let tensor = Tensor<T>(anyTensor) as? Self else {
throw Error(code: .invalidType, description: "Tensor is not of type \(Self.self)")
}
return tensor
}
}

@available(*, deprecated, message: "This API is experimental.")
extension String: ValueConstructible, ValueSequenceConstructible {
public static func from(_ value: Value) throws -> Self {
guard let string = value.string else {
throw Error(code: .invalidType, description: "Value is not a string")
}
return string
}
}

@available(*, deprecated, message: "This API is experimental.")
extension NSNumber: ValueConstructible, ValueSequenceConstructible {
public static func from(_ value: Value) throws -> Self {
guard let scalar = value.scalar as? Self else {
throw Error(code: .invalidType, description: "Value is not a scalar")
}
return scalar
}
}

@available(*, deprecated, message: "This API is experimental.")
extension UInt8: ValueConstructible, ValueSequenceConstructible {
public static func from(_ value: Value) throws -> Self {
guard let scalar = value.scalar else {
throw Error(code: .invalidType, description: "Value is not a scalar")
}
guard let integer = UInt8(exactly: scalar.uint8Value) else {
throw Error(code: .invalidType, description: "Cannot convert scalar to \(Self.self)")
}
return integer
}
}

@available(*, deprecated, message: "This API is experimental.")
extension Int8: ValueConstructible, ValueSequenceConstructible {
public static func from(_ value: Value) throws -> Self {
guard let scalar = value.scalar else {
throw Error(code: .invalidType, description: "Value is not a scalar")
}
guard let integer = Int8(exactly: scalar.int8Value) else {
throw Error(code: .invalidType, description: "Cannot convert scalar to \(Self.self)")
}
return integer
}
}

@available(*, deprecated, message: "This API is experimental.")
extension Int16: ValueConstructible, ValueSequenceConstructible {
public static func from(_ value: Value) throws -> Self {
guard let scalar = value.scalar else {
throw Error(code: .invalidType, description: "Value is not a scalar")
}
guard let integer = Int16(exactly: scalar.int16Value) else {
throw Error(code: .invalidType, description: "Cannot convert scalar to \(Self.self)")
}
return integer
}
}

@available(*, deprecated, message: "This API is experimental.")
extension Int32: ValueConstructible, ValueSequenceConstructible {
public static func from(_ value: Value) throws -> Self {
guard let scalar = value.scalar else {
throw Error(code: .invalidType, description: "Value is not a scalar")
}
guard let integer = Int32(exactly: scalar.int32Value) else {
throw Error(code: .invalidType, description: "Cannot convert scalar to \(Self.self)")
}
return integer
}
}

@available(*, deprecated, message: "This API is experimental.")
extension Int64: ValueConstructible, ValueSequenceConstructible {
public static func from(_ value: Value) throws -> Self {
guard let scalar = value.scalar else {
throw Error(code: .invalidType, description: "Value is not a scalar")
}
guard let integer = Int64(exactly: scalar.int64Value) else {
throw Error(code: .invalidType, description: "Cannot convert scalar to \(Self.self)")
}
return integer
}
}

@available(*, deprecated, message: "This API is experimental.")
extension Int: ValueConstructible, ValueSequenceConstructible {
public static func from(_ value: Value) throws -> Self {
guard let scalar = value.scalar else {
throw Error(code: .invalidType, description: "Value is not a scalar")
}
guard let integer = Int(exactly: scalar.intValue) else {
throw Error(code: .invalidType, description: "Cannot convert scalar to \(Self.self)")
}
return integer
}
}

@available(*, deprecated, message: "This API is experimental.")
extension Float: ValueConstructible, ValueSequenceConstructible {
public static func from(_ value: Value) throws -> Self {
guard value.isFloat else {
throw Error(code: .invalidType, description: "Value is not a float")
}
return value.float as Self
}
}

@available(*, deprecated, message: "This API is experimental.")
extension Double: ValueConstructible, ValueSequenceConstructible {
public static func from(_ value: Value) throws -> Self {
guard value.isDouble else {
throw Error(code: .invalidType, description: "Value is not a double")
}
return value.double as Self
}
}

@available(*, deprecated, message: "This API is experimental.")
extension Bool: ValueConstructible, ValueSequenceConstructible {
public static func from(_ value: Value) throws -> Self {
guard value.isBoolean else {
throw Error(code: .invalidType, description: "Value is not a boolean")
}
return value.boolean as Self
}
}

@available(*, deprecated, message: "This API is experimental.")
extension UInt16: ValueConstructible, ValueSequenceConstructible {
public static func from(_ value: Value) throws -> Self {
guard let scalar = value.scalar else {
throw Error(code: .invalidType, description: "Value is not a scalar")
}
guard let integer = UInt16(exactly: scalar.uint16Value) else {
throw Error(code: .invalidType, description: "Cannot convert scalar to \(Self.self)")
}
return integer
}
}

@available(*, deprecated, message: "This API is experimental.")
extension UInt32: ValueConstructible, ValueSequenceConstructible {
public static func from(_ value: Value) throws -> Self {
guard let scalar = value.scalar else {
throw Error(code: .invalidType, description: "Value is not a scalar")
}
guard let integer = UInt32(exactly: scalar.uint32Value) else {
throw Error(code: .invalidType, description: "Cannot convert scalar to \(Self.self)")
}
return integer
}
}

@available(*, deprecated, message: "This API is experimental.")
extension UInt64: ValueConstructible, ValueSequenceConstructible {
public static func from(_ value: Value) throws -> Self {
guard let scalar = value.scalar else {
throw Error(code: .invalidType, description: "Value is not a scalar")
}
guard let integer = UInt64(exactly: scalar.uint64Value) else {
throw Error(code: .invalidType, description: "Cannot convert scalar to \(Self.self)")
}
return integer
}
}

@available(*, deprecated, message: "This API is experimental.")
extension UInt: ValueConstructible, ValueSequenceConstructible {
public static func from(_ value: Value) throws -> Self {
guard let scalar = value.scalar else {
throw Error(code: .invalidType, description: "Value is not a scalar")
}
guard let integer = UInt(exactly: scalar.uintValue) else {
throw Error(code: .invalidType, description: "Cannot convert scalar to \(Self.self)")
}
return integer
}
}

// MARK: - ValueSequenceConstructible Conformances

@available(*, deprecated, message: "This API is experimental.")
extension Array: ValueSequenceConstructible where Element: ValueConstructible {
public static func from(_ values: [Value]) throws -> [Element] {
return try values.map { try Element.from($0) }
}
}
Loading
Loading