class Base58Utils {

  public static String encode(final byte[] input) {
    if (null == input || input.length == 0) {
      return "";
    }

    final char[] encoded = new char[input.length * 2];
    final byte[] copy = Arrays.copyOf(input, input.length); // since we modify it in-place

    // Count leading zeros.
    int zeros = 0;
    while (zeros < input.length && input[zeros] == 0) {
      ++zeros;
    }

    int inputIndex = zeros;
    int outputIndex = encoded.length;
    while (inputIndex < copy.length) {
      encoded[--outputIndex] = BASE58_CHARS[divmod(copy, inputIndex, 256, 58)];
      if (copy[inputIndex] == 0) {
        ++inputIndex; // optimization - skip leading zeros
      }
    }
    // Preserve exactly as many leading encoded zeros in output as there were leading zeros in
    // input.
    while (outputIndex < encoded.length && encoded[outputIndex] == ENCODED_ZERO) {
      ++outputIndex;
    }
    while (--zeros >= 0) {
      encoded[--outputIndex] = ENCODED_ZERO;
    }
    // Return encoded string (including encoded leading zeros).
    return new String(encoded, outputIndex, encoded.length - outputIndex);
  }

}