use std::{
ffi::{OsStr, OsString},
mem,
};
use crate::{
native_int_str::{NativeCharInt, NativeIntStr, to_native_int_representation},
string_parser::{Chunk, Error, StringParser},
};
pub struct StringExpander<'a> {
parser: StringParser<'a>,
output: Vec<NativeCharInt>,
}
impl<'a> StringExpander<'a> {
pub fn new(input: &'a NativeIntStr) -> Self {
Self {
parser: StringParser::new(input),
output: Vec::default(),
}
}
pub fn new_at(input: &'a NativeIntStr, pos: usize) -> Self {
Self {
parser: StringParser::new_at(input, pos),
output: Vec::default(),
}
}
pub fn get_parser(&self) -> &StringParser<'a> {
&self.parser
}
pub fn get_parser_mut(&mut self) -> &mut StringParser<'a> {
&mut self.parser
}
pub fn peek(&self) -> Result<char, Error> {
self.parser.peek()
}
pub fn skip_one(&mut self) -> Result<(), Error> {
self.get_parser_mut().consume_one_ascii_or_all_non_ascii()?;
Ok(())
}
pub fn get_peek_position(&self) -> usize {
self.get_parser().get_peek_position()
}
pub fn take_one(&mut self) -> Result<(), Error> {
let chunks = self.parser.consume_one_ascii_or_all_non_ascii()?;
for chunk in chunks {
match chunk {
Chunk::InvalidEncoding(invalid) => self.output.extend(invalid),
Chunk::ValidSingleIntChar((_c, ni)) => self.output.push(ni),
}
}
Ok(())
}
pub fn put_one_char(&mut self, c: char) {
let os_str = OsString::from(c.to_string());
self.put_string(os_str);
}
pub fn put_string<S: AsRef<OsStr>>(&mut self, os_str: S) {
let native = to_native_int_representation(os_str.as_ref());
self.output.extend(&*native);
}
pub fn put_native_string(&mut self, n_str: &NativeIntStr) {
self.output.extend(n_str);
}
pub fn take_collected_output(&mut self) -> Vec<NativeCharInt> {
mem::take(&mut self.output)
}
}