use xml::reader::XmlEvent; use yaserde::{YaDeserialize as YaDeserializeTrait, YaSerialize as YaSerializeTrait}; use yaserde_derive::{YaDeserialize, YaSerialize}; use std::collections::HashMap; use crate::xml_utils::MaybeString; #[derive(Default, PartialEq, Debug, YaSerialize, YaDeserialize)] pub struct Interfaces { pub interfaces: HashMap, } #[derive(Default, PartialEq, Debug, YaDeserialize, YaSerialize)] pub struct Interface { #[yaserde(rename = "if")] pub physical_interface_name: String, pub descr: String, pub enable: MaybeString, #[yaserde(rename = "spoofmac")] pub spoof_mac: Option, pub internal_dynamic: Option, pub ipaddr: Option, #[yaserde(rename = "blockpriv")] pub block_priv: Option, #[yaserde(rename = "blockbogons")] pub block_bogons: Option, pub lock: Option, #[yaserde(rename = "type")] pub r#type: Option, #[yaserde(rename = "virtual")] pub r#virtual: Option, pub subnet: Option, pub networks: Option, pub subnetv6: Option, pub ipaddrv6: Option, #[yaserde(rename = "track6-interface")] pub track6_interface: Option, #[yaserde(rename = "track6-prefix-id")] pub track6_prefix_id: Option, } pub trait MyDeserialize : YaDeserializeTrait {} pub trait MySerialize : YaSerializeTrait {} #[cfg(test)] mod test { use super::*; use pretty_assertions::assert_eq; #[test] fn should_deserialize_interfaces() { let interfaces = yaserde::de::from_str::(FULL_INTERFACES_XML).unwrap(); assert_eq!(interfaces.interfaces.len(), 6) } const FULL_INTERFACES_XML: &str = " pppoe0 WAN 1 1 1 1 pppoe em1 LAN 1 192.168.20.1 24 track6 0 1 Loopback 1 lo0 127.0.0.1 ::1 8 128 none 1 em5 backup_sync 1 1 10.10.5.1 24 1 WireGuard (Group) wireguard 1 1 group 1 1 openvpn OpenVPN group 1 "; } // impl YaSerializeTrait for Interfaces { // fn serialize( // &self, // writer: &mut yaserde::ser::Serializer, // ) -> Result<(), String> { // writer.write("Interfaces serializer TODO").map_err(|e| e.to_string()) // } // // fn serialize_attributes( // &self, // attributes: Vec, // namespace: xml::namespace::Namespace, // ) -> Result< // ( // Vec, // xml::namespace::Namespace, // ), // String, // > { // todo!() // } // } // // impl YaDeserializeTrait for Interfaces { // fn deserialize( // reader: &mut yaserde::de::Deserializer, // ) -> Result { // let mut interfaces = Interfaces::default(); // let mut current_interface_name = String::new(); // let mut current_interface = Interface::default(); // // let mut event = reader.next_event()?; // loop { // match event { // xml::reader::XmlEvent::EndElement { name } => { // println!( // "Handling EndElement {}, current_interface_name: {}", // name.local_name, current_interface_name // ); // println!("Peeking after EndElement {:?}", reader.peek()?); // if name.local_name == "interfaces" { // break; // } // todo!("Should not hit here"); // } // xml::reader::XmlEvent::StartElement { ref name, .. } => { // println!("Got start Element {:?}", name); // current_interface_name = name.local_name.clone(); // println!("About to deserialize interface from name {:?}", name); // // TODO store names // 'inner_iface: loop { // let peek = reader.peek()?; // println!("Peeking before forcing next event {:?}", peek); // // if let XmlEvent::EndElement { name } = peek { // // TODO save the interface name and struct in the hashmap // println!("Forcing next_event"); // reader.next_event()?; // // let peek = reader.peek()?; // println!("Peeking after next event deserializing {:?}", peek); // if let XmlEvent::EndElement { name } = peek { // println!("Got two EndElement in a row, breaking out of loop"); // break 'inner_iface; // } // } // println!("Peeking before deserializing {:?}", reader.peek()?); // let interface = ::deserialize(reader)?; // println!("Interface deserialized {:?}", interface); // println!("Peeking after deserializing {:?}", reader.peek()?); // } // println!( // "Done with inner interface, loop completed {:?}", // reader.peek()? // ); // } // xml::reader::XmlEvent::EndDocument => break, // _ => { // return Err( // "This Interfaces Deserializer does not support all XmlEvent types".into(), // ) // } // } // let peek = reader.peek()?; // // let read_next = true; // if let XmlEvent::EndElement { name } = peek { // if name.local_name == "interfaces" { // println!("Got endElement interfaces, not reading next event"); // break; // } // } // // if read_next { // event = reader.next_event()?; // } // println!("Outer loop got event {:?}", event); // println!("Outer loop got peek {:?}", reader.peek()?); // } // println!("Done with interfaces {:?}", interfaces); // println!("reader peeking shows {:?}", reader.peek()); // // Ok(interfaces) // } // }