// Path: src/main/java/io/github/novacrypto/base58/BadCharacterException.java
// public final class BadCharacterException extends RuntimeException {
// 
//     public BadCharacterException(final char charAtI) {
//         super("Bad character in base58 string, '" + charAtI + "'");
//     }
// }
// 
// Path: src/main/java/io/github/novacrypto/base58/Base58.java
// public final class Base58 {
// 
//     Base58() {
//     }
// 
//     public static GeneralEncoderDecoder newInstanceWithBuffer(final WorkingBuffer workingBuffer) {
//         return new Base58EncoderDecoder(workingBuffer);
//     }
// 
//     public static EncoderDecoder newInstance() {
//         return newInstanceWithBuffer(new ByteArrayWorkingBuffer());
//     }
// 
//     public static SecureEncoderDecoder newSecureInstance() {
//         return newInstanceWithBuffer(new SecureWorkingBuffer());
//     }
// 
//     private static final ThreadLocal<EncoderDecoder> working = new ThreadLocal<>();
// 
//     /**
//      * Encodes given bytes as a number in base58.
//      * Threadsafe, uses an instance per thread.
//      *
//      * @param bytes bytes to encode
//      * @return base58 string representation
//      */
//     public static String base58Encode(final byte[] bytes) {
//         return getThreadSharedBase58().encode(bytes);
//     }
// 
//     /**
//      * Decodes given bytes as a number in base58.
//      * Threadsafe, uses an instance per thread.
//      *
//      * @param base58 string to decode
//      * @return number as bytes
//      */
//     public static byte[] base58Decode(final CharSequence base58) {
//         return getThreadSharedBase58().decode(base58);
//     }
// 
//     private static EncoderDecoder getThreadSharedBase58() {
//         EncoderDecoder base58 = working.get();
//         if (base58 == null) {
//             base58 = newInstance();
//             working.set(base58);
//         }
//         return base58;
//     }
// }
// 
// Path: src/main/java/io/github/novacrypto/base58/ByteArrayWorkingBuffer.java
// public final class ByteArrayWorkingBuffer implements WorkingBuffer {
// 
//     private static final byte[] EMPTY = new byte[0];
// 
//     private byte[] bytes = EMPTY;
// 
//     @Override
//     public void setCapacity(final int atLeast) {
//         bytes = ensureCapacity(bytes, atLeast);
//         clear(bytes);
//     }
// 
//     @Override
//     public byte get(final int index) {
//         return bytes[index];
//     }
// 
//     @Override
//     public void put(final int index, final byte value) {
//         bytes[index] = value;
//     }
// 
//     @Override
//     public void clear() {
//         clear(bytes);
//     }
// 
//     private static byte[] ensureCapacity(final byte[] bytes, final int atLeast) {
//         if (bytes.length >= atLeast) {
//             return bytes;
//         }
//         clear(bytes);
//         return new byte[atLeast];
//     }
// 
//     private static void clear(final byte[] bytes) {
//         Arrays.fill(bytes, (byte) 255);
//     }
// }
// 
// Path: src/main/java/io/github/novacrypto/base58/GeneralEncoderDecoder.java
// public interface GeneralEncoderDecoder extends EncoderDecoder, SecureEncoderDecoder {
// }
// 
// Path: src/main/java/io/github/novacrypto/base58/WorkingBuffer.java
// public interface WorkingBuffer {
//     void setCapacity(int atLeast);
// 
//     byte get(int index);
// 
//     void put(int index, byte value);
// 
//     void clear();
// }


