use crate::new_less::context::ParseContext;
use crate::new_less::file::{path_join, readfile};
use crate::new_less::filenode::FileNode;
use crate::new_less::loc::LocMap;
use crate::new_less::node::StyleNode;
use crate::new_less::var::VarRuleNode;
use crate::new_less::var_node::VarNode;
use serde::ser::SerializeStruct;
use serde::{Serialize, Serializer};
use std::cell::RefCell;
use std::collections::HashSet;
use std::fmt::{Debug, Formatter};
use std::path::Path;
use std::rc::{Rc, Weak};
#[derive(Clone)]
pub struct FileInfo {
pub disk_location: String,
pub origin_txt_content: String,
pub origin_charlist: Vec<char>,
pub block_node: Vec<StyleNode>,
pub locmap: Option<LocMap>,
pub context: ParseContext,
pub self_weak: FileWeakRef,
pub import_files: Vec<FileNode>,
pub modules: bool,
pub class_selector_collect: HashSet<String>,
pub hash_perfix: String,
}
pub type FileRef = Rc<RefCell<FileInfo>>;
pub type FileWeakRef = Option<Weak<RefCell<FileInfo>>>;
impl Serialize for FileInfo {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: Serializer,
{
let mut state = serializer.serialize_struct("FileInfo", 3)?;
state.serialize_field("disk_location", &self.disk_location)?;
state.serialize_field("origin_txt_content", &self.disk_location)?;
state.serialize_field("block_node", &self.block_node)?;
state.serialize_field("import_file", &self.import_files)?;
state.end()
}
}
impl Debug for FileInfo {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
f.debug_struct("FileInfo")
.field("disk_location", &self.disk_location)
.field("block_node", &self.block_node)
.field("import_file", &self.import_files)
.finish()
}
}
impl FileInfo {
pub fn toheap(self) -> FileRef {
let heapobj = Rc::new(RefCell::new(self));
heapobj.borrow_mut().self_weak = Some(Rc::downgrade(&heapobj));
heapobj
}
pub fn collect_vars(&self) -> Vec<VarNode> {
let mut varlist = vec![];
for filenode in &self.import_files {
for item in &filenode.info.borrow().block_node {
if let StyleNode::Var(VarRuleNode::Var(var)) = &item {
varlist.push(var.clone());
}
}
let mut child_var_list = filenode.info.borrow().collect_vars();
varlist.append(&mut child_var_list)
}
varlist
}
pub fn get_loc_by_content(chars: &[char]) -> LocMap {
LocMap::new(chars)
}
pub fn get_dir(path_value: &str) -> Result<String, String> {
let path = Path::new(path_value);
if path.is_file() {
Ok(path.parent().unwrap().to_str().unwrap().to_string())
} else if path.is_dir() {
Ok(path_value.to_string())
} else {
Err(format!(
"path type is file or dir please check {}",
path_value
))
}
}
pub fn is_relative_path(txt: &str) -> bool {
let path = Path::new(txt);
path.is_relative()
}
pub fn resolve(filepath: String, include_path: &Vec<String>) -> Result<(String, String), String> {
return if Self::is_relative_path(&filepath) {
let mut abs_path: Option<String> = None;
let mut failpath = vec![];
let mut content: Option<String> = None;
for basepath in include_path {
let temp_path = path_join(basepath.as_str(), filepath.as_str());
match readfile(temp_path.as_str()) {
Ok(res) => {
content = Some(res);
abs_path = Some(temp_path.clone());
break;
}
Err(_) => failpath.push(temp_path.clone()),
}
}
return if let Some(match_path) = abs_path {
Ok((match_path, content.unwrap()))
} else {
Err(format!(
"Nothings File is find in cmdpath and inculdepath,{}",
failpath.join(";")
))
};
} else {
let res = readfile(filepath.as_str())?;
Ok((filepath.clone(), res))
};
}
}