]> git.lizzy.rs Git - rust.git/blob - src/tools/jsondocck/src/cache.rs
Rollup merge of #100796 - TaKO8Ki:remove-unnecessary-string-searching, r=compiler...
[rust.git] / src / tools / jsondocck / src / cache.rs
1 use crate::error::CkError;
2 use serde_json::Value;
3 use std::collections::HashMap;
4 use std::io;
5 use std::path::{Path, PathBuf};
6
7 use fs_err as fs;
8
9 #[derive(Debug)]
10 pub struct Cache {
11     root: PathBuf,
12     files: HashMap<PathBuf, String>,
13     values: HashMap<PathBuf, Value>,
14     pub variables: HashMap<String, Value>,
15     last_path: Option<PathBuf>,
16 }
17
18 impl Cache {
19     /// Create a new cache, used to read files only once and otherwise store their contents.
20     pub fn new(doc_dir: &str) -> Cache {
21         Cache {
22             root: Path::new(doc_dir).to_owned(),
23             files: HashMap::new(),
24             values: HashMap::new(),
25             variables: HashMap::new(),
26             last_path: None,
27         }
28     }
29
30     fn resolve_path(&mut self, path: &String) -> PathBuf {
31         if path != "-" {
32             let resolve = self.root.join(path);
33             self.last_path = Some(resolve.clone());
34             resolve
35         } else {
36             self.last_path
37                 .as_ref()
38                 // FIXME: Point to a line number
39                 .expect("No last path set. Make sure to specify a full path before using `-`")
40                 .clone()
41         }
42     }
43
44     fn read_file(&mut self, path: PathBuf) -> Result<String, io::Error> {
45         if let Some(f) = self.files.get(&path) {
46             return Ok(f.clone());
47         }
48
49         let file = fs::read_to_string(&path)?;
50
51         self.files.insert(path, file.clone());
52
53         Ok(file)
54     }
55
56     /// Get the text from a file. If called multiple times, the file will only be read once
57     pub fn get_file(&mut self, path: &String) -> Result<String, io::Error> {
58         let path = self.resolve_path(path);
59         self.read_file(path)
60     }
61
62     /// Parse the JSON from a file. If called multiple times, the file will only be read once.
63     pub fn get_value(&mut self, path: &String) -> Result<Value, CkError> {
64         let path = self.resolve_path(path);
65
66         if let Some(v) = self.values.get(&path) {
67             return Ok(v.clone());
68         }
69
70         let content = self.read_file(path.clone())?;
71         let val = serde_json::from_str::<Value>(&content)?;
72
73         self.values.insert(path, val.clone());
74
75         Ok(val)
76     }
77 }