/* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ //! Prefs file parsing utilities. /// Parse a single pref value (if any) from the prefs file contents. /// /// This parser could be improved (e.g., it doesn't respect comments), but it is compatible with /// prefs files generated by Firefox. /// /// This finds the first string match for the regex `user_pref\("PREFSTRING"[ \t\n\r\f\v,]*(.*)[ \t\n\r\f\v]*\);`. /// /// For example: /// ```rust /// let input = r#"user_pref("FOOBAR", "baz");"#; /// let expected_output = Some(r#""baz""#); /// assert_eq!(find_pref(input, "FOOBAR"), output); /// ``` pub fn find_pref<'a>(prefs_content: &'a str, pref: &str) -> Option<&'a str> { let mut search_content = prefs_content; loop { let (before, s) = search_content.split_once(&format!("\"{pref}\""))?; if !before.trim().ends_with("user_pref(") { search_content = s; continue; } let s = s.trim_start_matches(|c: char| c.is_whitespace() || c == ','); let (content, _) = s.split_once(");")?; return Some(content.trim()); } } /// Find a single string pref (if any) from the prefs file contents. pub fn find_string_pref<'a>(prefs_content: &'a str, pref: &str) -> Option<&'a str> { find_pref(prefs_content, pref).and_then(|s| s.strip_prefix('"')?.strip_suffix('"')) } /// Find a single bool pref (if any) from the prefs file contents. pub fn find_bool_pref(prefs_content: &str, pref: &str) -> Option { find_pref(prefs_content, pref).and_then(|s| s.parse().ok()) } // Doctests don't run for binaries, so make some unit tests instead. #[cfg(test)] mod test { use super::*; #[test] fn find_pref_read_value() { let input = r#"user_pref("FOOBAR", "baz");"#; assert_eq!(find_pref(input, "FOOBAR"), Some(r#""baz""#)); } #[test] fn find_pref_continues_search() { let input = r#" user_pref("rawr", "FOOBAR"); user_pref("FOOBAR", "baz"); "#; assert_eq!(find_pref(input, "FOOBAR"), Some(r#""baz""#)); } #[test] fn find_pref_missing() { let input = r#" user_pref("rawr", "FOOBAR"); user_pref("FOOBAR", "hello"); "#; assert_eq!(find_pref(input, "hello"), None); } #[test] fn test_find_string_pref() { let input = r#"user_pref("FOOBAR", "baz");"#; assert_eq!(find_string_pref(input, "FOOBAR"), Some("baz")); } #[test] fn test_find_bool_pref() { let input = r#"user_pref("FOOBAR", true);"#; assert_eq!(find_bool_pref(input, "FOOBAR"), Some(true)); let input = r#"user_pref("FOOBAR", false);"#; assert_eq!(find_bool_pref(input, "FOOBAR"), Some(false)); } }