@@ -4,7 +4,7 @@ module Json.Diff exposing (diff, invertibleDiff, diffWithCustomWeight)
4
4
5
5
This has been implemented rather simply, and is probably not very optimised, but it should work for a lot of use cases.
6
6
7
- @docs diff, invertibleDiff, diffWithCustomWeight
7
+ @docs diff, invertibleDiff, diffWithCustomWeight, cheapDiff
8
8
9
9
-}
10
10
@@ -62,6 +62,18 @@ diffWithCustomWeight weight =
62
62
internalDiff weight []
63
63
64
64
65
+ {- | Does a diff without using any testing of multiple options. This makes computing the diff much cheaper, but is much
66
+ more likely to produce less concise (but still correct) patches.
67
+
68
+ In particular, removing elements from the start of lists will produce changes for future elements, and lots of small
69
+ changes may be created rather than doing a single replace more efficiently.
70
+
71
+ -}
72
+ cheapDiff : Json .Value -> Json .Value -> Invertible .Patch
73
+ cheapDiff =
74
+ internalCheapDiff []
75
+
76
+
65
77
66
78
{- Private -}
67
79
@@ -86,7 +98,7 @@ internalDiff weight root a b =
86
98
d
87
99
88
100
Nothing ->
89
- case try ( Json . dict Json . value) a b |> Maybe . andThen ( diffObject weight root) of
101
+ case try ( Json . dict Json . value) a b |> Maybe . andThen ( diffObject ( internalDiff weight) root) of
90
102
Just modify ->
91
103
if weight modify > weight replace then
92
104
replace
@@ -98,6 +110,50 @@ internalDiff weight root a b =
98
110
replace
99
111
100
112
113
+ internalCheapDiff : Json .Pointer -> Json .Value -> Json .Value -> Invertible .Patch
114
+ internalCheapDiff root a b =
115
+ let
116
+ replace =
117
+ [ Invertible . Replace root a b ]
118
+ in
119
+ case try primitiveDecoder a b |> Maybe . map primitiveEquals of
120
+ Just equal ->
121
+ if equal then
122
+ []
123
+
124
+ else
125
+ replace
126
+
127
+ Nothing ->
128
+ case try ( Json . list Json . value) a b |> Maybe . map ( cheapDiffList root) of
129
+ Just d ->
130
+ d
131
+
132
+ Nothing ->
133
+ case try ( Json . dict Json . value) a b |> Maybe . andThen ( diffObject internalCheapDiff root) of
134
+ Just modify ->
135
+ modify
136
+
137
+ Nothing ->
138
+ replace
139
+
140
+
141
+ cheapDiffList : Json .Pointer -> ( List Json .Value , List Json .Value ) -> Invertible .Patch
142
+ cheapDiffList root ( a, b ) =
143
+ List . range 0 ( max ( List . length a) ( List . length b))
144
+ |> List . reverse
145
+ |> List . concatMap ( \ i -> diffField internalCheapDiff root ( String . fromInt i) ( get i a) ( get i b))
146
+
147
+
148
+ get : Int -> List a -> Maybe a
149
+ get i values =
150
+ if i > 0 then
151
+ values |> List . drop i |> List . head
152
+
153
+ else
154
+ Nothing
155
+
156
+
101
157
defaultPatchWeight : Invertible .Patch -> Int
102
158
defaultPatchWeight patch =
103
159
patch |> Invertible . toMinimalPatch |> JsonP . encoder |> jsonWeight
@@ -191,8 +247,8 @@ diffList weight root ( a, b ) =
191
247
|> List . map ( \ ( op, _ ) -> op)
192
248
193
249
194
- diffObject : (Invertible . Patch -> Int ) -> Json .Pointer -> ( Dict String Json .Value , Dict String Json .Value ) -> Maybe Invertible .Patch
195
- diffObject weight root ( a, b ) =
250
+ diffObject : (Json . Pointer -> Json . Value -> Json . Value -> Invertible . Patch ) -> Json .Pointer -> ( Dict String Json .Value , Dict String Json .Value ) -> Maybe Invertible .Patch
251
+ diffObject parentDiff root ( a, b ) =
196
252
let
197
253
aKeys =
198
254
a |> Dict . keys |> Set . fromList
@@ -212,12 +268,12 @@ diffObject weight root ( a, b ) =
212
268
else
213
269
Set . union aKeys bKeys
214
270
|> Set . toList
215
- |> List . concatMap ( \ k -> diffField weight root k ( Dict . get k a) ( Dict . get k b))
271
+ |> List . concatMap ( \ k -> diffField parentDiff root k ( Dict . get k a) ( Dict . get k b))
216
272
|> Just
217
273
218
274
219
- diffField : (Invertible . Patch -> Int ) -> Json .Pointer -> String -> Maybe Json .Value -> Maybe Json .Value -> Invertible .Patch
220
- diffField weight root key a b =
275
+ diffField : (Json . Pointer -> Json . Value -> Json . Value -> Invertible . Patch ) -> Json .Pointer -> String -> Maybe Json .Value -> Maybe Json .Value -> Invertible .Patch
276
+ diffField parentDiff root key a b =
221
277
let
222
278
pointer =
223
279
root ++ [ key ]
@@ -226,7 +282,7 @@ diffField weight root key a b =
226
282
Just ja ->
227
283
case b of
228
284
Just jb ->
229
- internalDiff weight pointer ja jb
285
+ parentDiff pointer ja jb
230
286
231
287
Nothing ->
232
288
[ Invertible . Remove pointer ja ]
0 commit comments