@@ -4,7 +4,7 @@ module Json.Diff exposing (diff, invertibleDiff, diffWithCustomWeight)
44
55This has been implemented rather simply, and is probably not very optimised, but it should work for a lot of use cases.
66
7- @docs diff, invertibleDiff, diffWithCustomWeight
7+ @docs diff, invertibleDiff, diffWithCustomWeight, cheapDiff
88
99-}
1010
@@ -62,6 +62,18 @@ diffWithCustomWeight weight =
6262 internalDiff weight []
6363
6464
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+
6577
6678{- Private -}
6779
@@ -86,7 +98,7 @@ internalDiff weight root a b =
8698 d
8799
88100 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
90102 Just modify ->
91103 if weight modify > weight replace then
92104 replace
@@ -98,6 +110,50 @@ internalDiff weight root a b =
98110 replace
99111
100112
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+
101157defaultPatchWeight : Invertible .Patch -> Int
102158defaultPatchWeight patch =
103159 patch |> Invertible . toMinimalPatch |> JsonP . encoder |> jsonWeight
@@ -191,8 +247,8 @@ diffList weight root ( a, b ) =
191247 |> List . map ( \ ( op, _ ) -> op)
192248
193249
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 ) =
196252 let
197253 aKeys =
198254 a |> Dict . keys |> Set . fromList
@@ -212,12 +268,12 @@ diffObject weight root ( a, b ) =
212268 else
213269 Set . union aKeys bKeys
214270 |> 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))
216272 |> Just
217273
218274
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 =
221277 let
222278 pointer =
223279 root ++ [ key ]
@@ -226,7 +282,7 @@ diffField weight root key a b =
226282 Just ja ->
227283 case b of
228284 Just jb ->
229- internalDiff weight pointer ja jb
285+ parentDiff pointer ja jb
230286
231287 Nothing ->
232288 [ Invertible . Remove pointer ja ]
0 commit comments