1use std::ffi::CString;
2
3pub trait Device: Sized {
4 fn new(config: Config) -> std::io::Result<Self>;
8
9 fn builder() -> DeviceBuilder<Self> {
14 DeviceBuilder::default()
15 }
16}
17
18pub struct Config {
19 pub name: Option<CString>,
20 pub num_queues: Option<usize>,
21 pub(crate) multi_queue: Option<bool>,
22 pub no_pi: bool,
23 pub address: Option<std::net::IpAddr>,
24 pub netmask: Option<cidr::IpCidr>,
25 pub up: bool,
26
27 #[cfg(target_os = "android")]
28 pub raw_fd: Option<std::os::fd::RawFd>,
29}
30
31impl Default for Config {
32 fn default() -> Self {
33 Self {
34 name: None,
35 num_queues: None,
36 multi_queue: None,
37 no_pi: true,
38 address: None,
39 netmask: None,
40 up: false,
41 #[cfg(target_os = "android")]
42 raw_fd: None,
43 }
44 }
45}
46
47pub struct DeviceBuilder<D: Device> {
49 _marker: std::marker::PhantomData<D>,
50 config: Config,
51}
52
53impl<D: Device> DeviceBuilder<D> {
54 pub fn new() -> Self {
56 Self {
57 _marker: std::marker::PhantomData,
58 config: Config {
59 name: None,
60 num_queues: None,
61 multi_queue: None,
62 no_pi: true,
63 address: None,
64 netmask: None,
65 up: true,
66 #[cfg(target_os = "android")]
67 raw_fd: None,
68 },
69 }
70 }
71
72 pub fn with_name(mut self, name: CString) -> Self {
73 self.config.name = Some(name);
74 self
75 }
76
77 pub fn with_pi(mut self, pi: bool) -> Self {
79 self.config.no_pi = !pi;
80 self
81 }
82
83 pub fn with_address(mut self, address: std::net::IpAddr) -> Self {
84 self.config.address = Some(address);
85 self
86 }
87
88 pub fn with_netmask(mut self, netmask: cidr::IpCidr) -> Self {
89 self.config.netmask = Some(netmask);
90 self
91 }
92
93 pub fn with_num_queues(mut self, num_queues: usize) -> Self {
101 if num_queues < 1 {
102 panic!("number of queues must be at least 1")
103 }
104 self.config.num_queues = Some(num_queues);
105 self.config.multi_queue = if num_queues > 1 {
106 Some(true)
107 } else {
108 Some(false)
109 };
110 self
111 }
112
113 pub fn with_up(mut self, up: bool) -> Self {
115 self.config.up = up;
116 self
117 }
118
119 #[cfg(target_os = "android")]
120 pub fn with_raw_fd(mut self, raw_fd: std::os::fd::RawFd) -> Self {
121 self.config.raw_fd = Some(raw_fd);
122 self
123 }
124
125 pub fn build(self) -> std::io::Result<D> {
127 Device::new(self.config)
128 }
129}
130
131impl<D: Device> Default for DeviceBuilder<D> {
132 fn default() -> Self {
133 Self::new()
134 }
135}