Hey, check this code:

/// A BAM reader.
pub struct BamReader<R> {
    reader: bam::Reader<bgzf::Reader<R>>,
    header: sam::Header,
    index: csi::Index,
}

impl BamReader<BufReader<File>> {
    /// Creates a BAM reader from a given file path.
    pub fn new_from_path(path: &str) -> std::io::Result<Self> {
        let index = index_from_path(path)?;
        let file = std::fs::File::open(path)?;
        let buf_file = std::io::BufReader::with_capacity(1024 * 1024, file);
        let mut reader = bam::Reader::new(buf_file);
        let header = reader.read_header()?;
        Ok(Self {
            reader,
            header,
            index,
        })
    }
}

impl<R: Read + Seek> BamReader<R> {
    /// Creates a BAM reader.
    pub fn new(read: R, index: csi::Index) -> std::io::Result<Self> {
        let mut reader = bam::Reader::new(read);
        let header = reader.read_header()?;
        Ok(Self {
            reader,
            header,
            index,
        })
    }

this bam::Reader::new() is coming from the noodles crate, here is its implementation:

impl<R> Reader<bgzf::Reader<R>>
where
    R: Read,
{
    /// Creates a BAM reader.
    ///
    /// The given reader must be a raw BGZF stream, as the underlying reader wraps it in a decoder.
    ///
    /// # Examples
    ///
    /// ```
    /// use noodles_bam as bam;
    /// let data = [];
    /// let reader = bam::io::Reader::new(&data[..]);
    /// ```
    pub fn new(reader: R) -> Self {
        Self::from(bgzf::Reader::new(reader))
    }
}

As far as I understand, here:

let buf_file = std::io::BufReader::with_capacity(1024 * 1024, file);
let mut reader = bam::Reader::new(buf_file);

they are allocating 1024*1024 bytes of memory to hold all the information inside the buffer and then reading from there. Now check this other part of the code:

impl<R: Read + Seek> BamReader<R> {
    /// Creates a BAM reader.
    pub fn new(read: R, index: csi::Index) -> std::io::Result<Self> {
        let mut reader = bam::Reader::new(read);
        let header = reader.read_header()?;
        Ok(Self {
            reader,
            header,
            index,
        })
    }

    /// Returns the records in the given region as Apache Arrow IPC.
    ///
    /// If the region is `None`, all records are returned.
    ///
    /// # Examples
    ///
    /// ```no_run
    /// use oxbow::bam::BamReader;
    ///
    /// let mut reader = BamReader::new_from_path("sample.bam").unwrap();
    /// let ipc = reader.records_to_ipc(Some("sq0:1-1000")).unwrap();
    /// ```
    pub fn records_to_ipc(&mut self, region: Option<&str>) -> Result<Vec<u8>, ArrowError> {
        let batch_builder = BamBatchBuilder::new(1024, &self.header)?;
        if let Some(region) = region {
            let region: Region = region.parse().unwrap();
            let query = self
                .reader
                .query(&self.header, &self.index, &region)
                .map_err(|e| ArrowError::ExternalError(e.into()))?
                .map(|i| i.map_err(|e| ArrowError::ExternalError(e.into())));

            return write_ipc_err(query, batch_builder);
        }
        let records = self
            .reader
            .records(&self.header)
            .map(|i| i.map_err(|e| ArrowError::ExternalError(e.into())));
        write_ipc_err(records, batch_builder)
    }

where they implement a reader method called "records_to_ipc". This method maps each record to an error (?):

let records = self
            .reader
            .records(&self.header)
            .map(|i| i.map_err(|e| ArrowError::ExternalError(e.into())));

and the passes it to another function called "write_ipc_err":

pub fn write_ipc_err<T>(
    records: impl Iterator<Item = Result<T, ArrowError>>,
    mut batch_builder: impl for<'a> BatchBuilder<Record<'a> = &'a T>,
) -> Result<Vec<u8>, ArrowError> {
    for record in records {
        let record = record?;
        batch_builder.push(&record)
    }
    finish_batch(batch_builder)
}

that loops over all the records. 

My questions are the following:

1) what should I modify if I want to achieve "read a file in chunks", is it possible? My idea here is: read a bam file in chunks of 10000 and then end with a vector of these things: finish_batch(batch_builder). So, each chunk follows the same route and all of them end up in a collection that I can iterate on. Does that make sense?
2) Do you think this approach is more efficient or better than the previous one?