1use 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 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 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}