rhai_rusp/lib.rs
1//! `rhai-rusp` offers `Rhai` bindings for the `Rust` `USP` (or
2//! [`rusp`](https://crates.io/crates/rusp) library to for comfortable introspection, creation, and
3//! manipulation of [`USP`](https://usp.technology) protocol communication primitives.
4use rhai::def_package;
5use rhai::{
6 plugin::{
7 combine_with_exported_module, export_module, mem, Dynamic, EvalAltResult, FnNamespace,
8 FuncRegistration, ImmutableString, Module, NativeCallContext, PluginFunc, RhaiResult,
9 TypeId,
10 },
11 Array, Blob, Map, Variant,
12};
13use rusp_lib::usp::{Body, Msg};
14use rusp_lib::usp_builder;
15use rusp_lib::usp_record::{self, Record};
16
17/// Evaluate a Rhai script in the context of the `rusp` package and return a supported type, like
18/// [`Record`], [`Msg`] or [`String`]
19///
20/// E.g. you can do:
21/// ```
22/// let script = r#"
23/// // Rhai script
24/// rusp::record_builder()
25/// .with_to_id("proto::to")
26/// .with_from_id("proto::from")
27/// .as_disconnect_record("Bye", 0)
28/// .build()
29/// "#;
30/// let record = rhai_rusp::eval_rusp::<rusp_lib::usp_record::Record>(script).unwrap();
31/// ```
32///
33/// # Errors
34///
35/// This function will return `Err` containing a textual description of the encountered error if
36/// the provided Rhai script fails to evaluate.
37pub fn eval_rusp<T>(str: &str) -> Result<T, String>
38where
39 T: Variant + Clone,
40{
41 use rhai::{packages::Package, Engine};
42
43 let mut engine = Engine::new();
44 engine.register_static_module("rusp", RuspPackage::new().as_shared_module());
45
46 engine.eval::<T>(str).map_err(|e| e.to_string())
47}
48
49/// Supply Rusp [`Record`] generation functionality
50///
51/// The general usage pattern from within a Rhai script is straight forward: First you obtain a
52/// builder type by calling `rusp::record_builder()`, then add data using any of the available
53/// builder methods and in the end obtain the [`Record`] structure by calling `build()`.
54///
55/// Here's a full example:
56/// ```
57/// # use rusp_lib::usp_record::{mod_Record::OneOfrecord_type,MQTTConnectRecord,mod_MQTTConnectRecord::MQTTVersion,Record};
58/// // Rhai script
59/// # let script = r#"
60/// rusp::record_builder()
61/// .with_version("1.3")
62/// .with_to_id("proto::to")
63/// .with_from_id("proto::from")
64/// .as_mqtt_connect_record("V5", "/topic")
65/// .build()
66/// # "#;
67/// # let record = rhai_rusp::eval_rusp::<Record>(script).unwrap();
68/// # assert_eq!(record.to_id, "proto::to");
69/// # assert_eq!(record.from_id, "proto::from");
70/// # assert_eq!(record.record_type, OneOfrecord_type::mqtt_connect(MQTTConnectRecord { subscribed_topic: "/topic".into(), version: MQTTVersion::V5 }));
71/// ```
72#[export_module]
73pub mod rhai_rusp_record {
74 use usp_builder::RecordBuilder;
75
76 /// Sets up a new USP `RecordBuilder`
77 #[must_use]
78 pub const fn record_builder() -> RecordBuilder {
79 RecordBuilder::new()
80 }
81
82 /// Sets the version of the USP standard being used by the [`Record`]
83 /// ```
84 /// # use rusp_lib::usp_record::Record;
85 /// // Rhai script
86 /// # let script = r#"
87 /// rusp::record_builder()
88 /// .with_version("1.3")
89 /// .build()
90 /// # "#;
91 /// # let record = rhai_rusp::eval_rusp::<Record>(script);
92 /// ```
93 #[rhai_fn(global)]
94 #[must_use]
95 pub fn with_version(builder: RecordBuilder, version: &str) -> RecordBuilder {
96 builder.with_version(version.into())
97 }
98
99 /// Sets the recipient endpoint id of the [`Record`]
100 /// ```
101 /// # use rusp_lib::usp_record::Record;
102 /// // Rhai script
103 /// # let script = r#"
104 /// rusp::record_builder()
105 /// .with_to_id("proto::controller")
106 /// .build()
107 /// # "#;
108 /// # let record = rhai_rusp::eval_rusp::<Record>(script);
109 /// ```
110 #[rhai_fn(global)]
111 #[must_use]
112 pub fn with_to_id(builder: RecordBuilder, id: &str) -> RecordBuilder {
113 builder.with_to_id(id.into())
114 }
115
116 /// Sets the sender endpoint id of the [`Record`]
117 /// ```
118 /// # use rusp_lib::usp_record::Record;
119 /// // Rhai script
120 /// # let script = r#"
121 /// rusp::record_builder()
122 /// .with_from_id("proto::agent")
123 /// .build()
124 /// # "#;
125 /// # let record = rhai_rusp::eval_rusp::<Record>(script);
126 /// ```
127 #[rhai_fn(global)]
128 #[must_use]
129 pub fn with_from_id(builder: RecordBuilder, id: &str) -> RecordBuilder {
130 builder.with_from_id(id.into())
131 }
132
133 /// Assigns the provided [`Msg`] as the "no session context" payload of the [`Record`]
134 /// ```
135 /// # use rusp_lib::usp_record::{mod_Record::OneOfrecord_type, NoSessionContextRecord, Record};
136 ///
137 /// // Rhai script
138 /// # let script = r#"
139 /// let body = rusp::get_builder()
140 /// .with_params(["Device."])
141 /// .build();
142 /// let msg = rusp::msg_builder()
143 /// .with_msg_id("Foo")
144 /// .with_body(body)
145 /// .build();
146 /// rusp::record_builder()
147 /// .with_version("1.2")
148 /// .with_to_id("proto::to")
149 /// .with_from_id("proto::from")
150 /// .with_no_session_context_payload(msg)
151 /// .build()
152 /// # "#;
153 /// # let record = rhai_rusp::eval_rusp::<Record>(script).unwrap();
154 ///
155 /// # assert_eq!(record.version, "1.2");
156 /// # assert_eq!(record.to_id, "proto::to");
157 /// # assert_eq!(record.from_id, "proto::from");
158 /// # assert!(matches!(record.record_type, OneOfrecord_type::no_session_context(NoSessionContextRecord { .. })));
159 /// ```
160 #[rhai_fn(global)]
161 #[must_use]
162 pub fn with_no_session_context_payload(builder: RecordBuilder, payload: Msg) -> RecordBuilder {
163 builder.with_no_session_context_payload(&payload)
164 }
165
166 /// Designates the [`Record`] to be of type WebSocketConnectRecord
167 /// ```
168 /// # use rusp_lib::usp_record::{mod_Record::OneOfrecord_type,WebSocketConnectRecord,Record};
169 /// // Rhai script
170 /// # let script = r#"
171 /// rusp::record_builder()
172 /// .with_version("1.3")
173 /// .with_to_id("proto::to")
174 /// .with_from_id("proto::from")
175 /// .as_websocket_connect_record()
176 /// .build()
177 /// # "#;
178 /// # let record = rhai_rusp::eval_rusp::<Record>(script).unwrap();
179 /// # assert_eq!(record.to_id, "proto::to");
180 /// # assert_eq!(record.from_id, "proto::from");
181 /// # assert_eq!(record.record_type, OneOfrecord_type::websocket_connect(WebSocketConnectRecord { }));
182 /// ```
183 #[rhai_fn(global)]
184 #[must_use]
185 pub fn as_websocket_connect_record(builder: RecordBuilder) -> RecordBuilder {
186 builder.as_websocket_connect_record()
187 }
188
189 /// Designates the [`Record`] to be of type MQTTConnectRecord
190 /// ```
191 /// # use rusp_lib::usp_record::{mod_Record::OneOfrecord_type,MQTTConnectRecord,mod_MQTTConnectRecord::MQTTVersion,Record};
192 /// // Rhai script
193 /// # let script = r#"
194 /// rusp::record_builder()
195 /// .with_to_id("proto::to")
196 /// .with_from_id("proto::from")
197 /// .as_mqtt_connect_record("V5", "/topic")
198 /// .build()
199 /// # "#;
200 /// # let record = rhai_rusp::eval_rusp::<Record>(script).unwrap();
201 /// # assert_eq!(record.to_id, "proto::to");
202 /// # assert_eq!(record.from_id, "proto::from");
203 /// # assert_eq!(record.record_type, OneOfrecord_type::mqtt_connect(MQTTConnectRecord { subscribed_topic: "/topic".into(), version: MQTTVersion::V5 }));
204 /// ```
205 ///
206 /// # Errors
207 ///
208 /// This function will return `Err` if the provided `version` is not `V3_1_1` or `V5`.
209 #[rhai_fn(global, return_raw)]
210 pub fn as_mqtt_connect_record(
211 builder: RecordBuilder,
212 version: &str,
213 subscribed_topic: &str,
214 ) -> Result<RecordBuilder, Box<EvalAltResult>> {
215 use usp_record::mod_MQTTConnectRecord::MQTTVersion;
216
217 let version = match version {
218 "V3_1_1" | "V5" => MQTTVersion::from(version),
219 _ => return Err("MQTT version must be either V3_1_1 or V5".into()),
220 };
221
222 Ok(builder.as_mqtt_connect_record(version, subscribed_topic.into()))
223 }
224
225 /// Designates the [`Record`] to be of type STOMPConnectRecord
226 /// ```
227 /// # use rusp_lib::usp_record::{mod_Record::OneOfrecord_type,STOMPConnectRecord,mod_STOMPConnectRecord::STOMPVersion,Record};
228 /// // Rhai script
229 /// # let script = r#"
230 /// rusp::record_builder()
231 /// .with_to_id("proto::to")
232 /// .with_from_id("proto::from")
233 /// .as_stomp_connect_record("V1_2", "/dest")
234 /// .build()
235 /// # "#;
236 /// # let record = rhai_rusp::eval_rusp::<Record>(script).unwrap();
237 /// # assert_eq!(record.to_id, "proto::to");
238 /// # assert_eq!(record.from_id, "proto::from");
239 /// # assert_eq!(record.record_type, OneOfrecord_type::stomp_connect(STOMPConnectRecord { subscribed_destination: "/dest".into(), version: STOMPVersion::V1_2 }));
240 /// ```
241 ///
242 /// # Errors
243 ///
244 /// This function will return `Err` if the provided `version` is not `V1_2`.
245 #[rhai_fn(global, return_raw)]
246 pub fn as_stomp_connect_record(
247 builder: RecordBuilder,
248 version: &str,
249 subscribed_destination: &str,
250 ) -> Result<RecordBuilder, Box<EvalAltResult>> {
251 use usp_record::mod_STOMPConnectRecord::STOMPVersion;
252
253 let version = match version {
254 "V1_2" => STOMPVersion::from(version),
255 _ => return Err("STOMP version must be V1_2".into()),
256 };
257
258 Ok(builder.as_stomp_connect_record(version, subscribed_destination.into()))
259 }
260
261 /// Designates the [`Record`] to be of type DisconnectRecord
262 /// ```
263 /// # use rusp_lib::usp_record::{mod_Record::OneOfrecord_type,DisconnectRecord,Record};
264 /// // Rhai script
265 /// # let script = r#"
266 /// rusp::record_builder()
267 /// .with_to_id("proto::to")
268 /// .with_from_id("proto::from")
269 /// .as_disconnect_record("Bye", 0)
270 /// .build()
271 /// # "#;
272 /// # let record = rhai_rusp::eval_rusp::<Record>(script).unwrap();
273 /// # assert_eq!(record.to_id, "proto::to");
274 /// # assert_eq!(record.from_id, "proto::from");
275 /// # assert_eq!(record.record_type, OneOfrecord_type::disconnect(DisconnectRecord { reason: "Bye".into(), reason_code: 0 }));
276 /// ```
277 #[rhai_fn(global)]
278 #[must_use]
279 pub fn as_disconnect_record(
280 builder: RecordBuilder,
281 reason: &str,
282 reason_code: i64,
283 ) -> RecordBuilder {
284 builder.as_disconnect_record(reason.into(), u32::try_from(reason_code).unwrap_or(7003))
285 }
286
287 /// Designates the [`Record`] to be of type UDSConnectRecord
288 /// ```
289 /// # use rusp_lib::usp_record::{mod_Record::OneOfrecord_type,UDSConnectRecord,Record};
290 /// // Rhai script
291 /// # let script = r#"
292 /// rusp::record_builder()
293 /// .with_to_id("proto::to")
294 /// .with_from_id("proto::from")
295 /// .as_uds_connect_record()
296 /// .build()
297 /// # "#;
298 /// # let record = rhai_rusp::eval_rusp::<Record>(script).unwrap();
299 /// # assert_eq!(record.to_id, "proto::to");
300 /// # assert_eq!(record.from_id, "proto::from");
301 /// # assert_eq!(record.record_type, OneOfrecord_type::uds_connect(UDSConnectRecord {}));
302 /// ```
303 #[rhai_fn(global)]
304 #[must_use]
305 pub fn as_uds_connect_record(builder: RecordBuilder) -> RecordBuilder {
306 builder.as_uds_connect_record()
307 }
308
309 /// Turns the builder into a [`Record`] structure
310 ///
311 /// # Errors
312 ///
313 /// This function will return `Err` if the provided `builder` was set up with incomplete or
314 /// incorrect data.
315 #[rhai_fn(global, return_raw)]
316 pub fn build(builder: RecordBuilder) -> Result<Record, Box<EvalAltResult>> {
317 Ok(builder.build().map_err(|e| e.to_string())?)
318 }
319}
320
321/// Supply Rusp [`Msg`] generation functionality
322/// ```
323/// // Rhai script
324/// # let script = r#"
325/// rusp::msg_builder()
326/// .with_msg_id("Foo")
327/// .build()
328/// "#;
329/// # let msg = rhai_rusp::eval_rusp::<rusp_lib::usp::Msg>(script);
330///
331/// // This will result in an `Err`:
332/// // Err("Runtime error: Cannot produce USP Msg without msg_body (line 8, position 10)")
333/// # assert!(msg.is_err());
334/// ```
335///
336/// ```
337/// // Rhai script
338/// # let script = r#"
339/// let body = rusp::get_builder()
340/// .with_params(["Device."])
341/// .build();
342/// rusp::msg_builder()
343/// .with_body(body)
344/// .build()
345/// "#;
346/// # let msg = rhai_rusp::eval_rusp::<rusp_lib::usp::Msg>(script);
347///
348/// // This will result in an `Err`:
349/// // Err("Runtime error: Cannot produce USP Msg without msg_id (line 8, position 10)")
350/// # assert!(msg.is_err());
351/// ```
352///
353/// ```
354/// // Rhai script
355/// # let script = r#"
356/// let body = rusp::get_builder()
357/// .with_params(["Device."])
358/// .build();
359/// rusp::msg_builder()
360/// .with_msg_id("Foo")
361/// .with_body(body)
362/// .build()
363/// "#;
364/// # let msg = rhai_rusp::eval_rusp::<rusp_lib::usp::Msg>(script).unwrap();
365/// # assert!(!msg.is_error());
366/// # assert!(msg.is_request());
367/// ```
368#[export_module]
369pub mod rhai_rusp_msg {
370 use usp_builder::MsgBuilder;
371
372 /// Sets up a new USP `MsgBuilder`
373 #[must_use]
374 pub const fn msg_builder() -> MsgBuilder {
375 MsgBuilder::new()
376 }
377
378 /// Sets the `msg_id` of the [`Msg`]
379 /// ```
380 /// # use rusp_lib::usp::Msg;
381 /// // Rhai script
382 /// # let script = r#"
383 /// rusp::msg_builder()
384 /// .with_msg_id("Foo")
385 /// .build()
386 /// # "#;
387 /// # let msg = rhai_rusp::eval_rusp::<Msg>(script);
388 /// ```
389 #[rhai_fn(global)]
390 #[must_use]
391 pub fn with_msg_id(builder: MsgBuilder, msg_id: &str) -> MsgBuilder {
392 builder.with_msg_id(msg_id.into())
393 }
394
395 /// Sets the `body` of the [`Msg`]
396 /// ```
397 /// # use rusp_lib::usp::Msg;
398 /// // Rhai script
399 /// # let script = r#"
400 /// let body = rusp::get_builder()
401 /// .with_params(["Device."])
402 /// .build();
403 /// rusp::msg_builder()
404 /// .with_msg_id("Foo")
405 /// .with_body(body)
406 /// .build()
407 /// # "#;
408 /// # let msg = rhai_rusp::eval_rusp::<Msg>(script);
409 /// ```
410 #[rhai_fn(global)]
411 #[must_use]
412 pub fn with_body(builder: MsgBuilder, body: Body) -> MsgBuilder {
413 builder.with_body(body)
414 }
415
416 /// Turns the builder into a [`Msg`] structure
417 ///
418 /// # Errors
419 ///
420 /// This function will return `Err` if the provided `builder` was set up with incomplete or
421 /// incorrect data.
422 #[rhai_fn(global, return_raw)]
423 pub fn build(builder: MsgBuilder) -> Result<Msg, Box<EvalAltResult>> {
424 Ok(builder.build().map_err(|e| e.to_string())?)
425 }
426}
427
428/// Supply Rusp Delete Message functionality
429/// ```
430/// // Rhai script
431/// # let script = r#"
432/// let body = rusp::delete_builder()
433/// .with_allow_partial(true)
434/// .with_obj_paths(["Device.Foo.1.", "Device.Bar.2"])
435/// .build();
436/// rusp::msg_builder()
437/// .with_msg_id("Foo")
438/// .with_body(body)
439/// .build()
440/// # "#;
441/// # let msg = rhai_rusp::eval_rusp::<rusp_lib::usp::Msg>(script).unwrap();
442/// # assert!(!msg.is_error());
443/// # assert!(msg.is_request());
444/// # assert!(!msg.is_response());
445/// ```
446#[export_module]
447pub mod rhai_rusp_delete {
448 use usp_builder::DeleteBuilder;
449
450 /// Sets up a new USP `DeleteBuilder`
451 #[must_use]
452 pub const fn delete_builder() -> DeleteBuilder {
453 DeleteBuilder::new()
454 }
455
456 #[rhai_fn(global)]
457 #[must_use]
458 pub const fn with_allow_partial(builder: DeleteBuilder, allow_partial: bool) -> DeleteBuilder {
459 builder.with_allow_partial(allow_partial)
460 }
461
462 #[rhai_fn(global)]
463 #[must_use]
464 pub fn with_obj_paths(builder: DeleteBuilder, obj_paths: Array) -> DeleteBuilder {
465 builder.with_obj_paths(obj_paths.into_iter().map(Dynamic::cast).collect())
466 }
467
468 /// Turns the builder into a [`Body`] structure
469 ///
470 /// # Errors
471 ///
472 /// This function will return `Err` if the provided `builder` was set up with incomplete or
473 /// incorrect data.
474 #[rhai_fn(global, return_raw)]
475 pub fn build(builder: DeleteBuilder) -> Result<Body, Box<EvalAltResult>> {
476 Ok(builder.build().map_err(|e| e.to_string())?)
477 }
478}
479
480/// Supply Rusp DeleteResp Message functionality
481/// ```
482/// // Rhai script
483/// # let script = r#"
484/// let deleted_objs = [
485/// rusp::deleteresp_oper_failure("Foo", 7004, ""),
486/// rusp::deleteresp_oper_success("Foo.Bar.", ["Foo.Bar.1", "Foo.Bar.2."], [["Foo.Bar.3.", 7004, ""]])
487/// ];
488/// let body = rusp::deleteresp_builder()
489/// .with_deleted_obj_results(deleted_objs)
490/// .build();
491/// rusp::msg_builder()
492/// .with_msg_id("Foo")
493/// .with_body(body)
494/// .build()
495/// # "#;
496/// # let msg = rhai_rusp::eval_rusp::<rusp_lib::usp::Msg>(script).unwrap();
497/// # assert!(!msg.is_error());
498/// # assert!(!msg.is_request());
499/// # assert!(msg.is_response());
500/// ```
501#[export_module]
502pub mod rhai_rusp_deleteresp {
503 use usp_builder::{
504 DeleteRespBuilder, DeleteRespUnaffectedPathError, DeletedObjectResultsBuilder,
505 };
506
507 /// Sets up a new USP `DeleteRespBuilder`
508 #[must_use]
509 pub const fn deleteresp_builder() -> DeleteRespBuilder {
510 DeleteRespBuilder::new()
511 }
512
513 #[rhai_fn(global)]
514 #[must_use]
515 pub fn with_deleted_obj_results(
516 builder: DeleteRespBuilder,
517 deleted_obj_results: Array,
518 ) -> DeleteRespBuilder {
519 let deleted_obj_results = deleted_obj_results.into_iter().map(Dynamic::cast).collect();
520 builder.with_deleted_obj_results(deleted_obj_results)
521 }
522
523 #[rhai_fn(global)]
524 #[must_use]
525 pub fn deleteresp_oper_failure(
526 requested_path: &str,
527 err_code: i64,
528 err_msg: &str,
529 ) -> DeletedObjectResultsBuilder {
530 DeletedObjectResultsBuilder::new(requested_path.into()).set_failure(
531 u32::try_from(err_code).unwrap_or(7003),
532 (!err_msg.is_empty()).then_some(err_msg.into()),
533 )
534 }
535
536 /// # Errors
537 ///
538 /// This function will return `Err` if the provided `unaffected_path_errs` cannot be converted
539 /// into an array of type `(String, u32, String)` or `affected_paths` cannot be converted into
540 /// an array of type `String`.
541 #[rhai_fn(global, return_raw)]
542 pub fn deleteresp_oper_success(
543 requested_path: &str,
544 affected_paths: Array,
545 unaffected_path_errs: Array,
546 ) -> Result<DeletedObjectResultsBuilder, Box<EvalAltResult>> {
547 let affected_paths = affected_paths
548 .into_iter()
549 .map(|p| {
550 p.try_cast::<String>()
551 .ok_or_else(|| "Expected to have an array of Strings".into())
552 })
553 .collect::<Result<Vec<String>, Box<EvalAltResult>>>()?;
554
555 let unaffected_path_errs = unaffected_path_errs
556 .into_iter()
557 .map(|p| {
558 let el = p.try_cast::<Array>()
559 .ok_or_else(|| "Expected to have an array of arrays [param: &str, err_code: u32, err_msg: &str]".to_string())?;
560 let el0 = el.first()
561 .and_then(|el| el.clone().try_cast::<String>())
562 .ok_or_else(|| "param (#1) needs to be a string".to_string())?;
563 let el1 = el.get(1)
564 .and_then(|el| el.clone().try_cast::<i64>())
565 .ok_or_else(|| "err_code (#2) needs to be a u32".to_string())?;
566 let el2 = el.get(2)
567 .and_then(|el| el.clone().try_cast::<String>())
568 .ok_or_else(|| "err_msg (#3) needs to be a string".to_string())?;
569
570 Ok(DeleteRespUnaffectedPathError{unaffected_path: el0, err_code: u32::try_from(el1).unwrap_or(7003), err_msg: el2 })
571 })
572 .collect::<Result<Vec<DeleteRespUnaffectedPathError>, Box<EvalAltResult>>>()?;
573
574 Ok(DeletedObjectResultsBuilder::new(requested_path.into())
575 .set_success(affected_paths, unaffected_path_errs))
576 }
577
578 /// Turns the builder into a [`Body`] structure
579 ///
580 /// # Errors
581 ///
582 /// This function will return `Err` if the provided `builder` was set up with incomplete or
583 /// incorrect data.
584 #[rhai_fn(global, return_raw)]
585 pub fn build(builder: DeleteRespBuilder) -> Result<Body, Box<EvalAltResult>> {
586 Ok(builder.build().map_err(|e| e.to_string())?)
587 }
588}
589
590/// Supply Rusp Deregister Message functionality
591/// ```
592/// // Rhai script
593/// # let script = r#"
594/// let body = rusp::deregister_builder()
595/// .with_req_paths(["Device.Foo.", "Device.Bar."])
596/// .build();
597/// rusp::msg_builder()
598/// .with_msg_id("Foo")
599/// .with_body(body)
600/// .build()
601/// # "#;
602/// # let msg = rhai_rusp::eval_rusp::<rusp_lib::usp::Msg>(script).unwrap();
603/// # assert!(!msg.is_error());
604/// # assert!(msg.is_request());
605/// # assert!(!msg.is_response());
606/// ```
607#[export_module]
608pub mod rhai_rusp_deregister {
609 use usp_builder::DeregisterBuilder;
610
611 /// Sets up a new USP `DeregisterBuilder`
612 #[must_use]
613 pub const fn deregister_builder() -> DeregisterBuilder {
614 DeregisterBuilder::new()
615 }
616
617 #[rhai_fn(global)]
618 #[must_use]
619 pub fn with_req_paths(builder: DeregisterBuilder, paths: Array) -> DeregisterBuilder {
620 builder.with_paths(paths.into_iter().map(Dynamic::cast).collect())
621 }
622
623 /// Turns the builder into a [`Body`] structure
624 ///
625 /// # Errors
626 ///
627 /// This function will return `Err` if the provided `builder` was set up with incomplete or
628 /// incorrect data.
629 #[rhai_fn(global, return_raw)]
630 pub fn build(builder: DeregisterBuilder) -> Result<Body, Box<EvalAltResult>> {
631 Ok(builder.build().map_err(|e| e.to_string())?)
632 }
633}
634
635/// Supply Rusp DeregistertResp Message functionality
636/// ```
637/// // Rhai script
638/// # let script = r#"
639/// let regpathres = [];
640/// regpathres += rusp::deregistered_path_result_builder("Device.")
641/// .set_failure(7002, "Look, a fancy error");
642/// regpathres += rusp::deregistered_path_result_builder("Device.")
643/// .set_success(["Device.Foo."]);
644/// let body = rusp::deregisterresp_builder()
645/// .with_deregistered_path_results(regpathres)
646/// .build();
647/// rusp::msg_builder()
648/// .with_msg_id("Foo")
649/// .with_body(body)
650/// .build()
651/// # "#;
652/// # let msg = rhai_rusp::eval_rusp::<rusp_lib::usp::Msg>(script).unwrap();
653/// # assert!(!msg.is_error());
654/// # assert!(!msg.is_request());
655/// # assert!(msg.is_response());
656/// ```
657#[export_module]
658pub mod rhai_rusp_deregisterresp {
659 use usp_builder::{DeregisterRespBuilder, DeregisteredPathResultBuilder};
660
661 /// Sets up a new USP `DeregisterRespBuilder`
662 #[must_use]
663 pub const fn deregisterresp_builder() -> DeregisterRespBuilder {
664 DeregisterRespBuilder::new()
665 }
666
667 #[rhai_fn(global)]
668 #[must_use]
669 pub fn with_deregistered_path_results(
670 builder: DeregisterRespBuilder,
671 deregistered_path_results: Array,
672 ) -> DeregisterRespBuilder {
673 builder.with_deregistered_path_results(
674 deregistered_path_results
675 .into_iter()
676 .map(Dynamic::cast)
677 .collect(),
678 )
679 }
680
681 /// Turns the builder into a [`Body`] structure
682 ///
683 /// # Errors
684 ///
685 /// This function will return `Err` if the provided `builder` was set up with incomplete or
686 /// incorrect data.
687 #[rhai_fn(global, return_raw)]
688 pub fn build(builder: DeregisterRespBuilder) -> Result<Body, Box<EvalAltResult>> {
689 Ok(builder.build().map_err(|e| e.to_string())?)
690 }
691
692 #[must_use]
693 pub fn deregistered_path_result_builder(requested_path: &str) -> DeregisteredPathResultBuilder {
694 DeregisteredPathResultBuilder::new(requested_path.into())
695 }
696
697 #[rhai_fn(global, name = "set_failure")]
698 #[must_use]
699 pub fn deregisterresp_set_failure(
700 builder: DeregisteredPathResultBuilder,
701 err_code: i64,
702 err_msg: &str,
703 ) -> DeregisteredPathResultBuilder {
704 builder.set_failure(
705 u32::try_from(err_code).unwrap_or(7003),
706 (!err_msg.is_empty()).then_some(err_msg.into()),
707 )
708 }
709
710 #[rhai_fn(global, name = "set_success")]
711 #[must_use]
712 pub fn deregisterresp_set_success(
713 builder: DeregisteredPathResultBuilder,
714 deregistered_path: Array,
715 ) -> DeregisteredPathResultBuilder {
716 builder.set_success(deregistered_path.into_iter().map(Dynamic::cast).collect())
717 }
718}
719
720/// Supply Rusp Register Message functionality
721/// ```
722/// // Rhai script
723/// # let script = r#"
724/// let body = rusp::register_builder()
725/// .with_allow_partial(false)
726/// .with_reg_paths(["Device.Foo.", "Device.Bar."])
727/// .build();
728/// rusp::msg_builder()
729/// .with_msg_id("Foo")
730/// .with_body(body)
731/// .build()
732/// # "#;
733/// # let msg = rhai_rusp::eval_rusp::<rusp_lib::usp::Msg>(script).unwrap();
734/// # assert!(!msg.is_error());
735/// # assert!(msg.is_request());
736/// # assert!(!msg.is_response());
737/// ```
738#[export_module]
739pub mod rhai_rusp_register {
740 use usp_builder::RegisterBuilder;
741
742 /// Sets up a new USP `RegisterBuilder`
743 #[must_use]
744 pub const fn register_builder() -> RegisterBuilder {
745 RegisterBuilder::new()
746 }
747
748 #[rhai_fn(global)]
749 #[must_use]
750 pub const fn with_allow_partial(
751 builder: RegisterBuilder,
752 allow_partial: bool,
753 ) -> RegisterBuilder {
754 builder.with_allow_partial(allow_partial)
755 }
756
757 #[rhai_fn(global)]
758 #[must_use]
759 pub fn with_reg_paths(builder: RegisterBuilder, req_paths: Array) -> RegisterBuilder {
760 builder.with_reg_paths(req_paths.into_iter().map(Dynamic::cast).collect())
761 }
762
763 /// Turns the builder into a [`Body`] structure
764 ///
765 /// # Errors
766 ///
767 /// This function will return `Err` if the provided `builder` was set up with incomplete or
768 /// incorrect data.
769 #[rhai_fn(global, return_raw)]
770 pub fn build(builder: RegisterBuilder) -> Result<Body, Box<EvalAltResult>> {
771 Ok(builder.build().map_err(|e| e.to_string())?)
772 }
773}
774
775/// Supply Rusp RegisterResp Message functionality
776/// ```
777/// // Rhai script
778/// # let script = r#"
779/// let regpathres = [];
780/// regpathres += rusp::registered_path_result_builder("Device.")
781/// .set_failure(7002, "Look, a fancy error");
782/// regpathres += rusp::registered_path_result_builder("Device.")
783/// .set_success("Device.Foo.");
784/// let body = rusp::registerresp_builder()
785/// .with_registered_path_results(regpathres)
786/// .build();
787/// rusp::msg_builder()
788/// .with_msg_id("Foo")
789/// .with_body(body)
790/// .build()
791/// # "#;
792/// # let msg = rhai_rusp::eval_rusp::<rusp_lib::usp::Msg>(script).unwrap();
793/// # assert!(!msg.is_error());
794/// # assert!(!msg.is_request());
795/// # assert!(msg.is_response());
796/// ```
797#[export_module]
798pub mod rhai_rusp_registerresp {
799 use usp_builder::{RegisterRespBuilder, RegisteredPathResultBuilder};
800
801 /// Sets up a new USP `RegisterRespBuilder`
802 #[must_use]
803 pub const fn registerresp_builder() -> RegisterRespBuilder {
804 RegisterRespBuilder::new()
805 }
806
807 #[rhai_fn(global)]
808 #[must_use]
809 pub fn with_registered_path_results(
810 builder: RegisterRespBuilder,
811 registered_path_results: Array,
812 ) -> RegisterRespBuilder {
813 builder.with_registered_path_results(
814 registered_path_results
815 .into_iter()
816 .map(Dynamic::cast)
817 .collect(),
818 )
819 }
820
821 /// Turns the builder into a [`Body`] structure
822 ///
823 /// # Errors
824 ///
825 /// This function will return `Err` if the provided `builder` was set up with incomplete or
826 /// incorrect data.
827 #[rhai_fn(global, return_raw)]
828 pub fn build(builder: RegisterRespBuilder) -> Result<Body, Box<EvalAltResult>> {
829 Ok(builder.build().map_err(|e| e.to_string())?)
830 }
831
832 #[must_use]
833 pub fn registered_path_result_builder(requested_path: &str) -> RegisteredPathResultBuilder {
834 RegisteredPathResultBuilder::new(requested_path.into())
835 }
836
837 #[rhai_fn(global, name = "set_failure")]
838 #[must_use]
839 pub fn registerresp_set_failure(
840 builder: RegisteredPathResultBuilder,
841 err_code: i64,
842 err_msg: &str,
843 ) -> RegisteredPathResultBuilder {
844 builder.set_failure(
845 u32::try_from(err_code).unwrap_or(7003),
846 (!err_msg.is_empty()).then_some(err_msg.into()),
847 )
848 }
849
850 #[rhai_fn(global, name = "set_success")]
851 #[must_use]
852 pub fn registerresp_set_success(
853 builder: RegisteredPathResultBuilder,
854 registered_path: &str,
855 ) -> RegisteredPathResultBuilder {
856 builder.set_success(registered_path.into())
857 }
858}
859
860/// Supply Rusp Set Message functionality
861/// ```
862/// // Rhai script
863/// # let script = r#"
864/// let update_obj = rusp::set_update_object_builder("Device.IP.Interface.")
865/// .with_param_settings([["Foo", "Bar", true],["Whee", "What?", false]]);
866/// let body = rusp::set_builder()
867/// .with_allow_partial(true)
868/// .with_update_objs([update_obj])
869/// .build();
870/// rusp::msg_builder()
871/// .with_msg_id("Foo")
872/// .with_body(body)
873/// .build()
874/// # "#;
875/// # let msg = rhai_rusp::eval_rusp::<rusp_lib::usp::Msg>(script).unwrap();
876/// # assert!(!msg.is_error());
877/// # assert!(msg.is_request());
878/// # assert!(!msg.is_response());
879/// ```
880#[export_module]
881pub mod rhai_rusp_set {
882 use usp_builder::{SetBuilder, UpdateObjectBuilder};
883
884 /// Sets up a new USP `SetBuilder`
885 #[must_use]
886 pub const fn set_builder() -> SetBuilder {
887 SetBuilder::new()
888 }
889
890 #[rhai_fn(global)]
891 #[must_use]
892 pub const fn with_allow_partial(builder: SetBuilder, allow_partial: bool) -> SetBuilder {
893 builder.with_allow_partial(allow_partial)
894 }
895
896 #[rhai_fn(global)]
897 #[must_use]
898 pub fn with_update_objs(builder: SetBuilder, create_objs: Array) -> SetBuilder {
899 builder.with_update_objs(create_objs.into_iter().map(Dynamic::cast).collect())
900 }
901
902 #[rhai_fn(global)]
903 #[must_use]
904 pub fn set_update_object_builder(obj_path: &str) -> UpdateObjectBuilder {
905 UpdateObjectBuilder::new(obj_path.into())
906 }
907
908 #[rhai_fn(global, return_raw)]
909 ///
910 /// # Errors
911 ///
912 /// This function will return `Err` if the provided `param_settings` cannot be converted into
913 /// an array of type `(String, String, bool)`.
914 pub fn with_param_settings(
915 mut builder: UpdateObjectBuilder,
916 param_settings: Array,
917 ) -> Result<UpdateObjectBuilder, Box<EvalAltResult>> {
918 let param_settings = param_settings
919 .into_iter()
920 .map(|p| {
921 let el = p.try_cast::<Array>()
922 .ok_or_else(|| "Expected to have an array of arrays [param: &str, value: &str, required: bool]".to_string())?;
923 let el0 = el.first()
924 .and_then(|el| el.clone().try_cast::<String>())
925 .ok_or_else(|| "param (#1) needs to be a string".to_string())?;
926 let el1 = el.get(1)
927 .and_then(|el| el.clone().try_cast::<String>())
928 .ok_or_else(|| "value (#2) needs to be a string".to_string())?;
929 let el2 = el.get(2)
930 .and_then(|el| el.clone().try_cast::<bool>())
931 .ok_or_else(|| "required (#3) needs to be a bool".to_string())?;
932
933 Ok((el0, el1, el2))
934 })
935 .collect::<Result<Vec<(String, String, bool)>, Box<EvalAltResult>>>()?;
936 builder = builder.with_param_settings(param_settings);
937
938 Ok(builder)
939 }
940
941 /// Turns the builder into a [`Body`] structure
942 ///
943 /// # Errors
944 ///
945 /// This function will return `Err` if the provided `builder` was set up with incomplete or
946 /// incorrect data.
947 #[rhai_fn(global, return_raw)]
948 pub fn build(builder: SetBuilder) -> Result<Body, Box<EvalAltResult>> {
949 Ok(builder.build().map_err(|e| e.to_string())?)
950 }
951}
952
953/// Supply Rusp SetResp Message functionality
954/// ```
955/// // Rhai script
956/// # let script = r#"
957/// let failure = setresp_updated_instance_failure_builder("Foo.Bar.")
958/// .with_param_errs ([["Baz", 7002, ""]]);
959/// let updated_objs = [
960/// rusp::setresp_updated_obj_failure("Foo.Bar.", 0, "", [failure]),
961/// rusp::setresp_updated_obj_success("Foo", "Foo.Bar.1", [["Bar", 7004, ""]], #{"Foo": "Bar"})
962/// ];
963/// let body = rusp::setresp_builder()
964/// .with_updated_obj_results(updated_objs)
965/// .build();
966/// rusp::msg_builder()
967/// .with_msg_id("Foo")
968/// .with_body(body)
969/// .build()
970/// # "#;
971/// # let msg = rhai_rusp::eval_rusp::<rusp_lib::usp::Msg>(script).unwrap();
972/// # assert!(!msg.is_error());
973/// # assert!(!msg.is_request());
974/// # assert!(msg.is_response());
975/// ```
976#[export_module]
977pub mod rhai_rusp_setresp {
978 use usp_builder::{
979 SetOperationStatus, SetOperationSuccessBuilder, SetRespBuilder, SetRespParameterError,
980 UpdatedInstanceFailureBuilder, UpdatedObjectResultsBuilder,
981 };
982
983 /// Sets up a new USP `SetRespBuilder`
984 #[must_use]
985 pub const fn setresp_builder() -> SetRespBuilder {
986 SetRespBuilder::new()
987 }
988
989 #[rhai_fn(global)]
990 #[must_use]
991 pub fn with_updated_obj_results(
992 builder: SetRespBuilder,
993 updated_obj_results: Array,
994 ) -> SetRespBuilder {
995 let updated_obj_results = updated_obj_results.into_iter().map(Dynamic::cast).collect();
996 builder.with_updated_obj_results(updated_obj_results)
997 }
998
999 #[rhai_fn(global)]
1000 #[must_use]
1001 pub fn setresp_updated_instance_failure_builder(
1002 affected_path: &str,
1003 ) -> UpdatedInstanceFailureBuilder {
1004 UpdatedInstanceFailureBuilder::new(affected_path.into())
1005 }
1006
1007 #[rhai_fn(global, return_raw)]
1008 ///
1009 /// # Errors
1010 ///
1011 /// This function will return `Err` if the provided `param_errs` cannot be converted into
1012 /// an array of type `(String, u32, String)`.
1013 pub fn with_param_errs(
1014 builder: UpdatedInstanceFailureBuilder,
1015 param_errs: Array,
1016 ) -> Result<UpdatedInstanceFailureBuilder, Box<EvalAltResult>> {
1017 let param_errs = param_errs
1018 .into_iter()
1019 .map(|p| {
1020 let el = p.try_cast::<Array>()
1021 .ok_or_else(|| "Expected to have an array of arrays [param: &str, err_code: u32, err_msg: &str]".to_string())?;
1022 let el0 = el.first()
1023 .and_then(|el| el.clone().try_cast::<String>())
1024 .ok_or_else(|| "param (#1) needs to be a string".to_string())?;
1025 let el1 = el.get(1)
1026 .and_then(|el| el.clone().try_cast::<i64>())
1027 .ok_or_else(|| "err_code (#2) needs to be a u32".to_string())?;
1028 let el2 = el.get(2)
1029 .and_then(|el| el.clone().try_cast::<String>())
1030 .ok_or_else(|| "err_msg (#3) needs to be a string".to_string())?;
1031
1032 Ok(SetRespParameterError::new(el0, u32::try_from(el1).unwrap_or(7003), Some(el2)))
1033 })
1034 .collect::<Result<Vec<SetRespParameterError>, Box<EvalAltResult>>>()?;
1035 Ok(builder.with_param_errs(param_errs))
1036 }
1037
1038 #[rhai_fn(global)]
1039 #[must_use]
1040 pub fn setresp_updated_obj_failure(
1041 requested_path: &str,
1042 err_code: i64,
1043 err_msg: &str,
1044 updated_inst_failures: Array,
1045 ) -> UpdatedObjectResultsBuilder {
1046 let oper_status = SetOperationStatus::new().set_failure(
1047 u32::try_from(err_code).unwrap_or(7003),
1048 (!err_msg.is_empty()).then_some(err_msg.into()),
1049 updated_inst_failures
1050 .into_iter()
1051 .map(Dynamic::cast)
1052 .collect(),
1053 );
1054 UpdatedObjectResultsBuilder::new(requested_path.into(), oper_status)
1055 }
1056
1057 /// # Errors
1058 ///
1059 /// This function will return `Err` if the provided `param_errs` cannot be converted into
1060 /// an array of type `(String, u32, String)`.
1061 #[rhai_fn(global, return_raw)]
1062 pub fn setresp_updated_obj_success(
1063 requested_path: &str,
1064 affected_path: &str,
1065 param_errs: Array,
1066 updated_params: Map,
1067 ) -> Result<UpdatedObjectResultsBuilder, Box<EvalAltResult>> {
1068 let param_errs = param_errs
1069 .into_iter()
1070 .map(|p| {
1071 let el = p.try_cast::<Array>()
1072 .ok_or_else(|| "Expected to have an array of arrays [param: &str, err_code: u32, err_msg: &str]".to_string())?;
1073 let el0 = el.first()
1074 .and_then(|el| el.clone().try_cast::<String>())
1075 .ok_or_else(|| "param (#1) needs to be a string".to_string())?;
1076 let el1 = el.get(1)
1077 .and_then(|el| el.clone().try_cast::<i64>())
1078 .ok_or_else(|| "err_code (#2) needs to be a u32".to_string())?;
1079 let el2 = el.get(2)
1080 .and_then(|el| el.clone().try_cast::<String>())
1081 .ok_or_else(|| "err_msg (#3) needs to be a string".to_string())?;
1082
1083 Ok(SetRespParameterError::new(el0, u32::try_from(el1).unwrap_or(7003), Some(el2)))
1084 })
1085 .collect::<Result<Vec<SetRespParameterError>, Box<EvalAltResult>>>()?;
1086
1087 let updated_params = updated_params
1088 .iter()
1089 .map(|(k, v)| (k.to_string(), v.to_string()))
1090 .collect();
1091
1092 Ok(UpdatedObjectResultsBuilder::new(
1093 requested_path.into(),
1094 SetOperationStatus::new().set_success(vec![SetOperationSuccessBuilder::new(
1095 affected_path.into(),
1096 )
1097 .with_updated_params(updated_params)
1098 .with_param_errs(param_errs)]),
1099 ))
1100 }
1101
1102 /// Turns the builder into a [`Body`] structure
1103 ///
1104 /// # Errors
1105 ///
1106 /// This function will return `Err` if the provided `builder` was set up with incomplete or
1107 /// incorrect data.
1108 #[rhai_fn(global, return_raw)]
1109 pub fn build(builder: SetRespBuilder) -> Result<Body, Box<EvalAltResult>> {
1110 Ok(builder.build().map_err(|e| e.to_string())?)
1111 }
1112}
1113
1114/// Supply Rusp Error Message functionality
1115/// ```
1116/// // Rhai script
1117/// # let script = r#"
1118/// let body = rusp::error_builder()
1119/// .set_err(7002, "I don't know")
1120/// .with_param_errs([["Foo", 7002, ""]])
1121/// .build();
1122/// rusp::msg_builder()
1123/// .with_msg_id("Foo")
1124/// .with_body(body)
1125/// .build()
1126/// # "#;
1127/// # let msg = rhai_rusp::eval_rusp::<rusp_lib::usp::Msg>(script).unwrap();
1128/// # assert!(msg.is_error());
1129/// # assert!(!msg.is_request());
1130/// # assert!(!msg.is_response());
1131/// ```
1132#[export_module]
1133pub mod rhai_rusp_error {
1134 use usp_builder::ErrorBuilder;
1135
1136 /// Sets up a new USP `ErrorBuilder`
1137 #[must_use]
1138 pub const fn error_builder() -> ErrorBuilder {
1139 ErrorBuilder::new()
1140 }
1141
1142 #[rhai_fn(global)]
1143 #[must_use]
1144 pub fn set_err(builder: ErrorBuilder, err_code: i64, err_msg: &str) -> ErrorBuilder {
1145 builder.set_err(
1146 u32::try_from(err_code).unwrap_or(7003),
1147 (!err_msg.is_empty()).then_some(err_msg.into()),
1148 )
1149 }
1150
1151 /// # Errors
1152 ///
1153 /// This function will return `Err` if the provided `param_errs` cannot be converted into
1154 /// an array of type `(String, u32, String)`.
1155 #[rhai_fn(global, return_raw)]
1156 pub fn with_param_errs(
1157 builder: ErrorBuilder,
1158 param_errs: Array,
1159 ) -> Result<ErrorBuilder, Box<EvalAltResult>> {
1160 let param_errs = param_errs
1161 .into_iter()
1162 .map(|p| {
1163 let el = p.try_cast::<Array>()
1164 .ok_or_else(|| "Expected to have an array of arrays [param: &str, err_code: u32, err_msg: &str]".to_string())?;
1165 let el0 = el.first()
1166 .and_then(|el| el.clone().try_cast::<String>())
1167 .ok_or_else(|| "param (#1) needs to be a string".to_string())?;
1168 let el1 = el.get(1)
1169 .and_then(|el| el.clone().try_cast::<i64>())
1170 .ok_or_else(|| "err_code (#2) needs to be a u32".to_string())?;
1171 let el2 = el.get(2)
1172 .and_then(|el| el.clone().try_cast::<String>())
1173 .ok_or_else(|| "err_msg (#3) needs to be a string".to_string())?;
1174
1175 Ok((el0, u32::try_from(el1).unwrap_or(7003), el2))
1176 })
1177 .collect::<Result<Vec<_>, Box<EvalAltResult>>>()?;
1178
1179 Ok(builder.with_param_errs(param_errs))
1180 }
1181
1182 /// Turns the builder into a [`Body`] structure
1183 ///
1184 /// # Errors
1185 ///
1186 /// This function will return `Err` if the provided `builder` was set up with incomplete or
1187 /// incorrect data.
1188 #[rhai_fn(global, return_raw)]
1189 pub fn build(builder: ErrorBuilder) -> Result<Body, Box<EvalAltResult>> {
1190 Ok(builder.build().map_err(|e| e.to_string())?)
1191 }
1192}
1193
1194/// Supply Rusp Get Message functionality
1195/// ```
1196/// // Rhai script
1197/// # let script = r#"
1198/// let body = rusp::get_builder()
1199/// .with_params(["Device."])
1200/// .with_max_depth(1)
1201/// .build();
1202/// rusp::msg_builder()
1203/// .with_msg_id("Foo")
1204/// .with_body(body)
1205/// .build()
1206/// # "#;
1207/// # let msg = rhai_rusp::eval_rusp::<rusp_lib::usp::Msg>(script).unwrap();
1208/// # assert!(!msg.is_error());
1209/// # assert!(msg.is_request());
1210/// # assert!(!msg.is_response());
1211/// ```
1212#[export_module]
1213pub mod rhai_rusp_get {
1214 use usp_builder::GetBuilder;
1215
1216 /// Sets up a new USP `GetBuilder`
1217 #[must_use]
1218 pub const fn get_builder() -> GetBuilder {
1219 GetBuilder::new()
1220 }
1221
1222 #[rhai_fn(global)]
1223 #[must_use]
1224 pub fn with_max_depth(builder: GetBuilder, max_depth: i64) -> GetBuilder {
1225 builder.with_max_depth(u32::try_from(max_depth).unwrap_or(0))
1226 }
1227
1228 #[rhai_fn(global)]
1229 #[must_use]
1230 pub fn with_params(builder: GetBuilder, params: Array) -> GetBuilder {
1231 builder.with_params(params.into_iter().map(Dynamic::cast).collect())
1232 }
1233
1234 /// Turns the builder into a [`Body`] structure
1235 ///
1236 /// # Errors
1237 ///
1238 /// This function will return `Err` if the provided `builder` was set up with incomplete or
1239 /// incorrect data.
1240 #[rhai_fn(global, return_raw)]
1241 pub fn build(builder: GetBuilder) -> Result<Body, Box<EvalAltResult>> {
1242 Ok(builder.build().map_err(|e| e.to_string())?)
1243 }
1244}
1245
1246/// Supply Rusp GetResp Message functionality
1247/// ```
1248/// // Rhai script
1249/// # let script = r#"
1250/// let respathres = [];
1251/// respathres += rusp::get_res_path_result_builder("Device.")
1252/// .with_result_params(#{"Foo": "Bar"});
1253/// let reqpathres = [];
1254/// reqpathres += rusp::req_path_result_builder("Device.")
1255/// .set_err(7002, "Look, a fancy error")
1256/// .with_res_path_result(respathres);
1257/// let body = rusp::getresp_builder()
1258/// .with_req_path_results(reqpathres)
1259/// .build();
1260/// rusp::msg_builder()
1261/// .with_msg_id("Foo")
1262/// .with_body(body)
1263/// .build()
1264/// # "#;
1265/// # let msg = rhai_rusp::eval_rusp::<rusp_lib::usp::Msg>(script).unwrap();
1266/// # assert!(!msg.is_error());
1267/// # assert!(!msg.is_request());
1268/// # assert!(msg.is_response());
1269/// ```
1270#[export_module]
1271pub mod rhai_rusp_getresp {
1272 use usp_builder::{GetReqPathResultBuilder, GetRespBuilder, ResolvedPathResultBuilder};
1273
1274 /// Sets up a new USP `GetRespBuilder`
1275 #[must_use]
1276 pub const fn getresp_builder() -> GetRespBuilder {
1277 GetRespBuilder::new()
1278 }
1279
1280 #[rhai_fn(global)]
1281 #[must_use]
1282 pub fn with_req_path_results(
1283 builder: GetRespBuilder,
1284 req_path_results: Array,
1285 ) -> GetRespBuilder {
1286 builder.with_req_path_results(req_path_results.into_iter().map(Dynamic::cast).collect())
1287 }
1288
1289 /// Turns the builder into a [`Body`] structure
1290 ///
1291 /// # Errors
1292 ///
1293 /// This function will return `Err` if the provided `builder` was set up with incomplete or
1294 /// incorrect data.
1295 #[rhai_fn(global, return_raw)]
1296 pub fn build(builder: GetRespBuilder) -> Result<Body, Box<EvalAltResult>> {
1297 Ok(builder.build().map_err(|e| e.to_string())?)
1298 }
1299
1300 #[must_use]
1301 pub fn req_path_result_builder(requested_path: &str) -> GetReqPathResultBuilder {
1302 GetReqPathResultBuilder::new(requested_path.into())
1303 }
1304
1305 #[rhai_fn(global)]
1306 #[must_use]
1307 pub fn set_err(
1308 builder: GetReqPathResultBuilder,
1309 err_code: i64,
1310 err_msg: &str,
1311 ) -> GetReqPathResultBuilder {
1312 builder.set_err(
1313 u32::try_from(err_code).unwrap_or(7003),
1314 (!err_msg.is_empty()).then_some(err_msg.into()),
1315 )
1316 }
1317
1318 #[rhai_fn(global)]
1319 #[must_use]
1320 pub fn with_res_path_result(
1321 builder: GetReqPathResultBuilder,
1322 resolved_path_results: Array,
1323 ) -> GetReqPathResultBuilder {
1324 builder.with_res_path_results(
1325 resolved_path_results
1326 .into_iter()
1327 .map(Dynamic::cast)
1328 .collect(),
1329 )
1330 }
1331
1332 #[must_use]
1333 pub fn get_res_path_result_builder(resolved_path: &str) -> ResolvedPathResultBuilder {
1334 ResolvedPathResultBuilder::new(resolved_path.into())
1335 }
1336
1337 #[rhai_fn(global)]
1338 #[must_use]
1339 pub fn with_result_params(
1340 builder: ResolvedPathResultBuilder,
1341 result_params: Map,
1342 ) -> ResolvedPathResultBuilder {
1343 let result_params = result_params
1344 .iter()
1345 .map(|(k, v)| (k.to_string(), v.to_string()))
1346 .collect();
1347 builder.with_result_params(result_params)
1348 }
1349}
1350
1351/// Supply Rusp GetSupportedDM Message functionality
1352/// ```
1353/// // Rhai script
1354/// # let script = r#"
1355/// let body = rusp::getsupporteddm_builder()
1356/// .with_obj_paths(["Device.", "Device.DeviceInfo."])
1357/// .with_first_level_only(true)
1358/// .with_return_commands(false)
1359/// .with_return_events(false)
1360/// .with_return_params(false)
1361/// .with_return_unique_key_sets(true)
1362/// .build();
1363/// rusp::msg_builder()
1364/// .with_msg_id("Foo")
1365/// .with_body(body)
1366/// .build()
1367/// # "#;
1368/// # let msg = rhai_rusp::eval_rusp::<rusp_lib::usp::Msg>(script).unwrap();
1369/// # assert!(!msg.is_error());
1370/// # assert!(msg.is_request());
1371/// # assert!(!msg.is_response());
1372/// ```
1373#[export_module]
1374pub mod rhai_rusp_getsupporteddm {
1375 use usp_builder::GetSupportedDMBuilder;
1376
1377 /// Sets up a new USP `GetSupportedDMBuilder`
1378 #[must_use]
1379 pub const fn getsupporteddm_builder() -> GetSupportedDMBuilder {
1380 GetSupportedDMBuilder::new()
1381 }
1382
1383 #[rhai_fn(global)]
1384 #[must_use]
1385 pub const fn with_first_level_only(
1386 builder: GetSupportedDMBuilder,
1387 first_level_only: bool,
1388 ) -> GetSupportedDMBuilder {
1389 builder.with_first_level_only(first_level_only)
1390 }
1391
1392 #[rhai_fn(global)]
1393 #[must_use]
1394 pub fn with_obj_paths(
1395 builder: GetSupportedDMBuilder,
1396 obj_paths: Array,
1397 ) -> GetSupportedDMBuilder {
1398 builder.with_obj_paths(obj_paths.into_iter().map(Dynamic::cast).collect())
1399 }
1400
1401 #[rhai_fn(global)]
1402 #[must_use]
1403 pub const fn with_return_commands(
1404 builder: GetSupportedDMBuilder,
1405 return_commands: bool,
1406 ) -> GetSupportedDMBuilder {
1407 builder.with_return_commands(return_commands)
1408 }
1409
1410 #[rhai_fn(global)]
1411 #[must_use]
1412 pub const fn with_return_events(
1413 builder: GetSupportedDMBuilder,
1414 return_events: bool,
1415 ) -> GetSupportedDMBuilder {
1416 builder.with_return_events(return_events)
1417 }
1418
1419 #[rhai_fn(global)]
1420 #[must_use]
1421 pub const fn with_return_params(
1422 builder: GetSupportedDMBuilder,
1423 return_params: bool,
1424 ) -> GetSupportedDMBuilder {
1425 builder.with_return_params(return_params)
1426 }
1427
1428 #[rhai_fn(global)]
1429 #[must_use]
1430 pub const fn with_return_unique_key_sets(
1431 builder: GetSupportedDMBuilder,
1432 return_unique_key_sets: bool,
1433 ) -> GetSupportedDMBuilder {
1434 builder.with_return_unique_key_sets(return_unique_key_sets)
1435 }
1436
1437 /// Turns the builder into a [`Body`] structure
1438 ///
1439 /// # Errors
1440 ///
1441 /// This function will return `Err` if the provided `builder` was set up with incomplete or
1442 /// incorrect data.
1443 #[rhai_fn(global, return_raw)]
1444 pub fn build(builder: GetSupportedDMBuilder) -> Result<Body, Box<EvalAltResult>> {
1445 Ok(builder.build().map_err(|e| e.to_string())?)
1446 }
1447}
1448
1449/// Supply Rusp GetSupportedDMResp Message functionality
1450/// ```
1451/// // Rhai script
1452/// # let script = r#"
1453/// let command = rusp::getsupporteddmresp_command_result_builder("Foo()")
1454/// .with_input_arg_names(["Foo", "Bar", "Baz"])
1455/// .with_output_arg_names(["Bam"])
1456/// .set_sync();
1457/// let event = rusp::getsupporteddmresp_event_result_builder("Foo!")
1458/// .with_arg_names(["Foo", "Bar", "Baz"]);
1459/// let param = rusp::getsupporteddmresp_param_result_builder("Foo")
1460/// .set_type_boolean()
1461/// .set_value_change_allowed()
1462/// .set_access_read_write();
1463/// let req_obj1 = rusp::getsupporteddm_req_obj_result_builder("Device.")
1464/// .set_err(7005, "");
1465/// let supported_obj = rusp::getsupporteddmresp_supported_obj_result_builder("Device.DeviceInfo.")
1466/// .with_is_multi_instance(false)
1467/// .set_access_add_delete()
1468/// .with_supported_commands([command])
1469/// .with_supported_events([event])
1470/// .with_supported_params([param])
1471/// .with_divergent_paths(["Device.DeviceInfo.Foo.1.", "Device.DeviceInfo.Foo.2."])
1472/// .with_unique_key_sets([["Foo", "Bar"], ["Baz"]]);
1473/// let req_obj2 = rusp::getsupporteddm_req_obj_result_builder("Device.DeviceInfo.")
1474/// .with_data_model_inst_uri("urn:broadband-forum-org:tr-181-2-17-0-usp")
1475/// .with_supported_objs([supported_obj]);
1476/// let body = rusp::getsupporteddmresp_builder()
1477/// .with_req_obj_results([req_obj1, req_obj2])
1478/// .build();
1479/// rusp::msg_builder()
1480/// .with_msg_id("Foo")
1481/// .with_body(body)
1482/// .build()
1483/// # "#;
1484/// # let msg = rhai_rusp::eval_rusp::<rusp_lib::usp::Msg>(script).unwrap();
1485/// # assert!(!msg.is_error());
1486/// # assert!(!msg.is_request());
1487/// # assert!(msg.is_response());
1488/// ```
1489#[export_module]
1490pub mod rhai_rusp_getsupporteddmresp {
1491 use usp_builder::{
1492 GSDMCommandResult, GSDMEventResult, GSDMParamResult, GSDMReqObjectResultBuilder,
1493 GSDMSupportedObjectResultBuilder, GetSupportedDMRespBuilder,
1494 };
1495
1496 /// Sets up a new USP `GetSupportedDMRespBuilder`
1497 #[must_use]
1498 pub const fn getsupporteddmresp_builder() -> GetSupportedDMRespBuilder {
1499 GetSupportedDMRespBuilder::new()
1500 }
1501
1502 #[rhai_fn(global)]
1503 #[must_use]
1504 pub fn with_req_obj_results(
1505 builder: GetSupportedDMRespBuilder,
1506 req_obj_results: Array,
1507 ) -> GetSupportedDMRespBuilder {
1508 builder.with_req_obj_results(req_obj_results.into_iter().map(Dynamic::cast).collect())
1509 }
1510
1511 /// Turns the builder into a [`Body`] structure
1512 ///
1513 /// # Errors
1514 ///
1515 /// This function will return `Err` if the provided `builder` was set up with incomplete or
1516 /// incorrect data.
1517 #[rhai_fn(global, return_raw)]
1518 pub fn build(builder: GetSupportedDMRespBuilder) -> Result<Body, Box<EvalAltResult>> {
1519 Ok(builder.build().map_err(|e| e.to_string())?)
1520 }
1521
1522 #[must_use]
1523 pub fn getsupporteddm_req_obj_result_builder(req_obj_path: &str) -> GSDMReqObjectResultBuilder {
1524 GSDMReqObjectResultBuilder::new(req_obj_path.into())
1525 }
1526
1527 #[rhai_fn(global)]
1528 #[must_use]
1529 pub fn set_err(
1530 builder: GSDMReqObjectResultBuilder,
1531 err_code: i64,
1532 err_msg: &str,
1533 ) -> GSDMReqObjectResultBuilder {
1534 builder.set_err(
1535 u32::try_from(err_code).unwrap_or(7003),
1536 (!err_msg.is_empty()).then_some(err_msg.into()),
1537 )
1538 }
1539
1540 #[rhai_fn(global)]
1541 #[must_use]
1542 pub fn with_data_model_inst_uri(
1543 builder: GSDMReqObjectResultBuilder,
1544 data_model_inst_uri: &str,
1545 ) -> GSDMReqObjectResultBuilder {
1546 builder.with_data_model_inst_uri(data_model_inst_uri.into())
1547 }
1548
1549 #[rhai_fn(global)]
1550 #[must_use]
1551 pub fn with_supported_objs(
1552 builder: GSDMReqObjectResultBuilder,
1553 supported_objs: Array,
1554 ) -> GSDMReqObjectResultBuilder {
1555 builder.with_supported_objs(supported_objs.into_iter().map(Dynamic::cast).collect())
1556 }
1557
1558 #[must_use]
1559 pub fn getsupporteddmresp_supported_obj_result_builder(
1560 req_obj_path: &str,
1561 ) -> GSDMSupportedObjectResultBuilder {
1562 GSDMSupportedObjectResultBuilder::new(req_obj_path.into())
1563 }
1564
1565 #[rhai_fn(global)]
1566 #[must_use]
1567 pub const fn with_is_multi_instance(
1568 builder: GSDMSupportedObjectResultBuilder,
1569 is_multi_instance: bool,
1570 ) -> GSDMSupportedObjectResultBuilder {
1571 builder.with_is_multi_instance(is_multi_instance)
1572 }
1573
1574 #[rhai_fn(global)]
1575 #[must_use]
1576 pub const fn set_access_add_only(
1577 builder: GSDMSupportedObjectResultBuilder,
1578 ) -> GSDMSupportedObjectResultBuilder {
1579 builder.set_access_add_only()
1580 }
1581
1582 #[rhai_fn(global)]
1583 #[must_use]
1584 pub const fn set_access_delete_only(
1585 builder: GSDMSupportedObjectResultBuilder,
1586 ) -> GSDMSupportedObjectResultBuilder {
1587 builder.set_access_delete_only()
1588 }
1589
1590 #[rhai_fn(global, name = "set_access_read_only")]
1591 #[must_use]
1592 pub const fn obj_set_access_read_only(
1593 builder: GSDMSupportedObjectResultBuilder,
1594 ) -> GSDMSupportedObjectResultBuilder {
1595 builder.set_access_read_only()
1596 }
1597
1598 #[rhai_fn(global)]
1599 #[must_use]
1600 pub const fn set_access_add_delete(
1601 builder: GSDMSupportedObjectResultBuilder,
1602 ) -> GSDMSupportedObjectResultBuilder {
1603 builder.set_access_add_delete()
1604 }
1605
1606 #[rhai_fn(global)]
1607 #[must_use]
1608 pub fn with_supported_commands(
1609 builder: GSDMSupportedObjectResultBuilder,
1610 supported_commands: Array,
1611 ) -> GSDMSupportedObjectResultBuilder {
1612 builder.with_supported_commands(supported_commands.into_iter().map(Dynamic::cast).collect())
1613 }
1614
1615 #[rhai_fn(global)]
1616 #[must_use]
1617 pub fn with_supported_events(
1618 builder: GSDMSupportedObjectResultBuilder,
1619 supported_events: Array,
1620 ) -> GSDMSupportedObjectResultBuilder {
1621 builder.with_supported_events(supported_events.into_iter().map(Dynamic::cast).collect())
1622 }
1623
1624 #[rhai_fn(global)]
1625 #[must_use]
1626 pub fn with_supported_params(
1627 builder: GSDMSupportedObjectResultBuilder,
1628 supported_params: Array,
1629 ) -> GSDMSupportedObjectResultBuilder {
1630 builder.with_supported_params(supported_params.into_iter().map(Dynamic::cast).collect())
1631 }
1632
1633 #[rhai_fn(global)]
1634 #[must_use]
1635 pub fn with_divergent_paths(
1636 builder: GSDMSupportedObjectResultBuilder,
1637 divergent_paths: Array,
1638 ) -> GSDMSupportedObjectResultBuilder {
1639 builder.with_divergent_paths(divergent_paths.into_iter().map(Dynamic::cast).collect())
1640 }
1641
1642 /// # Errors
1643 ///
1644 /// This function will return `Err` if the provided `unique_key_sets` cannot be converted into
1645 /// an array of type `String`.
1646 #[rhai_fn(global, return_raw)]
1647 pub fn with_unique_key_sets(
1648 builder: GSDMSupportedObjectResultBuilder,
1649 unique_key_sets: Array,
1650 ) -> Result<GSDMSupportedObjectResultBuilder, Box<EvalAltResult>> {
1651 let unique_key_sets = unique_key_sets
1652 .into_iter()
1653 .map(|p| {
1654 p.try_cast::<Array>()
1655 .ok_or_else(|| "Expected to have an array of arrays of string".to_string())?
1656 .iter()
1657 .map(|el| {
1658 el.clone()
1659 .try_cast::<String>()
1660 .ok_or_else(|| "param needs to be a string".to_string())
1661 })
1662 .collect::<Result<Vec<String>, _>>()
1663 })
1664 .collect::<Result<Vec<Vec<String>>, _>>()?;
1665 Ok(builder.with_unique_key_sets(unique_key_sets))
1666 }
1667
1668 #[must_use]
1669 pub fn getsupporteddmresp_command_result_builder(command_name: &str) -> GSDMCommandResult {
1670 GSDMCommandResult::new(command_name.into())
1671 }
1672
1673 #[rhai_fn(global)]
1674 #[must_use]
1675 pub fn with_input_arg_names(
1676 builder: GSDMCommandResult,
1677 input_arg_names: Array,
1678 ) -> GSDMCommandResult {
1679 builder.with_input_arg_names(input_arg_names.into_iter().map(Dynamic::cast).collect())
1680 }
1681
1682 #[rhai_fn(global)]
1683 #[must_use]
1684 pub fn with_output_arg_names(
1685 builder: GSDMCommandResult,
1686 output_arg_names: Array,
1687 ) -> GSDMCommandResult {
1688 builder.with_output_arg_names(output_arg_names.into_iter().map(Dynamic::cast).collect())
1689 }
1690
1691 #[rhai_fn(global)]
1692 #[must_use]
1693 pub const fn set_sync(builder: GSDMCommandResult) -> GSDMCommandResult {
1694 builder.set_sync()
1695 }
1696
1697 #[rhai_fn(global)]
1698 #[must_use]
1699 pub const fn set_async(builder: GSDMCommandResult) -> GSDMCommandResult {
1700 builder.set_async()
1701 }
1702
1703 #[must_use]
1704 pub fn getsupporteddmresp_event_result_builder(event_name: &str) -> GSDMEventResult {
1705 GSDMEventResult::new(event_name.into())
1706 }
1707
1708 #[rhai_fn(global)]
1709 #[must_use]
1710 pub fn with_arg_names(builder: GSDMEventResult, input_arg_names: Array) -> GSDMEventResult {
1711 builder.with_arg_names(input_arg_names.into_iter().map(Dynamic::cast).collect())
1712 }
1713
1714 #[must_use]
1715 pub fn getsupporteddmresp_param_result_builder(param_name: &str) -> GSDMParamResult {
1716 GSDMParamResult::new(param_name.into())
1717 }
1718
1719 #[rhai_fn(global)]
1720 #[must_use]
1721 pub const fn set_access_read_only(builder: GSDMParamResult) -> GSDMParamResult {
1722 builder.set_access_read_only()
1723 }
1724
1725 #[rhai_fn(global)]
1726 #[must_use]
1727 pub const fn set_access_write_only(builder: GSDMParamResult) -> GSDMParamResult {
1728 builder.set_access_write_only()
1729 }
1730
1731 #[rhai_fn(global)]
1732 #[must_use]
1733 pub const fn set_access_read_write(builder: GSDMParamResult) -> GSDMParamResult {
1734 builder.set_access_read_write()
1735 }
1736
1737 #[rhai_fn(global)]
1738 #[must_use]
1739 pub const fn set_type_int(builder: GSDMParamResult) -> GSDMParamResult {
1740 builder.set_type_int()
1741 }
1742
1743 #[rhai_fn(global)]
1744 #[must_use]
1745 pub const fn set_type_unsigned_int(builder: GSDMParamResult) -> GSDMParamResult {
1746 builder.set_type_unsigned_int()
1747 }
1748
1749 #[rhai_fn(global)]
1750 #[must_use]
1751 pub const fn set_type_long(builder: GSDMParamResult) -> GSDMParamResult {
1752 builder.set_type_long()
1753 }
1754
1755 #[rhai_fn(global)]
1756 #[must_use]
1757 pub const fn set_type_unsigned_long(builder: GSDMParamResult) -> GSDMParamResult {
1758 builder.set_type_unsigned_long()
1759 }
1760
1761 #[rhai_fn(global)]
1762 #[must_use]
1763 pub const fn set_type_string(builder: GSDMParamResult) -> GSDMParamResult {
1764 builder.set_type_string()
1765 }
1766
1767 #[rhai_fn(global)]
1768 #[must_use]
1769 pub const fn set_type_base64(builder: GSDMParamResult) -> GSDMParamResult {
1770 builder.set_type_base64()
1771 }
1772
1773 #[rhai_fn(global)]
1774 #[must_use]
1775 pub const fn set_type_hexbinary(builder: GSDMParamResult) -> GSDMParamResult {
1776 builder.set_type_hexbinary()
1777 }
1778
1779 #[rhai_fn(global)]
1780 #[must_use]
1781 pub const fn set_type_datetime(builder: GSDMParamResult) -> GSDMParamResult {
1782 builder.set_type_datetime()
1783 }
1784
1785 #[rhai_fn(global)]
1786 #[must_use]
1787 pub const fn set_type_decimal(builder: GSDMParamResult) -> GSDMParamResult {
1788 builder.set_type_decimal()
1789 }
1790
1791 #[rhai_fn(global)]
1792 #[must_use]
1793 pub const fn set_type_boolean(builder: GSDMParamResult) -> GSDMParamResult {
1794 builder.set_type_boolean()
1795 }
1796
1797 #[rhai_fn(global)]
1798 #[must_use]
1799 pub const fn set_value_change_allowed(builder: GSDMParamResult) -> GSDMParamResult {
1800 builder.set_value_change_allowed()
1801 }
1802
1803 #[rhai_fn(global)]
1804 #[must_use]
1805 pub const fn set_value_change_will_ignore(builder: GSDMParamResult) -> GSDMParamResult {
1806 builder.set_value_change_will_ignore()
1807 }
1808}
1809
1810/// Supply Rusp GetInstances Message functionality
1811/// ```
1812/// // Rhai script
1813/// # let script = r#"
1814/// let body = rusp::getinstances_builder()
1815/// .with_first_level_only(true)
1816/// .with_obj_paths(["Device."])
1817/// .build();
1818/// rusp::msg_builder()
1819/// .with_msg_id("Foo")
1820/// .with_body(body)
1821/// .build()
1822/// # "#;
1823/// # let msg = rhai_rusp::eval_rusp::<rusp_lib::usp::Msg>(script).unwrap();
1824/// # assert!(!msg.is_error());
1825/// # assert!(msg.is_request());
1826/// # assert!(!msg.is_response());
1827/// ```
1828#[export_module]
1829pub mod rhai_rusp_getinstances {
1830 use usp_builder::GetInstancesBuilder;
1831
1832 /// Sets up a new USP `GetInstancesBuilder`
1833 #[must_use]
1834 pub const fn getinstances_builder() -> GetInstancesBuilder {
1835 GetInstancesBuilder::new()
1836 }
1837
1838 #[rhai_fn(global)]
1839 #[must_use]
1840 pub const fn with_first_level_only(
1841 builder: GetInstancesBuilder,
1842 first_level_only: bool,
1843 ) -> GetInstancesBuilder {
1844 builder.with_first_level_only(first_level_only)
1845 }
1846
1847 #[rhai_fn(global)]
1848 #[must_use]
1849 pub fn with_obj_paths(builder: GetInstancesBuilder, obj_paths: Array) -> GetInstancesBuilder {
1850 builder.with_obj_paths(obj_paths.into_iter().map(Dynamic::cast).collect())
1851 }
1852
1853 /// Turns the builder into a [`Body`] structure
1854 ///
1855 /// # Errors
1856 ///
1857 /// This function will return `Err` if the provided `builder` was set up with incomplete or
1858 /// incorrect data.
1859 #[rhai_fn(global, return_raw)]
1860 pub fn build(builder: GetInstancesBuilder) -> Result<Body, Box<EvalAltResult>> {
1861 Ok(builder.build().map_err(|e| e.to_string())?)
1862 }
1863}
1864
1865/// Supply Rusp GetInstancesResp Message functionality
1866/// ```
1867/// // Rhai script
1868/// # let script = r#"
1869/// let curr_inst = rusp::curr_instance_builder("Device.")
1870/// .with_unique_keys(#{"Foo": "Bar"});
1871/// let reqpathres = rusp::getinstances_req_path_result_builder("Device.")
1872/// .set_err(7002, "Look, a fancy error")
1873/// .with_curr_insts([curr_inst]);
1874/// let body = rusp::getinstancesresp_builder()
1875/// .with_req_path_results([reqpathres])
1876/// .build();
1877/// rusp::msg_builder()
1878/// .with_msg_id("Foo")
1879/// .with_body(body)
1880/// .build()
1881/// # "#;
1882/// # let msg = rhai_rusp::eval_rusp::<rusp_lib::usp::Msg>(script).unwrap();
1883/// # assert!(!msg.is_error());
1884/// # assert!(!msg.is_request());
1885/// # assert!(msg.is_response());
1886/// ```
1887#[export_module]
1888pub mod rhai_rusp_getinstancesresp {
1889 use usp_builder::{
1890 CurrInstanceBuilder, GetInstancesRespBuilder, GetInstancesRespReqPathResultBuilder,
1891 };
1892
1893 /// Sets up a new USP `GetInstancesRespBuilder`
1894 #[must_use]
1895 pub const fn getinstancesresp_builder() -> GetInstancesRespBuilder {
1896 GetInstancesRespBuilder::new()
1897 }
1898
1899 #[rhai_fn(global)]
1900 #[must_use]
1901 pub fn with_req_path_results(
1902 builder: GetInstancesRespBuilder,
1903 req_path_results: Array,
1904 ) -> GetInstancesRespBuilder {
1905 builder.with_req_path_results(req_path_results.into_iter().map(Dynamic::cast).collect())
1906 }
1907
1908 #[must_use]
1909 pub fn getinstances_req_path_result_builder(
1910 requested_path: &str,
1911 ) -> GetInstancesRespReqPathResultBuilder {
1912 GetInstancesRespReqPathResultBuilder::new(requested_path.into())
1913 }
1914
1915 #[rhai_fn(global)]
1916 #[must_use]
1917 pub fn set_err(
1918 builder: GetInstancesRespReqPathResultBuilder,
1919 err_code: i64,
1920 err_msg: &str,
1921 ) -> GetInstancesRespReqPathResultBuilder {
1922 builder.set_err(
1923 u32::try_from(err_code).unwrap_or(7003),
1924 (!err_msg.is_empty()).then_some(err_msg.into()),
1925 )
1926 }
1927
1928 #[rhai_fn(global)]
1929 #[must_use]
1930 pub fn with_curr_insts(
1931 builder: GetInstancesRespReqPathResultBuilder,
1932 curr_insts: Array,
1933 ) -> GetInstancesRespReqPathResultBuilder {
1934 builder.with_curr_insts(curr_insts.into_iter().map(Dynamic::cast).collect())
1935 }
1936
1937 #[must_use]
1938 pub fn curr_instance_builder(resolved_path: &str) -> CurrInstanceBuilder {
1939 CurrInstanceBuilder::new(resolved_path.into())
1940 }
1941
1942 #[rhai_fn(global)]
1943 #[must_use]
1944 pub fn with_unique_keys(builder: CurrInstanceBuilder, unique_keys: Map) -> CurrInstanceBuilder {
1945 let unique_keys = unique_keys
1946 .iter()
1947 .map(|(k, v)| (k.to_string(), v.to_string()))
1948 .collect();
1949 builder.with_unique_keys(unique_keys)
1950 }
1951
1952 /// Turns the builder into a [`Body`] structure
1953 ///
1954 /// # Errors
1955 ///
1956 /// This function will return `Err` if the provided `builder` was set up with incomplete or
1957 /// incorrect data.
1958 #[rhai_fn(global, return_raw)]
1959 pub fn build(builder: GetInstancesRespBuilder) -> Result<Body, Box<EvalAltResult>> {
1960 Ok(builder.build().map_err(|e| e.to_string())?)
1961 }
1962}
1963
1964/// Supply Rusp GetSupportedProtocol Message functionality
1965/// ```
1966/// // Rhai script
1967/// # let script = r#"
1968/// let body = rusp::getsupportedprotocol_builder("1.3,1.4")
1969/// .build();
1970/// rusp::msg_builder()
1971/// .with_msg_id("Foo")
1972/// .with_body(body)
1973/// .build()
1974/// # "#;
1975/// # let msg = rhai_rusp::eval_rusp::<rusp_lib::usp::Msg>(script).unwrap();
1976/// # assert!(!msg.is_error());
1977/// # assert!(msg.is_request());
1978/// # assert!(!msg.is_response());
1979/// ```
1980#[export_module]
1981pub mod rhai_rusp_getsupportedprotocol {
1982 use usp_builder::GetSupportedProtocolBuilder;
1983
1984 /// Sets up a new USP `GetSupportedProtocolBuilder`
1985 #[must_use]
1986 pub fn getsupportedprotocol_builder(
1987 controller_supported_protocol_versions: &str,
1988 ) -> GetSupportedProtocolBuilder {
1989 GetSupportedProtocolBuilder::new(controller_supported_protocol_versions.into())
1990 }
1991
1992 /// Turns the builder into a [`Body`] structure
1993 ///
1994 /// # Errors
1995 ///
1996 /// This function will return `Err` if the provided `builder` was set up with incomplete or
1997 /// incorrect data.
1998 #[rhai_fn(global, return_raw)]
1999 pub fn build(builder: GetSupportedProtocolBuilder) -> Result<Body, Box<EvalAltResult>> {
2000 Ok(builder.build().map_err(|e| e.to_string())?)
2001 }
2002}
2003
2004/// Supply Rusp GetSupportedProtocolResp Message functionality
2005/// ```
2006/// // Rhai script
2007/// # let script = r#"
2008/// let body = rusp::getsupportedprotocolresp_builder("1.2,1.3")
2009/// .build();
2010/// rusp::msg_builder()
2011/// .with_msg_id("Foo")
2012/// .with_body(body)
2013/// .build()
2014/// # "#;
2015/// # let msg = rhai_rusp::eval_rusp::<rusp_lib::usp::Msg>(script).unwrap();
2016/// # assert!(!msg.is_error());
2017/// # assert!(!msg.is_request());
2018/// # assert!(msg.is_response());
2019/// ```
2020#[export_module]
2021pub mod rhai_rusp_getsupportedprotocolresp {
2022 use usp_builder::GetSupportedProtocolRespBuilder;
2023
2024 /// Sets up a new USP `GetSupportedProtocolRespBuilder`
2025 #[must_use]
2026 pub fn getsupportedprotocolresp_builder(
2027 agent_supported_protocol_versions: &str,
2028 ) -> GetSupportedProtocolRespBuilder {
2029 GetSupportedProtocolRespBuilder::new(agent_supported_protocol_versions.into())
2030 }
2031
2032 /// Turns the builder into a [`Body`] structure
2033 ///
2034 /// # Errors
2035 ///
2036 /// This function will return `Err` if the provided `builder` was set up with incomplete or
2037 /// incorrect data.
2038 #[rhai_fn(global, return_raw)]
2039 pub fn build(builder: GetSupportedProtocolRespBuilder) -> Result<Body, Box<EvalAltResult>> {
2040 Ok(builder.build().map_err(|e| e.to_string())?)
2041 }
2042}
2043
2044/// Supply Rusp Add Message functionality
2045/// ```
2046/// // Rhai script
2047/// # let script = r#"
2048/// let create_obj = rusp::add_create_object_builder("Device.IP.Interface.")
2049/// .with_param_settings([["Foo", "Bar", true],["Whee", "What?", false]]);
2050/// let body = rusp::add_builder()
2051/// .with_allow_partial(true)
2052/// .with_create_objs([create_obj])
2053/// .build();
2054/// rusp::msg_builder()
2055/// .with_msg_id("Foo")
2056/// .with_body(body)
2057/// .build()
2058/// # "#;
2059/// # let msg = rhai_rusp::eval_rusp::<rusp_lib::usp::Msg>(script).unwrap();
2060/// # assert!(!msg.is_error());
2061/// # assert!(msg.is_request());
2062/// # assert!(!msg.is_response());
2063/// ```
2064#[export_module]
2065pub mod rhai_rusp_add {
2066 use usp_builder::{AddBuilder, CreateObjectBuilder};
2067
2068 /// Sets up a new USP `AddBuilder`
2069 #[must_use]
2070 pub const fn add_builder() -> AddBuilder {
2071 AddBuilder::new()
2072 }
2073
2074 #[rhai_fn(global)]
2075 #[must_use]
2076 pub const fn with_allow_partial(builder: AddBuilder, allow_partial: bool) -> AddBuilder {
2077 builder.with_allow_partial(allow_partial)
2078 }
2079
2080 #[rhai_fn(global)]
2081 #[must_use]
2082 pub fn with_create_objs(builder: AddBuilder, create_objs: Array) -> AddBuilder {
2083 builder.with_create_objs(create_objs.into_iter().map(Dynamic::cast).collect())
2084 }
2085
2086 #[rhai_fn(global)]
2087 #[must_use]
2088 pub fn add_create_object_builder(obj_path: &str) -> CreateObjectBuilder {
2089 CreateObjectBuilder::new(obj_path.into())
2090 }
2091
2092 ///
2093 /// # Errors
2094 ///
2095 /// This function will return `Err` if the provided `param_settings` cannot be converted into
2096 /// an array of type `(String, String, bool)`.
2097 #[rhai_fn(global, return_raw)]
2098 pub fn with_param_settings(
2099 mut builder: CreateObjectBuilder,
2100 param_settings: Array,
2101 ) -> Result<CreateObjectBuilder, Box<EvalAltResult>> {
2102 let param_settings = param_settings
2103 .into_iter()
2104 .map(|p| {
2105 let el = p.try_cast::<Array>()
2106 .ok_or_else(|| "Expected to have an array of arrays [param: &str, value: &str, required: bool]".to_string())?;
2107 let el0 = el.first()
2108 .and_then(|el| el.clone().try_cast::<String>())
2109 .ok_or_else(|| "param (#1) needs to be a string".to_string())?;
2110 let el1 = el.get(1)
2111 .and_then(|el| el.clone().try_cast::<String>())
2112 .ok_or_else(|| "value (#2) needs to be a string".to_string())?;
2113 let el2 = el.get(2)
2114 .and_then(|el| el.clone().try_cast::<bool>())
2115 .ok_or_else(|| "required (#3) needs to be a bool".to_string())?;
2116
2117 Ok((el0, el1, el2))
2118 })
2119 .collect::<Result<Vec<(String, String, bool)>, Box<EvalAltResult>>>()?;
2120 builder = builder.with_param_settings(param_settings);
2121
2122 Ok(builder)
2123 }
2124
2125 /// Turns the builder into a [`Body`] structure
2126 ///
2127 /// # Errors
2128 ///
2129 /// This function will return `Err` if the provided `builder` was set up with incomplete or
2130 /// incorrect data.
2131 #[rhai_fn(global, return_raw)]
2132 pub fn build(builder: AddBuilder) -> Result<Body, Box<EvalAltResult>> {
2133 Ok(builder.build().map_err(|e| e.to_string())?)
2134 }
2135}
2136
2137/// Supply Rusp AddResp Message functionality
2138/// ```
2139/// // Rhai script
2140/// # let script = r#"
2141/// let created_objs = [
2142/// rusp::addresp_created_obj_failure("Foo", 7004, ""),
2143/// rusp::addresp_created_obj_success("Foo", "Foo.Bar.1", [["Bar", 7004, ""]], #{"Foo": "Bar"})
2144/// ];
2145/// let body = rusp::addresp_builder()
2146/// .with_created_obj_results(created_objs)
2147/// .build();
2148/// rusp::msg_builder()
2149/// .with_msg_id("Foo")
2150/// .with_body(body)
2151/// .build()
2152/// # "#;
2153/// # let msg = rhai_rusp::eval_rusp::<rusp_lib::usp::Msg>(script).unwrap();
2154/// # assert!(!msg.is_error());
2155/// # assert!(!msg.is_request());
2156/// # assert!(msg.is_response());
2157/// ```
2158#[export_module]
2159pub mod rhai_rusp_addresp {
2160 use usp_builder::{
2161 AddOperationStatus, AddRespBuilder, AddRespParameterError, CreatedObjectResultsBuilder,
2162 };
2163
2164 /// Sets up a new USP `AddRespBuilder`
2165 #[must_use]
2166 pub const fn addresp_builder() -> AddRespBuilder {
2167 AddRespBuilder::new()
2168 }
2169
2170 #[rhai_fn(global)]
2171 #[must_use]
2172 pub fn with_created_obj_results(
2173 builder: AddRespBuilder,
2174 created_obj_results: Array,
2175 ) -> AddRespBuilder {
2176 let created_obj_results = created_obj_results.into_iter().map(Dynamic::cast).collect();
2177 builder.with_created_obj_results(created_obj_results)
2178 }
2179
2180 #[rhai_fn(global)]
2181 #[must_use]
2182 pub fn addresp_created_obj_failure(
2183 requested_path: &str,
2184 err_code: i64,
2185 err_msg: &str,
2186 ) -> CreatedObjectResultsBuilder {
2187 let oper_status = AddOperationStatus::new().set_failure(
2188 u32::try_from(err_code).unwrap_or(7003),
2189 (!err_msg.is_empty()).then_some(err_msg.into()),
2190 );
2191 CreatedObjectResultsBuilder::new(requested_path.into(), oper_status)
2192 }
2193
2194 ///
2195 /// # Errors
2196 ///
2197 /// This function will return `Err` if the provided `param_errs` cannot be converted into
2198 /// an array of type `(String, u32, String)`.
2199 #[rhai_fn(global, return_raw)]
2200 pub fn addresp_created_obj_success(
2201 requested_path: &str,
2202 instantiated_path: &str,
2203 param_errs: Array,
2204 unique_keys: Map,
2205 ) -> Result<CreatedObjectResultsBuilder, Box<EvalAltResult>> {
2206 let param_errs = param_errs
2207 .into_iter()
2208 .map(|p| {
2209 let el = p.try_cast::<Array>()
2210 .ok_or_else(|| "Expected to have an array of arrays [param: &str, err_code: u32, err_msg: &str]".to_string())?;
2211 let el0 = el.first()
2212 .and_then(|el| el.clone().try_cast::<String>())
2213 .ok_or_else(|| "param (#1) needs to be a string".to_string())?;
2214 let el1 = el.get(1)
2215 .and_then(|el| el.clone().try_cast::<i64>())
2216 .ok_or_else(|| "err_code (#2) needs to be a u32".to_string())?;
2217 let el2 = el.get(2)
2218 .and_then(|el| el.clone().try_cast::<String>())
2219 .ok_or_else(|| "err_msg (#3) needs to be a string".to_string())?;
2220
2221 Ok(AddRespParameterError{param: el0, err_code: u32::try_from(el1).unwrap_or(7003) , err_msg: el2 })
2222 })
2223 .collect::<Result<Vec<AddRespParameterError>, Box<EvalAltResult>>>()?;
2224
2225 let unique_keys = unique_keys
2226 .iter()
2227 .map(|(k, v)| (k.to_string(), v.to_string()))
2228 .collect();
2229
2230 Ok(CreatedObjectResultsBuilder::new(
2231 requested_path.into(),
2232 AddOperationStatus::new().set_success(
2233 instantiated_path.into(),
2234 param_errs,
2235 unique_keys,
2236 ),
2237 ))
2238 }
2239
2240 /// Turns the builder into a [`Body`] structure
2241 ///
2242 /// # Errors
2243 ///
2244 /// This function will return `Err` if the provided `builder` was set up with incomplete or
2245 /// incorrect data.
2246 #[rhai_fn(global, return_raw)]
2247 pub fn build(builder: AddRespBuilder) -> Result<Body, Box<EvalAltResult>> {
2248 Ok(builder.build().map_err(|e| e.to_string())?)
2249 }
2250}
2251
2252/// Supply Rusp Notify Message functionality
2253///
2254/// This module facilities the assembly of [USP Notify
2255/// Message](https://usp.technology/specification/index.htm#sec:notify) [`bodies`](Body).
2256#[export_module]
2257pub mod rhai_rusp_notify {
2258 use usp_builder::NotifyBuilder;
2259
2260 /// Sets up a new USP `NotifyBuilder`
2261 #[must_use]
2262 pub fn notify_builder(subscription_id: &str) -> NotifyBuilder {
2263 usp_builder::NotifyBuilder::new(subscription_id.into())
2264 }
2265
2266 /// Set a notification body of type `ValueChange`
2267 ///
2268 /// ```
2269 /// // Rhai script
2270 /// # let script = r#"
2271 /// let body = rusp::notify_builder("not-sub")
2272 /// .with_event("Device.", "Boot!", #{"CommandKey": "ck"})
2273 /// .build();
2274 /// rusp::msg_builder()
2275 /// .with_msg_id("Foo")
2276 /// .with_body(body)
2277 /// .build()
2278 /// # "#;
2279 /// # let msg = rhai_rusp::eval_rusp::<rusp_lib::usp::Msg>(script).unwrap();
2280 /// # assert!(!msg.is_error());
2281 /// # assert!(msg.is_request());
2282 /// # assert!(!msg.is_response());
2283 /// ```
2284 #[rhai_fn(global)]
2285 #[must_use]
2286 pub fn with_event(
2287 builder: NotifyBuilder,
2288 obj_path: &str,
2289 event_name: &str,
2290 params: Map,
2291 ) -> NotifyBuilder {
2292 let params = params
2293 .iter()
2294 .map(|(k, v)| (k.to_string(), v.to_string()))
2295 .collect();
2296 builder.with_event(obj_path.into(), event_name.into(), params)
2297 }
2298
2299 /// Set a notification body of type `ValueChange`
2300 ///
2301 /// ```
2302 /// // Rhai script
2303 /// # let script = r#"
2304 /// let body = rusp::notify_builder("not-sub")
2305 /// .with_value_change("Device.Foo", "bar")
2306 /// .build();
2307 /// rusp::msg_builder()
2308 /// .with_msg_id("Foo")
2309 /// .with_body(body)
2310 /// .build()
2311 /// # "#;
2312 /// # let msg = rhai_rusp::eval_rusp::<rusp_lib::usp::Msg>(script).unwrap();
2313 /// # assert!(!msg.is_error());
2314 /// # assert!(msg.is_request());
2315 /// # assert!(!msg.is_response());
2316 /// ```
2317 #[rhai_fn(global)]
2318 #[must_use]
2319 pub fn with_value_change(
2320 builder: NotifyBuilder,
2321 param_path: &str,
2322 param_value: &str,
2323 ) -> NotifyBuilder {
2324 builder.with_value_change(param_path.into(), param_value.into())
2325 }
2326
2327 /// Set a notification body of type `ObjectCreation`
2328 ///
2329 /// ```
2330 /// // Rhai script
2331 /// # let script = r#"
2332 /// let body = rusp::notify_builder("not-sub")
2333 /// .with_send_resp(true)
2334 /// .with_object_creation("Device.Foo.1.", #{"Alias": "cpe-01"})
2335 /// .build();
2336 /// rusp::msg_builder()
2337 /// .with_msg_id("Foo")
2338 /// .with_body(body)
2339 /// .build()
2340 /// # "#;
2341 /// # let msg = rhai_rusp::eval_rusp::<rusp_lib::usp::Msg>(script).unwrap();
2342 /// # assert!(!msg.is_error());
2343 /// # assert!(msg.is_request());
2344 /// # assert!(!msg.is_response());
2345 /// ```
2346 #[rhai_fn(global)]
2347 #[must_use]
2348 pub fn with_object_creation(
2349 builder: NotifyBuilder,
2350 obj_path: &str,
2351 unique_keys: Map,
2352 ) -> NotifyBuilder {
2353 let unique_keys = unique_keys
2354 .iter()
2355 .map(|(k, v)| (k.to_string(), v.to_string()))
2356 .collect();
2357 builder.with_object_creation(obj_path.into(), unique_keys)
2358 }
2359
2360 /// Set a notification body of type `ObjectDeletion`
2361 ///
2362 /// ```
2363 /// // Rhai script
2364 /// # let script = r#"
2365 /// let body = rusp::notify_builder("not-sub")
2366 /// .with_send_resp(true)
2367 /// .with_object_deletion("Device.Foo.1.")
2368 /// .build();
2369 /// rusp::msg_builder()
2370 /// .with_msg_id("Foo")
2371 /// .with_body(body)
2372 /// .build()
2373 /// # "#;
2374 /// # let msg = rhai_rusp::eval_rusp::<rusp_lib::usp::Msg>(script).unwrap();
2375 /// # assert!(!msg.is_error());
2376 /// # assert!(msg.is_request());
2377 /// # assert!(!msg.is_response());
2378 /// ```
2379 #[rhai_fn(global)]
2380 #[must_use]
2381 pub fn with_object_deletion(builder: NotifyBuilder, obj_path: &str) -> NotifyBuilder {
2382 builder.with_object_deletion(obj_path.into())
2383 }
2384
2385 /// Set a notification body of type `OperationComplete` with success
2386 ///
2387 /// ```
2388 /// // Rhai script
2389 /// # let script = r#"
2390 /// let body = rusp::notify_builder("not-sub")
2391 /// .with_send_resp(true)
2392 /// .with_operation_complete_output_args("Device.", "Reboot()", "Foo", #{"Status": "Complete", "Results": ""})
2393 /// .build();
2394 /// rusp::msg_builder()
2395 /// .with_msg_id("Foo")
2396 /// .with_body(body)
2397 /// .build()
2398 /// # "#;
2399 /// # let msg = rhai_rusp::eval_rusp::<rusp_lib::usp::Msg>(script).unwrap();
2400 /// # assert!(!msg.is_error());
2401 /// # assert!(msg.is_request());
2402 /// # assert!(!msg.is_response());
2403 /// ```
2404 #[rhai_fn(global)]
2405 #[must_use]
2406 pub fn with_operation_complete_output_args(
2407 builder: NotifyBuilder,
2408 obj_path: &str,
2409 command_name: &str,
2410 command_key: &str,
2411 output_args: Map,
2412 ) -> NotifyBuilder {
2413 let output_args = output_args
2414 .iter()
2415 .map(|(k, v)| (k.to_string(), v.to_string()))
2416 .collect();
2417 builder.with_operation_complete_output_args(
2418 obj_path.into(),
2419 command_name.into(),
2420 command_key.into(),
2421 output_args,
2422 )
2423 }
2424
2425 /// Set a notification body of type `OperationComplete` with failure
2426 ///
2427 /// ```
2428 /// // Rhai script
2429 /// # let script = r#"
2430 /// let body = rusp::notify_builder("not-sub")
2431 /// .with_send_resp(true)
2432 /// .with_operation_complete_cmd_failure("Device.", "Reboot()", "Foo", 7002, "Don't want to")
2433 /// .build();
2434 /// rusp::msg_builder()
2435 /// .with_msg_id("Foo")
2436 /// .with_body(body)
2437 /// .build()
2438 /// # "#;
2439 /// # let msg = rhai_rusp::eval_rusp::<rusp_lib::usp::Msg>(script).unwrap();
2440 /// # assert!(!msg.is_error());
2441 /// # assert!(msg.is_request());
2442 /// # assert!(!msg.is_response());
2443 /// ```
2444 #[rhai_fn(global)]
2445 #[must_use]
2446 pub fn with_operation_complete_cmd_failure(
2447 builder: NotifyBuilder,
2448 obj_path: &str,
2449 command_name: &str,
2450 command_key: &str,
2451 err_code: i64,
2452 err_msg: &str,
2453 ) -> NotifyBuilder {
2454 builder.with_operation_complete_cmd_failure(
2455 obj_path.into(),
2456 command_name.into(),
2457 command_key.into(),
2458 u32::try_from(err_code).unwrap_or(7003),
2459 err_msg.into(),
2460 )
2461 }
2462
2463 /// Set a notification body of type `OnBoardRequest`
2464 ///
2465 /// ```
2466 /// // Rhai script
2467 /// # let script = r#"
2468 /// let body = rusp::notify_builder("not-sub")
2469 /// .with_send_resp(true)
2470 /// .with_onboard_request("00CAFE", "None", "000111", "1.3")
2471 /// .build();
2472 /// rusp::msg_builder()
2473 /// .with_msg_id("Foo")
2474 /// .with_body(body)
2475 /// .build()
2476 /// # "#;
2477 /// # let msg = rhai_rusp::eval_rusp::<rusp_lib::usp::Msg>(script).unwrap();
2478 /// # assert!(!msg.is_error());
2479 /// # assert!(msg.is_request());
2480 /// # assert!(!msg.is_response());
2481 /// ```
2482 #[rhai_fn(global)]
2483 #[must_use]
2484 pub fn with_onboard_request(
2485 builder: NotifyBuilder,
2486 oui: &str,
2487 product_class: &str,
2488 serial_number: &str,
2489 aspv: &str,
2490 ) -> NotifyBuilder {
2491 builder.with_onboard_request(
2492 oui.into(),
2493 product_class.into(),
2494 serial_number.into(),
2495 aspv.into(),
2496 )
2497 }
2498
2499 /// Sets the `send_resp` flag in the notification
2500 ///
2501 /// Setting this to `true` causes the recipient to acknowledge the received notification.
2502 /// Conversely, setting this to `false` also disables the retry mechanism so it should usually
2503 /// be set to `true`.
2504 ///
2505 /// ```
2506 /// // Rhai script
2507 /// # let script = r#"
2508 /// let body = rusp::notify_builder("not-sub")
2509 /// .with_send_resp(true)
2510 /// .with_operation_complete_cmd_failure("Device.", "Reboot()", "Foo", 7002, "Don't want to")
2511 /// .build();
2512 /// rusp::msg_builder()
2513 /// .with_msg_id("Foo")
2514 /// .with_body(body)
2515 /// .build()
2516 /// # "#;
2517 /// # let msg = rhai_rusp::eval_rusp::<rusp_lib::usp::Msg>(script).unwrap();
2518 /// # assert!(!msg.is_error());
2519 /// # assert!(msg.is_request());
2520 /// # assert!(!msg.is_response());
2521 /// ```
2522 #[rhai_fn(global)]
2523 #[must_use]
2524 pub const fn with_send_resp(builder: NotifyBuilder, send_resp: bool) -> NotifyBuilder {
2525 builder.with_send_resp(send_resp)
2526 }
2527
2528 /// Turns the builder into a [`Body`] structure
2529 ///
2530 /// # Errors
2531 ///
2532 /// This function will return `Err` if the provided `builder` was set up with incomplete or
2533 /// incorrect data.
2534 #[rhai_fn(global, return_raw)]
2535 pub fn build(builder: NotifyBuilder) -> Result<Body, Box<EvalAltResult>> {
2536 Ok(builder.build().map_err(|e| e.to_string())?)
2537 }
2538}
2539
2540/// Supply Rusp NotifyResp Message functionality
2541/// ```
2542/// let msg = rhai_rusp::eval_rusp::<rusp_lib::usp::Msg>(r#"
2543/// let body = rusp::notifyresp_builder("sub")
2544/// .build();
2545/// rusp::msg_builder()
2546/// .with_msg_id("Foo")
2547/// .with_body(body)
2548/// .build()
2549/// "#).unwrap();
2550/// assert!(!msg.is_error());
2551/// assert!(!msg.is_request());
2552/// assert!(msg.is_response());
2553/// ```
2554#[export_module]
2555pub mod rhai_rusp_notifyresp {
2556 use usp_builder::NotifyRespBuilder;
2557
2558 /// Sets up a new USP `NotifyRespBuilder`
2559 #[must_use]
2560 pub fn notifyresp_builder(subscription_id: &str) -> NotifyRespBuilder {
2561 usp_builder::NotifyRespBuilder::new(subscription_id.into())
2562 }
2563
2564 /// Turns the builder into a [`Body`] structure
2565 ///
2566 /// # Errors
2567 ///
2568 /// This function will return `Err` if the provided `builder` was set up with incomplete or
2569 /// incorrect data.
2570 #[rhai_fn(global, return_raw)]
2571 pub fn build(builder: NotifyRespBuilder) -> Result<Body, Box<EvalAltResult>> {
2572 Ok(builder.build().map_err(|e| e.to_string())?)
2573 }
2574}
2575
2576/// Supply Rusp Operate Message functionality
2577/// ```
2578/// # let script = r#"
2579/// // Rhai script
2580/// let body = rusp::operate_builder("Device.Reboot()")
2581/// .with_command_key("Command")
2582/// .with_send_resp(true)
2583/// .with_input_args(#{"Foo": "Bar", "Baz": "Bam"})
2584/// .build();
2585/// rusp::msg_builder()
2586/// .with_msg_id("Foo")
2587/// .with_body(body)
2588/// .build()
2589/// # "#;
2590/// # let msg = rhai_rusp::eval_rusp::<rusp_lib::usp::Msg>(script).unwrap();
2591/// # assert!(!msg.is_error());
2592/// # assert!(msg.is_request());
2593/// # assert!(!msg.is_response());
2594/// ```
2595#[export_module]
2596pub mod rhai_rusp_operate {
2597 use usp_builder::OperateBuilder;
2598
2599 /// Sets up a new USP `OperateBuilder`
2600 #[must_use]
2601 pub fn operate_builder(command: &str) -> OperateBuilder {
2602 OperateBuilder::new(command.into())
2603 }
2604
2605 #[rhai_fn(global)]
2606 #[must_use]
2607 pub fn with_command_key(builder: OperateBuilder, command_key: &str) -> OperateBuilder {
2608 builder.with_command_key(command_key.into())
2609 }
2610
2611 #[rhai_fn(global)]
2612 #[must_use]
2613 pub const fn with_send_resp(builder: OperateBuilder, send_resp: bool) -> OperateBuilder {
2614 builder.with_send_resp(send_resp)
2615 }
2616
2617 #[rhai_fn(global)]
2618 #[must_use]
2619 pub fn with_input_args(builder: OperateBuilder, input_args: Map) -> OperateBuilder {
2620 let input_args = input_args
2621 .iter()
2622 .map(|(k, v)| (k.to_string(), v.to_string()))
2623 .collect();
2624 builder.with_input_args(input_args)
2625 }
2626
2627 /// Turns the builder into a [`Body`] structure
2628 ///
2629 /// # Errors
2630 ///
2631 /// This function will return `Err` if the provided `builder` was set up with incomplete or
2632 /// incorrect data.
2633 #[rhai_fn(global, return_raw)]
2634 pub fn build(builder: OperateBuilder) -> Result<Body, Box<EvalAltResult>> {
2635 Ok(builder.build().map_err(|e| e.to_string())?)
2636 }
2637}
2638
2639/// Supply Rusp OperateResp Message functionality
2640/// ```
2641/// // Rhai script
2642/// # let script = r#"
2643/// let oper_results = [
2644/// rusp::operateresp_result_failure("Device.SelfTestDiagnostics()", 7004, ""),
2645/// rusp::operateresp_result_path("Device.Foo()", "Device.LocalAgent.Request.25."),
2646/// rusp::operateresp_result_output_args("Device.Bar()", #{"Baz": "Foo"}),
2647/// ];
2648/// let body = rusp::operateresp_builder()
2649/// .with_operation_results(oper_results)
2650/// .build();
2651/// rusp::msg_builder()
2652/// .with_msg_id("Foo")
2653/// .with_body(body)
2654/// .build()
2655/// # "#;
2656/// # let msg = rhai_rusp::eval_rusp::<rusp_lib::usp::Msg>(script).unwrap();
2657/// # assert!(!msg.is_error());
2658/// # assert!(!msg.is_request());
2659/// # assert!(msg.is_response());
2660/// ```
2661#[export_module]
2662pub mod rhai_rusp_operateresp {
2663 use usp_builder::{OperateRespBuilder, OperateRespResultBuilder};
2664
2665 /// Sets up a new USP `OperateRespBuilder`
2666 #[must_use]
2667 pub const fn operateresp_builder() -> OperateRespBuilder {
2668 OperateRespBuilder::new()
2669 }
2670
2671 #[rhai_fn(global)]
2672 #[must_use]
2673 pub fn with_operation_results(
2674 builder: OperateRespBuilder,
2675 operation_results: Array,
2676 ) -> OperateRespBuilder {
2677 let operation_results = operation_results.into_iter().map(Dynamic::cast).collect();
2678 builder.with_operation_results(operation_results)
2679 }
2680
2681 #[rhai_fn(global)]
2682 #[must_use]
2683 pub fn operateresp_result_failure(
2684 executed_command: &str,
2685 err_code: i64,
2686 err_msg: &str,
2687 ) -> OperateRespResultBuilder {
2688 OperateRespResultBuilder::new(executed_command.into()).set_failure(
2689 u32::try_from(err_code).unwrap_or(7003),
2690 (!err_msg.is_empty()).then_some(err_msg.into()),
2691 )
2692 }
2693
2694 #[rhai_fn(global)]
2695 #[must_use]
2696 pub fn operateresp_result_path(
2697 executed_command: &str,
2698 req_obj_path: &str,
2699 ) -> OperateRespResultBuilder {
2700 OperateRespResultBuilder::new(executed_command.into()).set_path(req_obj_path.into())
2701 }
2702
2703 #[rhai_fn(global)]
2704 #[must_use]
2705 pub fn operateresp_result_output_args(
2706 executed_command: &str,
2707 output_args: Map,
2708 ) -> OperateRespResultBuilder {
2709 let output_args = output_args
2710 .iter()
2711 .map(|(k, v)| (k.to_string(), v.to_string()))
2712 .collect();
2713
2714 OperateRespResultBuilder::new(executed_command.into()).set_output_args(output_args)
2715 }
2716
2717 /// Turns the builder into a [`Body`] structure
2718 ///
2719 /// # Errors
2720 ///
2721 /// This function will return `Err` if the provided `builder` was set up with incomplete or
2722 /// incorrect data.
2723 #[rhai_fn(global, return_raw)]
2724 pub fn build(builder: OperateRespBuilder) -> Result<Body, Box<EvalAltResult>> {
2725 Ok(builder.build().map_err(|e| e.to_string())?)
2726 }
2727}
2728
2729/// Supply Rusp de-/serialization functionality
2730/// ```
2731/// // Rhai script
2732/// let script = r#"
2733/// rusp::record_builder()
2734/// .with_version("1.3")
2735/// .with_to_id("proto::to")
2736/// .with_from_id("proto::from")
2737/// .as_websocket_connect_record()
2738/// .build()
2739/// .to_string()
2740/// "#;
2741/// let record = rhai_rusp::eval_rusp::<String>(script).unwrap();
2742///
2743/// assert_eq!(record, "{\n \"version\": \"1.3\",\n \"to_id\": \"proto::to\",\n \"from_id\": \"proto::from\",\n \"payload_security\": \"PLAINTEXT\",\n \"mac_signature\": [],\n \"sender_cert\": [],\n \"websocket_connect\": null\n}");
2744/// ```
2745#[export_module]
2746pub mod rhai_rusp {
2747 use std::io::{Read, Write as _};
2748
2749 use rusp_lib::usp_decoder::{try_decode_msg, try_decode_record};
2750 use usp_builder::{MsgBuilder, RecordBuilder};
2751 use usp_record::mod_Record::OneOfrecord_type;
2752
2753 /// Creates a new [`MsgBuilder`] with the given message [`Body`]. This is a shortcut to directly
2754 /// chain operations without using nested calls.
2755 /// ```
2756 /// // Rhai script
2757 /// # let script = r#"
2758 /// let msg =
2759 /// rusp::get_builder().with_max_depth(1).with_params(["Device."]).build().as_msg_builder().with_msg_id("id").build();
2760 /// msg.to_string()
2761 /// # "#;
2762 /// # let msg = rhai_rusp::eval_rusp::<String>(script).unwrap();
2763 /// # assert_eq!(msg, "{\n \"Header\": {\n \"msg_id\": \"id\",\n \"msg_type\": \"GET\"\n },\n \"Body\": {\n \"Request\": {\n \"Get\": {\n \"param_paths\": [\n \"Device.\"\n ],\n \"max_depth\": 1\n }\n }\n }\n}");
2764 /// ```
2765 ///
2766 /// This example will return a JSON output like:
2767 /// ```text
2768 /// {
2769 /// "Header": {
2770 /// "msg_id": "id",
2771 /// "msg_type": "GET"
2772 /// },
2773 /// "Body": {
2774 /// "Request": {
2775 /// "Get": {
2776 /// "param_paths": [
2777 /// "Device."
2778 /// ],
2779 /// "max_depth": 1
2780 /// }
2781 /// }
2782 /// }
2783 /// }
2784 /// ```
2785 ///
2786 /// # Errors
2787 ///
2788 /// This function will return `Err` containing a textual description of the encountered error if
2789 /// the conversion into a `MsgBuilder` fails.
2790 #[rhai_fn(global, return_raw)]
2791 pub fn as_msg_builder(body: Body) -> Result<MsgBuilder, Box<EvalAltResult>> {
2792 Ok(MsgBuilder::new().with_body(body))
2793 }
2794
2795 /// Creates a new [`RecordBuilder`] with the given [`MsgBuilder`] as "no_session_context"
2796 /// payload. This is a shortcut to directly chain operations without using nested calls.
2797 /// This function is polymorphic in Rhai and available as `as_no_session_record_builder()`
2798 /// ```
2799 /// // Rhai script
2800 /// # let script = r#"
2801 /// let msg =
2802 /// rusp::get_builder().with_params(["Device."]).build().as_msg_builder().with_msg_id("id").as_no_session_record_builder().with_to_id("proto::to").with_from_id("proto::from").build();
2803 /// msg.to_string()
2804 /// # "#;
2805 /// # let msg = rhai_rusp::eval_rusp::<String>(script).unwrap();
2806 /// # assert_eq!(msg, "{\n \"version\": \"1.4\",\n \"to_id\": \"proto::to\",\n \"from_id\": \"proto::from\",\n \"payload_security\": \"PLAINTEXT\",\n \"mac_signature\": [],\n \"sender_cert\": [],\n \"payload\": {\n \"Header\": {\n \"msg_id\": \"id\",\n \"msg_type\": \"GET\"\n },\n \"Body\": {\n \"Request\": {\n \"Get\": {\n \"param_paths\": [\n \"Device.\"\n ],\n \"max_depth\": 0\n }\n }\n }\n }\n}");
2807 /// ```
2808 ///
2809 /// This example will return a JSON output like:
2810 /// ```text
2811 /// {
2812 /// "version": "1.4",
2813 /// "to_id": "proto::to",
2814 /// "from_id": "proto::from",
2815 /// "payload_security": "PLAINTEXT",
2816 /// "mac_signature": [],
2817 /// "sender_cert": [],
2818 /// "payload": {
2819 /// "Header": {
2820 /// "msg_id": "id",
2821 /// "msg_type": "GET"
2822 /// },
2823 /// "Body": {
2824 /// "Request": {
2825 /// "Get": {
2826 /// "param_paths": [
2827 /// "Device."
2828 /// ],
2829 /// "max_depth": 0
2830 /// }
2831 /// }
2832 /// }
2833 /// }
2834 /// }
2835 /// ```
2836 ///
2837 /// # Errors
2838 ///
2839 /// This function will return `Err` containing a textual description of the encountered error if
2840 /// the conversion into a `RecordBuilder` fails.
2841 #[rhai_fn(global, name = "as_no_session_record_builder", return_raw)]
2842 pub fn msg_builder_as_no_session_record_builder(
2843 builder: MsgBuilder,
2844 ) -> Result<RecordBuilder, Box<EvalAltResult>> {
2845 let msg = builder.build().map_err(|e| e.to_string())?;
2846 Ok(RecordBuilder::new().with_no_session_context_payload(&msg))
2847 }
2848
2849 /// Creates a new [`RecordBuilder`] with the given [`Msg`] as "no_session_context"
2850 /// payload. This is a shortcut to directly chain operations without using nested calls.
2851 /// This function is polymorphic in Rhai and available as `as_no_session_record_builder()`
2852 /// ```
2853 /// // Rhai script
2854 /// # let script = r#"
2855 /// let msg =
2856 /// rusp::get_builder().with_params(["Device."]).build().as_msg_builder().with_msg_id("id").build().as_no_session_record_builder().with_to_id("proto::to").with_from_id("proto::from").build();
2857 /// msg.to_string()
2858 /// # "#;
2859 /// # let msg = rhai_rusp::eval_rusp::<String>(script).unwrap();
2860 /// # assert_eq!(msg, "{\n \"version\": \"1.4\",\n \"to_id\": \"proto::to\",\n \"from_id\": \"proto::from\",\n \"payload_security\": \"PLAINTEXT\",\n \"mac_signature\": [],\n \"sender_cert\": [],\n \"payload\": {\n \"Header\": {\n \"msg_id\": \"id\",\n \"msg_type\": \"GET\"\n },\n \"Body\": {\n \"Request\": {\n \"Get\": {\n \"param_paths\": [\n \"Device.\"\n ],\n \"max_depth\": 0\n }\n }\n }\n }\n}");
2861 /// ```
2862 ///
2863 /// This example will return a JSON output like:
2864 /// ```text
2865 /// {
2866 /// "version": "1.4",
2867 /// "to_id": "proto::to",
2868 /// "from_id": "proto::from",
2869 /// "payload_security": "PLAINTEXT",
2870 /// "mac_signature": [],
2871 /// "sender_cert": [],
2872 /// "payload": {
2873 /// "Header": {
2874 /// "msg_id": "id",
2875 /// "msg_type": "GET"
2876 /// },
2877 /// "Body": {
2878 /// "Request": {
2879 /// "Get": {
2880 /// "param_paths": [
2881 /// "Device."
2882 /// ],
2883 /// "max_depth": 0
2884 /// }
2885 /// }
2886 /// }
2887 /// }
2888 /// }
2889 /// ```
2890 ///
2891 /// # Errors
2892 ///
2893 /// This function will return `Err` containing a textual description of the encountered error
2894 /// if the conversion into a `RecordBuilder` fails.
2895 #[rhai_fn(global, name = "as_no_session_record_builder", return_raw)]
2896 pub fn msg_as_no_session_record_builder(msg: Msg) -> Result<RecordBuilder, Box<EvalAltResult>> {
2897 Ok(RecordBuilder::new().with_no_session_context_payload(&msg))
2898 }
2899
2900 /// Render a USP Body into JSON format, this function is polymorphic in Rhai and available as `to_string()`
2901 /// ```
2902 /// // Rhai script
2903 /// # let script = r#"
2904 /// let body = rusp::get_builder().with_max_depth(1).with_params(["Device."]).build();
2905 /// body.to_string()
2906 /// # "#;
2907 /// # let msg = rhai_rusp::eval_rusp::<String>(script).unwrap();
2908 /// # assert_eq!(msg, "{\n \"Request\": {\n \"Get\": {\n \"param_paths\": [\n \"Device.\"\n ],\n \"max_depth\": 1\n }\n }\n}");
2909 /// ```
2910 ///
2911 /// This example will return a JSON output like:
2912 /// ```text
2913 /// {
2914 /// "Request": {
2915 /// "Get": {
2916 /// "param_paths": [
2917 /// "Device."
2918 /// ],
2919 /// "max_depth": 1
2920 /// }
2921 /// }
2922 /// }
2923 /// ```
2924 ///
2925 /// `to_string()` is also implicitly called by the `print()` function
2926 ///
2927 /// # Errors
2928 ///
2929 /// This function will return `Err` containing a textual description of the encountered error if
2930 /// the serialization of the structure into JSON format fails.
2931 #[rhai_fn(global, name = "to_string", return_raw)]
2932 pub fn body_to_string(body: &mut Body) -> Result<String, Box<EvalAltResult>> {
2933 body_to_json(body)
2934 }
2935
2936 /// Render a [`Msg`] into JSON format, this function is polymorphic in Rhai and available as `to_string()`
2937 /// ```
2938 /// // Rhai script
2939 /// # let script = r#"
2940 /// let body = rusp::getsupportedprotocol_builder("1.3,1.4")
2941 /// .build();
2942 /// rusp::msg_builder()
2943 /// .with_msg_id("Foo")
2944 /// .with_body(body)
2945 /// .build()
2946 /// .to_string()
2947 /// # "#;
2948 /// # let msg = rhai_rusp::eval_rusp::<String>(script).unwrap();
2949 /// # assert_eq!(msg, "{\n \"Header\": {\n \"msg_id\": \"Foo\",\n \"msg_type\": \"GET_SUPPORTED_PROTO\"\n },\n \"Body\": {\n \"Request\": {\n \"GetSupportedProtocol\": {\n \"controller_supported_protocol_versions\": \"1.3,1.4\"\n }\n }\n }\n}");
2950 /// ```
2951 ///
2952 /// This example will return a JSON output like:
2953 /// ```text
2954 /// {
2955 /// "Header": {
2956 /// "msg_id": "Foo",
2957 /// "msg_type": "GET_SUPPORTED_PROTO"
2958 /// },
2959 /// "Body": {
2960 /// "Request": {
2961 /// "GetSupportedProtocol": {
2962 /// "controller_supported_protocol_versions": "1.3,1.4"
2963 /// }
2964 /// }
2965 /// }
2966 /// }
2967 /// ```
2968 ///
2969 /// `to_string()` is also implicitly called by the `print()` function
2970 ///
2971 /// # Errors
2972 ///
2973 /// This function will return `Err` containing a textual description of the encountered error if
2974 /// the serialization of the structure into JSON format fails.
2975 #[rhai_fn(global, name = "to_string", return_raw)]
2976 pub fn msg_to_string(msg: &mut Msg) -> Result<String, Box<EvalAltResult>> {
2977 msg_to_json(msg)
2978 }
2979
2980 /// Render a [`Record`] into JSON format, this function is polymorphic in Rhai and available as `to_string()`
2981 /// ```
2982 /// // Rhai script
2983 /// # let script = r#"
2984 /// rusp::record_builder()
2985 /// .with_version("1.3")
2986 /// .with_to_id("proto::to")
2987 /// .with_from_id("proto::from")
2988 /// .as_websocket_connect_record()
2989 /// .build()
2990 /// .to_string()
2991 /// # "#;
2992 /// # let record = rhai_rusp::eval_rusp::<String>(script).unwrap();
2993 /// # assert_eq!(record, "{\n \"version\": \"1.3\",\n \"to_id\": \"proto::to\",\n \"from_id\": \"proto::from\",\n \"payload_security\": \"PLAINTEXT\",\n \"mac_signature\": [],\n \"sender_cert\": [],\n \"websocket_connect\": null\n}");
2994 /// ```
2995 ///
2996 /// This example will return a JSON output like:
2997 /// ```text
2998 /// {
2999 /// "version": "1.3",
3000 /// "to_id": "proto::to",
3001 /// "from_id": "proto::from",
3002 /// "payload_security": "PLAINTEXT",
3003 /// "mac_signature": [],
3004 /// "sender_cert": [],
3005 /// "websocket_connect": null
3006 /// }
3007 /// ```
3008 ///
3009 /// `to_string()` is also implicitly called by the `print()` function
3010 ///
3011 /// # Errors
3012 ///
3013 /// This function will return `Err` containing a textual description of the encountered error if
3014 /// the serialization of the structure into JSON format fails.
3015 #[rhai_fn(global, name = "to_string", return_raw)]
3016 pub fn record_to_string(record: &mut Record) -> Result<String, Box<EvalAltResult>> {
3017 record_to_json(record)
3018 }
3019
3020 /// Render a USP Body into JSON format, this function is polymorphic in Rhai and available as `to_json()`
3021 /// ```
3022 /// // Rhai script
3023 /// # let script = r#"
3024 /// let body = rusp::get_builder().with_max_depth(1).with_params(["Device."]).build();
3025 /// body.to_json()
3026 /// # "#;
3027 /// # let msg = rhai_rusp::eval_rusp::<String>(script).unwrap();
3028 /// # assert_eq!(msg, "{\n \"Request\": {\n \"Get\": {\n \"param_paths\": [\n \"Device.\"\n ],\n \"max_depth\": 1\n }\n }\n}");
3029 /// ```
3030 ///
3031 /// This example will return a JSON output like:
3032 /// ```text
3033 /// {
3034 /// "Request": {
3035 /// "Get": {
3036 /// "param_paths": [
3037 /// "Device."
3038 /// ],
3039 /// "max_depth": 1
3040 /// }
3041 /// }
3042 /// }
3043 /// ```
3044 ///
3045 /// # Errors
3046 ///
3047 /// This function will return `Err` containing a textual description of the encountered error if
3048 /// the serialization of the structure into JSON format fails.
3049 #[rhai_fn(global, name = "to_json", return_raw)]
3050 pub fn body_to_json(body: &mut Body) -> Result<String, Box<EvalAltResult>> {
3051 Ok(serde_json::to_string_pretty(&body).map_err(|e| e.to_string())?)
3052 }
3053
3054 /// Render a [`Msg`] into JSON format, this function is polymorphic in Rhai and available as `to_json()`
3055 /// ```
3056 /// // Rhai script
3057 /// # let script = r#"
3058 /// let body = rusp::getsupportedprotocol_builder("1.3,1.4")
3059 /// .build();
3060 /// rusp::msg_builder()
3061 /// .with_msg_id("Foo")
3062 /// .with_body(body)
3063 /// .build()
3064 /// .to_json()
3065 /// # "#;
3066 /// # let msg = rhai_rusp::eval_rusp::<String>(script).unwrap();
3067 /// # assert_eq!(msg, "{\n \"Header\": {\n \"msg_id\": \"Foo\",\n \"msg_type\": \"GET_SUPPORTED_PROTO\"\n },\n \"Body\": {\n \"Request\": {\n \"GetSupportedProtocol\": {\n \"controller_supported_protocol_versions\": \"1.3,1.4\"\n }\n }\n }\n}");
3068 /// ```
3069 ///
3070 /// This example will return a JSON output like:
3071 /// ```text
3072 /// {
3073 /// "Header": {
3074 /// "msg_id": "Foo",
3075 /// "msg_type": "GET_SUPPORTED_PROTO"
3076 /// },
3077 /// "Body": {
3078 /// "Request": {
3079 /// "GetSupportedProtocol": {
3080 /// "controller_supported_protocol_versions": "1.3,1.4"
3081 /// }
3082 /// }
3083 /// }
3084 /// }
3085 /// ```
3086 ///
3087 /// # Errors
3088 ///
3089 /// This function will return `Err` containing a textual description of the encountered error if
3090 /// the serialization of the structure into JSON format fails.
3091 #[rhai_fn(global, name = "to_json", return_raw)]
3092 pub fn msg_to_json(msg: &mut Msg) -> Result<String, Box<EvalAltResult>> {
3093 Ok(serde_json::to_string_pretty(&msg).map_err(|e| e.to_string())?)
3094 }
3095
3096 /// Render a [`Msg`] into JSON format, this function is polymorphic in Rhai and available as `to_json()`
3097 /// ```
3098 /// // Rhai script
3099 /// # let script = r#"
3100 /// rusp::record_builder()
3101 /// .with_version("1.3")
3102 /// .with_to_id("proto::to")
3103 /// .with_from_id("proto::from")
3104 /// .as_websocket_connect_record()
3105 /// .build()
3106 /// .to_json()
3107 /// # "#;
3108 /// # let record = rhai_rusp::eval_rusp::<String>(script).unwrap();
3109 /// # assert_eq!(record, "{\n \"version\": \"1.3\",\n \"to_id\": \"proto::to\",\n \"from_id\": \"proto::from\",\n \"payload_security\": \"PLAINTEXT\",\n \"mac_signature\": [],\n \"sender_cert\": [],\n \"websocket_connect\": null\n}");
3110 /// ```
3111 ///
3112 /// This example will return a JSON output like:
3113 /// ```text
3114 /// {
3115 /// "version": "1.3",
3116 /// "to_id": "proto::to",
3117 /// "from_id": "proto::from",
3118 /// "payload_security": "PLAINTEXT",
3119 /// "mac_signature": [],
3120 /// "sender_cert": [],
3121 /// "websocket_connect": null
3122 /// }
3123 /// ```
3124 ///
3125 /// # Errors
3126 ///
3127 /// This function will return `Err` containing a textual description of the encountered error if
3128 /// the serialization of the structure into JSON format fails.
3129 #[rhai_fn(global, name = "to_json", return_raw)]
3130 pub fn record_to_json(record: &mut Record) -> Result<String, Box<EvalAltResult>> {
3131 Ok(serde_json::to_string_pretty(&record).map_err(|e| e.to_string())?)
3132 }
3133
3134 /// Render a USP Body into a Rhai Map, this function is polymorphic in Rhai and available as `to_map()`
3135 /// ```
3136 /// // Rhai script
3137 /// # let script = r#"
3138 /// let body = rusp::get_builder().with_max_depth(1).with_params(["Device."]).build().to_map();
3139 /// body.Request
3140 /// # "#;
3141 /// # let msg = rhai_rusp::eval_rusp::<rhai::Map>(script).unwrap();
3142 /// ```
3143 ///
3144 /// This example will return a Rhai Map like:
3145 /// ```text
3146 /// #{"Get": #{"max_depth": 1, "param_paths": ["Device."]}}
3147 /// ```
3148 ///
3149 /// # Errors
3150 ///
3151 /// This function will return `Err` containing a textual description of the encountered error if
3152 /// the serialization of the structure into a Rhai map fails.
3153 #[rhai_fn(global, name = "to_map", return_raw)]
3154 pub fn body_to_map(body: &mut Body) -> Result<Dynamic, Box<EvalAltResult>> {
3155 rhai::serde::to_dynamic(body)
3156 }
3157
3158 /// Render a [`Msg`] into a Rhai Map, this function is polymorphic in Rhai and available as `to_map()`
3159 /// ```
3160 /// // Rhai script
3161 /// # let script = r#"
3162 /// let body = rusp::getsupportedprotocol_builder("1.3,1.4")
3163 /// .build();
3164 /// let msg = rusp::msg_builder()
3165 /// .with_msg_id("Foo")
3166 /// .with_body(body)
3167 /// .build()
3168 /// .to_map();
3169 /// msg.Header
3170 /// # "#;
3171 /// # let msg = rhai_rusp::eval_rusp::<rhai::Map>(script).unwrap();
3172 /// ```
3173 ///
3174 /// This example will return a Rhai Map like:
3175 /// ```text
3176 /// #{"msg_id": "Foo", "msg_type": "GET_SUPPORTED_PROTO"}
3177 /// ```
3178 ///
3179 /// # Errors
3180 ///
3181 /// This function will return `Err` containing a textual description of the encountered error if
3182 /// the serialization of the structure into a Rhai map fails.
3183 #[rhai_fn(global, name = "to_map", return_raw)]
3184 pub fn msg_to_map(msg: &mut Msg) -> Result<Dynamic, Box<EvalAltResult>> {
3185 rhai::serde::to_dynamic(msg)
3186 }
3187
3188 /// Render a [`Record`] into a Rhai Map, this function is polymorphic in Rhai and available as `to_map()`
3189 /// ```
3190 /// // Rhai script
3191 /// # let script = r#"
3192 /// rusp::record_builder()
3193 /// .with_version("1.3")
3194 /// .with_to_id("proto::to")
3195 /// .with_from_id("proto::from")
3196 /// .as_websocket_connect_record()
3197 /// .build()
3198 /// .to_map()
3199 /// # "#;
3200 /// # let record = rhai_rusp::eval_rusp::<rhai::Map>(script).unwrap();
3201 /// # assert_eq!(record.get("version").and_then(|v| v.clone().into_string().ok()), Some("1.3".into()));
3202 /// ```
3203 ///
3204 /// This example will return a Rhai map like:
3205 /// ```text
3206 /// #{"from_id": "proto::from", "mac_signature": [], "payload_security": "PLAINTEXT", "sender_cert": [], "to_id": "proto::to", "version": "1.3", "websocket_connect": ()}
3207 /// ```
3208 ///
3209 /// # Errors
3210 ///
3211 /// This function will return `Err` containing a textual description of the encountered error if
3212 /// the serialization of the structure into a Rhai map fails.
3213 #[rhai_fn(global, name = "to_map", return_raw)]
3214 pub fn record_to_map(record: &mut Record) -> Result<Dynamic, Box<EvalAltResult>> {
3215 rhai::serde::to_dynamic(record)
3216 }
3217
3218 /// Render a [`Msg`] into C string format
3219 ///
3220 /// # Errors
3221 ///
3222 /// This function will return `Err` containing a textual description of the encountered error if
3223 /// the serialization of the structure into a C string fails.
3224 #[rhai_fn(global, name = "to_c_string", return_raw)]
3225 pub fn msg_to_c_string(msg: &mut Msg) -> Result<String, Box<EvalAltResult>> {
3226 Ok(msg.to_c_str().map_err(|e| e.to_string())?)
3227 }
3228
3229 /// Render a [`Record`] into C string format
3230 ///
3231 /// # Errors
3232 ///
3233 /// This function will return `Err` containing a textual description of the encountered error if
3234 /// the serialization of the structure into a C string fails.
3235 #[rhai_fn(global, name = "to_c_string", return_raw)]
3236 pub fn record_to_c_string(record: &mut Record) -> Result<String, Box<EvalAltResult>> {
3237 Ok(record.to_c_str().map_err(|e| e.to_string())?)
3238 }
3239
3240 /// Render a [`Msg`] into C array format, this function is polymorphic in Rhai and available as `to_c_array()`
3241 /// ```
3242 /// // Rhai script
3243 /// # let script = r#"
3244 /// let body = rusp::getsupportedprotocol_builder("1.3,1.4")
3245 /// .build();
3246 /// rusp::msg_builder()
3247 /// .with_msg_id("Foo")
3248 /// .with_body(body)
3249 /// .build()
3250 /// .to_c_array()
3251 /// # "#;
3252 /// # let msg = rhai_rusp::eval_rusp::<String>(script).unwrap();
3253 /// # assert_eq!(msg, "unsigned int pb_len = 24;\nconst char pb[] = {\n 0x0a, 0x07, 0x0a, 0x03, 0x46, 0x6f, 0x6f, 0x10, /* ____Foo_ */\n 0x11, 0x12, 0x0d, 0x0a, 0x0b, 0x4a, 0x09, 0x0a, /* _____J__ */\n 0x07, 0x31, 0x2e, 0x33, 0x2c, 0x31, 0x2e, 0x34, /* _1.3,1.4 */\n};\n");
3254 /// ```
3255 ///
3256 /// This example will return a string like:
3257 /// ```C
3258 /// unsigned int pb_len = 24;
3259 /// const char pb[] = {
3260 /// 0x0a, 0x07, 0x0a, 0x03, 0x46, 0x6f, 0x6f, 0x10, /* ____Foo_ */
3261 /// 0x11, 0x12, 0x0d, 0x0a, 0x0b, 0x4a, 0x09, 0x0a, /* _____J__ */
3262 /// 0x07, 0x31, 0x2e, 0x33, 0x2c, 0x31, 0x2e, 0x34, /* _1.3,1.4 */
3263 /// };
3264 /// ```
3265 ///
3266 /// # Errors
3267 ///
3268 /// This function will return `Err` containing a textual description of the encountered error if
3269 /// the serialization of the structure into a C array fails.
3270 #[rhai_fn(global, name = "to_c_array", return_raw)]
3271 pub fn msg_to_c_array(msg: &mut Msg) -> Result<String, Box<EvalAltResult>> {
3272 Ok(msg.to_c_array().map_err(|e| e.to_string())?)
3273 }
3274
3275 /// Render a [`Msg`] into C array format with a custom variable name, this function is polymorphic in Rhai and available as `to_c_array()`
3276 /// ```
3277 /// // Rhai script
3278 /// # let script = r#"
3279 /// let body = rusp::getsupportedprotocol_builder("1.3,1.4")
3280 /// .build();
3281 /// rusp::msg_builder()
3282 /// .with_msg_id("Foo")
3283 /// .with_body(body)
3284 /// .build()
3285 /// .to_c_array("msg")
3286 /// # "#;
3287 /// # let msg = rhai_rusp::eval_rusp::<String>(script).unwrap();
3288 /// # assert_eq!(msg, "unsigned int msg_len = 24;\nconst char msg[] = {\n 0x0a, 0x07, 0x0a, 0x03, 0x46, 0x6f, 0x6f, 0x10, /* ____Foo_ */\n 0x11, 0x12, 0x0d, 0x0a, 0x0b, 0x4a, 0x09, 0x0a, /* _____J__ */\n 0x07, 0x31, 0x2e, 0x33, 0x2c, 0x31, 0x2e, 0x34, /* _1.3,1.4 */\n};\n");
3289 /// ```
3290 ///
3291 /// This example will return a string like:
3292 /// ```C
3293 /// unsigned int msg_len = 24;
3294 /// const char msg[] = {
3295 /// 0x0a, 0x07, 0x0a, 0x03, 0x46, 0x6f, 0x6f, 0x10, /* ____Foo_ */
3296 /// 0x11, 0x12, 0x0d, 0x0a, 0x0b, 0x4a, 0x09, 0x0a, /* _____J__ */
3297 /// 0x07, 0x31, 0x2e, 0x33, 0x2c, 0x31, 0x2e, 0x34, /* _1.3,1.4 */
3298 /// };
3299 /// ```
3300 ///
3301 /// # Errors
3302 ///
3303 /// This function will return `Err` containing a textual description of the encountered error if
3304 /// the serialization of the structure into a C array fails.
3305 #[rhai_fn(global, name = "to_c_array", return_raw)]
3306 pub fn msg_to_c_array_custom(msg: &mut Msg, name: &str) -> Result<String, Box<EvalAltResult>> {
3307 Ok(msg.to_c_array_custom(name).map_err(|e| e.to_string())?)
3308 }
3309
3310 /// Render a [`Record`] into a C array variable, this function is polymorphic in Rhai and available as `to_c_array()`
3311 /// ```
3312 /// // Rhai script
3313 /// # let script = r#"
3314 /// rusp::record_builder()
3315 /// .with_version("1.3")
3316 /// .with_to_id("proto::to")
3317 /// .with_from_id("proto::from")
3318 /// .as_websocket_connect_record()
3319 /// .build()
3320 /// .to_c_array()
3321 /// # "#;
3322 /// # let record = rhai_rusp::eval_rusp::<String>(script).unwrap();
3323 /// # assert_eq!(record, "unsigned int pb_len = 31;\nconst char pb[] = {\n 0x0a, 0x03, 0x31, 0x2e, 0x33, 0x12, 0x09, 0x70, /* __1.3__p */\n 0x72, 0x6f, 0x74, 0x6f, 0x3a, 0x3a, 0x74, 0x6f, /* roto__to */\n 0x1a, 0x0b, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x3a, /* __proto_ */\n 0x3a, 0x66, 0x72, 0x6f, 0x6d, 0x4a, 0x00, /* _fromJ_ */\n};\n");
3324 /// ```
3325 ///
3326 /// This example will return a String like:
3327 /// ```C
3328 /// unsigned int pb_len = 31;
3329 /// const char pb[] = {
3330 /// 0x0a, 0x03, 0x31, 0x2e, 0x33, 0x12, 0x09, 0x70, /* __1.3__p */
3331 /// 0x72, 0x6f, 0x74, 0x6f, 0x3a, 0x3a, 0x74, 0x6f, /* roto__to */
3332 /// 0x1a, 0x0b, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x3a, /* __proto_ */
3333 /// 0x3a, 0x66, 0x72, 0x6f, 0x6d, 0x4a, 0x00, /* _fromJ_ */
3334 /// };
3335 /// ```
3336 ///
3337 /// # Errors
3338 ///
3339 /// This function will return `Err` containing a textual description of the encountered error if
3340 /// the serialization of the structure into a C array fails.
3341 #[rhai_fn(global, name = "to_c_array", return_raw)]
3342 pub fn record_to_c_array(record: &mut Record) -> Result<String, Box<EvalAltResult>> {
3343 Ok(record.to_c_array().map_err(|e| e.to_string())?)
3344 }
3345
3346 /// Render a [`Record`] into a C array variable with a custom name, this function is polymorphic in Rhai and available as `to_c_array()`
3347 /// ```
3348 /// // Rhai script
3349 /// # let script = r#"
3350 /// rusp::record_builder()
3351 /// .with_version("1.3")
3352 /// .with_to_id("proto::to")
3353 /// .with_from_id("proto::from")
3354 /// .as_websocket_connect_record()
3355 /// .build()
3356 /// .to_c_array("rec")
3357 /// # "#;
3358 /// # let record = rhai_rusp::eval_rusp::<String>(script).unwrap();
3359 /// # assert_eq!(record, "unsigned int rec_len = 31;\nconst char rec[] = {\n 0x0a, 0x03, 0x31, 0x2e, 0x33, 0x12, 0x09, 0x70, /* __1.3__p */\n 0x72, 0x6f, 0x74, 0x6f, 0x3a, 0x3a, 0x74, 0x6f, /* roto__to */\n 0x1a, 0x0b, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x3a, /* __proto_ */\n 0x3a, 0x66, 0x72, 0x6f, 0x6d, 0x4a, 0x00, /* _fromJ_ */\n};\n");
3360 /// ```
3361 ///
3362 /// This example will return a String like:
3363 /// ```C
3364 /// unsigned int rec_len = 31;
3365 /// const char rec[] = {
3366 /// 0x0a, 0x03, 0x31, 0x2e, 0x33, 0x12, 0x09, 0x70, /* __1.3__p */
3367 /// 0x72, 0x6f, 0x74, 0x6f, 0x3a, 0x3a, 0x74, 0x6f, /* roto__to */
3368 /// 0x1a, 0x0b, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x3a, /* __proto_ */
3369 /// 0x3a, 0x66, 0x72, 0x6f, 0x6d, 0x4a, 0x00, /* _fromJ_ */
3370 /// };
3371 /// ```
3372 ///
3373 /// # Errors
3374 ///
3375 /// This function will return `Err` containing a textual description of the encountered error if
3376 /// the serialization of the structure into a C array fails.
3377 #[rhai_fn(global, name = "to_c_array", return_raw)]
3378 pub fn record_to_c_array_custom(
3379 record: &mut Record,
3380 name: &str,
3381 ) -> Result<String, Box<EvalAltResult>> {
3382 Ok(record.to_c_array_custom(name).map_err(|e| e.to_string())?)
3383 }
3384
3385 /// Render a [`Msg`] into C array format and save it to the specified file
3386 ///
3387 /// # Errors
3388 ///
3389 /// This function will return `Err` containing a textual description of the encountered error
3390 /// if the serialization of the structure into a C array or the creation of the specified file
3391 /// fails.
3392 #[rhai_fn(global, name = "save_c_array", return_raw)]
3393 pub fn msg_save_c_array(msg: &mut Msg, filename: &str) -> Result<(), Box<EvalAltResult>> {
3394 let data = msg.to_c_array().map_err(|e| e.to_string())?;
3395 std::fs::write(filename, data).map_err(|e| e.to_string())?;
3396 Ok(())
3397 }
3398
3399 /// Render a [`Record`] into C array format and save it to the specified file
3400 ///
3401 /// # Errors
3402 ///
3403 /// This function will return `Err` containing a textual description of the encountered error
3404 /// if the serialization of the structure into a C array or the creation of the specified file
3405 /// fails.
3406 #[rhai_fn(global, name = "save_c_array", return_raw)]
3407 pub fn record_save_c_array(
3408 record: &mut Record,
3409 filename: &str,
3410 ) -> Result<(), Box<EvalAltResult>> {
3411 let data = record.to_c_array().map_err(|e| e.to_string())?;
3412 std::fs::write(filename, data).map_err(|e| e.to_string())?;
3413 Ok(())
3414 }
3415
3416 /// Render a [`Msg`] into Protobuf and print it to stdout
3417 ///
3418 /// # Errors
3419 ///
3420 /// This function will return `Err` containing a textual description of the encountered error
3421 /// if the serialization of the structure into Protobuf format fails.
3422 #[rhai_fn(global, name = "print_protobuf", return_raw)]
3423 pub fn msg_print_protobuf(msg: &mut Msg) -> Result<(), Box<EvalAltResult>> {
3424 std::io::stdout()
3425 .write_all(&msg.to_vec().map_err(|e| e.to_string())?)
3426 .map_err(|e| e.to_string())?;
3427 Ok(())
3428 }
3429
3430 /// Render a [`Record`] into Protobuf and print it to stdout
3431 ///
3432 /// # Errors
3433 ///
3434 /// This function will return `Err` containing a textual description of the encountered error
3435 /// if the serialization of the structure into Protobuf format fails.
3436 #[rhai_fn(global, name = "print_protobuf", return_raw)]
3437 pub fn record_print_protobuf(record: &mut Record) -> Result<(), Box<EvalAltResult>> {
3438 std::io::stdout()
3439 .write_all(&record.to_vec().map_err(|e| e.to_string())?)
3440 .map_err(|e| e.to_string())?;
3441 Ok(())
3442 }
3443
3444 /// Render a [`Msg`] into Protobuf and save it to the specified file
3445 ///
3446 /// # Errors
3447 ///
3448 /// This function will return `Err` containing a textual description of the encountered error
3449 /// if the serialization of the structure into Protobuf format or the creation of the specified file
3450 /// fails.
3451 #[rhai_fn(global, name = "save_protobuf", return_raw)]
3452 pub fn msg_save_protobuf(msg: &mut Msg, filename: &str) -> Result<(), Box<EvalAltResult>> {
3453 let data = msg.to_vec().map_err(|e| e.to_string())?;
3454 std::fs::File::create(filename)
3455 .and_then(|mut f| f.write_all(&data))
3456 .map_err(|e| e.to_string())?;
3457 Ok(())
3458 }
3459
3460 /// Render a [`Record`] into Protobuf and save it to the specified file
3461 ///
3462 /// # Errors
3463 ///
3464 /// This function will return `Err` containing a textual description of the encountered error
3465 /// if the serialization of the structure into Protobuf format or the creation of the specified file
3466 /// fails.
3467 #[rhai_fn(global, name = "save_protobuf", return_raw)]
3468 pub fn record_save_protobuf(
3469 record: &mut Record,
3470 filename: &str,
3471 ) -> Result<(), Box<EvalAltResult>> {
3472 let data = record.to_vec().map_err(|e| e.to_string())?;
3473 std::fs::File::create(filename)
3474 .and_then(|mut f| f.write_all(&data))
3475 .map_err(|e| e.to_string())?;
3476 Ok(())
3477 }
3478
3479 /// Extracts the [`Record`]'s payload. Returning [`Dynamic::UNIT`] for Records without payloads
3480 ///
3481 /// To avoid clones, this function leaves the used [`Record`] with an empty payload
3482 #[rhai_fn(global, name = "extract_msg")]
3483 pub fn record_extract_msg(record: &mut Record) -> Dynamic {
3484 match &mut record.record_type {
3485 OneOfrecord_type::session_context(ctx) => {
3486 let payload = ctx.payload_flatten();
3487 Dynamic::from_blob(mem::take(payload))
3488 }
3489 OneOfrecord_type::no_session_context(ctx) => {
3490 Dynamic::from_blob(mem::take(&mut ctx.payload))
3491 }
3492 _ => Dynamic::UNIT,
3493 }
3494 }
3495
3496 /// Parses a [`Msg`] from the provided Protobuf bytes
3497 ///
3498 /// # Errors
3499 ///
3500 /// This function will return `Err` when the deserialization of the structure from the Protobuf
3501 /// format fails
3502 #[rhai_fn(global, name = "parse_msg", return_raw)]
3503 pub fn parse_msg_protobuf(protobuf: &mut Blob) -> Result<Msg, Box<EvalAltResult>> {
3504 try_decode_msg(protobuf).map_err(|e| e.to_string().into())
3505 }
3506
3507 /// Read a [`Msg`] in Protobuf format from stdin. In Rhai this function is called `read_msg`.
3508 ///
3509 /// # Errors
3510 ///
3511 /// This function will return `Err` containing a textual description of the encountered error
3512 /// if the deserialization of the structure from Protobuf format fails.
3513 #[rhai_fn(global, name = "read_msg", return_raw)]
3514 pub fn read_msg_protobuf() -> Result<Msg, Box<EvalAltResult>> {
3515 let mut contents = Vec::new();
3516 std::io::stdin()
3517 .read_to_end(&mut contents)
3518 .map_err(|e| e.to_string())?;
3519 Ok(try_decode_msg(&contents).map_err(|e| e.to_string())?)
3520 }
3521
3522 /// Load a [`Msg`] from a Protobuf file. In Rhai this function is called `load_msg`
3523 ///
3524 /// # Errors
3525 ///
3526 /// This function will return `Err` containing a textual description of the encountered error
3527 /// if the file pointed to by the filename doesn't exist, is not readable or the
3528 /// deserialization of the structure from Protobuf format fails.
3529 #[rhai_fn(global, name = "load_msg", return_raw)]
3530 pub fn load_msg_protobuf(filename: &str) -> Result<Msg, Box<EvalAltResult>> {
3531 let mut contents = Vec::new();
3532 let _ = std::fs::File::open(filename)
3533 .map(|mut f| f.read_to_end(&mut contents))
3534 .map_err(|e| e.to_string())?;
3535 Ok(try_decode_msg(&contents).map_err(|e| e.to_string())?)
3536 }
3537
3538 /// Read a [`Record`] in Protobuf format from stdin. In Rhai this function is called `read_record`.
3539 /// ```
3540 /// // Rhai script
3541 /// # let script = r#"
3542 /// let record = rusp::read_record();
3543 /// record.to_string()
3544 /// # "#;
3545 /// ```
3546 ///
3547 /// # Errors
3548 ///
3549 /// This function will return `Err` containing a textual description of the encountered error
3550 /// if the deserialization of the structure from Protobuf format fails.
3551 #[rhai_fn(global, name = "read_record", return_raw)]
3552 pub fn read_record_protobuf() -> Result<Record, Box<EvalAltResult>> {
3553 let mut contents = Vec::new();
3554 std::io::stdin()
3555 .read_to_end(&mut contents)
3556 .map_err(|e| e.to_string())?;
3557 let record = try_decode_record(&contents).map_err(|e| e.to_string())?;
3558 if record.record_type == OneOfrecord_type::None {
3559 Err("Protobuf file doesn't contain a valid USP Record")?;
3560 }
3561 Ok(record)
3562 }
3563
3564 /// Load a [`Record`] from a Protobuf file, in Rhai this function is called `load_record`.
3565 /// ```
3566 /// // Rhai script
3567 /// # let script = r#"
3568 /// let record = rusp::load_record("test.pb");
3569 /// record.to_string()
3570 /// # "#;
3571 /// ```
3572 ///
3573 /// # Errors
3574 ///
3575 /// This function will return `Err` containing a textual description of the encountered error
3576 /// if the file pointed to by the filename doesn't exist, is not readable or the
3577 /// deserialization of the structure from Protobuf format fails.
3578 #[rhai_fn(global, name = "load_record", return_raw)]
3579 pub fn load_record_protobuf(filename: &str) -> Result<Record, Box<EvalAltResult>> {
3580 let mut contents = Vec::new();
3581 let _ = std::fs::File::open(filename)
3582 .map(|mut f| f.read_to_end(&mut contents))
3583 .map_err(|e| e.to_string())?;
3584 let record = try_decode_record(&contents).map_err(|e| e.to_string())?;
3585 if record.record_type == OneOfrecord_type::None {
3586 Err("Protobuf file doesn't contain a valid USP Record")?;
3587 }
3588 Ok(record)
3589 }
3590}
3591
3592def_package! {
3593 pub RuspPackage(module) {
3594 combine_with_exported_module!(module, "rusp", rhai_rusp);
3595 combine_with_exported_module!(module, "rusp", rhai_rusp_msg);
3596 combine_with_exported_module!(module, "rusp", rhai_rusp_record);
3597 combine_with_exported_module!(module, "rusp", rhai_rusp_add);
3598 combine_with_exported_module!(module, "rusp", rhai_rusp_addresp);
3599 combine_with_exported_module!(module, "rusp", rhai_rusp_delete);
3600 combine_with_exported_module!(module, "rusp", rhai_rusp_deleteresp);
3601 combine_with_exported_module!(module, "rusp", rhai_rusp_deregister);
3602 combine_with_exported_module!(module, "rusp", rhai_rusp_deregisterresp);
3603 combine_with_exported_module!(module, "rusp", rhai_rusp_error);
3604 combine_with_exported_module!(module, "rusp", rhai_rusp_get);
3605 combine_with_exported_module!(module, "rusp", rhai_rusp_getresp);
3606 combine_with_exported_module!(module, "rusp", rhai_rusp_getinstances);
3607 combine_with_exported_module!(module, "rusp", rhai_rusp_getinstancesresp);
3608 combine_with_exported_module!(module, "rusp", rhai_rusp_getsupportedprotocol);
3609 combine_with_exported_module!(module, "rusp", rhai_rusp_getsupportedprotocolresp);
3610 combine_with_exported_module!(module, "rusp", rhai_rusp_getsupporteddm);
3611 combine_with_exported_module!(module, "rusp", rhai_rusp_getsupporteddmresp);
3612 combine_with_exported_module!(module, "rusp", rhai_rusp_notify);
3613 combine_with_exported_module!(module, "rusp", rhai_rusp_notifyresp);
3614 combine_with_exported_module!(module, "rusp", rhai_rusp_operate);
3615 combine_with_exported_module!(module, "rusp", rhai_rusp_operateresp);
3616 combine_with_exported_module!(module, "rusp", rhai_rusp_register);
3617 combine_with_exported_module!(module, "rusp", rhai_rusp_registerresp);
3618 combine_with_exported_module!(module, "rusp", rhai_rusp_set);
3619 combine_with_exported_module!(module, "rusp", rhai_rusp_setresp);
3620 }
3621}