pub fn parse<M: GuestAddressSpace>(desc_chain: &mut DescriptorChain<M>) -> Result<Request> {
        let chain_head = desc_chain.next().ok_or(Error::DescriptorChainTooShort)?;
        // The head contains the request type which MUST be readable.
        if chain_head.is_write_only() {
            return Err(Error::UnexpectedWriteOnlyDescriptor);
        }

        let request_header = desc_chain
            .memory()
            .read_obj::<RequestHeader>(chain_head.addr())
            .map_err(Error::GuestMemory)?;

        if request_header.request_type == VIRTIO_BLK_T_FLUSH && request_header.sector != 0 {
            return Err(Error::InvalidFlushSector);
        }

        let mut request = Request {
            request_type: RequestType::from(request_header.request_type),
            data: Vec::new(),
            sector: request_header.sector,
            status_addr: GuestAddress(0),
        };

        let mut desc = desc_chain.next().ok_or(Error::DescriptorChainTooShort)?;

        while desc.has_next() {
            Request::check_data_desc(desc, request.request_type)?;

            request.data.push((desc.addr(), desc.len()));
            desc = desc_chain.next().ok_or(Error::DescriptorChainTooShort)?;
        }
        let status_desc = desc;

        Request::check_status_desc::<<M>::M>(desc_chain.memory(), status_desc)?;

        request.status_addr = status_desc.addr();
        Ok(request)
    }
/// Parses a `desc_chain` and returns the associated `Request`.
///
/// The checks we're doing here are mostly the `MUST`s from the virtio specification.
/// We are also partially validating `The driver MUST place any device-writable descriptor
/// elements after any device-readable descriptor elements` rule by checking that the
/// expected header descriptor (the chain head) is device-readable and the expected status
/// descriptor (the chain tail) is device-writable.
///
/// # Arguments
/// * `desc_chain` - A mutable reference to the descriptor chain that should point to the
///                  buffers of a virtio block request.
Parses a `desc_chain` and returns the associated `Request`.
The checks we're doing here are mostly the `MUST`s from the virtio specification.
We are also partially validating `The driver MUST place any device-writable descriptor
elements after any device-readable descriptor elements` rule by checking that the
expected header descriptor (the chain head) is device-readable and the expected status
descriptor (the chain tail) is device-writable.
Parses a ` desc_chain ` and returns the associated ` Request ` . The checks we ' re doing here are mostly the ` MUST ` s from the virtio specification . We are also partially validating ` The driver MUST place any device - writable descriptor elements after any device - readable descriptor elements ` rule by checking that the expected header descriptor ( the chain head ) is device - readable and the expected status descriptor ( the chain tail ) is device - writable .
pub fn parse<M: GuestAddressSpace>(desc_chain: &mut DescriptorChain<M>) -> Result<Request> {
        let chain_head = desc_chain.next().ok_or(Error::DescriptorChainTooShort)?;
        // The head contains the request type which MUST be readable.
        if chain_head.is_write_only() {
            return Err(Error::UnexpectedWriteOnlyDescriptor);
        }
        let request_header = desc_chain
            .memory()
            .read_obj::<RequestHeader>(chain_head.addr())
            .map_err(Error::GuestMemory)?;
        if request_header.request_type == VIRTIO_BLK_T_FLUSH && request_header.sector != 0 {
            return Err(Error::InvalidFlushSector);
        }
        let mut request = Request {
            request_type: RequestType::from(request_header.request_type),
            data: Vec::new(),
            sector: request_header.sector,
            status_addr: GuestAddress(0),
        };
        let mut desc = desc_chain.next().ok_or(Error::DescriptorChainTooShort)?;
        while desc.has_next() {
            Request::check_data_desc(desc, request.request_type)?;
            request.data.push((desc.addr(), desc.len()));
            desc = desc_chain.next().ok_or(Error::DescriptorChainTooShort)?;
        }
        let status_desc = desc;
        Request::check_status_desc::<<M>::M>(desc_chain.memory(), status_desc)?;
        request.status_addr = status_desc.addr();
        Ok(request)
    }
pub fn parse < M : GuestAddressSpace > ( desc_chain : & mut DescriptorChain < M > ) -> Result < Request > { let chain_head = desc_chain . next ( ) . ok_or ( Error :: DescriptorChainTooShort ) ? ; // The head contains the request type which MUST be readable. if chain_head . is_write_only ( ) { return Err ( Error :: UnexpectedWriteOnlyDescriptor ) ; } let request_header = desc_chain . memory ( ) . read_obj :: < RequestHeader > ( chain_head . addr ( ) ) . map_err ( Error :: GuestMemory ) ? ; if request_header . request_type == VIRTIO_BLK_T_FLUSH && request_header . sector != 0 { return Err ( Error :: InvalidFlushSector ) ; } let mut request = Request { request_type : RequestType :: from ( request_header . request_type ) , data : Vec :: new ( ) , sector : request_header . sector , status_addr : GuestAddress ( 0 ) , } ; let mut desc = desc_chain . next ( ) . ok_or ( Error :: DescriptorChainTooShort ) ? ; while desc . has_next ( ) { Request :: check_data_desc ( desc , request . request_type ) ? ; request . data . push ( ( desc . addr ( ) , desc . len ( ) ) ) ; desc = desc_chain . next ( ) . ok_or ( Error :: DescriptorChainTooShort ) ? ; } let status_desc = desc ; Request :: check_status_desc :: < < M > :: M > ( desc_chain . memory ( ) , status_desc ) ? ; request . status_addr = status_desc . addr ( ) ; Ok ( request ) }
Parses a `desc_chain` and returns the associated `Request`.
Parses a ` desc_chain ` and returns the associated ` Request ` .
desc_chain
&mut DescriptorChain<M>
desc_chain
&mut DescriptorChain<M>