def bx_decode(string, alphabet, mapping=None):
   """\
   Transforms a string in :attr:`alphabet` to an integer.
   
   If :attr:`mapping` is provided, each key must map to its 
   positional value without duplicates.

   ::

      mapping = {'a': 0, 'b': 1, 'c': 2}

      # 3
      bx_decode('ba', 'abc', mapping)
   
   :param string:       a string consisting of key from `alphabet`.
   :param alphabet:     a 0-based iterable.
   
   :param mapping:      a :class:`Mapping <collection.Mapping>`. If `None`, 
                        the inverse of `alphabet` is used, with values mapped
                        to indices.
   """
  
   mapping = mapping or dict([(d, i) for (i, d) in enumerate(alphabet)])
   base = len(alphabet)

   if not string:
      raise ValueError('string cannot be empty')

   if not isinstance(mapping, Mapping):
      raise TypeError('a Mapping is required')

   sum = 0

   for digit in string:
      try:
         sum = base*sum + mapping[digit]
      except KeyError:
         raise ValueError(
            "invalid literal for bx_decode with base %i: '%s'" % (base, digit))

   return sum