interface_rs/interface/interface_struct.rs
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
use super::{Family, InterfaceBuilder, Mapping};
use std::fmt;
/// Represents a network interface configuration in an `interfaces(5)` file.
///
/// The `Interface` struct encapsulates all the configuration details for a
/// network interface, including its name, whether it starts automatically,
/// allowed hotplug options, address family, method of configuration, and
/// additional options.
///
/// To construct an `Interface`, it is recommended to use the [`InterfaceBuilder`]
/// via the [`Interface::builder`] method for a more ergonomic and fluent API.
///
/// # Examples
///
/// Creating a new `Interface` using the builder pattern:
///
/// ```rust
/// use interface_rs::interface::{Interface, Family};
///
/// let iface = Interface::builder("eth0")
/// .with_auto(true)
/// .with_allow("hotplug")
/// .with_family(Family::Inet)
/// .with_method("dhcp")
/// .with_option("mtu", "1500")
/// .build();
/// ```
#[derive(Debug, Clone)]
pub struct Interface {
/// The name of the interface (e.g., `"eth0"`).
pub name: String,
/// Indicates if the interface is set to start automatically.
pub auto: bool,
/// A list of `allow-*` directives associated with the interface.
pub allow: Vec<String>,
/// The address family (e.g., `inet`).
pub family: Option<Family>,
/// The method of configuration (e.g., `"static"`, `"dhcp"`).
pub method: Option<String>,
/// A list of options specified under the `iface` stanza.
pub options: Vec<(String, String)>,
/// Optional mapping configuration for the interface.
pub mapping: Option<Mapping>,
}
impl Interface {
/// Creates a new [`InterfaceBuilder`] for constructing an `Interface`.
///
/// # Arguments
///
/// * `name` - The name of the interface (e.g., `"eth0"`).
///
/// # Examples
///
/// ```rust
/// use interface_rs::interface::Interface;
///
/// let builder = Interface::builder("eth0");
/// ```
pub fn builder(name: impl Into<String>) -> InterfaceBuilder {
InterfaceBuilder::new(name)
}
/// Creates a new [`InterfaceBuilder`] initialized with this `Interface`'s data.
///
/// This method allows you to modify an existing `Interface` using the builder pattern.
///
/// # Examples
///
/// ```rust
/// use interface_rs::interface::{Interface, Family};
///
/// let iface = Interface::builder("eth0")
/// .with_auto(true)
/// .with_family(Family::Inet)
/// .with_method("dhcp")
/// .build();
///
/// // Modify the existing interface
/// let modified_iface = iface.edit()
/// .with_method("static")
/// .with_option("address", "192.168.1.50")
/// .build();
/// ```
pub fn edit(&self) -> InterfaceBuilder {
InterfaceBuilder {
name: self.name.clone(),
auto: self.auto,
allow: self.allow.clone(),
family: self.family.clone(),
method: self.method.clone(),
options: self.options.clone(),
mapping: self.mapping.clone(),
}
}
}
impl fmt::Display for Interface {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
if self.auto {
writeln!(f, "auto {}", self.name)?;
}
for allow_type in &self.allow {
writeln!(f, "allow-{} {}", allow_type, self.name)?;
}
if let Some(mapping) = &self.mapping {
writeln!(f, "mapping {}", self.name)?;
writeln!(f, " script {}", mapping.script)?;
for map in &mapping.maps {
writeln!(f, " map {}", map)?;
}
}
write!(f, "iface {}", self.name)?;
if let Some(family) = &self.family {
write!(f, " {}", family)?;
}
if let Some(method) = &self.method {
write!(f, " {}", method)?;
}
writeln!(f)?;
// Sort options before printing
let mut sorted_options = self.options.clone();
sorted_options.sort_by(|a, b| a.0.cmp(&b.0));
for (option_name, option_value) in &sorted_options {
writeln!(f, " {} {}", option_name, option_value)?;
}
Ok(())
}
}