mark new version

This commit is contained in:
Ty Overby 2015-02-21 21:05:30 -08:00
commit 28b5007731
4 changed files with 181 additions and 68 deletions

View File

@ -1,6 +1,6 @@
[package]
name = "bincode"
version = "0.0.9"
version = "0.0.10"
authors = ["Ty Overby <ty@pre-alpha.com>", "Francesco Mazzoli <f@mazzo.li>"]
repository = "https://github.com/TyOverby/bincode"
@ -12,3 +12,7 @@ description = "A binary serialization / deserialization strategy and implementat
[dependencies]
rustc-serialize = "0.2.10"
[dependencies.byteorder]
git = "https://github.com/BurntSushi/byteorder.git"
branch = "newio"

View File

@ -2,13 +2,14 @@
#![crate_type = "rlib"]
#![crate_type = "dylib"]
#![feature(old_io, hash, core)]
#![doc(html_logo_url = "./icon.png")]
#![feature(hash, core, io, unicode, collections)]
extern crate "rustc-serialize" as rustc_serialize;
extern crate byteorder;
extern crate unicode;
use std::old_io::{Buffer, MemWriter};
//use std::old_io::{Buffer, MemWriter};
use rustc_serialize::{Encodable, Decodable};
pub use refbox::RefBox;
@ -16,6 +17,8 @@ pub use writer::{EncoderWriter, EncodingResult, EncodingError};
pub use reader::{DecoderReader, DecodingResult, DecodingError};
use writer::SizeChecker;
use std::io::{Write, BufRead};
mod writer;
mod reader;
mod refbox;
@ -46,30 +49,6 @@ mod refbox;
///! }
///! ```
///!
///! ### Using Into/From Functions
///!
///! ```rust
///! #![allow(unstable)]
///! extern crate bincode;
///! use std::old_io::pipe::PipeStream;
///! use std::old_io::BufferedReader;
///! fn main() {
///! // The pipes that we will be using to send values across.
///! let streams = PipeStream::pair().unwrap();
///! let (mut reader, mut writer) = (BufferedReader::new(streams.reader),
///! streams.writer);
///! // The object that we will send across.
///! let target = Some(5u32);
///! // The max-size of the encoded bytes.
///! let limit = bincode::SizeLimit::Bounded(10);
///!
///! // Do the actual encoding and decoding.
///! bincode::encode_into(&target, &mut writer, limit).ok();
///! let out: Option<u32> = bincode::decode_from(&mut reader, limit).unwrap();
///! assert_eq!(target, out);
///! }
///! ```
///!
/// A limit on the size of bytes to be read or written.
///
@ -100,9 +79,19 @@ pub enum SizeLimit {
/// If the encoding would take more bytes than allowed by `size_limit`,
/// an error is returned.
pub fn encode<T: Encodable>(t: &T, size_limit: SizeLimit) -> EncodingResult<Vec<u8>> {
let mut w = MemWriter::new();
match encode_into(t, &mut w, size_limit) {
Ok(()) => Ok(w.into_inner()),
// Since we are putting values directly into a vector, we can do size
// computation out here and pre-allocate a buffer of *exactly*
// the right size.
let mut w = if let SizeLimit::Bounded(l) = size_limit {
let actual_size = encoded_size_bounded(t, l);
let actual_size = try!(actual_size.ok_or(EncodingError::SizeLimit));
Vec::with_capacity(actual_size as usize)
} else {
vec![]
};
match encode_into(t, &mut w, SizeLimit::Infinite) {
Ok(()) => Ok(w),
Err(e) => Err(e)
}
}
@ -124,7 +113,7 @@ pub fn decode<T: Decodable>(b: &[u8]) -> DecodingResult<T> {
/// If this returns an `EncodingError` (other than SizeLimit), assume that the
/// writer is in an invalid state, as writing could bail out in the middle of
/// encoding.
pub fn encode_into<T: Encodable, W: Writer>(t: &T, w: &mut W, size_limit: SizeLimit) -> EncodingResult<()> {
pub fn encode_into<T: Encodable, W: Write>(t: &T, w: &mut W, size_limit: SizeLimit) -> EncodingResult<()> {
try!(match size_limit {
SizeLimit::Infinite => Ok(()),
SizeLimit::Bounded(x) => {
@ -133,7 +122,7 @@ pub fn encode_into<T: Encodable, W: Writer>(t: &T, w: &mut W, size_limit: SizeLi
}
});
t.encode(&mut writer::EncoderWriter::new(w, size_limit))
t.encode(&mut writer::EncoderWriter::new(w))
}
/// Decoes an object directly from a `Buffer`ed Reader.
@ -145,7 +134,7 @@ pub fn encode_into<T: Encodable, W: Writer>(t: &T, w: &mut W, size_limit: SizeLi
/// If this returns an `DecodingError`, assume that the buffer that you passed
/// in is in an invalid state, as the error could be returned during any point
/// in the reading.
pub fn decode_from<R: Buffer, T: Decodable>(r: &mut R, size_limit: SizeLimit) ->
pub fn decode_from<R: BufRead, T: Decodable>(r: &mut R, size_limit: SizeLimit) ->
DecodingResult<T> {
Decodable::decode(&mut reader::DecoderReader::new(r, size_limit))
}
@ -161,3 +150,13 @@ pub fn encoded_size<T: Encodable>(t: &T) -> u64 {
t.encode(&mut size_checker).ok();
size_checker.written
}
/// Given a maximum size limit, check how large an object would be if it
/// were to be encoded.
///
/// If it can be encoded in `max` or fewer bytes, that number will be returned
/// inside `Some`. If it goes over bounds, then None is returned.
pub fn encoded_size_bounded<T: Encodable>(t: &T, max: u64) -> Option<u64> {
let mut size_checker = SizeChecker::new(max);
t.encode(&mut size_checker).ok().map(|_| size_checker.written)
}

View File

@ -1,10 +1,15 @@
use std::old_io::{Buffer, Reader, IoError};
use std::io::{BufRead, Read};
use std::io::Error as IoError;
use std::io::Result as IoResult;
use std::num::{cast, NumCast};
use std::error::{Error, FromError};
use std::fmt;
use rustc_serialize::Decoder;
use byteorder::{BigEndian, ReadBytesExt};
use unicode;
use super::SizeLimit;
#[derive(Eq, PartialEq, Clone, Debug)]
@ -96,7 +101,7 @@ pub struct DecoderReader<'a, R: 'a> {
read: u64
}
impl<'a, R: Buffer> DecoderReader<'a, R> {
impl<'a, R: BufRead> DecoderReader<'a, R> {
pub fn new(r: &'a mut R, size_limit: SizeLimit) -> DecoderReader<'a, R> {
DecoderReader {
reader: r,
@ -123,7 +128,7 @@ impl <'a, A> DecoderReader<'a, A> {
}
}
impl<'a, R: Buffer> Decoder for DecoderReader<'a, R> {
impl<'a, R: BufRead> Decoder for DecoderReader<'a, R> {
type Error = DecodingError;
fn read_nil(&mut self) -> DecodingResult<()> {
@ -134,15 +139,15 @@ impl<'a, R: Buffer> Decoder for DecoderReader<'a, R> {
}
fn read_u64(&mut self) -> DecodingResult<u64> {
try!(self.read_type::<u64>());
self.reader.read_be_u64().map_err(wrap_io)
self.reader.read_u64::<BigEndian>().map_err(wrap_io)
}
fn read_u32(&mut self) -> DecodingResult<u32> {
try!(self.read_type::<u32>());
self.reader.read_be_u32().map_err(wrap_io)
self.reader.read_u32::<BigEndian>().map_err(wrap_io)
}
fn read_u16(&mut self) -> DecodingResult<u16> {
try!(self.read_type::<u16>());
self.reader.read_be_u16().map_err(wrap_io)
self.reader.read_u16::<BigEndian>().map_err(wrap_io)
}
fn read_u8(&mut self) -> DecodingResult<u8> {
try!(self.read_type::<u8>());
@ -153,15 +158,15 @@ impl<'a, R: Buffer> Decoder for DecoderReader<'a, R> {
}
fn read_i64(&mut self) -> DecodingResult<i64> {
try!(self.read_type::<i64>());
self.reader.read_be_i64().map_err(wrap_io)
self.reader.read_i64::<BigEndian>().map_err(wrap_io)
}
fn read_i32(&mut self) -> DecodingResult<i32> {
try!(self.read_type::<i32>());
self.reader.read_be_i32().map_err(wrap_io)
self.reader.read_i32::<BigEndian>().map_err(wrap_io)
}
fn read_i16(&mut self) -> DecodingResult<i16> {
try!(self.read_type::<i16>());
self.reader.read_be_i16().map_err(wrap_io)
self.reader.read_i16::<BigEndian>().map_err(wrap_io)
}
fn read_i8(&mut self) -> DecodingResult<i8> {
try!(self.read_type::<i8>());
@ -180,23 +185,53 @@ impl<'a, R: Buffer> Decoder for DecoderReader<'a, R> {
}
fn read_f64(&mut self) -> DecodingResult<f64> {
try!(self.read_type::<f64>());
self.reader.read_be_f64().map_err(wrap_io)
self.reader.read_f64::<BigEndian>().map_err(wrap_io)
}
fn read_f32(&mut self) -> DecodingResult<f32> {
try!(self.read_type::<f32>());
self.reader.read_be_f32().map_err(wrap_io)
self.reader.read_f32::<BigEndian>().map_err(wrap_io)
}
fn read_char(&mut self) -> DecodingResult<char> {
let c = try!(self.reader.read_char().map_err(wrap_io));
try!(self.read_bytes(c.len_utf8()));
Ok(c)
use std::str;
let error = DecodingError::InvalidEncoding(InvalidEncoding {
desc: "Invalid char encoding",
detail: None
});
let mut buf = [0];
let _ = try!(self.reader.read(&mut buf[]));
let first_byte = buf[0];
let width = unicode::str::utf8_char_width(first_byte);
if width == 1 { return Ok(first_byte as char) }
if width == 0 { return Err(error)}
let mut buf = [first_byte, 0, 0, 0];
{
let mut start = 1;
while start < width {
match try!(self.reader.read(&mut buf[start .. width])) {
n if n == width - start => break,
n if n < width - start => { start += n; }
_ => return Err(error)
}
}
}
let res = try!(match str::from_utf8(&buf[..width]).ok() {
Some(s) => Ok(s.char_at(0)),
None => Err(error)
});
try!(self.read_bytes(res.len_utf8()));
Ok(res)
}
fn read_str(&mut self) -> DecodingResult<String> {
let len = try!(self.read_usize());
try!(self.read_bytes(len));
let vector = try!(self.reader.read_exact(len));
let vector = try!(read_exact(&mut self.reader, len));
match String::from_utf8(vector) {
Ok(s) => Ok(s),
Err(err) => Err(DecodingError::InvalidEncoding(InvalidEncoding {
@ -307,3 +342,77 @@ impl<'a, R: Buffer> Decoder for DecoderReader<'a, R> {
})
}
}
fn read_at_least<R: Read>(reader: &mut R, min: usize, buf: &mut [u8]) -> IoResult<usize> {
use std::io::ErrorKind;
if min > buf.len() {
return Err(IoError::new(
ErrorKind::InvalidInput, "the buffer is too short", None));
}
let mut read = 0;
while read < min {
let mut zeroes = 0;
loop {
match reader.read(&mut buf[read..]) {
Ok(0) => {
zeroes += 1;
if zeroes >= 1000 {
return Err(IoError::new(ErrorKind::Other,
"no progress was made",
None ));
}
}
Ok(n) => {
read += n;
break;
}
err@Err(_) => return err
}
}
}
Ok(read)
}
unsafe fn slice_vec_capacity<'a, T>(v: &'a mut Vec<T>, start: usize, end: usize) -> &'a mut [T] {
use std::raw::Slice;
use std::ptr::PtrExt;
use std::mem::transmute;
assert!(start <= end);
assert!(end <= v.capacity());
transmute(Slice {
data: v.as_ptr().offset(start as isize),
len: end - start
})
}
fn push_at_least<R: Read>(reader: &mut R, min: usize, len: usize, buf: &mut Vec<u8>) -> IoResult<usize> {
use std::io::ErrorKind;
if min > len {
return Err(IoError::new(ErrorKind::InvalidInput, "the buffer is too short", None));
}
let start_len = buf.len();
buf.reserve(len);
let mut read = 0;
while read < min {
read += {
let s = unsafe { slice_vec_capacity(buf, start_len + read, start_len + len) };
try!(read_at_least(reader, 1, s))
};
unsafe { buf.set_len(start_len + read) };
}
Ok(read)
}
fn read_exact<R: Read>(reader: &mut R, len: usize) -> IoResult<Vec<u8>> {
let mut buf = Vec::with_capacity(len);
match push_at_least(reader, len, len, &mut buf) {
Ok(_) => Ok(buf),
Err(e) => Err(e),
}
}

View File

@ -1,11 +1,11 @@
use std::old_io::{Writer, IoError};
use std::io::Write;
use std::io::Error as IoError;
use std::error::Error;
use std::num::Int;
use std::fmt;
use rustc_serialize::Encoder;
use super::SizeLimit;
use byteorder::{BigEndian, WriteBytesExt};
pub type EncodingResult<T> = Result<T, EncodingError>;
@ -28,7 +28,6 @@ pub enum EncodingError {
/// For most cases, prefer the `encode_into` function.
pub struct EncoderWriter<'a, W: 'a> {
writer: &'a mut W,
_size_limit: SizeLimit
}
pub struct SizeChecker {
@ -65,11 +64,10 @@ impl Error for EncodingError {
}
}
impl <'a, W: Writer> EncoderWriter<'a, W> {
pub fn new(w: &'a mut W, size_limit: SizeLimit) -> EncoderWriter<'a, W> {
impl <'a, W: Write> EncoderWriter<'a, W> {
pub fn new(w: &'a mut W) -> EncoderWriter<'a, W> {
EncoderWriter {
writer: w,
_size_limit: size_limit
}
}
}
@ -97,7 +95,7 @@ impl SizeChecker {
}
}
impl<'a, W: Writer> Encoder for EncoderWriter<'a, W> {
impl<'a, W: Write> Encoder for EncoderWriter<'a, W> {
type Error = EncodingError;
fn emit_nil(&mut self) -> EncodingResult<()> { Ok(()) }
@ -105,13 +103,13 @@ impl<'a, W: Writer> Encoder for EncoderWriter<'a, W> {
self.emit_u64(v as u64)
}
fn emit_u64(&mut self, v: u64) -> EncodingResult<()> {
self.writer.write_be_u64(v).map_err(wrap_io)
self.writer.write_u64::<BigEndian>(v).map_err(wrap_io)
}
fn emit_u32(&mut self, v: u32) -> EncodingResult<()> {
self.writer.write_be_u32(v).map_err(wrap_io)
self.writer.write_u32::<BigEndian>(v).map_err(wrap_io)
}
fn emit_u16(&mut self, v: u16) -> EncodingResult<()> {
self.writer.write_be_u16(v).map_err(wrap_io)
self.writer.write_u16::<BigEndian>(v).map_err(wrap_io)
}
fn emit_u8(&mut self, v: u8) -> EncodingResult<()> {
self.writer.write_u8(v).map_err(wrap_io)
@ -120,13 +118,13 @@ impl<'a, W: Writer> Encoder for EncoderWriter<'a, W> {
self.emit_i64(v as i64)
}
fn emit_i64(&mut self, v: i64) -> EncodingResult<()> {
self.writer.write_be_i64(v).map_err(wrap_io)
self.writer.write_i64::<BigEndian>(v).map_err(wrap_io)
}
fn emit_i32(&mut self, v: i32) -> EncodingResult<()> {
self.writer.write_be_i32(v).map_err(wrap_io)
self.writer.write_i32::<BigEndian>(v).map_err(wrap_io)
}
fn emit_i16(&mut self, v: i16) -> EncodingResult<()> {
self.writer.write_be_i16(v).map_err(wrap_io)
self.writer.write_i16::<BigEndian>(v).map_err(wrap_io)
}
fn emit_i8(&mut self, v: i8) -> EncodingResult<()> {
self.writer.write_i8(v).map_err(wrap_io)
@ -135,17 +133,20 @@ impl<'a, W: Writer> Encoder for EncoderWriter<'a, W> {
self.writer.write_u8(if v {1} else {0}).map_err(wrap_io)
}
fn emit_f64(&mut self, v: f64) -> EncodingResult<()> {
self.writer.write_be_f64(v).map_err(wrap_io)
self.writer.write_f64::<BigEndian>(v).map_err(wrap_io)
}
fn emit_f32(&mut self, v: f32) -> EncodingResult<()> {
self.writer.write_be_f32(v).map_err(wrap_io)
self.writer.write_f32::<BigEndian>(v).map_err(wrap_io)
}
fn emit_char(&mut self, v: char) -> EncodingResult<()> {
self.writer.write_char(v).map_err(wrap_io)
let mut cbuf = [0; 4];
let sz = v.encode_utf8(&mut cbuf[]).unwrap_or(0);
let ptr = &cbuf[..sz];
self.writer.write_all(ptr).map_err(wrap_io)
}
fn emit_str(&mut self, v: &str) -> EncodingResult<()> {
try!(self.emit_usize(v.len()));
self.writer.write_str(v).map_err(wrap_io)
self.writer.write_all(v.as_bytes()).map_err(wrap_io)
}
fn emit_enum<F>(&mut self, __: &str, f: F) -> EncodingResult<()> where
F: FnOnce(&mut EncoderWriter<'a, W>) -> EncodingResult<()> {