1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
//! Error-handling utilities.

pub use crate::backend::BackendError;
pub use anyhow::{anyhow, bail, ensure, Error};
use std::fmt;

/// Enum describing what kind of buffer had insufficient size, in a [`BufferSizeError`].
#[non_exhaustive]
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
pub enum BufferKind {
    /// The too-small buffer is for holding a [`Geo`][crate::geo::Geo].
    Geo,
    /// The too-small buffer is for holding a header name.
    HeaderName,
    /// The too-small buffer is for holding a header value.
    HeaderValue,
    /// The too-small buffer is for holding an HTTP method.
    HttpMethod,
    /// The too-small buffer is for holding a URL.
    Url,
}

impl fmt::Display for BufferKind {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match self {
            BufferKind::Geo => {
                write!(f, "Geo")
            }
            BufferKind::HttpMethod => {
                write!(f, "HTTP method")
            }
            BufferKind::HeaderName => {
                write!(f, "header name")
            }
            BufferKind::HeaderValue => {
                write!(f, "header value")
            }
            BufferKind::Url => {
                write!(f, "URL")
            }
        }
    }
}

/// Insufficient buffer size error.
///
/// This is returned by methods like
/// [`RequestHandle::get_header_names()`][`crate::handle::RequestHandle::get_header_names()`] if a
/// value was larger than the provided maximum size.
///
/// If you get such an error, you can try the same call again with a larger buffer.
#[derive(Copy, Clone, Debug, PartialEq, Eq, thiserror::Error)]
#[error("insufficient buffer size {buf_size} for buffer '{buffer_kind}'; value requires {needed_buf_size} bytes")]
pub struct BufferSizeError {
    /// The attempted buffer size.
    ///
    /// This is to help make nicer error messages.
    pub buf_size: usize,
    /// The buffer size that was required.
    ///
    /// Trying an operation again with a buffer at least this big may succeed where a previous call
    /// failed. However, it is not guaranteed to succeed, for example if there is an even larger
    /// value later in the list than the first value that was too large.
    pub needed_buf_size: usize,
    /// The buffer kind whose size was insufficient.
    pub buffer_kind: BufferKind,
}

impl BufferSizeError {
    /// Create a new [`BufferSizeError`].
    pub(crate) fn new(buf_size: usize, needed_buf_size: usize, buffer_kind: BufferKind) -> Self {
        Self {
            buf_size,
            needed_buf_size,
            buffer_kind,
        }
    }

    /// Create a new [`BufferSizeError`] for a failure to handle a [`Geo`][crate::geo::Geo].
    pub(crate) fn geo(buf_size: usize, needed_buf_size: usize) -> Self {
        Self::new(buf_size, needed_buf_size, BufferKind::Geo)
    }

    /// Create a new [`BufferSizeError`] for a failure to handle a header name.
    pub(crate) fn header_name(buf_size: usize, needed_buf_size: usize) -> Self {
        Self::new(buf_size, needed_buf_size, BufferKind::HeaderName)
    }

    /// Create a new [`BufferSizeError`] for a failure to handle a header value.
    pub(crate) fn header_value(buf_size: usize, needed_buf_size: usize) -> Self {
        Self::new(buf_size, needed_buf_size, BufferKind::HeaderValue)
    }

    /// Create a new [`BufferSizeError`] for a failure to handle an HTTP method.
    pub(crate) fn http_method(buf_size: usize, needed_buf_size: usize) -> Self {
        Self::new(buf_size, needed_buf_size, BufferKind::HttpMethod)
    }

    /// Create a new [`BufferSizeError`] for a failure to handle a URL.
    pub(crate) fn url(buf_size: usize, needed_buf_size: usize) -> Self {
        Self::new(buf_size, needed_buf_size, BufferKind::Url)
    }
}