Repository: sharksforarms/deku
Pull request #547 (2025-04-12 11:31:27)

Bugfix/temp values as ref
Thank you for this great crate!

I encountered a small problem (#545). I tried to fix this with this PR.

I changed that `temp_value` is accessible for `cond`  as reference:

![17444628461661634612397217961494](https://github.com/user-attachments/assets/b5f5ca61-c88f-4108-986f-fb8038eb232b)


Please have a look. I gratefully appreciate any feedback to incorporate in this PR.

* `cargo test` seems to work fine.
* I added a test to illustrate the problem and to prove that it is fixed...

goto40: I would appreciate any help in fixing my clippy/fmt issues. I somehow am puzzled about the error - since I did not touch the corresponding location.

I also observed similar issues [on the master](https://github.com/sharksforarms/deku/actions/runs/14254021262/job/39953105704#step:4:69).
sharksforarms: @goto40 ah yes. since our CI is based on the latest rust stable/clippy sometimes it flags new things in CI. I've since fixed these in the main branch.

Patch:
diff --git a/deku-derive/src/macros/deku_write.rs b/deku-derive/src/macros/deku_write.rs
index 7dc6560..8a3ec67 100644
--- a/deku-derive/src/macros/deku_write.rs
+++ b/deku-derive/src/macros/deku_write.rs
@@ -7,7 +7,7 @@ use syn::LitStr;
 
 use crate::macros::{
     assertion_failed, gen_bit_order_from_str, gen_ctx_types_and_arg, gen_field_args,
-    gen_struct_destruction, token_contains_string, wrap_default_ctx,
+    gen_internal_field_ident, gen_struct_destruction, token_contains_string, wrap_default_ctx,
 };
 use crate::{DekuData, DekuDataEnum, DekuDataStruct, FieldData, Id};
 
@@ -721,8 +721,10 @@ fn emit_field_write(
         if f.temp {
             if let Some(temp_value) = &f.temp_value {
                 let field_type = &f.ty;
+                let internal_field_ident = gen_internal_field_ident(&field_ident);
                 quote! {
-                    let #field_ident: #field_type = #temp_value;
+                    let #internal_field_ident: #field_type = #temp_value;
+                    let #field_ident: &#field_type = &#internal_field_ident;
                     ::#crate_::DekuWriter::to_writer(#object_prefix &#field_ident, __deku_writer, (#write_args))
                 }
             } else {
diff --git a/src/lib.rs b/src/lib.rs
index 312438f..a2fb069 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -360,6 +360,8 @@ use alloc::vec::Vec;
 /// re-export of [no_std_io2](https://crates.io/crates/no-std-io2)
 pub mod no_std_io {
     pub use no_std_io::io::Cursor;
+    pub use no_std_io::io::Error;
+    pub use no_std_io::io::ErrorKind;
     pub use no_std_io::io::Read;
     pub use no_std_io::io::Result;
     pub use no_std_io::io::Seek;


Test patch:
diff --git a/tests/test_attributes/mod.rs b/tests/test_attributes/mod.rs
index 25eca93..918967f 100644
--- a/tests/test_attributes/mod.rs
+++ b/tests/test_attributes/mod.rs
@@ -7,4 +7,6 @@ mod test_map;
 mod test_padding;
 mod test_skip;
 mod test_temp;
+#[cfg(feature = "bits")]
+mod test_temp_value_with_cond;
 mod test_update;
diff --git a/tests/test_attributes/test_temp_value_with_cond.rs b/tests/test_attributes/test_temp_value_with_cond.rs
new file mode 100644
index 0000000..30abcb2
--- /dev/null
+++ b/tests/test_attributes/test_temp_value_with_cond.rs
@@ -0,0 +1,63 @@
+use deku::prelude::*;
+
+#[test]
+fn test_temp_value_with_cond() {
+    #[deku_derive(DekuRead, DekuWrite)]
+    #[derive(Debug, PartialEq)]
+    #[deku(endian = "big")]
+    struct TestStruct {
+        #[deku(bits = "5", temp, temp_value = "0")]
+        spare1: u8,
+        #[deku(bits = "1", temp, temp_value = "if payload1.is_some() {1} else {0}")]
+        fspec1_8: u8,
+        #[deku(bits = "1", temp, temp_value = "if payload2.is_some() {1} else {0}")]
+        fspec1_7: u8,
+        #[deku(bits = "1", temp, temp_value = "0")]
+        fspec1_fx: u8,
+        #[deku(skip, cond = "*fspec1_8 != 0x01", default = "None")]
+        payload1: Option<u32>,
+        #[deku(skip, cond = "*fspec1_7 != 0x01", default = "None")]
+        payload2: Option<u32>,
+    }
+
+    {
+        let d = TestStruct {
+            payload1: Some(1),
+            payload2: Some(2),
+        };
+        let bytes = d.to_bytes().unwrap();
+        assert_eq!(bytes, vec![6, 0, 0, 0, 1, 0, 0, 0, 2]);
+        let d2 = TestStruct::from_bytes((&bytes, 0)).unwrap().1;
+        assert_eq!(d, d2);
+    }
+    {
+        let d = TestStruct {
+            payload1: None,
+            payload2: Some(2),
+        };
+        let bytes = d.to_bytes().unwrap();
+        assert_eq!(bytes, vec![2, 0, 0, 0, 2]);
+        let d2 = TestStruct::from_bytes((&bytes, 0)).unwrap().1;
+        assert_eq!(d, d2);
+    }
+    {
+        let d = TestStruct {
+            payload1: Some(1),
+            payload2: None,
+        };
+        let bytes = d.to_bytes().unwrap();
+        assert_eq!(bytes, vec![4, 0, 0, 0, 1]);
+        let d2 = TestStruct::from_bytes((&bytes, 0)).unwrap().1;
+        assert_eq!(d, d2);
+    }
+    {
+        let d = TestStruct {
+            payload1: None,
+            payload2: None,
+        };
+        let bytes = d.to_bytes().unwrap();
+        assert_eq!(bytes, vec![0]);
+        let d2 = TestStruct::from_bytes((&bytes, 0)).unwrap().1;
+        assert_eq!(d, d2);
+    }
+}