use cli_utils::BoxResult;
use std::collections::HashMap;
use std::fmt;
use std::io::BufRead;
use thiserror::Error;
#[derive(Error, Debug)]
#[error("Failed to parse key-value pair; it has to be of the form 'key=value', but was '{input}'")]
pub struct ParseError {
input: String,
}
impl ParseError {
fn new(input: &str) -> Self {
Self {
input: input.to_string(),
}
}
}
#[derive(Clone)]
pub struct PairBuf {
pub key: String,
pub value: String,
}
impl PairBuf {
pub fn parse(key_value: &str) -> std::result::Result<Self, ParseError> {
Ok(Pair::parse(key_value)?.to_pair_buf())
}
}
pub struct Pair<'t> {
pub key: &'t str,
pub value: &'t str,
}
impl fmt::Display for Pair<'_> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "'{}'='{}'", self.key, self.value)
}
}
impl<'t> Pair<'t> {
pub fn parse(key_value: &'t str) -> std::result::Result<Self, ParseError> {
let mut splitter = key_value.splitn(2, '=');
let key = splitter.next().ok_or_else(|| ParseError::new(key_value))?;
let value = splitter.next().ok_or_else(|| ParseError::new(key_value))?;
Ok(Pair { key, value })
}
#[must_use]
pub fn to_pair_buf(&self) -> PairBuf {
PairBuf {
key: self.key.to_owned(),
value: self.value.to_owned(),
}
}
}
pub fn parse_vars_file_reader(reader: impl BufRead) -> BoxResult<HashMap<String, String>> {
let iter = dotenvy::Iter::new(reader);
let vars: Result<HashMap<_, _>, _> = iter.into_iter().collect();
Ok(vars?)
}