Skip to main content

luaur_analysis/methods/
ast_json_encoder_write_primitives.rs

1//! Source: `Analysis/src/AstJsonEncoder.cpp` (lines 89-210, hand-ported)
2//! The C++ overloaded `write(...)` family, expressed as the Rust shape of
3//! overloading: a `WriteJson` trait + a generic `write(propName, value)`.
4//! PROP!(emitter, node, prop) expands to `emitter.write("prop", &node.prop)`.
5
6use crate::records::ast_json_encoder::AstJsonEncoder;
7use alloc::format;
8use alloc::string::String;
9use luaur_ast::records::ast_name::AstName;
10
11pub trait WriteJson {
12    fn write_json(&self, enc: &mut AstJsonEncoder);
13}
14
15impl AstJsonEncoder {
16    /// C++ template write(std::string_view propName, const T& value)
17    pub fn write<T: WriteJson + ?Sized>(&mut self, prop_name: &str, value: &T) {
18        if self.comma {
19            self.write_raw_string_view(",");
20        }
21        self.comma = true;
22        self.write_raw_string_view("\"");
23        self.write_raw_string_view(prop_name);
24        self.write_raw_string_view("\":");
25        value.write_json(self);
26    }
27}
28
29impl WriteJson for bool {
30    fn write_json(&self, enc: &mut AstJsonEncoder) {
31        enc.write_raw_string_view(if *self { "true" } else { "false" });
32    }
33}
34
35impl WriteJson for f64 {
36    fn write_json(&self, enc: &mut AstJsonEncoder) {
37        enc.write_f64(*self);
38    }
39}
40
41macro_rules! write_json_int {
42    ($($t:ty),*) => {$(
43        impl WriteJson for $t {
44            fn write_json(&self, enc: &mut AstJsonEncoder) {
45                let s = format!("{}", self);
46                enc.write_raw_string_view(&s);
47            }
48        }
49    )*};
50}
51// NB: no i8/u8 here -- C++ `char` writes as a one-char STRING (write(char),
52// AstJsonEncoder.cpp:156) and AstArray<char> as a string; c_char resolves to
53// i8 or u8 per target, so neither may be a JSON integer.
54write_json_int!(i32, i64, u32, u64, usize, isize, u16, i16);
55
56impl WriteJson for str {
57    fn write_json(&self, enc: &mut AstJsonEncoder) {
58        enc.write_string(self);
59    }
60}
61
62impl WriteJson for String {
63    fn write_json(&self, enc: &mut AstJsonEncoder) {
64        enc.write_string(self);
65    }
66}
67
68impl WriteJson for AstName {
69    fn write_json(&self, enc: &mut AstJsonEncoder) {
70        // C++ write(AstName): name.value ? writeString(name.value) : write("")
71        if self.value.is_null() {
72            enc.write_string("");
73        } else {
74            let s = unsafe { core::ffi::CStr::from_ptr(self.value) };
75            enc.write_string(&s.to_string_lossy());
76        }
77    }
78}
79
80impl<T: WriteJson> WriteJson for Option<T> {
81    fn write_json(&self, enc: &mut AstJsonEncoder) {
82        match self {
83            Some(v) => v.write_json(enc),
84            None => enc.write_raw_string_view("null"),
85        }
86    }
87}