Struct nop_json::Reader[][src]

pub struct Reader<T> where
    T: Iterator<Item = u8>, 
{ /* fields omitted */ }

Implementations

impl<T> Reader<T> where
    T: Iterator<Item = u8>, 
[src]

pub fn new(iter: T) -> Reader<T>[src]

Construct new reader object, that can read values from a JSON stream, passing an object that implements Iterator<Item=u8>. This allows to use &str as data source like this:

let source = "\"Data\"";
let mut reader = Reader::new(source.bytes());

To use &[u8] do this:

let source: &[u8] = b"\"Data\"";
let mut reader = Reader::new(source.iter().map(|i| *i));

To use std::io::Read as source, you can convert it to Iterator<Item=u8> like this:

use std::io::Read;
use nop_json::Reader;
let source = std::io::stdin();
let source = source.lock(); // this implements std::io::Read
let mut reader = Reader::new(source.bytes().map(|b| b.unwrap()));

Though, this will panic on i/o error. Another technique is to use read_iter crate.

use read_iter::ReadIter;
use nop_json::Reader;
let mut source = ReadIter::new(std::io::stdin());
let mut reader = Reader::new(&mut source);
// ...
source.take_last_error().unwrap();

To read from file:

use std::fs::File;
use read_iter::ReadIter;
use nop_json::Reader;
let mut source = ReadIter::new(File::open("/tmp/test.json").unwrap());
let mut reader = Reader::new(&mut source);
// ...
source.take_last_error().unwrap();

pub fn unwrap(self) -> T[src]

Destroy this reader, unwrapping the underlying iterator that was passed to constructor when this object created.

pub fn read<U>(&mut self) -> Result<U> where
    U: TryFromJson
[src]

Read one JSON value from the stream.

The value will be converted to target variable type with TryFromJson trait. The conversion is inspired by Javascript values conversion. For example, a JSON string that represents a number (like “123.4e5”) can be read to a numeric variable.

