mirror of
https://codeberg.org/icewind/bitbuffer.git
synced 2026-06-03 16:44:06 +02:00
remove seperate BitSize traits
This commit is contained in:
parent
4785f80cce
commit
28b1d15bff
8 changed files with 263 additions and 227 deletions
|
|
@ -1,6 +1,6 @@
|
||||||
[package]
|
[package]
|
||||||
name = "bitstream_reader"
|
name = "bitstream_reader"
|
||||||
version = "0.6.9"
|
version = "0.7.0"
|
||||||
authors = ["Robin Appelman <robin@icewind.nl>"]
|
authors = ["Robin Appelman <robin@icewind.nl>"]
|
||||||
edition = "2018"
|
edition = "2018"
|
||||||
description = "Reading bit sequences from a byte slice"
|
description = "Reading bit sequences from a byte slice"
|
||||||
|
|
@ -12,7 +12,7 @@ travis-ci = { repository = "icewind1991/bitstream_reader" }
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
num-traits = "0.2"
|
num-traits = "0.2"
|
||||||
bitstream_reader_derive = { version = "0.6", path = "bitstream_reader_derive" }
|
bitstream_reader_derive = { version = "0.7", path = "bitstream_reader_derive" }
|
||||||
memchr = "2.2"
|
memchr = "2.2"
|
||||||
|
|
||||||
[dev-dependencies]
|
[dev-dependencies]
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
[package]
|
[package]
|
||||||
name = "bitstream_reader_derive"
|
name = "bitstream_reader_derive"
|
||||||
version = "0.6.0"
|
version = "0.7.0"
|
||||||
authors = ["Robin Appelman <robin@icewind.nl>"]
|
authors = ["Robin Appelman <robin@icewind.nl>"]
|
||||||
edition = "2018"
|
edition = "2018"
|
||||||
description = "Reading bit sequences from a byte slice"
|
description = "Reading bit sequences from a byte slice"
|
||||||
|
|
@ -18,4 +18,4 @@ proc-macro2 = "0.4"
|
||||||
syn_util = "0.3"
|
syn_util = "0.3"
|
||||||
|
|
||||||
[dev-dependencies]
|
[dev-dependencies]
|
||||||
bitstream_reader = { version = "0.6", path = ".." }
|
bitstream_reader = { version = "0.7", path = ".." }
|
||||||
|
|
|
||||||
|
|
@ -185,6 +185,12 @@ fn derive_bitread_trait(
|
||||||
let (impl_generics, _, _) = trait_generics.split_for_impl();
|
let (impl_generics, _, _) = trait_generics.split_for_impl();
|
||||||
let span = input.span();
|
let span = input.span();
|
||||||
|
|
||||||
|
let size = size(
|
||||||
|
input.data.clone(),
|
||||||
|
&name,
|
||||||
|
&input.attrs,
|
||||||
|
extra_param.is_some(),
|
||||||
|
);
|
||||||
let parse = parse(input.data, &name, &input.attrs);
|
let parse = parse(input.data, &name, &input.attrs);
|
||||||
|
|
||||||
let endianness_placeholder = endianness.unwrap_or("_E".to_owned());
|
let endianness_placeholder = endianness.unwrap_or("_E".to_owned());
|
||||||
|
|
@ -196,11 +202,30 @@ fn derive_bitread_trait(
|
||||||
|
|
||||||
let endianness_ident = Ident::new(&endianness_placeholder, span);
|
let endianness_ident = Ident::new(&endianness_placeholder, span);
|
||||||
|
|
||||||
|
let size_extra_param = if extra_param.is_some() {
|
||||||
|
Some(quote!(input_size: usize))
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
};
|
||||||
|
|
||||||
|
let size_method_name = Ident::new(
|
||||||
|
if extra_param.is_some() {
|
||||||
|
"bit_size_sized"
|
||||||
|
} else {
|
||||||
|
"bit_size"
|
||||||
|
},
|
||||||
|
Span::call_site(),
|
||||||
|
);
|
||||||
|
|
||||||
let expanded = quote! {
|
let expanded = quote! {
|
||||||
impl #impl_generics #trait_def for #name #ty_generics #where_clause {
|
impl #impl_generics #trait_def for #name #ty_generics #where_clause {
|
||||||
fn read(stream: &mut ::bitstream_reader::BitStream<#endianness_ident>#extra_param) -> ::bitstream_reader::Result<Self> {
|
fn read(stream: &mut ::bitstream_reader::BitStream<#endianness_ident>#extra_param) -> ::bitstream_reader::Result<Self> {
|
||||||
#parse
|
#parse
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn #size_method_name(#size_extra_param) -> Option<usize> {
|
||||||
|
#size
|
||||||
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -336,6 +361,91 @@ fn parse(data: Data, struct_name: &Ident, attrs: &Vec<Attribute>) -> TokenStream
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn size(
|
||||||
|
data: Data,
|
||||||
|
struct_name: &Ident,
|
||||||
|
attrs: &Vec<Attribute>,
|
||||||
|
has_input_size: bool,
|
||||||
|
) -> TokenStream {
|
||||||
|
let span = struct_name.span();
|
||||||
|
|
||||||
|
match data {
|
||||||
|
Data::Struct(DataStruct { fields, .. }) => {
|
||||||
|
let sizes = fields.iter().map(|f| {
|
||||||
|
// Get attributes `#[..]` on each field
|
||||||
|
if is_const_size(&f.attrs, has_input_size) {
|
||||||
|
let size = get_field_size(&f.attrs, f.span());
|
||||||
|
let field_type = &f.ty;
|
||||||
|
let span = f.span();
|
||||||
|
match size {
|
||||||
|
Some(size) => {
|
||||||
|
quote_spanned! { span =>
|
||||||
|
<#field_type as ::bitstream_reader::BitReadSized<::bitstream_reader::LittleEndian>>::bit_size_sized(#size)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
None => {
|
||||||
|
quote_spanned! { span =>
|
||||||
|
<#field_type as ::bitstream_reader::BitRead<::bitstream_reader::LittleEndian>>::bit_size()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
quote_spanned! { span =>
|
||||||
|
None
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
match &fields {
|
||||||
|
Fields::Named(_) => quote_spanned! { span =>
|
||||||
|
Some(0usize)#(.and_then(|sum: usize| #sizes.map(|size: usize| sum + size)))*
|
||||||
|
},
|
||||||
|
Fields::Unnamed(_) => quote_spanned! { span =>
|
||||||
|
Some(0usize)#(.and_then(|sum: usize| #sizes.map(|size: usize| sum + size)))*
|
||||||
|
},
|
||||||
|
Fields::Unit => quote_spanned! {span=>
|
||||||
|
Some(0usize)
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Data::Enum(data) => {
|
||||||
|
let discriminant_bits = get_attribute_value::<u64>(attrs, &["discriminant_bits"])
|
||||||
|
.expect(
|
||||||
|
"'discriminant_bits' attribute is required when deriving `BinRead` for enums",
|
||||||
|
) as usize;
|
||||||
|
|
||||||
|
let is_unit = data.variants.iter().all(|variant| match &variant.fields {
|
||||||
|
Fields::Unit => true,
|
||||||
|
_ => false,
|
||||||
|
});
|
||||||
|
|
||||||
|
if is_unit {
|
||||||
|
quote_spanned! {span=>
|
||||||
|
Some(#discriminant_bits)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
quote_spanned! {span=>
|
||||||
|
None
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_ => unimplemented!(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn is_const_size(attrs: &[Attribute], has_input_size: bool) -> bool {
|
||||||
|
if get_attribute_value::<Lit>(attrs, &["size_bits"]).is_some() {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
get_attribute_value(attrs, &["size"])
|
||||||
|
.map(|size_lit| match size_lit {
|
||||||
|
Lit::Int(_) => true,
|
||||||
|
Lit::Str(size_field) => &size_field.value() == "input_size" && has_input_size,
|
||||||
|
_ => panic!("Unsupported value for size attribute"),
|
||||||
|
})
|
||||||
|
.unwrap_or(true)
|
||||||
|
}
|
||||||
|
|
||||||
fn get_field_size(attrs: &[Attribute], span: Span) -> Option<TokenStream> {
|
fn get_field_size(attrs: &[Attribute], span: Span) -> Option<TokenStream> {
|
||||||
get_attribute_value(attrs, &["size"])
|
get_attribute_value(attrs, &["size"])
|
||||||
.map(|size_lit| match size_lit {
|
.map(|size_lit| match size_lit {
|
||||||
|
|
@ -361,76 +471,6 @@ fn get_field_size(attrs: &[Attribute], span: Span) -> Option<TokenStream> {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
/// See the [crate documentation](index.html) for details
|
|
||||||
#[proc_macro_derive(BitSize, attributes(size))]
|
|
||||||
pub fn derive_bitsize(input: proc_macro::TokenStream) -> proc_macro::TokenStream {
|
|
||||||
derive_bitsize_trait(input, "BitSize".to_owned(), None)
|
|
||||||
}
|
|
||||||
|
|
||||||
/// See the [crate documentation](index.html) for details
|
|
||||||
#[proc_macro_derive(BitSizeSized, attributes(size))]
|
|
||||||
pub fn derive_bitsize_sized(input: proc_macro::TokenStream) -> proc_macro::TokenStream {
|
|
||||||
let extra_param = parse_str::<TokenStream>("input_size: usize").unwrap();
|
|
||||||
derive_bitsize_trait(input, "BitSizeSized".to_owned(), Some(extra_param))
|
|
||||||
}
|
|
||||||
|
|
||||||
fn derive_bitsize_trait(
|
|
||||||
input: proc_macro::TokenStream,
|
|
||||||
trait_name: String,
|
|
||||||
extra_param: Option<TokenStream>,
|
|
||||||
) -> proc_macro::TokenStream {
|
|
||||||
let input: DeriveInput = parse_macro_input!(input as DeriveInput);
|
|
||||||
|
|
||||||
let name = &input.ident;
|
|
||||||
|
|
||||||
let (impl_generics, ty_generics, where_clause) = input.generics.split_for_impl();
|
|
||||||
|
|
||||||
let sum = bit_size_sum(input.data);
|
|
||||||
|
|
||||||
let trait_def_str = format!("::bitstream_reader::{}", trait_name);
|
|
||||||
let trait_def = parse_str::<Path>(&trait_def_str).unwrap();
|
|
||||||
|
|
||||||
let expanded = quote! {
|
|
||||||
impl # impl_generics # trait_def for # name # ty_generics # where_clause {
|
|
||||||
fn bit_size( # extra_param) -> usize {
|
|
||||||
# sum
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
// panic!("{}", TokenStream::to_string(&expanded));
|
|
||||||
|
|
||||||
proc_macro::TokenStream::from(expanded)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Generate an expression to sum up the heap size of each field.
|
|
||||||
fn bit_size_sum(data: Data) -> TokenStream {
|
|
||||||
match data {
|
|
||||||
Data::Struct(DataStruct { fields, .. }) => {
|
|
||||||
let recurse = fields.iter().map(|f| {
|
|
||||||
let span = f.span();
|
|
||||||
let field_type = &f.ty;
|
|
||||||
match get_field_size(&f.attrs, span) {
|
|
||||||
Some(size) => {
|
|
||||||
quote_spanned! {span =>
|
|
||||||
::bitstream_reader::bit_size_of_sized::< # field_type> ( # size)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
None => {
|
|
||||||
quote_spanned! {span =>
|
|
||||||
::bitstream_reader::bit_size_of::< # field_type> ()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
quote! {
|
|
||||||
0 # ( + # recurse) *
|
|
||||||
}
|
|
||||||
}
|
|
||||||
_ => unimplemented!(),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
enum Discriminant {
|
enum Discriminant {
|
||||||
Int(usize),
|
Int(usize),
|
||||||
Default,
|
Default,
|
||||||
|
|
|
||||||
|
|
@ -4,7 +4,7 @@
|
||||||
use bitstream_reader::{
|
use bitstream_reader::{
|
||||||
bit_size_of, bit_size_of_sized, BigEndian, BitBuffer, BitStream, Endianness, LittleEndian,
|
bit_size_of, bit_size_of_sized, BigEndian, BitBuffer, BitStream, Endianness, LittleEndian,
|
||||||
};
|
};
|
||||||
use bitstream_reader_derive::{BitRead, BitReadSized, BitSize, BitSizeSized};
|
use bitstream_reader_derive::{BitRead, BitReadSized};
|
||||||
|
|
||||||
#[derive(BitRead, PartialEq, Debug)]
|
#[derive(BitRead, PartialEq, Debug)]
|
||||||
struct TestStruct {
|
struct TestStruct {
|
||||||
|
|
@ -59,6 +59,7 @@ fn test_read_struct() {
|
||||||
},
|
},
|
||||||
stream.read().unwrap()
|
stream.read().unwrap()
|
||||||
);
|
);
|
||||||
|
assert_eq!(None, bit_size_of::<TestStruct>());
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(BitRead, PartialEq, Debug)]
|
#[derive(BitRead, PartialEq, Debug)]
|
||||||
|
|
@ -87,6 +88,7 @@ fn test_read_bare_enum() {
|
||||||
assert_eq!(TestBareEnum::Foo, stream.read().unwrap());
|
assert_eq!(TestBareEnum::Foo, stream.read().unwrap());
|
||||||
assert_eq!(TestBareEnum::Bar, stream.read().unwrap());
|
assert_eq!(TestBareEnum::Bar, stream.read().unwrap());
|
||||||
assert_eq!(true, stream.read::<TestBareEnum>().is_err());
|
assert_eq!(true, stream.read::<TestBareEnum>().is_err());
|
||||||
|
assert_eq!(Some(2), bit_size_of::<TestBareEnum>());
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(BitRead, PartialEq, Debug)]
|
#[derive(BitRead, PartialEq, Debug)]
|
||||||
|
|
@ -124,6 +126,7 @@ fn test_read_unnamed_field_enum() {
|
||||||
stream.set_pos(4).unwrap();
|
stream.set_pos(4).unwrap();
|
||||||
assert_eq!(TestUnnamedFieldEnum::Bar(true), stream.read().unwrap());
|
assert_eq!(TestUnnamedFieldEnum::Bar(true), stream.read().unwrap());
|
||||||
assert_eq!(7, stream.pos());
|
assert_eq!(7, stream.pos());
|
||||||
|
assert_eq!(None, bit_size_of::<TestUnnamedFieldEnum>());
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(BitReadSized, PartialEq, Debug)]
|
#[derive(BitReadSized, PartialEq, Debug)]
|
||||||
|
|
@ -150,6 +153,7 @@ fn test_read_struct_sized() {
|
||||||
},
|
},
|
||||||
stream.read_sized(3).unwrap()
|
stream.read_sized(3).unwrap()
|
||||||
);
|
);
|
||||||
|
assert_eq!(Some(8 + 2 * 8 + 2), bit_size_of_sized::<TestStructSized>(2));
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(BitReadSized, PartialEq, Debug)]
|
#[derive(BitReadSized, PartialEq, Debug)]
|
||||||
|
|
@ -182,6 +186,7 @@ fn test_read_unnamed_field_enum_sized() {
|
||||||
stream.read_sized(6).unwrap()
|
stream.read_sized(6).unwrap()
|
||||||
);
|
);
|
||||||
assert_eq!(8, stream.pos());
|
assert_eq!(8, stream.pos());
|
||||||
|
assert_eq!(None, bit_size_of_sized::<TestUnnamedFieldEnumSized>(6));
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(BitRead, PartialEq, Debug)]
|
#[derive(BitRead, PartialEq, Debug)]
|
||||||
|
|
@ -216,6 +221,7 @@ fn test_read_struct2() {
|
||||||
},
|
},
|
||||||
stream.read().unwrap()
|
stream.read().unwrap()
|
||||||
);
|
);
|
||||||
|
assert_eq!(None, bit_size_of::<TestStruct2>());
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(BitRead)]
|
#[derive(BitRead)]
|
||||||
|
|
@ -234,6 +240,7 @@ fn test_read_struct3() {
|
||||||
let result: TestStruct3<BigEndian> = stream.read().unwrap();
|
let result: TestStruct3<BigEndian> = stream.read().unwrap();
|
||||||
assert_eq!(5, result.size);
|
assert_eq!(5, result.size);
|
||||||
assert_eq!(5, result.stream.bit_len());
|
assert_eq!(5, result.stream.bit_len());
|
||||||
|
assert_eq!(None, bit_size_of::<TestStruct3<LittleEndian>>());
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(BitRead, PartialEq, Debug)]
|
#[derive(BitRead, PartialEq, Debug)]
|
||||||
|
|
@ -263,6 +270,7 @@ fn test_read_rest_enum() {
|
||||||
assert_eq!(TestEnumRest::Foo, stream.read().unwrap());
|
assert_eq!(TestEnumRest::Foo, stream.read().unwrap());
|
||||||
assert_eq!(TestEnumRest::Bar, stream.read().unwrap());
|
assert_eq!(TestEnumRest::Bar, stream.read().unwrap());
|
||||||
assert_eq!(TestEnumRest::Asd, stream.read().unwrap());
|
assert_eq!(TestEnumRest::Asd, stream.read().unwrap());
|
||||||
|
assert_eq!(Some(2), bit_size_of::<TestEnumRest>());
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(BitRead, PartialEq, Debug)]
|
#[derive(BitRead, PartialEq, Debug)]
|
||||||
|
|
@ -281,7 +289,7 @@ fn test_unnamed_struct() {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(BitRead, BitSize, PartialEq, Debug)]
|
#[derive(BitRead, PartialEq, Debug)]
|
||||||
struct EmptyStruct;
|
struct EmptyStruct;
|
||||||
|
|
||||||
fn test_empty_struct() {
|
fn test_empty_struct() {
|
||||||
|
|
@ -290,10 +298,10 @@ fn test_empty_struct() {
|
||||||
let mut stream = BitStream::from(buffer);
|
let mut stream = BitStream::from(buffer);
|
||||||
assert_eq!(EmptyStruct, stream.read().unwrap());
|
assert_eq!(EmptyStruct, stream.read().unwrap());
|
||||||
assert_eq!(0, stream.pos());
|
assert_eq!(0, stream.pos());
|
||||||
assert_eq!(0, bit_size_of::<EmptyStruct>());
|
assert_eq!(Some(0), bit_size_of::<EmptyStruct>());
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(BitSize)]
|
#[derive(BitRead)]
|
||||||
struct SizeStruct {
|
struct SizeStruct {
|
||||||
foo: u8,
|
foo: u8,
|
||||||
#[size = 6]
|
#[size = 6]
|
||||||
|
|
@ -301,16 +309,16 @@ struct SizeStruct {
|
||||||
bar: bool,
|
bar: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(BitSize)]
|
#[derive(BitRead)]
|
||||||
struct UnnamedSizeStruct(u8, #[size = 6] String, bool);
|
struct UnnamedSizeStruct(u8, #[size = 6] String, bool);
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_bit_size() {
|
fn test_bit_size() {
|
||||||
assert_eq!(bit_size_of::<SizeStruct>(), 8 + 8 * 6 + 1);
|
assert_eq!(bit_size_of::<SizeStruct>(), Some(8 + 8 * 6 + 1));
|
||||||
assert_eq!(bit_size_of::<UnnamedSizeStruct>(), 8 + 8 * 6 + 1);
|
assert_eq!(bit_size_of::<UnnamedSizeStruct>(), Some(8 + 8 * 6 + 1));
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(BitSizeSized)]
|
#[derive(BitReadSized)]
|
||||||
struct SizeStructSized {
|
struct SizeStructSized {
|
||||||
foo: u8,
|
foo: u8,
|
||||||
#[size = "input_size"]
|
#[size = "input_size"]
|
||||||
|
|
@ -320,6 +328,9 @@ struct SizeStructSized {
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_bit_size_sized() {
|
fn test_bit_size_sized() {
|
||||||
assert_eq!(bit_size_of_sized::<SizeStructSized>(6), 8 + 8 * 6 + 1);
|
assert_eq!(bit_size_of_sized::<SizeStructSized>(6), Some(8 + 8 * 6 + 1));
|
||||||
assert_eq!(bit_size_of_sized::<SizeStructSized>(16), 8 + 8 * 16 + 1);
|
assert_eq!(
|
||||||
|
bit_size_of_sized::<SizeStructSized>(16),
|
||||||
|
Some(8 + 8 * 16 + 1)
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -172,6 +172,8 @@ where
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[doc(hidden)]
|
||||||
|
#[inline]
|
||||||
pub unsafe fn read_bool_unchecked(&self, position: usize) -> bool {
|
pub unsafe fn read_bool_unchecked(&self, position: usize) -> bool {
|
||||||
let byte_index = position / 8;
|
let byte_index = position / 8;
|
||||||
let bit_offset = position & 7;
|
let bit_offset = position & 7;
|
||||||
|
|
@ -239,6 +241,7 @@ where
|
||||||
Ok(unsafe { self.read_int_unchecked(position, count) })
|
Ok(unsafe { self.read_int_unchecked(position, count) })
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[doc(hidden)]
|
||||||
#[inline]
|
#[inline]
|
||||||
pub unsafe fn read_int_unchecked<T>(&self, position: usize, count: usize) -> T
|
pub unsafe fn read_int_unchecked<T>(&self, position: usize, count: usize) -> T
|
||||||
where
|
where
|
||||||
|
|
@ -362,6 +365,7 @@ where
|
||||||
Ok(unsafe { self.read_bytes_unchecked(position, byte_count) })
|
Ok(unsafe { self.read_bytes_unchecked(position, byte_count) })
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[doc(hidden)]
|
||||||
#[inline]
|
#[inline]
|
||||||
pub unsafe fn read_bytes_unchecked(&self, position: usize, byte_count: usize) -> Vec<u8> {
|
pub unsafe fn read_bytes_unchecked(&self, position: usize, byte_count: usize) -> Vec<u8> {
|
||||||
let shift = position & 7;
|
let shift = position & 7;
|
||||||
|
|
@ -530,6 +534,8 @@ where
|
||||||
Ok(unsafe { self.read_float_unchecked(position) })
|
Ok(unsafe { self.read_float_unchecked(position) })
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[doc(hidden)]
|
||||||
|
#[inline]
|
||||||
pub unsafe fn read_float_unchecked<T>(&self, position: usize) -> T
|
pub unsafe fn read_float_unchecked<T>(&self, position: usize) -> T
|
||||||
where
|
where
|
||||||
T: Float + UncheckedPrimitiveFloat,
|
T: Float + UncheckedPrimitiveFloat,
|
||||||
|
|
|
||||||
12
src/lib.rs
12
src/lib.rs
|
|
@ -59,12 +59,10 @@ use std::fmt;
|
||||||
use std::fmt::Display;
|
use std::fmt::Display;
|
||||||
pub use std::string::FromUtf8Error;
|
pub use std::string::FromUtf8Error;
|
||||||
|
|
||||||
pub use bitstream_reader_derive::{BitRead, BitReadSized, BitSize, BitSizeSized};
|
pub use bitstream_reader_derive::{BitRead, BitReadSized};
|
||||||
pub use buffer::BitBuffer;
|
pub use buffer::BitBuffer;
|
||||||
pub use endianness::*;
|
pub use endianness::*;
|
||||||
pub use read::{
|
pub use read::{BitRead, BitReadSized, BitSkip, LazyBitRead, LazyBitReadSized};
|
||||||
BitRead, BitReadSized, BitSize, BitSizeSized, BitSkip, LazyBitRead, LazyBitReadSized,
|
|
||||||
};
|
|
||||||
pub use stream::BitStream;
|
pub use stream::BitStream;
|
||||||
|
|
||||||
mod buffer;
|
mod buffer;
|
||||||
|
|
@ -145,12 +143,12 @@ pub type Result<T> = std::result::Result<T, ReadError>;
|
||||||
|
|
||||||
/// Get the number of bits required to read a type from stream
|
/// Get the number of bits required to read a type from stream
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
pub fn bit_size_of<T: BitSize>() -> usize {
|
pub fn bit_size_of<T: BitRead<LittleEndian>>() -> Option<usize> {
|
||||||
T::bit_size()
|
T::bit_size()
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Get the number of bits required to read a type from stream
|
/// Get the number of bits required to read a type from stream
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
pub fn bit_size_of_sized<T: BitSizeSized>(size: usize) -> usize {
|
pub fn bit_size_of_sized<T: BitReadSized<LittleEndian>>(size: usize) -> Option<usize> {
|
||||||
T::bit_size(size)
|
T::bit_size_sized(size)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
214
src/read.rs
214
src/read.rs
|
|
@ -91,12 +91,13 @@ use std::sync::Arc;
|
||||||
pub trait BitRead<E: Endianness>: Sized {
|
pub trait BitRead<E: Endianness>: Sized {
|
||||||
/// Read the type from stream
|
/// Read the type from stream
|
||||||
fn read(stream: &mut BitStream<E>) -> Result<Self>;
|
fn read(stream: &mut BitStream<E>) -> Result<Self>;
|
||||||
}
|
|
||||||
|
|
||||||
/// Trait to get the number of bits needed to read types that can be read from a stream without requiring the size to be configured.
|
/// The number of bits that will be read or None if the number of bits will change depending
|
||||||
pub trait BitSize {
|
/// on the bit stream
|
||||||
/// How many bits are required to read this type
|
#[inline(always)]
|
||||||
fn bit_size() -> usize;
|
fn bit_size() -> Option<usize> {
|
||||||
|
return None;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Trait to allow skipping a type
|
/// Trait to allow skipping a type
|
||||||
|
|
@ -105,14 +106,11 @@ pub trait BitSize {
|
||||||
pub trait BitSkip<E: Endianness>: BitRead<E> {
|
pub trait BitSkip<E: Endianness>: BitRead<E> {
|
||||||
/// Skip the type
|
/// Skip the type
|
||||||
fn skip(stream: &mut BitStream<E>) -> Result<()> {
|
fn skip(stream: &mut BitStream<E>) -> Result<()> {
|
||||||
Self::read(stream).map(|_| ())
|
match Self::bit_size() {
|
||||||
|
Some(size) => stream.skip_bits(size),
|
||||||
|
None => Self::read(stream).map(|_| ()),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<T: BitRead<E> + BitSize, E: Endianness> BitSkip<E> for T {
|
|
||||||
fn skip(stream: &mut BitStream<E>) -> Result<()> {
|
|
||||||
stream.skip_bits(Self::bit_size())
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
macro_rules! impl_read_int {
|
macro_rules! impl_read_int {
|
||||||
|
|
@ -122,12 +120,10 @@ macro_rules! impl_read_int {
|
||||||
fn read(stream: &mut BitStream<E>) -> Result<$type> {
|
fn read(stream: &mut BitStream<E>) -> Result<$type> {
|
||||||
stream.read_int::<$type>(size_of::<$type>() * 8)
|
stream.read_int::<$type>(size_of::<$type>() * 8)
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
impl BitSize for $type {
|
#[inline(always)]
|
||||||
#[inline]
|
fn bit_size() -> Option<usize> {
|
||||||
fn bit_size() -> usize {
|
Some(size_of::<$type>() * 8)
|
||||||
size_of::<$type>() * 8
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
@ -140,6 +136,11 @@ macro_rules! impl_read_int_nonzero {
|
||||||
fn read(stream: &mut BitStream<LittleEndian>) -> Result<Self> {
|
fn read(stream: &mut BitStream<LittleEndian>) -> Result<Self> {
|
||||||
Ok(<$type>::new(stream.read()?))
|
Ok(<$type>::new(stream.read()?))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[inline(always)]
|
||||||
|
fn bit_size() -> Option<usize> {
|
||||||
|
Some(size_of::<$type>() * 8)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl BitRead<BigEndian> for Option<$type> {
|
impl BitRead<BigEndian> for Option<$type> {
|
||||||
|
|
@ -147,12 +148,10 @@ macro_rules! impl_read_int_nonzero {
|
||||||
fn read(stream: &mut BitStream<BigEndian>) -> Result<Self> {
|
fn read(stream: &mut BitStream<BigEndian>) -> Result<Self> {
|
||||||
Ok(<$type>::new(stream.read()?))
|
Ok(<$type>::new(stream.read()?))
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
impl BitSize for $type {
|
#[inline(always)]
|
||||||
#[inline]
|
fn bit_size() -> Option<usize> {
|
||||||
fn bit_size() -> usize {
|
Some(size_of::<$type>() * 8)
|
||||||
size_of::<$type>() * 8
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
@ -180,12 +179,10 @@ impl<E: Endianness> BitRead<E> for f32 {
|
||||||
fn read(stream: &mut BitStream<E>) -> Result<f32> {
|
fn read(stream: &mut BitStream<E>) -> Result<f32> {
|
||||||
stream.read_float::<f32>()
|
stream.read_float::<f32>()
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
impl BitSize for f32 {
|
#[inline(always)]
|
||||||
#[inline]
|
fn bit_size() -> Option<usize> {
|
||||||
fn bit_size() -> usize {
|
Some(32)
|
||||||
32
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -194,12 +191,10 @@ impl<E: Endianness> BitRead<E> for f64 {
|
||||||
fn read(stream: &mut BitStream<E>) -> Result<f64> {
|
fn read(stream: &mut BitStream<E>) -> Result<f64> {
|
||||||
stream.read_float::<f64>()
|
stream.read_float::<f64>()
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
impl BitSize for f64 {
|
#[inline(always)]
|
||||||
#[inline]
|
fn bit_size() -> Option<usize> {
|
||||||
fn bit_size() -> usize {
|
Some(64)
|
||||||
64
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -208,12 +203,10 @@ impl<E: Endianness> BitRead<E> for bool {
|
||||||
fn read(stream: &mut BitStream<E>) -> Result<bool> {
|
fn read(stream: &mut BitStream<E>) -> Result<bool> {
|
||||||
stream.read_bool()
|
stream.read_bool()
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
impl BitSize for bool {
|
#[inline(always)]
|
||||||
#[inline]
|
fn bit_size() -> Option<usize> {
|
||||||
fn bit_size() -> usize {
|
Some(1)
|
||||||
1
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -229,6 +222,11 @@ impl<E: Endianness, T: BitRead<E>> BitRead<E> for Rc<T> {
|
||||||
fn read(stream: &mut BitStream<E>) -> Result<Self> {
|
fn read(stream: &mut BitStream<E>) -> Result<Self> {
|
||||||
Ok(Rc::new(T::read(stream)?))
|
Ok(Rc::new(T::read(stream)?))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[inline(always)]
|
||||||
|
fn bit_size() -> Option<usize> {
|
||||||
|
T::bit_size()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<E: Endianness, T: BitRead<E>> BitRead<E> for Arc<T> {
|
impl<E: Endianness, T: BitRead<E>> BitRead<E> for Arc<T> {
|
||||||
|
|
@ -236,6 +234,11 @@ impl<E: Endianness, T: BitRead<E>> BitRead<E> for Arc<T> {
|
||||||
fn read(stream: &mut BitStream<E>) -> Result<Self> {
|
fn read(stream: &mut BitStream<E>) -> Result<Self> {
|
||||||
Ok(Arc::new(T::read(stream)?))
|
Ok(Arc::new(T::read(stream)?))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[inline(always)]
|
||||||
|
fn bit_size() -> Option<usize> {
|
||||||
|
T::bit_size()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<E: Endianness, T: BitRead<E>> BitRead<E> for Box<T> {
|
impl<E: Endianness, T: BitRead<E>> BitRead<E> for Box<T> {
|
||||||
|
|
@ -243,26 +246,10 @@ impl<E: Endianness, T: BitRead<E>> BitRead<E> for Box<T> {
|
||||||
fn read(stream: &mut BitStream<E>) -> Result<Self> {
|
fn read(stream: &mut BitStream<E>) -> Result<Self> {
|
||||||
Ok(Box::new(T::read(stream)?))
|
Ok(Box::new(T::read(stream)?))
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
impl<T: BitSize> BitSize for Rc<T> {
|
#[inline(always)]
|
||||||
#[inline]
|
fn bit_size() -> Option<usize> {
|
||||||
fn bit_size() -> usize {
|
T::bit_size().and_then(|sum| T::bit_size().map(|size| sum + size))
|
||||||
T::bit_size()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<T: BitSize> BitSize for Arc<T> {
|
|
||||||
#[inline]
|
|
||||||
fn bit_size() -> usize {
|
|
||||||
T::bit_size()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<T: BitSize> BitSize for Box<T> {
|
|
||||||
#[inline]
|
|
||||||
fn bit_size() -> usize {
|
|
||||||
T::bit_size()
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -273,12 +260,10 @@ macro_rules! impl_read_tuple {
|
||||||
fn read(stream: &mut BitStream<E>) -> Result<Self> {
|
fn read(stream: &mut BitStream<E>) -> Result<Self> {
|
||||||
Ok(($(<$type>::read(stream)?),*))
|
Ok(($(<$type>::read(stream)?),*))
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
impl<$($type: BitSize),*> BitSize for ($($type),*) {
|
#[inline(always)]
|
||||||
#[inline]
|
fn bit_size() -> Option<usize> {
|
||||||
fn bit_size() -> usize {
|
Some(0)$(.and_then(|sum| <$type>::bit_size().map(|size| sum + size)))*
|
||||||
$(<$type>::bit_size() + )* 0
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
@ -355,12 +340,13 @@ impl_read_tuple!(T1, T2, T3, T4);
|
||||||
pub trait BitReadSized<E: Endianness>: Sized {
|
pub trait BitReadSized<E: Endianness>: Sized {
|
||||||
/// Read the type from stream
|
/// Read the type from stream
|
||||||
fn read(stream: &mut BitStream<E>, size: usize) -> Result<Self>;
|
fn read(stream: &mut BitStream<E>, size: usize) -> Result<Self>;
|
||||||
}
|
|
||||||
|
|
||||||
/// Trait to get the number of bits needed to read types that can be read from a stream requiring the size to be configured.
|
/// The number of bits that will be read or None if the number of bits will change depending
|
||||||
pub trait BitSizeSized {
|
/// on the bit stream
|
||||||
/// How many bits are required to read this type
|
#[inline(always)]
|
||||||
fn bit_size(size: usize) -> usize;
|
fn bit_size_sized(_size: usize) -> Option<usize> {
|
||||||
|
return None;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
macro_rules! impl_read_int_sized {
|
macro_rules! impl_read_int_sized {
|
||||||
|
|
@ -370,12 +356,10 @@ macro_rules! impl_read_int_sized {
|
||||||
fn read(stream: &mut BitStream<E>, size: usize) -> Result<$type> {
|
fn read(stream: &mut BitStream<E>, size: usize) -> Result<$type> {
|
||||||
stream.read_int::<$type>(size)
|
stream.read_int::<$type>(size)
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
impl BitSizeSized for $type {
|
#[inline(always)]
|
||||||
#[inline]
|
fn bit_size_sized(size: usize) -> Option<usize> {
|
||||||
fn bit_size(size: usize) -> usize {
|
Some(size)
|
||||||
size
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
@ -397,12 +381,10 @@ impl<E: Endianness> BitReadSized<E> for String {
|
||||||
fn read(stream: &mut BitStream<E>, size: usize) -> Result<String> {
|
fn read(stream: &mut BitStream<E>, size: usize) -> Result<String> {
|
||||||
stream.read_string(Some(size))
|
stream.read_string(Some(size))
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
impl BitSizeSized for String {
|
#[inline(always)]
|
||||||
#[inline]
|
fn bit_size_sized(size: usize) -> Option<usize> {
|
||||||
fn bit_size(size: usize) -> usize {
|
Some(8 * size)
|
||||||
8 * size
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -417,13 +399,6 @@ impl<E: Endianness, T: BitRead<E>> BitRead<E> for Option<T> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<T: BitSize> BitSize for Option<T> {
|
|
||||||
#[inline]
|
|
||||||
fn bit_size() -> usize {
|
|
||||||
1 + T::bit_size()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<E: Endianness, T: BitReadSized<E>> BitReadSized<E> for Option<T> {
|
impl<E: Endianness, T: BitReadSized<E>> BitReadSized<E> for Option<T> {
|
||||||
fn read(stream: &mut BitStream<E>, size: usize) -> Result<Self> {
|
fn read(stream: &mut BitStream<E>, size: usize) -> Result<Self> {
|
||||||
if stream.read()? {
|
if stream.read()? {
|
||||||
|
|
@ -434,24 +409,15 @@ impl<E: Endianness, T: BitReadSized<E>> BitReadSized<E> for Option<T> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<T: BitSizeSized> BitSizeSized for Option<T> {
|
|
||||||
#[inline]
|
|
||||||
fn bit_size(size: usize) -> usize {
|
|
||||||
1 + T::bit_size(size)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<E: Endianness> BitReadSized<E> for BitStream<E> {
|
impl<E: Endianness> BitReadSized<E> for BitStream<E> {
|
||||||
#[inline]
|
#[inline]
|
||||||
fn read(stream: &mut BitStream<E>, size: usize) -> Result<Self> {
|
fn read(stream: &mut BitStream<E>, size: usize) -> Result<Self> {
|
||||||
stream.read_bits(size)
|
stream.read_bits(size)
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
impl<E: Endianness> BitSizeSized for BitStream<E> {
|
#[inline(always)]
|
||||||
#[inline]
|
fn bit_size_sized(size: usize) -> Option<usize> {
|
||||||
fn bit_size(size: usize) -> usize {
|
Some(size)
|
||||||
size
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -464,12 +430,10 @@ impl<E: Endianness, T: BitRead<E>> BitReadSized<E> for Vec<T> {
|
||||||
}
|
}
|
||||||
Ok(vec)
|
Ok(vec)
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
impl<T: BitSize> BitSizeSized for Vec<T> {
|
#[inline(always)]
|
||||||
#[inline]
|
fn bit_size_sized(size: usize) -> Option<usize> {
|
||||||
fn bit_size(size: usize) -> usize {
|
T::bit_size().map(|element_size| size * element_size)
|
||||||
size * T::bit_size()
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -492,12 +456,14 @@ impl<E: Endianness, K: BitRead<E> + Eq + Hash, T: BitRead<E>> BitReadSized<E> fo
|
||||||
}
|
}
|
||||||
Ok(map)
|
Ok(map)
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
impl<K: BitSize, T: BitSize> BitSizeSized for HashMap<K, T> {
|
#[inline(always)]
|
||||||
#[inline]
|
fn bit_size_sized(size: usize) -> Option<usize> {
|
||||||
fn bit_size(size: usize) -> usize {
|
if let (Some(key_size), Some(value_size)) = (K::bit_size(), T::bit_size()) {
|
||||||
size * (K::bit_size() + T::bit_size())
|
Some(size * (key_size + value_size))
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -507,12 +473,12 @@ impl<K: BitSize, T: BitSize> BitSizeSized for HashMap<K, T> {
|
||||||
/// Requires [`BitSize`] to be implemented for it's contents so it can grab the correct number of bytes
|
/// Requires [`BitSize`] to be implemented for it's contents so it can grab the correct number of bytes
|
||||||
///
|
///
|
||||||
/// [`BitSize`]: trait.BitSize.html
|
/// [`BitSize`]: trait.BitSize.html
|
||||||
pub struct LazyBitRead<T: BitRead<E> + BitSize, E: Endianness> {
|
pub struct LazyBitRead<T: BitRead<E>, E: Endianness> {
|
||||||
source: BitStream<E>,
|
source: BitStream<E>,
|
||||||
inner_type: PhantomData<T>,
|
inner_type: PhantomData<T>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<T: BitRead<E> + BitSize, E: Endianness> LazyBitRead<T, E> {
|
impl<T: BitRead<E>, E: Endianness> LazyBitRead<T, E> {
|
||||||
#[inline]
|
#[inline]
|
||||||
/// Get the contents of the lazy struct
|
/// Get the contents of the lazy struct
|
||||||
pub fn read(mut self) -> Result<T> {
|
pub fn read(mut self) -> Result<T> {
|
||||||
|
|
@ -520,20 +486,20 @@ impl<T: BitRead<E> + BitSize, E: Endianness> LazyBitRead<T, E> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<T: BitRead<E> + BitSize, E: Endianness> BitRead<E> for LazyBitRead<T, E> {
|
impl<T: BitRead<E>, E: Endianness> BitRead<E> for LazyBitRead<T, E> {
|
||||||
#[inline]
|
#[inline]
|
||||||
fn read(stream: &mut BitStream<E>) -> Result<Self> {
|
fn read(stream: &mut BitStream<E>) -> Result<Self> {
|
||||||
let bit_size = T::bit_size();
|
match T::bit_size() {
|
||||||
Ok(LazyBitRead {
|
Some(bit_size) => Ok(LazyBitRead {
|
||||||
source: stream.read_bits(bit_size)?,
|
source: stream.read_bits(bit_size)?,
|
||||||
inner_type: PhantomData,
|
inner_type: PhantomData,
|
||||||
})
|
}),
|
||||||
|
None => panic!(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<T: BitRead<E> + BitSize, E: Endianness> BitSize for LazyBitRead<T, E> {
|
#[inline(always)]
|
||||||
#[inline]
|
fn bit_size() -> Option<usize> {
|
||||||
fn bit_size() -> usize {
|
|
||||||
T::bit_size()
|
T::bit_size()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -541,16 +507,14 @@ impl<T: BitRead<E> + BitSize, E: Endianness> BitSize for LazyBitRead<T, E> {
|
||||||
#[derive(Clone, Debug)]
|
#[derive(Clone, Debug)]
|
||||||
/// Struct that lazily reads it's contents from the stream
|
/// Struct that lazily reads it's contents from the stream
|
||||||
///
|
///
|
||||||
/// Requires [`BitSizeSized`] to be implemented for it's contents so it can grab the correct number of bytes
|
|
||||||
///
|
|
||||||
/// [`BitReadSized`]: trait.BitReadSized.html
|
/// [`BitReadSized`]: trait.BitReadSized.html
|
||||||
pub struct LazyBitReadSized<T: BitReadSized<E> + BitSizeSized, E: Endianness> {
|
pub struct LazyBitReadSized<T: BitReadSized<E>, E: Endianness> {
|
||||||
source: RefCell<BitStream<E>>,
|
source: RefCell<BitStream<E>>,
|
||||||
size: usize,
|
size: usize,
|
||||||
inner_type: PhantomData<T>,
|
inner_type: PhantomData<T>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<T: BitReadSized<E> + BitSizeSized, E: Endianness> LazyBitReadSized<T, E> {
|
impl<T: BitReadSized<E>, E: Endianness> LazyBitReadSized<T, E> {
|
||||||
#[inline]
|
#[inline]
|
||||||
/// Get the contents of the lazy struct
|
/// Get the contents of the lazy struct
|
||||||
pub fn value(self) -> Result<T> {
|
pub fn value(self) -> Result<T> {
|
||||||
|
|
@ -558,21 +522,21 @@ impl<T: BitReadSized<E> + BitSizeSized, E: Endianness> LazyBitReadSized<T, E> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<T: BitReadSized<E> + BitSizeSized, E: Endianness> BitReadSized<E> for LazyBitReadSized<T, E> {
|
impl<T: BitReadSized<E>, E: Endianness> BitReadSized<E> for LazyBitReadSized<T, E> {
|
||||||
#[inline]
|
#[inline]
|
||||||
fn read(stream: &mut BitStream<E>, size: usize) -> Result<Self> {
|
fn read(stream: &mut BitStream<E>, size: usize) -> Result<Self> {
|
||||||
let bit_size = T::bit_size(size);
|
match T::bit_size_sized(size) {
|
||||||
Ok(LazyBitReadSized {
|
Some(bit_size) => Ok(LazyBitReadSized {
|
||||||
source: RefCell::new(stream.read_bits(bit_size)?),
|
source: RefCell::new(stream.read_bits(bit_size)?),
|
||||||
inner_type: PhantomData,
|
inner_type: PhantomData,
|
||||||
size,
|
size,
|
||||||
})
|
}),
|
||||||
|
None => panic!(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<T: BitReadSized<E> + BitSizeSized, E: Endianness> BitSizeSized for LazyBitReadSized<T, E> {
|
#[inline(always)]
|
||||||
#[inline]
|
fn bit_size_sized(size: usize) -> Option<usize> {
|
||||||
fn bit_size(size: usize) -> usize {
|
T::bit_size_sized(size)
|
||||||
T::bit_size(size)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -138,6 +138,7 @@ where
|
||||||
result
|
result
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[doc(hidden)]
|
||||||
#[inline]
|
#[inline]
|
||||||
pub unsafe fn read_int_unchecked<T>(&mut self, count: usize) -> T
|
pub unsafe fn read_int_unchecked<T>(&mut self, count: usize) -> T
|
||||||
where
|
where
|
||||||
|
|
@ -187,6 +188,8 @@ where
|
||||||
result
|
result
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[doc(hidden)]
|
||||||
|
#[inline]
|
||||||
pub unsafe fn read_float_unchecked<T>(&mut self) -> T
|
pub unsafe fn read_float_unchecked<T>(&mut self) -> T
|
||||||
where
|
where
|
||||||
T: Float + UncheckedPrimitiveFloat,
|
T: Float + UncheckedPrimitiveFloat,
|
||||||
|
|
@ -233,6 +236,8 @@ where
|
||||||
result
|
result
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[doc(hidden)]
|
||||||
|
#[inline]
|
||||||
pub unsafe fn read_bytes_unchecked(&mut self, byte_count: usize) -> Vec<u8> {
|
pub unsafe fn read_bytes_unchecked(&mut self, byte_count: usize) -> Vec<u8> {
|
||||||
let count = byte_count * 8;
|
let count = byte_count * 8;
|
||||||
self.pos += count;
|
self.pos += count;
|
||||||
|
|
@ -585,6 +590,18 @@ where
|
||||||
pub fn read_sized<T: BitReadSized<E>>(&mut self, size: usize) -> Result<T> {
|
pub fn read_sized<T: BitReadSized<E>>(&mut self, size: usize) -> Result<T> {
|
||||||
T::read(self, size)
|
T::read(self, size)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Check if we can read a number of bits from the stream
|
||||||
|
pub fn check_read(&self, count: usize) -> Result<()> {
|
||||||
|
if self.bits_left() < count {
|
||||||
|
Err(ReadError::NotEnoughData {
|
||||||
|
requested: count,
|
||||||
|
bits_left: self.bits_left(),
|
||||||
|
})
|
||||||
|
} else {
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<E: Endianness> Clone for BitStream<E> {
|
impl<E: Endianness> Clone for BitStream<E> {
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue