]> git.proxmox.com Git - rustc.git/blame - src/vendor/toml/src/decoder/mod.rs
New upstream version 1.16.0+dfsg1
[rustc.git] / src / vendor / toml / src / decoder / mod.rs
CommitLineData
476ff2be
SL
1use std::error;
2use std::fmt;
3use std::collections::{btree_map, BTreeMap};
4use std::iter::Peekable;
5
6use Value;
7use self::DecodeErrorKind::*;
8
9#[cfg(feature = "rustc-serialize")] mod rustc_serialize;
10#[cfg(feature = "serde")] mod serde;
11
12/// A structure to transform TOML values into Rust values.
13///
14/// This decoder implements the serialization `Decoder` interface, allowing
15/// `Decodable` types to be generated by this decoder. The input is any
16/// arbitrary TOML value.
17pub struct Decoder {
18 /// The TOML value left over after decoding. This can be used to inspect
19 /// whether fields were decoded or not.
20 pub toml: Option<Value>,
21 cur_field: Option<String>,
22 cur_map: Peekable<btree_map::IntoIter<String, Value>>,
23 leftover_map: ::Table,
24}
25
26/// Description for errors which can occur while decoding a type.
27#[derive(PartialEq, Debug)]
28pub struct DecodeError {
29 /// Field that this error applies to.
30 pub field: Option<String>,
31 /// The type of error which occurred while decoding,
32 pub kind: DecodeErrorKind,
33}
34
35/// Enumeration of possible errors which can occur while decoding a structure.
36#[derive(PartialEq, Debug)]
37pub enum DecodeErrorKind {
38 /// An error flagged by the application, e.g. value out of range
39 ApplicationError(String),
40 /// A field was expected, but none was found.
41 ExpectedField(/* type */ Option<&'static str>),
42 /// A field was found, but it was not an expected one.
43 UnknownField,
44 /// A field was found, but it had the wrong type.
45 ExpectedType(/* expected */ &'static str, /* found */ &'static str),
46 /// The nth map key was expected, but none was found.
47 ExpectedMapKey(usize),
48 /// The nth map element was expected, but none was found.
49 ExpectedMapElement(usize),
50 /// An enum decoding was requested, but no variants were supplied
51 NoEnumVariants,
52 /// The unit type was being decoded, but a non-zero length string was found
53 NilTooLong,
54 /// There was an error with the syntactical structure of the TOML.
55 SyntaxError,
56 /// A custom error was generated when decoding.
57 CustomError(String),
58 /// The end of the TOML input was reached too soon
59 EndOfStream,
60 /// Produced by serde ...
61 InvalidType(&'static str),
62}
63
64/// Decodes a TOML value into a decodable type.
65///
66/// This function will consume the given TOML value and attempt to decode it
67/// into the type specified. If decoding fails, `None` will be returned. If a
68/// finer-grained error is desired, then it is recommended to use `Decodable`
69/// directly.
70#[cfg(feature = "rustc-serialize")]
71pub fn decode<T: ::rustc_serialize::Decodable>(toml: Value) -> Option<T> {
72 ::rustc_serialize::Decodable::decode(&mut Decoder::new(toml)).ok()
73}
74
75/// Decodes a TOML value into a decodable type.
76///
77/// This function will consume the given TOML value and attempt to decode it
78/// into the type specified. If decoding fails, `None` will be returned. If a
79/// finer-grained error is desired, then it is recommended to use `Decodable`
80/// directly.
81#[cfg(all(not(feature = "rustc-serialize"), feature = "serde"))]
82pub fn decode<T: ::serde::Deserialize>(toml: Value) -> Option<T> {
83 ::serde::Deserialize::deserialize(&mut Decoder::new(toml)).ok()
84}
85
86/// Decodes a string into a toml-encoded value.
87///
88/// This function will parse the given string into a TOML value, and then parse
89/// the TOML value into the desired type. If any error occurs, `None` is
90/// returned.
91///
92/// If more fine-grained errors are desired, these steps should be driven
93/// manually.
94#[cfg(feature = "rustc-serialize")]
95pub fn decode_str<T: ::rustc_serialize::Decodable>(s: &str) -> Option<T> {
96 ::Parser::new(s).parse().and_then(|t| decode(Value::Table(t)))
97}
98
99/// Decodes a string into a toml-encoded value.
100///
101/// This function will parse the given string into a TOML value, and then parse
102/// the TOML value into the desired type. If any error occurs, `None` is
103/// returned.
104///
105/// If more fine-grained errors are desired, these steps should be driven
106/// manually.
107#[cfg(all(not(feature = "rustc-serialize"), feature = "serde"))]
108pub fn decode_str<T: ::serde::Deserialize>(s: &str) -> Option<T> {
109 ::Parser::new(s).parse().and_then(|t| decode(Value::Table(t)))
110}
111
112impl Decoder {
113 /// Creates a new decoder, consuming the TOML value to decode.
114 ///
115 /// This decoder can be passed to the `Decodable` methods or driven
116 /// manually.
117 pub fn new(toml: Value) -> Decoder {
118 Decoder {
119 toml: Some(toml),
120 cur_field: None,
121 leftover_map: BTreeMap::new(),
122 cur_map: BTreeMap::new().into_iter().peekable(),
123 }
124 }
125
126 fn sub_decoder(&self, toml: Option<Value>, field: &str) -> Decoder {
127 Decoder {
128 toml: toml,
129 cur_field: if field.len() == 0 {
130 self.cur_field.clone()
131 } else {
132 match self.cur_field {
133 None => Some(format!("{}", field)),
134 Some(ref s) => Some(format!("{}.{}", s, field))
135 }
136 },
137 leftover_map: BTreeMap::new(),
138 cur_map: BTreeMap::new().into_iter().peekable(),
139 }
140 }
141
142 fn err(&self, kind: DecodeErrorKind) -> DecodeError {
143 DecodeError {
144 field: self.cur_field.clone(),
145 kind: kind,
146 }
147 }
148
149 fn mismatch(&self, expected: &'static str,
150 found: &Option<Value>) -> DecodeError{
151 match *found {
152 Some(ref val) => self.err(ExpectedType(expected, val.type_str())),
153 None => self.err(ExpectedField(Some(expected))),
154 }
155 }
156}
157
158impl fmt::Display for DecodeError {
159 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
160 try!(match self.kind {
161 ApplicationError(ref err) => {
162 write!(f, "{}", err)
163 }
164 ExpectedField(expected_type) => {
165 match expected_type {
166 Some("table") => write!(f, "expected a section"),
167 Some(e) => write!(f, "expected a value of type `{}`", e),
168 None => write!(f, "expected a value"),
169 }
170 }
171 UnknownField => write!(f, "unknown field"),
172 ExpectedType(expected, found) => {
173 fn humanize(s: &str) -> String {
174 if s == "section" {
175 format!("a section")
176 } else {
177 format!("a value of type `{}`", s)
178 }
179 }
180 write!(f, "expected {}, but found {}",
181 humanize(expected),
182 humanize(found))
183 }
184 ExpectedMapKey(idx) => {
185 write!(f, "expected at least {} keys", idx + 1)
186 }
187 ExpectedMapElement(idx) => {
188 write!(f, "expected at least {} elements", idx + 1)
189 }
190 NoEnumVariants => {
191 write!(f, "expected an enum variant to decode to")
192 }
193 NilTooLong => {
194 write!(f, "expected 0-length string")
195 }
196 SyntaxError => {
197 write!(f, "syntax error")
198 }
199 EndOfStream => {
200 write!(f, "end of stream")
201 }
202 InvalidType(s) => {
203 write!(f, "invalid type: {}", s)
204 }
205 CustomError(ref s) => {
206 write!(f, "custom error: {}", s)
207 }
208 });
209 match self.field {
210 Some(ref s) => {
211 write!(f, " for the key `{}`", s)
212 }
213 None => Ok(())
214 }
215 }
216}
217
218impl error::Error for DecodeError {
219 fn description(&self) -> &str {
220 match self.kind {
221 ApplicationError(ref s) => &**s,
222 ExpectedField(..) => "expected a field",
223 UnknownField => "found an unknown field",
224 ExpectedType(..) => "expected a type",
225 ExpectedMapKey(..) => "expected a map key",
226 ExpectedMapElement(..) => "expected a map element",
227 NoEnumVariants => "no enum variants to decode to",
228 NilTooLong => "nonzero length string representing nil",
229 SyntaxError => "syntax error",
230 EndOfStream => "end of stream",
231 InvalidType(..) => "invalid type",
232 CustomError(..) => "custom error",
233 }
234 }
235}