Skip to content

Commit

Permalink
make clippy happy and run fmt
Browse files Browse the repository at this point in the history
  • Loading branch information
wiggels committed Nov 19, 2024
1 parent 131f314 commit 812066f
Show file tree
Hide file tree
Showing 6 changed files with 121 additions and 67 deletions.
4 changes: 2 additions & 2 deletions src/interface/family.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
use std::str::FromStr;
use std::fmt;
use std::error::Error;
use std::fmt;
use std::str::FromStr;

/// Represents the address family in the `interfaces(5)` file.
///
Expand Down
24 changes: 16 additions & 8 deletions src/interface/interface_builder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ pub struct InterfaceBuilder {
pub(crate) allow: Vec<String>,
pub(crate) family: Option<Family>,
pub(crate) method: Option<String>,
pub(crate) options: Vec<(String, String)>,
pub(crate) options: Vec<(String, String)>,
pub(crate) mapping: Option<Mapping>,
}

Expand Down Expand Up @@ -230,7 +230,6 @@ impl InterfaceBuilder {
self.options.retain(|(k, v)| !(k == key && v == value));
self
}


/// Builds the [`Interface`] instance.
///
Expand Down Expand Up @@ -275,7 +274,10 @@ mod tests {
.build();

assert_eq!(iface.options.len(), 1);
assert_eq!(iface.options[0], ("netmask".to_string(), "255.255.255.0".to_string()));
assert_eq!(
iface.options[0],
("netmask".to_string(), "255.255.255.0".to_string())
);
}

#[test]
Expand All @@ -287,10 +289,16 @@ mod tests {
.with_option("address", "192.168.1.52") // Duplicate address key with different value
.remove_option_value("address", "192.168.1.50") // Should remove only this address pair
.build();

assert_eq!(iface.options.len(), 3);
assert!(iface.options.contains(&("netmask".to_string(), "255.255.255.0".to_string())));
assert!(iface.options.contains(&("address".to_string(), "192.168.1.51".to_string())));
assert!(iface.options.contains(&("address".to_string(), "192.168.1.52".to_string())));
assert!(iface
.options
.contains(&("netmask".to_string(), "255.255.255.0".to_string())));
assert!(iface
.options
.contains(&("address".to_string(), "192.168.1.51".to_string())));
assert!(iface
.options
.contains(&("address".to_string(), "192.168.1.52".to_string())));
}
}
}
8 changes: 4 additions & 4 deletions src/interface/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,11 +8,11 @@
//! Refer to the `interfaces(5)` manual page for details on the file format.
pub mod family;
pub mod mapping;
pub mod interface_struct;
pub mod interface_builder;
pub mod interface_struct;
pub mod mapping;

pub use family::{Family, FamilyParseError};
pub use mapping::Mapping;
pub use interface_struct::Interface;
pub use interface_builder::InterfaceBuilder;
pub use interface_struct::Interface;
pub use mapping::Mapping;
6 changes: 3 additions & 3 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -99,11 +99,11 @@
//!
//! This project is licensed under the MIT License.
pub mod error;
pub mod interface;
pub mod network_interfaces;
mod parser;
pub mod error;

pub use network_interfaces::NetworkInterfaces;
pub use interface::{Interface, InterfaceBuilder, Family, Mapping};
pub use error::NetworkInterfacesError;
pub use interface::{Family, Interface, InterfaceBuilder, Mapping};
pub use network_interfaces::NetworkInterfaces;
7 changes: 3 additions & 4 deletions src/network_interfaces.rs
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
use crate::error::NetworkInterfacesError;
use crate::interface::Interface;
use crate::parser::Parser;
use crate::error::NetworkInterfacesError;
use std::collections::HashMap;
use std::fmt;
use std::fs;
use std::io::Write;
use std::path::{Path, PathBuf};
use std::time::SystemTime;
use std::fmt;

/// Represents the collection of network interfaces defined in an `interfaces(5)` file.
///
Expand Down Expand Up @@ -215,7 +215,7 @@ impl NetworkInterfaces {
))
}
};
let reloaded = NetworkInterfaces::load(&path)?;
let reloaded = NetworkInterfaces::load(path)?;
self.interfaces = reloaded.interfaces;
self.comments = reloaded.comments;
self.sources = reloaded.sources;
Expand Down Expand Up @@ -257,4 +257,3 @@ impl NetworkInterfaces {
self.interfaces.iter()
}
}

139 changes: 93 additions & 46 deletions src/parser.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
use crate::interface::{Family, Interface};
use crate::error::ParserError;
use crate::interface::{Family, Interface};
use std::collections::HashMap;

/// A parser for an `interfaces(5)` file.
Expand All @@ -8,6 +8,8 @@ use std::collections::HashMap;
/// and produce a collection of `Interface` instances.
pub struct Parser;

type ParseResult = Result<(HashMap<String, Interface>, Vec<String>, Vec<String>), ParserError>;

