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
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
use super::{BridgeDevice, EthernetDevice, GenericDevice, VethDevice, WiFiDevice};
use crate::configs::{Dhcp4Config, Dhcp6Config, Ip4Config, Ip6Config};
use crate::connection::Connection;
use crate::errors::Error;
use crate::gen::OrgFreedesktopNetworkManagerDevice;
use crate::types::{Capability, ConnectivityState, DeviceInterfaceFlag, DeviceType};
use num_traits::FromPrimitive;

type HashMapDBusVariant =
    std::collections::HashMap<String, dbus::arg::Variant<Box<dyn dbus::arg::RefArg + 'static>>>;

type HashMapDBusVariantStr<'a> = std::collections::HashMap<
    &'a str,
    std::collections::HashMap<String, dbus::arg::Variant<Box<dyn dbus::arg::RefArg>>>,
>;

pub trait Any {
    fn reapply(
        &self,
        connection: HashMapDBusVariantStr<'_>,
        version_id: u64,
        flags: u32,
    ) -> Result<(), Error>;
    fn get_applied_connection(
        &self,
        flags: u32,
    ) -> Result<(::std::collections::HashMap<String, HashMapDBusVariant>, u64), Error>;
    fn disconnect(&self) -> Result<(), Error>;
    fn delete(&self) -> Result<(), Error>;
    fn udi(&self) -> Result<String, Error>;
    fn interface(&self) -> Result<String, Error>;
    fn ip_interface(&self) -> Result<String, Error>;
    fn driver(&self) -> Result<String, Error>;
    fn driver_version(&self) -> Result<String, Error>;
    fn firmware_version(&self) -> Result<String, Error>;
    fn capabilities(&self) -> Result<Capability, Error>;
    fn ip4_address(&self) -> Result<u32, Error>;
    fn state(&self) -> Result<u32, Error>;
    fn state_reason(&self) -> Result<(u32, u32), Error>;
    fn active_connection(&self) -> Result<Connection, Error>;
    fn ip4_config(&self) -> Result<Ip4Config, Error>;
    fn dhcp4_config(&self) -> Result<Dhcp4Config, Error>;
    fn ip6_config(&self) -> Result<Ip6Config, Error>;
    fn dhcp6_config(&self) -> Result<Dhcp6Config, Error>;
    fn managed(&self) -> Result<bool, Error>;
    fn set_managed(&self, value: bool) -> Result<(), Error>;
    fn autoconnect(&self) -> Result<bool, Error>;
    fn set_autoconnect(&self, value: bool) -> Result<(), Error>;
    fn firmware_missing(&self) -> Result<bool, Error>;
    fn nm_plugin_missing(&self) -> Result<bool, Error>;
    fn device_type(&self) -> Result<DeviceType, Error>;
    fn available_connections(&self) -> Result<Vec<Connection>, Error>;
    fn physical_port_id(&self) -> Result<String, Error>;
    fn mtu(&self) -> Result<u32, Error>;
    fn metered(&self) -> Result<u32, Error>;
    fn lldp_neighbors(&self) -> Result<Vec<HashMapDBusVariant>, Error>;
    fn real(&self) -> Result<bool, Error>;
    fn ip4_connectivity(&self) -> Result<ConnectivityState, Error>;
    fn ip6_connectivity(&self) -> Result<ConnectivityState, Error>;
    fn interface_flags(&self) -> Result<DeviceInterfaceFlag, Error>;
    fn hw_address(&self) -> Result<String, Error>;
}

