class TypedRowAccounting implements RowAccounting<Row> {

    private final RamAccounting ramAccounting;
    private final CellsSizeEstimator estimateRowSize;
    private int extraSizePerRow = 0;

    /**
     * See {@link TypedRowAccounting#TypedRowAccounting(List, RamAccounting, int)}
     */
    public TypedRowAccounting(List<? extends DataType<?>> columnTypes, RamAccounting ramAccounting) {
        this.estimateRowSize = CellsSizeEstimator.forColumns(columnTypes);
        this.ramAccounting = ramAccounting;
    }

    /**
     * Create a new instance over a set of column types
     *
     * @param columnTypes     The column types to use for size estimation
     * @param ramAccounting   {@link RamAccounting} implementing the CircuitBreaker logic
     * @param extraSizePerRow Extra size that need to be calculated per row. E.g. {@link HashInnerJoinBatchIterator}
     *                        might instantiate an ArrayList per row used for the internal hash->row buffer
     */
    public TypedRowAccounting(List<? extends DataType<?>> columnTypes,
                              RamAccounting ramAccounting,
                              int extraSizePerRow) {
        this(columnTypes, ramAccounting);
        this.extraSizePerRow = extraSizePerRow;
    }

    /**
     * Account for the size of the values of the row.
     *
     * This should only be used if the values are stored/buffered in another in-memory data structure.
     */
    @Override
    public long accountForAndMaybeBreak(Row row) {<FILL_FUNCTION_BODY>}

    @Override
    public void release() {
        ramAccounting.release();
    }
}

        // Container size of the row is excluded because here it's unknown where the values will be saved to.
        // As size estimation is generally "best-effort" this should be good enough.
        long bytes = estimateRowSize.estimateSize(row) + extraSizePerRow;
        ramAccounting.addBytes(bytes);
        return bytes;
    
<no_super_class>