diff options
Diffstat (limited to 'src/decoder/rustc_serialize.rs')
-rw-r--r-- | src/decoder/rustc_serialize.rs | 371 |
1 files changed, 0 insertions, 371 deletions
diff --git a/src/decoder/rustc_serialize.rs b/src/decoder/rustc_serialize.rs deleted file mode 100644 index f850663..0000000 --- a/src/decoder/rustc_serialize.rs +++ /dev/null @@ -1,371 +0,0 @@ -use rustc_serialize; -use std::mem; -use std::collections::BTreeMap; - -use super::{Decoder, DecodeError}; -use super::DecodeErrorKind::*; -use Value; - -impl rustc_serialize::Decoder for Decoder { - type Error = DecodeError; - fn read_nil(&mut self) -> Result<(), DecodeError> { - match self.toml { - Some(Value::String(ref s)) if s.is_empty() => {} - Some(Value::String(..)) => return Err(self.err(NilTooLong)), - ref found => return Err(self.mismatch("string", found)), - } - self.toml.take(); - Ok(()) - } - fn read_usize(&mut self) -> Result<usize, DecodeError> { - self.read_i64().map(|i| i as usize) - } - fn read_u64(&mut self) -> Result<u64, DecodeError> { - self.read_i64().map(|i| i as u64) - } - fn read_u32(&mut self) -> Result<u32, DecodeError> { - self.read_i64().map(|i| i as u32) - } - fn read_u16(&mut self) -> Result<u16, DecodeError> { - self.read_i64().map(|i| i as u16) - } - fn read_u8(&mut self) -> Result<u8, DecodeError> { - self.read_i64().map(|i| i as u8) - } - fn read_isize(&mut self) -> Result<isize, DecodeError> { - self.read_i64().map(|i| i as isize) - } - fn read_i64(&mut self) -> Result<i64, DecodeError> { - match self.toml { - Some(Value::Integer(i)) => { self.toml.take(); Ok(i) } - ref found => Err(self.mismatch("integer", found)), - } - } - fn read_i32(&mut self) -> Result<i32, DecodeError> { - self.read_i64().map(|i| i as i32) - } - fn read_i16(&mut self) -> Result<i16, DecodeError> { - self.read_i64().map(|i| i as i16) - } - fn read_i8(&mut self) -> Result<i8, DecodeError> { - self.read_i64().map(|i| i as i8) - } - fn read_bool(&mut self) -> Result<bool, DecodeError> { - match self.toml { - Some(Value::Boolean(b)) => { self.toml.take(); Ok(b) } - ref found => Err(self.mismatch("bool", found)), - } - } - fn read_f64(&mut self) -> Result<f64, DecodeError> { - match self.toml { - Some(Value::Float(f)) => { self.toml.take(); Ok(f) }, - ref found => Err(self.mismatch("float", found)), - } - } - fn read_f32(&mut self) -> Result<f32, DecodeError> { - self.read_f64().map(|f| f as f32) - } - fn read_char(&mut self) -> Result<char, DecodeError> { - let ch = match self.toml { - Some(Value::String(ref s)) if s.chars().count() == 1 => - s.chars().next().unwrap(), - ref found => return Err(self.mismatch("string", found)), - }; - self.toml.take(); - Ok(ch) - } - fn read_str(&mut self) -> Result<String, DecodeError> { - match self.toml.take() { - Some(Value::String(s)) => Ok(s), - found => { - let err = Err(self.mismatch("string", &found)); - self.toml = found; - err - } - } - } - - // Compound types: - fn read_enum<T, F>(&mut self, _name: &str, f: F) - -> Result<T, DecodeError> - where F: FnOnce(&mut Decoder) -> Result<T, DecodeError> - { - f(self) - } - - fn read_enum_variant<T, F>(&mut self, names: &[&str], mut f: F) - -> Result<T, DecodeError> - where F: FnMut(&mut Decoder, usize) -> Result<T, DecodeError> - { - // When decoding enums, this crate takes the strategy of trying to - // decode the current TOML as all of the possible variants, returning - // success on the first one that succeeds. - // - // Note that fidelity of the errors returned here is a little nebulous, - // but we try to return the error that had the relevant field as the - // longest field. This way we hopefully match an error against what was - // most likely being written down without losing too much info. - let mut first_error = None::<DecodeError>; - for i in 0..names.len() { - let mut d = self.sub_decoder(self.toml.clone(), ""); - match f(&mut d, i) { - Ok(t) => { - self.toml = d.toml; - return Ok(t) - } - Err(e) => { - if let Some(ref first) = first_error { - let my_len = e.field.as_ref().map(|s| s.len()); - let first_len = first.field.as_ref().map(|s| s.len()); - if my_len <= first_len { - continue - } - } - first_error = Some(e); - } - } - } - Err(first_error.unwrap_or_else(|| self.err(NoEnumVariants))) - } - fn read_enum_variant_arg<T, F>(&mut self, _a_idx: usize, f: F) - -> Result<T, DecodeError> - where F: FnOnce(&mut Decoder) -> Result<T, DecodeError> - { - f(self) - } - - fn read_enum_struct_variant<T, F>(&mut self, _names: &[&str], _f: F) - -> Result<T, DecodeError> - where F: FnMut(&mut Decoder, usize) -> Result<T, DecodeError> - { - panic!() - } - fn read_enum_struct_variant_field<T, F>(&mut self, - _f_name: &str, - _f_idx: usize, - _f: F) - -> Result<T, DecodeError> - where F: FnOnce(&mut Decoder) -> Result<T, DecodeError> - { - panic!() - } - - fn read_struct<T, F>(&mut self, _s_name: &str, _len: usize, f: F) - -> Result<T, DecodeError> - where F: FnOnce(&mut Decoder) -> Result<T, DecodeError> - { - match self.toml { - Some(Value::Table(..)) => { - let ret = try!(f(self)); - match self.toml { - Some(Value::Table(ref t)) if t.is_empty() => {} - _ => return Ok(ret) - } - self.toml.take(); - Ok(ret) - } - ref found => Err(self.mismatch("table", found)), - } - } - fn read_struct_field<T, F>(&mut self, f_name: &str, _f_idx: usize, f: F) - -> Result<T, DecodeError> - where F: FnOnce(&mut Decoder) -> Result<T, DecodeError> - { - let field = f_name.to_string(); - let toml = match self.toml { - Some(Value::Table(ref mut table)) => { - table.remove(&field) - .or_else(|| table.remove(&f_name.replace("_", "-"))) - }, - ref found => return Err(self.mismatch("table", found)), - }; - let mut d = self.sub_decoder(toml, f_name); - let ret = try!(f(&mut d)); - if let Some(value) = d.toml { - if let Some(Value::Table(ref mut table)) = self.toml { - table.insert(field, value); - } - } - Ok(ret) - } - - fn read_tuple<T, F>(&mut self, tuple_len: usize, f: F) - -> Result<T, DecodeError> - where F: FnOnce(&mut Decoder) -> Result<T, DecodeError> - { - self.read_seq(move |d, len| { - assert!(len == tuple_len, - "expected tuple of length `{}`, found tuple \ - of length `{}`", tuple_len, len); - f(d) - }) - } - fn read_tuple_arg<T, F>(&mut self, a_idx: usize, f: F) - -> Result<T, DecodeError> - where F: FnOnce(&mut Decoder) -> Result<T, DecodeError> - { - self.read_seq_elt(a_idx, f) - } - - fn read_tuple_struct<T, F>(&mut self, _s_name: &str, _len: usize, _f: F) - -> Result<T, DecodeError> - where F: FnOnce(&mut Decoder) -> Result<T, DecodeError> - { - panic!() - } - fn read_tuple_struct_arg<T, F>(&mut self, _a_idx: usize, _f: F) - -> Result<T, DecodeError> - where F: FnOnce(&mut Decoder) -> Result<T, DecodeError> - { - panic!() - } - - // Specialized types: - fn read_option<T, F>(&mut self, mut f: F) - -> Result<T, DecodeError> - where F: FnMut(&mut Decoder, bool) -> Result<T, DecodeError> - { - match self.toml { - Some(..) => f(self, true), - None => f(self, false), - } - } - - fn read_seq<T, F>(&mut self, f: F) -> Result<T, DecodeError> - where F: FnOnce(&mut Decoder, usize) -> Result<T, DecodeError> - { - let len = match self.toml { - Some(Value::Array(ref arr)) => arr.len(), - None => 0, - ref found => return Err(self.mismatch("array", found)), - }; - let ret = try!(f(self, len)); - match self.toml { - Some(Value::Array(ref mut arr)) => { - arr.retain(|slot| slot.as_integer() != Some(0)); - if !arr.is_empty() { return Ok(ret) } - } - _ => return Ok(ret) - } - self.toml.take(); - Ok(ret) - } - fn read_seq_elt<T, F>(&mut self, idx: usize, f: F) - -> Result<T, DecodeError> - where F: FnOnce(&mut Decoder) -> Result<T, DecodeError> - { - let toml = match self.toml { - Some(Value::Array(ref mut arr)) => { - mem::replace(&mut arr[idx], Value::Integer(0)) - } - ref found => return Err(self.mismatch("array", found)), - }; - let mut d = self.sub_decoder(Some(toml), ""); - let ret = try!(f(&mut d)); - if let Some(toml) = d.toml { - if let Some(Value::Array(ref mut arr)) = self.toml { - arr[idx] = toml; - } - } - Ok(ret) - } - - fn read_map<T, F>(&mut self, f: F) - -> Result<T, DecodeError> - where F: FnOnce(&mut Decoder, usize) -> Result<T, DecodeError> - { - let map = match self.toml.take() { - Some(Value::Table(table)) => table, - found => { - self.toml = found; - return Err(self.mismatch("table", &self.toml)) - } - }; - let amt = map.len(); - let prev_iter = mem::replace(&mut self.cur_map, - map.into_iter().peekable()); - let prev_map = mem::replace(&mut self.leftover_map, BTreeMap::new()); - let ret = try!(f(self, amt)); - let leftover = mem::replace(&mut self.leftover_map, prev_map); - self.cur_map = prev_iter; - if !leftover.is_empty() { - self.toml = Some(Value::Table(leftover)); - } - Ok(ret) - } - fn read_map_elt_key<T, F>(&mut self, idx: usize, f: F) - -> Result<T, DecodeError> - where F: FnOnce(&mut Decoder) -> Result<T, DecodeError> - { - let key = match self.cur_map.peek().map(|p| p.0.clone()) { - Some(k) => k, - None => return Err(self.err(ExpectedMapKey(idx))), - }; - let val = Value::String(key.clone()); - f(&mut self.sub_decoder(Some(val), &key)) - } - fn read_map_elt_val<T, F>(&mut self, idx: usize, f: F) - -> Result<T, DecodeError> - where F: FnOnce(&mut Decoder) -> Result<T, DecodeError> - { - match self.cur_map.next() { - Some((key, value)) => { - let mut d = self.sub_decoder(Some(value), &key); - let ret = f(&mut d); - if let Some(toml) = d.toml.take() { - self.leftover_map.insert(key, toml); - } - ret - } - None => Err(self.err(ExpectedMapElement(idx))), - } - } - - fn error(&mut self, err: &str) -> DecodeError { - DecodeError { - field: self.cur_field.clone(), - kind: ApplicationError(err.to_string()) - } - } -} - -#[cfg(test)] -mod tests { - use rustc_serialize::Decodable; - use std::collections::HashMap; - - use {Parser, Decoder, Value}; - - #[test] - fn bad_enum_chooses_longest_error() { - #[derive(RustcDecodable)] - #[allow(dead_code)] - struct Foo { - wut: HashMap<String, Bar>, - } - - #[derive(RustcDecodable)] - enum Bar { - Simple(String), - Detailed(Baz), - } - - #[derive(RustcDecodable, Debug)] - struct Baz { - features: Vec<String>, - } - - let s = r#" - [wut] - a = { features = "" } - "#; - let v = Parser::new(s).parse().unwrap(); - let mut d = Decoder::new(Value::Table(v)); - let err = match Foo::decode(&mut d) { - Ok(_) => panic!("expected error"), - Err(e) => e, - }; - assert_eq!(err.field.as_ref().unwrap(), "wut.a.features"); - - } -} |