Add `__getitem__` slicing

Add support for slicing (including incomplete indexing) through a `DistArray`'s `__getitem__`.  Currently only `BlockMap`s and `NoDistMap`s are supported, and only slices with step-sizes of 1 are supported.

Slices return `DistArray` views as one would expect.

This required a small bit of refactoring
1. I added a couple small attributes to `NoDistMap`s from `BlockMap`s for convenience
2. I consolidated two separated implementations of `sanitize_indices` and expanded its functionality and usage.

Slicing currently throws errors when a resulting slice would have a dimension of size 0, but maybe Kurt's upcoming changes will resolve this.
We might be able to figure it out on the local side, but it was easier to figure it out client-side (and easy to do it all in one roundtrip).

Figuring out the new distribution locally would only work for `dist_type`s that have full global information locally though, because to figure out the new global shape the distribution has to know how the slice changes the shape on other processes.