Skip to content

Commit c640883

Browse files
authored
Merge pull request #221 from huaoguo/feature/attrs
Serialize basic type as attributes when using serde
2 parents a14f87e + cc50bcb commit c640883

File tree

9 files changed

+115
-27
lines changed

9 files changed

+115
-27
lines changed

Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ memchr = "2.3.3"
2222

2323
[dev-dependencies]
2424
serde = { version = "1.0", features = ["derive"] }
25+
regex = "1"
2526

2627
[lib]
2728
bench = false

src/events/attributes.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -295,7 +295,7 @@ impl<'a> Iterator for Attributes<'a> {
295295
.consumed
296296
.iter()
297297
.filter(|r| r.len() == end_key - start_key)
298-
.find(|r| &self.bytes[(*r).clone()] == &self.bytes[start_key..end_key])
298+
.find(|r| self.bytes[(*r).clone()] == self.bytes[start_key..end_key])
299299
.map(|ref r| r.start)
300300
{
301301
err!(Error::DuplicatedAttribute(start_key, start));

src/events/mod.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,7 @@ impl<'a> BytesStart<'a> {
4545
pub fn borrowed(content: &'a [u8], name_len: usize) -> Self {
4646
BytesStart {
4747
buf: Cow::Borrowed(content),
48-
name_len: name_len,
48+
name_len,
4949
}
5050
}
5151

@@ -66,7 +66,7 @@ impl<'a> BytesStart<'a> {
6666
pub fn owned<C: Into<Vec<u8>>>(content: C, name_len: usize) -> BytesStart<'static> {
6767
BytesStart {
6868
buf: Cow::Owned(content.into()),
69-
name_len: name_len,
69+
name_len,
7070
}
7171
}
7272

src/reader.rs

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -97,7 +97,7 @@ impl<B: BufRead> Reader<B> {
9797
/// Creates a `Reader` that reads from a reader implementing `BufRead`.
9898
pub fn from_reader(reader: B) -> Reader<B> {
9999
Reader {
100-
reader: reader,
100+
reader,
101101
opened_buffer: Vec::new(),
102102
opened_starts: Vec::new(),
103103
tag_state: TagState::Closed,
@@ -339,7 +339,7 @@ impl<B: BufRead> Reader<B> {
339339
return Err(Error::UnexpectedEof("Comment".to_string()));
340340
}
341341
Ok(_) => (),
342-
Err(e) => return Err(e.into()),
342+
Err(e) => return Err(e),
343343
}
344344
}
345345
let len = buf.len();
@@ -394,11 +394,11 @@ impl<B: BufRead> Reader<B> {
394394
&buf[buf_start + 8..buf.len()],
395395
)))
396396
}
397-
_ => return Err(Error::UnexpectedBang),
397+
_ => Err(Error::UnexpectedBang),
398398
}
399399
} else {
400400
self.buf_position -= buf.len() - buf_start;
401-
return Err(Error::UnexpectedBang);
401+
Err(Error::UnexpectedBang)
402402
}
403403
}
404404

@@ -1144,21 +1144,21 @@ impl NamespaceBufferIndex {
11441144
let start = buffer.len();
11451145
buffer.extend_from_slice(&*v);
11461146
self.slices.push(Namespace {
1147-
start: start,
1147+
start,
11481148
prefix_len: 0,
11491149
value_len: v.len(),
1150-
level: level,
1150+
level,
11511151
});
11521152
}
11531153
Some(&b':') => {
11541154
let start = buffer.len();
11551155
buffer.extend_from_slice(&k[6..]);
11561156
buffer.extend_from_slice(&*v);
11571157
self.slices.push(Namespace {
1158-
start: start,
1158+
start,
11591159
prefix_len: k.len() - 6,
11601160
value_len: v.len(),
1161-
level: level,
1161+
level,
11621162
});
11631163
}
11641164
_ => break,

src/se/mod.rs

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -209,8 +209,9 @@ impl<'w, W: Write> ser::Serializer for &'w mut Serializer<W> {
209209
name: &'static str,
210210
_len: usize,
211211
) -> Result<Self::SerializeStruct, DeError> {
212-
self.writer
213-
.write_event(Event::Start(BytesStart::borrowed_name(name.as_bytes())))?;
212+
write!(self.writer.inner(), "<{}", name).map_err(|err| {
213+
DeError::Custom(format!("serialize struct {} failed: {}", name, err))
214+
})?;
214215
Ok(Struct::new(self, name))
215216
}
216217

@@ -258,7 +259,7 @@ mod tests {
258259
}
259260

260261
let got = String::from_utf8(buffer).unwrap();
261-
assert_eq!(got, "<foo>");
262+
assert_eq!(got, "<foo");
262263
}
263264

264265
#[test]
@@ -269,10 +270,13 @@ mod tests {
269270
let mut ser = Serializer::new(&mut buffer);
270271
let mut struct_ser = Struct::new(&mut ser, "baz");
271272
struct_ser.serialize_field("foo", "bar").unwrap();
273+
let attrs = std::str::from_utf8(&struct_ser.attrs).unwrap();
274+
assert_eq!(attrs, " foo=\"bar\"");
275+
let _ = struct_ser.end().unwrap();
272276
}
273277

274278
let got = String::from_utf8(buffer).unwrap();
275-
assert_eq!(got, "<foo>bar</foo>");
279+
assert_eq!(got, " foo=\"bar\"></baz>");
276280
}
277281

278282
#[test]
@@ -287,7 +291,7 @@ mod tests {
287291
name: "Bob".to_string(),
288292
age: 42,
289293
};
290-
let should_be = "<Person><name>Bob</name><age>42</age></Person>";
294+
let should_be = "<Person name=\"Bob\" age=\"42\"></Person>";
291295
let mut buffer = Vec::new();
292296

