From 2d49247b92f74cf760202b7d1a08d61804f45bca Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Thu, 2 Apr 2015 17:04:17 -0700 Subject: Modularize rustc-serialize support * Add rustc-serialize as a default feature * Make room for for serde support --- src/decoder/rustc_serialize.rs | 311 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 311 insertions(+) create mode 100644 src/decoder/rustc_serialize.rs (limited to 'src/decoder/rustc_serialize.rs') diff --git a/src/decoder/rustc_serialize.rs b/src/decoder/rustc_serialize.rs new file mode 100644 index 0000000..6e8fe59 --- /dev/null +++ b/src/decoder/rustc_serialize.rs @@ -0,0 +1,311 @@ +use rustc_serialize; +use std::mem; + +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.len() == 0 => {} + 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 { + self.read_i64().map(|i| i as usize) + } + fn read_u64(&mut self) -> Result { + self.read_i64().map(|i| i as u64) + } + fn read_u32(&mut self) -> Result { + self.read_i64().map(|i| i as u32) + } + fn read_u16(&mut self) -> Result { + self.read_i64().map(|i| i as u16) + } + fn read_u8(&mut self) -> Result { + self.read_i64().map(|i| i as u8) + } + fn read_isize(&mut self) -> Result { + self.read_i64().map(|i| i as isize) + } + fn read_i64(&mut self) -> Result { + 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 { + self.read_i64().map(|i| i as i32) + } + fn read_i16(&mut self) -> Result { + self.read_i64().map(|i| i as i16) + } + fn read_i8(&mut self) -> Result { + self.read_i64().map(|i| i as i8) + } + fn read_bool(&mut self) -> Result { + 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 { + match self.toml { + Some(Value::Float(f)) => Ok(f), + ref found => Err(self.mismatch("float", found)), + } + } + fn read_f32(&mut self) -> Result { + self.read_f64().map(|f| f as f32) + } + fn read_char(&mut self) -> Result { + 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 { + 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(&mut self, _name: &str, f: F) + -> Result + where F: FnOnce(&mut Decoder) -> Result + { + f(self) + } + + fn read_enum_variant(&mut self, names: &[&str], mut f: F) + -> Result + where F: FnMut(&mut Decoder, usize) -> Result + { + let mut first_error = None; + 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 first_error.is_none() { + first_error = Some(e); + } + } + } + } + Err(first_error.unwrap_or_else(|| self.err(NoEnumVariants))) + } + fn read_enum_variant_arg(&mut self, _a_idx: usize, f: F) + -> Result + where F: FnOnce(&mut Decoder) -> Result + { + f(self) + } + + fn read_enum_struct_variant(&mut self, _names: &[&str], _f: F) + -> Result + where F: FnMut(&mut Decoder, usize) -> Result + { + panic!() + } + fn read_enum_struct_variant_field(&mut self, + _f_name: &str, + _f_idx: usize, + _f: F) + -> Result + where F: FnOnce(&mut Decoder) -> Result + { + panic!() + } + + fn read_struct(&mut self, _s_name: &str, _len: usize, f: F) + -> Result + where F: FnOnce(&mut Decoder) -> Result + { + match self.toml { + Some(Value::Table(..)) => { + let ret = try!(f(self)); + match self.toml { + Some(Value::Table(ref t)) if t.len() == 0 => {} + _ => return Ok(ret) + } + self.toml.take(); + Ok(ret) + } + ref found => Err(self.mismatch("table", found)), + } + } + fn read_struct_field(&mut self, f_name: &str, _f_idx: usize, f: F) + -> Result + where F: FnOnce(&mut Decoder) -> Result + { + let field = format!("{}", f_name); + 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(&mut self, tuple_len: usize, f: F) + -> Result + where F: FnOnce(&mut Decoder) -> Result + { + 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(&mut self, a_idx: usize, f: F) + -> Result + where F: FnOnce(&mut Decoder) -> Result + { + self.read_seq_elt(a_idx, f) + } + + fn read_tuple_struct(&mut self, _s_name: &str, _len: usize, _f: F) + -> Result + where F: FnOnce(&mut Decoder) -> Result + { + panic!() + } + fn read_tuple_struct_arg(&mut self, _a_idx: usize, _f: F) + -> Result + where F: FnOnce(&mut Decoder) -> Result + { + panic!() + } + + // Specialized types: + fn read_option(&mut self, mut f: F) + -> Result + where F: FnMut(&mut Decoder, bool) -> Result + { + match self.toml { + Some(..) => f(self, true), + None => f(self, false), + } + } + + fn read_seq(&mut self, f: F) -> Result + where F: FnOnce(&mut Decoder, usize) -> Result + { + 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.len() != 0 { return Ok(ret) } + } + _ => return Ok(ret) + } + self.toml.take(); + Ok(ret) + } + fn read_seq_elt(&mut self, idx: usize, f: F) + -> Result + where F: FnOnce(&mut Decoder) -> Result + { + 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)); + match d.toml { + Some(toml) => match self.toml { + Some(Value::Array(ref mut arr)) => arr[idx] = toml, + _ => {} + }, + _ => {} + } + Ok(ret) + } + + fn read_map(&mut self, f: F) + -> Result + where F: FnOnce(&mut Decoder, usize) -> Result + { + let len = match self.toml { + Some(Value::Table(ref table)) => table.len(), + ref found => return Err(self.mismatch("table", found)), + }; + let ret = try!(f(self, len)); + self.toml.take(); + Ok(ret) + } + fn read_map_elt_key(&mut self, idx: usize, f: F) + -> Result + where F: FnOnce(&mut Decoder) -> Result + { + match self.toml { + Some(Value::Table(ref table)) => { + match table.iter().skip(idx).next() { + Some((key, _)) => { + let val = Value::String(format!("{}", key)); + f(&mut self.sub_decoder(Some(val), &**key)) + } + None => Err(self.err(ExpectedMapKey(idx))), + } + } + ref found => Err(self.mismatch("table", found)), + } + } + fn read_map_elt_val(&mut self, idx: usize, f: F) + -> Result + where F: FnOnce(&mut Decoder) -> Result + { + match self.toml { + Some(Value::Table(ref table)) => { + match table.iter().skip(idx).next() { + Some((_, value)) => { + // XXX: this shouldn't clone + f(&mut self.sub_decoder(Some(value.clone()), "")) + } + None => Err(self.err(ExpectedMapElement(idx))), + } + } + ref found => Err(self.mismatch("table", found)), + } + } + + fn error(&mut self, err: &str) -> DecodeError { + DecodeError { + field: self.cur_field.clone(), + kind: ApplicationError(format!("{}", err)) + } + } +} -- cgit v1.2.3