Skip to content

Commit e92700a

Browse files
Add reader::read_bytes_const (#429)
* Add reader::read_bytes_const * Reduce codegen for known sizes at compile time - DekuReader<_, Endian> for all types - DekuReader<_, (Endian, Endian)> for u8 * Change Strings in DekuError to Cow<'static, str> * Change all strings in DekuError to Cow<'static, str> so that more can be defined as "not alloc'ed strings" and be removed with panic=abort, build-std and friends. * Remove unused DekuError::Unexpected * Add comment to lib.rs about parser binary size * Add returning io:ErrorKind from reader and writer * Remove DekuError::Write and replace with DekuError::Io. Instead of ignoring error other then UnexpectedEof, return them to bubble up. * clippy * clippy * update trybuild output * clippy --------- Co-authored-by: Emmanuel Thompson <ethompson@fastly.com>
1 parent 1079ada commit e92700a

File tree

15 files changed

+160
-89
lines changed

15 files changed

+160
-89
lines changed

deku-derive/src/lib.rs

Lines changed: 12 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,13 @@
11
/*!
22
Procedural macros that implement `DekuRead` and `DekuWrite` traits
33
*/
4-
54
#![warn(missing_docs)]
65

7-
use std::borrow::Cow;
6+
extern crate alloc;
7+
8+
use alloc::borrow::Cow;
89
use std::convert::TryFrom;
10+
use std::fmt::Display;
911

1012
use darling::{ast, FromDeriveInput, FromField, FromMeta, FromVariant, ToTokens};
1113
use proc_macro2::TokenStream;
@@ -25,9 +27,9 @@ enum Id {
2527
Int(syn::LitInt),
2628
}
2729

28-
impl ToString for Id {
29-
fn to_string(&self) -> String {
30-
self.to_token_stream().to_string()
30+
impl Display for Id {
31+
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
32+
f.write_str(&self.to_token_stream().to_string())
3133
}
3234
}
3335

@@ -73,9 +75,9 @@ impl Num {
7375
}
7476
}
7577

76-
impl ToString for Num {
77-
fn to_string(&self) -> String {
78-
self.0.to_token_stream().to_string()
78+
impl Display for Num {
79+
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
80+
f.write_str(&self.0.to_token_stream().to_string())
7981
}
8082
}
8183

@@ -267,14 +269,12 @@ impl DekuData {
267269

268270
/// Emit a reader. On error, a compiler error is emitted
269271
fn emit_reader(&self) -> TokenStream {
270-
self.emit_reader_checked()
271-
.map_or_else(|e| e.to_compile_error(), |tks| tks)
272+
self.emit_reader_checked().unwrap_or_else(|e| e.to_compile_error())
272273
}
273274

274275
/// Emit a writer. On error, a compiler error is emitted
275276
fn emit_writer(&self) -> TokenStream {
276-
self.emit_writer_checked()
277-
.map_or_else(|e| e.to_compile_error(), |tks| tks)
277+
self.emit_writer_checked().unwrap_or_else(|e| e.to_compile_error())
278278
}
279279

280280
/// Same as `emit_reader`, but won't auto convert error to compile error

deku-derive/src/macros/deku_read.rs

Lines changed: 14 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -275,12 +275,14 @@ fn emit_enum(input: &DekuData) -> Result<TokenStream, syn::Error> {
275275
if !has_default_match && default_reader.is_none() {
276276
variant_matches.push(quote! {
277277
_ => {
278+
extern crate alloc;
279+
use alloc::borrow::Cow;
278280
return Err(::#crate_::DekuError::Parse(
279-
format!(
281+
Cow::from(format!(
280282
"Could not match enum variant id = {:?} on enum `{}`",
281283
__deku_variant_id,
282284
#ident_as_string
283-
)
285+
))
284286
));
285287
}
286288
});
@@ -440,7 +442,9 @@ fn emit_magic_read(input: &DekuData) -> TokenStream {
440442
for __deku_byte in __deku_magic {
441443
let __deku_read_byte = u8::from_reader_with_ctx(__deku_reader, ())?;
442444
if *__deku_byte != __deku_read_byte {
443-
return Err(::#crate_::DekuError::Parse(format!("Missing magic value {:?}", #magic)));
445+
extern crate alloc;
446+
use alloc::borrow::Cow;
447+
return Err(::#crate_::DekuError::Parse(Cow::from(format!("Missing magic value {:?}", #magic))));
444448
}
445449
}
446450
}
@@ -514,11 +518,13 @@ fn emit_padding(bit_size: &TokenStream) -> TokenStream {
514518
{
515519
use core::convert::TryFrom;
516520
// TODO: I hope this consts in most cases?
521+
extern crate alloc;
522+
use alloc::borrow::Cow;
517523
let __deku_pad = usize::try_from(#bit_size).map_err(|e|
518-
::#crate_::DekuError::InvalidParam(format!(
524+
::#crate_::DekuError::InvalidParam(Cow::from(format!(
519525
"Invalid padding param \"({})\": cannot convert to usize",
520526
stringify!(#bit_size)
521-
))
527+
)))
522528
)?;
523529

524530

@@ -820,7 +826,9 @@ pub fn emit_try_from(
820826
let mut cursor = ::#crate_::no_std_io::Cursor::new(input);
821827
let (amt_read, res) = <Self as ::#crate_::DekuContainerRead>::from_reader((&mut cursor, 0))?;
822828
if (amt_read / 8) != total_len {
823-
return Err(::#crate_::DekuError::Parse(format!("Too much data")));
829+
extern crate alloc;
830+
use alloc::borrow::Cow;
831+
return Err(::#crate_::DekuError::Parse(Cow::from("Too much data")));
824832
}
825833
Ok(res)
826834
}

deku-derive/src/macros/deku_write.rs

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -414,11 +414,13 @@ fn emit_padding(bit_size: &TokenStream) -> TokenStream {
414414
quote! {
415415
{
416416
use core::convert::TryFrom;
417+
extern crate alloc;
418+
use alloc::borrow::Cow;
417419
let __deku_pad = usize::try_from(#bit_size).map_err(|e|
418-
::#crate_::DekuError::InvalidParam(format!(
420+
::#crate_::DekuError::InvalidParam(Cow::from(format!(
419421
"Invalid padding param \"({})\": cannot convert to usize",
420422
stringify!(#bit_size)
421-
))
423+
)))
422424
)?;
423425
__deku_writer.write_bits(::#crate_::bitvec::bitvec![u8, ::#crate_::bitvec::Msb0; 0; __deku_pad].as_bitslice())?;
424426
}

deku-derive/src/macros/mod.rs

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -372,12 +372,14 @@ fn assertion_failed(
372372
#[cfg(not(feature = "no-assert-string"))]
373373
{
374374
quote! {
375-
return Err(::#crate_::DekuError::Assertion(format!(
375+
extern crate alloc;
376+
use alloc::borrow::Cow;
377+
return Err(::#crate_::DekuError::Assertion(Cow::from(format!(
376378
"{}.{} field failed assertion: {}",
377379
#ident,
378380
#field_ident_str,
379381
#stringify,
380-
)));
382+
))));
381383
}
382384
}
383385
}

