forked from ml-explore/mlx-swift-lm
-
Notifications
You must be signed in to change notification settings - Fork 11
Expand file tree
/
Copy pathJSONDecodingTypes.swift
More file actions
156 lines (139 loc) · 4.75 KB
/
Copy pathJSONDecodingTypes.swift
File metadata and controls
156 lines (139 loc) · 4.75 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
// Copyright © 2024 Apple Inc.
import Foundation
// MARK: - IntOrIntArray
/// Decodes a JSON value that can be either a single Int or an array of Ints.
/// Used for fields like `eos_token_id` which may appear as `128001` or `[128001, 128008]`.
public struct IntOrIntArray: Codable, Sendable, Equatable {
public let values: [Int]
public init(_ values: [Int]) {
self.values = values
}
public init(_ value: Int) {
self.values = [value]
}
public init(from decoder: Decoder) throws {
let container = try decoder.singleValueContainer()
if let array = try? container.decode([Int].self) {
self.values = array
} else if let single = try? container.decode(Int.self) {
self.values = [single]
} else {
throw DecodingError.typeMismatch(
IntOrIntArray.self,
DecodingError.Context(
codingPath: decoder.codingPath,
debugDescription: "Expected Int or [Int]"
)
)
}
}
public func encode(to encoder: Encoder) throws {
var container = encoder.singleValueContainer()
if values.count == 1 {
try container.encode(values[0])
} else {
try container.encode(values)
}
}
/// Get the intermediate size for a specific layer
public subscript(layerIdx: Int) -> Int {
if values.count == 1 {
return values[0]
}
return values[layerIdx]
}
}
// MARK: - StringOrNumber
/// Representation of a heterogenous type in a JSON configuration file.
///
/// This can be: a string, a numeric value or an array of numeric values.
/// There are methods to do unwrapping, see e.g. ``asFloat()`` and
/// ``asFloats()`` or callers can switch on the enum.
public enum StringOrNumber: Codable, Equatable, Sendable {
case string(String)
case int(Int)
case float(Float)
case ints([Int])
case floats([Float])
case bool(Bool)
public init(from decoder: Decoder) throws {
let values = try decoder.singleValueContainer()
if let v = try? values.decode(Int.self) {
self = .int(v)
} else if let v = try? values.decode(Float.self) {
self = .float(v)
} else if let v = try? values.decode([Int].self) {
self = .ints(v)
} else if let v = try? values.decode([Float].self) {
self = .floats(v)
} else if let v = try? values.decode(Bool.self) {
self = .bool(v)
} else {
let v = try values.decode(String.self)
self = .string(v)
}
}
public func encode(to encoder: Encoder) throws {
var container = encoder.singleValueContainer()
switch self {
case .string(let v): try container.encode(v)
case .int(let v): try container.encode(v)
case .float(let v): try container.encode(v)
case .ints(let v): try container.encode(v)
case .floats(let v): try container.encode(v)
case .bool(let v): try container.encode(v)
}
}
/// Return the value as an optional array of integers.
///
/// This will not coerce `Float` or `String` to `Int`.
public func asInts() -> [Int]? {
switch self {
case .string(_): nil
case .int(let v): [v]
case .float(_): nil
case .ints(let array): array
case .floats(_): nil
case .bool(_): nil
}
}
/// Return the value as an optional integer.
///
/// This will not coerce `Float` or `String` to `Int`.
public func asInt() -> Int? {
switch self {
case .string(_): nil
case .int(let v): v
case .float(_): nil
case .ints(let array): array.count == 1 ? array[0] : nil
case .floats(_): nil
case .bool(let bool): bool ? 1 : 0
}
}
/// Return the value as an optional array of floats.
///
/// This will not coerce `Int` or `String` to `Float`.
public func asFloats() -> [Float]? {
switch self {
case .string(_): nil
case .int(let v): [Float(v)]
case .float(let float): [float]
case .ints(let array): array.map { Float($0) }
case .floats(let array): array
case .bool(let bool): [bool ? 1.0 : 0.0]
}
}
/// Return the value as an optional float.
///
/// This will not coerce `Int` or `String` to `Float`.
public func asFloat() -> Float? {
switch self {
case .string(_): nil
case .int(let v): Float(v)
case .float(let float): float
case .ints(let array): array.count == 1 ? Float(array[0]) : nil
case .floats(let array): array.count == 1 ? array[0] : nil
case .bool(let bool): bool ? 1.0 : 0.0
}
}
}