1use std::fs::File;
2use std::io::Read;
3use std::path::{Path, PathBuf};
4
5use crate::ast::WplPackage;
6
7use crate::parser::error::{WplCodeError, WplCodeReason, WplCodeResult, error_detail};
8use crate::parser::wpl_pkg::wpl_package;
9use crate::parser::wpl_rule::wpl_rule;
10use crate::winnow::Parser;
11use derive_getters::Getters;
12use orion_error::{ErrorOwe, ErrorWith, ToStructError, UvsFrom};
13use wp_primitives::comment::CommentParser;
14
15#[derive(Debug, Clone, Getters)]
16pub struct WplCode {
17 path: PathBuf,
18 code: String,
19}
20
21impl TryFrom<(PathBuf, String)> for WplCode {
22 type Error = WplCodeError;
23 fn try_from(v: (PathBuf, String)) -> WplCodeResult<Self> {
24 Self::build(v.0, v.1.as_str())
25 }
26}
27
28impl TryFrom<(PathBuf, &str)> for WplCode {
29 type Error = WplCodeError;
30 fn try_from(v: (PathBuf, &str)) -> WplCodeResult<Self> {
31 Self::build(v.0, v.1)
32 }
33}
34impl TryFrom<&str> for WplCode {
35 type Error = WplCodeError;
36 fn try_from(v: &str) -> WplCodeResult<Self> {
37 Self::build(PathBuf::new(), v)
38 }
39}
40
41impl WplCode {
42 pub fn build(path: PathBuf, code: &str) -> WplCodeResult<Self> {
43 let mut in_code = code;
44 let pure_code = CommentParser::ignore_comment(&mut in_code).map_err(|e| {
45 WplCodeError::from(WplCodeReason::Syntax(format!("comment proc error {} ", e)))
46 })?;
47
48 Ok(Self {
49 path,
50 code: pure_code.to_string(),
51 })
52 }
53 pub fn get_code(&self) -> &String {
54 &self.code
55 }
56 pub fn parse_pkg(&self) -> WplCodeResult<WplPackage> {
57 let package = wpl_package
58 .parse(self.code.as_str())
59 .map_err(|err| WplCodeError::from(WplCodeReason::Syntax(error_detail(err))))?;
60 Ok(package)
61 }
62 pub fn parse_rule(&self) -> WplCodeResult<WplPackage> {
63 let rule = wpl_rule
64 .parse(self.code.as_str())
65 .map_err(|err| WplCodeError::from(WplCodeReason::Syntax(error_detail(err))))?;
66 let mut target = WplPackage::default();
67 target.rules.push_back(rule);
68 Ok(target)
69 }
70 pub fn empty_ins() -> WplCodeResult<Self> {
71 WplCode::try_from((PathBuf::new(), ""))
72 }
73 pub fn is_empty(&self) -> bool {
74 self.code.is_empty()
75 }
76 pub fn load<P: AsRef<Path> + Clone>(wpl_file: P) -> WplCodeResult<Self> {
77 let mut buffer = Vec::with_capacity(10240);
78 let mut f = File::open(wpl_file.clone())
79 .owe_conf()
81 .with(wpl_file.as_ref())?;
82 f.read_to_end(&mut buffer).expect("read conf file error");
84 let file_data = String::from_utf8(buffer).expect("conf file is not utf8");
85 let code = WplCode::build(PathBuf::from(wpl_file.as_ref()), file_data.as_str())?;
86 Ok(code)
87 }
88
89 pub fn mix_load<P: AsRef<Path> + Clone>(
90 arg_file: Option<P>,
91 src_rule: Option<String>,
92 ) -> WplCodeResult<Self> {
93 if let Some(rule) = src_rule {
94 let code = format!("rule cli {{ {} }}", rule);
95 return WplCode::try_from((PathBuf::from("src"), code.as_str()));
96 }
97 if let Some(rule_file) = arg_file {
98 return WplCode::load(rule_file);
99 }
100 Err(WplCodeReason::from_not_found()
101 .to_err()
102 .with_detail("miss wpl file"))
103 }
104}