neutralts/bif/
parse_bif_debug.rs

1#![doc = include_str!("../../doc/bif-debug.md")]
2
3use crate::{
4    bif::constants::*,
5    bif::Bif,
6    bif::BifError,
7    constants::*,
8    utils::*,
9};
10use std::fs;
11use std::path::Path;
12use std::time::{SystemTime, Duration};
13
14impl<'a> Bif<'a> {
15    /*
16        {:debug; data->key :}
17    */
18    pub(crate) fn parse_bif_debug(&mut self) -> Result<(), BifError> {
19        if self.mod_scope {
20            return Err(self.bif_error(BIF_ERROR_MODIFIER_NOT_ALLOWED));
21        }
22
23        let debug_enable = self.debug_enable();
24
25        if self.mod_negate {
26            if debug_enable {
27                self.out = UNPRINTABLE.to_string();
28            } else {
29                self.out = EMPTY_STRING;
30            }
31
32            return Ok(());
33        }
34
35        if !debug_enable {
36            self.out = EMPTY_STRING;
37            if self.mod_negate {
38                return Ok(());
39            } else {
40                return Err(self.bif_error("Debug is disabled. Remember to remove the bif debug in production."));
41            }
42        }
43
44        self.extract_params_code(true);
45
46        let mut schema = &self.shared.schema;
47        let mut key_name = self.code.clone();
48        if key_name.starts_with("local::") {
49            key_name = key_name.strip_prefix("local::").unwrap_or("").to_string();
50            schema = &self.shared.schema["__indir"][&self.inherit.indir];
51        }
52
53        let k = if self.code.is_empty() {
54            self.out = VERSION.to_string();
55            return Ok(());
56        } else if key_name == "full-schema" {
57            "".to_string()
58        } else {
59            format!("/{}", key_name).replace(BIF_ARRAY, "/")
60        };
61
62        self.out = match schema.pointer(&k) {
63            Some(value) => match serde_json::to_string_pretty(value) {
64                Ok(json_str) => json_str,
65                Err(e) => format!("Error formatting JSON: {}", e),
66            },
67            None => format!("Undefined: '{}'", self.code),
68        };
69
70        if self.mod_filter {
71            // unescape_chars for prevent double encoding
72            let tmp = unescape_chars(&self.out, true);
73            self.out = escape_chars(&tmp, true);
74        }
75
76        Ok(())
77    }
78
79    /// check if debug is enabled
80    pub(crate) fn debug_enable(&self) -> bool {
81        if self.shared.debug_file.is_empty() {
82            return false;
83        }
84
85        let path = Path::new(&self.shared.debug_file);
86
87        if !path.exists() || !path.is_file() {
88            return false;
89        }
90
91        let metadata = match fs::metadata(path) {
92            Ok(md) => md,
93            Err(_) => return false,
94        };
95
96        let modified_time = match metadata.modified() {
97            Ok(time) => time,
98            Err(_) => return false,
99        };
100
101        let now = SystemTime::now();
102
103        match now.duration_since(modified_time) {
104            Ok(duration) => duration < Duration::from_secs(self.shared.debug_expire),
105            Err(_) => false,
106        }
107    }
108}
109
110
111#[cfg(test)]
112#[path = "parse_bif_debug_tests.rs"]
113mod tests;