293297
{

src/se/var.rs

Lines changed: 31 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
use crate::{
22
errors::{serialize::DeError, Error},
3-
events::{BytesEnd, BytesStart, Event},
3+
events::{BytesEnd, Event},
44
se::Serializer,
55
};
66
use serde::ser::{self, Serialize};
@@ -72,6 +72,9 @@ where
7272
{
7373
parent: &'w mut Serializer<W>,
7474
name: &'w str,
75+
pub(crate) attrs: Vec<u8>,
76+
children: Vec<u8>,
77+
buffer: Vec<u8>,
7578
}
7679

7780
impl<'w, W> Struct<'w, W>
@@ -80,7 +83,7 @@ where
8083
{
8184
/// Create a new `Struct`
8285
pub fn new(parent: &'w mut Serializer<W>, name: &'w str) -> Struct<'w, W> {
83-
Struct { parent, name }
86+
Struct { parent, name, attrs: Vec::new(), children: Vec::new(), buffer: Vec::new() }
8487
}
8588
}
8689

@@ -96,18 +99,36 @@ where
9699
key: &'static str,
97100
value: &T,
98101
) -> Result<(), DeError> {
99-
let key = key.as_bytes();
100-
self.parent
101-
.writer
102-
.write_event(Event::Start(BytesStart::borrowed_name(key)))?;
103-
value.serialize(&mut *self.parent)?;
104-
self.parent
105-
.writer
106-
.write_event(Event::End(BytesEnd::borrowed(key)))?;
102+
let mut serializer = Serializer::new(&mut self.buffer);
103+
value.serialize(&mut serializer)?;
104+
105+
if !self.buffer.is_empty() {
106+
if self.buffer[0] == b'<' {
107+
write!(&mut self.children, "<{}>", key).map_err(Error::Io)?;
108+
self.children.extend(&self.buffer);
109+
write!(&mut self.children, "</{}>", key).map_err(Error::Io)?;
110+
} else {
111+
write!(&mut self.attrs, " {}=\"", key).map_err(Error::Io)?;
112+
self.attrs.extend(&self.buffer);
113+
write!(&mut self.attrs, "\"").map_err(Error::Io)?;
114+
}
115+
116+
self.buffer.clear();
117+
}
118+
107119
Ok(())
108120
}
109121

110122
fn end(self) -> Result<Self::Ok, DeError> {
123+
self.parent
124+
.writer
125+
.write(&self.attrs)?;
126+
self.parent
127+
.writer
128+
.write(">".as_bytes())?;
129+
self.parent
130+
.writer
131+
.write(&self.children)?;
111132
self.parent
112133
.writer
113134
.write_event(Event::End(BytesEnd::borrowed(self.name.as_bytes())))?;

src/writer.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -190,7 +190,7 @@ impl Indentation {
190190
}
191191

192192
fn grow(&mut self) {
193-
self.indents_len = self.indents_len + self.indent_size;
193+
self.indents_len += self.indent_size;
194194
if self.indents_len > self.indents.len() {
195195
self.indents.resize(self.indents_len, self.indent_char);
196196
}

tests/serde_attrs.rs

Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
#![cfg(feature = "serialize")]
2+
3+
extern crate quick_xml;
4+
extern crate serde;
5+
extern crate regex;
6+
7+
use quick_xml::se::to_string;
8+
use serde::Serialize;
9+
use regex::Regex;
10+
use std::borrow::Cow;
11+
12+
#[derive(Serialize)]
13+
#[serde(rename="classroom")]
14+
struct Classroom {
15+
pub students: Vec<Person>,
16+
pub number: String,
17+
pub adviser: Person
18+
}
19+
20+
#[derive(Serialize)]
21+
#[serde(rename="person")]
22+
struct Person {
23+
pub name: String,
24+
pub age: u32
25+
}
26+
27+
#[derive(Serialize)]
28+
#[serde(rename="empty")]
29+
struct Empty {}
30+
31+
#[test]
32+
fn test_nested() {
33+
let s1 = Person { name: "sherlock".to_string(), age: 20 };
34+
let s2 = Person { name: "harry".to_string(), age: 19 };
35+
let t = Person { name: "albus".to_string(), age: 88 };
36+
let doc = Classroom { students: vec![s1, s2], number: "3-1".to_string(), adviser: t };
37+
let xml = quick_xml::se::to_string(&doc).unwrap();
38+
39+
let str = r#"<classroom number="3-1">
40+
<students>
41+
<person name="sherlock" age="20"></person>
42+
<person name="harry" age="19"></person>
43+
</students>
44+
<adviser>
45+
<person name="albus" age="88"></person>
46+
</adviser>
47+
</classroom>"#;
48+
assert_eq!(xml, inline(str));
49+
}
50+
51+
fn inline(str: &str) -> Cow<str> {
52+
let regex = Regex::new(r">\s+<").unwrap();
53+
regex.replace_all(str, "><")
54+
}
55+
56+
#[test]
57+
fn test_empty() {
58+
let e = Empty {};
59+
let xml = to_string(&e).unwrap();
60+
assert_eq!(xml, "<empty></empty>");
61+
}

tests/serde_roundtrip.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@ fn basic_struct() {
3737
assert_eq!(item, should_be);
3838

3939
let reserialized_item = to_string(&item).unwrap();
40+
let src = "<Item name=\"Banana\" source=\"Store\"></Item>";
4041
assert_eq!(src, reserialized_item);
4142
}
4243

0 commit comments

Comments
 (0)