use super::_line::{format_value, is_valid_key, parse_line};
use super::error::InvalidKeyError;
pub fn set(content: &str, key: &str, value: &str) -> Result<String, InvalidKeyError> {
if !is_valid_key(key) {
return Err(InvalidKeyError::new(key));
}
let assignment = format!("{key}={}", format_value(value));
let mut out = String::with_capacity(content.len() + assignment.len() + 1);
let mut replaced = false;
for line in content.split_inclusive('\n') {
match parse_line(line) {
Some((k, _)) if k == key => {
if !replaced {
out.push_str(&assignment);
out.push_str(line_ending(line));
replaced = true;
}
}
_ => out.push_str(line),
}
}
if !replaced {
if !out.is_empty() && !out.ends_with('\n') {
out.push('\n');
}
out.push_str(&assignment);
out.push('\n');
}
Ok(out)
}
fn line_ending(line: &str) -> &'static str {
if line.ends_with("\r\n") {
"\r\n"
} else if line.ends_with('\n') {
"\n"
} else {
""
}
}
#[cfg(test)]
#[path = "set.test.rs"]
mod tests;
#[cfg(test)]
#[path = "set.spec.rs"]
mod spec;