simple snappy bindings, enabling alloc free code
This commit is contained in:
parent
b88eef5374
commit
75013003f7
@ -65,6 +65,8 @@ pub enum UtilError {
|
|||||||
SimpleString(String),
|
SimpleString(String),
|
||||||
/// Error from a bad input size being given for the needed output.
|
/// Error from a bad input size being given for the needed output.
|
||||||
BadSize,
|
BadSize,
|
||||||
|
/// Error from snappy.
|
||||||
|
Snappy(::snappy::Error),
|
||||||
}
|
}
|
||||||
|
|
||||||
impl fmt::Display for UtilError {
|
impl fmt::Display for UtilError {
|
||||||
@ -82,6 +84,7 @@ impl fmt::Display for UtilError {
|
|||||||
UtilError::Decoder(ref err) => f.write_fmt(format_args!("{}", err)),
|
UtilError::Decoder(ref err) => f.write_fmt(format_args!("{}", err)),
|
||||||
UtilError::SimpleString(ref msg) => f.write_str(&msg),
|
UtilError::SimpleString(ref msg) => f.write_str(&msg),
|
||||||
UtilError::BadSize => f.write_str("Bad input size."),
|
UtilError::BadSize => f.write_str("Bad input size."),
|
||||||
|
UtilError::Snappy(ref err) => f.write_fmt(format_args!("{}", err)),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -179,6 +182,12 @@ impl From<String> for UtilError {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl From<::snappy::Error> for UtilError {
|
||||||
|
fn from(err: ::snappy::Error) -> UtilError {
|
||||||
|
UtilError::Snappy(err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// TODO: uncomment below once https://github.com/rust-lang/rust/issues/27336 sorted.
|
// TODO: uncomment below once https://github.com/rust-lang/rust/issues/27336 sorted.
|
||||||
/*#![feature(concat_idents)]
|
/*#![feature(concat_idents)]
|
||||||
macro_rules! assimilate {
|
macro_rules! assimilate {
|
||||||
|
@ -155,6 +155,7 @@ pub mod keys;
|
|||||||
pub mod table;
|
pub mod table;
|
||||||
pub mod network_settings;
|
pub mod network_settings;
|
||||||
pub mod path;
|
pub mod path;
|
||||||
|
pub mod snappy;
|
||||||
|
|
||||||
pub use common::*;
|
pub use common::*;
|
||||||
pub use misc::*;
|
pub use misc::*;
|
||||||
|
140
util/src/snappy.rs
Normal file
140
util/src/snappy.rs
Normal file
@ -0,0 +1,140 @@
|
|||||||
|
// Copyright 2015, 2016 Ethcore (UK) Ltd.
|
||||||
|
// This file is part of Parity.
|
||||||
|
|
||||||
|
// Parity is free software: you can redistribute it and/or modify
|
||||||
|
// it under the terms of the GNU General Public License as published by
|
||||||
|
// the Free Software Foundation, either version 3 of the License, or
|
||||||
|
// (at your option) any later version.
|
||||||
|
|
||||||
|
// Parity is distributed in the hope that it will be useful,
|
||||||
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
// GNU General Public License for more details.
|
||||||
|
|
||||||
|
// You should have received a copy of the GNU General Public License
|
||||||
|
// along with Parity. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
//! Snappy compression bindings.
|
||||||
|
|
||||||
|
use std::fmt;
|
||||||
|
use libc::{c_char, c_int, size_t};
|
||||||
|
|
||||||
|
const SNAPPY_OK: c_int = 0;
|
||||||
|
const SNAPPY_INVALID_INPUT: c_int = 1;
|
||||||
|
const SNAPPY_BUFFER_TOO_SMALL: c_int = 2;
|
||||||
|
|
||||||
|
#[link(name = "snappy")]
|
||||||
|
extern {
|
||||||
|
fn snappy_compress(
|
||||||
|
input: *const c_char,
|
||||||
|
input_len: size_t,
|
||||||
|
compressed: *mut c_char,
|
||||||
|
compressed_len: *mut size_t
|
||||||
|
) -> c_int;
|
||||||
|
|
||||||
|
fn snappy_max_compressed_length(source_len: size_t) -> size_t;
|
||||||
|
|
||||||
|
fn snappy_uncompress(
|
||||||
|
compressed: *const c_char,
|
||||||
|
compressed_len: size_t,
|
||||||
|
uncompressed: *mut c_char,
|
||||||
|
uncompressed_len: *mut size_t,
|
||||||
|
) -> c_int;
|
||||||
|
|
||||||
|
fn snappy_uncompressed_length(
|
||||||
|
compressed: *const c_char,
|
||||||
|
compressed_len: size_t,
|
||||||
|
result: *mut size_t,
|
||||||
|
) -> c_int;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Errors that can occur during usage of snappy.
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub enum Error {
|
||||||
|
/// An invalid input was supplied. Usually means that you tried to decompress an uncompressed
|
||||||
|
/// buffer.
|
||||||
|
InvalidInput,
|
||||||
|
/// The output buffer supplied was too small. Make sure to provide buffers large enough to hold
|
||||||
|
/// all the output data.
|
||||||
|
BufferTooSmall,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl fmt::Display for Error {
|
||||||
|
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||||
|
match *self {
|
||||||
|
Error::InvalidInput => write!(f, "Snappy error (invalid input)"),
|
||||||
|
Error::BufferTooSmall => write!(f, "Snappy error (buffer too small)"),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Compress a buffer using snappy.
|
||||||
|
pub fn compress(input: &[u8]) -> Vec<u8> {
|
||||||
|
let mut buf_size = unsafe { snappy_max_compressed_length(input.len() as size_t) };
|
||||||
|
let mut output = vec![0; buf_size as usize];
|
||||||
|
|
||||||
|
buf_size = compress_into(input, &mut output).expect("snappy compression failed with large enough buffer.");
|
||||||
|
output.truncate(buf_size);
|
||||||
|
output
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Compress a buffer using snappy, writing the result into
|
||||||
|
/// the given output buffer. Will error if the buffer is too small.
|
||||||
|
/// Otherwise, returns the length of the compressed data.
|
||||||
|
pub fn compress_into(input: &[u8], output: &mut [u8]) -> Result<usize, Error> {
|
||||||
|
let mut len = output.len() as size_t;
|
||||||
|
let status = unsafe {
|
||||||
|
snappy_compress(
|
||||||
|
input.as_ptr() as *const c_char,
|
||||||
|
input.len() as size_t,
|
||||||
|
output.as_mut_ptr() as *mut c_char,
|
||||||
|
&mut len,
|
||||||
|
)
|
||||||
|
};
|
||||||
|
|
||||||
|
match status {
|
||||||
|
SNAPPY_OK => Ok(len as usize),
|
||||||
|
SNAPPY_INVALID_INPUT => Err(Error::InvalidInput), // should never happen, but can't hurt!
|
||||||
|
SNAPPY_BUFFER_TOO_SMALL => Err(Error::BufferTooSmall),
|
||||||
|
_ => panic!("snappy returned unspecified status"),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Decompress a buffer using snappy. Will return an error if the buffer is not snappy-compressed.
|
||||||
|
pub fn decompress(input: &[u8]) -> Result<Vec<u8>, Error> {
|
||||||
|
let mut buf_size: size_t = 0;
|
||||||
|
|
||||||
|
let status = unsafe { snappy_uncompressed_length(input.as_ptr() as *const c_char, input.len() as size_t, &mut buf_size) };
|
||||||
|
if status == SNAPPY_INVALID_INPUT {
|
||||||
|
return Err(Error::InvalidInput);
|
||||||
|
}
|
||||||
|
|
||||||
|
let mut output = vec![0; buf_size];
|
||||||
|
|
||||||
|
buf_size = try!(decompress_into(input, &mut output));
|
||||||
|
output.truncate(buf_size);
|
||||||
|
Ok(output)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Decompress a buffer using snappy, writing the result into
|
||||||
|
/// the given output buffer. Will error if the input buffer is not snappy-compressed
|
||||||
|
/// or the output buffer is too small.
|
||||||
|
/// Otherwise, returns the length of the decompressed data.
|
||||||
|
pub fn decompress_into(input: &[u8], output: &mut [u8]) -> Result<usize, Error> {
|
||||||
|
let mut len = output.len() as size_t;
|
||||||
|
let status = unsafe {
|
||||||
|
snappy_uncompress(
|
||||||
|
input.as_ptr() as *const c_char,
|
||||||
|
input.len() as size_t,
|
||||||
|
output.as_mut_ptr() as *mut c_char,
|
||||||
|
&mut len,
|
||||||
|
)
|
||||||
|
};
|
||||||
|
|
||||||
|
match status {
|
||||||
|
SNAPPY_OK => Ok(len as usize),
|
||||||
|
SNAPPY_INVALID_INPUT => Err(Error::InvalidInput),
|
||||||
|
SNAPPY_BUFFER_TOO_SMALL => Err(Error::BufferTooSmall),
|
||||||
|
_ => panic!("snappy returned unspecified status"),
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user