Skip to content

Commit 0ac1982

Browse files
add comparison when both IEnumerable (or IDictionary) are null
The case when one IEnumerable is null and the other isn't is handled poorly. The case when one IDictionary is null and the other isn't is not handled.
1 parent 4809555 commit 0ac1982

File tree

1 file changed

+45
-33
lines changed

1 file changed

+45
-33
lines changed

src/Diffract/Differ.fs

+45-33
Original file line numberDiff line numberDiff line change
@@ -154,20 +154,28 @@ module DifferImpl =
154154
let diffItem = diffWith<'Elt> custom cache
155155
{ new IDiffer<'Enum> with
156156
member _.Diff(s1, s2) =
157-
let s1 = Seq.cache s1
158-
let s2 = Seq.cache s2
159-
let l1 = Seq.length s1
160-
let l2 = Seq.length s2
161-
match
162-
(s1, s2)
163-
||> Seq.mapi2 (fun i e1 e2 ->
164-
diffItem.Diff(e1, e2)
165-
|> Option.map (fun diff -> { Name = string i; Diff = diff }))
166-
|> Seq.choose id
167-
|> List.ofSeq
168-
with
169-
| [] when l1 = l2 -> None
170-
| diffs -> Some (Diff.Collection (l1, l2, diffs)) }
157+
let tryCache s =
158+
match box s with
159+
| null -> Error Seq.empty
160+
| _ -> Ok (Seq.cache s)
161+
162+
match tryCache s1, tryCache s2 with
163+
| Ok s1, Ok s2
164+
| Error s1, Ok s2
165+
| Ok s1, Error s2 ->
166+
let l1 = Seq.length s1
167+
let l2 = Seq.length s2
168+
match
169+
(s1, s2)
170+
||> Seq.mapi2 (fun i e1 e2 ->
171+
diffItem.Diff(e1, e2)
172+
|> Option.map (fun diff -> { Name = string i; Diff = diff }))
173+
|> Seq.choose id
174+
|> List.ofSeq
175+
with
176+
| [] when l1 = l2 -> None
177+
| diffs -> Some (Diff.Collection (l1, l2, diffs))
178+
| Error _, Error _ -> None }
171179
|> unbox<IDiffer<'T>> }
172180
|> e.Accept
173181

@@ -178,25 +186,29 @@ module DifferImpl =
178186
let diffItem = diffWith<'V> custom cache
179187
{ new IDiffer<'Dict> with
180188
member _.Diff(d1, d2) =
181-
let seen = HashSet<'K>()
182-
let struct (keysInX1, common) =
183-
(struct ([], []), d1)
184-
||> Seq.fold (fun (struct (keysInX1, common) as state) (KeyValue (k, v1)) ->
185-
seen.Add(k) |> ignore
186-
match d2.TryGetValue(k) with
187-
| true, v2 ->
188-
match diffItem.Diff(v1, v2) with
189-
| Some d -> struct (keysInX1, { Name = string k; Diff = d } :: common)
190-
| None -> state
191-
| false, _ -> struct (string k :: keysInX1, common))
192-
let keysInX2 =
193-
d2
194-
|> Seq.choose (fun (KeyValue (k, _)) ->
195-
if seen.Contains(k) then None else Some (string k))
196-
|> List.ofSeq
197-
match keysInX1, keysInX2, common with
198-
| [], [], [] -> None
199-
| _ -> Some (Diff.Dictionary (keysInX1, keysInX2, common)) }
189+
match box d1, box d2 with
190+
| null, null ->
191+
None
192+
| _ ->
193+
let seen = HashSet<'K>()
194+
let struct (keysInX1, common) =
195+
(struct ([], []), d1)
196+
||> Seq.fold (fun (struct (keysInX1, common) as state) (KeyValue (k, v1)) ->
197+
seen.Add(k) |> ignore
198+
match d2.TryGetValue(k) with
199+
| true, v2 ->
200+
match diffItem.Diff(v1, v2) with
201+
| Some d -> struct (keysInX1, { Name = string k; Diff = d } :: common)
202+
| None -> state
203+
| false, _ -> struct (string k :: keysInX1, common))
204+
let keysInX2 =
205+
d2
206+
|> Seq.choose (fun (KeyValue (k, _)) ->
207+
if seen.Contains(k) then None else Some (string k))
208+
|> List.ofSeq
209+
match keysInX1, keysInX2, common with
210+
| [], [], [] -> None
211+
| _ -> Some (Diff.Dictionary (keysInX1, keysInX2, common)) }
200212
|> unbox<IDiffer<'T>> }
201213
|> d.Accept
202214

0 commit comments

Comments
 (0)