Implement deep collection equality (#1853)

Add a `deepCollectionEquals` utility to find the Rejection for any
collection type. Add extensions for `Iterable` and `Map` to use the new
utility.

Iterable checking is implemented with a Queue that tracks the path
within a deeply nested iterable and the elements that need to be
compared.

Set and Map checking are implemented by comparing the all combinations
of values or entries and checking that all elements or entries can be
paired between the expected and actual collections. This allows for
cases where a Condition matches more than one key or element, and the
specific pairing needs to be aligned correctly to allow matching all
elements. This flexibility for matching Map keys does cause less
specific failure for mismatches within the Map value.

Add `deepEqual` conditions for Iterable and map. The Iterable condition
covers List and Set.

Add a `isARejection` extension for `Check<Rejection?>` and test against
`deepCollectionEquals` directly, instead of testing through the
`deepEquals` signature.
Drop the `toStringEquals` extension in favor of using `deepEquals`.
6 files changed