/// Create a new session config from the device information.
///
/// This method also does the boundary checks so that data_length/offset fields read
/// from descriptors are safe to convert to [`usize`].
Create a new session config from the device information.
This method also does the boundary checks so that data_length/offset fields read
from descriptors are safe to convert to [`usize`].
Create a new session config from the device information . This method also does the boundary checks so that data_length / offset fields read from descriptors are safe to convert to [ ` usize ` ] .
pub fn make_config(
        &self,
        buffer_length: usize,
        options: netdev::SessionFlags,
    ) -> Result<Config> {
        let DeviceInfo {
            min_descriptor_length,
            descriptor_version,
            rx_depth,
            tx_depth,
            buffer_alignment,
            max_buffer_length,
            min_rx_buffer_length,
            min_tx_buffer_length,
            min_tx_buffer_head,
            min_tx_buffer_tail,
            rx_accel: _,
            tx_accel: _,
        } = self;
        if NETWORK_DEVICE_DESCRIPTOR_VERSION != u32::from(*descriptor_version) {
            return Err(Error::Config(format!(
                "descriptor version mismatch: {} != {}",
                NETWORK_DEVICE_DESCRIPTOR_VERSION, descriptor_version
            )));
        }
        if NETWORK_DEVICE_DESCRIPTOR_LENGTH < usize::from(*min_descriptor_length) {
            return Err(Error::Config(format!(
                "descriptor length too small: {} < {}",
                NETWORK_DEVICE_DESCRIPTOR_LENGTH, min_descriptor_length
            )));
        }
        let num_rx_buffers =
            NonZeroU16::new(*rx_depth).ok_or_else(|| Error::Config("no RX buffers".to_owned()))?;
        let num_tx_buffers =
            NonZeroU16::new(*tx_depth).ok_or_else(|| Error::Config("no TX buffers".to_owned()))?;
        let max_buffer_length = max_buffer_length
            .and_then(|max| {
                match usize::try_from(max.get()) {
                    Ok(max) => Some(max),
                    // The error case is the case where max_buffer_length can't fix in a
                    // usize, but we use it to compare it to usizes, so that's
                    // equivalent to no limit.
                    Err(std::num::TryFromIntError { .. }) => None,
                }
            })
            .unwrap_or(usize::MAX);
        if buffer_length > max_buffer_length {
            return Err(Error::Config(format!(
                "buffer length too big: {} > {}",
                buffer_length, max_buffer_length
            )));
        }
        let buffer_alignment = usize::try_from(*buffer_alignment).map_err(
            |std::num::TryFromIntError { .. }| {
                Error::Config(format!(
                    "buffer_alignment not representable within usize: {}",
                    buffer_alignment,
                ))
            },
        )?;
        let buffer_stride = buffer_length
            .checked_add(buffer_alignment - 1)
            .map(|x| x / buffer_alignment * buffer_alignment)
            .ok_or_else(|| {
                Error::Config(format!(
                    "not possible to align {} to {} under usize::MAX",
                    buffer_length, buffer_alignment,
                ))
            })?;
        if buffer_stride < buffer_length {
            return Err(Error::Config(format!(
                "buffer stride too small {} < {}",
                buffer_stride, buffer_length
            )));
        }
        if buffer_length < usize::from(*min_tx_buffer_head) + usize::from(*min_tx_buffer_tail) {
            return Err(Error::Config(format!(
                "buffer length {} does not meet minimum tx buffer head/tail requirement {}/{}",
                buffer_length, min_tx_buffer_head, min_tx_buffer_tail,
            )));
        }
        let num_buffers =
            rx_depth.checked_add(*tx_depth).filter(|num| *num != u16::MAX).ok_or_else(|| {
                Error::Config(format!(
                    "too many buffers requested: {} + {} > u16::MAX",
                    rx_depth, tx_depth
                ))
            })?;
        let buffer_stride =
            u64::try_from(buffer_stride).map_err(|std::num::TryFromIntError { .. }| {
                Error::Config(format!("buffer_stride too big: {} > u64::MAX", buffer_stride))
            })?;
        // This is following the practice of rust stdlib to ensure allocation
        // size never reaches isize::MAX.
        // https://doc.rust-lang.org/std/primitive.pointer.html#method.add-1.
        match buffer_stride.checked_mul(num_buffers.into()).map(isize::try_from) {
            None | Some(Err(std::num::TryFromIntError { .. })) => {
                return Err(Error::Config(format!(
                    "too much memory required for the buffers: {} * {} > isize::MAX",
                    buffer_stride, num_buffers
                )))
            }
            Some(Ok(_total)) => (),
        };
        let buffer_stride = NonZeroU64::new(buffer_stride)
            .ok_or_else(|| Error::Config("buffer_stride is zero".to_owned()))?;
        let min_tx_data = match usize::try_from(*min_tx_buffer_length)
            .map(|min_tx| (min_tx <= buffer_length).then(|| min_tx))
        {
            Ok(Some(min_tx_buffer_length)) => min_tx_buffer_length,
            // Either the conversion or the comparison failed.
            Ok(None) | Err(std::num::TryFromIntError { .. }) => {
                return Err(Error::Config(format!(
                    "buffer_length smaller than minimum TX requirement: {} < {}",
                    buffer_length, *min_tx_buffer_length
                )));
            }
        };
        if buffer_length < usize::try_from(*min_rx_buffer_length).unwrap_or(usize::MAX) {
            return Err(Error::Config(format!(
                "buffer_length smaller than minimum RX requirement: {} < {}",
                buffer_length, *min_rx_buffer_length
            )));
        }
        Ok(Config {
            buffer_stride,
            num_rx_buffers,
            num_tx_buffers,
            options,
            buffer_layout: BufferLayout {
                length: buffer_length,
                min_tx_head: *min_tx_buffer_head,
                min_tx_tail: *min_tx_buffer_tail,
                min_tx_data,
            },
        })
    }
