1 use std
::collections
::BTreeMap
;
8 #[cfg(feature = "rustc-serialize")] mod rustc_serialize;
9 #[cfg(feature = "serde")] mod serde;
11 /// A structure to transform Rust values into TOML values.
13 /// This encoder implements the serialization `Encoder` interface, allowing
14 /// `Encodable` rust types to be fed into the encoder. The output of this
15 /// encoder is a TOML `Table` structure. The resulting TOML can be stringified
21 /// extern crate rustc_serialize;
22 /// extern crate toml;
25 /// use toml::{Encoder, Value};
26 /// use rustc_serialize::Encodable;
28 /// #[derive(RustcEncodable)]
29 /// struct MyStruct { foo: isize, bar: String }
30 /// let my_struct = MyStruct { foo: 4, bar: "hello!".to_string() };
32 /// let mut e = Encoder::new();
33 /// my_struct.encode(&mut e).unwrap();
35 /// assert_eq!(e.toml.get(&"foo".to_string()), Some(&Value::Integer(4)))
39 /// Output TOML that is emitted. The current version of this encoder forces
40 /// the top-level representation of a structure to be a table.
42 /// This field can be used to extract the return value after feeding a value
43 /// into this `Encoder`.
48 /// Enumeration of errors which can occur while encoding a rust value into a
50 #[allow(missing_copy_implementations)]
53 /// Indication that a key was needed when a value was emitted, but no key
54 /// was previously emitted.
56 /// Indication that a key was emitted, but not value was emitted.
58 /// Indicates that a map key was attempted to be emitted at an invalid
60 InvalidMapKeyLocation
,
61 /// Indicates that a type other than a string was attempted to be used as a
64 /// A custom error type was generated
72 NextArray(Vec
<Value
>),
77 /// Constructs a new encoder which will emit to the given output stream.
78 pub fn new() -> Encoder
{
79 Encoder { state: State::Start, toml: BTreeMap::new() }
82 fn emit_value(&mut self, v
: Value
) -> Result
<(), Error
> {
83 match mem
::replace(&mut self.state
, State
::Start
) {
84 State
::NextKey(key
) => { self.toml.insert(key, v); Ok(()) }
85 State
::NextArray(mut vec
) => {
86 // TODO: validate types
88 self.state
= State
::NextArray(vec
);
91 State
::NextMapKey
=> {
93 Value
::String(s
) => { self.state = State::NextKey(s); Ok(()) }
94 _
=> Err(Error
::InvalidMapKeyType
)
97 _
=> Err(Error
::NeedsKey
)
101 fn emit_none(&mut self) -> Result
<(), Error
> {
102 match mem
::replace(&mut self.state
, State
::Start
) {
103 State
::Start
=> unreachable
!(),
104 State
::NextKey(_
) => Ok(()),
105 State
::NextArray(..) => panic
!("how to encode None in an array?"),
106 State
::NextMapKey
=> Err(Error
::InvalidMapKeyLocation
),
110 fn seq
<F
>(&mut self, f
: F
) -> Result
<(), Error
>
111 where F
: FnOnce(&mut Encoder
) -> Result
<(), Error
>
113 let old
= mem
::replace(&mut self.state
, State
::NextArray(Vec
::new()));
115 match mem
::replace(&mut self.state
, old
) {
116 State
::NextArray(v
) => self.emit_value(Value
::Array(v
)),
121 fn table
<F
>(&mut self, f
: F
) -> Result
<(), Error
>
122 where F
: FnOnce(&mut Encoder
) -> Result
<(), Error
>
124 match mem
::replace(&mut self.state
, State
::Start
) {
125 State
::NextKey(key
) => {
126 let mut nested
= Encoder
::new();
127 try
!(f(&mut nested
));
128 self.toml
.insert(key
, Value
::Table(nested
.toml
));
131 State
::NextArray(mut arr
) => {
132 let mut nested
= Encoder
::new();
133 try
!(f(&mut nested
));
134 arr
.push(Value
::Table(nested
.toml
));
135 self.state
= State
::NextArray(arr
);
138 State
::Start
=> f(self),
139 State
::NextMapKey
=> Err(Error
::InvalidMapKeyLocation
),
143 fn table_key
<F
>(&mut self, f
: F
) -> Result
<(), Error
>
144 where F
: FnOnce(&mut Encoder
) -> Result
<(), Error
>
146 match mem
::replace(&mut self.state
, State
::NextMapKey
) {
148 _
=> return Err(Error
::InvalidMapKeyLocation
),
152 State
::NextKey(_
) => Ok(()),
153 _
=> Err(Error
::InvalidMapKeyLocation
),
158 /// Encodes an encodable value into a TOML value.
160 /// This function expects the type given to represent a TOML table in some form.
161 /// If encoding encounters an error, then this function will fail the task.
162 #[cfg(feature = "rustc-serialize")]
163 pub fn encode
<T
: ::rustc_serialize
::Encodable
>(t
: &T
) -> Value
{
164 let mut e
= Encoder
::new();
165 t
.encode(&mut e
).unwrap();
169 /// Encodes an encodable value into a TOML value.
171 /// This function expects the type given to represent a TOML table in some form.
172 /// If encoding encounters an error, then this function will fail the task.
173 #[cfg(all(not(feature = "rustc-serialize"), feature = "serde"))]
174 pub fn encode
<T
: ::serde
::Serialize
>(t
: &T
) -> Value
{
175 let mut e
= Encoder
::new();
176 t
.serialize(&mut e
).unwrap();
180 /// Encodes an encodable value into a TOML string.
182 /// This function expects the type given to represent a TOML table in some form.
183 /// If encoding encounters an error, then this function will fail the task.
184 #[cfg(feature = "rustc-serialize")]
185 pub fn encode_str
<T
: ::rustc_serialize
::Encodable
>(t
: &T
) -> String
{
186 encode(t
).to_string()
189 /// Encodes an encodable value into a TOML string.
191 /// This function expects the type given to represent a TOML table in some form.
192 /// If encoding encounters an error, then this function will fail the task.
193 #[cfg(all(not(feature = "rustc-serialize"), feature = "serde"))]
194 pub fn encode_str
<T
: ::serde
::Serialize
>(t
: &T
) -> String
{
195 encode(t
).to_string()
198 impl fmt
::Display
for Error
{
199 fn fmt(&self, f
: &mut fmt
::Formatter
) -> fmt
::Result
{
201 Error
::NeedsKey
=> write
!(f
, "need a key to encode"),
202 Error
::NoValue
=> write
!(f
, "no value to emit for a previous key"),
203 Error
::InvalidMapKeyLocation
=> write
!(f
, "a map cannot be emitted \
205 Error
::InvalidMapKeyType
=> write
!(f
, "only strings can be used as \
207 Error
::Custom(ref s
) => write
!(f
, "custom error: {}", s
),
212 impl error
::Error
for Error
{
213 fn description(&self) -> &str { "TOML encoding error" }