|
7 | 7 | // See http://www.apache.org/licenses/LICENSE-2.0 for license information. |
8 | 8 | //=----------------------------------------------------------------------------= |
9 | 9 |
|
| 10 | +import DiffableTextKit |
| 11 | + |
10 | 12 | //*============================================================================* |
11 | 13 | // MARK: * Bounds |
12 | 14 | //*============================================================================* |
@@ -85,3 +87,92 @@ extension Bounds: CustomStringConvertible { |
85 | 87 | "\(min) to \(max)" |
86 | 88 | } |
87 | 89 | } |
| 90 | + |
| 91 | +//=----------------------------------------------------------------------------= |
| 92 | +// MARK: + Upstream - Autocorrect |
| 93 | +//=----------------------------------------------------------------------------= |
| 94 | + |
| 95 | +extension Bounds { |
| 96 | + |
| 97 | + //=------------------------------------------------------------------------= |
| 98 | + // MARK: Value |
| 99 | + //=------------------------------------------------------------------------= |
| 100 | + |
| 101 | + @inlinable func autocorrect(_ value: inout Value) { |
| 102 | + value = Swift.min(Swift.max(min, value), max) |
| 103 | + } |
| 104 | + |
| 105 | + //=------------------------------------------------------------------------= |
| 106 | + // MARK: Number |
| 107 | + //=------------------------------------------------------------------------= |
| 108 | + |
| 109 | + @inlinable func autocorrect(_ number: inout Number) { |
| 110 | + autocorrect(&number.sign) |
| 111 | + } |
| 112 | + |
| 113 | + //=------------------------------------------------------------------------= |
| 114 | + // MARK: Number - Helpers |
| 115 | + //=------------------------------------------------------------------------= |
| 116 | + |
| 117 | + @inlinable func autocorrect(_ sign: inout Sign) { |
| 118 | + switch sign { |
| 119 | + case .positive: if max <= .zero, min != .zero { sign.toggle() } |
| 120 | + case .negative: if min >= .zero { sign.toggle() } |
| 121 | + } |
| 122 | + } |
| 123 | +} |
| 124 | + |
| 125 | +//=----------------------------------------------------------------------------= |
| 126 | +// MARK: + Downstream - Autovalidate |
| 127 | +//=----------------------------------------------------------------------------= |
| 128 | + |
| 129 | +extension Bounds { |
| 130 | + |
| 131 | + //=------------------------------------------------------------------------= |
| 132 | + // MARK: Number |
| 133 | + //=------------------------------------------------------------------------= |
| 134 | + |
| 135 | + @inlinable func autovalidate(_ number: Number) throws { |
| 136 | + try autovalidate(number.sign) |
| 137 | + } |
| 138 | + |
| 139 | + //=------------------------------------------------------------------------= |
| 140 | + // MARK: Number - Helpers |
| 141 | + //=------------------------------------------------------------------------= |
| 142 | + |
| 143 | + @inlinable func autovalidate(_ sign: Sign) throws { |
| 144 | + guard sign == sign.transformed(autocorrect) else { |
| 145 | + throw Info([.mark(sign), "is not in", .mark(self)]) |
| 146 | + } |
| 147 | + } |
| 148 | + |
| 149 | + //=------------------------------------------------------------------------= |
| 150 | + // MARK: Value |
| 151 | + //=------------------------------------------------------------------------= |
| 152 | + |
| 153 | + @inlinable func autovalidate(_ value: Value, _ number: inout Number) throws { |
| 154 | + if try edge(value), number.removeSeparatorAsSuffix() { |
| 155 | + Info.print([.autocorrection, .mark(number), "does not fit a fraction separator"]) |
| 156 | + } |
| 157 | + } |
| 158 | + |
| 159 | + //=------------------------------------------------------------------------= |
| 160 | + // MARK: Value - Helpers |
| 161 | + //=------------------------------------------------------------------------= |
| 162 | + |
| 163 | + @inlinable func edge(_ value: Value) throws -> Bool { |
| 164 | + if min < value && value < max { return false } |
| 165 | + //=--------------------------------------= |
| 166 | + // MARK: Value == Max |
| 167 | + //=--------------------------------------= |
| 168 | + if value == max { return value > .zero || min == max } |
| 169 | + //=--------------------------------------= |
| 170 | + // MARK: Value == Min |
| 171 | + //=--------------------------------------= |
| 172 | + if value == min { return value < .zero } |
| 173 | + //=--------------------------------------= |
| 174 | + // MARK: Value Is Out Of Bounds |
| 175 | + //=--------------------------------------= |
| 176 | + throw Info([.mark(value), "is not in", .mark(self)]) |
| 177 | + } |
| 178 | +} |
0 commit comments