diff --git a/irp/src/lib.rs b/irp/src/lib.rs index 2cb9007..a9c341e 100644 --- a/irp/src/lib.rs +++ b/irp/src/lib.rs @@ -13,12 +13,13 @@ mod inverse; mod message; mod parser; mod pronto; -pub mod protocols; +mod protocols; mod variants; pub use build_dfa::DFA; pub use build_nfa::NFA; pub use decoder::Decoder; +pub use protocols::Protocol; use num_rational::Rational64; use std::{collections::HashMap, fmt, rc::Rc}; diff --git a/irp/src/protocols.rs b/irp/src/protocols.rs index ae2b832..60b4b73 100644 --- a/irp/src/protocols.rs +++ b/irp/src/protocols.rs @@ -1,9 +1,15 @@ //! Parsing of IrpTransmogrifier's IrpProtocols.xml. use serde::Deserialize; -use std::{fs::File, io::BufReader, path::Path, str::FromStr}; +use std::{ + fs::File, + io::{self, BufReader}, + path::Path, + str::FromStr, +}; use xml::reader::{EventReader, XmlEvent}; +/// Entry in IrpTransmogrifier's IrpProtocols.xml. #[derive(Debug, Deserialize, PartialEq, Default)] pub struct Protocol { pub name: String, @@ -31,122 +37,123 @@ enum Element { RejectRepeatLess, } -/// Parsing IrpProtocols.xml file -#[allow(dead_code)] -pub fn parse(path: &Path) -> Vec { - let file = File::open(path).unwrap(); - let file = BufReader::new(file); +impl Protocol { + /// Parse IrpTransmogrifier's IrpProtocols.xml. + pub fn parse(path: &Path) -> io::Result> { + let file = File::open(path)?; + let file = BufReader::new(file); - let parser = EventReader::new(file); - let mut protocols: Vec = Vec::new(); - let mut protocol = None; - let mut element = Element::None; + let parser = EventReader::new(file); + let mut protocols: Vec = Vec::new(); + let mut protocol = None; + let mut element = Element::None; - for e in parser { - match e { - Ok(XmlEvent::StartElement { - name, attributes, .. - }) => match name.local_name.as_ref() { - "protocol" => { - if attributes.len() == 1 && attributes[0].name.local_name == "name" { - protocol = Some(Protocol { - name: attributes[0].value.to_owned(), - decodable: true, - absolute_tolerance: 100, - relative_tolerance: 0.3, - minimum_leadout: 20000, - ..Default::default() - }); - } else { - panic!("missing name attribute"); + for e in parser { + match e { + Ok(XmlEvent::StartElement { + name, attributes, .. + }) => match name.local_name.as_ref() { + "protocol" => { + if attributes.len() == 1 && attributes[0].name.local_name == "name" { + protocol = Some(Protocol { + name: attributes[0].value.to_owned(), + decodable: true, + absolute_tolerance: 100, + relative_tolerance: 0.3, + minimum_leadout: 20000, + ..Default::default() + }); + } else { + panic!("missing name attribute"); + } } - } - "irp" => { - element = Element::Irp; - } - "parameter" => { - for attr in attributes { - match attr.name.local_name.as_ref() { - "prefer_over" => { - element = Element::PreferOver; + "irp" => { + element = Element::Irp; + } + "parameter" => { + for attr in attributes { + match attr.name.local_name.as_ref() { + "prefer_over" => { + element = Element::PreferOver; + } + "absolute-tolerance" => { + element = Element::AbsoluteTolerance; + } + "relative-tolerance" => { + element = Element::RelativeTolerance; + } + "decodable" => { + element = Element::Decodable; + } + "decode-only" => { + element = Element::DecodeOnly; + } + "alt_name" => { + element = Element::AlternateName; + } + "minimum-leadout" => { + element = Element::MinimumLeadout; + } + "reject_repeatless" => { + element = Element::RejectRepeatLess; + } + _ => (), + } + } + } + _ => (), + }, + Ok(XmlEvent::CData(data)) => { + if let Some(protocol) = &mut protocol { + match element { + Element::Irp => { + protocol.irp = data; + } + Element::AlternateName => { + protocol.alt_name.push(data); } - "absolute-tolerance" => { - element = Element::AbsoluteTolerance; + Element::PreferOver => { + protocol.prefer_over.push(data); } - "relative-tolerance" => { - element = Element::RelativeTolerance; + Element::Decodable => { + protocol.decodable = bool::from_str(&data).unwrap(); } - "decodable" => { - element = Element::Decodable; + Element::DecodeOnly => { + protocol.decode_only = bool::from_str(&data).unwrap(); } - "decode-only" => { - element = Element::DecodeOnly; + Element::RejectRepeatLess => { + protocol.reject_repeatess = bool::from_str(&data).unwrap(); } - "alt_name" => { - element = Element::AlternateName; + Element::AbsoluteTolerance => { + protocol.absolute_tolerance = u32::from_str(&data).unwrap(); } - "minimum-leadout" => { - element = Element::MinimumLeadout; + Element::RelativeTolerance => { + protocol.relative_tolerance = f32::from_str(&data).unwrap(); } - "reject_repeatless" => { - element = Element::RejectRepeatLess; + Element::MinimumLeadout => { + protocol.minimum_leadout = u32::from_str(&data).unwrap(); } - _ => (), + Element::None => (), } } + + element = Element::None; } - _ => (), - }, - Ok(XmlEvent::CData(data)) => { - if let Some(protocol) = &mut protocol { - match element { - Element::Irp => { - protocol.irp = data; - } - Element::AlternateName => { - protocol.alt_name.push(data); - } - Element::PreferOver => { - protocol.prefer_over.push(data); - } - Element::Decodable => { - protocol.decodable = bool::from_str(&data).unwrap(); + Ok(XmlEvent::EndElement { name }) => { + if name.local_name == "protocol" { + if let Some(protocol) = protocol { + protocols.push(protocol); } - Element::DecodeOnly => { - protocol.decode_only = bool::from_str(&data).unwrap(); - } - Element::RejectRepeatLess => { - protocol.reject_repeatess = bool::from_str(&data).unwrap(); - } - Element::AbsoluteTolerance => { - protocol.absolute_tolerance = u32::from_str(&data).unwrap(); - } - Element::RelativeTolerance => { - protocol.relative_tolerance = f32::from_str(&data).unwrap(); - } - Element::MinimumLeadout => { - protocol.minimum_leadout = u32::from_str(&data).unwrap(); - } - Element::None => (), + protocol = None; } } - - element = Element::None; - } - Ok(XmlEvent::EndElement { name }) => { - if name.local_name == "protocol" { - if let Some(protocol) = protocol { - protocols.push(protocol); - } - protocol = None; + Err(e) => { + panic!("Error: {e}"); } + _ => {} } - Err(e) => { - panic!("Error: {e}"); - } - _ => {} } - } - protocols + Ok(protocols) + } } diff --git a/irp/tests/tests.rs b/irp/tests/tests.rs index eb73a82..b7dc68f 100644 --- a/irp/tests/tests.rs +++ b/irp/tests/tests.rs @@ -1,7 +1,4 @@ -use irp::{ - protocols::{parse, Protocol}, - Decoder, Event, InfraredData, Irp, Message, Options, Vartable, -}; +use irp::{Decoder, Event, InfraredData, Irp, Message, Options, Protocol, Vartable}; use irptransmogrifier::{create_jvm, IrpTransmogrifierRender}; use itertools::Itertools; use rand::Rng; @@ -266,9 +263,10 @@ fn vars() { #[test] fn parse_all_of_them() { - let protocols = parse(&PathBuf::from( + let protocols = Protocol::parse(&PathBuf::from( "tests/IrpTransmogrifier/src/main/resources/IrpProtocols.xml", - )); + )) + .unwrap(); let mut broken = 0; let mut total = 0; @@ -327,9 +325,10 @@ fn compare_with_rounding(l: &[u32], r: &[u32]) -> bool { #[test] fn compare_encode_to_transmogrifier() { - let mut protocols = parse(&PathBuf::from( + let mut protocols = Protocol::parse(&PathBuf::from( "tests/IrpTransmogrifier/src/main/resources/IrpProtocols.xml", - )); + )) + .unwrap(); let mut total_tests = 0; let mut fails = 0; @@ -424,9 +423,10 @@ fn compare_encode_to_transmogrifier() { #[test] fn decode_all() { - let protocols = parse(&PathBuf::from( + let protocols = Protocol::parse(&PathBuf::from( "tests/IrpTransmogrifier/src/main/resources/IrpProtocols.xml", - )); + )) + .unwrap(); let mut total_tests = 0; let mut fails = 0;