use crate::{panic, Any, Arc, BTreeMap, Data, Rc, Transaction, Value};
use serde::{Deserialize, Serialize};
#[derive(Serialize, Deserialize, Debug)]
#[non_exhaustive]
pub struct GenQuery {
pub sql: Arc<String>,
pub path: String,
pub params: BTreeMap<String, String>,
pub form: BTreeMap<String, String>,
pub cookies: BTreeMap<String, String>,
pub parts: Vec<Part>,
pub now: i64,
}
#[non_exhaustive]
pub struct GenResponse {
pub err: String,
pub status_code: u16,
pub headers: Vec<(String, String)>,
pub output: Vec<u8>,
}
#[non_exhaustive]
pub struct GenTransaction {
pub qy: GenQuery,
pub rp: GenResponse,
pub ext: Box<dyn Any + Send + Sync>,
}
#[derive(Serialize, Deserialize, Debug, Default)]
#[non_exhaustive]
pub struct Part {
pub name: String,
pub file_name: String,
pub content_type: String,
pub text: String,
pub data: Data,
}
impl GenTransaction {
pub fn new() -> Self {
let now = std::time::SystemTime::now()
.duration_since(std::time::SystemTime::UNIX_EPOCH)
.unwrap();
let now = now.as_micros() as i64;
let output = Vec::with_capacity(10000);
let headers = Vec::new();
let status_code = 200;
Self {
qy: GenQuery {
sql: Arc::new("EXEC web.Main()".to_string()),
path: String::new(),
params: BTreeMap::new(),
form: BTreeMap::new(),
cookies: BTreeMap::new(),
parts: Vec::new(),
now,
},
rp: GenResponse {
err: String::new(),
output,
status_code,
headers,
},
ext: Box::new(()),
}
}
fn push_str(&mut self, s: &str) {
self.rp.output.extend_from_slice(s.as_bytes());
}
}
impl Transaction for GenTransaction {
fn arg(&mut self, kind: i64, s: &str) -> Rc<String> {
let s = match kind {
0 => Some(&self.qy.path),
1 => self.qy.params.get(s),
2 => self.qy.form.get(s),
3 => self.qy.cookies.get(s),
_ => None,
};
let s = if let Some(s) = s { s } else { "" };
Rc::new(s.to_string())
}
fn status_code(&mut self, code: i64) {
self.rp.status_code = code as u16;
}
fn header(&mut self, name: &str, value: &str) {
self.rp.headers.push((name.to_string(), value.to_string()));
}
fn global(&self, kind: i64) -> i64 {
match kind {
0 => self.qy.now,
_ => panic!(),
}
}
fn selected(&mut self, values: &[Value]) {
for v in values {
match v {
Value::RcBinary(x) => {
self.rp.output.extend_from_slice(x);
}
Value::ArcBinary(x) => {
self.rp.output.extend_from_slice(x);
}
_ => {
self.push_str(&v.str());
}
}
}
}
fn set_error(&mut self, err: String) {
self.rp.err = err;
}
fn get_error(&mut self) -> String {
let result = self.rp.err.to_string();
self.rp.err = String::new();
result
}
fn file_attr(&mut self, k: i64, x: i64) -> Rc<String> {
let k = k as usize;
let result: &str = {
if k >= self.qy.parts.len() {
""
} else {
let p = &self.qy.parts[k];
match x {
0 => &p.name,
1 => &p.content_type,
2 => &p.file_name,
3 => &p.text,
_ => panic!(),
}
}
};
Rc::new(result.to_string())
}
fn file_content(&mut self, k: i64) -> Data {
self.qy.parts[k as usize].data.clone()
}
fn set_extension(&mut self, ext: Box<dyn Any + Send + Sync>) {
self.ext = ext;
}
fn get_extension(&mut self) -> Box<dyn Any + Send + Sync> {
std::mem::replace(&mut self.ext, Box::new(()))
}
}
impl Default for GenTransaction {
fn default() -> Self {
Self::new()
}
}