public OptionalInt bytesNeeded(Collection<T> records, ObjectSerializationCache serializationCache) {
        int bytesNeeded = bytesNeededForRecords(
            records,
            serializationCache
        );

        if (!isOpenForAppends) {
            return OptionalInt.of(Math.addExact(batchHeaderSizeInBytes(), bytesNeeded));
        }

        int approxUnusedSizeInBytes = maxBytes - approximateSizeInBytes();
        if (approxUnusedSizeInBytes >= bytesNeeded) {
            return OptionalInt.empty();
        } else if (unflushedBytes > 0) {
            recordOutput.flush();
            unflushedBytes = 0;
            int unusedSizeInBytes = maxBytes - flushedSizeInBytes();
            if (unusedSizeInBytes >= bytesNeeded) {
                return OptionalInt.empty();
            }
        }

        return OptionalInt.of(Math.addExact(batchHeaderSizeInBytes(), bytesNeeded));
    }
Check whether the batch has enough room for all the record values.

Returns an empty {@link OptionalInt} if the batch builder has room for this list of records.
Otherwise, it returns the expected number of bytes needed for a batch to contain these records.

@param records the records to use when checking for room
@param serializationCache serialization cache for computing sizes
@return empty {@link OptionalInt} if there is room for the records to be appended, otherwise
        returns the number of bytes needed
raft/src/main/java/org/apache/kafka/raft/internals/BatchBuilder.java