Skip to content

Commit

Permalink
add comparison when both IEnumerable (or IDictionary) are null
Browse files Browse the repository at this point in the history
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.
  • Loading branch information
amine-mej-dedge committed Dec 21, 2022
1 parent 4809555 commit 0ac1982
Showing 1 changed file with 45 additions and 33 deletions.
78 changes: 45 additions & 33 deletions src/Diffract/Differ.fs
Original file line number Diff line number Diff line change
Expand Up @@ -154,20 +154,28 @@ module DifferImpl =
let diffItem = diffWith<'Elt> custom cache
{ new IDiffer<'Enum> with
member _.Diff(s1, s2) =
let s1 = Seq.cache s1
let s2 = Seq.cache s2
let l1 = Seq.length s1
let l2 = Seq.length s2
match
(s1, s2)
||> Seq.mapi2 (fun i e1 e2 ->
diffItem.Diff(e1, e2)
|> Option.map (fun diff -> { Name = string i; Diff = diff }))
|> Seq.choose id
|> List.ofSeq
with
| [] when l1 = l2 -> None
| diffs -> Some (Diff.Collection (l1, l2, diffs)) }
let tryCache s =
match box s with
| null -> Error Seq.empty
| _ -> Ok (Seq.cache s)

match tryCache s1, tryCache s2 with
| Ok s1, Ok s2
| Error s1, Ok s2
| Ok s1, Error s2 ->
let l1 = Seq.length s1
let l2 = Seq.length s2
match
(s1, s2)
||> Seq.mapi2 (fun i e1 e2 ->
diffItem.Diff(e1, e2)
|> Option.map (fun diff -> { Name = string i; Diff = diff }))
|> Seq.choose id
|> List.ofSeq
with
| [] when l1 = l2 -> None
| diffs -> Some (Diff.Collection (l1, l2, diffs))
| Error _, Error _ -> None }
|> unbox<IDiffer<'T>> }
|> e.Accept

Expand All @@ -178,25 +186,29 @@ module DifferImpl =
let diffItem = diffWith<'V> custom cache
{ new IDiffer<'Dict> with
member _.Diff(d1, d2) =
let seen = HashSet<'K>()
let struct (keysInX1, common) =
(struct ([], []), d1)
||> Seq.fold (fun (struct (keysInX1, common) as state) (KeyValue (k, v1)) ->
seen.Add(k) |> ignore
match d2.TryGetValue(k) with
| true, v2 ->
match diffItem.Diff(v1, v2) with
| Some d -> struct (keysInX1, { Name = string k; Diff = d } :: common)
| None -> state
| false, _ -> struct (string k :: keysInX1, common))
let keysInX2 =
d2
|> Seq.choose (fun (KeyValue (k, _)) ->
if seen.Contains(k) then None else Some (string k))
|> List.ofSeq
match keysInX1, keysInX2, common with
| [], [], [] -> None
| _ -> Some (Diff.Dictionary (keysInX1, keysInX2, common)) }
match box d1, box d2 with
| null, null ->
None
| _ ->
let seen = HashSet<'K>()
let struct (keysInX1, common) =
(struct ([], []), d1)
||> Seq.fold (fun (struct (keysInX1, common) as state) (KeyValue (k, v1)) ->
seen.Add(k) |> ignore
match d2.TryGetValue(k) with
| true, v2 ->
match diffItem.Diff(v1, v2) with
| Some d -> struct (keysInX1, { Name = string k; Diff = d } :: common)
| None -> state
| false, _ -> struct (string k :: keysInX1, common))
let keysInX2 =
d2
|> Seq.choose (fun (KeyValue (k, _)) ->
if seen.Contains(k) then None else Some (string k))
|> List.ofSeq
match keysInX1, keysInX2, common with
| [], [], [] -> None
| _ -> Some (Diff.Dictionary (keysInX1, keysInX2, common)) }
|> unbox<IDiffer<'T>> }
|> d.Accept

Expand Down

0 comments on commit 0ac1982

Please sign in to comment.