Skip to content

Commit a1b192d

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 4ef92db commit a1b192d

59 files changed

Lines changed: 1001 additions & 352 deletions

Some content is hidden

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

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

@@ -353,16 +357,7 @@ fn emit_enum(input: &DekuData) -> Result<TokenStream, syn::Error> {
353357
if !has_default_match && default_reader.is_none() {
354358
variant_matches.push(quote! {
355359
_ => {
356-
extern crate alloc;
357-
use alloc::borrow::Cow;
358-
use alloc::format;
359-
return Err(::#crate_::DekuError::Parse(
360-
Cow::from(format!(
361-
"Could not match enum variant id = {:?} on enum `{}`",
362-
__deku_variant_id,
363-
#ident_as_string
364-
))
365-
));
360+
return Err(::#crate_::deku_error!(::#crate_::DekuError::Parse, "Could not match enum variant", "ID {:?} not found on {}", __deku_variant_id, #ident_as_string));
366361
}
367362
});
368363
}
@@ -534,10 +529,7 @@ fn emit_magic_read_lit(crate_: &Ident, magic: &LitByteStr) -> TokenStream {
534529
for __deku_byte in __deku_magic {
535530
let __deku_read_byte = u8::from_reader_with_ctx(__deku_reader, ())?;
536531
if *__deku_byte != __deku_read_byte {
537-
extern crate alloc;
538-
use alloc::borrow::Cow;
539-
use alloc::format;
540-
return Err(::#crate_::DekuError::Parse(Cow::from(format!("Missing magic value {:?}", #magic))));
532+
return Err(::#crate_::deku_error!(::#crate_::DekuError::Parse, "Missing magic value", "{:?}", #magic));
541533
}
542534
}
543535
}
@@ -609,19 +601,13 @@ fn emit_padding(bit_size: &TokenStream, bit_order: Option<&LitStr>) -> TokenStre
609601
let order = gen_bit_order_from_str(bit_order).unwrap();
610602
quote! {
611603
{
612-
use core::convert::TryFrom;
613-
// TODO: I hope this consts in most cases?
614604
extern crate alloc;
615-
use alloc::borrow::Cow;
616-
use alloc::format;
605+
606+
use core::convert::TryFrom;
617607
let __deku_pad = usize::try_from(#bit_size).map_err(|e|
618-
::#crate_::DekuError::InvalidParam(Cow::from(format!(
619-
"Invalid padding param \"({})\": cannot convert to usize",
620-
stringify!(#bit_size)
621-
)))
608+
::#crate_::deku_error!(::#crate_::DekuError::InvalidParam, "Invalid padding param, cannot convert ot usize", "{}", stringify!(#bit_size))
622609
)?;
623610

624-
625611
if (__deku_pad % 8) == 0 {
626612
let bytes_read = __deku_pad / 8;
627613
let mut buf = alloc::vec![0; bytes_read];
@@ -636,19 +622,13 @@ fn emit_padding(bit_size: &TokenStream, bit_order: Option<&LitStr>) -> TokenStre
636622
} else {
637623
quote! {
638624
{
639-
use core::convert::TryFrom;
640-
// TODO: I hope this consts in most cases?
641625
extern crate alloc;
642-
use alloc::borrow::Cow;
643-
use alloc::format;
626+
627+
use core::convert::TryFrom;
644628
let __deku_pad = usize::try_from(#bit_size).map_err(|e|
645-
::#crate_::DekuError::InvalidParam(Cow::from(format!(
646-
"Invalid padding param \"({})\": cannot convert to usize",
647-
stringify!(#bit_size)
648-
)))
629+
::#crate_::deku_error!(::#crate_::DekuError::InvalidParam, "Invalid padding param, cannot convert to usize", "{}", stringify!(#bit_size))
649630
)?;
650631

651-
652632
if (__deku_pad % 8) == 0 {
653633
let bytes_read = __deku_pad / 8;
654634
let mut buf = alloc::vec![0; bytes_read];
@@ -670,19 +650,16 @@ fn emit_padding_bytes(bit_size: &TokenStream) -> TokenStream {
670650
quote! {
671651
{
672652
use core::convert::TryFrom;
673-
extern crate alloc;
674-
use alloc::borrow::Cow;
675-
use alloc::format;
676-
let __deku_pad = usize::try_from(#bit_size).map_err(|e|
677-
::#crate_::DekuError::InvalidParam(Cow::from(format!(
678-
"Invalid padding param \"({})\": cannot convert to usize",
679-
stringify!(#bit_size)
680-
)))
653+
let mut __deku_pad = usize::try_from(#bit_size).map_err(|e|
654+
::#crate_::deku_error!(::#crate_::DekuError::InvalidParam, "Invalid padding param, cannot convert to usize", "{}", stringify!(#bit_size))
681655
)?;
682656

683-
684-
let mut buf = alloc::vec![0; __deku_pad];
685-
let _ = __deku_reader.read_bytes(__deku_pad, &mut buf, ::#crate_::ctx::Order::default())?;
657+
while __deku_pad > 0 {
658+
let mut __deku_pad_source = [0u8; 64];
659+
let __deku_pad_chunk = core::cmp::min(__deku_pad_source.len(), __deku_pad);
660+
__deku_reader.read_bytes(__deku_pad_chunk, &mut __deku_pad_source[..__deku_pad_chunk], ::#crate_::ctx::Order::default())?;
661+
__deku_pad -= __deku_pad_chunk;
662+
}
686663
}
687664
}
688665
}
@@ -1088,9 +1065,7 @@ pub fn emit_try_from(
10881065
let mut cursor = ::#crate_::no_std_io::Cursor::new(input);
10891066
let (amt_read, res) = <Self as ::#crate_::DekuContainerRead>::from_reader((&mut cursor, 0))?;
10901067
if (amt_read / 8) != total_len {
1091-
extern crate alloc;
1092-
use alloc::borrow::Cow;
1093-
return Err(::#crate_::DekuError::Parse(Cow::from("Too much data")));
1068+
return Err(::#crate_::deku_error!(::#crate_::DekuError::Parse, "Too much data"));
10941069
}
10951070
Ok(res)
10961071
}

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)