зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1328221 - Support GASpecificConfig audio channel in rust mp4 parser. r=rillian
MozReview-Commit-ID: IQKxtjatU9J --HG-- extra : rebase_source : d710f6f639415e1ff7d99b39a6ef97dfd65868e3
This commit is contained in:
Родитель
cc5147ace0
Коммит
a455e9f1e7
|
@ -98,6 +98,9 @@ mp4parse_parser* mp4parse_new(mp4parse_io const* io);
|
|||
/// Free an `mp4parse_parser*` allocated by `mp4parse_new()`.
|
||||
void mp4parse_free(mp4parse_parser* parser);
|
||||
|
||||
/// Enable mp4_parser log.
|
||||
void mp4parse_log(bool enable);
|
||||
|
||||
/// Run the `mp4parse_parser*` allocated by `mp4parse_new()` until EOF or error.
|
||||
mp4parse_error mp4parse_read(mp4parse_parser* parser);
|
||||
|
||||
|
|
|
@ -6,13 +6,13 @@ index ff9422c..814c4c6 100644
|
|||
]
|
||||
|
||||
[dependencies]
|
||||
-byteorder = "0.5.0"
|
||||
-byteorder = "1.0.0"
|
||||
-afl = { version = "0.1.1", optional = true }
|
||||
-afl-plugin = { version = "0.1.1", optional = true }
|
||||
-abort_on_panic = { version = "1.0.0", optional = true }
|
||||
-bitreader = { version = "0.1.0" }
|
||||
+byteorder = "0.5.0"
|
||||
+bitreader = { version = "0.1.0" }
|
||||
-bitreader = { version = "0.2.0" }
|
||||
+byteorder = "1.0.0"
|
||||
+bitreader = { version = "0.2.0" }
|
||||
|
||||
[dev-dependencies]
|
||||
test-assembler = "0.1.2"
|
||||
|
@ -34,7 +34,7 @@ index aeeebc65..5c0836a 100644
|
|||
-build = "build.rs"
|
||||
-
|
||||
[dependencies]
|
||||
byteorder = "0.5.0"
|
||||
byteorder = "1.0.0"
|
||||
"mp4parse" = {version = "0.6.0", path = "../mp4parse"}
|
||||
|
||||
-[build-dependencies]
|
||||
|
|
|
@ -19,8 +19,8 @@ exclude = [
|
|||
]
|
||||
|
||||
[dependencies]
|
||||
byteorder = "0.5.0"
|
||||
bitreader = { version = "0.1.0" }
|
||||
byteorder = "1.0.0"
|
||||
bitreader = { version = "0.2.0" }
|
||||
|
||||
[dev-dependencies]
|
||||
test-assembler = "0.1.2"
|
||||
|
|
|
@ -1,10 +1,11 @@
|
|||
// This Source Code Form is subject to the terms of the Mozilla Public
|
||||
// License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
// file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
use std::fmt;
|
||||
|
||||
macro_rules! box_database {
|
||||
($($boxenum:ident $boxtype:expr),*,) => {
|
||||
#[derive(Debug, Clone, Copy, PartialEq)]
|
||||
#[derive(Clone, Copy, PartialEq)]
|
||||
pub enum BoxType {
|
||||
$($boxenum),*,
|
||||
UnknownBox(u32),
|
||||
|
@ -19,6 +20,75 @@ macro_rules! box_database {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Into<u32> for BoxType {
|
||||
fn into(self) -> u32 {
|
||||
use self::BoxType::*;
|
||||
match self {
|
||||
$($boxenum => $boxtype),*,
|
||||
UnknownBox(t) => t,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::Debug for BoxType {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
let fourcc: FourCC = From::from(self.clone());
|
||||
write!(f, "{}", fourcc)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Default, PartialEq)]
|
||||
pub struct FourCC {
|
||||
pub value: String
|
||||
}
|
||||
|
||||
impl From<u32> for FourCC {
|
||||
fn from(number: u32) -> FourCC {
|
||||
let mut box_chars = Vec::new();
|
||||
for x in 0..4 {
|
||||
let c = (number >> x * 8 & 0x000000FF) as u8;
|
||||
box_chars.push(c);
|
||||
}
|
||||
box_chars.reverse();
|
||||
|
||||
let box_string = match String::from_utf8(box_chars) {
|
||||
Ok(t) => t,
|
||||
_ => String::from("null"), // error to retrieve fourcc
|
||||
};
|
||||
|
||||
FourCC {
|
||||
value: box_string
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<BoxType> for FourCC {
|
||||
fn from(t: BoxType) -> FourCC {
|
||||
let box_num: u32 = Into::into(t);
|
||||
From::from(box_num)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> From<&'a str> for FourCC {
|
||||
fn from(v: &'a str) -> FourCC {
|
||||
FourCC {
|
||||
value: v.to_owned()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::Debug for FourCC {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
write!(f, "{}", self.value)
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::Display for FourCC {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
write!(f, "{}", self.value)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -17,7 +17,7 @@ use std::io::Cursor;
|
|||
use std::cmp;
|
||||
|
||||
mod boxes;
|
||||
use boxes::BoxType;
|
||||
use boxes::{BoxType, FourCC};
|
||||
|
||||
// Unit tests.
|
||||
#[cfg(test)]
|
||||
|
@ -106,9 +106,9 @@ struct BoxHeader {
|
|||
/// File type box 'ftyp'.
|
||||
#[derive(Debug)]
|
||||
struct FileTypeBox {
|
||||
major_brand: u32,
|
||||
major_brand: FourCC,
|
||||
minor_version: u32,
|
||||
compatible_brands: Vec<u32>,
|
||||
compatible_brands: Vec<FourCC>,
|
||||
}
|
||||
|
||||
/// Movie header box 'mvhd'.
|
||||
|
@ -196,7 +196,7 @@ struct Sample {
|
|||
// Handler reference box 'hdlr'
|
||||
#[derive(Debug)]
|
||||
struct HandlerBox {
|
||||
handler_type: u32,
|
||||
handler_type: FourCC,
|
||||
}
|
||||
|
||||
// Sample description box 'stsd'
|
||||
|
@ -476,6 +476,15 @@ impl<'a, T: Read> BMFFBox<'a, T> {
|
|||
}
|
||||
}
|
||||
|
||||
impl<'a, T: Read> Drop for BMFFBox<'a, T> {
|
||||
fn drop(&mut self) {
|
||||
if self.content.limit() > 0 {
|
||||
let name: FourCC = From::from(self.head.name);
|
||||
log!("Dropping {} bytes in '{}'", self.content.limit(), name);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Read and parse a box header.
|
||||
///
|
||||
/// Call this first to determine the type of a particular mp4 box
|
||||
|
@ -793,9 +802,10 @@ fn read_mdia<T: Read>(f: &mut BMFFBox<T>, track: &mut Track) -> Result<()> {
|
|||
}
|
||||
BoxType::HandlerBox => {
|
||||
let hdlr = read_hdlr(&mut b)?;
|
||||
match hdlr.handler_type {
|
||||
0x76696465 /* 'vide' */ => track.track_type = TrackType::Video,
|
||||
0x736f756e /* 'soun' */ => track.track_type = TrackType::Audio,
|
||||
|
||||
match hdlr.handler_type.value.as_ref() {
|
||||
"vide" => track.track_type = TrackType::Video,
|
||||
"soun" => track.track_type = TrackType::Audio,
|
||||
_ => (),
|
||||
}
|
||||
log!("{:?}", hdlr);
|
||||
|
@ -874,10 +884,10 @@ fn read_ftyp<T: Read>(src: &mut BMFFBox<T>) -> Result<FileTypeBox> {
|
|||
let brand_count = bytes_left / 4;
|
||||
let mut brands = Vec::new();
|
||||
for _ in 0..brand_count {
|
||||
brands.push(be_u32(src)?);
|
||||
brands.push(From::from(be_u32(src)?));
|
||||
}
|
||||
Ok(FileTypeBox {
|
||||
major_brand: major,
|
||||
major_brand: From::from(major),
|
||||
minor_version: minor,
|
||||
compatible_brands: brands,
|
||||
})
|
||||
|
@ -1276,7 +1286,52 @@ fn read_ds_descriptor(data: &[u8], esds: &mut ES_Descriptor) -> Result<()> {
|
|||
},
|
||||
};
|
||||
|
||||
let channel_counts: u16 = ReadInto::read(bit_reader, 4)?;
|
||||
let mut channel_counts: u16 = ReadInto::read(bit_reader, 4)?;
|
||||
|
||||
// parsing GASpecificConfig
|
||||
bit_reader.skip(1)?; // frameLengthFlag
|
||||
let depend_on_core_order: u8 = ReadInto::read(bit_reader, 1)?;
|
||||
if depend_on_core_order > 0 {
|
||||
bit_reader.skip(14)?; // codeCoderDelay
|
||||
}
|
||||
bit_reader.skip(1)?; // extensionFlag
|
||||
|
||||
// When channel_counts is 0, we need to parse the program_config_element
|
||||
// to calculate the channel counts.
|
||||
if channel_counts == 0 {
|
||||
log!("Parsing program_config_element for channel counts");
|
||||
|
||||
bit_reader.skip(4)?; // element_instance_tag
|
||||
bit_reader.skip(2)?; // object_type
|
||||
bit_reader.skip(4)?; // sampling_frequency_index
|
||||
let num_front_channel: u8 = ReadInto::read(bit_reader, 4)?;
|
||||
let num_side_channel: u8 = ReadInto::read(bit_reader, 4)?;
|
||||
let num_back_channel:u8 = ReadInto::read(bit_reader, 4)?;
|
||||
let num_lfe_channel: u8 = ReadInto::read(bit_reader, 2)?;
|
||||
bit_reader.skip(3)?; // num_assoc_data
|
||||
bit_reader.skip(4)?; // num_valid_cc
|
||||
|
||||
let mono_mixdown_present: bool = ReadInto::read(bit_reader, 1)?;
|
||||
if mono_mixdown_present {
|
||||
bit_reader.skip(4)?; // mono_mixdown_element_number
|
||||
}
|
||||
|
||||
let stereo_mixdown_present: bool = ReadInto::read(bit_reader, 1)?;
|
||||
if stereo_mixdown_present {
|
||||
bit_reader.skip(4)?; // stereo_mixdown_element_number
|
||||
}
|
||||
|
||||
let matrix_mixdown_idx_present: bool = ReadInto::read(bit_reader, 1)?;
|
||||
if matrix_mixdown_idx_present {
|
||||
bit_reader.skip(2)?; // matrix_mixdown_idx
|
||||
bit_reader.skip(1)?; // pseudo_surround_enable
|
||||
}
|
||||
|
||||
channel_counts += read_surround_channel_count(bit_reader, num_front_channel)?;
|
||||
channel_counts += read_surround_channel_count(bit_reader, num_side_channel)?;
|
||||
channel_counts += read_surround_channel_count(bit_reader, num_back_channel)?;
|
||||
channel_counts += read_surround_channel_count(bit_reader, num_lfe_channel)?;
|
||||
}
|
||||
|
||||
esds.audio_object_type = Some(audio_object_type);
|
||||
esds.audio_sample_rate = sample_frequency;
|
||||
|
@ -1285,6 +1340,16 @@ fn read_ds_descriptor(data: &[u8], esds: &mut ES_Descriptor) -> Result<()> {
|
|||
Ok(())
|
||||
}
|
||||
|
||||
fn read_surround_channel_count(bit_reader: &mut BitReader, channels: u8) -> Result<u16> {
|
||||
let mut count = 0;
|
||||
for _ in 0..channels {
|
||||
let is_cpe: bool = ReadInto::read(bit_reader, 1)?;
|
||||
count += if is_cpe { 2 } else { 1 };
|
||||
bit_reader.skip(4)?;
|
||||
}
|
||||
Ok(count)
|
||||
}
|
||||
|
||||
fn read_dc_descriptor(data: &[u8], esds: &mut ES_Descriptor) -> Result<()> {
|
||||
let des = &mut Cursor::new(data);
|
||||
let object_profile = des.read_u8()?;
|
||||
|
@ -1470,7 +1535,7 @@ fn read_hdlr<T: Read>(src: &mut BMFFBox<T>) -> Result<HandlerBox> {
|
|||
// Skip uninteresting fields.
|
||||
skip(src, 4)?;
|
||||
|
||||
let handler_type = be_u32(src)?;
|
||||
let handler_type = FourCC::from(be_u32(src)?);
|
||||
|
||||
// Skip uninteresting fields.
|
||||
skip(src, 12)?;
|
||||
|
|
|
@ -12,7 +12,7 @@ use super::Error;
|
|||
extern crate test_assembler;
|
||||
use self::test_assembler::*;
|
||||
|
||||
use boxes::BoxType;
|
||||
use boxes::{BoxType, FourCC};
|
||||
|
||||
enum BoxSize {
|
||||
Short(u32),
|
||||
|
@ -130,11 +130,11 @@ fn read_ftyp() {
|
|||
assert_eq!(stream.head.name, BoxType::FileTypeBox);
|
||||
assert_eq!(stream.head.size, 24);
|
||||
let parsed = super::read_ftyp(&mut stream).unwrap();
|
||||
assert_eq!(parsed.major_brand, 0x6d703432); // mp42
|
||||
assert_eq!(parsed.major_brand, FourCC::from("mp42")); // mp42
|
||||
assert_eq!(parsed.minor_version, 0);
|
||||
assert_eq!(parsed.compatible_brands.len(), 2);
|
||||
assert_eq!(parsed.compatible_brands[0], 0x69736f6d); // isom
|
||||
assert_eq!(parsed.compatible_brands[1], 0x6d703432); // mp42
|
||||
assert_eq!(parsed.compatible_brands[0], FourCC::from("isom")); // isom
|
||||
assert_eq!(parsed.compatible_brands[1], FourCC::from("mp42")); // mp42
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
@ -172,11 +172,11 @@ fn read_ftyp_case() {
|
|||
assert_eq!(stream.head.name, BoxType::FileTypeBox);
|
||||
assert_eq!(stream.head.size, 24);
|
||||
let parsed = super::read_ftyp(&mut stream).unwrap();
|
||||
assert_eq!(parsed.major_brand, 0x4d503432);
|
||||
assert_eq!(parsed.major_brand, FourCC::from("MP42"));
|
||||
assert_eq!(parsed.minor_version, 0);
|
||||
assert_eq!(parsed.compatible_brands.len(), 2);
|
||||
assert_eq!(parsed.compatible_brands[0], 0x49534f4d); // ISOM
|
||||
assert_eq!(parsed.compatible_brands[1], 0x4d503432); // MP42
|
||||
assert_eq!(parsed.compatible_brands[0], FourCC::from("ISOM")); // ISOM
|
||||
assert_eq!(parsed.compatible_brands[1], FourCC::from("MP42")); // MP42
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
@ -404,7 +404,7 @@ fn read_hdlr() {
|
|||
assert_eq!(stream.head.name, BoxType::HandlerBox);
|
||||
assert_eq!(stream.head.size, 45);
|
||||
let parsed = super::read_hdlr(&mut stream).unwrap();
|
||||
assert_eq!(parsed.handler_type, 0x76696465); // vide
|
||||
assert_eq!(parsed.handler_type, FourCC::from("vide"));
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
@ -422,7 +422,7 @@ fn read_hdlr_short_name() {
|
|||
assert_eq!(stream.head.name, BoxType::HandlerBox);
|
||||
assert_eq!(stream.head.size, 33);
|
||||
let parsed = super::read_hdlr(&mut stream).unwrap();
|
||||
assert_eq!(parsed.handler_type, 0x76696465); // vide
|
||||
assert_eq!(parsed.handler_type, FourCC::from("vide"));
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
@ -439,7 +439,7 @@ fn read_hdlr_zero_length_name() {
|
|||
assert_eq!(stream.head.name, BoxType::HandlerBox);
|
||||
assert_eq!(stream.head.size, 32);
|
||||
let parsed = super::read_hdlr(&mut stream).unwrap();
|
||||
assert_eq!(parsed.handler_type, 0x76696465); // vide
|
||||
assert_eq!(parsed.handler_type, FourCC::from("vide"));
|
||||
}
|
||||
|
||||
fn flac_streaminfo() -> Vec<u8> {
|
||||
|
@ -858,3 +858,29 @@ fn read_qt_wave_atom() {
|
|||
.expect("fail to read qt wave atom");
|
||||
assert_eq!(track.codec_type, super::CodecType::MP3);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn read_esds() {
|
||||
let aac_esds =
|
||||
vec![
|
||||
0x03, 0x24, 0x00, 0x00, 0x00, 0x04, 0x1c, 0x40,
|
||||
0x15, 0x00, 0x12, 0x00, 0x00, 0x01, 0xf4, 0x00,
|
||||
0x00, 0x01, 0xf4, 0x00, 0x05, 0x0d, 0x13, 0x00,
|
||||
0x05, 0x88, 0x05, 0x00, 0x48, 0x21, 0x10, 0x00,
|
||||
0x56, 0xe5, 0x98, 0x06, 0x01, 0x02,
|
||||
];
|
||||
let mut stream = make_box(BoxSize::Auto, b"esds", |s| {
|
||||
s.B32(0) // reserved
|
||||
.append_bytes(aac_esds.as_slice())
|
||||
});
|
||||
let mut iter = super::BoxIter::new(&mut stream);
|
||||
let mut stream = iter.next_box().unwrap().unwrap();
|
||||
|
||||
let es = super::read_esds(&mut stream).unwrap();
|
||||
|
||||
assert_eq!(es.audio_codec, super::CodecType::AAC);
|
||||
assert_eq!(es.audio_object_type, Some(2));
|
||||
assert_eq!(es.audio_sample_rate, Some(24000));
|
||||
assert_eq!(es.audio_channel_count, Some(6));
|
||||
assert_eq!(es.codec_esds, aac_esds);
|
||||
}
|
||||
|
|
|
@ -19,7 +19,7 @@ exclude = [
|
|||
]
|
||||
|
||||
[dependencies]
|
||||
byteorder = "0.5.0"
|
||||
byteorder = "1.0.0"
|
||||
"mp4parse" = {version = "0.6.0", path = "../mp4parse"}
|
||||
|
||||
# Somewhat heavy-handed, but we want at least -Z force-overflow-checks=on.
|
||||
|
|
|
@ -267,6 +267,7 @@ pub unsafe extern fn mp4parse_new(io: *const mp4parse_io) -> *mut mp4parse_parse
|
|||
opus_header: HashMap::new(),
|
||||
pssh_data: Vec::new(),
|
||||
}));
|
||||
|
||||
Box::into_raw(parser)
|
||||
}
|
||||
|
||||
|
@ -277,6 +278,12 @@ pub unsafe extern fn mp4parse_free(parser: *mut mp4parse_parser) {
|
|||
let _ = Box::from_raw(parser);
|
||||
}
|
||||
|
||||
/// Enable mp4_parser log.
|
||||
#[no_mangle]
|
||||
pub unsafe extern fn mp4parse_log(enable: bool) {
|
||||
mp4parse::set_debug_mode(enable);
|
||||
}
|
||||
|
||||
/// Run the `mp4parse_parser*` allocated by `mp4parse_new()` until EOF or error.
|
||||
#[no_mangle]
|
||||
pub unsafe extern fn mp4parse_read(parser: *mut mp4parse_parser) -> mp4parse_error {
|
||||
|
|
|
@ -1 +1 @@
|
|||
{"files":{".cargo-ok":"e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855",".gitignore":"f9b1ca6ae27d1c18215265024629a8960c31379f206d9ed20f64e0b2dcf79805","Cargo.toml":"958f2305ab8afcf59f3eeef619f95e511ee2721654417784bbec5ef135fe608b","LICENSE":"cfc7749b96f63bd31c3c42b5c471bf756814053e847c10f3eb003417bc523d30","README.md":"dc19fd728ea91808d5f4109b9343f6a6bfb931f20a3094f4d5d77f9343b09579","src/lib.rs":"343e09a0e40a7d88e69e346bcc0816260e91abafbc9fe854b3aae16305cb717e","src/tests.rs":"bf0d60d6b70f79eb36a394ba51eae7c36e185778f31ef9bfba12399ec60b6e75"},"package":"b245039eddbd1a051b8bfa5d5b6afaad6d34d172057a15d561e80b50b4978e8d"}
|
||||
{"files":{".cargo-ok":"e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855",".gitignore":"f9b1ca6ae27d1c18215265024629a8960c31379f206d9ed20f64e0b2dcf79805",".travis.yml":"f79c29325421aef57d8191a6a19450b62a431a78a6a5be39f5e8ec259316cdac","Cargo.toml":"672e17bc43e09796c9af69270ab47db16b77da461176ca8692ac211f6b7c09f5","LICENSE":"cfc7749b96f63bd31c3c42b5c471bf756814053e847c10f3eb003417bc523d30","README.md":"979a08488d27db4ea70e4db255ea759d7f4c4c0b65b53e32bd3743117538d20b","src/lib.rs":"62b815c44f50074bc199b6abe9ef2728c3e5dad9539ebe9107b3d818c32c453f","src/tests.rs":"e90f5e1ccbc4c41c42cb3ad0f88aee26b1e08e953b7979a4ddbe0a0826ddbad4"},"package":"8319aa6588c40cce19a135009ec70dc730a34ed9d27bab2409298b948546da7a"}
|
|
@ -0,0 +1,4 @@
|
|||
language: rust
|
||||
rust:
|
||||
- stable
|
||||
- nightly
|
|
@ -1,6 +1,6 @@
|
|||
[package]
|
||||
name = "bitreader"
|
||||
version = "0.1.0"
|
||||
version = "0.2.0"
|
||||
authors = ["Ilkka Rauta <ilkka.rauta@gmail.com>"]
|
||||
|
||||
description = """
|
||||
|
@ -10,6 +10,7 @@ You can read "unusual" numbers of bits from the byte slice, for example 13 bits
|
|||
at once. The reader internally keeps track of position within the buffer.
|
||||
"""
|
||||
|
||||
documentation = "https://docs.rs/bitreader"
|
||||
homepage = "https://github.com/irauta/bitreader"
|
||||
repository = "https://github.com/irauta/bitreader"
|
||||
|
||||
|
|
|
@ -2,6 +2,10 @@
|
|||
|
||||
BitReader is a helper type to extract strings of bits from a slice of bytes.
|
||||
|
||||
[![Published Package](https://img.shields.io/crates/v/bitreader.svg)](https://crates.io/crates/bitreader)
|
||||
[![Documentation](https://docs.rs/bitreader/badge.svg)](https://docs.rs/bitreader)
|
||||
[![Build Status](https://travis-ci.org/irauta/bitreader.svg)](https://travis-ci.org/irauta/bitreader)
|
||||
|
||||
Here is how you read first a single bit, then three bits and finally four bits from a byte buffer:
|
||||
|
||||
use bitreader::BitReader;
|
||||
|
@ -16,4 +20,4 @@ Here is how you read first a single bit, then three bits and finally four bits f
|
|||
|
||||
You can naturally read bits from longer buffer of data than just a single byte.
|
||||
|
||||
As you read bits, the internal cursor of BitReader moves on along the stream of bits. Little endian format is assumed when reading the multi-byte values. BitReader supports reading maximum of 64 bits at a time (with read_u64). Reading signed values directly is not supported at the moment.
|
||||
As you read bits, the internal cursor of BitReader moves on along the stream of bits. Little endian format is assumed when reading the multi-byte values. BitReader supports reading maximum of 64 bits at a time (with read_u64).
|
||||
|
|
|
@ -161,6 +161,15 @@ impl<'a> BitReader<'a> {
|
|||
Ok(value)
|
||||
}
|
||||
|
||||
/// Read a single bit as a boolean value.
|
||||
/// Interprets 1 as true and 0 as false.
|
||||
pub fn read_bool(&mut self) -> Result<bool> {
|
||||
match try!(self.read_value(1, 1)) {
|
||||
0 => Ok(false),
|
||||
_ => Ok(true),
|
||||
}
|
||||
}
|
||||
|
||||
/// Skip arbitrary number of bits. However, you can skip at most to the end of the byte slice.
|
||||
pub fn skip(&mut self, bit_count: u64) -> Result<()> {
|
||||
let end_position = self.position + bit_count;
|
||||
|
@ -283,24 +292,28 @@ impl fmt::Display for BitReaderError {
|
|||
///
|
||||
/// If you can't or want, for some reason, to use BitReader's read methods (`read_u8` etc.) but
|
||||
/// want to rely on type inference instead, you can use the ReadInto trait. The trait is
|
||||
/// implemented for all basic integer types (8/16/32/64 bits, signed/unsigned).
|
||||
/// implemented for all basic integer types (8/16/32/64 bits, signed/unsigned)
|
||||
/// and the boolean type.
|
||||
///
|
||||
/// ```
|
||||
/// use bitreader::{BitReader,ReadInto};
|
||||
///
|
||||
/// let slice_of_u8 = &[0b1100_0000];
|
||||
/// let slice_of_u8 = &[0b1110_0000];
|
||||
/// let mut reader = BitReader::new(slice_of_u8);
|
||||
///
|
||||
/// struct Foo {
|
||||
/// bar: u8
|
||||
/// bar: u8,
|
||||
/// valid: bool,
|
||||
/// }
|
||||
///
|
||||
/// // No type mentioned here, instead the type of bits is inferred from the type of Foo::bar,
|
||||
/// // and consequently the correct "overload" is used.
|
||||
/// let bits = ReadInto::read(&mut reader, 2).unwrap();
|
||||
/// let valid = ReadInto::read(&mut reader, 1).unwrap();
|
||||
///
|
||||
/// let foo = Foo { bar: bits };
|
||||
/// assert_eq!(foo.bar, 3)
|
||||
/// let foo = Foo { bar: bits, valid: valid };
|
||||
/// assert_eq!(foo.bar, 3);
|
||||
/// assert!(foo.valid);
|
||||
/// ```
|
||||
pub trait ReadInto
|
||||
where Self: Sized
|
||||
|
@ -328,3 +341,13 @@ impl_read_into!(i8, read_i8);
|
|||
impl_read_into!(i16, read_i16);
|
||||
impl_read_into!(i32, read_i32);
|
||||
impl_read_into!(i64, read_i64);
|
||||
|
||||
// We can't cast to bool, so this requires a separate method.
|
||||
impl ReadInto for bool {
|
||||
fn read(reader: &mut BitReader, bits: u8) -> Result<Self> {
|
||||
match try!(reader.read_u8(bits)) {
|
||||
0 => Ok(false),
|
||||
_ => Ok(true),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -41,7 +41,7 @@ fn read_buffer() {
|
|||
|
||||
assert_eq!(reader.read_u8(4).unwrap(), 0b1110);
|
||||
assert_eq!(reader.read_u8(3).unwrap(), 0b011);
|
||||
assert_eq!(reader.read_u8(1).unwrap(), 0b1);
|
||||
assert_eq!(reader.read_bool().unwrap(), true);
|
||||
|
||||
// Could also be 8 at this point!
|
||||
assert!(reader.is_aligned(4));
|
||||
|
@ -83,7 +83,7 @@ fn try_all_sizes() {
|
|||
#[test]
|
||||
fn skipping_and_zero_reads() {
|
||||
let bytes = &[
|
||||
0b1011_0101, 0b1110_1010, 0b1010_1100,
|
||||
0b1011_0101, 0b1110_1010, 0b1010_1100, 0b0011_0101,
|
||||
];
|
||||
|
||||
let mut reader = BitReader::new(bytes);
|
||||
|
@ -95,6 +95,10 @@ fn skipping_and_zero_reads() {
|
|||
reader.skip(3).unwrap(); // 0b111
|
||||
assert_eq!(reader.read_u16(10).unwrap(), 0b0101010101);
|
||||
assert_eq!(reader.read_u8(3).unwrap(), 0b100);
|
||||
reader.skip(4).unwrap(); // 0b0011
|
||||
assert_eq!(reader.read_u32(2).unwrap(), 0b01);
|
||||
assert_eq!(reader.read_bool().unwrap(), false);
|
||||
assert_eq!(reader.read_bool().unwrap(), true);
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
@ -138,3 +142,17 @@ fn signed_values() {
|
|||
assert_eq!(reader.read_i16(12).unwrap(), x);
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn boolean_values() {
|
||||
let bytes: Vec<u8> = (0..16).collect();
|
||||
let mut reader = BitReader::new(&bytes);
|
||||
for v in &bytes {
|
||||
assert_eq!(reader.read_bool().unwrap(), false);
|
||||
reader.skip(3).unwrap();
|
||||
assert_eq!(reader.read_bool().unwrap(), v & 0x08 == 8);
|
||||
assert_eq!(reader.read_bool().unwrap(), v & 0x04 == 4);
|
||||
assert_eq!(reader.read_bool().unwrap(), v & 0x02 == 2);
|
||||
assert_eq!(reader.read_bool().unwrap(), v & 0x01 == 1);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1 +1 @@
|
|||
{"files":{".cargo-ok":"e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855",".gitignore":"2879af3c0512f976015d532e2d768f04ff22fdcf8745b69b955b78fda321c3fb",".travis.yml":"81545ce3c6c72111a68434464c3f9fa8df9cbe39759a081fac527628ab21ae0c","COPYING":"01c266bced4a434da0051174d6bee16a4c82cf634e2679b6155d40d75012390f","Cargo.toml":"a7282931b50dff2e463f82baaed95a9d76636bc0fef3e921acd8ca69eab32b83","LICENSE-MIT":"0f96a83840e146e43c0ec96a22ec1f392e0680e6c1226e6f3ba87e0740af850f","Makefile":"a45a128685a2ae7d4fa39d310786674417ee113055ef290a11f88002285865fc","README.md":"fbcc46b6d0a585096737f50922818b59016b69d959b05f1b29863b2af8e4da43","UNLICENSE":"7e12e5df4bae12cb21581ba157ced20e1986a0508dd10d0e8a4ab9a4cf94e85c","benches/bench.rs":"f583692d829c8dfe19b1d5b9e968ccf5c74d6733367ca183edff74041a6afedd","session.vim":"95cb1d7caf0ff7fbe76ec911988d908ddd883381c925ba64b537695bc9f021c4","src/lib.rs":"ef9e7a218fa3a4912c47f6840d32b975940d98277b6c9be85e8d7d045552eb87","src/new.rs":"161c21b7ebb5668c7cc70b46b0eb37709e06bb9c854f2fdfc6ce3d3babcbf3de"},"package":"0fc10e8cc6b2580fda3f36eb6dc5316657f812a3df879a44a66fc9f0fdbc4855"}
|
||||
{"files":{".cargo-ok":"e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855",".gitignore":"2879af3c0512f976015d532e2d768f04ff22fdcf8745b69b955b78fda321c3fb",".travis.yml":"c8243fb884ca390f5a7b8cc45e1c0d5bbbdd7e4e82ada2dc1880b3a904c9ce12","COPYING":"01c266bced4a434da0051174d6bee16a4c82cf634e2679b6155d40d75012390f","Cargo.toml":"b6cd79e1f2a93cd8a5c6e6dd7985c46fc26e442ae5b8ed4a0ff37a4ad4708023","LICENSE-MIT":"0f96a83840e146e43c0ec96a22ec1f392e0680e6c1226e6f3ba87e0740af850f","README.md":"0559514b9d7488e96fb7a2f3c043a62fadf3495a1e10602d109ce79ee67da998","UNLICENSE":"7e12e5df4bae12cb21581ba157ced20e1986a0508dd10d0e8a4ab9a4cf94e85c","benches/bench.rs":"f583692d829c8dfe19b1d5b9e968ccf5c74d6733367ca183edff74041a6afedd","src/lib.rs":"b038b8a84b2b7b2143b2835185b3cbbacaf056fa8a2f03bec84bfd79c913c726","src/new.rs":"161c21b7ebb5668c7cc70b46b0eb37709e06bb9c854f2fdfc6ce3d3babcbf3de"},"package":"c40977b0ee6b9885c9013cd41d9feffdd22deb3bb4dc3a71d901cc7a77de18c8"}
|
|
@ -1,15 +1,15 @@
|
|||
language: rust
|
||||
matrix:
|
||||
include:
|
||||
- rust: "nightly"
|
||||
env: TEST_SUITE=suite_nightly
|
||||
- rust: "beta"
|
||||
env: TEST_SUITE=suite_beta
|
||||
- rust: "stable"
|
||||
env: TEST_SUITE=suite_stable
|
||||
rust:
|
||||
- 1.12.0
|
||||
- stable
|
||||
- beta
|
||||
- nightly
|
||||
script:
|
||||
- cargo build --verbose
|
||||
- cargo doc
|
||||
- cargo test --verbose
|
||||
- if [ "$TEST_SUITE" = "suite_nightly" ]; then
|
||||
- cargo test --verbose --no-default-features --lib
|
||||
- if [ "$TRAVIS_RUST_VERSION" = "nightly" ]; then
|
||||
cargo bench --verbose;
|
||||
cargo bench --verbose --no-default-features;
|
||||
fi
|
||||
|
|
|
@ -1,9 +1,9 @@
|
|||
[package]
|
||||
name = "byteorder"
|
||||
version = "0.5.3" #:version
|
||||
version = "1.0.0" #:version
|
||||
authors = ["Andrew Gallant <jamslam@gmail.com>"]
|
||||
description = "Library for reading/writing numbers in big-endian and little-endian."
|
||||
documentation = "http://burntsushi.net/rustdoc/byteorder/"
|
||||
documentation = "https://docs.rs/byteorder"
|
||||
homepage = "https://github.com/BurntSushi/byteorder"
|
||||
repository = "https://github.com/BurntSushi/byteorder"
|
||||
readme = "README.md"
|
||||
|
@ -12,9 +12,10 @@ license = "Unlicense/MIT"
|
|||
|
||||
[lib]
|
||||
name = "byteorder"
|
||||
bench = false
|
||||
|
||||
[dev-dependencies]
|
||||
quickcheck = "0.2"
|
||||
quickcheck = "0.4"
|
||||
rand = "0.3"
|
||||
|
||||
[features]
|
||||
|
|
|
@ -1,14 +0,0 @@
|
|||
all:
|
||||
echo Nothing to do...
|
||||
|
||||
ctags:
|
||||
ctags --recurse --options=ctags.rust --languages=Rust
|
||||
|
||||
docs:
|
||||
cargo doc
|
||||
in-dir ./target/doc fix-perms
|
||||
rscp ./target/doc/* gopher:~/www/burntsushi.net/rustdoc/
|
||||
|
||||
push:
|
||||
git push origin master
|
||||
git push github master
|
|
@ -1,6 +1,5 @@
|
|||
This crate provides convenience methods for encoding and decoding numbers in
|
||||
either big-endian or little-endian order. This is meant to replace the old
|
||||
methods defined on the standard library `Reader` and `Writer` traits.
|
||||
either big-endian or little-endian order.
|
||||
|
||||
[![Build status](https://api.travis-ci.org/BurntSushi/byteorder.png)](https://travis-ci.org/BurntSushi/byteorder)
|
||||
[![](http://meritbadge.herokuapp.com/byteorder)](https://crates.io/crates/byteorder)
|
||||
|
@ -10,20 +9,18 @@ Dual-licensed under MIT or the [UNLICENSE](http://unlicense.org).
|
|||
|
||||
### Documentation
|
||||
|
||||
[http://burntsushi.net/rustdoc/byteorder/](http://burntsushi.net/rustdoc/byteorder/).
|
||||
|
||||
The documentation includes examples.
|
||||
https://docs.rs/byteorder
|
||||
|
||||
|
||||
### Installation
|
||||
|
||||
This crate works with Cargo and is on
|
||||
[crates.io](https://crates.io/crates/byteorder). The package is regularly
|
||||
updated. Add it to your `Cargo.toml` like so:
|
||||
[crates.io](https://crates.io/crates/byteorder). Add it to your `Cargo.toml`
|
||||
like so:
|
||||
|
||||
```toml
|
||||
[dependencies]
|
||||
byteorder = "0.5"
|
||||
byteorder = "1"
|
||||
```
|
||||
|
||||
If you want to augment existing `Read` and `Write` traits, then import the
|
||||
|
@ -55,5 +52,5 @@ in a `no_std` context, add the following to your `Cargo.toml`:
|
|||
|
||||
```toml
|
||||
[dependencies]
|
||||
byteorder = { version = "0.5", default-features = false }
|
||||
byteorder = { version = "1", default-features = false }
|
||||
```
|
||||
|
|
|
@ -1 +0,0 @@
|
|||
au BufWritePost *.rs silent!make ctags > /dev/null 2>&1
|
|
@ -36,16 +36,14 @@ assert_eq!(wtr, vec![5, 2, 0, 3]);
|
|||
```
|
||||
*/
|
||||
|
||||
#![crate_name = "byteorder"]
|
||||
#![doc(html_root_url = "http://burntsushi.net/rustdoc/byteorder")]
|
||||
|
||||
#![cfg_attr(not(feature = "std"), no_std)]
|
||||
|
||||
#![deny(missing_docs)]
|
||||
#![cfg_attr(not(feature = "std"), no_std)]
|
||||
|
||||
#[cfg(feature = "std")]
|
||||
extern crate core;
|
||||
|
||||
use core::fmt::Debug;
|
||||
use core::hash::Hash;
|
||||
use core::mem::transmute;
|
||||
use core::ptr::copy_nonoverlapping;
|
||||
|
||||
|
@ -118,7 +116,8 @@ fn pack_size(n: u64) -> usize {
|
|||
/// BigEndian::write_i16(&mut buf, -50_000);
|
||||
/// assert_eq!(-50_000, BigEndian::read_i16(&buf));
|
||||
/// ```
|
||||
pub trait ByteOrder {
|
||||
pub trait ByteOrder
|
||||
: Clone + Copy + Debug + Default + Eq + Hash + Ord + PartialEq + PartialOrd {
|
||||
/// Reads an unsigned 16 bit integer from `buf`.
|
||||
///
|
||||
/// Panics when `buf.len() < 2`.
|
||||
|
@ -264,13 +263,27 @@ pub trait ByteOrder {
|
|||
///
|
||||
/// Note that this type has no value constructor. It is used purely at the
|
||||
/// type level.
|
||||
#[allow(missing_copy_implementations)] pub enum BigEndian {}
|
||||
#[derive(Clone, Copy, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
|
||||
pub enum BigEndian {}
|
||||
|
||||
impl Default for BigEndian {
|
||||
fn default() -> BigEndian {
|
||||
unreachable!()
|
||||
}
|
||||
}
|
||||
|
||||
/// Defines little-endian serialization.
|
||||
///
|
||||
/// Note that this type has no value constructor. It is used purely at the
|
||||
/// type level.
|
||||
#[allow(missing_copy_implementations)] pub enum LittleEndian {}
|
||||
#[derive(Clone, Copy, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
|
||||
pub enum LittleEndian {}
|
||||
|
||||
impl Default for LittleEndian {
|
||||
fn default() -> LittleEndian {
|
||||
unreachable!()
|
||||
}
|
||||
}
|
||||
|
||||
/// Defines network byte order serialization.
|
||||
///
|
||||
|
@ -439,13 +452,13 @@ mod test {
|
|||
extern crate quickcheck;
|
||||
extern crate rand;
|
||||
|
||||
use test::rand::thread_rng;
|
||||
use test::quickcheck::{QuickCheck, StdGen, Testable};
|
||||
use self::rand::thread_rng;
|
||||
use self::quickcheck::{QuickCheck, StdGen, Testable};
|
||||
|
||||
const U64_MAX: u64 = ::std::u64::MAX;
|
||||
const I64_MAX: u64 = ::std::i64::MAX as u64;
|
||||
pub const U64_MAX: u64 = ::core::u64::MAX;
|
||||
pub const I64_MAX: u64 = ::core::i64::MAX as u64;
|
||||
|
||||
fn qc_sized<A: Testable>(f: A, size: u64) {
|
||||
pub fn qc_sized<A: Testable>(f: A, size: u64) {
|
||||
QuickCheck::new()
|
||||
.gen(StdGen::new(thread_rng(), size as usize))
|
||||
.tests(1_00)
|
||||
|
@ -497,7 +510,7 @@ mod test {
|
|||
($name:ident, $ty_int:ident, $max:expr,
|
||||
$read:ident, $write:ident) => (
|
||||
mod $name {
|
||||
use std::mem::size_of;
|
||||
use core::mem::size_of;
|
||||
use {BigEndian, ByteOrder, NativeEndian, LittleEndian};
|
||||
use super::qc_sized;
|
||||
|
||||
|
@ -537,14 +550,14 @@ mod test {
|
|||
);
|
||||
}
|
||||
|
||||
qc_byte_order!(prop_u16, u16, ::std::u16::MAX as u64, read_u16, write_u16);
|
||||
qc_byte_order!(prop_i16, i16, ::std::i16::MAX as u64, read_i16, write_i16);
|
||||
qc_byte_order!(prop_u32, u32, ::std::u32::MAX as u64, read_u32, write_u32);
|
||||
qc_byte_order!(prop_i32, i32, ::std::i32::MAX as u64, read_i32, write_i32);
|
||||
qc_byte_order!(prop_u64, u64, ::std::u64::MAX as u64, read_u64, write_u64);
|
||||
qc_byte_order!(prop_i64, i64, ::std::i64::MAX as u64, read_i64, write_i64);
|
||||
qc_byte_order!(prop_f32, f32, ::std::u64::MAX as u64, read_f32, write_f32);
|
||||
qc_byte_order!(prop_f64, f64, ::std::i64::MAX as u64, read_f64, write_f64);
|
||||
qc_byte_order!(prop_u16, u16, ::core::u16::MAX as u64, read_u16, write_u16);
|
||||
qc_byte_order!(prop_i16, i16, ::core::i16::MAX as u64, read_i16, write_i16);
|
||||
qc_byte_order!(prop_u32, u32, ::core::u32::MAX as u64, read_u32, write_u32);
|
||||
qc_byte_order!(prop_i32, i32, ::core::i32::MAX as u64, read_i32, write_i32);
|
||||
qc_byte_order!(prop_u64, u64, ::core::u64::MAX as u64, read_u64, write_u64);
|
||||
qc_byte_order!(prop_i64, i64, ::core::i64::MAX as u64, read_i64, write_i64);
|
||||
qc_byte_order!(prop_f32, f32, ::core::u64::MAX as u64, read_f32, write_f32);
|
||||
qc_byte_order!(prop_f64, f64, ::core::i64::MAX as u64, read_f64, write_f64);
|
||||
|
||||
qc_byte_order!(prop_uint_1, u64, super::U64_MAX, 1, read_uint, write_uint);
|
||||
qc_byte_order!(prop_uint_2, u64, super::U64_MAX, 2, read_uint, write_uint);
|
||||
|
@ -564,128 +577,6 @@ mod test {
|
|||
qc_byte_order!(prop_int_7, i64, super::I64_MAX, 7, read_int, write_int);
|
||||
qc_byte_order!(prop_int_8, i64, super::I64_MAX, 8, read_int, write_int);
|
||||
|
||||
macro_rules! qc_bytes_ext {
|
||||
($name:ident, $ty_int:ident, $max:expr,
|
||||
$bytes:expr, $read:ident, $write:ident) => (
|
||||
mod $name {
|
||||
use std::io::Cursor;
|
||||
use {
|
||||
ReadBytesExt, WriteBytesExt,
|
||||
BigEndian, NativeEndian, LittleEndian,
|
||||
};
|
||||
use super::qc_sized;
|
||||
|
||||
#[test]
|
||||
fn big_endian() {
|
||||
let max = ($max - 1) >> (8 * (8 - $bytes));
|
||||
fn prop(n: $ty_int) -> bool {
|
||||
let mut wtr = vec![];
|
||||
wtr.$write::<BigEndian>(n).unwrap();
|
||||
let mut rdr = Vec::new();
|
||||
rdr.extend(wtr[8 - $bytes..].iter().map(|&x|x));
|
||||
let mut rdr = Cursor::new(rdr);
|
||||
n == rdr.$read::<BigEndian>($bytes).unwrap()
|
||||
}
|
||||
qc_sized(prop as fn($ty_int) -> bool, max);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn little_endian() {
|
||||
let max = ($max - 1) >> (8 * (8 - $bytes));
|
||||
fn prop(n: $ty_int) -> bool {
|
||||
let mut wtr = vec![];
|
||||
wtr.$write::<LittleEndian>(n).unwrap();
|
||||
let mut rdr = Cursor::new(wtr);
|
||||
n == rdr.$read::<LittleEndian>($bytes).unwrap()
|
||||
}
|
||||
qc_sized(prop as fn($ty_int) -> bool, max);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn native_endian() {
|
||||
let max = ($max - 1) >> (8 * (8 - $bytes));
|
||||
fn prop(n: $ty_int) -> bool {
|
||||
let mut wtr = vec![];
|
||||
wtr.$write::<NativeEndian>(n).unwrap();
|
||||
let mut rdr = Cursor::new(wtr);
|
||||
n == rdr.$read::<NativeEndian>($bytes).unwrap()
|
||||
}
|
||||
qc_sized(prop as fn($ty_int) -> bool, max);
|
||||
}
|
||||
}
|
||||
);
|
||||
($name:ident, $ty_int:ident, $max:expr, $read:ident, $write:ident) => (
|
||||
mod $name {
|
||||
use std::io::Cursor;
|
||||
use {
|
||||
ReadBytesExt, WriteBytesExt,
|
||||
BigEndian, NativeEndian, LittleEndian,
|
||||
};
|
||||
use super::qc_sized;
|
||||
|
||||
#[test]
|
||||
fn big_endian() {
|
||||
fn prop(n: $ty_int) -> bool {
|
||||
let mut wtr = vec![];
|
||||
wtr.$write::<BigEndian>(n).unwrap();
|
||||
let mut rdr = Cursor::new(wtr);
|
||||
n == rdr.$read::<BigEndian>().unwrap()
|
||||
}
|
||||
qc_sized(prop as fn($ty_int) -> bool, $max - 1);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn little_endian() {
|
||||
fn prop(n: $ty_int) -> bool {
|
||||
let mut wtr = vec![];
|
||||
wtr.$write::<LittleEndian>(n).unwrap();
|
||||
let mut rdr = Cursor::new(wtr);
|
||||
n == rdr.$read::<LittleEndian>().unwrap()
|
||||
}
|
||||
qc_sized(prop as fn($ty_int) -> bool, $max - 1);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn native_endian() {
|
||||
fn prop(n: $ty_int) -> bool {
|
||||
let mut wtr = vec![];
|
||||
wtr.$write::<NativeEndian>(n).unwrap();
|
||||
let mut rdr = Cursor::new(wtr);
|
||||
n == rdr.$read::<NativeEndian>().unwrap()
|
||||
}
|
||||
qc_sized(prop as fn($ty_int) -> bool, $max - 1);
|
||||
}
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
qc_bytes_ext!(prop_ext_u16, u16, ::std::u16::MAX as u64, read_u16, write_u16);
|
||||
qc_bytes_ext!(prop_ext_i16, i16, ::std::i16::MAX as u64, read_i16, write_i16);
|
||||
qc_bytes_ext!(prop_ext_u32, u32, ::std::u32::MAX as u64, read_u32, write_u32);
|
||||
qc_bytes_ext!(prop_ext_i32, i32, ::std::i32::MAX as u64, read_i32, write_i32);
|
||||
qc_bytes_ext!(prop_ext_u64, u64, ::std::u64::MAX as u64, read_u64, write_u64);
|
||||
qc_bytes_ext!(prop_ext_i64, i64, ::std::i64::MAX as u64, read_i64, write_i64);
|
||||
qc_bytes_ext!(prop_ext_f32, f32, ::std::u64::MAX as u64, read_f32, write_f32);
|
||||
qc_bytes_ext!(prop_ext_f64, f64, ::std::i64::MAX as u64, read_f64, write_f64);
|
||||
|
||||
qc_bytes_ext!(prop_ext_uint_1, u64, super::U64_MAX, 1, read_uint, write_u64);
|
||||
qc_bytes_ext!(prop_ext_uint_2, u64, super::U64_MAX, 2, read_uint, write_u64);
|
||||
qc_bytes_ext!(prop_ext_uint_3, u64, super::U64_MAX, 3, read_uint, write_u64);
|
||||
qc_bytes_ext!(prop_ext_uint_4, u64, super::U64_MAX, 4, read_uint, write_u64);
|
||||
qc_bytes_ext!(prop_ext_uint_5, u64, super::U64_MAX, 5, read_uint, write_u64);
|
||||
qc_bytes_ext!(prop_ext_uint_6, u64, super::U64_MAX, 6, read_uint, write_u64);
|
||||
qc_bytes_ext!(prop_ext_uint_7, u64, super::U64_MAX, 7, read_uint, write_u64);
|
||||
qc_bytes_ext!(prop_ext_uint_8, u64, super::U64_MAX, 8, read_uint, write_u64);
|
||||
|
||||
qc_bytes_ext!(prop_ext_int_1, i64, super::I64_MAX, 1, read_int, write_i64);
|
||||
qc_bytes_ext!(prop_ext_int_2, i64, super::I64_MAX, 2, read_int, write_i64);
|
||||
qc_bytes_ext!(prop_ext_int_3, i64, super::I64_MAX, 3, read_int, write_i64);
|
||||
qc_bytes_ext!(prop_ext_int_4, i64, super::I64_MAX, 4, read_int, write_i64);
|
||||
qc_bytes_ext!(prop_ext_int_5, i64, super::I64_MAX, 5, read_int, write_i64);
|
||||
qc_bytes_ext!(prop_ext_int_6, i64, super::I64_MAX, 6, read_int, write_i64);
|
||||
qc_bytes_ext!(prop_ext_int_7, i64, super::I64_MAX, 7, read_int, write_i64);
|
||||
qc_bytes_ext!(prop_ext_int_8, i64, super::I64_MAX, 8, read_int, write_i64);
|
||||
|
||||
// Test that all of the byte conversion functions panic when given a
|
||||
// buffer that is too small.
|
||||
//
|
||||
|
@ -800,3 +691,130 @@ mod test {
|
|||
assert_eq!(n, 0x0504030201);
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
#[cfg(feature = "std")]
|
||||
mod stdtests {
|
||||
macro_rules! qc_bytes_ext {
|
||||
($name:ident, $ty_int:ident, $max:expr,
|
||||
$bytes:expr, $read:ident, $write:ident) => (
|
||||
mod $name {
|
||||
use std::io::Cursor;
|
||||
use {
|
||||
ReadBytesExt, WriteBytesExt,
|
||||
BigEndian, NativeEndian, LittleEndian,
|
||||
};
|
||||
use test::qc_sized;
|
||||
|
||||
#[test]
|
||||
fn big_endian() {
|
||||
let max = ($max - 1) >> (8 * (8 - $bytes));
|
||||
fn prop(n: $ty_int) -> bool {
|
||||
let mut wtr = vec![];
|
||||
wtr.$write::<BigEndian>(n).unwrap();
|
||||
let mut rdr = Vec::new();
|
||||
rdr.extend(wtr[8 - $bytes..].iter().map(|&x|x));
|
||||
let mut rdr = Cursor::new(rdr);
|
||||
n == rdr.$read::<BigEndian>($bytes).unwrap()
|
||||
}
|
||||
qc_sized(prop as fn($ty_int) -> bool, max);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn little_endian() {
|
||||
let max = ($max - 1) >> (8 * (8 - $bytes));
|
||||
fn prop(n: $ty_int) -> bool {
|
||||
let mut wtr = vec![];
|
||||
wtr.$write::<LittleEndian>(n).unwrap();
|
||||
let mut rdr = Cursor::new(wtr);
|
||||
n == rdr.$read::<LittleEndian>($bytes).unwrap()
|
||||
}
|
||||
qc_sized(prop as fn($ty_int) -> bool, max);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn native_endian() {
|
||||
let max = ($max - 1) >> (8 * (8 - $bytes));
|
||||
fn prop(n: $ty_int) -> bool {
|
||||
let mut wtr = vec![];
|
||||
wtr.$write::<NativeEndian>(n).unwrap();
|
||||
let mut rdr = Cursor::new(wtr);
|
||||
n == rdr.$read::<NativeEndian>($bytes).unwrap()
|
||||
}
|
||||
qc_sized(prop as fn($ty_int) -> bool, max);
|
||||
}
|
||||
}
|
||||
);
|
||||
($name:ident, $ty_int:ident, $max:expr, $read:ident, $write:ident) => (
|
||||
mod $name {
|
||||
use std::io::Cursor;
|
||||
use {
|
||||
ReadBytesExt, WriteBytesExt,
|
||||
BigEndian, NativeEndian, LittleEndian,
|
||||
};
|
||||
use test::qc_sized;
|
||||
|
||||
#[test]
|
||||
fn big_endian() {
|
||||
fn prop(n: $ty_int) -> bool {
|
||||
let mut wtr = vec![];
|
||||
wtr.$write::<BigEndian>(n).unwrap();
|
||||
let mut rdr = Cursor::new(wtr);
|
||||
n == rdr.$read::<BigEndian>().unwrap()
|
||||
}
|
||||
qc_sized(prop as fn($ty_int) -> bool, $max - 1);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn little_endian() {
|
||||
fn prop(n: $ty_int) -> bool {
|
||||
let mut wtr = vec![];
|
||||
wtr.$write::<LittleEndian>(n).unwrap();
|
||||
let mut rdr = Cursor::new(wtr);
|
||||
n == rdr.$read::<LittleEndian>().unwrap()
|
||||
}
|
||||
qc_sized(prop as fn($ty_int) -> bool, $max - 1);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn native_endian() {
|
||||
fn prop(n: $ty_int) -> bool {
|
||||
let mut wtr = vec![];
|
||||
wtr.$write::<NativeEndian>(n).unwrap();
|
||||
let mut rdr = Cursor::new(wtr);
|
||||
n == rdr.$read::<NativeEndian>().unwrap()
|
||||
}
|
||||
qc_sized(prop as fn($ty_int) -> bool, $max - 1);
|
||||
}
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
qc_bytes_ext!(prop_ext_u16, u16, ::std::u16::MAX as u64, read_u16, write_u16);
|
||||
qc_bytes_ext!(prop_ext_i16, i16, ::std::i16::MAX as u64, read_i16, write_i16);
|
||||
qc_bytes_ext!(prop_ext_u32, u32, ::std::u32::MAX as u64, read_u32, write_u32);
|
||||
qc_bytes_ext!(prop_ext_i32, i32, ::std::i32::MAX as u64, read_i32, write_i32);
|
||||
qc_bytes_ext!(prop_ext_u64, u64, ::std::u64::MAX as u64, read_u64, write_u64);
|
||||
qc_bytes_ext!(prop_ext_i64, i64, ::std::i64::MAX as u64, read_i64, write_i64);
|
||||
qc_bytes_ext!(prop_ext_f32, f32, ::std::u64::MAX as u64, read_f32, write_f32);
|
||||
qc_bytes_ext!(prop_ext_f64, f64, ::std::i64::MAX as u64, read_f64, write_f64);
|
||||
|
||||
qc_bytes_ext!(prop_ext_uint_1, u64, ::test::U64_MAX, 1, read_uint, write_u64);
|
||||
qc_bytes_ext!(prop_ext_uint_2, u64, ::test::U64_MAX, 2, read_uint, write_u64);
|
||||
qc_bytes_ext!(prop_ext_uint_3, u64, ::test::U64_MAX, 3, read_uint, write_u64);
|
||||
qc_bytes_ext!(prop_ext_uint_4, u64, ::test::U64_MAX, 4, read_uint, write_u64);
|
||||
qc_bytes_ext!(prop_ext_uint_5, u64, ::test::U64_MAX, 5, read_uint, write_u64);
|
||||
qc_bytes_ext!(prop_ext_uint_6, u64, ::test::U64_MAX, 6, read_uint, write_u64);
|
||||
qc_bytes_ext!(prop_ext_uint_7, u64, ::test::U64_MAX, 7, read_uint, write_u64);
|
||||
qc_bytes_ext!(prop_ext_uint_8, u64, ::test::U64_MAX, 8, read_uint, write_u64);
|
||||
|
||||
qc_bytes_ext!(prop_ext_int_1, i64, ::test::I64_MAX, 1, read_int, write_i64);
|
||||
qc_bytes_ext!(prop_ext_int_2, i64, ::test::I64_MAX, 2, read_int, write_i64);
|
||||
qc_bytes_ext!(prop_ext_int_3, i64, ::test::I64_MAX, 3, read_int, write_i64);
|
||||
qc_bytes_ext!(prop_ext_int_4, i64, ::test::I64_MAX, 4, read_int, write_i64);
|
||||
qc_bytes_ext!(prop_ext_int_5, i64, ::test::I64_MAX, 5, read_int, write_i64);
|
||||
qc_bytes_ext!(prop_ext_int_6, i64, ::test::I64_MAX, 6, read_int, write_i64);
|
||||
qc_bytes_ext!(prop_ext_int_7, i64, ::test::I64_MAX, 7, read_int, write_i64);
|
||||
qc_bytes_ext!(prop_ext_int_8, i64, ::test::I64_MAX, 8, read_int, write_i64);
|
||||
}
|
||||
|
||||
|
|
|
@ -9,12 +9,12 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "bitreader"
|
||||
version = "0.1.0"
|
||||
version = "0.2.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
name = "byteorder"
|
||||
version = "0.5.3"
|
||||
version = "1.0.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
|
@ -50,8 +50,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||
name = "mp4parse"
|
||||
version = "0.6.0"
|
||||
dependencies = [
|
||||
"bitreader 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"byteorder 0.5.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"bitreader 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"byteorder 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -62,7 +62,7 @@ version = "0.1.0"
|
|||
name = "mp4parse_capi"
|
||||
version = "0.6.0"
|
||||
dependencies = [
|
||||
"byteorder 0.5.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"byteorder 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"mp4parse 0.6.0",
|
||||
]
|
||||
|
||||
|
@ -109,8 +109,8 @@ dependencies = [
|
|||
]
|
||||
|
||||
[metadata]
|
||||
"checksum bitreader 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b245039eddbd1a051b8bfa5d5b6afaad6d34d172057a15d561e80b50b4978e8d"
|
||||
"checksum byteorder 0.5.3 (registry+https://github.com/rust-lang/crates.io-index)" = "0fc10e8cc6b2580fda3f36eb6dc5316657f812a3df879a44a66fc9f0fdbc4855"
|
||||
"checksum bitreader 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "8319aa6588c40cce19a135009ec70dc730a34ed9d27bab2409298b948546da7a"
|
||||
"checksum byteorder 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "c40977b0ee6b9885c9013cd41d9feffdd22deb3bb4dc3a71d901cc7a77de18c8"
|
||||
"checksum idna 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "1053236e00ce4f668aeca4a769a09b3bf5a682d802abd6f3cb39374f6b162c11"
|
||||
"checksum libc 0.2.18 (registry+https://github.com/rust-lang/crates.io-index)" = "a51822fc847e7a8101514d1d44e354ba2ffa7d4c194dcab48870740e327cac70"
|
||||
"checksum matches 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "bcc3ad8109fa4b522f9b0cd81440422781f564aaf8c195de6b9d6642177ad0dd"
|
||||
|
|
|
@ -7,12 +7,12 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "bitreader"
|
||||
version = "0.1.0"
|
||||
version = "0.2.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
name = "byteorder"
|
||||
version = "0.5.3"
|
||||
version = "1.0.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
|
@ -48,15 +48,15 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||
name = "mp4parse"
|
||||
version = "0.6.0"
|
||||
dependencies = [
|
||||
"bitreader 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"byteorder 0.5.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"bitreader 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"byteorder 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "mp4parse_capi"
|
||||
version = "0.6.0"
|
||||
dependencies = [
|
||||
"byteorder 0.5.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"byteorder 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"mp4parse 0.6.0",
|
||||
]
|
||||
|
||||
|
@ -96,8 +96,8 @@ dependencies = [
|
|||
]
|
||||
|
||||
[metadata]
|
||||
"checksum bitreader 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b245039eddbd1a051b8bfa5d5b6afaad6d34d172057a15d561e80b50b4978e8d"
|
||||
"checksum byteorder 0.5.3 (registry+https://github.com/rust-lang/crates.io-index)" = "0fc10e8cc6b2580fda3f36eb6dc5316657f812a3df879a44a66fc9f0fdbc4855"
|
||||
"checksum bitreader 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "8319aa6588c40cce19a135009ec70dc730a34ed9d27bab2409298b948546da7a"
|
||||
"checksum byteorder 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "c40977b0ee6b9885c9013cd41d9feffdd22deb3bb4dc3a71d901cc7a77de18c8"
|
||||
"checksum idna 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "1053236e00ce4f668aeca4a769a09b3bf5a682d802abd6f3cb39374f6b162c11"
|
||||
"checksum libc 0.2.18 (registry+https://github.com/rust-lang/crates.io-index)" = "a51822fc847e7a8101514d1d44e354ba2ffa7d4c194dcab48870740e327cac70"
|
||||
"checksum matches 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "bcc3ad8109fa4b522f9b0cd81440422781f564aaf8c195de6b9d6642177ad0dd"
|
||||
|
|
Загрузка…
Ссылка в новой задаче