Repository: sharksforarms/deku
Pull request #394 (2023-12-28 20:22:47)

Allow lit attributes
Working on deku, and I was thinking "the usage `"` around `id` is kinda weird? surely we can support *not* doing this". And this patch does that. I don't know if there is a philosophical reason for all the `"`? I prefer it not existing, and this patch just allows it to not and exist at the same time.
- [Allow Lit::Int for enum id](https://github.com/sharksforarms/deku/commit/b223767b422ad61dcbb180eac293c614f07e6e2a)

I went to make the same changes to `bytes` and `bits` and low and behold this was already allowed! I changed all references and removed the `"` from them.
- [Remove quotation marks from attribute bytes and bits](https://github.com/sharksforarms/deku/commit/fb097d98e52c91a3651bdcef31d63adbcfd0af7a)

github-actions[bot]: ## Benchmark for 2ecc2d5
  <details>
    <summary>Click to view benchmark</summary>

| Test | Base         | PR               | % |
|------|--------------|------------------|---|
| deku_read_bits | 1173.8±17.34ns | **1119.8±11.77ns** | **-4.60%** |
| deku_read_byte | 19.3±0.26ns | 19.3±0.24ns | 0.00% |
| deku_read_enum | 9.3±0.06ns | 9.3±0.15ns | 0.00% |
| deku_read_vec | 53.7±0.62ns | 53.7±1.00ns | 0.00% |
| deku_write_bits | 113.2±2.13ns | 114.3±2.27ns | +0.97% |
| deku_write_byte | 122.0±2.86ns | 124.5±4.02ns | +2.05% |
| deku_write_enum | 87.0±5.53ns | 88.4±4.89ns | +1.61% |
| deku_write_vec | 3.0±0.03µs | 3.0±0.05µs | 0.00% |

  </details>
  

Patch:
diff --git a/README.md b/README.md
index 4a215b6..e8dd4fb 100644
--- a/README.md
+++ b/README.md
@@ -44,9 +44,9 @@ use deku::prelude::*;
 #[derive(Debug, PartialEq, DekuRead, DekuWrite)]
 #[deku(endian = "big")]
 struct DekuTest {
-    #[deku(bits = "4")]
+    #[deku(bits = 4)]
     field_a: u8,
-    #[deku(bits = "4")]
+    #[deku(bits = 4)]
     field_b: u8,
     field_c: u16,
 }
diff --git a/benches/deku.rs b/benches/deku.rs
index 4243ff5..d6bad65 100644
--- a/benches/deku.rs
+++ b/benches/deku.rs
@@ -5,11 +5,11 @@ use deku::prelude::*;
 
 #[derive(Debug, PartialEq, DekuRead, DekuWrite)]
 struct DekuBits {
-    #[deku(bits = "1")]
+    #[deku(bits = 1)]
     data_01: u8,
-    #[deku(bits = "2")]
+    #[deku(bits = 2)]
     data_02: u8,
-    #[deku(bits = "5")]
+    #[deku(bits = 5)]
     data_03: u8,
 }
 
diff --git a/deku-derive/src/lib.rs b/deku-derive/src/lib.rs
index 87e28f4..061a0c2 100644
--- a/deku-derive/src/lib.rs
+++ b/deku-derive/src/lib.rs
@@ -23,6 +23,7 @@ mod macros;
 enum Id {
     TokenStream(TokenStream),
     LitByteStr(syn::LitByteStr),
+    Int(syn::LitInt),
 }
 
 impl ToString for Id {
@@ -36,6 +37,7 @@ impl ToTokens for Id {
         match self {
             Id::TokenStream(v) => v.to_tokens(tokens),
             Id::LitByteStr(v) => v.to_tokens(tokens),
+            Id::Int(v) => v.to_tokens(tokens),
         }
     }
 }
@@ -49,6 +51,7 @@ impl FromMeta for Id {
                     .parse::<TokenStream>()
                     .expect("could not parse token stream"),
             )),
+            syn::Lit::Int(ref s) => Ok(Id::Int(s.clone())),
             syn::Lit::ByteStr(ref s) => Ok(Id::LitByteStr(s.clone())),
             _ => Err(darling::Error::unexpected_lit_type(value)),
         })