pub fn make_config ( & self , buffer_length : usize , options : netdev :: SessionFlags , ) -> Result < Config > { let DeviceInfo { min_descriptor_length , descriptor_version , rx_depth , tx_depth , buffer_alignment , max_buffer_length , min_rx_buffer_length , min_tx_buffer_length , min_tx_buffer_head , min_tx_buffer_tail , rx_accel : _ , tx_accel : _ , } = self ; if NETWORK_DEVICE_DESCRIPTOR_VERSION != u32 :: from ( * descriptor_version ) { return Err ( Error :: Config ( format ! ( " " NETWORK_DEVICE_DESCRIPTOR_VERSION descriptor_version ) ) ) ; } if NETWORK_DEVICE_DESCRIPTOR_LENGTH < usize :: from ( * min_descriptor_length ) { return Err ( Error :: Config ( format ! ( " " NETWORK_DEVICE_DESCRIPTOR_LENGTH min_descriptor_length ) ) ) ; } let num_rx_buffers = NonZeroU16 :: new ( * rx_depth ) . ok_or_else ( | | Error :: Config ( " " . to_owned ( ) ) ) ? ; let num_tx_buffers = NonZeroU16 :: new ( * tx_depth ) . ok_or_else ( | | Error :: Config ( " " . to_owned ( ) ) ) ? ; let max_buffer_length = max_buffer_length . and_then ( | max | { match usize :: try_from ( max . get ( ) ) { Ok ( max ) => Some ( max ) , // The error case is the case where max_buffer_length can't fix in a // usize, but we use it to compare it to usizes, so that's // equivalent to no limit. Err ( std :: num :: TryFromIntError { .. } ) => None , } } ) . unwrap_or ( usize :: MAX ) ; if buffer_length > max_buffer_length { return Err ( Error :: Config ( format ! ( " " buffer_length max_buffer_length ) ) ) ; } let buffer_alignment = usize :: try_from ( * buffer_alignment ) . map_err ( | std :: num :: TryFromIntError { .. } | { Error :: Config ( format ! ( " " buffer_alignment ) ) } , ) ? ; let buffer_stride = buffer_length . checked_add ( buffer_alignment - 1 ) . map ( | x | x / buffer_alignment * buffer_alignment ) . ok_or_else ( | | { Error :: Config ( format ! ( " " buffer_length buffer_alignment ) ) } ) ? ; if buffer_stride < buffer_length { return Err ( Error :: Config ( format ! ( " " buffer_stride buffer_length ) ) ) ; } if buffer_length < usize :: from ( * min_tx_buffer_head ) + usize :: from ( * min_tx_buffer_tail ) { return Err ( Error :: Config ( format ! ( " " buffer_length min_tx_buffer_head min_tx_buffer_tail ) ) ) ; } let num_buffers = rx_depth . checked_add ( * tx_depth ) . filter ( | num | * num != u16 :: MAX ) . ok_or_else ( | | { Error :: Config ( format ! ( " " rx_depth tx_depth ) ) } ) ? ; let buffer_stride = u64 :: try_from ( buffer_stride ) . map_err ( | std :: num :: TryFromIntError { .. } | { Error :: Config ( format ! ( " " buffer_stride ) ) } ) ? ; // This is following the practice of rust stdlib to ensure allocation // size never reaches isize::MAX. // https://doc.rust-lang.org/std/primitive.pointer.html#method.add-1. match buffer_stride . checked_mul ( num_buffers . into ( ) ) . map ( isize :: try_from ) { None | Some ( Err ( std :: num :: TryFromIntError { .. } ) ) => { return Err ( Error :: Config ( format ! ( " " buffer_stride num_buffers ) ) ) } Some ( Ok ( _total ) ) => ( ) , } ; let buffer_stride = NonZeroU64 :: new ( buffer_stride ) . ok_or_else ( | | Error :: Config ( " " . to_owned ( ) ) ) ? ; let min_tx_data = match usize :: try_from ( * min_tx_buffer_length ) . map ( | min_tx | ( min_tx <= buffer_length ) . then ( | | min_tx ) ) { Ok ( Some ( min_tx_buffer_length ) ) => min_tx_buffer_length , // Either the conversion or the comparison failed. Ok ( None ) | Err ( std :: num :: TryFromIntError { .. } ) => { return Err ( Error :: Config ( format ! ( " " buffer_length min_tx_buffer_length ) ) ) ; } } ; if buffer_length < usize :: try_from ( * min_rx_buffer_length ) . unwrap_or ( usize :: MAX ) { return Err ( Error :: Config ( format ! ( " " buffer_length min_rx_buffer_length ) ) ) ; } Ok ( Config { buffer_stride , num_rx_buffers , num_tx_buffers , options , buffer_layout : BufferLayout { length : buffer_length , min_tx_head : * min_tx_buffer_head , min_tx_tail : * min_tx_buffer_tail , min_tx_data , } , } ) }
Create a new session config from the device information.
Create a new session config from the device information .
&self
buffer_length
usize
options
netdev::SessionFlags