|
1 | 1 | use core::convert::{TryFrom, TryInto}; |
| 2 | +use std::collections::HashSet; |
2 | 3 | use std::io::Cursor; |
3 | 4 |
|
4 | 5 | use deku::prelude::*; |
@@ -346,3 +347,62 @@ fn test_interior_mutability_for_context_read_until_with_ctx() { |
346 | 347 | let check_data = A::from_bytes((&[8, 9, 0, 1, 7, 9, 1, 0], 0)).unwrap().1; |
347 | 348 | assert_eq!(check_data.items.len(), 2); |
348 | 349 | } |
| 350 | + |
| 351 | +#[test] |
| 352 | +fn test_interior_mutability_for_context_read_until_with_ctx_hashset() { |
| 353 | + #[derive(Debug, Clone)] |
| 354 | + struct IndexContext { |
| 355 | + idx: std::rc::Rc<std::cell::Cell<usize>>, |
| 356 | + n: usize, |
| 357 | + fx: std::rc::Rc<std::cell::Cell<bool>>, |
| 358 | + } |
| 359 | + #[deku_derive(DekuRead, DekuWrite)] |
| 360 | + #[derive(PartialEq, Debug, Clone)] |
| 361 | + struct A { |
| 362 | + #[deku( |
| 363 | + until_with_ctx = "|_:&B,ctx:IndexContext| !ctx.fx.get()", |
| 364 | + ctx = "IndexContext { idx: std::rc::Rc::new(std::cell::Cell::new(0)), n: 0, fx: std::rc::Rc::new(std::cell::Cell::new(false))}", |
| 365 | + writer_ctx = "IndexContext { idx: std::rc::Rc::new(std::cell::Cell::new(0)), n: items.len(), fx: std::rc::Rc::new(std::cell::Cell::new(false)) }" |
| 366 | + )] |
| 367 | + items: HashSet<B>, |
| 368 | + } |
| 369 | + |
| 370 | + #[deku_derive(DekuRead, DekuWrite)] |
| 371 | + #[derive(PartialEq, Debug, Clone, Eq, Hash)] |
| 372 | + #[deku( |
| 373 | + ctx = "ctx: IndexContext", |
| 374 | + ctx_default = "IndexContext{idx: std::rc::Rc::new(std::cell::Cell::new(0)), n: 0, fx: std::rc::Rc::new(std::cell::Cell::new(false))}" |
| 375 | + )] // this struct uses a context for serialization. For deserialization it also works with the default context. |
| 376 | + struct B { |
| 377 | + x: u8, |
| 378 | + y: u8, |
| 379 | + #[deku( |
| 380 | + temp, |
| 381 | + temp_value = "{let ret = ctx.idx.get() as u8; ctx.idx.set(ctx.idx.get()+1); ret}" |
| 382 | + )] |
| 383 | + idx_automatically_filled: u8, |
| 384 | + #[deku( |
| 385 | + read_post_processing = "ctx.fx.set(*auto_fx!=0);", |
| 386 | + temp, |
| 387 | + temp_value = "if ctx.idx.get() < ctx.n {1} else {0}" |
| 388 | + )] |
| 389 | + auto_fx: u8, |
| 390 | + } |
| 391 | + |
| 392 | + let test_data = A { |
| 393 | + items: HashSet::from([B { x: 8, y: 9 }, B { x: 7, y: 9 }, B { x: 6, y: 9 }]), |
| 394 | + }; |
| 395 | + |
| 396 | + let ret_write: Vec<u8> = test_data.clone().try_into().unwrap(); |
| 397 | + let test_bytes = vec![8, 9, 0, 1, 7, 9, 1, 1, 6, 9, 2, 0]; |
| 398 | + assert_eq!(ret_write.len(), test_bytes.len()); |
| 399 | + assert_eq!(ret_write.last().unwrap(), &0); |
| 400 | + |
| 401 | + // read the data back |
| 402 | + let check_data = A::from_bytes((&ret_write, 0)).unwrap().1; |
| 403 | + assert_eq!(check_data, test_data); |
| 404 | + |
| 405 | + // check with fx=0 after the second element: |
| 406 | + let check_data = A::from_bytes((&[8, 9, 0, 1, 7, 9, 1, 0], 0)).unwrap().1; |
| 407 | + assert_eq!(check_data.items.len(), 2); |
| 408 | +} |
0 commit comments