1111// MARK: * Context
1212//* ============================================================================*
1313
14- /// A set of values describing the state of a diffable text view.
15- ///
16- /// - Uses copy-on-write semantics.
17- ///
14+ /// State of a diffable text view.
1815public struct Context < Style: DiffableTextStyle > {
1916
2017 public typealias Cache = Style . Cache
@@ -41,67 +38,40 @@ public struct Context<Style: DiffableTextStyle> {
4138 // MARK: Transformation
4239 //=------------------------------------------------------------------------=
4340
44- /// Writes to storage with copy-on-write behavior.
45- @inlinable mutating func write( _ write: ( Storage ) -> Void ) {
46- //=--------------------------------------=
47- // Unique
48- //=--------------------------------------=
49- if !isKnownUniquelyReferenced( & storage) {
50- self . storage = Storage ( status, layout, backup)
51- }
52- //=--------------------------------------=
53- // Update
54- //=--------------------------------------=
55- write ( self . storage)
56- }
57-
58- @inlinable mutating func merge( _ remote: Transaction ) {
59- //=--------------------------------------=
60- // Active
61- //=--------------------------------------=
62- if remote. base != nil , layout != nil {
63- self . write { storage in
64- storage. status = remote. status
65- storage. layout!. merge ( snapshot: remote. base!)
66- }
67- //=--------------------------------------=
68- // Inactive
69- //=--------------------------------------=
70- } else { self . storage = Storage ( remote) }
41+ @inlinable mutating func unique( ) {
42+ if !isKnownUniquelyReferenced( & storage) { self . storage = storage. copy ( ) }
7143 }
7244
7345 //*========================================================================*
74- // MARK: * Storage
46+ // MARK: * Storage [...]
7547 //*========================================================================*
7648
7749 @usableFromInline final class Storage {
7850
7951 //=--------------------------------------------------------------------=
80- // MARK: State
81- //=--------------------------------------------------------------------=
8252
8353 @usableFromInline var status : Status
8454 @usableFromInline var layout : Layout ?
8555 @usableFromInline var backup : String ?
8656
87- //=--------------------------------------------------------------------=
88- // MARK: Initializers
8957 //=--------------------------------------------------------------------=
9058
9159 @inlinable init ( _ status: Status , _ layout: Layout ? , _ backup: String ? ) {
9260 self . status = status
9361 self . layout = layout
9462 self . backup = backup
95- //=----------------------------------=
96- // Invariants
97- //=----------------------------------=
63+
9864 assert ( ( status. focus == true ) == ( layout != nil ) )
9965 assert ( ( status. focus == false ) == ( backup != nil ) )
10066 }
10167
10268 @inlinable convenience init ( _ remote: Transaction ) {
10369 self . init ( remote. status, remote. base. map ( Layout . init) , remote. backup)
10470 }
71+
72+ @inlinable func copy( ) -> Storage {
73+ Storage ( status, layout, backup)
74+ }
10575 }
10676
10777 //*========================================================================*
@@ -211,7 +181,7 @@ extension Context {
211181extension Context {
212182
213183 //=------------------------------------------------------------------------=
214- // MARK: Synchronization
184+ // MARK: Status
215185 //=------------------------------------------------------------------------=
216186
217187 /// Call this on view update.
@@ -238,6 +208,24 @@ extension Context {
238208 update += . value( changes. contains ( . value) )
239209 return update
240210 }
211+
212+ //=------------------------------------------------------------------------=
213+ // MARK: Transaction
214+ //=------------------------------------------------------------------------=
215+
216+ @inlinable mutating func merge( _ remote: Transaction ) {
217+ //=--------------------------------------=
218+ // Active
219+ //=--------------------------------------=
220+ if remote. base != nil , layout != nil {
221+ self . unique ( )
222+ self . storage. status = remote. status
223+ self . storage. layout!. merge ( snapshot: remote. base!)
224+ //=--------------------------------------=
225+ // Inactive
226+ //=--------------------------------------=
227+ } else { self . storage = Storage ( remote) }
228+ }
241229}
242230
243231//=----------------------------------------------------------------------------=
@@ -251,8 +239,9 @@ extension Context {
251239 //=------------------------------------------------------------------------=
252240
253241 /// Call this on changes to text.
254- @inlinable public mutating func merge( _ characters: String , in range:
255- Range < Offset < some Encoding > > , with cache: inout Cache ) throws -> Update {
242+ @inlinable public mutating func merge< T> (
243+ _ characters: String , in range: Range < Offset < T > > ,
244+ with cache: inout Cache ) throws -> Update {
256245 //=--------------------------------------=
257246 // Layout
258247 //=--------------------------------------=
@@ -271,11 +260,10 @@ extension Context {
271260 //=--------------------------------------=
272261 // Update
273262 //=--------------------------------------=
274- self . write { storage in
275- storage. status. value = commit. value
276- storage. layout!. selection. collapse ( )
277- storage. layout!. merge ( snapshot: commit. snapshot)
278- }
263+ self . unique ( )
264+ self . storage. status. value = commit. value
265+ self . storage. layout!. selection. collapse ( )
266+ self . storage. layout!. merge ( snapshot: commit. snapshot)
279267 //=--------------------------------------=
280268 // Return
281269 //=--------------------------------------=
@@ -289,24 +277,24 @@ extension Context {
289277 //=------------------------------------------------------------------------=
290278
291279 /// Call this on changes to selection.
292- @inlinable public mutating func merge(
293- selection: Range < Offset < some Encoding > > , momentums: Bool ) -> Update {
280+ @inlinable public mutating func merge< T > (
281+ selection: Range < Offset < T > > , momentums: Bool ) -> Update {
294282 //=--------------------------------------=
295283 // Layout
296284 //=--------------------------------------=
297285 if layout == nil { return [ ] }
298286 //=--------------------------------------=
299287 // Values
300288 //=--------------------------------------=
301- let selection = Selection ( layout!. snapshot. indices ( at: selection) )
289+ let selection = Selection (
290+ layout!. snapshot. indices ( at: selection) )
302291 //=--------------------------------------=
303292 // Update
304293 //=--------------------------------------=
305- self . write { storage in
306- storage. layout!. merge (
307- selection: selection,
308- momentums: momentums)
309- }
294+ self . unique ( )
295+ self . storage. layout!. merge (
296+ selection: selection,
297+ momentums: momentums)
310298 //=--------------------------------------=
311299 // Return
312300 //=--------------------------------------=
0 commit comments