#![cfg(all(direct_wasm, target_arch = "wasm32"))]
use js_sys::Array;
use wasm_bindgen::prelude::*;
#[wasm_bindgen(start)]
pub fn start() {
console_error_panic_hook::set_once();
}
#[wasm_bindgen]
pub fn detect(xml: &str) -> Option<String> {
crate::detect(xml).map(|id| id.message_name())
}
#[wasm_bindgen]
pub fn from_namespace(namespace: &str) -> Option<String> {
crate::from_namespace(namespace).map(|id| id.message_name())
}
#[wasm_bindgen]
pub fn mx_id(namespace_or_name: &str) -> Option<String> {
let id = crate::MxId::parse(namespace_or_name).ok()?;
Some(format!(
"{{\"messageName\":{},\"namespace\":{},\"businessArea\":{},\"functionality\":{},\"variant\":{},\"version\":{}}}",
js(&id.message_name()),
js(&id.namespace()),
js(id.business_area.code()),
js(&id.functionality),
js(&id.variant),
js(&id.version),
))
}
#[wasm_bindgen]
pub fn business_area_description(code: &str) -> Option<String> {
crate::BusinessArea::from_code(code).map(|a| a.description().to_string())
}
#[wasm_bindgen]
pub fn business_areas() -> Array {
crate::BusinessArea::ALL
.iter()
.map(|a| JsValue::from_str(a.code()))
.collect()
}
#[wasm_bindgen]
pub fn catalogue_contains(message_name: &str) -> bool {
crate::catalogue::contains(message_name)
}
#[wasm_bindgen]
pub fn namespace_of(message_name: &str) -> Option<String> {
crate::catalogue::from_message_name(message_name).map(|e| e.namespace.to_string())
}
#[wasm_bindgen]
pub fn business_area_of(message_name: &str) -> Option<String> {
crate::catalogue::from_message_name(message_name).map(|e| e.business_area.to_string())
}
#[wasm_bindgen]
pub fn has_model(message_name: &str) -> bool {
crate::catalogue::from_message_name(message_name)
.map(|e| e.has_model)
.unwrap_or(false)
}
#[wasm_bindgen]
pub fn catalogue_entry(message_name: &str) -> Option<String> {
let e = crate::catalogue::from_message_name(message_name)?;
Some(format!(
"{{\"messageName\":{},\"namespace\":{},\"businessArea\":{},\"hasModel\":{}}}",
js(e.message_name),
js(e.namespace),
js(e.business_area),
e.has_model,
))
}
#[wasm_bindgen]
pub fn catalogue_all() -> Array {
crate::catalogue::all()
.iter()
.map(|e| JsValue::from_str(e.message_name))
.collect()
}
#[wasm_bindgen]
pub fn parse_app_hdr(xml: &str) -> Option<String> {
crate::app_hdr::parse_business_header(xml).map(|h| json_header(&h))
}
#[wasm_bindgen]
pub fn build_app_hdr(
from: Option<String>,
to: Option<String>,
biz_msg_idr: Option<String>,
msg_def_idr: Option<String>,
cre_dt: Option<String>,
) -> String {
crate::app_hdr::BusinessHeader {
from,
to,
biz_msg_idr,
msg_def_idr,
cre_dt,
}
.to_app_hdr_xml()
}
#[wasm_bindgen]
pub fn extract_metadata(xml: &str) -> String {
json_metadata(&crate::metadata::extract(xml))
}
#[wasm_bindgen]
pub fn read_business_message(xml: &str) -> String {
let bm = crate::read_business_message(xml);
format!(
"{{\"messageName\":{},\"header\":{},\"metadata\":{}}}",
bm.id.map(|i| js(&i.message_name())).unwrap_or_else(|| "null".into()),
bm.header
.map(|h| json_header(&h))
.unwrap_or_else(|| "null".into()),
json_metadata(&bm.metadata),
)
}
#[wasm_bindgen]
pub fn node_text(xml: &str, path: &str) -> Option<String> {
let root = crate::MxNode::parse(xml)?;
let segs: Vec<&str> = path.split('/').filter(|s| !s.is_empty()).collect();
root.at(&segs).and_then(|n| n.text()).map(str::to_string)
}
#[wasm_bindgen]
pub fn node_find(xml: &str, local: &str) -> Option<String> {
let root = crate::MxNode::parse(xml)?;
root.find(local).and_then(|n| n.text()).map(str::to_string)
}
#[wasm_bindgen]
pub fn node_attr(xml: &str, path: &str, attr: &str) -> Option<String> {
let root = crate::MxNode::parse(xml)?;
let segs: Vec<&str> = path.split('/').filter(|s| !s.is_empty()).collect();
root.at(&segs).and_then(|n| n.attr(attr)).map(str::to_string)
}
#[wasm_bindgen]
pub fn node_find_attr(xml: &str, local: &str, attr: &str) -> Option<String> {
let root = crate::MxNode::parse(xml)?;
root.find(local).and_then(|n| n.attr(attr)).map(str::to_string)
}
#[wasm_bindgen]
pub fn node_to_json(xml: &str) -> Option<String> {
crate::MxNode::parse(xml).as_ref().map(json_node)
}
#[wasm_bindgen]
pub fn node_find_all(xml: &str, local: &str) -> Array {
match crate::MxNode::parse(xml) {
Some(root) => root
.find_all(local)
.into_iter()
.filter_map(|n| n.text())
.map(JsValue::from_str)
.collect(),
None => Array::new(),
}
}
fn js(s: &str) -> String {
let mut out = String::with_capacity(s.len() + 2);
out.push('"');
for c in s.chars() {
match c {
'"' => out.push_str("\\\""),
'\\' => out.push_str("\\\\"),
'\n' => out.push_str("\\n"),
'\r' => out.push_str("\\r"),
'\t' => out.push_str("\\t"),
c => out.push(c),
}
}
out.push('"');
out
}
fn jso(v: &Option<String>) -> String {
match v {
Some(s) => js(s),
None => "null".to_string(),
}
}
fn json_node(n: &crate::MxNode) -> String {
let mut out = String::from("{\"name\":");
out.push_str(&js(&n.name));
out.push_str(",\"value\":");
out.push_str(&jso(&n.value));
out.push_str(",\"attributes\":{");
for (i, (k, v)) in n.attributes.iter().enumerate() {
if i > 0 {
out.push(',');
}
out.push_str(&js(k));
out.push(':');
out.push_str(&js(v));
}
out.push_str("},\"children\":[");
for (i, c) in n.children.iter().enumerate() {
if i > 0 {
out.push(',');
}
out.push_str(&json_node(c));
}
out.push_str("]}");
out
}
fn json_header(h: &crate::app_hdr::BusinessHeader) -> String {
format!(
"{{\"from\":{},\"to\":{},\"bizMsgIdr\":{},\"msgDefIdr\":{},\"creDt\":{}}}",
jso(&h.from),
jso(&h.to),
jso(&h.biz_msg_idr),
jso(&h.msg_def_idr),
jso(&h.cre_dt),
)
}
fn json_metadata(m: &crate::metadata::MessageMetadata) -> String {
format!(
"{{\"messageId\":{},\"creationDateTime\":{},\"numberOfTransactions\":{},\"amount\":{},\"currency\":{},\"valueDate\":{}}}",
jso(&m.message_id),
jso(&m.creation_date_time),
jso(&m.number_of_transactions),
jso(&m.amount),
jso(&m.currency),
jso(&m.value_date),
)
}