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
104
105
106
107
// Unless explicitly stated otherwise all files in this repository are licensed under the
// MIT/Apache-2.0 License, at your convenience
//
// This product includes software developed at Datadog (https://www.datadoghq.com/). Copyright 2021
// Datadog, Inc.
use endianness::EndiannessError;
use serde::de;
use serde::ser;
use std::fmt;
use std::fmt::Display;
use std::fmt::Formatter;
use std::io;

/// Error returned by Kafka serde
pub type Error = Box<ErrorKind>;

/// Result alias where the Error component is a kafka_serde::Error
pub type Result<T> = core::result::Result<T, Error>;

#[derive(Debug)]
/// Errors that may happen when parsing a kafka payload (reader or writer)
pub enum ErrorKind {
    /// Wraps an I/O Error. Will only be seen if the write cursors return an I/O error
    Io(io::Error),
    /// Trying to serialize to or from a type that is not yet supported
    TypeNotSupported(&'static str),
    /// A boolean was expected, but a value different than 0 or 1 was found
    InvalidBoolEncoding(u8),
    /// A UTF-8 string was expected, but could not decode it.
    InvalidStringEncoding,
    /// The buffer ran out of bytes but we still had more data to deserialize
    NotEnoughBytes,
    /// Custom errors
    Custom(String),
}

impl Display for ErrorKind {
    fn fmt(&self, fmt: &mut Formatter<'_>) -> fmt::Result {
        match *self {
            ErrorKind::Io(ref ioerr) => write!(fmt, "io error: {}", ioerr),
            ErrorKind::InvalidBoolEncoding(b) => {
                write!(fmt, "{}, expected 0 or 1, found {}", self, b)
            }
            ErrorKind::InvalidStringEncoding => {
                write!(fmt, "string not utf-8 encoded")
            }
            ErrorKind::NotEnoughBytes => {
                write!(fmt, "not enought bytes")
            }
            ErrorKind::TypeNotSupported(s) => {
                write!(fmt, "not supported: {}", s)
            }
            ErrorKind::Custom(ref s) => s.fmt(fmt),
        }
    }
}

impl From<io::Error> for Error {
    #[cold]
    fn from(err: io::Error) -> Error {
        ErrorKind::Io(err).into()
    }
}

impl From<EndiannessError> for Error {
    fn from(_err: EndiannessError) -> Error {
        ErrorKind::NotEnoughBytes.into()
    }
}

impl From<std::str::Utf8Error> for Error {
    fn from(_err: std::str::Utf8Error) -> Error {
        ErrorKind::InvalidStringEncoding.into()
    }
}

impl From<std::string::FromUtf8Error> for Error {
    fn from(_err: std::string::FromUtf8Error) -> Error {
        ErrorKind::InvalidStringEncoding.into()
    }
}

impl From<Error> for io::Error {
    fn from(err: Error) -> io::Error {
        io::Error::new(io::ErrorKind::Other, err)
    }
}

impl serde::de::StdError for Error {
    fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
        None
    }
}

impl de::Error for Error {
    #[cold]
    fn custom<T: Display>(desc: T) -> Error {
        ErrorKind::Custom(desc.to_string()).into()
    }
}

impl ser::Error for Error {
    #[cold]
    fn custom<T: Display>(msg: T) -> Error {
        ErrorKind::Custom(msg.to_string()).into()
    }
}