ReasonRateLimiting: Refactor: Extract `queueSlotMap`

Makes `reasonRateLimit` easier to read.

Signed-off-by: Niklas Hambuechen <niklash@google.com>
Generalize SlotMap

This turns the existing `SlotMap` from the structure

  Map (label :: String, limit :: Int) (occupied :: Int)

into

  Map (label :: a) (occupied :: Int, limit :: Int)

and extracts it into its own module; this makes it possible to use
`SlotMap`s for cases outside of reason rate limiting.

There is also a semantic clean-up (not affecting how reason rate limiting
works): `joinSlotMap` (now `occupySlots`) no longer takes a `SlotMap`
as second argument, removing the need to decide how the limits of the
second `SlotMap` affect the return value.

Before `c = joinSlotMap a b`  allowed to have keys in `b` that don't appear
in `a`, and those would appear in `c` with the limits from `b` (so `a` does
not constrain them).
In the new `occupySlots`, such keys have a limit of 0 instead.

Signed-off-by: Niklas Hambuechen <niklash@google.com>