src/error.rs

Lines changed: 12 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,11 @@
11
//! Error module
22
33
#![cfg(feature = "alloc")]
4+
use alloc::borrow::Cow;
5+
6+
use no_std_io::io::ErrorKind;
47

58
use alloc::format;
6-
use alloc::string::String;
79

810
/// Number of bits needed to retry parsing
911
#[derive(Debug, Clone, PartialEq, Eq)]
@@ -38,30 +40,28 @@ pub enum DekuError {
3840
/// Parsing error when reading
3941
Incomplete(NeedSize),
4042
/// Parsing error when reading
41-
Parse(String),
43+
Parse(Cow<'static, str>),
4244
/// Invalid parameter
43-
InvalidParam(String),
44-
/// Unexpected error
45-
Unexpected(String),
45+
InvalidParam(Cow<'static, str>),
4646
/// Assertion error from `assert` or `assert_eq` attributes
47-
Assertion(String),
47+
Assertion(Cow<'static, str>),
4848
/// Assertion error from `assert` or `assert_eq` attributes, without string
4949
AssertionNoStr,
5050
/// Could not resolve `id` for variant
5151
IdVariantNotFound,
52-
/// IO error while writing
53-
Write,
52+
/// IO error while reading or writing
53+
Io(ErrorKind),
5454
}
5555

5656
impl From<core::num::TryFromIntError> for DekuError {
5757
fn from(e: core::num::TryFromIntError) -> DekuError {
58-
DekuError::Parse(format!("error parsing int: {e}"))
58+
DekuError::Parse(Cow::from(format!("error parsing int: {e}")))
5959
}
6060
}
6161

6262
impl From<core::array::TryFromSliceError> for DekuError {
6363
fn from(e: core::array::TryFromSliceError) -> DekuError {
64-
DekuError::Parse(format!("error parsing from slice: {e}"))
64+
DekuError::Parse(Cow::from(format!("error parsing from slice: {e}")))
6565
}
6666
}
6767

@@ -82,11 +82,10 @@ impl core::fmt::Display for DekuError {
8282
),
8383
DekuError::Parse(ref err) => write!(f, "Parse error: {err}"),
8484
DekuError::InvalidParam(ref err) => write!(f, "Invalid param error: {err}"),
85-
DekuError::Unexpected(ref err) => write!(f, "Unexpected error: {err}"),
8685
DekuError::Assertion(ref err) => write!(f, "Assertion error: {err}"),
8786
DekuError::AssertionNoStr => write!(f, "Assertion error"),
8887
DekuError::IdVariantNotFound => write!(f, "Could not resolve `id` for variant"),
89-
DekuError::Write => write!(f, "write error"),
88+
DekuError::Io(ref e) => write!(f, "io errorr: {e:?}"),
9089
}
9190
}
9291
}
@@ -106,11 +105,10 @@ impl From<DekuError> for std::io::Error {
106105
DekuError::Incomplete(_) => io::Error::new(io::ErrorKind::UnexpectedEof, error),
107106
DekuError::Parse(_) => io::Error::new(io::ErrorKind::InvalidData, error),
108107
DekuError::InvalidParam(_) => io::Error::new(io::ErrorKind::InvalidInput, error),
109-
DekuError::Unexpected(_) => io::Error::new(io::ErrorKind::Other, error),
110108
DekuError::Assertion(_) => io::Error::new(io::ErrorKind::InvalidData, error),
111109
DekuError::AssertionNoStr => io::Error::from(io::ErrorKind::InvalidData),
112110
DekuError::IdVariantNotFound => io::Error::new(io::ErrorKind::NotFound, error),
113-
DekuError::Write => io::Error::new(io::ErrorKind::BrokenPipe, error),
111+
DekuError::Io(e) => io::Error::new(e, error),
114112
}
115113
}
116114
}

