1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
use std::sync::{Arc,RwLock};
use quick_xml::{
Reader
,events::Event
};
use semilattice_database::Database;
mod script;
use script::Script;
mod xml_util;
use xml_util::XmlAttr;
mod include;
pub use include::{IncludeAdaptor,IncludeLocal};
pub struct WildDocResult{
body:Vec<u8>
,options_json:String
}
impl WildDocResult{
pub fn body(&self)->&[u8]{
&self.body
}
pub fn options_json(&self)->&str{
&self.options_json
}
}
pub struct WildDoc<T:IncludeAdaptor>{
database:Arc<RwLock<Database>>
,default_include_adaptor:T
}
impl<T:IncludeAdaptor> WildDoc<T>{
pub fn new(
dir:&str
,default_include_adaptor:T
)->Result<Self,std::io::Error>{
Ok(Self{
database:Arc::new(RwLock::new(Database::new(dir)?))
,default_include_adaptor
})
}
pub fn run(&mut self,xml:&str,input_json:&str)->Result<WildDocResult,std::io::Error>{
let mut reader=Reader::from_str(xml);
loop{
match reader.read_event(){
Ok(Event::Start(e))=>{
if e.name().as_ref()==b"wd"{
let mut script=Script::new(
self.database.clone()
);
return script.parse_xml(input_json,&mut reader,&mut self.default_include_adaptor);
}
}
,_=>{}
}
}
}
pub fn run_specify_include_adaptor(&mut self,xml:&str,input_json:&str,index_adaptor:&mut impl IncludeAdaptor)->Result<WildDocResult,std::io::Error>{
let mut reader=Reader::from_str(xml);
loop{
match reader.read_event(){
Ok(Event::Start(e))=>{
if e.name().as_ref()==b"wd"{
let mut script=Script::new(
self.database.clone()
);
return script.parse_xml(input_json,&mut reader,index_adaptor);
}
}
,_=>{
return Ok(WildDocResult{
body:xml.into()
,options_json:"".to_string()
});
}
}
}
}
}
fn eval<'s>(scope: &mut v8::HandleScope<'s>,code: &str) -> Option<v8::Local<'s, v8::Value>> {
let scope = &mut v8::EscapableHandleScope::new(scope);
let source = v8::String::new(scope, code).unwrap();
let script = v8::Script::compile(scope, source, None).unwrap();
let r = script.run(scope);
r.map(|v| scope.escape(v))
}
fn eval_result(scope:&mut v8::HandleScope,value:&str)->String{
if let Some(v8_value)=v8::String::new(scope,value)
.and_then(|code|v8::Script::compile(scope, code, None))
.and_then(|v|v.run(scope))
.and_then(|v|v.to_string(scope))
{
v8_value.to_rust_string_lossy(scope)
}else{
"".to_string()
}
}
fn attr_parse_or_static(scope:&mut v8::HandleScope,attr:&XmlAttr,key:&str)->String{
let wdkey="wd:".to_owned()+key;
if let Some(value)=attr.get(&wdkey){
if let Ok(value)=std::str::from_utf8(value){
crate::eval_result(scope,value)
}else{
"".to_owned()
}
}else if let Some(value)=attr.get(key){
if let Ok(value)=std::str::from_utf8(value){
value
}else{
""
}.to_owned()
}else{
"".to_owned()
}
}