wsdom_core/
serialize.rs

1use serde::Serialize;
2
3use crate::js::value::JsValue;
4use crate::protocol::GET;
5
6/// For values that can be serialized to JS code:
7/// - Rust values that implement `serde::Serialize`
8/// - WRMI stubs ([JsValue]s)
9///
10/// This trait is used by [ToJs].
11pub trait UseInJsCode {
12    fn serialize_to(&self, buf: &mut std::fmt::Formatter<'_>) -> std::fmt::Result;
13}
14
15impl UseInJsCode for JsValue {
16    fn serialize_to(&self, buf: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
17        let self_id = self.id;
18        write!(buf, "{GET}({self_id})").unwrap();
19        Ok(())
20    }
21}
22
23pub struct SerdeToJs<'a, T: ?Sized>(pub &'a T);
24
25impl<'a, T: Serialize + ?Sized> UseInJsCode for SerdeToJs<'a, T> {
26    fn serialize_to(&self, buf: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
27        struct WriteAdapter<'a, 'b>(&'a mut std::fmt::Formatter<'b>);
28        impl<'a, 'b> std::io::Write for WriteAdapter<'a, 'b> {
29            fn write(&mut self, buf: &[u8]) -> std::io::Result<usize> {
30                match self.0.write_str(unsafe {
31                    // WriteAdapter is only to be written to by serde_json,
32                    // which only writes valid utf8
33                    std::str::from_utf8_unchecked(buf)
34                }) {
35                    Ok(()) => Ok(buf.len()),
36                    Err(std::fmt::Error) => Err(std::io::ErrorKind::Other.into()),
37                }
38            }
39            fn flush(&mut self) -> std::io::Result<()> {
40                Ok(())
41            }
42        }
43        match serde_json::to_writer(&mut WriteAdapter(buf), self.0) {
44            Ok(()) => Ok(()),
45            Err(_) => Err(std::fmt::Error),
46        }
47    }
48}
49
50pub(crate) struct UseInJsCodeWriter<'a, T: UseInJsCode + ?Sized>(pub &'a T);
51
52impl<'a, T: UseInJsCode + ?Sized> std::fmt::Display for UseInJsCodeWriter<'a, T> {
53    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
54        self.0.serialize_to(f)
55    }
56}
57
58pub struct RawCodeImmediate<'a>(pub &'a str);
59impl<'a> UseInJsCode for RawCodeImmediate<'a> {
60    fn serialize_to(&self, buf: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
61        buf.write_str(self.0)
62    }
63}
64
65/// Values that can be serialized to JS code satisfying certain types.
66///
67/// For example, `ToJs<JsNumber>` means serializable to the same type that
68/// `JsNumber` serializes to.
69pub trait ToJs<JsType>
70where
71    Self: UseInJsCode,
72    JsType: ?Sized,
73{
74}
75
76impl<T: ?Sized> ToJs<T> for T where T: UseInJsCode {}