zcash_proofs 0.10.0

Zcash zk-SNARK circuits and proving APIs
Documentation
//! [`io::Read`] implementations for [`minreq`].

use std::io;

/// A wrapper that implements [`io::Read`] on a [`minreq::ResponseLazy`].
pub enum ResponseLazyReader {
    Request(minreq::Request),
    Response(minreq::ResponseLazy),
    Complete(Result<(), String>),
}

impl From<minreq::Request> for ResponseLazyReader {
    fn from(request: minreq::Request) -> ResponseLazyReader {
        ResponseLazyReader::Request(request)
    }
}

impl From<minreq::ResponseLazy> for ResponseLazyReader {
    fn from(response: minreq::ResponseLazy) -> ResponseLazyReader {
        ResponseLazyReader::Response(response)
    }
}

impl io::Read for ResponseLazyReader {
    fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
        use ResponseLazyReader::{Complete, Request, Response};

        // Zero-sized buffer. This should never happen.
        if buf.is_empty() {
            return Ok(0);
        }

        loop {
            match self {
                // Launch a lazy response for this request
                Request(request) => match request.clone().send_lazy() {
                    Ok(response) => *self = Response(response),
                    Err(error) => {
                        let error = Err(format!("download request failed: {:?}", error));

                        *self = Complete(error);
                    }
                },

                // Read from the response
                Response(response) => {
                    for (i, buf_byte) in buf.iter_mut().enumerate() {
                        match response.next() {
                            // Load a byte into the buffer.
                            Some(Ok((byte, _length))) => {
                                *buf_byte = byte;
                            }

                            // The whole response has been processed.
                            None => {
                                *self = Complete(Ok(()));
                                return Ok(i);
                            }

                            // The response is corrupted.
                            Some(Err(error)) => {
                                let error = format!("download response failed: {:?}", error);

                                *self = Complete(Err(error.clone()));
                                return Err(io::Error::new(io::ErrorKind::Other, error));
                            }
                        }
                    }

                    return Ok(buf.len());
                }

                Complete(result) => {
                    return match result {
                        // Return a zero-byte read for download success and EOF.
                        Ok(()) => Ok(0),
                        // Keep returning the download error,
                        Err(error) => Err(io::Error::new(io::ErrorKind::Other, error.clone())),
                    };
                }
            }
        }
    }
}