impl Parser {
/// Creates a new `Parser` instance.
pub fn new() -> Self {
Expand All @@ -24,17 +26,14 @@ impl Parser {
///
/// A `Result` containing a tuple `(interfaces, comments, sources)` if successful,
/// or a `ParserError` if parsing fails.
pub fn parse(
&self,
content: &str,
) -> Result<(HashMap<String, Interface>, Vec<String>, Vec<String>), ParserError> {
pub fn parse(&self, content: &str) -> ParseResult {
let mut interfaces = HashMap::new();
let mut lines = content.lines().enumerate().peekable();
let lines = content.lines().enumerate().peekable();
let mut current_interface: Option<Interface> = None;
let mut comments = Vec::new();
let mut sources = Vec::new();

while let Some((line_number, line)) = lines.next() {
for (line_number, line) in lines {
let line = line.trim();

// Collect comments at the top
Expand Down Expand Up @@ -107,10 +106,13 @@ impl Parser {
}
"iface" => {
// Start a new interface
let iface_name = tokens.get(1).ok_or_else(|| ParserError {
message: "Missing interface name in 'iface' stanza".to_string(),
line: Some(line_number + 1),
})?.to_string();
let iface_name = tokens
.get(1)
.ok_or_else(|| ParserError {
message: "Missing interface name in 'iface' stanza".to_string(),
line: Some(line_number + 1),
})?
.to_string();

// Remove existing interface if any
let existing_iface = interfaces.remove(&iface_name);
Expand Down Expand Up @@ -154,10 +156,7 @@ impl Parser {
let mut tokens = line.split_whitespace();
if let Some(option_name) = tokens.next() {
let option_value = tokens.collect::<Vec<&str>>().join(" ");
iface.options.push((
option_name.to_string(),
option_value,
));
iface.options.push((option_name.to_string(), option_value));
}
} else {
// Handle global options if needed
Expand Down Expand Up @@ -196,8 +195,13 @@ iface eth0
assert_eq!(iface.name, "eth0");
assert_eq!(iface.family, None);
assert_eq!(iface.method, None);
assert!(iface.options.contains(&("address".to_string(), "10.130.17.36/255.255.255.128".to_string())));
assert!(iface.options.contains(&("vrf".to_string(), "mgmt".to_string())));
assert!(iface.options.contains(&(
"address".to_string(),
"10.130.17.36/255.255.255.128".to_string()
)));
assert!(iface
.options
.contains(&("vrf".to_string(), "mgmt".to_string())));
}

#[test]
Expand All @@ -214,8 +218,12 @@ iface eth1 inet static
assert_eq!(iface.name, "eth1");
assert_eq!(iface.family, Some(Family::Inet));
assert_eq!(iface.method.as_deref(), Some("static"));
assert!(iface.options.contains(&("address".to_string(), "192.168.1.10".to_string())));
assert!(iface.options.contains(&("netmask".to_string(), "255.255.255.0".to_string())));
assert!(iface
.options
.contains(&("address".to_string(), "192.168.1.10".to_string())));
assert!(iface
.options
.contains(&("netmask".to_string(), "255.255.255.0".to_string())));
}

#[test]
Expand Down Expand Up @@ -257,8 +265,12 @@ iface wlan0 inet static
assert_eq!(wlan0_iface.auto, true);
assert_eq!(wlan0_iface.family, Some(Family::Inet));
assert_eq!(wlan0_iface.method.as_deref(), Some("static"));
assert!(wlan0_iface.options.contains(&("address".to_string(), "192.168.0.100".to_string())));
assert!(wlan0_iface.options.contains(&("netmask".to_string(), "255.255.255.0".to_string())));
assert!(wlan0_iface
.options
.contains(&("address".to_string(), "192.168.0.100".to_string())));
assert!(wlan0_iface
.options
.contains(&("netmask".to_string(), "255.255.255.0".to_string())));
}

#[test]
Expand Down Expand Up @@ -299,8 +311,12 @@ iface wlan0 inet static
assert_eq!(wlan0_iface.auto, true);
assert_eq!(wlan0_iface.family, Some(Family::Inet));
assert_eq!(wlan0_iface.method.as_deref(), Some("static"));
assert!(wlan0_iface.options.contains(&("address".to_string(), "192.168.0.100".to_string())));
assert!(wlan0_iface.options.contains(&("netmask".to_string(), "255.255.255.0".to_string())));
assert!(wlan0_iface
.options
.contains(&("address".to_string(), "192.168.0.100".to_string())));
assert!(wlan0_iface
.options
.contains(&("netmask".to_string(), "255.255.255.0".to_string())));
}

#[test]
Expand Down Expand Up @@ -337,23 +353,35 @@ iface vlan101
"#;
let parser = Parser::new();
let (interfaces, _comments, _sources) = parser.parse(content).unwrap();

assert_eq!(interfaces.len(), 4);

// Check 'swp54' interface
let swp54_iface = &interfaces["swp54"];
assert_eq!(swp54_iface.name, "swp54");
assert_eq!(swp54_iface.auto, true);
assert_eq!(swp54_iface.family, None);
assert_eq!(swp54_iface.method, None);
// Check options
assert!(swp54_iface.options.contains(&("bridge-access".to_string(), "199".to_string())));
assert!(swp54_iface.options.contains(&("mstpctl-bpduguard".to_string(), "yes".to_string())));
assert!(swp54_iface.options.contains(&("mstpctl-portadminedge".to_string(), "yes".to_string())));
assert!(swp54_iface.options.contains(&("mtu".to_string(), "9216".to_string())));
assert!(swp54_iface.options.contains(&("post-down".to_string(), "/some/script.sh".to_string())));
assert!(swp54_iface.options.contains(&("post-up".to_string(), "/some/script.sh".to_string())));

assert!(swp54_iface
.options
.contains(&("bridge-access".to_string(), "199".to_string())));
assert!(swp54_iface
.options
.contains(&("mstpctl-bpduguard".to_string(), "yes".to_string())));
assert!(swp54_iface
.options
.contains(&("mstpctl-portadminedge".to_string(), "yes".to_string())));
assert!(swp54_iface
.options
.contains(&("mtu".to_string(), "9216".to_string())));
assert!(swp54_iface
.options
.contains(&("post-down".to_string(), "/some/script.sh".to_string())));
assert!(swp54_iface
.options
.contains(&("post-up".to_string(), "/some/script.sh".to_string())));

// Check 'bridge' interface
let bridge_iface = &interfaces["bridge"];
assert_eq!(bridge_iface.name, "bridge");
Expand All @@ -362,32 +390,52 @@ iface vlan101
assert_eq!(bridge_iface.method, None);
// Check options
assert!(bridge_iface.options.contains(&("bridge-ports".to_string(), "swp1 swp2 swp3 swp4 swp5 swp6 swp7 swp8 swp9 swp10 swp11 swp12 swp13 swp14 swp15 swp16 swp17 swp18 swp19 swp20 swp21 swp22 swp23 swp24 swp31 swp32 swp33 swp34 swp35 swp36 swp37 swp38 swp39 swp40 swp41 swp42 swp43 swp44 swp45 swp46 swp47 swp48 swp49 swp50 swp51 swp52 swp53 swp54".to_string())));
assert!(bridge_iface.options.contains(&("bridge-pvid".to_string(), "1".to_string())));
assert!(bridge_iface.options.contains(&("bridge-vids".to_string(), "100-154 199".to_string())));
assert!(bridge_iface.options.contains(&("bridge-vlan-aware".to_string(), "yes".to_string())));

assert!(bridge_iface
.options
.contains(&("bridge-pvid".to_string(), "1".to_string())));
assert!(bridge_iface
.options
.contains(&("bridge-vids".to_string(), "100-154 199".to_string())));
assert!(bridge_iface
.options
.contains(&("bridge-vlan-aware".to_string(), "yes".to_string())));

// Check 'mgmt' interface
let mgmt_iface = &interfaces["mgmt"];
assert_eq!(mgmt_iface.name, "mgmt");
assert_eq!(mgmt_iface.auto, true);
assert_eq!(mgmt_iface.family, None);
assert_eq!(mgmt_iface.method, None);
// Check options
assert!(mgmt_iface.options.contains(&("address".to_string(), "127.0.0.1/8".to_string())));
assert!(mgmt_iface.options.contains(&("address".to_string(), "::1/128".to_string())));
assert!(mgmt_iface.options.contains(&("vrf-table".to_string(), "auto".to_string())));

assert!(mgmt_iface
.options
.contains(&("address".to_string(), "127.0.0.1/8".to_string())));
assert!(mgmt_iface
.options
.contains(&("address".to_string(), "::1/128".to_string())));
assert!(mgmt_iface
.options
.contains(&("vrf-table".to_string(), "auto".to_string())));

// Check 'vlan101' interface
let vlan101_iface = &interfaces["vlan101"];
assert_eq!(vlan101_iface.name, "vlan101");
assert_eq!(vlan101_iface.auto, true);
assert_eq!(vlan101_iface.family, None);
assert_eq!(vlan101_iface.method, None);
// Check options
assert!(vlan101_iface.options.contains(&("mtu".to_string(), "9216".to_string())));
assert!(vlan101_iface.options.contains(&("post-up".to_string(), "/some/script.sh".to_string())));
assert!(vlan101_iface.options.contains(&("vlan-id".to_string(), "101".to_string())));
assert!(vlan101_iface.options.contains(&("vlan-raw-device".to_string(), "bridge".to_string())));
assert!(vlan101_iface
.options
.contains(&("mtu".to_string(), "9216".to_string())));
assert!(vlan101_iface
.options
.contains(&("post-up".to_string(), "/some/script.sh".to_string())));
assert!(vlan101_iface
.options
.contains(&("vlan-id".to_string(), "101".to_string())));
assert!(vlan101_iface
.options
.contains(&("vlan-raw-device".to_string(), "bridge".to_string())));

// Check print/display formatting
// At the end of the test
Expand Down Expand Up @@ -434,6 +482,5 @@ iface vlan101
let output = output.trim();

assert_eq!(output, expected_output);

}
}
}

0 comments on commit 812066f

Please sign in to comment.