public function format(array $rows, array $headers = []) : string
    {
        if (count($rows) === 0) {
            return '';
        }

        foreach ($rows as &$row) {
            $row = (array)$row;
        }

        unset($row);

        // If there are headers, we want them to be formatted along with the rows
        $headersAndRows = count($headers) === 0 ? $rows : array_merge([$headers], $rows);
        $headersAndRows = count($headers) === 0 ? $rows : array_merge([$headers], $rows);
        $maxLengths = $this->padding->normalizeColumns($headersAndRows);
        $eolChar = $this->padding->getEolChar();
        $rowText = explode($eolChar, $this->padding->format($headersAndRows, function ($row) {
            return sprintf(
                '%s%s%s%s%s',
                $this->verticalBorderChar,
                $this->cellPaddingString,
                implode($this->cellPaddingString . $this->verticalBorderChar . $this->cellPaddingString, $row),
                $this->cellPaddingString,
                $this->verticalBorderChar
            );
        }));

        // Create the borders
        $borders = [];

        foreach ($maxLengths as $maxLength) {
            $borders[] = str_repeat($this->horizontalBorderChar, $maxLength + 2 * mb_strlen($this->cellPaddingString));
        }

        $borderText = $this->intersectionChar . implode($this->intersectionChar, $borders) . $this->intersectionChar;
        $headerText = count($headers) > 0 ? array_shift($rowText) . $eolChar . $borderText . $eolChar : '';

        return $borderText . $eolChar . $headerText . implode($eolChar, $rowText) . $eolChar . $borderText;
    }