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
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
use crate::{command::Command, stream::StreamError};
use dbus_message_parser::{
    match_rule::MatchRule,
    message::Message,
    value::{Error as ErrorName, Interface, ObjectPath},
};
use futures::channel::{mpsc::TrySendError, oneshot::Canceled};
use std::{
    fmt::{Display, Formatter, Result as FmtResult},
    io::{Error as IoError, ErrorKind as IoErrorKind},
};
use thiserror::Error;

#[derive(Debug, Error)]
pub enum DBusError {
    SendMessage(Message),
    AddMethodCall(ObjectPath),
    DeleteMethodCall(Option<ObjectPath>),
    ListMethodCall(ObjectPath),
    AddMethodCallInterface(Interface),
    DeleteMethodCallInterface(Option<Interface>),
    AddSignal(ObjectPath),
    DeleteSignal,
    AddMatchRules(Vec<MatchRule>),
    DeleteMatchRules,
    ReceiveMessage(Option<Message>),
    StreamError(#[from] StreamError),
    DBusSessionBusAddress,
    Hello(ErrorName),
    Close,
}

impl From<TrySendError<Command>> for DBusError {
    fn from(e: TrySendError<Command>) -> Self {
        match e.into_inner() {
            Command::SendMessage(msg) => DBusError::SendMessage(msg),
            Command::SendMessageOneshot(msg, _) => DBusError::SendMessage(msg),
            Command::SendMessageMpcs(msg, _, _) => DBusError::SendMessage(msg),
            Command::AddMethodCall(object_path, _) => DBusError::AddMethodCall(object_path),
            Command::DeleteMethodCall(object_path) => {
                DBusError::DeleteMethodCall(Some(object_path))
            }
            Command::DeleteMethodCallSender(_) => DBusError::DeleteMethodCall(None),
            Command::DeleteMethodCallReceiver(_) => DBusError::DeleteMethodCall(None),
            Command::ListMethodCall(object_path, _) => DBusError::ListMethodCall(object_path),
            Command::AddMethodCallInterface(object_path, _) => {
                DBusError::AddMethodCallInterface(object_path)
            }
            Command::DeleteMethodCallInterface(interface) => {
                DBusError::DeleteMethodCallInterface(Some(interface))
            }
            Command::DeleteMethodCallInterfaceSender(_) => {
                DBusError::DeleteMethodCallInterface(None)
            }
            Command::DeleteMethodCallInterfaceReceiver(_) => {
                DBusError::DeleteMethodCallInterface(None)
            }
            Command::AddSignal(object_path, _, _) => DBusError::AddSignal(object_path),
            Command::DeleteSignalSender(_) => DBusError::DeleteSignal,
            Command::DeleteSignalReceiver(_) => DBusError::DeleteSignal,
            Command::AddMatchRules(match_rules, _) => DBusError::AddMatchRules(match_rules),
            Command::DeleteMatchRulesSender(_) => DBusError::DeleteMatchRules,
            Command::DeleteMatchRulesReceiver(_) => DBusError::DeleteMatchRules,
            Command::Close => DBusError::Close,
        }
    }
}

impl From<Canceled> for DBusError {
    fn from(_: Canceled) -> Self {
        DBusError::ReceiveMessage(None)
    }
}

impl From<DBusError> for IoError {
    fn from(e: DBusError) -> Self {
        IoError::new(IoErrorKind::Other, format!("call_hello: {:?}", e))
    }
}

impl Display for DBusError {
    fn fmt(&self, f: &mut Formatter<'_>) -> FmtResult {
        match self {
            DBusError::SendMessage(msg) => write!(f, "Could not send message: {:?}", msg),
            DBusError::AddMethodCall(object_path) => {
                write!(f, "Could not add channel for method call: {}", object_path)
            }
            DBusError::DeleteMethodCall(object_path) => {
                write!(f, "Could not delete channel for method call")?;
                if let Some(object_path) = object_path {
                    write!(f, ": {}", object_path)
                } else {
                    Ok(())
                }
            }
            DBusError::ListMethodCall(path) => write!(f, "Could not list method call: {}", path),
            DBusError::AddMethodCallInterface(interface) => write!(
                f,
                "Could not add chanell for method call(interface): {}",
                interface
            ),
            DBusError::DeleteMethodCallInterface(interface) => {
                write!(f, "Could not delete channel for method call(interface)")?;
                if let Some(interface) = interface {
                    write!(f, ": {}", interface)
                } else {
                    Ok(())
                }
            }
            DBusError::AddSignal(path) => write!(f, "Could not add channel for signals: {}", path),
            DBusError::DeleteSignal => write!(f, "Could not delete channel for signals"),
            DBusError::AddMatchRules(match_rules) => {
                write!(f, "Could not add channel for matches rules:")?;
                for match_rule in match_rules.iter() {
                    write!(f, " {}", match_rule)?;
                }
                Ok(())
            }
            DBusError::DeleteMatchRules => write!(f, "Could not delete channel for match_rules"),
            DBusError::ReceiveMessage(msg) => {
                write!(f, "Could not receive response for message: {:?}", msg)
            }
            DBusError::StreamError(e) => write!(f, "Could not create stream: {}", e),
            DBusError::DBusSessionBusAddress => write!(
                f,
                "DBUS_SESSION_BUS_ADDRESS environment variable is not defined"
            ),
            DBusError::Hello(e) => write!(f, "Hello: {}", e),
            DBusError::Close => write!(f, "Could not close DBus"),
        }
    }
}

pub type DBusResult<T> = std::result::Result<T, DBusError>;