vnetod/src/domain/switch.rs

137 lines
3.4 KiB
Rust

use std::cell::RefCell;
use std::io::{BufWriter, Read, Write};
use super::Section;
#[derive(Debug)]
pub enum Error {
ReadData,
WriteData,
}
pub struct Request<'args, R, W>
where
R: Read,
W: Write,
{
pub reader: RefCell<R>,
pub writer: W,
pub sections: &'args [String],
}
pub fn execute<R, W>(req: Request<R, W>) -> Result<(), Error>
where
R: Read,
W: Write,
{
let mut content = String::new();
req.reader
.borrow_mut()
.read_to_string(&mut content)
.map_err(|_| Error::ReadData)?;
let mut writer = BufWriter::new(req.writer);
let choose_sections = req
.sections
.iter()
.map(|s| Section::from(s.as_str()))
.collect::<Vec<_>>();
dbg!(&choose_sections);
let choose_namespaces = choose_sections
.iter()
.map(|s| s.namespace.clone())
.collect::<Vec<_>>();
let mut current_sections: Option<Vec<Section>> = None;
for line in content.split_inclusive('\n') {
let new_line = if is_section_end(line) {
current_sections = None;
line.to_string()
} else if let Some(section_info) = line.strip_prefix("### ") {
current_sections = section_info
.split_whitespace()
.next()
.map(|r| r.split(',').map(Section::from).collect());
line.to_string()
} else if let Some(cur_sections) = current_sections.clone() {
let trimmed_line = line.trim_start_matches(['#', ' ']);
if cur_sections.iter().any(|s| choose_sections.contains(s)) {
String::from(trimmed_line)
} else {
format!("# {}", trimmed_line)
}
} else {
line.to_string()
};
dbg!(line, &current_sections, &new_line);
writer
.write_all(new_line.as_bytes())
.map_err(|_| Error::WriteData)?;
}
writer.flush().map_err(|_| Error::WriteData)
}
fn is_section_end(line: &str) -> bool {
line.trim().is_empty()
}
#[cfg(test)]
mod tests {
use super::*;
use std::cell::RefCell;
use std::io::Cursor;
const BASE_ENV: &str = include_str!("../../test_data/base_env");
fn make_test(input: &str, expected_output: &str, sections: Vec<&str>) {
let reader = RefCell::new(Cursor::new(input));
let mut output_data = vec![];
let writer = Cursor::new(&mut output_data);
match execute(Request {
reader,
writer,
sections: &sections.into_iter().map(String::from).collect::<Vec<_>>(),
}) {
Ok(()) => {
let output = String::from_utf8(output_data).unwrap();
assert_eq!(
output.lines().collect::<Vec<_>>(),
expected_output.lines().collect::<Vec<_>>()
);
}
_ => unreachable!(),
}
}
#[test]
fn should_disable_all_sections() {
make_test(include_str!("../../test_data/all_env"), BASE_ENV, vec![]);
}
#[test]
fn should_enable_local_sections() {
make_test(
BASE_ENV,
include_str!("../../test_data/should_enable_local"),
vec!["local"],
);
}
#[test]
fn should_enable_staging_sections() {
make_test(
BASE_ENV,
include_str!("../../test_data/should_enable_staging"),
vec!["staging"],
);
}
}