relay_event_schema/protocol/
templateinfo.rs

1use relay_protocol::{Annotated, Array, Empty, FromValue, IntoValue, Object, Value};
2
3use crate::processor::ProcessValue;
4
5/// Template debug information.
6#[derive(Clone, Debug, Default, PartialEq, Empty, FromValue, IntoValue, ProcessValue)]
7#[metastructure(process_func = "process_template_info")]
8pub struct TemplateInfo {
9    /// The file name (basename only).
10    #[metastructure(pii = "true", max_chars = 128, max_chars_allowance = 20)]
11    pub filename: Annotated<String>,
12
13    /// Absolute path to the file.
14    #[metastructure(pii = "true", max_chars = 256, max_chars_allowance = 40)]
15    pub abs_path: Annotated<String>,
16
17    /// Line number within the source file.
18    pub lineno: Annotated<u64>,
19
20    /// Column number within the source file.
21    pub colno: Annotated<u64>,
22
23    /// Source code leading up to the current line.
24    pub pre_context: Annotated<Array<String>>,
25
26    /// Source code of the current line.
27    pub context_line: Annotated<String>,
28
29    /// Source code of the lines after the current line.
30    pub post_context: Annotated<Array<String>>,
31
32    /// Additional arbitrary fields for forwards compatibility.
33    #[metastructure(additional_properties)]
34    pub other: Object<Value>,
35}
36
37#[cfg(test)]
38mod tests {
39    use relay_protocol::Map;
40    use similar_asserts::assert_eq;
41
42    use super::*;
43
44    #[test]
45    fn test_template_roundtrip() {
46        let json = r#"{
47  "filename": "myfile.rs",
48  "abs_path": "/path/to",
49  "lineno": 2,
50  "colno": 42,
51  "pre_context": [
52    "fn main() {"
53  ],
54  "context_line": "unimplemented!()",
55  "post_context": [
56    "}"
57  ],
58  "other": "value"
59}"#;
60        let template_info = Annotated::new(TemplateInfo {
61            filename: Annotated::new("myfile.rs".to_string()),
62            abs_path: Annotated::new("/path/to".to_string()),
63            lineno: Annotated::new(2),
64            colno: Annotated::new(42),
65            pre_context: Annotated::new(vec![Annotated::new("fn main() {".to_string())]),
66            context_line: Annotated::new("unimplemented!()".to_string()),
67            post_context: Annotated::new(vec![Annotated::new("}".to_string())]),
68            other: {
69                let mut map = Map::new();
70                map.insert(
71                    "other".to_string(),
72                    Annotated::new(Value::String("value".to_string())),
73                );
74                map
75            },
76        });
77
78        assert_eq!(template_info, Annotated::from_json(json).unwrap());
79        assert_eq!(json, template_info.to_json_pretty().unwrap());
80    }
81
82    #[test]
83    fn test_template_default_values() {
84        let json = "{}";
85        let template_info = Annotated::new(TemplateInfo {
86            filename: Annotated::empty(),
87            abs_path: Annotated::empty(),
88            lineno: Annotated::empty(),
89            colno: Annotated::empty(),
90            pre_context: Annotated::empty(),
91            context_line: Annotated::empty(),
92            post_context: Annotated::empty(),
93            other: Object::default(),
94        });
95
96        assert_eq!(template_info, Annotated::from_json(json).unwrap());
97        assert_eq!(json, template_info.to_json().unwrap());
98    }
99}