Compare commits

...

7 Commits

Author SHA1 Message Date
Erick Tryzelaar 206e19edb4 Fix unquoting arms with latest quasi 2015-05-02 10:44:57 -07:00
Erick Tryzelaar f0c87fbd4c Format flats with Debug to properly print "-0.0". 2015-05-01 07:43:48 -07:00
Erick Tryzelaar c3fe6c9c67 Update the README to point at https://github.com/serde-rs 2015-04-26 18:37:18 -07:00
Erick Tryzelaar e5df4b6653 Simplify PrettyFormatter::new 2015-04-26 12:05:38 -07:00
Erick Tryzelaar 12cf2f0b0b Simplify the return types 2015-04-26 11:01:55 -07:00
Erick Tryzelaar 8d4de2b3db Rename Serializer::new_with_formatter to with_formatter 2015-04-26 10:29:28 -07:00
Erick Tryzelaar e509adcac5 Allow the pretty printer character to be changed
This unfortunately loses the simd-ish whitespace printer, but since
pretty printing shouldn't be on a hot path, this shouldn't really
matter.

Partially addresses #65.
2015-04-26 09:29:06 -07:00
5 changed files with 80 additions and 69 deletions
+7 -8
View File
@@ -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" }
+28 -27
View File
@@ -1,7 +1,8 @@
Serde Rust Serialization Framework
==================================
[![Build Status](https://travis-ci.org/erickt/rust-serde.png?branch=master)](https://travis-ci.org/erickt/rust-serde)
[![Build Status](https://api.travis-ci.org/serde-rs/serde.png?branch=master)](https://travis-ci.org/serde-rs/serde)
[![Latest Version](https://img.shields.io/crates/v/serde.svg)](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 -1
View File
@@ -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"
+2 -2
View File
@@ -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
View File
@@ -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(())
}