diff --git a/deku-derive/src/macros/deku_read.rs b/deku-derive/src/macros/deku_read.rs
index b075355..9e7a788 100644
--- a/deku-derive/src/macros/deku_read.rs
+++ b/deku-derive/src/macros/deku_read.rs
@@ -183,6 +183,7 @@ fn emit_enum(input: &DekuData) -> Result<TokenStream, syn::Error> {
             match variant_id {
                 Id::TokenStream(v) => (false, quote! {&#v}.into_token_stream()),
                 Id::LitByteStr(v) => (false, v.into_token_stream()),
+                Id::Int(v) => (false, v.into_token_stream()),
             }
         } else if let Some(variant_id_pat) = &variant.id_pat {
             // If user has supplied an id, then we have an id_pat that and the id variant doesn't
@@ -234,6 +235,7 @@ fn emit_enum(input: &DekuData) -> Result<TokenStream, syn::Error> {
             if let Some(variant_id) = &variant.id {
                 let deref = match variant_id {
                     Id::TokenStream(_) => quote! {},
+                    Id::Int(_) => quote! {},
                     Id::LitByteStr(_) => quote! {*},
                 };
 
diff --git a/deku-derive/src/macros/deku_write.rs b/deku-derive/src/macros/deku_write.rs
index 69243a5..6e0b715 100644
--- a/deku-derive/src/macros/deku_write.rs
+++ b/deku-derive/src/macros/deku_write.rs
@@ -203,6 +203,12 @@ fn emit_enum(input: &DekuData) -> Result<TokenStream, syn::Error> {
                             __deku_variant_id.write(__deku_output, (#id_args))?;
                         }
                     }
+                    Id::Int(v) => {
+                        quote! {
+                            let mut __deku_variant_id: #id_type = #v;
+                            __deku_variant_id.write(__deku_output, (#id_args))?;
+                        }
+                    }
                     Id::LitByteStr(v) => {
                         quote! {
                             let mut __deku_variant_id: #id_type = *#v;
diff --git a/deku-derive/src/macros/mod.rs b/deku-derive/src/macros/mod.rs
index 3dccf46..b24d0ba 100644
--- a/deku-derive/src/macros/mod.rs
+++ b/deku-derive/src/macros/mod.rs
@@ -232,8 +232,8 @@ fn gen_type_from_ctx_id(
 }
 
 /// Generate argument for `id`:
-/// `#deku(endian = "big", bits = "1")` -> `Endian::Big, BitSize(1)`
-/// `#deku(endian = "big", bytes = "1")` -> `Endian::Big, ByteSize(1)`
+/// `#deku(endian = "big", bits = 1)` -> `Endian::Big, BitSize(1)`
+/// `#deku(endian = "big", bytes = 1)` -> `Endian::Big, ByteSize(1)`
 pub(crate) fn gen_id_args(
     endian: Option<&syn::LitStr>,
     bits: Option<&Num>,
@@ -258,8 +258,8 @@ pub(crate) fn gen_id_args(
 
 /// Generate argument for fields:
 ///
-/// `#deku(endian = "big", bits = "1", ctx = "a")` -> `Endian::Big, BitSize(1), a`
-/// `#deku(endian = "big", bytes = "1", ctx = "a")` -> `Endian::Big, ByteSize(1), a`
+/// `#deku(endian = "big", bits = 1, ctx = "a")` -> `Endian::Big, BitSize(1), a`
+/// `#deku(endian = "big", bytes = 1, ctx = "a")` -> `Endian::Big, ByteSize(1), a`
 fn gen_field_args(
     endian: Option<&syn::LitStr>,
     bits: Option<&Num>,
diff --git a/ensure_no_std/src/bin/main.rs b/ensure_no_std/src/bin/main.rs
index 8bf3102..fdaf576 100644
--- a/ensure_no_std/src/bin/main.rs
+++ b/ensure_no_std/src/bin/main.rs
@@ -17,9 +17,9 @@ use deku::prelude::*;
 
 #[derive(Debug, PartialEq, DekuRead, DekuWrite)]
 struct DekuTest {
-    #[deku(bits = "5")]
+    #[deku(bits = 5)]
     field_a: u8,
-    #[deku(bits = "3")]
+    #[deku(bits = 3)]
     field_b: u8,
     count: u8,
     #[deku(count = "count")]
diff --git a/ensure_wasm/src/lib.rs b/ensure_wasm/src/lib.rs
index 539f94e..bbcbdfa 100644
--- a/ensure_wasm/src/lib.rs
+++ b/ensure_wasm/src/lib.rs
@@ -25,9 +25,9 @@ use deku::prelude::*;
 #[wasm_bindgen]
 #[derive(Debug, PartialEq, DekuRead, DekuWrite)]
 pub struct DekuTest {
-    #[deku(bits = "5")]
+    #[deku(bits = 5)]
     pub field_a: u8,
-    #[deku(bits = "3")]
+    #[deku(bits = 3)]
     pub field_b: u8,
     pub field_c: u8,
 }
diff --git a/examples/enums.rs b/examples/enums.rs
index 9286c15..296ffc5 100644
--- a/examples/enums.rs
+++ b/examples/enums.rs
@@ -3,25 +3,33 @@ use std::io::Cursor;
 use deku::{prelude::*, reader::Reader};
 use hexlit::hex;
 
+const THREE: u8 = 3;
+
 #[derive(Debug, PartialEq, DekuRead, DekuWrite)]
 #[deku(type = "u8")]
 enum DekuTest {
-    #[deku(id = "0")]
+    #[deku(id = 0)]
     Var1,
-    #[deku(id = "1")]
-    Var2(#[deku(bytes = "2")] u32),
-    #[deku(id = "2")]
+
+    #[deku(id = 1)]
+    Var2(#[deku(bytes = 2)] u32),
+
+    #[deku(id = 0x02)]
     Var3(u8, u8),
-    #[deku(id = "3")]
+
+    #[deku(id = "THREE")]
     Var4 {
         field_a: u8,
         #[deku(count = "field_a")]
         field_b: Vec<u8>,
     },
+
     #[deku(id_pat = "4..=6")]
     Var5 { id: u8 },
+
     #[deku(id_pat = "&id if id > 6")]
     Var6 { id: u8 },
+
     #[deku(id_pat = "_")]
     VarDefault { id: u8, value: u8 },
 }
diff --git a/examples/example.rs b/examples/example.rs
index eae2f91..2f7d9f6 100644
--- a/examples/example.rs
+++ b/examples/example.rs
@@ -11,7 +11,7 @@ use deku::prelude::*;
 
 #[derive(Debug, PartialEq, DekuRead, DekuWrite)]
 struct FieldF {
-    #[deku(bits = "6")]
+    #[deku(bits = 6)]
     #[deku(assert_eq = "6")]
     data: u8,
 }
@@ -26,13 +26,13 @@ struct FieldF {
 // #[deku(endian = "little")] // By default it uses the system endianness, but can be overwritten
 struct DekuTest {
     field_a: u8,
-    #[deku(bits = "7")]
+    #[deku(bits = 7)]
     field_b: u8,
-    #[deku(bits = "1")]
+    #[deku(bits = 1)]
     field_c: u8,
     #[deku(endian = "big")]
     field_d: u16,
-    #[deku(bits = "2")]
+    #[deku(bits = 2)]
     field_e: u8,
     field_f: FieldF,
     num_items: u8,
diff --git a/examples/ipv4.rs b/examples/ipv4.rs
index a14e1c3..2cfb76b 100644
--- a/examples/ipv4.rs
+++ b/examples/ipv4.rs
@@ -25,19 +25,19 @@ use hexlit::hex;
 #[derive(Debug, PartialEq, DekuRead, DekuWrite)]
 #[deku(endian = "big")]
 pub struct Ipv4Header {
-    #[deku(bits = "4")]
+    #[deku(bits = 4)]
     pub version: u8, // Version
-    #[deku(bits = "4")]
+    #[deku(bits = 4)]
     pub ihl: u8, // Internet Header Length
-    #[deku(bits = "6")]
+    #[deku(bits = 6)]
     pub dscp: u8, // Differentiated Services Code Point
-    #[deku(bits = "2")]
+    #[deku(bits = 2)]
     pub ecn: u8, // Explicit Congestion Notification
     pub length: u16,         // Total Length
     pub identification: u16, // Identification
-    #[deku(bits = "3")]
+    #[deku(bits = 3)]
     pub flags: u8, // Flags
-    #[deku(bits = "13")]
+    #[deku(bits = 13)]
     pub offset: u16, // Fragment Offset
     pub ttl: u8,             // Time To Live
     pub protocol: u8,        // Protocol
diff --git a/src/attributes.rs b/src/attributes.rs
index 16b0028..bd90cdd 100644
--- a/src/attributes.rs
+++ b/src/attributes.rs
@@ -887,7 +887,7 @@ assert_eq!(value.sub.b, 0x01 + 0x02)
 Example:
 ```ignore
 struct Type1 {
-    #[deku(endian = "big", bits = "1")]
+    #[deku(endian = "big", bits = 1)]
     field: u8,
 }
 
@@ -904,7 +904,7 @@ Example: Adding context
 #[deku(endian = "big")]
 struct Type1 {
     field_a: u16,
-    #[deku(bits = "5", ctx = "*field_a")]
+    #[deku(bits = 5, ctx = "*field_a")]
     field_b: SubType,
 }
 
@@ -982,9 +982,9 @@ struct DekuTest {
 #[derive(PartialEq, Debug, DekuRead, DekuWrite)]
 #[deku(ctx = "my_id: u8", id = "my_id")]
 enum MyEnum {
-    #[deku(id = "1")]
+    #[deku(id = 1)]
     VariantA(u8),
-    #[deku(id = "2")]
+    #[deku(id = 2)]
     VariantB,
 }
 
@@ -1021,9 +1021,9 @@ Example:
 # #[derive(PartialEq, Debug, DekuRead, DekuWrite)]
 #[deku(type = "u8")]
 enum DekuTest {
-    #[deku(id = "0x01")]
+    #[deku(id = 0x01)]
     VariantA(u8),
-    #[deku(id = "0x02")]
+    #[deku(id = 0x02)]
     VariantB(u8, u16),
 }
 
@@ -1101,7 +1101,7 @@ Example:
 # #[derive(PartialEq, Debug, DekuRead, DekuWrite)]
 #[deku(type = "u8")]
 enum DekuTest {
-    #[deku(id = "0x01")]
+    #[deku(id = 0x01)]
     VariantA(u8),
     #[deku(id_pat = "0x02..=0x06")]
     VariantB {
@@ -1151,10 +1151,10 @@ Example:
 # use std::io::Cursor;
 # use std::convert::{TryInto, TryFrom};
 # #[derive(PartialEq, Debug, DekuRead, DekuWrite)]
-#[deku(type = "u8", bits = "4")]
+#[deku(type = "u8", bits = 4)]
 enum DekuTest {
-    #[deku(id = "0b1001")]
-    VariantA( #[deku(bits = "4")] u8, u8),
+    #[deku(id = 0b1001)]
+    VariantA( #[deku(bits = 4)] u8, u8),
 }
 
 let data: &[u8] = &[0b1001_0110, 0xFF];
@@ -1182,9 +1182,9 @@ Example:
 # use deku::prelude::*;
 # use std::convert::{TryInto, TryFrom};
 # #[derive(PartialEq, Debug, DekuRead, DekuWrite)]
-#[deku(type = "u32", bytes = "2")]
+#[deku(type = "u32", bytes = 2)]
 enum DekuTest {
-    #[deku(id = "0xBEEF")]
+    #[deku(id = 0xBEEF)]
     VariantA(u8),
 }
 
diff --git a/src/lib.rs b/src/lib.rs
index c3d8c8d..64d36de 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -38,9 +38,9 @@ use deku::prelude::*;
 #[derive(Debug, PartialEq, DekuRead, DekuWrite)]
 #[deku(endian = "big")]
 struct DekuTest {
-    #[deku(bits = "4")]
+    #[deku(bits = 4)]
     field_a: u8,
-    #[deku(bits = "4")]
+    #[deku(bits = 4)]
     field_b: u8,
     field_c: u16,
 }
@@ -176,9 +176,9 @@ use deku::prelude::*;
 #[derive(Debug, PartialEq, DekuRead, DekuWrite)]
 #[deku(type = "u8")]
 enum DekuTest {
-    #[deku(id = "0x01")]
+    #[deku(id = 0x01)]
     VariantA,
-    #[deku(id = "0x02")]
+    #[deku(id = 0x02)]
     VariantB(u16),
 }
 
diff --git a/src/reader.rs b/src/reader.rs
index 6de4b35..f31ed1b 100644
--- a/src/reader.rs
+++ b/src/reader.rs
@@ -55,9 +55,9 @@ impl<'a, R: Read> Reader<'a, R> {
     /// #[derive(Debug, PartialEq, DekuRead, DekuWrite)]
     /// #[deku(endian = "big")]
     /// struct DekuTest {
-    ///     #[deku(bits = "4")]
+    ///     #[deku(bits = 4)]
     ///     field_a: u8,
-    ///     #[deku(bits = "2")]
+    ///     #[deku(bits = 2)]
     ///     field_b: u8,
     /// }
     /// //                       |         | <= this entire byte is Read


Test patch:
diff --git a/tests/test_alloc.rs b/tests/test_alloc.rs
index 5a735d1..32dd937 100644
--- a/tests/test_alloc.rs
+++ b/tests/test_alloc.rs
@@ -21,7 +21,7 @@ enum NestedEnum {
 }
 
 #[derive(Debug, PartialEq, DekuRead, DekuWrite)]
-#[deku(type = "u32", bytes = "2", ctx = "_endian: Endian")]
+#[deku(type = "u32", bytes = 2, ctx = "_endian: Endian")]
 enum NestedEnum2 {
     #[deku(id = "0x01")]
     VarA(u8),
@@ -37,9 +37,9 @@ struct TestDeku {
     #[deku(count = "1")]
     field_e: Vec<u8>, // 1 alloc
     field_f: [u8; 3],
-    #[deku(bits = "3")]
+    #[deku(bits = 3)]
     field_g: u8, // 3 allocs (read_bits(Ordering::Greater))
-    #[deku(bits = "5")]
+    #[deku(bits = 5)]
     field_h: u8, // 1 alloc (read_bits(Ordering::Equal))
                  //field_i: NestedEnum2,
 }
diff --git a/tests/test_attributes/test_ctx.rs b/tests/test_attributes/test_ctx.rs
index 7795ff6..3d16fcd 100644
--- a/tests/test_attributes/test_ctx.rs
+++ b/tests/test_attributes/test_ctx.rs
@@ -136,7 +136,7 @@ fn test_struct_enum_ctx_id() {
     #[derive(PartialEq, Debug, DekuRead, DekuWrite)]
     struct StructEnumId {
         my_id: u8,
-        #[deku(bytes = "1")]
+        #[deku(bytes = 1)]
         data: usize,
         #[deku(ctx = "*my_id, *data")]
         enum_from_id: EnumId,
diff --git a/tests/test_compile/cases/bits_bytes_conflict.rs b/tests/test_compile/cases/bits_bytes_conflict.rs
index 20ab2a8..bc43d3b 100644
--- a/tests/test_compile/cases/bits_bytes_conflict.rs
+++ b/tests/test_compile/cases/bits_bytes_conflict.rs
@@ -1,26 +1,26 @@
 use deku::prelude::*;
 
 #[derive(DekuRead)]
-#[deku(type = "u8", bits = "1", bytes = "2")]
+#[deku(type = "u8", bits = 1, bytes = 2)]
 enum Test1 {}
 
 #[derive(DekuRead)]
 #[deku(type = "u8")]
 enum Test2 {
-    A(#[deku(bits = "1", bytes = "2")] u8),
+    A(#[deku(bits = 1, bytes = 2)] u8),
     B {
-        #[deku(bits = "3", bytes = "4")]
+        #[deku(bits = 3, bytes = 4)]
         a: u8,
     },
 }
 
 #[derive(DekuRead)]
 struct Test3 {
-    #[deku(bits = "5", bytes = "6")]
+    #[deku(bits = 5, bytes = 6)]
     a: u8,
 }
 
 #[derive(DekuRead)]
-struct Test4(#[deku(bits = "7", bytes = "8")] u8);
+struct Test4(#[deku(bits = 7, bytes = 8)] u8);
 
 fn main() {}
diff --git a/tests/test_compile/cases/bits_bytes_conflict.stderr b/tests/test_compile/cases/bits_bytes_conflict.stderr
index d8c433e..ff8f9d5 100644
--- a/tests/test_compile/cases/bits_bytes_conflict.stderr
+++ b/tests/test_compile/cases/bits_bytes_conflict.stderr
@@ -1,23 +1,23 @@
 error: conflicting: both `bits` and `bytes` specified on enum
  --> $DIR/bits_bytes_conflict.rs:4:28
   |
-4 | #[deku(type = "u8", bits = "1", bytes = "2")]
-  |                            ^^^
+4 | #[deku(type = "u8", bits = 1, bytes = 2)]
+  |                            ^
 
 error: conflicting: both `bits` and `bytes` specified on field
   --> $DIR/bits_bytes_conflict.rs:10:21
    |
-10 |     A(#[deku(bits = "1", bytes = "2")] u8),
-   |                     ^^^
+10 |     A(#[deku(bits = 1, bytes = 2)] u8),
+   |                     ^
 
 error: conflicting: both `bits` and `bytes` specified on field
   --> $DIR/bits_bytes_conflict.rs:19:19
    |
-19 |     #[deku(bits = "5", bytes = "6")]
-   |                   ^^^
+19 |     #[deku(bits = 5, bytes = 6)]
+   |                   ^
 
 error: conflicting: both `bits` and `bytes` specified on field
   --> $DIR/bits_bytes_conflict.rs:24:28
    |
-24 | struct Test4(#[deku(bits = "7", bytes = "8")] u8);
-   |                            ^^^
+24 | struct Test4(#[deku(bits = 7, bytes = 8)] u8);
+   |                            ^
diff --git a/tests/test_compile/cases/enum_validation.rs b/tests/test_compile/cases/enum_validation.rs
index 9cd2008..cf1aedc 100644
--- a/tests/test_compile/cases/enum_validation.rs
+++ b/tests/test_compile/cases/enum_validation.rs
@@ -13,49 +13,50 @@ enum Test2 {}
 #[derive(DekuRead)]
 #[deku(type = "u8")]
 enum Test3 {
-    #[deku(id = "1", id_pat = "2..=3")] A(u8),
+    #[deku(id = "1", id_pat = "2..=3")]
+    A(u8),
 }
 
 // test `type` only allowed on enum
 #[derive(DekuRead)]
 #[deku(type = "u8")]
 struct Test4 {
-    a: u8
+    a: u8,
 }
 
 // test `bits` only allowed on enum
 #[derive(DekuRead)]
-#[deku(bits = "1")]
+#[deku(bits = 1)]
 struct Test5 {
-    a: u8
+    a: u8,
 }
 
 // test `bytes` only allowed on enum
 #[derive(DekuRead)]
-#[deku(bits = "1")]
+#[deku(bits = 1)]
 struct Test6 {
-    a: u8
+    a: u8,
 }
 
 // test `id` only allowed on enum
 #[derive(DekuRead)]
 #[deku(id = "test")]
 struct Test7 {
-    a: u8
+    a: u8,
 }
 
 // test `bits` cannot be used with `id`
 #[derive(DekuRead)]
-#[deku(id = "test", bits = "4")]
+#[deku(id = "test", bits = 4)]
 enum Test8 {
-    A
+    A,
 }
 
 // test `bytes` cannot be used with `id`
 #[derive(DekuRead)]
-#[deku(id = "test", bytes = "4")]
+#[deku(id = "test", bytes = 4)]
 enum Test9 {
-    A
+    A,
 }
 
 // test `id` cannot be `_`
@@ -63,7 +64,7 @@ enum Test9 {
 #[deku(type = "u8")]
 enum Test10 {
     #[deku(id = "_")]
-    A
+    A,
 }
 
 // test missing `id`
@@ -72,7 +73,7 @@ enum Test10 {
 enum Test11 {
     #[deku(id = "1")]
     A,
-    B(u8)
+    B(u8),
 }
 
 fn main() {}
diff --git a/tests/test_compile/cases/enum_validation.stderr b/tests/test_compile/cases/enum_validation.stderr
index e097cb3..1ebfc69 100644
--- a/tests/test_compile/cases/enum_validation.stderr
+++ b/tests/test_compile/cases/enum_validation.stderr
@@ -13,53 +13,53 @@ error: conflicting: both `type` and `id` specified on enum
 error: conflicting: both `id` and `id_pat` specified on variant
   --> $DIR/enum_validation.rs:16:17
    |
-16 |     #[deku(id = "1", id_pat = "2..=3")] A(u8),
+16 |     #[deku(id = "1", id_pat = "2..=3")]
    |                 ^^^
 
 error: `type` only supported on enum
-  --> $DIR/enum_validation.rs:21:15
+  --> $DIR/enum_validation.rs:22:15
    |
-21 | #[deku(type = "u8")]
+22 | #[deku(type = "u8")]
    |               ^^^^
 
 error: `bits` only supported on enum
-  --> $DIR/enum_validation.rs:28:15
+  --> $DIR/enum_validation.rs:29:15
    |
-28 | #[deku(bits = "1")]
-   |               ^^^
+29 | #[deku(bits = 1)]
+   |               ^
 
 error: `bits` only supported on enum
-  --> $DIR/enum_validation.rs:35:15
+  --> $DIR/enum_validation.rs:36:15
    |
-35 | #[deku(bits = "1")]
-   |               ^^^
+36 | #[deku(bits = 1)]
+   |               ^
 
 error: `id` only supported on enum
-  --> $DIR/enum_validation.rs:42:13
+  --> $DIR/enum_validation.rs:43:13
    |
-42 | #[deku(id = "test")]
+43 | #[deku(id = "test")]
    |             ^^^^^^
 
 error: error: cannot use `bits` with `id`
-  --> $DIR/enum_validation.rs:50:6
+  --> $DIR/enum_validation.rs:51:6
    |
-50 | enum Test8 {
+51 | enum Test8 {
    |      ^^^^^
 
 error: error: cannot use `bytes` with `id`
-  --> $DIR/enum_validation.rs:57:6
+  --> $DIR/enum_validation.rs:58:6
    |
-57 | enum Test9 {
+58 | enum Test9 {
    |      ^^^^^
 
 error: error: `id_pat` should be used for `_`
-  --> $DIR/enum_validation.rs:66:5
+  --> $DIR/enum_validation.rs:67:5
    |
-66 |     A
+67 |     A,
    |     ^
 
 error: DekuRead: `id` must be specified on non-unit variants
-  --> $DIR/enum_validation.rs:75:5
+  --> $DIR/enum_validation.rs:76:5
    |
-75 |     B(u8)
+76 |     B(u8),
    |     ^
diff --git a/tests/test_from_bytes.rs b/tests/test_from_bytes.rs
index dd14d58..b40e529 100644
--- a/tests/test_from_bytes.rs
+++ b/tests/test_from_bytes.rs
@@ -31,12 +31,12 @@ fn test_from_bytes_struct() {
 #[test]
 fn test_from_bytes_enum() {
     #[derive(Debug, PartialEq, DekuRead, DekuWrite)]
-    #[deku(type = "u8", bits = "4")]
+    #[deku(type = "u8", bits = 4)]
     enum TestDeku {
         #[deku(id = "0b0110")]
-        VariantA(#[deku(bits = "4")] u8),
+        VariantA(#[deku(bits = 4)] u8),
         #[deku(id = "0b0101")]
-        VariantB(#[deku(bits = "2")] u8),
+        VariantB(#[deku(bits = 2)] u8),
     }
 
     let test_data: Vec<u8> = [0b0110_0110u8, 0b0101_1010u8].to_vec();
diff --git a/tests/test_from_reader.rs b/tests/test_from_reader.rs
index 537a6b9..eb7780f 100644
--- a/tests/test_from_reader.rs
+++ b/tests/test_from_reader.rs
@@ -37,12 +37,12 @@ fn test_from_reader_struct() {
 #[test]
 fn test_from_reader_enum() {
     #[derive(Debug, PartialEq, DekuRead, DekuWrite)]
-    #[deku(type = "u8", bits = "4")]
+    #[deku(type = "u8", bits = 4)]
     enum TestDeku {
         #[deku(id = "0b0110")]
-        VariantA(#[deku(bits = "4")] u8),
+        VariantA(#[deku(bits = 4)] u8),
         #[deku(id = "0b0101")]
-        VariantB(#[deku(bits = "2")] u8),
+        VariantB(#[deku(bits = 2)] u8),
     }
 
     let test_data = [0b0110_0110u8, 0b0101_1010u8];
diff --git a/tests/test_regression.rs b/tests/test_regression.rs
index 28fbcb8..c3afb70 100644
--- a/tests/test_regression.rs
+++ b/tests/test_regression.rs
@@ -18,7 +18,7 @@ fn issue_224() {
     }
 
     #[derive(Debug, PartialEq, DekuRead, DekuWrite)]
-    #[deku(type = "u8", bits = "2")]
+    #[deku(type = "u8", bits = 2)]
     pub enum One {
         Start = 0,
         Go = 1,
@@ -26,7 +26,7 @@ fn issue_224() {
     }
 
     #[derive(Debug, PartialEq, DekuRead, DekuWrite)]
-    #[deku(type = "u8", bits = "4")]
+    #[deku(type = "u8", bits = 4)]
     pub enum Two {
         #[deku(id = "0b0000")]
         Put(Op1),
@@ -40,17 +40,17 @@ fn issue_224() {
 
     #[derive(Debug, PartialEq, DekuRead, DekuWrite)]
     pub struct Op1 {
-        #[deku(bits = "2")]
+        #[deku(bits = 2)]
         pub i: u8,
-        #[deku(bits = "4")]
+        #[deku(bits = 4)]
         pub o: u8,
     }
 
     #[derive(Debug, PartialEq, DekuRead, DekuWrite)]
     pub struct Op2 {
-        #[deku(bits = "8")]
+        #[deku(bits = 8)]
         pub w: u8,
-        #[deku(bits = "6")]
+        #[deku(bits = 6)]
         pub j: u8,
     }
 
diff --git a/tests/test_struct.rs b/tests/test_struct.rs
index 063bf5a..9880309 100644
--- a/tests/test_struct.rs
+++ b/tests/test_struct.rs
@@ -18,9 +18,9 @@ pub struct DoubleNestedDeku {
 // Common struct to test nesting
 #[derive(PartialEq, Debug, DekuRead, DekuWrite)]
 pub struct NestedDeku {
-    #[deku(bits = "6")]
+    #[deku(bits = 6)]
     pub nest_a: u8,
-    #[deku(bits = "2")]
+    #[deku(bits = 2)]
     pub nest_b: u8,
 
     pub inner: DoubleNestedDeku,
@@ -31,7 +31,7 @@ pub struct NestedDeku {
 fn test_read_too_much_data() {
     #[derive(DekuRead)]
     pub struct TestStruct {
-        #[deku(bits = "6")]
+        #[deku(bits = 6)]
         pub field_a: u8,
     }
 
@@ -44,9 +44,9 @@ fn test_unnamed_struct() {
     #[derive(PartialEq, Debug, DekuRead, DekuWrite)]
     pub struct TestUnamedStruct(
         pub u8,
-        #[deku(bits = "2")] pub u8,
-        #[deku(bits = "6")] pub u8,
-        #[deku(bytes = "2")] pub u16,
+        #[deku(bits = 2)] pub u8,
+        #[deku(bits = 6)] pub u8,
+        #[deku(bytes = 2)] pub u16,
         #[deku(endian = "big")] pub u16,
         pub NestedDeku,
         #[deku(update = "self.7.len()")] pub u8,
@@ -101,11 +101,11 @@ fn test_named_struct() {
     #[derive(PartialEq, Debug, DekuRead, DekuWrite)]
     pub struct TestStruct {
         pub field_a: u8,
-        #[deku(bits = "2")]
+        #[deku(bits = 2)]
         pub field_b: u8,
-        #[deku(bits = "6")]
+        #[deku(bits = 6)]
         pub field_c: u8,
-        #[deku(bytes = "2")]
+        #[deku(bytes = 2)]
         pub field_d: u16,
         #[deku(update = "1+self.field_d")]
         #[deku(endian = "big")]