1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133
//! A crate to parse the Java Properties file format. //! //! The Properties file format is simple key/value text format that can be read //! and written by the standard library of Java. It is often used for //! configuration files, and also for translation files (Bundles). //! //! The Java class that supports this format is `java.util.Properties`, with //! its methods `load` and `store`. Note that the Java class also provides the //! methods `loadFromXML` and `storeToXML`, but this crate does not support //! the XML format. //! //! Starting from Java 9, the Properties files used as Resource Bundles are //! allowed to be utf-8, instead of only latin1 with unicode escapes ([JEP //! 226](http://openjdk.java.net/jeps/226)). This crate does not support JEP //! 226. //! //! This crate was written based on the [Java 8 API //! reference](https://docs.oracle.com/javase/8/docs/api/java/util/Properties.html#load-java.io.Reader-). //! As far as the author knows, this crate supports reading the full Properties //! format with no exception. There is no support to write Properties files, //! yet. #[macro_use] extern crate nom; #[macro_use] #[cfg(test)] mod test_helpers; mod parsers; use std::path::Path; use std::fs::File; use std::io; use std::io::Read; /// A parsing error #[derive(Debug)] pub struct Error; impl From<io::Error> for Error { fn from(_: io::Error) -> Error { Error } } /// Parse the bytes and return a vec of key/value pairs. The order of the /// elements in the parsed content is preserved. /// /// Keys are not guaranteed to be unique. /// /// # Examples /// /// ``` /// let parsed = dotproperties::parse_from_slice(b"knowledge = power\n1+1 = 2").unwrap(); /// assert_eq!(parsed, vec![("knowledge".to_string(), "power".to_string()), /// ("1+1".to_string(), "2".to_string())]); /// ``` /// /// It is often more convenient to work with a map, instead of a vec of pairs. /// The conversion can be done using the tools from std. /// /// ``` /// use std::collections::HashMap; /// /// let parsed = dotproperties::parse_from_slice(b"a:b\nc:d").unwrap(); /// let mapped : HashMap<_,_> = parsed.into_iter().collect(); /// /// ``` /// /// Note that if you use `collect` to create a map from a vec containing /// duplicate keys, only the value of the last one is retained. /// /// ``` /// use std::collections::HashMap; /// /// let parsed = dotproperties::parse_from_slice(b"a:x\na:y").unwrap(); /// let mapped : HashMap<_,_> = parsed.into_iter().collect(); /// assert_eq!(mapped.len(), 1); /// // The `map` converts the `Option<&String>` to an `Option<&str>` /// assert_eq!(mapped.get("a").map(|v| &**v), Some("y")); /// /// ``` /// /// # Failures /// /// There is no fine-grained error reporting, yet. If the function encounters /// a parse error, then an empty struct `Error` is returned. /// pub fn parse_from_slice(input: &[u8]) -> Result<Vec<(String, String)>, Error> { parsers::full_parser(input).to_result().map_err(|_| Error) } /// Parse the file and return a vec of key/value pairs. The order of the /// elements in the parsed content is preserved. /// /// Keys are not guaranteed to be unique. /// /// # Examples /// /// ``` /// # std::fs::File::create("config.properties").unwrap(); /// let parsed = dotproperties::parse_from_file("config.properties").unwrap(); /// # std::fs::remove_file("config.properties").unwrap(); /// ``` /// /// It is often more convenient to work with a map, instead of a vec of pairs. /// The conversion can be done using the tools from std. /// /// ``` /// use std::collections::HashMap; /// /// # std::fs::File::create("config.properties").unwrap(); /// let parsed = dotproperties::parse_from_file("config.properties").unwrap(); /// let mapped : HashMap<_,_> = parsed.into_iter().collect(); /// # std::fs::remove_file("config.properties").unwrap(); /// /// ``` /// /// Note that if you use `collect` to create a map from a vec containing /// duplicate keys, only the value of the last one is retained. /// /// # Failures /// /// There is no fine-grained error reporting, yet. If the function encounters /// a parse error or an IO error, then an empty struct `Error` is returned. /// pub fn parse_from_file<P: AsRef<Path>>(path: P) -> Result<Vec<(String, String)>, Error> { let mut file = File::open(path)?; let mut contents = vec![]; file.read_to_end(&mut contents)?; parse_from_slice(&*contents) }