use alloc::{format, string::String};
use proc_macro2::{Span, TokenStream as TokenStream2};
use std::{borrow::Cow, io::Error as IOError, path::Path};
use syn::Error as SynError;
use crate::PointTrack;
#[derive(Debug)]
pub enum LoadFileAndAutoMakeTreeErr<'a> {
ReadToString { err: IOError, path: Cow<'a, Path> },
ParseStr(SynError),
}
impl<'a> LoadFileAndAutoMakeTreeErr<'a> {
#[inline]
pub const fn read_to_string(err: IOError, path: Cow<'a, Path>) -> Self {
Self::ReadToString { err, path }
}
pub fn into_tt_err(self, span: Span) -> TokenStream2 {
match self {
Self::ReadToString { err, path } => {
let spath = format!("{path:?}"); let se = format!("{err:?}");
throw_sg_err! {
[span]: "Error loading file, err: '", #se, "', path: ", #spath, "."
}
}
Self::ParseStr(e) => {
let se = format!("{e:?}");
throw_sg_err! {
[span]: "Failed to convert to tree `tt`: '", #se, "'."
}
}
}
}
}
#[allow(dead_code)]
pub fn load_file_and_automake_tree<'path>(
path: &'path Path,
point_track: Option<&'_ mut PointTrack>,
prepare_file_str: impl FnOnce(&mut String),
) -> Result<Option<TokenStream2>, LoadFileAndAutoMakeTreeErr<'path>> {
load_file_and_automake_tree_with_fns(path, point_track, prepare_file_str, Ok, Err)
}
pub fn load_file_and_automake_tree_with_fns<'path, R>(
path: &'path Path,
point_track: Option<&mut PointTrack>,
prepare_file_str: impl FnOnce(&mut String),
next: impl FnOnce(Option<TokenStream2>) -> R,
err: impl FnOnce(LoadFileAndAutoMakeTreeErr<'path>) -> R,
) -> R {
let mut data = match std::fs::read_to_string(path) {
Ok(a) => a,
Err(e) => {
let path = path
.canonicalize()
.map_or_else(|_| Cow::Borrowed(path), Cow::Owned);
return err(LoadFileAndAutoMakeTreeErr::read_to_string(e, path));
}
};
if let Some(point_track) = point_track {
point_track.append_track_file(path);
}
if data.is_empty() {
return next(None);
}
prepare_file_str(&mut data);
match syn::parse_str(&data) {
Ok(a) => next(Some(a)),
Err(e) => err(LoadFileAndAutoMakeTreeErr::ParseStr(e)),
}
}