public static byte[] decodeHex(String str) throws IOException {
        if ((str.length() & 0x1) != 0)
            throw new IOException("Odd number of characters.");

        int len = str.length() >> 1;
        byte[] out = new byte[len];

        for (int i = 0; i < len; i++) {
            int j = i << 1;
            int f = (toDigit(str.charAt(j)) << 4) | toDigit(str.charAt(j + 1));

            out[i] = (byte) f;
        }

        return out;
    }
@Test
    public void testDecodeHex() throws IOException {
        assertArrayEquals(new byte[0], Hex.decodeHex(""));
        assertArrayEquals(new byte[1], Hex.decodeHex("00"));
        assertArrayEquals(new byte[4], Hex.decodeHex("00000000"));

        assertArrayEquals(
                new byte[]{0x10, (byte) 0xa3, (byte) 0xd1, (byte) 0xff},
                Hex.decodeHex("10a3D1Ff")
        );

        assertThrows(IOException.class, () -> Hex.decodeHex("1"));
        assertThrows(IOException.class, () -> Hex.decodeHex("1a1"));
        assertThrows(IOException.class, () -> Hex.decodeHex("1g"));
    }