1#![cfg_attr(docsrs, feature(doc_cfg))]
2#![doc = include_str!("../README.md")]
3
4use melodium_core::{executive::*, *};
5use melodium_macro::{check, mel_data, mel_function, mel_package, mel_treatment};
6use std::sync::Arc;
7
8pub mod value;
9
10#[mel_data(traits(ToString TryToString TryToBool TryToI64 TryToU64 TryToF64 Display))]
18#[derive(Debug, Clone, Serialize)]
19pub struct Json(pub serde_json::Value);
20
21impl ToString for Json {
22 fn to_string(&self) -> string {
23 self.0.to_string()
24 }
25}
26
27impl TryToString for Json {
28 fn try_to_string(&self) -> Option<string> {
29 if let Json(serde_json::Value::String(s)) = self {
30 Some(s.clone())
31 } else {
32 None
33 }
34 }
35}
36
37impl TryToBool for Json {
38 fn try_to_bool(&self) -> Option<bool> {
39 if let Json(serde_json::Value::Bool(b)) = self {
40 Some(*b)
41 } else {
42 None
43 }
44 }
45}
46
47impl TryToI64 for Json {
48 fn try_to_i64(&self) -> Option<i64> {
49 if let Json(serde_json::Value::Number(num)) = self {
50 num.as_i64()
51 } else {
52 None
53 }
54 }
55}
56
57impl TryToU64 for Json {
58 fn try_to_u64(&self) -> Option<u64> {
59 if let Json(serde_json::Value::Number(num)) = self {
60 num.as_u64()
61 } else {
62 None
63 }
64 }
65}
66
67impl TryToF64 for Json {
68 fn try_to_f64(&self) -> Option<f64> {
69 if let Json(serde_json::Value::Number(num)) = self {
70 num.as_f64()
71 } else {
72 None
73 }
74 }
75}
76
77impl Display for Json {
78 fn display(&self, f: &mut core::fmt::Formatter<'_>) -> Result<(), core::fmt::Error> {
79 write!(f, "{}", serde_json::ser::to_string_pretty(&self.0).unwrap())
80 }
81}
82
83#[mel_function]
85pub fn to_json(text: string) -> Option<Json> {
86 serde_json::from_str::<serde_json::Value>(&text)
87 .ok()
88 .map(|json| Json(json))
89}
90
91#[mel_treatment(
96 input text Stream<string>
97 output json Stream<Option<Json>>
98 output error Stream<Option<string>>
99)]
100pub async fn to_json() {
101 'main: while let Ok(text) = text
102 .recv_many()
103 .await
104 .map(|values| TryInto::<Vec<string>>::try_into(values).unwrap())
105 {
106 for t in text {
107 let result = serde_json::from_str::<serde_json::Value>(&t);
108 match result {
109 Ok(json_value) => {
110 if let (Err(_), Err(_)) = futures::join!(
111 json.send_one(Some(Arc::new(Json(json_value)) as Arc<dyn Data>).into()),
112 error.send_one(Option::<string>::None.into())
113 ) {
114 break 'main;
115 }
116 }
117 Err(err) => {
118 if let (Err(_), Err(_)) = futures::join!(
119 json.send_one(Option::<Arc<dyn Data>>::None.into()),
120 error.send_one(Some(err.to_string()).into())
121 ) {
122 break 'main;
123 }
124 }
125 }
126 }
127 }
128}
129
130#[mel_treatment(
134 input {content(json)} text Stream<string>
135 output is_json Stream<bool>
136)]
137pub async fn validate() {
138 while let Ok(text) = text
139 .recv_many()
140 .await
141 .map(|values| TryInto::<Vec<string>>::try_into(values).unwrap())
142 {
143 check!(
144 is_json
145 .send_many(
146 text.iter()
147 .map(|t| match serde_json::from_str::<serde::de::IgnoredAny>(t) {
148 Ok(_) => true,
149 Err(_) => false,
150 })
151 .collect::<VecDeque<_>>()
152 .into()
153 )
154 .await
155 );
156 }
157}
158
159mel_package!();