import io.github.novacrypto.base58.BadCharacterException;
import io.github.novacrypto.base58.Base58;
import io.github.novacrypto.base58.ByteArrayWorkingBuffer;
import io.github.novacrypto.base58.GeneralEncoderDecoder;
import io.github.novacrypto.base58.WorkingBuffer;
import org.junit.Test;
import static org.assertj.core.api.Assertions.assertThatThrownBy;
import static org.junit.Assert.assertEquals;
        final SpyWorkingBuffer spy = givenSpyBuffer();
        final GeneralEncoderDecoder encoder = Base58.newInstanceWithBuffer(throwingPut(spy));
        assertThatThrownBy(() -> encoder.encode(new byte[]{(byte) 1}))
                .hasMessage("Can't put");
        spy.assertClearedLast();
    }

    @Test
    public void clearsBufferOnGetExceptionDuringDecode() {
        final SpyWorkingBuffer spy = givenSpyBuffer();
        final GeneralEncoderDecoder encoder = Base58.newInstanceWithBuffer(throwingGet(spy));
        assertThatThrownBy(() -> encoder.decode("a"))
                .hasMessage("Can't get");
        spy.assertClearedLast();
    }

    @Test
    public void clearsBufferOnPutExceptionDuringDecode() {
        final SpyWorkingBuffer spy = givenSpyBuffer();
        final GeneralEncoderDecoder encoder = Base58.newInstanceWithBuffer(throwingPut(spy));
        assertThatThrownBy(() -> encoder.decode("a"))
                .hasMessage("Can't put");
        spy.assertClearedLast();
    }

    @Test
    public void clearsBufferOnBadCharExceptionDuringDecode() {
        final SpyWorkingBuffer spy = givenSpyBuffer();
        final GeneralEncoderDecoder encoder = Base58.newInstanceWithBuffer(throwingGet(spy));
        assertThatThrownBy(() -> encoder.decode("0"))
// Path: src/main/java/io/github/novacrypto/base58/BadCharacterException.java
// public final class BadCharacterException extends RuntimeException {
// 
//     public BadCharacterException(final char charAtI) {
//         super("Bad character in base58 string, '" + charAtI + "'");
//     }
// }
// 
// Path: src/main/java/io/github/novacrypto/base58/Base58.java
// public final class Base58 {
// 
//     Base58() {
//     }
// 
//     public static GeneralEncoderDecoder newInstanceWithBuffer(final WorkingBuffer workingBuffer) {
//         return new Base58EncoderDecoder(workingBuffer);
//     }
// 
//     public static EncoderDecoder newInstance() {
//         return newInstanceWithBuffer(new ByteArrayWorkingBuffer());
//     }
// 
//     public static SecureEncoderDecoder newSecureInstance() {
//         return newInstanceWithBuffer(new SecureWorkingBuffer());
//     }
// 
//     private static final ThreadLocal<EncoderDecoder> working = new ThreadLocal<>();
// 
//     /**
//      * Encodes given bytes as a number in base58.
//      * Threadsafe, uses an instance per thread.
//      *
//      * @param bytes bytes to encode
//      * @return base58 string representation
//      */
//     public static String base58Encode(final byte[] bytes) {
//         return getThreadSharedBase58().encode(bytes);
//     }
// 
//     /**
//      * Decodes given bytes as a number in base58.
//      * Threadsafe, uses an instance per thread.
//      *
//      * @param base58 string to decode
//      * @return number as bytes
//      */
//     public static byte[] base58Decode(final CharSequence base58) {
//         return getThreadSharedBase58().decode(base58);
//     }
// 
//     private static EncoderDecoder getThreadSharedBase58() {
//         EncoderDecoder base58 = working.get();
//         if (base58 == null) {
//             base58 = newInstance();
//             working.set(base58);
//         }
//         return base58;
//     }
// }
// 
// Path: src/main/java/io/github/novacrypto/base58/ByteArrayWorkingBuffer.java
// public final class ByteArrayWorkingBuffer implements WorkingBuffer {
// 
//     private static final byte[] EMPTY = new byte[0];
// 
//     private byte[] bytes = EMPTY;
// 
//     @Override
//     public void setCapacity(final int atLeast) {
//         bytes = ensureCapacity(bytes, atLeast);
//         clear(bytes);
//     }
// 
//     @Override
//     public byte get(final int index) {
//         return bytes[index];
//     }
// 
//     @Override
//     public void put(final int index, final byte value) {
//         bytes[index] = value;
//     }
// 
//     @Override
//     public void clear() {
//         clear(bytes);
//     }
// 
//     private static byte[] ensureCapacity(final byte[] bytes, final int atLeast) {
//         if (bytes.length >= atLeast) {
//             return bytes;
//         }
//         clear(bytes);
//         return new byte[atLeast];
//     }
// 
//     private static void clear(final byte[] bytes) {
//         Arrays.fill(bytes, (byte) 255);
//     }
// }
// 
// Path: src/main/java/io/github/novacrypto/base58/GeneralEncoderDecoder.java
// public interface GeneralEncoderDecoder extends EncoderDecoder, SecureEncoderDecoder {
// }
// 
// Path: src/main/java/io/github/novacrypto/base58/WorkingBuffer.java
// public interface WorkingBuffer {
//     void setCapacity(int atLeast);
// 
//     byte get(int index);
// 
//     void put(int index, byte value);
// 
//     void clear();
// }


// Path: src/test/java/io/github/novacrypto/BufferClearTests.java
import io.github.novacrypto.base58.BadCharacterException;
import io.github.novacrypto.base58.Base58;
import io.github.novacrypto.base58.ByteArrayWorkingBuffer;
import io.github.novacrypto.base58.GeneralEncoderDecoder;
import io.github.novacrypto.base58.WorkingBuffer;
import org.junit.Test;
import static org.assertj.core.api.Assertions.assertThatThrownBy;
import static org.junit.Assert.assertEquals;

        final SpyWorkingBuffer spy = givenSpyBuffer();
        final GeneralEncoderDecoder encoder = Base58.newInstanceWithBuffer(throwingPut(spy));
        assertThatThrownBy(() -> encoder.encode(new byte[]{(byte) 1}))
                .hasMessage("Can't put");
        spy.assertClearedLast();
    }

    @Test
    public void clearsBufferOnGetExceptionDuringDecode() {
        final SpyWorkingBuffer spy = givenSpyBuffer();
        final GeneralEncoderDecoder encoder = Base58.newInstanceWithBuffer(throwingGet(spy));
        assertThatThrownBy(() -> encoder.decode("a"))
                .hasMessage("Can't get");
        spy.assertClearedLast();
    }

    @Test
    public void clearsBufferOnPutExceptionDuringDecode() {
        final SpyWorkingBuffer spy = givenSpyBuffer();
        final GeneralEncoderDecoder encoder = Base58.newInstanceWithBuffer(throwingPut(spy));
        assertThatThrownBy(() -> encoder.decode("a"))
                .hasMessage("Can't put");
        spy.assertClearedLast();
    }

    @Test
    public void clearsBufferOnBadCharExceptionDuringDecode() {
        final SpyWorkingBuffer spy = givenSpyBuffer();
        final GeneralEncoderDecoder encoder = Base58.newInstanceWithBuffer(throwingGet(spy));
        assertThatThrownBy(() -> encoder.decode("0"))
                .isInstanceOf(BadCharacterException.class);