diff options
| author | Edward Barnard | 2018-08-26 09:07:34 +0200 | 
|---|---|---|
| committer | Edward Barnard | 2018-08-26 09:07:34 +0200 | 
| commit | 0808a65055cc2beb7244b7a145e80d382c453d68 (patch) | |
| tree | 0362ee6d1910a28f0c05e620c0c90ef253769697 | |
| parent | 96b7e5cdbafc7dfa32d3a7339655a7f9b674b4b1 (diff) | |
| download | rust-plist-0808a65055cc2beb7244b7a145e80d382c453d68.tar.bz2 | |
Move private Builder struct into value module.
| -rw-r--r-- | src/builder.rs | 146 | ||||
| -rw-r--r-- | src/lib.rs | 1 | ||||
| -rw-r--r-- | src/value.rs | 142 | 
3 files changed, 137 insertions, 152 deletions
| diff --git a/src/builder.rs b/src/builder.rs deleted file mode 100644 index ca9deb5..0000000 --- a/src/builder.rs +++ /dev/null @@ -1,146 +0,0 @@ -use std::collections::BTreeMap; - -use events::Event; -use {u64_option_to_usize, Error, Value}; - -pub struct Builder<T> { -    stream: T, -    token: Option<Event>, -} - -impl<T: Iterator<Item = Result<Event, Error>>> Builder<T> { -    pub fn new(stream: T) -> Builder<T> { -        Builder { -            stream, -            token: None, -        } -    } - -    pub fn build(mut self) -> Result<Value, Error> { -        self.bump()?; - -        let plist = self.build_value()?; -        self.bump()?; -        match self.token { -            None => (), -            // The stream should have finished -            _ => return Err(Error::InvalidData), -        }; -        Ok(plist) -    } - -    fn bump(&mut self) -> Result<(), Error> { -        self.token = match self.stream.next() { -            Some(Ok(token)) => Some(token), -            Some(Err(err)) => return Err(err), -            None => None, -        }; -        Ok(()) -    } - -    fn build_value(&mut self) -> Result<Value, Error> { -        match self.token.take() { -            Some(Event::StartArray(len)) => Ok(Value::Array(self.build_array(len)?)), -            Some(Event::StartDictionary(len)) => Ok(Value::Dictionary(self.build_dict(len)?)), - -            Some(Event::BooleanValue(b)) => Ok(Value::Boolean(b)), -            Some(Event::DataValue(d)) => Ok(Value::Data(d)), -            Some(Event::DateValue(d)) => Ok(Value::Date(d)), -            Some(Event::IntegerValue(i)) => Ok(Value::Integer(i)), -            Some(Event::RealValue(f)) => Ok(Value::Real(f)), -            Some(Event::StringValue(s)) => Ok(Value::String(s)), - -            Some(Event::EndArray) => Err(Error::InvalidData), -            Some(Event::EndDictionary) => Err(Error::InvalidData), - -            // The stream should not have ended here -            None => Err(Error::InvalidData), -        } -    } - -    fn build_array(&mut self, len: Option<u64>) -> Result<Vec<Value>, Error> { -        let len = u64_option_to_usize(len)?; -        let mut values = match len { -            Some(len) => Vec::with_capacity(len), -            None => Vec::new(), -        }; - -        loop { -            self.bump()?; -            if let Some(Event::EndArray) = self.token { -                self.token.take(); -                return Ok(values); -            } -            values.push(self.build_value()?); -        } -    } - -    fn build_dict(&mut self, _len: Option<u64>) -> Result<BTreeMap<String, Value>, Error> { -        let mut values = BTreeMap::new(); - -        loop { -            self.bump()?; -            match self.token.take() { -                Some(Event::EndDictionary) => return Ok(values), -                Some(Event::StringValue(s)) => { -                    self.bump()?; -                    values.insert(s, self.build_value()?); -                } -                _ => { -                    // Only string keys are supported in plists -                    return Err(Error::InvalidData); -                } -            } -        } -    } -} - -#[cfg(test)] -mod tests { -    use std::collections::BTreeMap; - -    use super::*; -    use events::Event::*; -    use Value; - -    #[test] -    fn builder() { -        // Input -        let events = vec![ -            StartDictionary(None), -            StringValue("Author".to_owned()), -            StringValue("William Shakespeare".to_owned()), -            StringValue("Lines".to_owned()), -            StartArray(None), -            StringValue("It is a tale told by an idiot,".to_owned()), -            StringValue("Full of sound and fury, signifying nothing.".to_owned()), -            EndArray, -            StringValue("Birthdate".to_owned()), -            IntegerValue(1564), -            StringValue("Height".to_owned()), -            RealValue(1.60), -            EndDictionary, -        ]; - -        let builder = Builder::new(events.into_iter().map(|e| Ok(e))); -        let plist = builder.build(); - -        // Expected output -        let mut lines = Vec::new(); -        lines.push(Value::String("It is a tale told by an idiot,".to_owned())); -        lines.push(Value::String( -            "Full of sound and fury, signifying nothing.".to_owned(), -        )); - -        let mut dict = BTreeMap::new(); -        dict.insert( -            "Author".to_owned(), -            Value::String("William Shakespeare".to_owned()), -        ); -        dict.insert("Lines".to_owned(), Value::Array(lines)); -        dict.insert("Birthdate".to_owned(), Value::Integer(1564)); -        dict.insert("Height".to_owned(), Value::Real(1.60)); - -        assert_eq!(plist.unwrap(), Value::Dictionary(dict)); -    } -} @@ -65,7 +65,6 @@ extern crate xml as xml_rs;  pub mod events; -mod builder;  mod date;  mod value; diff --git a/src/value.rs b/src/value.rs index e0a95e5..c4b2a76 100644 --- a/src/value.rs +++ b/src/value.rs @@ -2,7 +2,7 @@ use std::collections::BTreeMap;  use std::io::{Read, Seek};  use events::{Event, Reader}; -use {builder, Date, Error}; +use {u64_option_to_usize, Date, Error};  #[derive(Clone, Debug, PartialEq)]  pub enum Value { @@ -26,9 +26,7 @@ impl Value {      where          T: IntoIterator<Item = Result<Event, Error>>,      { -        let iter = events.into_iter(); -        let builder = builder::Builder::new(iter); -        builder.build() +        Builder::new(events.into_iter()).build()      }      pub fn into_events(self) -> Vec<Event> { @@ -334,15 +332,108 @@ impl<'a> From<&'a str> for Value {      }  } +struct Builder<T> { +    stream: T, +    token: Option<Event>, +} + +impl<T: Iterator<Item = Result<Event, Error>>> Builder<T> { +    fn new(stream: T) -> Builder<T> { +        Builder { +            stream, +            token: None, +        } +    } + +    fn build(mut self) -> Result<Value, Error> { +        self.bump()?; +        let plist = self.build_value()?; + +        // Ensure the stream has been fully consumed +        self.bump()?; +        match self.token { +            None => Ok(plist), +            _ => Err(Error::InvalidData), +        } +    } + +    fn bump(&mut self) -> Result<(), Error> { +        self.token = match self.stream.next() { +            Some(Ok(token)) => Some(token), +            Some(Err(err)) => return Err(err), +            None => None, +        }; +        Ok(()) +    } + +    fn build_value(&mut self) -> Result<Value, Error> { +        match self.token.take() { +            Some(Event::StartArray(len)) => Ok(Value::Array(self.build_array(len)?)), +            Some(Event::StartDictionary(len)) => Ok(Value::Dictionary(self.build_dict(len)?)), + +            Some(Event::BooleanValue(b)) => Ok(Value::Boolean(b)), +            Some(Event::DataValue(d)) => Ok(Value::Data(d)), +            Some(Event::DateValue(d)) => Ok(Value::Date(d)), +            Some(Event::IntegerValue(i)) => Ok(Value::Integer(i)), +            Some(Event::RealValue(f)) => Ok(Value::Real(f)), +            Some(Event::StringValue(s)) => Ok(Value::String(s)), + +            Some(Event::EndArray) => Err(Error::InvalidData), +            Some(Event::EndDictionary) => Err(Error::InvalidData), + +            // The stream should not have ended here +            None => Err(Error::InvalidData), +        } +    } + +    fn build_array(&mut self, len: Option<u64>) -> Result<Vec<Value>, Error> { +        let len = u64_option_to_usize(len)?; +        let mut values = match len { +            Some(len) => Vec::with_capacity(len), +            None => Vec::new(), +        }; + +        loop { +            self.bump()?; +            if let Some(Event::EndArray) = self.token { +                self.token.take(); +                return Ok(values); +            } +            values.push(self.build_value()?); +        } +    } + +    fn build_dict(&mut self, _len: Option<u64>) -> Result<BTreeMap<String, Value>, Error> { +        let mut values = BTreeMap::new(); + +        loop { +            self.bump()?; +            match self.token.take() { +                Some(Event::EndDictionary) => return Ok(values), +                Some(Event::StringValue(s)) => { +                    self.bump()?; +                    values.insert(s, self.build_value()?); +                } +                _ => { +                    // Only string keys are supported in plists +                    return Err(Error::InvalidData); +                } +            } +        } +    } +} +  #[cfg(test)]  mod tests {      use std::collections::BTreeMap;      use std::time::SystemTime; +    use super::*; +    use events::Event::*;      use {Date, Value};      #[test] -    fn test_plist_access() { +    fn value_accessors() {          let vec = vec![Value::Real(0.0)];          let mut array = Value::Array(vec.clone());          assert_eq!(array.as_array(), Some(&vec.clone())); @@ -374,4 +465,45 @@ mod tests {              Some("t".to_owned())          );      } + +    #[test] +    fn builder() { +        // Input +        let events = vec![ +            StartDictionary(None), +            StringValue("Author".to_owned()), +            StringValue("William Shakespeare".to_owned()), +            StringValue("Lines".to_owned()), +            StartArray(None), +            StringValue("It is a tale told by an idiot,".to_owned()), +            StringValue("Full of sound and fury, signifying nothing.".to_owned()), +            EndArray, +            StringValue("Birthdate".to_owned()), +            IntegerValue(1564), +            StringValue("Height".to_owned()), +            RealValue(1.60), +            EndDictionary, +        ]; + +        let builder = Builder::new(events.into_iter().map(|e| Ok(e))); +        let plist = builder.build(); + +        // Expected output +        let mut lines = Vec::new(); +        lines.push(Value::String("It is a tale told by an idiot,".to_owned())); +        lines.push(Value::String( +            "Full of sound and fury, signifying nothing.".to_owned(), +        )); + +        let mut dict = BTreeMap::new(); +        dict.insert( +            "Author".to_owned(), +            Value::String("William Shakespeare".to_owned()), +        ); +        dict.insert("Lines".to_owned(), Value::Array(lines)); +        dict.insert("Birthdate".to_owned(), Value::Integer(1564)); +        dict.insert("Height".to_owned(), Value::Real(1.60)); + +        assert_eq!(plist.unwrap(), Value::Dictionary(dict)); +    }  } | 
