Skip to content

Commit 334efd9

Browse files
authored
Merge pull request #19 from maciejhirsz/0.6.0
0.6.0 closes #13, closes #16, closes #17
2 parents 3688b9b + d99750e commit 334efd9

File tree

6 files changed

+359
-109
lines changed

6 files changed

+359
-109
lines changed

Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
[package]
22
name = "json"
3-
version = "0.5.1"
3+
version = "0.6.0"
44
authors = ["Maciej Hirsz <maciej.hirsz@gmail.com>"]
55
description = "JSON implementation in Rust"
66
repository = "https://github.com/maciejhirsz/json-rust"

README.md

Lines changed: 22 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,7 @@ assert!(data["payload"]["features"].contains("easyAPI"));
4444
assert!(data["this"]["does"]["not"]["exist"].is_null());
4545
```
4646

47-
## Easily create JSON data without defining structs
47+
## Create JSON data without defining structs
4848

4949
```rust
5050
#[macro_use]
@@ -60,6 +60,27 @@ fn main() {
6060
}
6161
```
6262

63+
## Mutate simply by assigning new values
64+
65+
```rust
66+
let mut data = json::parse(r#"
67+
68+
{
69+
"name": "Bob",
70+
"isAwesome": false
71+
}
72+
73+
"#).unwrap();
74+
75+
data["isAwesome"] = true.into();
76+
data["likes"] = "Rust".into();
77+
78+
assert_eq!(data.dump(), r#"{"isAwesome":true,"likes":"Rust","name":"Bob"}"#);
79+
80+
// Pretty print the output
81+
println!("{:#}", data);
82+
```
83+
6384
## Installation
6485

6586
Just add it to your `Cargo.toml` file:

src/lib.rs

Lines changed: 49 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,7 @@
4444
//! assert!(data["this"]["does"]["not"]["exist"].is_null());
4545
//! ```
4646
//!
47-
//! ## Easily create JSON data without defining structs
47+
//! ## Create JSON data without defining structs
4848
//!
4949
//! ```
5050
//! #[macro_use]
@@ -60,6 +60,27 @@
6060
//! }
6161
//! ```
6262
//!
63+
//! ## Mutate simply by assigning new values
64+
//!
65+
//! ```
66+
//! let mut data = json::parse(r#"
67+
//!
68+
//! {
69+
//! "name": "Bob",
70+
//! "isAwesome": false
71+
//! }
72+
//!
73+
//! "#).unwrap();
74+
//!
75+
//! data["isAwesome"] = true.into();
76+
//! data["likes"] = "Rust".into();
77+
//!
78+
//! assert_eq!(data.dump(), r#"{"isAwesome":true,"likes":"Rust","name":"Bob"}"#);
79+
//!
80+
//! // Pretty print the output
81+
//! println!("{:#}", data);
82+
//! ```
83+
//!
6384
//! ## Serialize with `json::stringify(value)`
6485
//!
6586
//! Primitives:
@@ -126,8 +147,8 @@
126147
//! ```
127148
//! let mut data = json::JsonValue::new_object();
128149
//!
129-
//! data.put("answer", 42);
130-
//! data.put("foo", "bar");
150+
//! data["answer"] = 42.into();
151+
//! data["foo"] = "bar".into();
131152
//!
132153
//! assert_eq!(json::stringify(data), "{\"answer\":42,\"foo\":\"bar\"}");
133154
//! ```
@@ -177,6 +198,7 @@ use codegen::Generator;
177198

178199
use std::collections::HashMap;
179200
use std::collections::BTreeMap;
201+
use std::fmt;
180202

181203
pub type Array = Vec<JsonValue>;
182204
pub type Object = BTreeMap<String, JsonValue>;
@@ -198,6 +220,30 @@ impl JsonValue {
198220
}
199221
}
200222

223+
/// Implements formatting
224+
///
225+
/// ```
226+
/// # use json;
227+
/// let data = json::parse(r#"{"url":"https://github.com/"}"#).unwrap();
228+
/// println!("{}", data);
229+
/// println!("{:#}", data);
230+
/// ```
231+
impl fmt::Display for JsonValue {
232+
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
233+
if f.alternate() {
234+
f.write_str(&self.pretty(4))
235+
} else {
236+
match *self {
237+
JsonValue::String(ref value) => value.fmt(f),
238+
JsonValue::Number(ref value) => value.fmt(f),
239+
JsonValue::Boolean(ref value) => value.fmt(f),
240+
JsonValue::Null => f.write_str("null"),
241+
_ => f.write_str(&self.dump())
242+
}
243+
}
244+
}
245+
}
246+
201247
#[deprecated(since="0.5.0", note="Use `value.dump(0)` instead")]
202248
pub fn stringify_ref(root: &JsonValue) -> String {
203249
root.dump()

src/parser.rs

Lines changed: 42 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -29,12 +29,14 @@ pub enum Token {
2929

3030
struct Tokenizer<'a> {
3131
source: Peekable<Chars<'a>>,
32+
buffer: String,
3233
}
3334

3435
impl<'a> Tokenizer<'a> {
3536
pub fn new(source: &'a str) -> Self {
3637
Tokenizer {
3738
source: source.chars().peekable(),
39+
buffer: String::new()
3840
}
3941
}
4042

@@ -64,20 +66,21 @@ impl<'a> Tokenizer<'a> {
6466
})
6567
}
6668

