Skip to content

Commit 8f599c1

Browse files
committed
Don't require alloc feature
Enable use of deku in tightly constrained environments. Signed-off-by: Andrew Jeffery <andrew@codeconstruct.com.au>
1 parent 38a0d53 commit 8f599c1

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

59 files changed

+1002
-352
lines changed

Cargo.toml

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ members = [
2222
[features]
2323
default = ["std", "bits"]
2424
std = ["deku_derive/std", "bitvec?/std", "alloc", "no_std_io/std"]
25-
alloc = ["bitvec?/alloc"]
25+
alloc = ["bitvec?/alloc", "deku_derive/alloc", "no_std_io/alloc" ]
2626
logging = ["deku_derive/logging", "log"]
2727
no-assert-string = ["deku_derive/no-assert-string"]
2828
bits = ["dep:bitvec", "deku_derive/bits", "alloc" ]
@@ -31,7 +31,7 @@ bits = ["dep:bitvec", "deku_derive/bits", "alloc" ]
3131
deku_derive = { version = "^0.19.1", path = "deku-derive", default-features = false}
3232
bitvec = { version = "1.0.1", default-features = false, optional = true }
3333
log = { version = "0.4.22", optional = true }
34-
no_std_io = { version = "0.9.0", default-features = false, features = ["alloc"], package = "no_std_io2" }
34+
no_std_io = { version = "0.9.0", default-features = false, package = "no_std_io2" }
3535
rustversion = "1.0.17"
3636

3737
[dev-dependencies]
@@ -48,6 +48,7 @@ log = { version = "0.4.22" }
4848
[[bench]]
4949
name = "deku"
5050
harness = false
51+
required-features = ["alloc"]
5152

5253
[lints]
5354
workspace = true
@@ -63,13 +64,15 @@ required-features = ["bits"]
6364

6465
[[example]]
6566
name = "deku_input"
67+
required-features = ["std"]
6668

6769
[[example]]
6870
name = "enums_catch_all"
6971
required-features = ["bits"]
7072

7173
[[example]]
7274
name = "enums"
75+
required-features = ["std"]
7376

7477
[[example]]
7578
name = "example"
@@ -85,6 +88,8 @@ required-features = ["bits"]
8588

8689
[[example]]
8790
name = "many"
91+
required-features = ["std"]
8892

8993
[[example]]
9094
name = "read_all"
95+
required-features = ["std"]

deku-derive/Cargo.toml

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,8 @@ rust-version = "1.81"
1313
proc-macro = true
1414

1515
[features]
16-
std = ["proc-macro-crate"]
16+
std = ["proc-macro-crate", "alloc"]
17+
alloc = []
1718
logging = []
1819
no-assert-string = []
1920
bits = []

deku-derive/src/macros/deku_read.rs

Lines changed: 23 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -4,12 +4,16 @@ use darling::ast::{Data, Fields};
44
use darling::ToTokens;
55
use proc_macro2::TokenStream;
66
use quote::quote;
7+
#[cfg(feature = "bits")]
78
use syn::LitStr;
89
use syn::{Ident, LitByteStr};
910

11+
#[cfg(feature = "bits")]
12+
use crate::macros::gen_bit_order_from_str;
13+
1014
use crate::macros::{
11-
assertion_failed, gen_bit_order_from_str, gen_ctx_types_and_arg, gen_field_args,
12-
gen_internal_field_idents, token_contains_string, wrap_default_ctx,
15+
assertion_failed, gen_ctx_types_and_arg, gen_field_args, gen_internal_field_idents,
16+
token_contains_string, wrap_default_ctx,
1317
};
1418
use crate::{from_token, DekuData, DekuDataEnum, DekuDataStruct, FieldData, Id};
1519

@@ -357,16 +361,7 @@ fn emit_enum(input: &DekuData) -> Result<TokenStream, syn::Error> {
357361
if !has_default_match && default_reader.is_none() {
358362
variant_matches.push(quote! {
359363
_ => {
360-
extern crate alloc;
361-
use alloc::borrow::Cow;
362-
use alloc::format;
363-
return Err(::#crate_::DekuError::Parse(
364-
Cow::from(format!(
365-
"Could not match enum variant id = {:?} on enum `{}`",
366-
__deku_variant_id,
367-
#ident_as_string
368-
))
369-
));
364+
return Err(::#crate_::deku_error!(::#crate_::DekuError::Parse, "Could not match enum variant", "ID {:?} not found on {}", __deku_variant_id, #ident_as_string));
370365
}
371366
});
372367
}
@@ -538,10 +533,7 @@ fn emit_magic_read_lit(crate_: &Ident, magic: &LitByteStr) -> TokenStream {
538533
for __deku_byte in __deku_magic {
539534
let __deku_read_byte = u8::from_reader_with_ctx(__deku_reader, ())?;
540535
if *__deku_byte != __deku_read_byte {
541-
extern crate alloc;
542-
use alloc::borrow::Cow;
543-
use alloc::format;
544-
return Err(::#crate_::DekuError::Parse(Cow::from(format!("Missing magic value {:?}", #magic))));
536+
return Err(::#crate_::deku_error!(::#crate_::DekuError::Parse, "Missing magic value", "{:?}", #magic));
545537
}
546538
}
547539
}
@@ -613,19 +605,13 @@ fn emit_padding(bit_size: &TokenStream, bit_order: Option<&LitStr>) -> TokenStre
613605
let order = gen_bit_order_from_str(bit_order).unwrap();
614606
quote! {
615607
{
616-
use core::convert::TryFrom;
617-
// TODO: I hope this consts in most cases?
618608
extern crate alloc;
619-
use alloc::borrow::Cow;
620-
use alloc::format;
609+
610+
use core::convert::TryFrom;
621611
let __deku_pad = usize::try_from(#bit_size).map_err(|e|
622-
::#crate_::DekuError::InvalidParam(Cow::from(format!(
623-
"Invalid padding param \"({})\": cannot convert to usize",
624-
stringify!(#bit_size)
625-
)))
612+
::#crate_::deku_error!(::#crate_::DekuError::InvalidParam, "Invalid padding param, cannot convert ot usize", "{}", stringify!(#bit_size))
626613
)?;
627614

628-
629615
if (__deku_pad % 8) == 0 {
630616
let bytes_read = __deku_pad / 8;
631617
let mut buf = alloc::vec![0; bytes_read];
@@ -640,19 +626,13 @@ fn emit_padding(bit_size: &TokenStream, bit_order: Option<&LitStr>) -> TokenStre
640626
} else {
641627
quote! {
642628
{
643-
use core::convert::TryFrom;
644-
// TODO: I hope this consts in most cases?
645629
extern crate alloc;
646-
use alloc::borrow::Cow;
647-
use alloc::format;
630+
631+
use core::convert::TryFrom;
648632
let __deku_pad = usize::try_from(#bit_size).map_err(|e|
649-
::#crate_::DekuError::InvalidParam(Cow::from(format!(
650-
"Invalid padding param \"({})\": cannot convert to usize",
651-
stringify!(#bit_size)
652-
)))
633+
::#crate_::deku_error!(::#crate_::DekuError::InvalidParam, "Invalid padding param, cannot convert to usize", "{}", stringify!(#bit_size))
653634
)?;
654635

655-
656636
if (__deku_pad % 8) == 0 {
657637
let bytes_read = __deku_pad / 8;
658638
let mut buf = alloc::vec![0; bytes_read];
@@ -674,19 +654,16 @@ fn emit_padding_bytes(bit_size: &TokenStream) -> TokenStream {
674654
quote! {
675655
{
676656
use core::convert::TryFrom;
677-
extern crate alloc;
678-
use alloc::borrow::Cow;
679-
use alloc::format;
680-
let __deku_pad = usize::try_from(#bit_size).map_err(|e|
681-
::#crate_::DekuError::InvalidParam(Cow::from(format!(
682-
"Invalid padding param \"({})\": cannot convert to usize",
683-
stringify!(#bit_size)
684-
)))
657+
let mut __deku_pad = usize::try_from(#bit_size).map_err(|e|
658+
::#crate_::deku_error!(::#crate_::DekuError::InvalidParam, "Invalid padding param, cannot convert to usize", "{}", stringify!(#bit_size))
685659
)?;
686660

687-
688-
let mut buf = alloc::vec![0; __deku_pad];
689-
let _ = __deku_reader.read_bytes(__deku_pad, &mut buf, ::#crate_::ctx::Order::default())?;
661+
while __deku_pad > 0 {
662+
let mut __deku_pad_source = [0u8; 64];
663+
let __deku_pad_chunk = core::cmp::min(__deku_pad_source.len(), __deku_pad);
664+
__deku_reader.read_bytes(__deku_pad_chunk, &mut __deku_pad_source[..__deku_pad_chunk], ::#crate_::ctx::Order::default())?;
665+
__deku_pad -= __deku_pad_chunk;
666+
}
690667
}
691668
}
692669
}
@@ -1092,9 +1069,7 @@ pub fn emit_try_from(
10921069
let mut cursor = ::#crate_::no_std_io::Cursor::new(input);
10931070
let (amt_read, res) = <Self as ::#crate_::DekuContainerRead>::from_reader((&mut cursor, 0))?;
10941071
if (amt_read / 8) != total_len {
1095-
extern crate alloc;
1096-
use alloc::borrow::Cow;
1097-
return Err(::#crate_::DekuError::Parse(Cow::from("Too much data")));
1072+
return Err(::#crate_::deku_error!(::#crate_::DekuError::Parse, "Too much data"));
10981073
}
10991074
Ok(res)
11001075
}

deku-derive/src/macros/deku_write.rs

Lines changed: 21 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -3,11 +3,15 @@ use std::convert::TryFrom;
33
use darling::ast::{Data, Fields};
44
use proc_macro2::TokenStream;
55
use quote::quote;
6+
#[cfg(feature = "bits")]
67
use syn::LitStr;
78

9+
#[cfg(feature = "bits")]
10+
use crate::macros::gen_bit_order_from_str;
11+
812
use crate::macros::{
9-
assertion_failed, gen_bit_order_from_str, gen_ctx_types_and_arg, gen_field_args,
10-
gen_internal_field_ident, gen_struct_destruction, token_contains_string, wrap_default_ctx,
13+
assertion_failed, gen_ctx_types_and_arg, gen_field_args, gen_internal_field_ident,
14+
gen_struct_destruction, token_contains_string, wrap_default_ctx,
1115
};
1216
use crate::{from_token, DekuData, DekuDataEnum, DekuDataStruct, FieldData, Id};
1317

@@ -109,6 +113,7 @@ fn emit_struct(input: &DekuData) -> Result<TokenStream, syn::Error> {
109113
}
110114
});
111115

116+
#[cfg(feature = "alloc")]
112117
tokens.extend(quote! {
113118
const _: () = {
114119
extern crate alloc;
@@ -124,7 +129,9 @@ fn emit_struct(input: &DekuData) -> Result<TokenStream, syn::Error> {
124129
}
125130
}
126131
};
132+
});
127133

134+
tokens.extend(quote! {
128135
#[automatically_derived]
129136
impl #imp ::#crate_::DekuContainerWrite for #ident #wher {}
130137
});
@@ -364,6 +371,7 @@ fn emit_enum(input: &DekuData) -> Result<TokenStream, syn::Error> {
364371
}
365372
});
366373

374+
#[cfg(feature = "alloc")]
367375
tokens.extend(quote! {
368376
const _: () = {
369377
extern crate alloc;
@@ -541,14 +549,8 @@ fn emit_padding(bit_size: &TokenStream, bit_order: Option<&LitStr>) -> TokenStre
541549
quote! {
542550
{
543551
use core::convert::TryFrom;
544-
extern crate alloc;
545-
use alloc::borrow::Cow;
546-
use alloc::format;
547552
let __deku_pad = usize::try_from(#bit_size).map_err(|e|
548-
::#crate_::DekuError::InvalidParam(Cow::from(format!(
549-
"Invalid padding param \"({})\": cannot convert to usize",
550-
stringify!(#bit_size)
551-
)))
553+
::#crate_::deku_error!(::#crate_::DekuError::InvalidParam, "Invalid padding param, cannot convert to usize", "{}", stringify!(#bit_size))
552554
)?;
553555
__deku_writer.write_bits_order(::#crate_::bitvec::bitvec![u8, ::#crate_::bitvec::Msb0; 0; __deku_pad].as_bitslice(), #order)?;
554556
}
@@ -557,14 +559,8 @@ fn emit_padding(bit_size: &TokenStream, bit_order: Option<&LitStr>) -> TokenStre
557559
quote! {
558560
{
559561
use core::convert::TryFrom;
560-
extern crate alloc;
561-
use alloc::borrow::Cow;
562-
use alloc::format;
563562
let __deku_pad = usize::try_from(#bit_size).map_err(|e|
564-
::#crate_::DekuError::InvalidParam(Cow::from(format!(
565-
"Invalid padding param \"({})\": cannot convert to usize",
566-
stringify!(#bit_size)
567-
)))
563+
::#crate_::deku_error!(::#crate_::DekuError::InvalidParam, "Invalid padding param, cannot convert to usize", "{}", stringify!(#bit_size))
568564
)?;
569565
__deku_writer.write_bits(::#crate_::bitvec::bitvec![u8, ::#crate_::bitvec::Msb0; 0; __deku_pad].as_bitslice())?;
570566
}
@@ -579,16 +575,16 @@ fn emit_padding_bytes(bit_size: &TokenStream) -> TokenStream {
579575
quote! {
580576
{
581577
use core::convert::TryFrom;
582-
extern crate alloc;
583-
use alloc::borrow::Cow;
584-
use alloc::format;
585-
let __deku_pad = usize::try_from(#bit_size).map_err(|e|
586-
::#crate_::DekuError::InvalidParam(Cow::from(format!(
587-
"Invalid padding param \"({})\": cannot convert to usize",
588-
stringify!(#bit_size)
589-
)))
578+
let mut __deku_pad = usize::try_from(#bit_size).map_err(|e|
579+
::#crate_::deku_error!(::#crate_::DekuError::InvalidParam, "Invalid padding param, cannot convert to usize", "{}", stringify!(#bit_size))
590580
)?;
591-
__deku_writer.write_bytes(&vec![0; __deku_pad])?;
581+
582+
let __deku_pad_source = [0u8; 64];
583+
while __deku_pad > 0 {
584+
let __deku_pad_chunk = core::cmp::min(__deku_pad_source.len(), __deku_pad);
585+
__deku_writer.write_bytes(&__deku_pad_source[..__deku_pad_chunk])?;
586+
__deku_pad -= __deku_pad_chunk;
587+
}
592588
}
593589
}
594590
}

deku-derive/src/macros/mod.rs

Lines changed: 4 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,9 @@ use syn::parse::Parser;
44
use syn::punctuated::Punctuated;
55
use syn::spanned::Spanned;
66
use syn::token::Comma;
7-
use syn::{Lifetime, LitStr};
7+
use syn::Lifetime;
8+
#[cfg(feature = "bits")]
9+
use syn::LitStr;
810

911
use crate::Num;
1012

@@ -424,15 +426,7 @@ fn assertion_failed(
424426
#[cfg(not(feature = "no-assert-string"))]
425427
{
426428
quote! {
427-
extern crate alloc;
428-
use alloc::borrow::Cow;
429-
use alloc::format;
430-
return Err(::#crate_::DekuError::Assertion(Cow::from(format!(
431-
"{}.{} field failed assertion: {}",
432-
#ident,
433-
#field_ident_str,
434-
#stringify,
435-
))));
429+
return Err(::#crate_::deku_error!(::#crate_::DekuError::Assertion, "Field failed assertion", "{}.{}: {}", #ident, #field_ident_str, #stringify));
436430
}
437431
}
438432
}

examples/custom_reader_and_writer.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,9 @@ use core::convert::TryInto;
33
use deku::ctx::BitSize;
44
use deku::writer::Writer;
55
use deku::{prelude::*, DekuWriter};
6-
use no_std_io::io::{Seek, Write};
6+
use no_std_io::io::{Cursor, Read, Seek, Write};
77

8-
fn bit_flipper_read<R: std::io::Read + std::io::Seek>(
8+
fn bit_flipper_read<R: Read + Seek>(
99
field_a: u8,
1010
reader: &mut Reader<R>,
1111
bit_size: BitSize,
@@ -59,7 +59,7 @@ struct DekuTest {
5959

6060
fn main() {
6161
let test_data = [0x01, 0b1001_0110];
62-
let mut cursor = std::io::Cursor::new(test_data);
62+
let mut cursor = Cursor::new(test_data);
6363

6464
let (_read_amt, ret_read) = DekuTest::from_reader((&mut cursor, 0)).unwrap();
6565

examples/enums.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
use std::io::Cursor;
1+
use no_std_io::io::Cursor;
22

33
use deku::{prelude::*, reader::Reader};
44
use hexlit::hex;

examples/ipv4.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,7 @@ pub struct Ipv4Header {
5050
fn main() {
5151
let test_data = hex!("4500004b0f490000801163a591fea0ed91fd02cb").to_vec();
5252

53-
let mut cursor = std::io::Cursor::new(test_data.clone());
53+
let mut cursor = no_std_io::io::Cursor::new(test_data.clone());
5454
let mut reader = deku::reader::Reader::new(&mut cursor);
5555
let ip_header = Ipv4Header::from_reader_with_ctx(&mut reader, ()).unwrap();
5656

0 commit comments

Comments
 (0)