Discussion:
[rust-dev] json read_str crashes
Daneel Yaitskov
2014-09-18 15:44:39 UTC
Permalink
I have a custom json deserializer. It can parse string or number.

json functions return Result enum so I guess if it fails it should return
Err. But lines println!("crap") or println!("string is ok") are not
reached.

Program crashes with the following output:

not int. let's try string
task '<main>' failed at 'called `Option::unwrap()` on a `None` value',
/home/rustbuild/src/rust-buildbot/slave/nightly-linux/build/src/libcore/
option.rs:278


extern crate serialize;
use serialize::{json, Decodable, Decoder};

fn main() {
let raw_json = "\"ddd\"";
let person: Primitive = json::decode(raw_json).unwrap();
println!("{}", person);
}

#[deriving(Show)]
enum Primitive { ItInt(int), ItStr(String) }

impl<S: Decoder<E>, E> Decodable<S, E> for Primitive {
fn decode(decoder: &mut S) -> Result<Primitive, E> {
match decoder.read_int() {
Ok(n) => Ok(ItInt(n)),
_ => {
println!("not int. let's try string");
match decoder.read_str() {
Ok(s) => {
println!("string is ok");
Ok(ItStr(s))
},
_ => {
println!("crap");
Ok(ItStr("DDD".to_string()))
}
}
}
}
}
}
--
Daneel S. Yaitskov
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.mozilla.org/pipermail/rust-dev/attachments/20140918/1e954117/attachment.html>
Tim Joseph Dumol
2014-09-18 15:52:23 UTC
Permalink
Hi Daneel,

Your `read_str` function tried to unwrap an `Option` that turned out to be
`None`, which caused your error. You'll want to `match` on the that
`Option` instead and handle for the case when it's a `None`. Good luck!

Cheers,

Tim Joseph Dumol

On Thu, Sep 18, 2014 at 11:44 PM, Daneel Yaitskov <rtfm.rtfm.rtfm at gmail.com>
Post by Daneel Yaitskov
I have a custom json deserializer. It can parse string or number.
json functions return Result enum so I guess if it fails it should return
Err. But lines println!("crap") or println!("string is ok") are not
reached.
not int. let's try string
task '<main>' failed at 'called `Option::unwrap()` on a `None` value',
/home/rustbuild/src/rust-buildbot/slave/nightly-linux/build/src/libcore/
option.rs:278
extern crate serialize;
use serialize::{json, Decodable, Decoder};
fn main() {
let raw_json = "\"ddd\"";
let person: Primitive = json::decode(raw_json).unwrap();
println!("{}", person);
}
#[deriving(Show)]
enum Primitive { ItInt(int), ItStr(String) }
impl<S: Decoder<E>, E> Decodable<S, E> for Primitive {
fn decode(decoder: &mut S) -> Result<Primitive, E> {
match decoder.read_int() {
Ok(n) => Ok(ItInt(n)),
_ => {
println!("not int. let's try string");
match decoder.read_str() {
Ok(s) => {
println!("string is ok");
Ok(ItStr(s))
},
_ => {
println!("crap");
Ok(ItStr("DDD".to_string()))
}
}
}
}
}
}
--
Daneel S. Yaitskov
_______________________________________________
Rust-dev mailing list
Rust-dev at mozilla.org
https://mail.mozilla.org/listinfo/rust-dev
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.mozilla.org/pipermail/rust-dev/attachments/20140918/a6794f50/attachment.html>
Tim Joseph Dumol
2014-09-18 16:54:05 UTC
Permalink
Hi Daneel,

