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