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::conversion::{ErrorWith, SourceErr, ToStructError};
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 let msg = format!("comment proc error {} ", e);
46 WplCodeError::builder(WplCodeReason::Syntax)
47 .detail(msg)
48 .finish()
49 })?;
50
51 Ok(Self {
52 path,
53 code: pure_code.to_string(),
54 })
55 }
56 pub fn get_code(&self) -> &String {
57 &self.code
58 }
59 pub fn parse_pkg(&self) -> WplCodeResult<WplPackage> {
60 let package = wpl_package.parse(self.code.as_str()).map_err(|err| {
61 let msg = error_detail(err);
62 WplCodeError::builder(WplCodeReason::Syntax)
63 .detail(msg)
64 .finish()
65 })?;
66 Ok(package)
67 }
68 pub fn parse_rule(&self) -> WplCodeResult<WplPackage> {
69 let rule = wpl_rule.parse(self.code.as_str()).map_err(|err| {
70 let msg = error_detail(err);
71 WplCodeError::builder(WplCodeReason::Syntax)
72 .detail(msg)
73 .finish()
74 })?;
75 let mut target = WplPackage::default();
76 target.rules.push_back(rule);
77 Ok(target)
78 }
79 pub fn empty_ins() -> WplCodeResult<Self> {
80 WplCode::try_from((PathBuf::new(), ""))
81 }
82 pub fn is_empty(&self) -> bool {
83 self.code.is_empty()
84 }
85 pub fn load<P: AsRef<Path> + Clone>(wpl_file: P) -> WplCodeResult<Self> {
86 let mut buffer = Vec::with_capacity(10240);
87 let mut f = File::open(wpl_file.clone())
88 .source_err(WplCodeReason::core_conf(), "open wpl file")
90 .at(wpl_file.as_ref())?;
91 f.read_to_end(&mut buffer).expect("read conf file error");
93 let file_data = String::from_utf8(buffer).expect("conf file is not utf8");
94 let code = WplCode::build(PathBuf::from(wpl_file.as_ref()), file_data.as_str())?;
95 Ok(code)
96 }
97
98 pub fn mix_load<P: AsRef<Path> + Clone>(
99 arg_file: Option<P>,
100 src_rule: Option<String>,
101 ) -> WplCodeResult<Self> {
102 if let Some(rule) = src_rule {
103 let code = format!("rule cli {{ {} }}", rule);
104 return WplCode::try_from((PathBuf::from("src"), code.as_str()));
105 }
106 if let Some(rule_file) = arg_file {
107 return WplCode::load(rule_file);
108 }
109 Err(WplCodeReason::not_found_error()
110 .to_err()
111 .with_detail("miss wpl file"))
112 }
113}