static Pair<Integer, Integer> calculateBytesPerRowAndIndexWidth(int numberOfBytes, int desiredStringWidth) {
        if (DebugHex) {
            LOGGER.debug("Calculating max row and index for {} number of bytes and a desired string width of {}", numberOfBytes, desiredStringWidth);
        }
        int indexDigits = (int) (Math.log10(numberOfBytes) + 1);
        int requiredIndexWidth = indexDigits + pipeWidth;
        if (DebugHex) {
            LOGGER.debug("index width {} for indexDigits {} for bytes {}", requiredIndexWidth, indexDigits, numberOfBytes);
        }
        // strings get quoted by 2 chars
        int quoteRune = 1;
        int potentialStringRenderRune = 1;
        // 0 00  '.'
        int availableSpace = requiredIndexWidth + byteWidth + quoteRune + potentialStringRenderRune + quoteRune;
        if (DebugHex) {
            LOGGER.debug("calculated {} minimal width for number of bytes {}", availableSpace, numberOfBytes);
        }
        if (desiredStringWidth >= availableSpace) {
            availableSpace = desiredStringWidth;
        } else {
            if (DebugHex) {
                LOGGER.debug("Overflow by {} runes", desiredStringWidth - availableSpace);
            }
        }
        if (DebugHex) {
            LOGGER.debug("Actual space {}", availableSpace);
        }

        double z = availableSpace;
        double y = requiredIndexWidth;
        double a = byteWidth;
        double b = quoteRune;
        // c = needed space for bytes x * byteWidth
        // x = maxBytesPerRow
        // x = (z - (y + b + x * 1 + b)) / a == x = (-2 * b - y + z)/(a + 1) and a + 1!=0 and a!=0
        double x = ((-2 * b) - y + z) / (a + 1);
        if (DebugHex) {
            LOGGER.debug("Calculated number of bytes per row {} in int {}", x, (int) x);
        }
        return Pair.of((int) x, indexDigits);
    }
dumps a 56 char wide hex string

@param data bytes to dump
@return the hex string
plc4j/spi/src/main/java/org/apache/plc4x/java/spi/utils/hex/Hex.java