Skip to content

Commit 2e32bc2

Browse files
authored
Introduce ValueConstructible protocol. (#13089)
Summary: . Reviewed By: kirklandsign Differential Revision: D79381679
1 parent c706387 commit 2e32bc2

File tree

2 files changed

+433
-8
lines changed

2 files changed

+433
-8
lines changed

extension/apple/ExecuTorch/Exported/ExecuTorch+Value.swift

Lines changed: 267 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -8,14 +8,6 @@
88

99
@_exported import ExecuTorch
1010

11-
/// A protocol that provides a uniform way to convert different Swift types
12-
/// into a `Value`.
13-
@available(*, deprecated, message: "This API is experimental.")
14-
public protocol ValueConvertible {
15-
/// Converts the instance into a `Value`.
16-
func asValue() -> Value
17-
}
18-
1911
@available(*, deprecated, message: "This API is experimental.")
2012
public extension Value {
2113
/// Creates a `Value` instance encapsulating a `Tensor`.
@@ -41,6 +33,52 @@ public extension Value {
4133
}
4234
}
4335

36+
/// A protocol that provides a uniform way to convert different Swift types
37+
/// into a `Value`.
38+
@available(*, deprecated, message: "This API is experimental.")
39+
public protocol ValueConvertible {
40+
/// Converts the instance into a `Value`.
41+
func asValue() -> Value
42+
}
43+
44+
/// A protocol that provides a uniform way to create an instance from a `Value`.
45+
@available(*, deprecated, message: "This API is experimental.")
46+
public protocol ValueConstructible {
47+
/// Constructs the instance from a `Value`.
48+
static func from(_ value: Value) throws -> Self
49+
}
50+
51+
@available(*, deprecated, message: "This API is experimental.")
52+
public extension ValueConstructible {
53+
/// Sugar on top of `decode(from:)`
54+
init(_ value: Value) throws {
55+
self = try Self.from(value)
56+
}
57+
}
58+
59+
/// A protocol that provides a uniform way to create an instance from an array of `Value`.
60+
@available(*, deprecated, message: "This API is experimental.")
61+
public protocol ValueSequenceConstructible {
62+
/// Constructs the instance from a `Value` array.
63+
static func from(_ values: [Value]) throws -> Self
64+
}
65+
66+
@available(*, deprecated, message: "This API is experimental.")
67+
extension ValueSequenceConstructible where Self: ValueConstructible {
68+
public static func from(_ values: [Value]) throws -> Self {
69+
guard values.count == 1 else { throw Error(code: .invalidType) }
70+
return try Self.from(values[0])
71+
}
72+
}
73+
74+
@available(*, deprecated, message: "This API is experimental.")
75+
public extension ValueSequenceConstructible {
76+
/// Sugar on top of `decode(from:)`
77+
init(_ values: [Value]) throws {
78+
self = try Self.from(values)
79+
}
80+
}
81+
4482
// MARK: - ValueConvertible Conformances
4583

4684
@available(*, deprecated, message: "This API is experimental.")
@@ -150,3 +188,224 @@ extension UInt: ValueConvertible {
150188
/// Converts the `UInt` into a `Value`.
151189
public func asValue() -> Value { Value(NSNumber(value: self)) }
152190
}
191+
192+
// MARK: - ValueConstructible Conformances
193+
194+
@available(*, deprecated, message: "This API is experimental.")
195+
extension Value: ValueConstructible, ValueSequenceConstructible {
196+
public static func from(_ value: Value) throws -> Self {
197+
value as! Self
198+
}
199+
}
200+
201+
@available(*, deprecated, message: "This API is experimental.")
202+
extension AnyTensor: ValueConstructible, ValueSequenceConstructible {
203+
public static func from(_ value: Value) throws -> Self {
204+
guard let tensor = value.anyTensor else {
205+
throw Error(code: .invalidType, description: "Value is not a tensor")
206+
}
207+
return tensor as! Self
208+
}
209+
}
210+
211+
@available(*, deprecated, message: "This API is experimental.")
212+
extension Tensor: ValueConstructible, ValueSequenceConstructible {
213+
public static func from(_ value: Value) throws -> Self {
214+
guard let anyTensor = value.anyTensor else {
215+
throw Error(code: .invalidType, description: "Value is not a tensor")
216+
}
217+
guard let tensor = Tensor<T>(anyTensor) as? Self else {
218+
throw Error(code: .invalidType, description: "Tensor is not of type \(Self.self)")
219+
}
220+
return tensor
221+
}
222+
}
223+
224+
@available(*, deprecated, message: "This API is experimental.")
225+
extension String: ValueConstructible, ValueSequenceConstructible {
226+
public static func from(_ value: Value) throws -> Self {
227+
guard let string = value.string else {
228+
throw Error(code: .invalidType, description: "Value is not a string")
229+
}
230+
return string
231+
}
232+
}
233+
234+
@available(*, deprecated, message: "This API is experimental.")
235+
extension NSNumber: ValueConstructible, ValueSequenceConstructible {
236+
public static func from(_ value: Value) throws -> Self {
237+
guard let scalar = value.scalar as? Self else {
238+
throw Error(code: .invalidType, description: "Value is not a scalar")
239+
}
240+
return scalar
241+
}
242+
}
243+
244+
@available(*, deprecated, message: "This API is experimental.")
245+
extension UInt8: ValueConstructible, ValueSequenceConstructible {
246+
public static func from(_ value: Value) throws -> Self {
247+
guard let scalar = value.scalar else {
248+
throw Error(code: .invalidType, description: "Value is not a scalar")
249+
}
250+
guard let integer = UInt8(exactly: scalar.uint8Value) else {
251+
throw Error(code: .invalidType, description: "Cannot convert scalar to \(Self.self)")
252+
}
253+
return integer
254+
}
255+
}
256+
257+
@available(*, deprecated, message: "This API is experimental.")
258+
extension Int8: ValueConstructible, ValueSequenceConstructible {
259+
public static func from(_ value: Value) throws -> Self {
260+
guard let scalar = value.scalar else {
261+
throw Error(code: .invalidType, description: "Value is not a scalar")
262+
}
263+
guard let integer = Int8(exactly: scalar.int8Value) else {
264+
throw Error(code: .invalidType, description: "Cannot convert scalar to \(Self.self)")
265+
}
266+
return integer
267+
}
268+
}
269+
270+
@available(*, deprecated, message: "This API is experimental.")
271+
extension Int16: ValueConstructible, ValueSequenceConstructible {
272+
public static func from(_ value: Value) throws -> Self {
273+
guard let scalar = value.scalar else {
274+
throw Error(code: .invalidType, description: "Value is not a scalar")
275+
}
276+
guard let integer = Int16(exactly: scalar.int16Value) else {
277+
throw Error(code: .invalidType, description: "Cannot convert scalar to \(Self.self)")
278+
}
279+
return integer
280+
}
281+
}
282+
283+
@available(*, deprecated, message: "This API is experimental.")
284+
extension Int32: ValueConstructible, ValueSequenceConstructible {
285+
public static func from(_ value: Value) throws -> Self {
286+
guard let scalar = value.scalar else {
287+
throw Error(code: .invalidType, description: "Value is not a scalar")
288+
}
289+
guard let integer = Int32(exactly: scalar.int32Value) else {
290+
throw Error(code: .invalidType, description: "Cannot convert scalar to \(Self.self)")
291+
}
292+
return integer
293+
}
294+
}
295+
296+
@available(*, deprecated, message: "This API is experimental.")
297+
extension Int64: ValueConstructible, ValueSequenceConstructible {
298+
public static func from(_ value: Value) throws -> Self {
299+
guard let scalar = value.scalar else {
300+
throw Error(code: .invalidType, description: "Value is not a scalar")
301+
}
302+
guard let integer = Int64(exactly: scalar.int64Value) else {
303+
throw Error(code: .invalidType, description: "Cannot convert scalar to \(Self.self)")
304+
}
305+
return integer
306+
}
307+
}
308+
309+
@available(*, deprecated, message: "This API is experimental.")
310+
extension Int: ValueConstructible, ValueSequenceConstructible {
311+
public static func from(_ value: Value) throws -> Self {
312+
guard let scalar = value.scalar else {
313+
throw Error(code: .invalidType, description: "Value is not a scalar")
314+
}
315+
guard let integer = Int(exactly: scalar.intValue) else {
316+
throw Error(code: .invalidType, description: "Cannot convert scalar to \(Self.self)")
317+
}
318+
return integer
319+
}
320+
}
321+
322+
@available(*, deprecated, message: "This API is experimental.")
323+
extension Float: ValueConstructible, ValueSequenceConstructible {
324+
public static func from(_ value: Value) throws -> Self {
325+
guard value.isFloat else {
326+
throw Error(code: .invalidType, description: "Value is not a float")
327+
}
328+
return value.float as Self
329+
}
330+
}
331+
332+
@available(*, deprecated, message: "This API is experimental.")
333+
extension Double: ValueConstructible, ValueSequenceConstructible {
334+
public static func from(_ value: Value) throws -> Self {
335+
guard value.isDouble else {
336+
throw Error(code: .invalidType, description: "Value is not a double")
337+
}
338+
return value.double as Self
339+
}
340+
}
341+
342+
@available(*, deprecated, message: "This API is experimental.")
343+
extension Bool: ValueConstructible, ValueSequenceConstructible {
344+
public static func from(_ value: Value) throws -> Self {
345+
guard value.isBoolean else {
346+
throw Error(code: .invalidType, description: "Value is not a boolean")
347+
}
348+
return value.boolean as Self
349+
}
350+
}
351+
352+
@available(*, deprecated, message: "This API is experimental.")
353+
extension UInt16: ValueConstructible, ValueSequenceConstructible {
354+
public static func from(_ value: Value) throws -> Self {
355+
guard let scalar = value.scalar else {
356+
throw Error(code: .invalidType, description: "Value is not a scalar")
357+
}
358+
guard let integer = UInt16(exactly: scalar.uint16Value) else {
359+
throw Error(code: .invalidType, description: "Cannot convert scalar to \(Self.self)")
360+
}
361+
return integer
362+
}
363+
}
364+
365+
@available(*, deprecated, message: "This API is experimental.")
366+
extension UInt32: ValueConstructible, ValueSequenceConstructible {
367+
public static func from(_ value: Value) throws -> Self {
368+
guard let scalar = value.scalar else {
369+
throw Error(code: .invalidType, description: "Value is not a scalar")
370+
}
371+
guard let integer = UInt32(exactly: scalar.uint32Value) else {
372+
throw Error(code: .invalidType, description: "Cannot convert scalar to \(Self.self)")
373+
}
374+
return integer
375+
}
376+
}
377+
378+
@available(*, deprecated, message: "This API is experimental.")
379+
extension UInt64: ValueConstructible, ValueSequenceConstructible {
380+
public static func from(_ value: Value) throws -> Self {
381+
guard let scalar = value.scalar else {
382+
throw Error(code: .invalidType, description: "Value is not a scalar")
383+
}
384+
guard let integer = UInt64(exactly: scalar.uint64Value) else {
385+
throw Error(code: .invalidType, description: "Cannot convert scalar to \(Self.self)")
386+
}
387+
return integer
388+
}
389+
}
390+
391+
@available(*, deprecated, message: "This API is experimental.")
392+
extension UInt: ValueConstructible, ValueSequenceConstructible {
393+
public static func from(_ value: Value) throws -> Self {
394+
guard let scalar = value.scalar else {
395+
throw Error(code: .invalidType, description: "Value is not a scalar")
396+
}
397+
guard let integer = UInt(exactly: scalar.uintValue) else {
398+
throw Error(code: .invalidType, description: "Cannot convert scalar to \(Self.self)")
399+
}
400+
return integer
401+
}
402+
}
403+
404+
// MARK: - ValueSequenceConstructible Conformances
405+
406+
@available(*, deprecated, message: "This API is experimental.")
407+
extension Array: ValueSequenceConstructible where Element: ValueConstructible {
408+
public static func from(_ values: [Value]) throws -> [Element] {
409+
return try values.map { try Element.from($0) }
410+
}
411+
}

0 commit comments

Comments
 (0)