Trouble finding an appropriate trait bound, what would you use?
⚓ Rust 📅 2026-01-20 👤 surdeus 👁️ 2I'm using serde and not quite sure I should be, but the churn of using something else would be much worse.
Essentially, I'm trying to implement a wrapper type for a length-prefixed sequence as I have any combination of u8, u16, u32, VarInt, VarShort (which is neither var nor short) for length and String (would prefer &'de str), ByteString, ByteStr, Vec<u8>, &[u8] for the actual data.
Example usage I was aiming for:
#[packet(0, s2c)]
pub struct HandShakeS2C {
pub protocol_version: VarInt,
pub server_address: VarString, // 255
pub server_port: u16,
pub next_state: ConnectionState,
}
#[packet(0x01, s2c)]
pub struct EncryptionS2C<'a> {
pub server_id: &'a str, // 20, also haven't figured out how to make a type for &str :(
pub public_key: NetSlice<'a, u16, u8>,
pub verify_token: NetSlice<'a, u16, u8>,
}
/// A String that encodes its length using a VarInt.
pub type VarString = NetList<VarInt, String, char>;
/// A slice that encodes its length using the specified length type.
pub type NetSlice<'a, I, T> = NetList<I, &'a [T], T>;
This may be a bit of an XY problem. If there is a better way, please let me know.
Here's what I came up with, my problem is that I can't find the appropriate bound to fit all these data collections. Some of them either don't implement AsRef<[Item]> (like String for AsRef<[char]> or Extend<Item> (like ByteString).
/// A list that encodes its length using the specified type.
#[derive(Debug, PartialEq)]
pub struct NetList<Len, Data, Item>(pub Data, PhantomData<Item>, PhantomData<Len>);
impl<L, D, I> NetList<L, D, I> {
pub fn new(data: D) -> Self {
Self(data, PhantomData::<I>, PhantomData::<L>)
}
}
impl<L, D, I> Serialize for NetList<L, D, I>
where
L: TryFrom<usize> + Default + Serialize,
D: AsRef<[I]>,
I: Serialize,
{
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: Serializer,
{
let iter = self.0.as_ref().into_iter();
let (min, max) = iter.size_hint();
let len = max.unwrap_or(min);
let mut seq = serializer.serialize_tuple(len)?;
seq.serialize_element(&L::try_from(len).unwrap_or(L::default()))?;
for e in self.0.as_ref().into_iter() {
seq.serialize_element(e)?;
}
seq.end()
}
}
impl<'de, L, Data, I> Deserialize<'de> for NetList<L, Data, I>
where
L: Deserialize<'de> + Into<usize>,
Data: Default + Extend<I>,
I: Deserialize<'de>,
{
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where
D: Deserializer<'de>,
{
let data = deserializer.deserialize_newtype_struct(
"[?; ?]",
PrefixedCollectionVisitor(PhantomData::<L>, PhantomData::<Data>, PhantomData::<I>),
)?;
Ok(NetList(data, PhantomData::<I>, PhantomData::<L>))
}
}
struct PrefixedCollectionVisitor<Len, Data, Item>(
PhantomData<Len>,
PhantomData<Data>,
PhantomData<Item>,
);
impl<'de, I, Data, T> Visitor<'de> for PrefixedCollectionVisitor<I, Data, T>
where
I: Deserialize<'de> + Into<usize>,
Data: Default + Extend<T>,
T: Deserialize<'de>,
{
type Value = Data;
fn expecting(&self, formatter: &mut Formatter) -> std::fmt::Result {
write!(
formatter,
"a {}-prefixed list of {}",
any::type_name::<I>(),
any::type_name::<T>()
)
}
fn visit_newtype_struct<D>(self, deserializer: D) -> Result<Self::Value, D::Error>
where
D: Deserializer<'de>,
{
deserializer.deserialize_seq(self)
}
fn visit_seq<A>(self, mut seq: A) -> Result<Self::Value, A::Error>
where
A: SeqAccess<'de>,
{
let prefix: I = seq.next_element()?.ok_or(A::Error::missing_field("len"))?;
seq.next_element_seed(PrefixedCollectionSeed(
prefix.into(),
PhantomData::<I>,
PhantomData::<Data>,
PhantomData::<T>,
))?
.ok_or(A::Error::missing_field("elements"))
}
}
struct PrefixedCollectionSeed<I, D, T>(usize, PhantomData<I>, PhantomData<D>, PhantomData<T>);
impl<'de, I, Data, T> DeserializeSeed<'de> for PrefixedCollectionSeed<I, Data, T>
where
I: Deserialize<'de>,
Data: Default + Extend<T>,
T: Deserialize<'de>,
{
type Value = Data;
fn deserialize<D>(self, deserializer: D) -> Result<Self::Value, D::Error>
where
D: Deserializer<'de>,
{
deserializer.deserialize_tuple_struct("NetList", self.0, self)
}
}
impl<'de, I, Data, T> Visitor<'de> for PrefixedCollectionSeed<I, Data, T>
where
I: Deserialize<'de>,
Data: Default + Extend<T>,
T: Deserialize<'de>,
{
type Value = Data;
fn expecting(&self, formatter: &mut Formatter) -> std::fmt::Result {
write!(formatter, "a [{:?}; {}]", any::type_name::<T>(), self.0)
}
fn visit_seq<A>(self, mut seq: A) -> Result<Self::Value, A::Error>
where
A: SeqAccess<'de>,
{
let mut data = Data::default();
data.extend_reserve(self.0);
while let Some(next) = seq.next_element()? {
data.extend_one(next);
}
Ok(data)
}
}
1 post - 1 participant
🏷️ Rust_feed