67-
fn read_label(&mut self, first: char) -> String {
68-
let mut label = first.to_string();
69+
fn read_label(&mut self, first: char) -> &String {
70+
self.buffer.clear();
71+
self.buffer.push(first);
6972

7073
while let Some(&ch) = self.source.peek() {
7174
match ch {
7275
'a'...'z' => {
73-
label.push(ch);
76+
self.buffer.push(ch);
7477
self.source.next();
7578
},
7679
_ => break,
7780
}
7881
}
7982

80-
label
83+
&self.buffer
8184
}
8285

8386
fn read_codepoint(&mut self) -> JsonResult<char> {
@@ -122,30 +125,53 @@ impl<'a> Tokenizer<'a> {
122125
Ok(value)
123126
}
124127

128+
fn read_digits_to_buffer(&mut self) {
129+
while let Some(&ch) = self.source.peek() {
130+
match ch {
131+
'0' ... '9' => {
132+
self.buffer.push(ch);
133+
self.source.next();
134+
},
135+
_ => break
136+
}
137+
}
138+
}
139+
125140
fn read_number(&mut self, first: char) -> f64 {
126-
let mut value = first.to_string();
141+
self.buffer.clear();
142+
self.buffer.push(first);
143+
self.read_digits_to_buffer();
144+
127145
let mut period = false;
128146

129147
while let Some(&ch) = self.source.peek() {
130148
match ch {
131-
'0'...'9' => {
132-
value.push(ch);
149+
'.' => {
150+
if period {
151+
panic!("Invalid character `{:?}`", ch);
152+
}
153+
period = true;
154+
self.buffer.push(ch);
133155
self.source.next();
156+
self.read_digits_to_buffer();
134157
},
135-
'.' => {
136-
if !period {
137-
period = true;
138-
value.push(ch);
139-
self.source.next();
140-
} else {
141-
return value.parse::<f64>().unwrap();
158+
'e' | 'E' => {
159+
self.buffer.push(ch);
160+
self.source.next();
161+
match self.source.peek() {
162+
Some(&'-') | Some(&'+') => {
163+
self.buffer.push(self.source.next().unwrap());
164+
},
165+
_ => {}
142166
}
167+
self.read_digits_to_buffer();
168+
break;
143169
},
144-
_ => return value.parse::<f64>().unwrap(),
170+
_ => break
145171
}
146172
}
147173

148-
value.parse::<f64>().unwrap()
174+
self.buffer.parse::<f64>().unwrap()
149175
}
150176
}
151177

0 commit comments

Comments
 (0)