1 use serde::{de, ser}; 2 use static_assertions::assert_impl_all; 3 use std::{convert::Infallible, error, fmt, result}; 4 5 /// Error type used by zvariant API. 6 #[derive(Debug)] 7 #[non_exhaustive] 8 pub enum Error { 9 /// Generic error. All serde errors gets transformed into this variant. 10 Message(String), 11 12 /// Wrapper for [`std::io::Error`](https://doc.rust-lang.org/std/io/struct.Error.html) 13 Io(std::io::Error), 14 /// Type conversions errors. 15 IncorrectType, 16 /// Wrapper for [`std::str::Utf8Error`](https://doc.rust-lang.org/std/str/struct.Utf8Error.html) 17 Utf8(std::str::Utf8Error), 18 /// Non-0 padding byte(s) encountered. 19 PaddingNot0(u8), 20 /// The deserialized file descriptor is not in the given FD index. 21 UnknownFd, 22 /// Missing framing offset at the end of a GVariant-encoded container, 23 MissingFramingOffset, 24 /// The type (signature as first argument) being (de)serialized is not supported by the format. 25 IncompatibleFormat(crate::Signature<'static>, crate::EncodingFormat), 26 /// The provided signature (first argument) was not valid for reading as the requested type. 27 /// Details on the expected signatures are in the second argument. 28 SignatureMismatch(crate::Signature<'static>, String), 29 } 30 31 assert_impl_all!(Error: Send, Sync, Unpin); 32 33 impl PartialEq for Error { eq(&self, other: &Self) -> bool34 fn eq(&self, other: &Self) -> bool { 35 match (self, other) { 36 (Error::Message(msg), Error::Message(other)) => msg == other, 37 // Io is false 38 (Error::IncorrectType, Error::IncorrectType) => true, 39 (Error::Utf8(msg), Error::Utf8(other)) => msg == other, 40 (Error::PaddingNot0(p), Error::PaddingNot0(other)) => p == other, 41 (Error::UnknownFd, Error::UnknownFd) => true, 42 (_, _) => false, 43 } 44 } 45 } 46 47 impl error::Error for Error { source(&self) -> Option<&(dyn error::Error + 'static)>48 fn source(&self) -> Option<&(dyn error::Error + 'static)> { 49 match self { 50 Error::Io(e) => Some(e), 51 Error::Utf8(e) => Some(e), 52 _ => None, 53 } 54 } 55 } 56 57 impl fmt::Display for Error { fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result58 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { 59 match self { 60 Error::Message(s) => write!(f, "{}", s), 61 Error::Io(e) => e.fmt(f), 62 Error::IncorrectType => write!(f, "incorrect type"), 63 Error::Utf8(e) => write!(f, "{}", e), 64 Error::PaddingNot0(b) => write!(f, "Unexpected non-0 padding byte `{}`", b), 65 Error::UnknownFd => write!(f, "File descriptor not in the given FD index"), 66 Error::MissingFramingOffset => write!( 67 f, 68 "Missing framing offset at the end of GVariant-encoded container" 69 ), 70 Error::IncompatibleFormat(sig, format) => write!( 71 f, 72 "Type `{}` is not compatible with `{}` format", 73 sig, format, 74 ), 75 Error::SignatureMismatch(provided, expected) => write!( 76 f, 77 "Signature mismatch: got `{}`, expected {}", 78 provided, expected, 79 ), 80 } 81 } 82 } 83 84 impl From<Infallible> for Error { from(i: Infallible) -> Self85 fn from(i: Infallible) -> Self { 86 match i {} 87 } 88 } 89 90 impl de::Error for Error { 91 // TODO: Add more specific error variants to Error enum above so we can implement other methods 92 // here too. custom<T>(msg: T) -> Error where T: fmt::Display,93 fn custom<T>(msg: T) -> Error 94 where 95 T: fmt::Display, 96 { 97 Error::Message(msg.to_string()) 98 } 99 } 100 101 impl ser::Error for Error { custom<T>(msg: T) -> Error where T: fmt::Display,102 fn custom<T>(msg: T) -> Error 103 where 104 T: fmt::Display, 105 { 106 Error::Message(msg.to_string()) 107 } 108 } 109 110 /// Alias for a `Result` with the error type `zvariant::Error`. 111 pub type Result<T> = result::Result<T, Error>; 112