src/impls/bool.rs

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
use no_std_io::io::{Read, Write};
22

3+
#[cfg(feature = "alloc")]
4+
use alloc::borrow::Cow;
35
#[cfg(feature = "alloc")]
46
use alloc::format;
57

@@ -21,7 +23,9 @@ where
2123
let ret = match val {
2224
0x01 => Ok(true),
2325
0x00 => Ok(false),
24-
_ => Err(DekuError::Parse(format!("cannot parse bool value: {val}",))),
26+
_ => Err(DekuError::Parse(Cow::from(format!(
27+
"cannot parse bool value: {val}",
28+
)))),
2529
}?;
2630

2731
Ok(ret)

src/impls/cstring.rs

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
use alloc::borrow::Cow;
12
use no_std_io::io::{Read, Write};
23
use std::ffi::CString;
34

@@ -27,8 +28,9 @@ where
2728
let bytes =
2829
Vec::from_reader_with_ctx(reader, (Limit::from(|b: &u8| *b == 0x00), inner_ctx))?;
2930

30-
let value = CString::from_vec_with_nul(bytes)
31-
.map_err(|e| DekuError::Parse(format!("Failed to convert Vec to CString: {e}")))?;
31+
let value = CString::from_vec_with_nul(bytes).map_err(|e| {
32+
DekuError::Parse(Cow::from(format!("Failed to convert Vec to CString: {e}")))
33+
})?;
3234

3335
Ok(value)
3436
}

src/impls/nonzero.rs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,6 @@
11
#[cfg(feature = "alloc")]
2+
use alloc::borrow::Cow;
3+
#[cfg(feature = "alloc")]
24
use alloc::format;
35
use core::num::*;
46
use no_std_io::io::{Read, Write};
@@ -19,7 +21,7 @@ macro_rules! ImplDekuTraitsCtx {
1921
let value = <$typ>::new(value);
2022

2123
match value {
22-
None => Err(DekuError::Parse(format!("NonZero assertion"))),
24+
None => Err(DekuError::Parse(Cow::from(format!("NonZero assertion")))),
2325
Some(v) => Ok(v),
2426
}
2527
}

0 commit comments

Comments
 (0)