use super::{Family, Interface, InterfaceOption, Mapping, Method};
#[derive(Debug, Clone)]
pub struct InterfaceBuilder {
pub(crate) name: String,
pub(crate) auto: bool,
pub(crate) allow: Vec<String>,
pub(crate) family: Option<Family>,
pub(crate) method: Option<Method>,
pub(crate) options: Vec<InterfaceOption>,
pub(crate) mapping: Option<Mapping>,
}
impl InterfaceBuilder {
pub fn new(name: impl Into<String>) -> Self {
InterfaceBuilder {
name: name.into(),
auto: false,
allow: Vec::new(),
family: None,
method: None,
options: Vec::new(),
mapping: None,
}
}
pub fn with_auto(mut self, auto: bool) -> Self {
self.auto = auto;
self
}
pub fn with_allow(mut self, allow: impl Into<String>) -> Self {
self.allow.push(allow.into());
self
}
pub fn with_family(mut self, family: Family) -> Self {
self.family = Some(family);
self
}
pub fn with_method(mut self, method: Method) -> Self {
self.method = Some(method);
self
}
pub fn with_option(mut self, key: impl Into<String>, value: impl Into<String>) -> Self {
let key = key.into();
let value = value.into();
self.options.push(InterfaceOption::from_key_value(&key, &value));
self
}
pub fn with_typed_option(mut self, option: InterfaceOption) -> Self {
self.options.push(option);
self
}
pub fn with_mapping(mut self, mapping: Mapping) -> Self {
self.mapping = Some(mapping);
self
}
pub fn remove_option(mut self, key: &str) -> Self {
self.options.retain(|opt| opt.name() != key);
self
}
pub fn remove_option_value(mut self, key: &str, value: &str) -> Self {
self.options.retain(|opt| !(opt.name() == key && opt.value() == value));
self
}
pub fn build(self) -> Interface {
Interface {
name: self.name,
auto: self.auto,
allow: self.allow,
family: self.family,
method: self.method,
options: self.options,
mapping: self.mapping,
}
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_remove_option() {
let iface = Interface::builder("eth0")
.with_option("address", "192.168.1.50")
.with_option("netmask", "255.255.255.0")
.with_option("address", "192.168.1.51") .remove_option("address") .build();
assert_eq!(iface.options.len(), 1);
assert_eq!(
iface.options[0],
InterfaceOption::Netmask("255.255.255.0".to_string())
);
}
#[test]
fn test_remove_option_value() {
let iface = Interface::builder("eth0")
.with_option("address", "192.168.1.50")
.with_option("netmask", "255.255.255.0")
.with_option("address", "192.168.1.51") .with_option("address", "192.168.1.52") .remove_option_value("address", "192.168.1.50") .build();
assert_eq!(iface.options.len(), 3);
assert!(iface
.options
.contains(&InterfaceOption::Netmask("255.255.255.0".to_string())));
assert!(iface
.options
.contains(&InterfaceOption::Address("192.168.1.51".to_string())));
assert!(iface
.options
.contains(&InterfaceOption::Address("192.168.1.52".to_string())));
}
#[test]
fn test_with_typed_option() {
let iface = Interface::builder("eth0")
.with_typed_option(InterfaceOption::Mtu(1500))
.with_typed_option(InterfaceOption::BridgeVlanAware(true))
.build();
assert_eq!(iface.options.len(), 2);
assert!(iface.options.contains(&InterfaceOption::Mtu(1500)));
assert!(iface.options.contains(&InterfaceOption::BridgeVlanAware(true)));
}
}