1use crate::ir::NetworkConfig;
2use crate::profile::{detect_domain_mismatches, DeviceProfile};
3use crate::report::ConversionReport;
4
5pub trait ConfigParser {
7 type Error: std::fmt::Debug;
8
9 fn parse(&self, input: &str) -> Result<(NetworkConfig, ConversionReport), Self::Error>;
10
11 fn vendor_name(&self) -> &str;
12}
13
14pub trait ConfigRenderer {
16 type Error: std::fmt::Debug;
17
18 fn render(
19 &self,
20 config: &NetworkConfig,
21 report: &mut ConversionReport,
22 ) -> Result<String, Self::Error>;
23
24 fn vendor_name(&self) -> &str;
25}
26
27pub fn convert<P, R>(
29 parser: &P,
30 renderer: &R,
31 input: &str,
32) -> Result<ConversionOutput, ConvertError>
33where
34 P: ConfigParser,
35 R: ConfigRenderer,
36{
37 let (ir, mut report) = parser
38 .parse(input)
39 .map_err(|e| ConvertError::ParseError(format!("{:?}", e)))?;
40
41 let output = renderer
42 .render(&ir, &mut report)
43 .map_err(|e| ConvertError::RenderError(format!("{:?}", e)))?;
44
45 Ok(ConversionOutput {
46 config_text: output,
47 report,
48 })
49}
50
51pub fn convert_with_profile<P, R>(
59 parser: &P,
60 renderer: &R,
61 input: &str,
62 profile: DeviceProfile,
63) -> Result<ConversionOutput, ConvertError>
64where
65 P: ConfigParser,
66 R: ConfigRenderer,
67{
68 let (ir, mut report) = parser
69 .parse(input)
70 .map_err(|e| ConvertError::ParseError(format!("{:?}", e)))?;
71
72 report.domain_mismatches = detect_domain_mismatches(&ir, profile);
73
74 let output = renderer
75 .render(&ir, &mut report)
76 .map_err(|e| ConvertError::RenderError(format!("{:?}", e)))?;
77
78 Ok(ConversionOutput {
79 config_text: output,
80 report,
81 })
82}
83
84#[derive(Debug)]
85pub struct ConversionOutput {
86 pub config_text: String,
87 pub report: ConversionReport,
88}
89
90#[derive(Debug)]
91pub enum ConvertError {
92 ParseError(String),
93 RenderError(String),
94}
95
96impl std::fmt::Display for ConvertError {
97 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
98 match self {
99 ConvertError::ParseError(e) => write!(f, "Parse error: {}", e),
100 ConvertError::RenderError(e) => write!(f, "Render error: {}", e),
101 }
102 }
103}