mirror of
https://github.com/pezkuwichain/serde.git
synced 2026-04-24 05:18:00 +00:00
Compare commits
7 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 206e19edb4 | |||
| f0c87fbd4c | |||
| c3fe6c9c67 | |||
| e5df4b6653 | |||
| 12cf2f0b0b | |||
| 8d4de2b3db | |||
| e509adcac5 |
+7
-8
@@ -1,18 +1,17 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "serde"
|
name = "serde"
|
||||||
version = "0.3.2"
|
version = "0.3.3"
|
||||||
authors = ["Erick Tryzelaar <erick.tryzelaar@gmail.com>"]
|
authors = ["Erick Tryzelaar <erick.tryzelaar@gmail.com>"]
|
||||||
license = "MIT/Apache-2.0"
|
license = "MIT/Apache-2.0"
|
||||||
description = "A serialization/deserialization framework"
|
description = "A generic serialization/deserialization framework"
|
||||||
repository = "https://github.com/erickt/rust-serde"
|
repository = "https://github.com/serde-rs/serde"
|
||||||
documentation = "http://erickt.github.io/rust-serde/serde"
|
documentation = "http://serde-rs.github.io/serde/serde"
|
||||||
|
readme = "README.md"
|
||||||
|
keywords = ["serialization"]
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
num = "*"
|
num = "*"
|
||||||
|
|
||||||
[dev-dependencies]
|
[dev-dependencies]
|
||||||
rustc-serialize = "*"
|
rustc-serialize = "*"
|
||||||
|
serde_macros = { version = "*", path = "serde_macros" }
|
||||||
[dev-dependencies.serde_macros]
|
|
||||||
path = "serde_macros/"
|
|
||||||
version = "0.3.2"
|
|
||||||
|
|||||||
@@ -1,7 +1,8 @@
|
|||||||
Serde Rust Serialization Framework
|
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
|
Serde is a powerful framework that enables serialization libraries to
|
||||||
generically serialize Rust data structures without the overhead of runtime type
|
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
|
serializees can be completely optimized away, leaving Serde to perform roughly
|
||||||
the same speed as a hand written serializer for a specific type.
|
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
|
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`
|
The simplest way to make a type serializable is to use the `serde_macros`
|
||||||
syntax extension, which comes with a `#[derive(Serialize, Deserialize)]`
|
syntax extension, which comes with a `#[derive(Serialize, Deserialize)]`
|
||||||
annotation, which automatically generates implementations of
|
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
|
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:
|
for the annotated type:
|
||||||
|
|
||||||
```rust
|
```rust
|
||||||
@@ -38,11 +39,11 @@ struct Point {
|
|||||||
```
|
```
|
||||||
|
|
||||||
Serde bundles a high performance JSON serializer and deserializer,
|
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
|
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
|
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:
|
that make it easy to go to and from JSON:
|
||||||
|
|
||||||
```rust
|
```rust
|
||||||
@@ -58,19 +59,19 @@ println!("{}", serialized_point); // prints: {"x":1,"y":2}
|
|||||||
let deserialize_point: Point = json::from_str(&serialized_point).unwrap();
|
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
|
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
|
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
|
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
|
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
|
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
|
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
|
```rust
|
||||||
let point = Point { x: 1, y: 2 };
|
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
|
Under the covers, Serde extensively uses the Visitor pattern to thread state
|
||||||
between the
|
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
|
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.
|
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
|
This has many of the same benefits as frameworks that use runtime type
|
||||||
information without the overhead. In fact, when compiling with optimizations,
|
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.
|
To see it in action, lets look at how a simple type like `i32` is serialized.
|
||||||
The
|
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:
|
is threaded through the type:
|
||||||
|
|
||||||
```rust
|
```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
|
As you can see it's pretty simple. More complex types like `BTreeMap` need to
|
||||||
pass a
|
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
|
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:
|
in order to walk through the type:
|
||||||
|
|
||||||
```rust
|
```rust
|
||||||
@@ -224,11 +225,11 @@ Deserialization without Macros
|
|||||||
|
|
||||||
Deserialization is a little more complicated since there's a bit more error
|
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`
|
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
|
implementation. It passes a
|
||||||
[Visitor](http://erickt.github.io/rust-serde/serde/de/trait.Visitor.html) to the
|
[Visitor](http://serde-rs.github.io/serde/serde/de/trait.Visitor.html) to 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).
|
||||||
The [Visitor](http://erickt.github.io/rust-serde/serde/de/trait.Visitor.html)
|
The [Visitor](http://serde-rs.github.io/serde/serde/de/trait.Visitor.html)
|
||||||
can create the `i32` from a variety of different types:
|
can create the `i32` from a variety of different types:
|
||||||
|
|
||||||
```rust
|
```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
|
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
|
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
|
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:
|
to generate an error for a few common error conditions. Here's how it could be used:
|
||||||
|
|
||||||
```rust
|
```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
|
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
|
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
|
```rust
|
||||||
impl<K, V> serde::Deserialize for BTreeMap<K, V>
|
impl<K, V> serde::Deserialize for BTreeMap<K, V>
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "serde_macros"
|
name = "serde_macros"
|
||||||
version = "0.3.2"
|
version = "0.3.3"
|
||||||
authors = ["Erick Tryzelaar <erick.tryzelaar@gmail.com>"]
|
authors = ["Erick Tryzelaar <erick.tryzelaar@gmail.com>"]
|
||||||
license = "MIT/Apache-2.0"
|
license = "MIT/Apache-2.0"
|
||||||
description = "Macros to auto-generate implementations for the serde framework"
|
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()
|
let variant_arms: Vec<_> = enum_def.variants.iter()
|
||||||
.enumerate()
|
.enumerate()
|
||||||
.map(|(i, variant)| {
|
.map(|(i, variant)| {
|
||||||
let variant_name = builder.expr().path()
|
let variant_name = builder.pat().enum_()
|
||||||
.id("__Field").id(format!("__field{}", i))
|
.id("__Field").id(format!("__field{}", i)).build()
|
||||||
.build();
|
.build();
|
||||||
|
|
||||||
let expr = deserialize_variant(
|
let expr = deserialize_variant(
|
||||||
|
|||||||
+41
-30
@@ -17,11 +17,20 @@ pub struct Serializer<W, F=CompactFormatter> {
|
|||||||
impl<W> Serializer<W>
|
impl<W> Serializer<W>
|
||||||
where W: io::Write,
|
where W: io::Write,
|
||||||
{
|
{
|
||||||
/// Creates a new JSON visitr whose output will be written to the writer
|
/// Creates a new JSON serializer.
|
||||||
/// specified.
|
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn new(writer: W) -> Serializer<W> {
|
pub fn new(writer: W) -> Self {
|
||||||
Serializer::new_with_formatter(writer, CompactFormatter)
|
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,
|
where W: io::Write,
|
||||||
F: Formatter,
|
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.
|
/// specified.
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn new_with_formatter(writer: W, formatter: F) -> Serializer<W, F> {
|
pub fn with_formatter(writer: W, formatter: F) -> Self {
|
||||||
Serializer {
|
Serializer {
|
||||||
writer: writer,
|
writer: writer,
|
||||||
formatter: formatter,
|
formatter: formatter,
|
||||||
@@ -295,16 +304,29 @@ impl Formatter for CompactFormatter {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct PrettyFormatter {
|
pub struct PrettyFormatter<'a> {
|
||||||
current_indent: usize,
|
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<()>
|
fn open<W>(&mut self, writer: &mut W, ch: u8) -> io::Result<()>
|
||||||
where W: io::Write,
|
where W: io::Write,
|
||||||
{
|
{
|
||||||
self.current_indent += self.indent;
|
self.current_indent += 1;
|
||||||
writer.write_all(&[ch])
|
writer.write_all(&[ch])
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -317,7 +339,7 @@ impl Formatter for PrettyFormatter {
|
|||||||
try!(writer.write_all(b",\n"));
|
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<()>
|
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<()>
|
fn close<W>(&mut self, writer: &mut W, ch: u8) -> io::Result<()>
|
||||||
where W: io::Write,
|
where W: io::Write,
|
||||||
{
|
{
|
||||||
self.current_indent -= self.indent;
|
self.current_indent -= 1;
|
||||||
try!(writer.write(b"\n"));
|
try!(writer.write(b"\n"));
|
||||||
try!(spaces(writer, self.current_indent));
|
try!(indent(writer, self.current_indent, self.indent));
|
||||||
|
|
||||||
writer.write_all(&[ch])
|
writer.write_all(&[ch])
|
||||||
}
|
}
|
||||||
@@ -396,7 +418,7 @@ fn fmt_f32_or_null<W>(wr: &mut W, value: f32) -> io::Result<()>
|
|||||||
match value.classify() {
|
match value.classify() {
|
||||||
FpCategory::Nan | FpCategory::Infinite => wr.write_all(b"null"),
|
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()));
|
try!(wr.write_all(s.as_bytes()));
|
||||||
if !s.contains('.') {
|
if !s.contains('.') {
|
||||||
try!(wr.write_all(b".0"))
|
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() {
|
match value.classify() {
|
||||||
FpCategory::Nan | FpCategory::Infinite => wr.write_all(b"null"),
|
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()));
|
try!(wr.write_all(s.as_bytes()));
|
||||||
if !s.contains('.') {
|
if !s.contains('.') {
|
||||||
try!(wr.write_all(b".0"))
|
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,
|
where W: io::Write,
|
||||||
T: ser::Serialize,
|
T: ser::Serialize,
|
||||||
{
|
{
|
||||||
let mut ser = Serializer::new_with_formatter(writer, PrettyFormatter {
|
let mut ser = Serializer::pretty(writer);
|
||||||
current_indent: 0,
|
|
||||||
indent: 2,
|
|
||||||
});
|
|
||||||
try!(value.serialize(&mut ser));
|
try!(value.serialize(&mut ser));
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
@@ -489,20 +508,12 @@ pub fn to_string_pretty<T>(value: &T) -> Result<String, FromUtf8Error>
|
|||||||
String::from_utf8(vec)
|
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,
|
where W: io::Write,
|
||||||
{
|
{
|
||||||
const LEN: usize = 16;
|
for _ in 0 .. n {
|
||||||
const BUF: &'static [u8; LEN] = &[b' '; 16];
|
try!(wr.write_all(s));
|
||||||
|
|
||||||
while n >= LEN {
|
|
||||||
try!(wr.write_all(BUF));
|
|
||||||
n -= LEN;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if n > 0 {
|
|
||||||
wr.write_all(&BUF[..n])
|
|
||||||
} else {
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user