makeDecodeFromSmallcaps = (decodeOptions = {}) => {
  const {
    decodeRemotableFromSmallcaps = dontDecodeRemotableFromSmallcaps,
    decodePromiseFromSmallcaps = dontDecodePromiseFromSmallcaps,
    decodeErrorFromSmallcaps = dontDecodeErrorFromSmallcaps,
  } = decodeOptions;

  /**
   * `decodeFromSmallcaps` may rely on `encoding` being the result of a
   * plain call to JSON.parse. However, it *cannot* rely on `encoding`
   * having been produced by JSON.stringify on the output of `encodeToSmallcaps`
   * above, i.e., `decodeFromSmallcaps` cannot rely on `encoding` being a
   * valid marshalled representation. Rather, `decodeFromSmallcaps` must
   * validate that.
   *
   * @param {SmallcapsEncoding} encoding must be hardened
   */
  const decodeFromSmallcaps = encoding => {
    switch (typeof encoding) {
      case 'boolean':
      case 'number': {
        return encoding;
      }
      case 'string': {
        if (!startsSpecial(encoding)) {
          return encoding;
        }
        const c = encoding.charAt(0);
        switch (c) {
          case '!': {
            // un-hilbert-ify the string
            return encoding.slice(1);
          }
          case '%': {
            return passableSymbolForName(encoding.slice(1));
          }
          case '#': {
            switch (encoding) {
              case '#undefined': {
                return undefined;
              }
              case '#NaN': {
                return NaN;
              }
              case '#Infinity': {
                return Infinity;
              }
              case '#-Infinity': {
                return -Infinity;
              }
              default: {
                throw assert.fail(
                  X`unknown constant "${q(encoding)}"`,
                  TypeError,
                );
              }
            }
          }
          case '+':
          case '-': {
            return BigInt(encoding);
          }
          case '$': {
            const result = decodeRemotableFromSmallcaps(
              encoding,
              decodeFromSmallcaps,
            );
            // @ts-ignore XXX SmallCapsEncoding
            if (passStyleOf(result) !== 'remotable') {
              Fail`internal: decodeRemotableFromSmallcaps option must return a remotable: ${result}`;
            }
            return result;
          }
          case '&': {
            const result = decodePromiseFromSmallcaps(
              encoding,
              decodeFromSmallcaps,
            );
            if (passStyleOf(result) !== 'promise') {
              Fail`internal: decodePromiseFromSmallcaps option must return a promise: ${result}`;
            }
            return result;
          }
          default: {
            throw Fail`Special char ${q(
              c,
            )} reserved for future use: ${encoding}`;
          }
        }
      }
      case 'object': {
        if (encoding === null) {
          return encoding;
        }

        if (isArray(encoding)) {
          return encoding.map(val => decodeFromSmallcaps(val));
        }

        if (hasOwnPropertyOf(encoding, '#tag')) {
          const { '#tag': tag, payload, ...rest } = encoding;
          typeof tag === 'string' ||
            Fail`Value of "#tag", the tag, must be a string: ${encoding}`;
          ownKeys(rest).length === 0 ||
            Fail`#tag record unexpected properties: ${q(ownKeys(rest))}`;
          return makeTagged(
            decodeFromSmallcaps(tag),
            decodeFromSmallcaps(payload),
          );
        }

        if (hasOwnPropertyOf(encoding, '#error')) {
          const result = decodeErrorFromSmallcaps(
            encoding,
            decodeFromSmallcaps,
          );
          passStyleOf(result) === 'error' ||
            Fail`internal: decodeErrorFromSmallcaps option must return an error: ${result}`;
          return result;
        }

        const decodeEntry = ([encodedName, encodedVal]) => {
          typeof encodedName === 'string' ||
            Fail`Property name ${q(
              encodedName,
            )} of ${encoding} must be a string`;
          encodedName.charAt(0) !== '#' ||
            Fail`Unrecognized record type ${q(encodedName)}: ${encoding}`;
          const name = decodeFromSmallcaps(encodedName);
          typeof name === 'string' ||
            Fail`Decoded property name ${name} from ${encoding} must be a string`;
          return [name, decodeFromSmallcaps(encodedVal)];
        };
        const decodedEntries = entries(encoding).map(decodeEntry);
        return fromEntries(decodedEntries);
      }
      default: {
        throw assert.fail(
          X`internal: unrecognized JSON typeof ${q(
            typeof encoding,
          )}: ${encoding}`,
          TypeError,
        );
      }
    }
  };
  return harden(decodeFromSmallcaps);
}
@param {DecodeFromSmallcapsOptions} [decodeOptions]
@returns {(encoded: SmallcapsEncoding) => Passable}