mozprofile/
profile.rs

1/* This Source Code Form is subject to the terms of the Mozilla Public
2 * License, v. 2.0. If a copy of the MPL was not distributed with this
3 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
4
5use crate::preferences::{Pref, Preferences};
6use crate::prefreader::{parse, serialize, PrefReaderError};
7use std::collections::btree_map::Iter;
8use std::fs::File;
9use std::io::prelude::*;
10use std::io::Result as IoResult;
11use std::path::{Path, PathBuf};
12use tempfile::{Builder, TempDir};
13
14#[derive(Debug)]
15pub struct Profile {
16    pub path: PathBuf,
17    pub temp_dir: Option<TempDir>,
18    prefs: Option<PrefFile>,
19    user_prefs: Option<PrefFile>,
20}
21
22impl PartialEq for Profile {
23    fn eq(&self, other: &Profile) -> bool {
24        self.path == other.path
25    }
26}
27
28impl Profile {
29    pub fn new(temp_root: Option<&Path>) -> IoResult<Profile> {
30        let mut dir_builder = Builder::new();
31        dir_builder.prefix("rust_mozprofile");
32        let dir = if let Some(temp_root) = temp_root {
33            dir_builder.tempdir_in(temp_root)
34        } else {
35            dir_builder.tempdir()
36        }?;
37        let path = dir.path().to_path_buf();
38        let temp_dir = Some(dir);
39        Ok(Profile {
40            path,
41            temp_dir,
42            prefs: None,
43            user_prefs: None,
44        })
45    }
46
47    pub fn new_from_path(p: &Path) -> IoResult<Profile> {
48        let path = p.to_path_buf();
49        let temp_dir = None;
50        Ok(Profile {
51            path,
52            temp_dir,
53            prefs: None,
54            user_prefs: None,
55        })
56    }
57
58    pub fn prefs(&mut self) -> Result<&mut PrefFile, PrefReaderError> {
59        if self.prefs.is_none() {
60            let mut pref_path = PathBuf::from(&self.path);
61            pref_path.push("prefs.js");
62            self.prefs = Some(PrefFile::new(pref_path)?)
63        };
64        // This error handling doesn't make much sense
65        Ok(self.prefs.as_mut().unwrap())
66    }
67
68    pub fn user_prefs(&mut self) -> Result<&mut PrefFile, PrefReaderError> {
69        if self.user_prefs.is_none() {
70            let mut pref_path = PathBuf::from(&self.path);
71            pref_path.push("user.js");
72            self.user_prefs = Some(PrefFile::new(pref_path)?)
73        };
74        // This error handling doesn't make much sense
75        Ok(self.user_prefs.as_mut().unwrap())
76    }
77}
78
79#[derive(Debug)]
80pub struct PrefFile {
81    pub path: PathBuf,
82    pub prefs: Preferences,
83}
84
85impl PrefFile {
86    pub fn new(path: PathBuf) -> Result<PrefFile, PrefReaderError> {
87        let prefs = if !path.exists() {
88            Preferences::new()
89        } else {
90            let mut f = File::open(&path)?;
91            let mut buf = String::with_capacity(4096);
92            f.read_to_string(&mut buf)?;
93            parse(buf.as_bytes())?
94        };
95
96        Ok(PrefFile { path, prefs })
97    }
98
99    pub fn write(&self) -> IoResult<()> {
100        let mut f = File::create(&self.path)?;
101        serialize(&self.prefs, &mut f)
102    }
103
104    pub fn insert_slice<K>(&mut self, preferences: &[(K, Pref)])
105    where
106        K: Into<String> + Clone,
107    {
108        for (name, value) in preferences.iter() {
109            self.insert((*name).clone(), (*value).clone());
110        }
111    }
112
113    pub fn insert<K>(&mut self, key: K, value: Pref)
114    where
115        K: Into<String>,
116    {
117        self.prefs.insert(key.into(), value);
118    }
119
120    pub fn remove(&mut self, key: &str) -> Option<Pref> {
121        self.prefs.remove(key)
122    }
123
124    pub fn get(&mut self, key: &str) -> Option<&Pref> {
125        self.prefs.get(key)
126    }
127
128    pub fn contains_key(&self, key: &str) -> bool {
129        self.prefs.contains_key(key)
130    }
131
132    pub fn iter(&self) -> Iter<String, Pref> {
133        self.prefs.iter()
134    }
135}