pub fn read_prop<U>(&mut self, prop: &'static str) -> Result<U> where
    U: TryFromJson
[src]

This method is intended for use in cases when you want to implement TryFromJson manually. Use it when you read an object with read_object() or read_object_use_buffer(). It works exactly like read(), but uses provided static string in error message. This string must be the name of the object property that you are reading.

pub fn read_index<U>(&mut self) -> Result<U> where
    U: TryFromJson
[src]

This method is intended for use in cases when you want to implement TryFromJson manually. Use it when you read an array with read_array(). It works exactly like read(), but if error occures, the error message will contain index number in array. The index number is stored internally, and is incremented each time you call read_index() (read_array() resets it).

pub fn format_error(&self, msg: &str) -> Error[src]

Creates std::io::Error from given string. The error message will be prefixed with current path in objects/arrays tree. This path is built by read_prop() and read_index().

pub fn format_error_fmt(&self, args: Arguments<'_>) -> Error[src]

Like format_error(), but receives std::fmt::Arguments object. Create it with format_args!().

pub fn read_bytes(&mut self) -> Result<&[u8]>[src]

Reads a JSON string (numbers, booleans and null will be converted to strings) to internal buffer, which is 128 bytes long. And return a reference to the read bytes. Long strings will be truncated.

pub fn read_blob(&mut self) -> Result<Vec<u8>>[src]

This function allows us to exploit standard JSON containers to pass binary data (BLOBs, binary large objects, or Vec<u8>).

Accodring to JSON standard only valid unicode strings are valid JSON values. But the standard doesn’t specify what kind of unicode it must be: utf-8, utf-16, or other. What is invalid utf-8 can be valid utf-16, and what is invalid utf-16 can be valid something else. If we pack an invalid utf-8 sequence to a JSON container and hand it to some other application, that application will encounter errors when it will try to convert it to a string, and it will say that the JSON was invalid. But that application can not convert the bytes to string, and use the bytes themselves.

The wisdom is how to pack bytes that way. There’s trouble here only with bytes in range 80 - FF. Here is how we can encode our binary object:

  • 00 - 1F - we can encode with the \u00xx encoding - this is the only option.
  • 20 - 7F except " and \ - we can leave intact - they are valid utf-8 JSON, or optionally we can encode them with \u00xx.
  • " and \ - escape with a slash.
  • 80 - FF - leave them as they are. They make our string invalid utf-8, but we cannot encode them with \u00xx. Because \u0080 will expand to 2-byte utf-8 character on JSON-decoding.

Decoding example:

use nop_json::Reader;

let mut reader = Reader::new(b" \"\x80\x81\" ".iter().map(|i| *i));

let data = reader.read_blob().unwrap();
assert_eq!(data, b"\x80\x81");

Encoding (and decoding back) example:

use nop_json::{escape_bytes, Reader};
use std::io::Write;

let data = b"\x80\x81";
let mut json_container = Vec::with_capacity(100);
json_container.push(b'"');
json_container.write_all(escape_bytes(data).as_ref()).unwrap();
json_container.push(b'"');
assert_eq!(json_container, vec![b'"', b'\x80', b'\x81', b'"']);

let mut reader = Reader::new(json_container.iter().map(|i| *i));
let data_back = reader.read_blob().unwrap();
assert_eq!(data_back, data);

pub fn pipe_blob<U>(&mut self, writer: &mut U) -> Result<()> where
    U: Write
[src]

Like read_blob(), but pipes data to the provided writer.

pub fn read_object<F>(&mut self, on_value: F) -> Result<bool> where
    F: FnMut(&mut Self, String) -> Result<()>, 
[src]

This method is intended for use in cases when you want to implement TryFromJson manually. This method reads a JSON object from stream.

First it reads starting { char from the stream. Then it reads a property name. Then for each property name read, it calls given callback function, assuming that from this function you will read the property value using read_prop(). Reading the value with read() will also work, but in case of error, the error message will not contain path to the property where error occured.

Example:


let mut reader = Reader::new(r#" {"x": 10, "y": "the y"} "#.bytes());

let mut x: Option<i32> = None;
let mut y = String::new();

reader.read_object
(	|reader, prop|
	{	match prop.as_ref()
		{	"x" => x = reader.read_prop("x")?,
			"y" => y = reader.read_prop("y")?,
			_ => return Err(reader.format_error_fmt(format_args!("Invalid property: {}", prop)))
		}
		Ok(())
	}
)?;

assert_eq!(x, Some(10));
assert_eq!(y, "the y".to_string());

pub fn read_object_use_buffer<F>(&mut self, on_value: F) -> Result<bool> where
    F: FnMut(&mut Self) -> Result<()>, 
[src]

This method is intended for use in cases when you want to implement TryFromJson manually. This method reads a JSON object from stream.

First it reads starting { char from the stream. Then it reads a property name, and stores it in internal buffer. You can get it with get_key(). The buffer is 128 bytes long, so if the property name is longer, it will be truncated. To avoid this limitation, use read_object(). Then for each property name read, it calls given callback function, assuming that from this function you will read the property value using read_prop(). Reading the value with read() will also work, but in case of error, the error message will not contain path to the property where error occured.

Example:


let mut reader = Reader::new(r#" {"x": 10, "y": "the y"} "#.bytes());

let mut x: Option<i32> = None;
let mut y = String::new();

reader.read_object_use_buffer
(	|reader|
	{	match reader.get_key()
		{	b"x" => x = reader.read_prop("x")?,
			b"y" => y = reader.read_prop("y")?,
			_ => return Err(reader.format_error_fmt(format_args!("Invalid property: {}", String::from_utf8_lossy(reader.get_key()))))
		}
		Ok(())
	}
)?;

assert_eq!(x, Some(10));
assert_eq!(y, "the y".to_string());

pub fn get_key(&self) -> &[u8][src]

pub fn read_array<F>(&mut self, on_value: F) -> Result<bool> where
    F: FnMut(&mut Self) -> Result<()>, 
[src]

This method is intended for use in cases when you want to implement TryFromJson manually. This method reads a JSON array from stream.

First it reads starting [ char from the stream. Then it calls given callback function as many times as needed to read each value till terminating ]. The callback function is assumed to call read_index() to read next array element.

Example:


let mut reader = Reader::new(r#" ["One", "Two", "Three"] "#.bytes());

let mut value: Vec<String> = Vec::new();

reader.read_array
(	|reader|
	{	value.push(reader.read_index()?);
		Ok(())
	}
)?;

assert_eq!(value, vec!["One".to_string(), "Two".to_string(), "Three".to_string()]);

Auto Trait Implementations

impl<T> RefUnwindSafe for Reader<T> where
    T: RefUnwindSafe

impl<T> Send for Reader<T> where
    T: Send

impl<T> Sync for Reader<T> where
    T: Sync

impl<T> Unpin for Reader<T> where
    T: Unpin

impl<T> UnwindSafe for Reader<T> where
    T: UnwindSafe

Blanket Implementations

impl<T> Any for T where
    T: 'static + ?Sized
[src]

impl<T> Borrow<T> for T where
    T: ?Sized
[src]

impl<T> BorrowMut<T> for T where
    T: ?Sized
[src]

impl<T> From<T> for T[src]

impl<T, U> Into<U> for T where
    U: From<T>, 
[src]

impl<T, U> TryFrom<U> for T where
    U: Into<T>, 
[src]

type Error = Infallible

The type returned in the event of a conversion error.

impl<T, U> TryInto<U> for T where
    U: TryFrom<T>, 
[src]

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.