What seems to be happening (which others might be able to confirm) is that
the JSON decoder is consuming the string as a stack, and after the first
read_int() fails, there is no nothing left to pop (in
doc.rust-lang.org/src/serialize/home/rustbuild/src/rust-buildbot/slave/nightly-linux/build/src/libserialize/json.rs.html#1916),
which causes the subsequent read_str() to fail. You can double-check this
by removing the `read_int()` call, after which the `read_str()` works.

Cheers,

Tim Joseph Dumol
Whoops, my bad! I misread your code in my haste to answer your question.
I'm a newbie to Rust, actually, so I'll have to spend some time exploring
why this is happening. Maybe someone else can help faster. Sorry for the
confusion!
Tim Joseph Dumol
On Fri, Sep 19, 2014 at 12:23 AM, Daneel Yaitskov <
Why does read_str returns Result? I cannot catch the Err because of fail!
It looks weird. Where is the sense?
Just String result would better fit to read_str wiith such behavior,
wouldn't it?
Here is another question. Have Rust standard painless method to
deserialize json map with different primitive value types (int, string,
bool...)?
json::decode(String) -> Option<HashMap<String,String>>
or
json::decode(String) -> Option<HashMap<String,Primitive>>
where
enum Primitive { Pint(int), Pstr(String), .... }
Post by Tim Joseph Dumol
Hi Daneel,
Your `read_str` function tried to unwrap an `Option` that turned out to
be `None`, which caused your error. You'll want to `match` on the that
`Option` instead and handle for the case when it's a `None`. Good luck!
Cheers,
Tim Joseph Dumol
On Thu, Sep 18, 2014 at 11:44 PM, Daneel Yaitskov <
Post by Daneel Yaitskov
I have a custom json deserializer. It can parse string or number.
json functions return Result enum so I guess if it fails it should return
Err. But lines println!("crap") or println!("string is ok") are not
reached.
not int. let's try string
task '<main>' failed at 'called `Option::unwrap()` on a `None` value',
/home/rustbuild/src/rust-buildbot/slave/nightly-linux/build/src/libcore/
option.rs:278
extern crate serialize;
use serialize::{json, Decodable, Decoder};
fn main() {
let raw_json = "\"ddd\"";
let person: Primitive = json::decode(raw_json).unwrap();
println!("{}", person);
}
#[deriving(Show)]
enum Primitive { ItInt(int), ItStr(String) }
impl<S: Decoder<E>, E> Decodable<S, E> for Primitive {
fn decode(decoder: &mut S) -> Result<Primitive, E> {
match decoder.read_int() {
Ok(n) => Ok(ItInt(n)),
_ => {
println!("not int. let's try string");
match decoder.read_str() {
Ok(s) => {
println!("string is ok");
Ok(ItStr(s))
},
_ => {
println!("crap");
Ok(ItStr("DDD".to_string()))
}
}
}
}
}
}
--
Daneel S. Yaitskov
_______________________________________________
Rust-dev mailing list
Rust-dev at mozilla.org
https://mail.mozilla.org/listinfo/rust-dev
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.mozilla.org/pipermail/rust-dev/attachments/20140919/f68f4dfb/attachment.html>
Daneel Yaitskov
2014-09-18 19:42:21 UTC
Permalink
Thanks, Tim.

I understood my fault but still cannot get deserialization mixed value.
I tried to call pop method directly but it's private.


extern crate serialize;
use serialize::{Decodable, Decoder};
use serialize::json::{Json, Boolean, String, Null, I64, U64, F64};
use serialize::json;

#[deriving(Show)]
struct Primitive(Json);

impl<S: Decoder<E>, E> Decodable<S, E> for Primitive {
fn decode(decoder: &mut S) -> Result<Primitive, E> {
match decoder.pop() {
Null => Primitive(Null),
b @ Boolean(_)=> Primitive(b),
n @ I64(_) => Primitive(n),
n @ U64(_) => Primitive(n),
n @ F64(_) => Primitive(n),
s @ String(_) => Primitive(s),
bad => fail!("bad {}", bad)
}
}
}
Post by Tim Joseph Dumol
Hi Daneel,
What seems to be happening (which others might be able to confirm) is that
the JSON decoder is consuming the string as a stack, and after the first
read_int() fails, there is no nothing left to pop (in
doc.rust-lang.org/src/serialize/home/rustbuild/src/rust-buildbot/slave/nightly-linux/build/src/libserialize/json.rs.html#1916),
which causes the subsequent read_str() to fail. You can double-check this by
removing the `read_int()` call, after which the `read_str()` works.
Cheers,
Tim Joseph Dumol
Whoops, my bad! I misread your code in my haste to answer your question.
I'm a newbie to Rust, actually, so I'll have to spend some time exploring
why this is happening. Maybe someone else can help faster. Sorry for the
confusion!
Tim Joseph Dumol
On Fri, Sep 19, 2014 at 12:23 AM, Daneel Yaitskov
Why does read_str returns Result? I cannot catch the Err because of fail!
It looks weird. Where is the sense?
Just String result would better fit to read_str wiith such behavior,
wouldn't it?
Here is another question. Have Rust standard painless method to
deserialize json map with different primitive value types (int, string,
bool...)?
json::decode(String) -> Option<HashMap<String,String>>
or
json::decode(String) -> Option<HashMap<String,Primitive>>
where
enum Primitive { Pint(int), Pstr(String), .... }
Post by Tim Joseph Dumol
Hi Daneel,
Your `read_str` function tried to unwrap an `Option` that turned out to
be `None`, which caused your error. You'll want to `match` on the that
`Option` instead and handle for the case when it's a `None`. Good luck!
Cheers,
Tim Joseph Dumol
On Thu, Sep 18, 2014 at 11:44 PM, Daneel Yaitskov
Post by Daneel Yaitskov
I have a custom json deserializer. It can parse string or number.
json functions return Result enum so I guess if it fails it should return
Err. But lines println!("crap") or println!("string is ok") are not
reached.
not int. let's try string
task '<main>' failed at 'called `Option::unwrap()` on a `None` value',
/home/rustbuild/src/rust-buildbot/slave/nightly-linux/build/src/libcore/option.rs:278
extern crate serialize;
use serialize::{json, Decodable, Decoder};
fn main() {
let raw_json = "\"ddd\"";
let person: Primitive = json::decode(raw_json).unwrap();
println!("{}", person);
}
#[deriving(Show)]
enum Primitive { ItInt(int), ItStr(String) }
impl<S: Decoder<E>, E> Decodable<S, E> for Primitive {
fn decode(decoder: &mut S) -> Result<Primitive, E> {
match decoder.read_int() {
Ok(n) => Ok(ItInt(n)),
_ => {
println!("not int. let's try string");
match decoder.read_str() {
Ok(s) => {
println!("string is ok");
Ok(ItStr(s))
},
_ => {
println!("crap");
Ok(ItStr("DDD".to_string()))
}
}
}
}
}
}
--
Daneel S. Yaitskov
_______________________________________________
Rust-dev mailing list
Rust-dev at mozilla.org
https://mail.mozilla.org/listinfo/rust-dev
--
Daneel S. Yaitskov
Loading...