use sexp::SourcePosition; use crate::asm::error::CrsnError; pub trait TryRemove { type Item; fn try_remove(&mut self, index: usize) -> Option; fn remove_or_err(&mut self, index: usize, pos: &SourcePosition, err: &'static str) -> Result; } impl TryRemove for Vec { type Item = T; fn try_remove(&mut self, index: usize) -> Option { if self.is_empty() { None } else { Some(self.remove(index)) } } fn remove_or_err(&mut self, index: usize, pos: &SourcePosition, err: &'static str) -> Result { match self.try_remove(index) { None => { Err(CrsnError::Parse(err.into(), pos.clone())) } Some(removed) => Ok(removed) } } } pub trait NextOrErr { fn next_or_err(&mut self, pos: SourcePosition, err: &'static str) -> Result; } impl> NextOrErr for K { fn next_or_err(&mut self, pos: SourcePosition, err: &'static str) -> Result { match self.next() { None => { Err(CrsnError::Parse(err.into(), pos)) } Some(removed) => Ok(removed) } } } pub trait ErrWithPos { fn err_pos(self, pos: &SourcePosition) -> Result; } impl ErrWithPos for Result { fn err_pos(self, pos: &SourcePosition) -> Result { match self { Ok(v) => Ok(v), Err(e) => Err(CrsnError::ParseOther(Box::new(e), pos.clone())) } } } pub trait ErrSetFile { fn err_file(self, file: u32) -> Result; } impl ErrSetFile for Result { /// Set file context in the error fn err_file(self, file: u32) -> Result { match self { Ok(v) => Ok(v), Err(CrsnError::Parse(a, p)) => Err(CrsnError::Parse(a, p.with_file(file))), Err(CrsnError::ParseOther(a, p)) => Err(CrsnError::ParseOther(a, p.with_file(file))), Err(CrsnError::Asm(a, p)) => Err(CrsnError::Asm(a, p.with_file(file))), Err(CrsnError::Sexp(mut se)) => { se.pos.file = file; Err(CrsnError::Sexp(se)) }, Err(other @ CrsnError::IOError(_)) => Err(other), } } }