use std::{cell::RefCell, fmt::Display};
use quote::ToTokens;
use syn::{Error, Ident, Path, Result};
use tracing::{error, instrument};
#[derive(Debug)]
pub(crate) struct Ctx {
pub capi: Ident,
pub conv: Path,
pub util: Path,
pub error: Path,
pub err_ty: Path,
pub ext_err_ty: Path,
pub fn_prefix: Ident,
pub ty_prefix: Ident,
pub defs: Path,
pub hidden: Ident,
pub imports: Ident,
pub errs: RefCell<Errors>,
}
impl Ctx {
pub fn error(&self, tokens: impl ToTokens, msg: impl Display) {
self.errs.borrow_mut().error(tokens, msg);
}
pub fn push(&self, err: Error) {
self.errs.borrow_mut().push(err);
}
pub fn propagate(&mut self) -> Result<()> {
self.errs.borrow_mut().propagate()
}
}
#[derive(Debug, Default)]
pub(crate) struct Errors(Vec<Error>);
impl Errors {
#[instrument(skip_all)]
fn push(&mut self, err: Error) {
error!(%err);
self.0.push(err);
}
fn error(&mut self, tokens: impl ToTokens, msg: impl Display) {
self.push(Error::new_spanned(tokens, msg));
}
fn propagate(&mut self) -> Result<()> {
let mut iter = self.0.drain(..);
let mut all = match iter.next() {
Some(err) => err,
None => return Ok(()),
};
for err in iter {
all.combine(err);
}
Err(all)
}
#[cfg(test)]
pub(crate) fn clear(&mut self) {
self.0.clear();
}
}