mirror of
https://github.com/pezkuwichain/serde.git
synced 2026-04-23 00:08:01 +00:00
Compare commits
7 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 206e19edb4 | |||
| f0c87fbd4c | |||
| c3fe6c9c67 | |||
| e5df4b6653 | |||
| 12cf2f0b0b | |||
| 8d4de2b3db | |||
| e509adcac5 |
+7
-8
@@ -1,18 +1,17 @@
|
||||
[package]
|
||||
name = "serde"
|
||||
version = "0.3.2"
|
||||
version = "0.3.3"
|
||||
authors = ["Erick Tryzelaar <erick.tryzelaar@gmail.com>"]
|
||||
license = "MIT/Apache-2.0"
|
||||
description = "A serialization/deserialization framework"
|
||||
repository = "https://github.com/erickt/rust-serde"
|
||||
documentation = "http://erickt.github.io/rust-serde/serde"
|
||||
description = "A generic serialization/deserialization framework"
|
||||
repository = "https://github.com/serde-rs/serde"
|
||||
documentation = "http://serde-rs.github.io/serde/serde"
|
||||
readme = "README.md"
|
||||
keywords = ["serialization"]
|
||||
|
||||
[dependencies]
|
||||
num = "*"
|
||||
|
||||
[dev-dependencies]
|
||||
rustc-serialize = "*"
|
||||
|
||||
[dev-dependencies.serde_macros]
|
||||
path = "serde_macros/"
|
||||
version = "0.3.2"
|
||||
serde_macros = { version = "*", path = "serde_macros" }
|
||||
|
||||
@@ -1,7 +1,8 @@
|
||||
Serde Rust Serialization Framework
|
||||
==================================
|
||||
|
||||
[](https://travis-ci.org/erickt/rust-serde)
|
||||
[](https://travis-ci.org/serde-rs/serde)
|
||||
[](https://crates.io/crates/serde)
|
||||
|
||||
Serde is a powerful framework that enables serialization libraries to
|
||||
generically serialize Rust data structures without the overhead of runtime type
|
||||
@@ -9,7 +10,7 @@ information. In many situations, the handshake protocol between serializers and
|
||||
serializees can be completely optimized away, leaving Serde to perform roughly
|
||||
the same speed as a hand written serializer for a specific type.
|
||||
|
||||
Documentation is available at http://erickt.github.io/rust-serde/serde
|
||||
Documentation is available at http://serde-rs.github.io/serde/serde
|
||||
|
||||
Making a Type Serializable
|
||||
==========================
|
||||
@@ -17,9 +18,9 @@ Making a Type Serializable
|
||||
The simplest way to make a type serializable is to use the `serde_macros`
|
||||
syntax extension, which comes with a `#[derive(Serialize, Deserialize)]`
|
||||
annotation, which automatically generates implementations of
|
||||
[Serialize](http://erickt.github.io/rust-serde/serde/ser/trait.Serialize.html)
|
||||
[Serialize](http://serde-rs.github.io/serde/serde/ser/trait.Serialize.html)
|
||||
and
|
||||
[Deserialize](http://erickt.github.io/rust-serde/serde/de/trait.Deserialize.html)
|
||||
[Deserialize](http://serde-rs.github.io/serde/serde/de/trait.Deserialize.html)
|
||||
for the annotated type:
|
||||
|
||||
```rust
|
||||
@@ -38,11 +39,11 @@ struct Point {
|
||||
```
|
||||
|
||||
Serde bundles a high performance JSON serializer and deserializer,
|
||||
[serde::json](http://erickt.github.io/rust-serde/serde/json/index.html),
|
||||
[serde::json](http://serde-rs.github.io/serde/serde/json/index.html),
|
||||
which comes with the helper functions
|
||||
[to_string](http://erickt.github.io/rust-serde/serde/json/ser/fn.to_string.html)
|
||||
[to_string](http://serde-rs.github.io/serde/serde/json/ser/fn.to_string.html)
|
||||
and
|
||||
[from_str](http://erickt.github.io/rust-serde/serde/json/de/fn.from_str.html)
|
||||
[from_str](http://serde-rs.github.io/serde/serde/json/de/fn.from_str.html)
|
||||
that make it easy to go to and from JSON:
|
||||
|
||||
```rust
|
||||
@@ -58,19 +59,19 @@ println!("{}", serialized_point); // prints: {"x":1,"y":2}
|
||||
let deserialize_point: Point = json::from_str(&serialized_point).unwrap();
|
||||
```
|
||||
|
||||
[serde::json](http://erickt.github.io/rust-serde/serde/json/index.html) also
|
||||
[serde::json](http://serde-rs.github.io/serde/serde/json/index.html) also
|
||||
supports a generic
|
||||
[Value](http://erickt.github.io/rust-serde/serde/json/value/enum.Value.html)
|
||||
[Value](http://serde-rs.github.io/serde/serde/json/value/enum.Value.html)
|
||||
type, which can represent any JSON value. Also, any
|
||||
[Serialize](http://erickt.github.io/rust-serde/serde/ser/trait.Serialize.html)
|
||||
[Serialize](http://serde-rs.github.io/serde/serde/ser/trait.Serialize.html)
|
||||
and
|
||||
[Deserialize](http://erickt.github.io/rust-serde/serde/de/trait.Deserialize.html)
|
||||
[Deserialize](http://serde-rs.github.io/serde/serde/de/trait.Deserialize.html)
|
||||
can be converted into a
|
||||
[Value](http://erickt.github.io/rust-serde/serde/json/value/enum.Value.html)
|
||||
[Value](http://serde-rs.github.io/serde/serde/json/value/enum.Value.html)
|
||||
with the methods
|
||||
[to_value](http://erickt.github.io/rust-serde/serde/json/value/fn.to_value.html)
|
||||
[to_value](http://serde-rs.github.io/serde/serde/json/value/fn.to_value.html)
|
||||
and
|
||||
[from_value](http://erickt.github.io/rust-serde/serde/json/value/fn.from_value.html):
|
||||
[from_value](http://serde-rs.github.io/serde/serde/json/value/fn.from_value.html):
|
||||
|
||||
```rust
|
||||
let point = Point { x: 1, y: 2 };
|
||||
@@ -86,9 +87,9 @@ Serialization without Macros
|
||||
|
||||
Under the covers, Serde extensively uses the Visitor pattern to thread state
|
||||
between the
|
||||
[Serializer](http://erickt.github.io/rust-serde/serde/ser/trait.Serializer.html)
|
||||
[Serializer](http://serde-rs.github.io/serde/serde/ser/trait.Serializer.html)
|
||||
and
|
||||
[Serialize](http://erickt.github.io/rust-serde/serde/ser/trait.Serialize.html)
|
||||
[Serialize](http://serde-rs.github.io/serde/serde/ser/trait.Serialize.html)
|
||||
without the two having specific information about each other's concrete type.
|
||||
This has many of the same benefits as frameworks that use runtime type
|
||||
information without the overhead. In fact, when compiling with optimizations,
|
||||
@@ -97,7 +98,7 @@ nearly as fast as a hand written serializer format for a specific type.
|
||||
|
||||
To see it in action, lets look at how a simple type like `i32` is serialized.
|
||||
The
|
||||
[Serializer](http://erickt.github.io/rust-serde/serde/ser/trait.Serializer.html)
|
||||
[Serializer](http://serde-rs.github.io/serde/serde/ser/trait.Serializer.html)
|
||||
is threaded through the type:
|
||||
|
||||
```rust
|
||||
@@ -112,9 +113,9 @@ impl serde::Serialize for i32 {
|
||||
|
||||
As you can see it's pretty simple. More complex types like `BTreeMap` need to
|
||||
pass a
|
||||
[MapVisitor](http://erickt.github.io/rust-serde/serde/ser/trait.MapVisitor.html)
|
||||
[MapVisitor](http://serde-rs.github.io/serde/serde/ser/trait.MapVisitor.html)
|
||||
to the
|
||||
[Serializer](http://erickt.github.io/rust-serde/serde/ser/trait.Serializer.html)
|
||||
[Serializer](http://serde-rs.github.io/serde/serde/ser/trait.Serializer.html)
|
||||
in order to walk through the type:
|
||||
|
||||
```rust
|
||||
@@ -224,11 +225,11 @@ Deserialization without Macros
|
||||
|
||||
Deserialization is a little more complicated since there's a bit more error
|
||||
handling that needs to occur. Let's start with the simple `i32`
|
||||
[Deserialize](http://erickt.github.io/rust-serde/serde/de/trait.Deserialize.html)
|
||||
[Deserialize](http://serde-rs.github.io/serde/serde/de/trait.Deserialize.html)
|
||||
implementation. It passes a
|
||||
[Visitor](http://erickt.github.io/rust-serde/serde/de/trait.Visitor.html) to the
|
||||
[Deserializer](http://erickt.github.io/rust-serde/serde/de/trait.Deserializer.html).
|
||||
The [Visitor](http://erickt.github.io/rust-serde/serde/de/trait.Visitor.html)
|
||||
[Visitor](http://serde-rs.github.io/serde/serde/de/trait.Visitor.html) to the
|
||||
[Deserializer](http://serde-rs.github.io/serde/serde/de/trait.Deserializer.html).
|
||||
The [Visitor](http://serde-rs.github.io/serde/serde/de/trait.Visitor.html)
|
||||
can create the `i32` from a variety of different types:
|
||||
|
||||
```rust
|
||||
@@ -263,9 +264,9 @@ impl serde::de::Visitor for I32Visitor {
|
||||
|
||||
Since it's possible for this type to get passed an unexpected type, we need a
|
||||
way to error out. This is done by way of the
|
||||
[Error](http://erickt.github.io/rust-serde/serde/de/trait.Error.html) trait,
|
||||
[Error](http://serde-rs.github.io/serde/serde/de/trait.Error.html) trait,
|
||||
which allows a
|
||||
[Deserialize](http://erickt.github.io/rust-serde/serde/de/trait.Deserialize.html)
|
||||
[Deserialize](http://serde-rs.github.io/serde/serde/de/trait.Deserialize.html)
|
||||
to generate an error for a few common error conditions. Here's how it could be used:
|
||||
|
||||
```rust
|
||||
@@ -282,9 +283,9 @@ to generate an error for a few common error conditions. Here's how it could be u
|
||||
```
|
||||
|
||||
Maps follow a similar pattern as before, and use a
|
||||
[MapVisitor](http://erickt.github.io/rust-serde/serde/de/trait.MapVisitor.html)
|
||||
[MapVisitor](http://serde-rs.github.io/serde/serde/de/trait.MapVisitor.html)
|
||||
to walk through the values generated by the
|
||||
[Deserializer](http://erickt.github.io/rust-serde/serde/de/trait.Deserializer.html).
|
||||
[Deserializer](http://serde-rs.github.io/serde/serde/de/trait.Deserializer.html).
|
||||
|
||||
```rust
|
||||
impl<K, V> serde::Deserialize for BTreeMap<K, V>
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "serde_macros"
|
||||
version = "0.3.2"
|
||||
version = "0.3.3"
|
||||
authors = ["Erick Tryzelaar <erick.tryzelaar@gmail.com>"]
|
||||
license = "MIT/Apache-2.0"
|
||||
description = "Macros to auto-generate implementations for the serde framework"
|
||||
|
||||
@@ -361,8 +361,8 @@ fn deserialize_item_enum(
|
||||
let variant_arms: Vec<_> = enum_def.variants.iter()
|
||||
.enumerate()
|
||||
.map(|(i, variant)| {
|
||||
let variant_name = builder.expr().path()
|
||||
.id("__Field").id(format!("__field{}", i))
|
||||
let variant_name = builder.pat().enum_()
|
||||
.id("__Field").id(format!("__field{}", i)).build()
|
||||
.build();
|
||||
|
||||
let expr = deserialize_variant(
|
||||
|
||||
+42
-31
@@ -17,11 +17,20 @@ pub struct Serializer<W, F=CompactFormatter> {
|
||||
impl<W> Serializer<W>
|
||||
where W: io::Write,
|
||||
{
|
||||
/// Creates a new JSON visitr whose output will be written to the writer
|
||||
/// specified.
|
||||
/// Creates a new JSON serializer.
|
||||
#[inline]
|
||||
pub fn new(writer: W) -> Serializer<W> {
|
||||
Serializer::new_with_formatter(writer, CompactFormatter)
|
||||
pub fn new(writer: W) -> Self {
|
||||
Serializer::with_formatter(writer, CompactFormatter)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, W> Serializer<W, PrettyFormatter<'a>>
|
||||
where W: io::Write,
|
||||
{
|
||||
/// Creates a new JSON pretty print serializer.
|
||||
#[inline]
|
||||
pub fn pretty(writer: W) -> Self {
|
||||
Serializer::with_formatter(writer, PrettyFormatter::new())
|
||||
}
|
||||
}
|
||||
|
||||
@@ -29,10 +38,10 @@ impl<W, F> Serializer<W, F>
|
||||
where W: io::Write,
|
||||
F: Formatter,
|
||||
{
|
||||
/// Creates a new JSON visitr whose output will be written to the writer
|
||||
/// Creates a new JSON visitor whose output will be written to the writer
|
||||
/// specified.
|
||||
#[inline]
|
||||
pub fn new_with_formatter(writer: W, formatter: F) -> Serializer<W, F> {
|
||||
pub fn with_formatter(writer: W, formatter: F) -> Self {
|
||||
Serializer {
|
||||
writer: writer,
|
||||
formatter: formatter,
|
||||
@@ -295,16 +304,29 @@ impl Formatter for CompactFormatter {
|
||||
}
|
||||
}
|
||||
|
||||
pub struct PrettyFormatter {
|
||||
pub struct PrettyFormatter<'a> {
|
||||
current_indent: usize,
|
||||
indent: usize,
|
||||
indent: &'a [u8],
|
||||
}
|
||||
|
||||
impl Formatter for PrettyFormatter {
|
||||
impl<'a> PrettyFormatter<'a> {
|
||||
fn new() -> Self {
|
||||
PrettyFormatter::with_indent(b" ")
|
||||
}
|
||||
|
||||
fn with_indent(indent: &'a [u8]) -> Self {
|
||||
PrettyFormatter {
|
||||
current_indent: 0,
|
||||
indent: indent,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> Formatter for PrettyFormatter<'a> {
|
||||
fn open<W>(&mut self, writer: &mut W, ch: u8) -> io::Result<()>
|
||||
where W: io::Write,
|
||||
{
|
||||
self.current_indent += self.indent;
|
||||
self.current_indent += 1;
|
||||
writer.write_all(&[ch])
|
||||
}
|
||||
|
||||
@@ -317,7 +339,7 @@ impl Formatter for PrettyFormatter {
|
||||
try!(writer.write_all(b",\n"));
|
||||
}
|
||||
|
||||
spaces(writer, self.current_indent)
|
||||
indent(writer, self.current_indent, self.indent)
|
||||
}
|
||||
|
||||
fn colon<W>(&mut self, writer: &mut W) -> io::Result<()>
|
||||
@@ -329,9 +351,9 @@ impl Formatter for PrettyFormatter {
|
||||
fn close<W>(&mut self, writer: &mut W, ch: u8) -> io::Result<()>
|
||||
where W: io::Write,
|
||||
{
|
||||
self.current_indent -= self.indent;
|
||||
self.current_indent -= 1;
|
||||
try!(writer.write(b"\n"));
|
||||
try!(spaces(writer, self.current_indent));
|
||||
try!(indent(writer, self.current_indent, self.indent));
|
||||
|
||||
writer.write_all(&[ch])
|
||||
}
|
||||
@@ -396,7 +418,7 @@ fn fmt_f32_or_null<W>(wr: &mut W, value: f32) -> io::Result<()>
|
||||
match value.classify() {
|
||||
FpCategory::Nan | FpCategory::Infinite => wr.write_all(b"null"),
|
||||
_ => {
|
||||
let s = value.to_string();
|
||||
let s = format!("{:?}", value);
|
||||
try!(wr.write_all(s.as_bytes()));
|
||||
if !s.contains('.') {
|
||||
try!(wr.write_all(b".0"))
|
||||
@@ -412,7 +434,7 @@ fn fmt_f64_or_null<W>(wr: &mut W, value: f64) -> io::Result<()>
|
||||
match value.classify() {
|
||||
FpCategory::Nan | FpCategory::Infinite => wr.write_all(b"null"),
|
||||
_ => {
|
||||
let s = value.to_string();
|
||||
let s = format!("{:?}", value);
|
||||
try!(wr.write_all(s.as_bytes()));
|
||||
if !s.contains('.') {
|
||||
try!(wr.write_all(b".0"))
|
||||
@@ -439,10 +461,7 @@ pub fn to_writer_pretty<W, T>(writer: &mut W, value: &T) -> io::Result<()>
|
||||
where W: io::Write,
|
||||
T: ser::Serialize,
|
||||
{
|
||||
let mut ser = Serializer::new_with_formatter(writer, PrettyFormatter {
|
||||
current_indent: 0,
|
||||
indent: 2,
|
||||
});
|
||||
let mut ser = Serializer::pretty(writer);
|
||||
try!(value.serialize(&mut ser));
|
||||
Ok(())
|
||||
}
|
||||
@@ -489,20 +508,12 @@ pub fn to_string_pretty<T>(value: &T) -> Result<String, FromUtf8Error>
|
||||
String::from_utf8(vec)
|
||||
}
|
||||
|
||||
fn spaces<W>(wr: &mut W, mut n: usize) -> io::Result<()>
|
||||
fn indent<W>(wr: &mut W, n: usize, s: &[u8]) -> io::Result<()>
|
||||
where W: io::Write,
|
||||
{
|
||||
const LEN: usize = 16;
|
||||
const BUF: &'static [u8; LEN] = &[b' '; 16];
|
||||
|
||||
while n >= LEN {
|
||||
try!(wr.write_all(BUF));
|
||||
n -= LEN;
|
||||
for _ in 0 .. n {
|
||||
try!(wr.write_all(s));
|
||||
}
|
||||
|
||||
if n > 0 {
|
||||
wr.write_all(&BUF[..n])
|
||||
} else {
|
||||
Ok(())
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user