macro_rules! impl_any {
    ($name:ty) => {
        impl Any for $name {
            fn reapply(
                &self,
                connection: HashMapDBusVariantStr<'_>,
                version_id: u64,
                flags: u32,
            ) -> Result<(), Error> {
                Ok(proxy!(self).reapply(connection, version_id, flags)?)
            }
            fn get_applied_connection(
                &self,
                flags: u32,
            ) -> Result<(std::collections::HashMap<String, HashMapDBusVariant>, u64), Error> {
                Ok(proxy!(self).get_applied_connection(flags)?)
            }
            fn disconnect(&self) -> Result<(), Error> {
                Ok(proxy!(self).disconnect()?)
            }
            fn delete(&self) -> Result<(), Error> {
                Ok(proxy!(self).delete()?)
            }
            fn udi(&self) -> Result<String, Error> {
                Ok(proxy!(self).udi()?)
            }
            fn interface(&self) -> Result<String, Error> {
                Ok(proxy!(self).interface()?)
            }
            fn ip_interface(&self) -> Result<String, Error> {
                Ok(proxy!(self).ip_interface()?)
            }
            fn driver(&self) -> Result<String, Error> {
                Ok(proxy!(self).driver()?)
            }
            fn driver_version(&self) -> Result<String, Error> {
                Ok(proxy!(self).driver_version()?)
            }
            fn firmware_version(&self) -> Result<String, Error> {
                Ok(proxy!(self).firmware_version()?)
            }
            fn capabilities(&self) -> Result<Capability, Error> {
                let cap = proxy!(self).capabilities()?;
                match FromPrimitive::from_u32(cap) {
                    Some(x) => Ok(x),
                    None => Err(Error::UnsupportedType),
                }
            }
            fn ip4_address(&self) -> Result<u32, Error> {
                Ok(proxy!(self).ip4_address()?)
            }
            fn state(&self) -> Result<u32, Error> {
                Ok(proxy!(self).state()?)
            }
            fn state_reason(&self) -> Result<(u32, u32), Error> {
                Ok(proxy!(self).state_reason()?)
            }
            fn active_connection(&self) -> Result<Connection, Error> {
                let path = proxy!(self).active_connection()?;
                Ok(Connection::new(self.dbus_accessor.with_path(path)))
            }
            fn ip4_config(&self) -> Result<Ip4Config, Error> {
                let path = proxy!(self).ip4_config()?;
                Ok(Ip4Config::new(self.dbus_accessor.with_path(path)))
            }
            fn dhcp4_config(&self) -> Result<Dhcp4Config, Error> {
                let path = proxy!(self).dhcp4_config()?;
                Ok(Dhcp4Config::new(self.dbus_accessor.with_path(path)))
            }
            fn ip6_config(&self) -> Result<Ip6Config, Error> {
                let path = proxy!(self).ip6_config()?;
                Ok(Ip6Config::new(self.dbus_accessor.with_path(path)))
            }
            fn dhcp6_config(&self) -> Result<Dhcp6Config, Error> {
                let path = proxy!(self).dhcp6_config()?;
                Ok(Dhcp6Config::new(self.dbus_accessor.with_path(path)))
            }
            fn managed(&self) -> Result<bool, Error> {
                Ok(proxy!(self).managed()?)
            }
            fn set_managed(&self, value: bool) -> Result<(), Error> {
                Ok(proxy!(self).set_managed(value)?)
            }
            fn autoconnect(&self) -> Result<bool, Error> {
                Ok(proxy!(self).autoconnect()?)
            }
            fn set_autoconnect(&self, value: bool) -> Result<(), Error> {
                Ok(proxy!(self).set_autoconnect(value)?)
            }
            fn firmware_missing(&self) -> Result<bool, Error> {
                Ok(proxy!(self).firmware_missing()?)
            }
            fn nm_plugin_missing(&self) -> Result<bool, Error> {
                Ok(proxy!(self).nm_plugin_missing()?)
            }
            fn device_type(&self) -> Result<DeviceType, Error> {
                let dev_type = proxy!(self).device_type()?;
                match FromPrimitive::from_u32(dev_type) {
                    Some(x) => Ok(x),
                    None => Err(Error::UnsupportedType),
                }
            }
            fn available_connections(&self) -> Result<Vec<Connection>, Error> {
                let paths = proxy!(self).available_connections()?;
                let mut connections = Vec::with_capacity(paths.len());
                for path in paths {
                    connections.push(Connection::new(self.dbus_accessor.with_path(path)));
                }
                Ok(connections)
            }
            fn physical_port_id(&self) -> Result<String, Error> {
                Ok(proxy!(self).physical_port_id()?)
            }
            fn mtu(&self) -> Result<u32, Error> {
                Ok(proxy!(self).mtu()?)
            }
            fn lldp_neighbors(&self) -> Result<Vec<HashMapDBusVariant>, Error> {
                Ok(proxy!(self).lldp_neighbors()?)
            }
            fn metered(&self) -> Result<u32, Error> {
                Ok(proxy!(self).metered()?)
            }
            fn real(&self) -> Result<bool, Error> {
                Ok(proxy!(self).real()?)
            }
            fn ip4_connectivity(&self) -> Result<ConnectivityState, Error> {
                let con = proxy!(self).ip4_connectivity()?;
                match FromPrimitive::from_u32(con) {
                    Some(x) => Ok(x),
                    None => Err(Error::UnsupportedType),
                }
            }
            fn ip6_connectivity(&self) -> Result<ConnectivityState, Error> {
                let con = proxy!(self).ip6_connectivity()?;
                match FromPrimitive::from_u32(con) {
                    Some(x) => Ok(x),
                    None => Err(Error::UnsupportedType),
                }
            }
            fn interface_flags(&self) -> Result<DeviceInterfaceFlag, Error> {
                let interface_flag = proxy!(self).interface_flags()?;
                match FromPrimitive::from_u32(interface_flag) {
                    Some(x) => Ok(x),
                    None => Err(Error::UnsupportedType),
                }
            }
            fn hw_address(&self) -> Result<String, Error> {
                Ok(proxy!(self).hw_address()?)
            }
        }
    };
}

impl_any!(VethDevice);
impl_any!(BridgeDevice);
impl_any!(WiFiDevice);
impl_any!(EthernetDevice);
impl_any!(GenericDevice);