Skip to content

Commit

Permalink
Merge pull request #26 from maciejhirsz/0.7.2
Browse files Browse the repository at this point in the history
0.7.2 fixes #25, relevant to #24
  • Loading branch information
maciejhirsz authored Jun 24, 2016
2 parents 604effa + 4b79c5f commit 0fb3777
Show file tree
Hide file tree
Showing 7 changed files with 248 additions and 139 deletions.
2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "json"
version = "0.7.1"
version = "0.7.2"
authors = ["Maciej Hirsz <maciej.hirsz@gmail.com>"]
description = "JSON implementation in Rust"
repository = "https://github.com/maciejhirsz/json-rust"
Expand Down
4 changes: 3 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,9 @@

Parse and serialize [JSON](http://json.org/) with ease.

**[Complete Documentation](http://terhix.com/doc/json/) - [Cargo](https://crates.io/crates/json) - [Repository](https://github.com/maciejhirsz/json-rust)**
**[Complete Documentation](http://terhix.com/doc/json/) -**
**[Cargo](https://crates.io/crates/json) -**
**[Repository](https://github.com/maciejhirsz/json-rust)**

## Why?

Expand Down
8 changes: 4 additions & 4 deletions src/codegen.rs
Original file line number Diff line number Diff line change
Expand Up @@ -36,8 +36,8 @@ pub trait Generator {

fn write_digits_from_u64(&mut self, mut num: u64, length: &mut u8) {
let digit = (num % 10) as u8;
num /= 10;
if num > 0 {
if num > 9 {
num /= 10;
self.write_digits_from_u64(num, length);
}
*length += 1;
Expand All @@ -54,7 +54,7 @@ pub trait Generator {
self.write_digits_from_u64(num as u64, &mut length);

let mut fract = num.fract();
if fract < 1e-10 {
if fract < 1e-16 {
return;
}

Expand All @@ -64,7 +64,7 @@ pub trait Generator {
fract = fract.fract();
length += 2;

while length < 17 && fract > 0.01 {
while length < 17 && fract > 1e-15 {
fract *= 10.0;
self.write_char((fract as u8) + b'0');
fract = fract.fract();
Expand Down
24 changes: 17 additions & 7 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,9 @@
//!
//! Parse and serialize [JSON](http://json.org/) with ease.
//!
//! **[Complete Documentation](http://terhix.com/doc/json/) - [Cargo](https://crates.io/crates/json) - [Repository](https://github.com/maciejhirsz/json-rust)**
//! **[Complete Documentation](http://terhix.com/doc/json/) -**
//! **[Cargo](https://crates.io/crates/json) -**
//! **[Repository](https://github.com/maciejhirsz/json-rust)**
//!
//! ## Why?
//!
Expand Down Expand Up @@ -244,6 +246,11 @@ impl fmt::Display for JsonValue {
}
}

/// Convenience for `JsonValue::from(value)`
pub fn from<T>(value: T) -> JsonValue where T: Into<JsonValue> {
value.into()
}

#[deprecated(since="0.5.0", note="Use `value.dump(0)` instead")]
pub fn stringify_ref(root: &JsonValue) -> String {
root.dump()
Expand All @@ -262,6 +269,7 @@ pub fn stringify_pretty<T>(root: T, spaces: u16) -> String where T: Into<JsonVal
root.pretty(spaces)
}


#[macro_export]
macro_rules! array {
[] => ($crate::JsonValue::new_array());
Expand Down Expand Up @@ -307,18 +315,20 @@ macro_rules! implement_extras {

impl From<Vec<$from>> for JsonValue {
fn from(mut val: Vec<$from>) -> JsonValue {
JsonValue::Array(val.drain(..)
.map(|value| value.into())
.collect::<Vec<JsonValue>>()
JsonValue::Array(
val.drain(..)
.map(|value| value.into())
.collect()
)
}
}

impl From<Vec<Option<$from>>> for JsonValue {
fn from(mut val: Vec<Option<$from>>) -> JsonValue {
JsonValue::Array(val.drain(..)
.map(|item| item.into())
.collect::<Vec<JsonValue>>()
JsonValue::Array(
val.drain(..)
.map(|item| item.into())
.collect()
)
}
}
Expand Down
43 changes: 20 additions & 23 deletions src/parser.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,12 +19,14 @@ pub enum Token {
}

macro_rules! expect_char {
($tok:ident, $ch:pat) => {
match $tok.source.next() {
Some($ch) => {},
Some(ch) => return Err(JsonError::unexpected_character(ch)),
None => return Err(JsonError::UnexpectedEndOfJson)
}
($tok:ident, $( $ch:pat ),*) => {
$(
match $tok.source.next() {
Some($ch) => {},
Some(ch) => return Err(JsonError::unexpected_character(ch)),
None => return Err(JsonError::UnexpectedEndOfJson)
}
)*
}
}

Expand Down Expand Up @@ -205,22 +207,15 @@ impl<'a> Tokenizer<'a> {
b'"' => Token::String(try!(self.read_string())),
b'0' ... b'9' | b'-' => Token::Number(try!(self.read_number(ch))),
b't' => {
expect_char!(self, b'r');
expect_char!(self, b'u');
expect_char!(self, b'e');
expect_char!(self, b'r', b'u', b'e');
Token::Boolean(true)
},
b'f' => {
expect_char!(self, b'a');
expect_char!(self, b'l');
expect_char!(self, b's');
expect_char!(self, b'e');
expect_char!(self, b'a', b'l', b's', b'e');
Token::Boolean(false)
},
b'n' => {
expect_char!(self, b'u');
expect_char!(self, b'l');
expect_char!(self, b'l');
expect_char!(self, b'u', b'l', b'l');
Token::Null
},
// whitespace
Expand Down Expand Up @@ -326,13 +321,15 @@ impl<'a> Parser<'a> {

fn value_from(&mut self, token: Token) -> JsonResult<JsonValue> {
Ok(match token {
Token::String(value) => JsonValue::String(value),
Token::Number(value) => JsonValue::Number(value),
Token::Boolean(value) => JsonValue::Boolean(value),
Token::Null => JsonValue::Null,
Token::BracketOn => return self.array(),
Token::BraceOn => return self.object(),
token => return Err(JsonError::unexpected_token(token))
Token::String(value) => JsonValue::String(value),
Token::Number(value) => JsonValue::Number(value),
Token::Boolean(value) => JsonValue::Boolean(value),
Token::Null => JsonValue::Null,
Token::BracketOn => return self.array(),
Token::BraceOn => return self.object(),
token => {
return Err(JsonError::unexpected_token(token))
}
})
}

Expand Down
135 changes: 93 additions & 42 deletions src/value.rs
Original file line number Diff line number Diff line change
Expand Up @@ -62,8 +62,60 @@ impl JsonValue {
}
}

/// Deprecated because the return type is planned to change to
/// `Option<String>` eventually down the road.
pub fn is_number(&self) -> bool {
match *self {
JsonValue::Number(_) => true,
_ => false,
}
}

pub fn is_boolean(&self) -> bool {
match *self {
JsonValue::Boolean(_) => true,
_ => false
}
}

pub fn is_null(&self) -> bool {
match *self {
JsonValue::Null => true,
_ => false,
}
}

pub fn is_object(&self) -> bool {
match *self {
JsonValue::Object(_) => true,
_ => false,
}
}

pub fn is_array(&self) -> bool {
match *self {
JsonValue::Array(_) => true,
_ => false,
}
}

/// Checks whether the value is empty. Returns true for:
///
/// - empty string (`""`)
/// - number `0`
/// - boolean `false`
/// - null
/// - empty array (`array![]`)
/// - empty object (`object!{}`)
pub fn is_empty(&self) -> bool {
match *self {
JsonValue::String(ref value) => value.is_empty(),
JsonValue::Number(ref value) => !value.is_normal(),
JsonValue::Boolean(ref value) => !value,
JsonValue::Null => true,
JsonValue::Array(ref value) => value.is_empty(),
JsonValue::Object(ref value) => value.is_empty(),
}
}

#[deprecated(since="0.6.1", note="Use `as_str` instead")]
pub fn as_string(&self) -> JsonResult<&String> {
match *self {
Expand All @@ -79,13 +131,6 @@ impl JsonValue {
}
}

pub fn is_number(&self) -> bool {
match *self {
JsonValue::Number(_) => true,
_ => false,
}
}

#[deprecated(since="0.6.1", note="Use `as_f64` instead")]
pub fn as_number(&self) -> JsonResult<&f64> {
match *self {
Expand Down Expand Up @@ -145,10 +190,10 @@ impl JsonValue {
self.as_f64().and_then(|value| f64_to_singed!(isize, value))
}

pub fn is_boolean(&self) -> bool {
pub fn as_bool(&self) -> Option<bool> {
match *self {
JsonValue::Boolean(_) => true,
_ => false
JsonValue::Boolean(ref value) => Some(*value),
_ => None
}
}

Expand All @@ -160,34 +205,6 @@ impl JsonValue {
}
}

pub fn as_bool(&self) -> Option<bool> {
match *self {
JsonValue::Boolean(ref value) => Some(*value),
_ => None
}
}

pub fn is_null(&self) -> bool {
match *self {
JsonValue::Null => true,
_ => false,
}
}

pub fn is_object(&self) -> bool {
match *self {
JsonValue::Object(_) => true,
_ => false,
}
}

pub fn is_array(&self) -> bool {
match *self {
JsonValue::Array(_) => true,
_ => false,
}
}

/// Works on `JsonValue::Object` - create or override key with value.
#[must_use]
#[deprecated(since="0.6.0", note="Use `object[key] = value.into()` instead")]
Expand Down Expand Up @@ -262,6 +279,17 @@ impl JsonValue {
}
}

/// Works on `JsonValue::Array` - remove and return last element from
/// an array. On failure returns a null.
pub fn pop(&mut self) -> JsonValue {
match *self {
JsonValue::Array(ref mut vec) => {
vec.pop().unwrap_or(JsonValue::Null)
},
_ => JsonValue::Null
}
}

/// Works on `JsonValue::Array` - gets a reference to a value at index.
/// For most purposes consider using `array[index]` instead.
#[deprecated(since="0.6.0", note="Use `array[index]` instead")]
Expand Down Expand Up @@ -358,6 +386,29 @@ impl JsonValue {
_ => EntriesMut::None
}
}

/// Works on `JsonValue::Object` - remove a key and return the value it held.
/// If the key was not present, the method is called on anything but an
/// object, it will return a null.
pub fn remove(&mut self, key: &str) -> JsonValue {
match *self {
JsonValue::Object(ref mut btree) => {
btree.remove(key).unwrap_or(JsonValue::Null)
},
_ => JsonValue::Null
}
}

/// When called on an array or an object, will wipe them clean. When called
/// on a string will clear the string. Numbers and booleans become null.
pub fn clear(&mut self) {
match *self {
JsonValue::String(ref mut string) => string.clear(),
JsonValue::Object(ref mut btree) => btree.clear(),
JsonValue::Array(ref mut vec) => vec.clear(),
_ => *self = JsonValue::Null,
}
}
}

/// Implements indexing by `usize` to easily access array members:
Expand Down Expand Up @@ -411,7 +462,7 @@ impl IndexMut<usize> for JsonValue {
_ => {
*self = JsonValue::new_array();
self.push(JsonValue::Null).unwrap();
&mut self[0]
self.index_mut(index)
}
}
}
Expand Down Expand Up @@ -470,7 +521,7 @@ impl<'a> IndexMut<&'a str> for JsonValue {
},
_ => {
*self = JsonValue::new_object();
&mut self[index]
self.index_mut(index)
}
}
}
Expand Down
Loading

0 comments on commit 0fb3777

Please sign in to comment.