From 35a6203c4340121b59369f381ebb06b849de86a5 Mon Sep 17 00:00:00 2001 From: eltitanb Date: Thu, 4 Jun 2026 13:33:34 +0100 Subject: [PATCH 1/2] bump --- Cargo.toml | 8 +- crates/flux-network/tests/tcp_roundtrip.rs | 2 +- crates/flux-utils/src/arrayvec.rs | 118 +++++++++++++-------- 3 files changed, 80 insertions(+), 48 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index bb2fe30..9b84a47 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -9,7 +9,7 @@ members = [ "crates/spine-derive", "crates/type-hash", "crates/type-hash-derive", - "crates/flux-network" + "crates/flux-network", ] resolver = "2" @@ -55,8 +55,8 @@ bitflags = { version = "2.6.0", features = ["serde"] } crossterm = "0.28.1" strum = { features = ["derive"], version = "0.26.1" } indexmap = { features = ["serde"], version = "2.11.1" } -wincode = "0.2.5" -wincode-derive = "0.2.3" +wincode = "0.4" +wincode-derive = "0.4" bytes = "1" mio = { version = "1.1.1", features = ["net", "os-poll"] } tempfile = "3" @@ -81,4 +81,4 @@ nursery = "warn" pedantic = "warn" redundant_pub_crate = { level = "allow", priority = 1 } return_self_not_must_use = { level = "allow", priority = 1 } -redundant_closure_for_method_calls = { level = "allow", priority = 1 } # only allowed because otherwise I was getting an ICE on cargo clippy +redundant_closure_for_method_calls = { level = "allow", priority = 1 } # only allowed because otherwise I was getting an ICE on cargo clippy diff --git a/crates/flux-network/tests/tcp_roundtrip.rs b/crates/flux-network/tests/tcp_roundtrip.rs index a068122..29a52b3 100644 --- a/crates/flux-network/tests/tcp_roundtrip.rs +++ b/crates/flux-network/tests/tcp_roundtrip.rs @@ -12,7 +12,7 @@ struct TestMsg(u32); fn wincode_ser_into_vec(buf: &mut Vec, value: &T) where - T: wincode::SchemaWrite, + T: wincode::SchemaWrite, { wincode::serialize_into(buf, value).unwrap(); } diff --git a/crates/flux-utils/src/arrayvec.rs b/crates/flux-utils/src/arrayvec.rs index 82bdcb8..a2a7c4e 100644 --- a/crates/flux-utils/src/arrayvec.rs +++ b/crates/flux-utils/src/arrayvec.rs @@ -606,61 +606,77 @@ mod bytes_impl { #[cfg(feature = "wincode")] mod wincode_impl { - use std::{ - mem::{self, MaybeUninit}, - ptr, - }; + use std::mem::{self, MaybeUninit}; - use wincode::{TypeMeta, io::Writer, len::SeqLen}; + use wincode::{ + TypeMeta, + config::ConfigCore, + io::{Reader, Writer}, + len::SeqLen, + }; use super::ArrayVec; type BatchWireLen = wincode::len::BincodeLen; - fn is_pod() -> bool + fn can_write_zero_copy() -> bool + where + C: ConfigCore, + T: wincode::SchemaWrite, + { + matches!( + >::TYPE_META, + TypeMeta::Static { size: _, zero_copy: true } + ) + } + + fn can_read_zero_copy<'de, T, C>() -> bool where - T: wincode::SchemaWrite, + C: ConfigCore, + T: wincode::SchemaRead<'de, C, Dst = T>, { - matches!(T::TYPE_META, TypeMeta::Static { size: _, zero_copy: true }) + matches!( + >::TYPE_META, + TypeMeta::Static { size: _, zero_copy: true } + ) } - impl, const N: usize> wincode::SchemaWrite - for ArrayVec + unsafe impl wincode::SchemaWrite for ArrayVec + where + C: ConfigCore, + T: Copy + wincode::SchemaWrite, { type Src = Self; #[inline] fn size_of(src: &Self::Src) -> wincode::WriteResult { let len = src.len(); - let len_bytes = BatchWireLen::write_bytes_needed(len)?; + let len_bytes = >::write_bytes_needed(len)?; - if is_pod::() { + if can_write_zero_copy::() { return Ok(len_bytes + len * mem::size_of::()); } let mut total = len_bytes; for x in src.as_slice() { - total += ::size_of(x)?; + total += >::size_of(x)?; } Ok(total) } #[inline] - fn write( - writer: &mut impl wincode::io::Writer, - src: &Self::Src, - ) -> wincode::WriteResult<()> { + fn write(mut writer: impl Writer, src: &Self::Src) -> wincode::WriteResult<()> { let total_bytes = Self::size_of(src)?; let mut w = unsafe { writer.as_trusted_for(total_bytes)? }; - BatchWireLen::write(&mut w, src.len())?; + >::write(w.by_ref(), src.len())?; - if is_pod::() { + if can_write_zero_copy::() { let slice = src.as_slice(); unsafe { w.write_slice_t(slice)?; } } else { for item in src.as_slice() { - ::write(&mut w, item)?; + >::write(w.by_ref(), item)?; } } w.finish()?; @@ -668,25 +684,24 @@ mod wincode_impl { } } - impl< - 'de, - T: Copy + wincode::SchemaRead<'de, Dst = T> + wincode::SchemaWrite, - const N: usize, - > wincode::SchemaRead<'de> for ArrayVec + unsafe impl<'de, T, C, const N: usize> wincode::SchemaRead<'de, C> for ArrayVec + where + C: ConfigCore, + T: Copy + wincode::SchemaRead<'de, C, Dst = T>, { type Dst = Self; fn read( - reader: &mut impl wincode::io::Reader<'de>, + mut reader: impl Reader<'de>, dst: &mut MaybeUninit, ) -> wincode::ReadResult<()> { - let len = BatchWireLen::read::(reader)?; + let len = >::read(reader.by_ref())?; if len > N { return Err(wincode::ReadError::LengthEncodingOverflow("too many values")); } let mut arr = Self::new(); - if is_pod::() { + if can_read_zero_copy::<'de, T, C>() { unsafe { let dst_slice: &mut [MaybeUninit] = core::slice::from_raw_parts_mut(arr.data.as_mut_ptr(), len); @@ -696,7 +711,7 @@ mod wincode_impl { } else { for _ in 0..len { let mut tmp = MaybeUninit::::uninit(); - ::read(reader, &mut tmp)?; + >::read(reader.by_ref(), &mut tmp)?; arr.push(unsafe { tmp.assume_init() }); } } @@ -706,35 +721,33 @@ mod wincode_impl { } } - impl wincode::SchemaWrite for super::ArrayStr { + unsafe impl wincode::SchemaWrite for super::ArrayStr { type Src = Self; #[inline] fn size_of(src: &Self::Src) -> wincode::WriteResult { - as wincode::SchemaWrite>::size_of(&src.buf) + as wincode::SchemaWrite>::size_of(&src.buf) } #[inline] - fn write( - writer: &mut impl wincode::io::Writer, - src: &Self::Src, - ) -> wincode::WriteResult<()> { - as wincode::SchemaWrite>::write(writer, &src.buf) + fn write(writer: impl Writer, src: &Self::Src) -> wincode::WriteResult<()> { + as wincode::SchemaWrite>::write(writer, &src.buf) } } - impl<'de, const N: usize> wincode::SchemaRead<'de> for super::ArrayStr { + unsafe impl<'de, C: ConfigCore, const N: usize> wincode::SchemaRead<'de, C> + for super::ArrayStr + { type Dst = Self; fn read( - reader: &mut impl wincode::io::Reader<'de>, + reader: impl Reader<'de>, dst: &mut MaybeUninit, ) -> wincode::ReadResult<()> { - let buf_dst = unsafe { - &mut *(ptr::from_mut::>(dst)) - .cast::>>() - }; - as wincode::SchemaRead>::read(reader, buf_dst) + let buf = as wincode::SchemaRead<'de, C>>::get(reader)?; + let value = Self::try_from(buf).map_err(wincode::ReadError::InvalidUtf8Encoding)?; + dst.write(value); + Ok(()) } } } @@ -867,4 +880,23 @@ mod wincode_tests { "serialized output should contain slice payload bytes; got: {bytes:?}" ); } + + #[test] + fn arraystr() { + let value = ArrayStr::<16>::from_str_truncate("hello"); + + let bytes = wincode::serialize(&value).unwrap(); + let decoded = wincode::deserialize::>(bytes.as_slice()).unwrap(); + + assert_eq!(decoded.as_str(), "hello"); + } + + #[test] + fn arraystr_rejects_invalid_utf8() { + let mut invalid = ArrayVec::::new(); + invalid.push(0xff); + let bytes = wincode::serialize(&invalid).unwrap(); + + assert!(wincode::deserialize::>(bytes.as_slice()).is_err()); + } } From bed1742578f72b45edb6c118af200a91b20e0792 Mon Sep 17 00:00:00 2001 From: eltitanb Date: Thu, 4 Jun 2026 13:35:26 +0100 Subject: [PATCH 2/2] fmt --- crates/flux-utils/src/arrayvec.rs | 20 +++++++++----------- 1 file changed, 9 insertions(+), 11 deletions(-) diff --git a/crates/flux-utils/src/arrayvec.rs b/crates/flux-utils/src/arrayvec.rs index a2a7c4e..5993664 100644 --- a/crates/flux-utils/src/arrayvec.rs +++ b/crates/flux-utils/src/arrayvec.rs @@ -623,10 +623,10 @@ mod wincode_impl { C: ConfigCore, T: wincode::SchemaWrite, { - matches!( - >::TYPE_META, - TypeMeta::Static { size: _, zero_copy: true } - ) + matches!(>::TYPE_META, TypeMeta::Static { + size: _, + zero_copy: true + }) } fn can_read_zero_copy<'de, T, C>() -> bool @@ -634,10 +634,10 @@ mod wincode_impl { C: ConfigCore, T: wincode::SchemaRead<'de, C, Dst = T>, { - matches!( - >::TYPE_META, - TypeMeta::Static { size: _, zero_copy: true } - ) + matches!(>::TYPE_META, TypeMeta::Static { + size: _, + zero_copy: true + }) } unsafe impl wincode::SchemaWrite for ArrayVec @@ -735,9 +735,7 @@ mod wincode_impl { } } - unsafe impl<'de, C: ConfigCore, const N: usize> wincode::SchemaRead<'de, C> - for super::ArrayStr - { + unsafe impl<'de, C: ConfigCore, const N: usize> wincode::SchemaRead<'de, C> for super::ArrayStr { type Dst = Self; fn read(