from typing import Mapping
from typing import Optional
from typing import Dict


def offsets_to_slices(
    offsets: Mapping[str, int],
    sizes: Mapping[str, int],
    base: Optional[Mapping[str, int]] = None,
) -> Dict[str, slice]:
  """Convert offsets into slices with an optional base offset.

  Args:
    offsets: integer offsets from the origin along each axis.
    sizes: dimension sizes for the corresponding chunks.
    base: optional base-offset to subract from this key. This allows for
      relative indexing, e.g., into a chunk of a larger Dataset.

  Returns:
    Slices suitable for indexing with xarray.Dataset.isel().

  Raises:
    ValueError: if an offset is specified for a dimension where there is no
      corresponding size specified.

  Example usage::

    >>> offsets_to_slices({'x': 100}, sizes={'x': 10})
    {'x': slice(100, 110, 1)}
    >>> offsets_to_slices({'x': 100}, sizes={'x': 10}, base={'x': 100})
    {'x': slice(0, 10, 1)}
  """
  if base is None:
    base = {}
  slices = {}
  for k in offsets.keys():
    if k not in sizes:
      raise ValueError(f"An offset was specified for dimension {k}, but we don't "
                       "have a chunk size for this dimension.")
  for k, size in sizes.items():
    offset = offsets.get(k, 0) - base.get(k, 0)
    slices[k] = slice(offset, offset + size, 1)
  return slices