Skip to main content

wasm_tokio/
core.rs

1use ::core::future::Future;
2use ::core::mem;
3use ::core::str;
4
5use std::sync::Arc;
6
7use leb128_tokio::{AsyncReadLeb128, Leb128DecoderU32, Leb128Encoder};
8use tokio::io::{AsyncRead, AsyncReadExt as _, AsyncWrite, AsyncWriteExt as _};
9use tokio_util::bytes::{BufMut as _, Bytes, BytesMut};
10use tokio_util::codec::{Decoder, Encoder};
11
12pub trait AsyncReadCore: AsyncRead {
13    /// Read [`core:name`](https://webassembly.github.io/spec/core/binary/values.html#names)
14    #[cfg_attr(
15        feature = "tracing",
16        tracing::instrument(level = "trace", ret, skip_all, fields(ty = "name"))
17    )]
18    fn read_core_name(&mut self, s: &mut String) -> impl Future<Output = std::io::Result<()>>
19    where
20        Self: Unpin + Sized,
21    {
22        async move {
23            let n = self.read_u32_leb128().await?;
24            let len = usize::try_from(n).unwrap_or(usize::MAX);
25            let mut buf = Vec::with_capacity(len.min(DEFAULT_MAX_INITIAL_CAPACITY));
26            if self.take(n.into()).read_to_end(&mut buf).await? != len {
27                return Err(std::io::ErrorKind::UnexpectedEof.into());
28            }
29            let buf = String::from_utf8(buf)
30                .map_err(|err| std::io::Error::new(std::io::ErrorKind::InvalidData, err))?;
31            s.push_str(&buf);
32            Ok(())
33        }
34    }
35}
36
37impl<T: AsyncRead> AsyncReadCore for T {}
38
39pub trait AsyncWriteCore: AsyncWrite {
40    /// Write [`core:name`](https://webassembly.github.io/spec/core/binary/values.html#names)
41    #[cfg_attr(
42        feature = "tracing",
43        tracing::instrument(level = "trace", ret, skip_all, fields(ty = "name"))
44    )]
45    fn write_core_name(&mut self, s: &str) -> impl Future<Output = std::io::Result<()>>
46    where
47        Self: Unpin,
48    {
49        async move {
50            let mut buf = BytesMut::with_capacity(5usize.saturating_add(s.len()));
51            CoreNameEncoder.encode(s, &mut buf)?;
52            self.write_all(&buf).await
53        }
54    }
55}
56
57impl<T: AsyncWrite> AsyncWriteCore for T {}
58
59/// [`core:name`](https://webassembly.github.io/spec/core/binary/values.html#names) encoder
60#[derive(Copy, Clone, Debug, Default, Eq, PartialEq)]
61pub struct CoreNameEncoder;
62
63impl<T: AsRef<str>> Encoder<T> for CoreNameEncoder {
64    type Error = std::io::Error;
65
66    fn encode(&mut self, item: T, dst: &mut BytesMut) -> Result<(), Self::Error> {
67        let item = item.as_ref();
68        let len = item.len();
69        let n: u32 = len
70            .try_into()
71            .map_err(|e| std::io::Error::new(std::io::ErrorKind::InvalidInput, e))?;
72        dst.reserve(len + 5 - n.leading_zeros() as usize / 7);
73        Leb128Encoder.encode(n, dst)?;
74        dst.put(item.as_bytes());
75        Ok(())
76    }
77}
78
79/// [`core:name`](https://webassembly.github.io/spec/core/binary/values.html#names) decoder
80///
81/// At most `MAX_INITIAL_CAPACITY` bytes are preallocated based on the name length read from the input
82#[derive(Debug)]
83pub struct CoreNameDecoder<const MAX_INITIAL_CAPACITY: usize = DEFAULT_MAX_INITIAL_CAPACITY>(
84    CoreVecDecoderBytes<MAX_INITIAL_CAPACITY>,
85);
86
87impl<const MAX_INITIAL_CAPACITY: usize> Default for CoreNameDecoder<MAX_INITIAL_CAPACITY> {
88    fn default() -> Self {
89        Self(CoreVecDecoderBytes::default())
90    }
91}
92
93impl<const MAX_INITIAL_CAPACITY: usize> Decoder for CoreNameDecoder<MAX_INITIAL_CAPACITY> {
94    type Item = String;
95    type Error = std::io::Error;
96
97    fn decode(&mut self, src: &mut BytesMut) -> Result<Option<Self::Item>, Self::Error> {
98        let v = self.0.decode(src)?;
99        v.map(bytes_to_string).transpose()
100    }
101
102    fn decode_eof(&mut self, src: &mut BytesMut) -> Result<Option<Self::Item>, Self::Error> {
103        let v = self.0.decode_eof(src)?;
104        v.map(bytes_to_string).transpose()
105    }
106}
107
108fn bytes_to_string(buf: Bytes) -> std::io::Result<String> {
109    let s = str::from_utf8(&buf)
110        .map_err(|err| std::io::Error::new(std::io::ErrorKind::InvalidData, err))?;
111    Ok(s.to_string())
112}
113
114/// [`core:vec`](https://webassembly.github.io/spec/core/binary/conventions.html#binary-vec) encoder
115pub struct CoreVecEncoder<E>(pub E);
116
117impl<E, T, const N: usize> Encoder<[T; N]> for CoreVecEncoder<E>
118where
119    E: Encoder<T>,
120    std::io::Error: From<E::Error>,
121{
122    type Error = std::io::Error;
123
124    fn encode(&mut self, item: [T; N], dst: &mut BytesMut) -> Result<(), Self::Error> {
125        dst.reserve(5 + N);
126        let len = u32::try_from(N)
127            .map_err(|err| std::io::Error::new(std::io::ErrorKind::InvalidInput, err))?;
128        Leb128Encoder.encode(len, dst)?;
129        for item in item {
130            self.0.encode(item, dst)?;
131        }
132        Ok(())
133    }
134}
135
136impl<E, T> Encoder<Vec<T>> for CoreVecEncoder<E>
137where
138    E: Encoder<T>,
139    std::io::Error: From<E::Error>,
140{
141    type Error = std::io::Error;
142
143    fn encode(&mut self, item: Vec<T>, dst: &mut BytesMut) -> Result<(), Self::Error> {
144        let len = item.len();
145        dst.reserve(5 + len);
146        let len = u32::try_from(len)
147            .map_err(|err| std::io::Error::new(std::io::ErrorKind::InvalidInput, err))?;
148        Leb128Encoder.encode(len, dst)?;
149        for item in item {
150            self.0.encode(item, dst)?;
151        }
152        Ok(())
153    }
154}
155
156impl<E, T> Encoder<Box<[T]>> for CoreVecEncoder<E>
157where
158    E: Encoder<T>,
159    std::io::Error: From<E::Error>,
160{
161    type Error = std::io::Error;
162
163    fn encode(&mut self, item: Box<[T]>, dst: &mut BytesMut) -> Result<(), Self::Error> {
164        self.encode(Vec::from(item), dst)
165    }
166}
167
168impl<'a, E, T, const N: usize> Encoder<&'a [T; N]> for CoreVecEncoder<E>
169where
170    E: Encoder<&'a T>,
171    std::io::Error: From<E::Error>,
172{
173    type Error = std::io::Error;
174
175    fn encode(&mut self, item: &'a [T; N], dst: &mut BytesMut) -> Result<(), Self::Error> {
176        dst.reserve(5 + N);
177        let len = u32::try_from(N)
178            .map_err(|err| std::io::Error::new(std::io::ErrorKind::InvalidInput, err))?;
179        Leb128Encoder.encode(len, dst)?;
180        for item in item {
181            self.0.encode(item, dst)?;
182        }
183        Ok(())
184    }
185}
186
187impl<'a, E, T> Encoder<&'a [T]> for CoreVecEncoder<E>
188where
189    E: Encoder<&'a T>,
190    std::io::Error: From<E::Error>,
191{
192    type Error = std::io::Error;
193
194    fn encode(&mut self, item: &'a [T], dst: &mut BytesMut) -> Result<(), Self::Error> {
195        let len = item.len();
196        dst.reserve(5 + len);
197        let len = u32::try_from(len)
198            .map_err(|err| std::io::Error::new(std::io::ErrorKind::InvalidInput, err))?;
199        Leb128Encoder.encode(len, dst)?;
200        for item in item {
201            self.0.encode(item, dst)?;
202        }
203        Ok(())
204    }
205}
206
207impl<'a, 'b, E, T> Encoder<&'a &'b [T]> for CoreVecEncoder<E>
208where
209    E: Encoder<&'b T>,
210    std::io::Error: From<E::Error>,
211{
212    type Error = std::io::Error;
213
214    fn encode(&mut self, item: &'a &'b [T], dst: &mut BytesMut) -> Result<(), Self::Error> {
215        self.encode(*item, dst)
216    }
217}
218
219impl<'a, E, T> Encoder<&'a Vec<T>> for CoreVecEncoder<E>
220where
221    E: Encoder<&'a T>,
222    std::io::Error: From<E::Error>,
223{
224    type Error = std::io::Error;
225
226    fn encode(&mut self, item: &'a Vec<T>, dst: &mut BytesMut) -> Result<(), Self::Error> {
227        self.encode(item.as_slice(), dst)
228    }
229}
230
231impl<'a, 'b, E, T> Encoder<&'a &'b Vec<T>> for CoreVecEncoder<E>
232where
233    E: Encoder<&'b T>,
234    std::io::Error: From<E::Error>,
235{
236    type Error = std::io::Error;
237
238    fn encode(&mut self, item: &'a &'b Vec<T>, dst: &mut BytesMut) -> Result<(), Self::Error> {
239        self.encode(item.as_slice(), dst)
240    }
241}
242
243impl<'a, E, T> Encoder<&'a Box<[T]>> for CoreVecEncoder<E>
244where
245    E: Encoder<&'a T>,
246    std::io::Error: From<E::Error>,
247{
248    type Error = std::io::Error;
249
250    fn encode(&mut self, item: &'a Box<[T]>, dst: &mut BytesMut) -> Result<(), Self::Error> {
251        let item: &[T] = item.as_ref();
252        self.encode(item, dst)
253    }
254}
255
256impl<E, T> Encoder<Arc<[T]>> for CoreVecEncoder<E>
257where
258    for<'a> E: Encoder<&'a T>,
259    for<'a> std::io::Error: From<<E as Encoder<&'a T>>::Error>,
260{
261    type Error = std::io::Error;
262
263    fn encode(&mut self, item: Arc<[T]>, dst: &mut BytesMut) -> Result<(), Self::Error> {
264        let item = item.as_ref();
265        let len = item.len();
266        dst.reserve(5 + len);
267        let len = u32::try_from(len)
268            .map_err(|err| std::io::Error::new(std::io::ErrorKind::InvalidInput, err))?;
269        Leb128Encoder.encode(len, dst)?;
270        for item in item {
271            self.0.encode(item, dst)?;
272        }
273        Ok(())
274    }
275}
276
277impl<'a, E, T> Encoder<&'a Arc<[T]>> for CoreVecEncoder<E>
278where
279    E: Encoder<&'a T>,
280    std::io::Error: From<E::Error>,
281{
282    type Error = std::io::Error;
283
284    fn encode(&mut self, item: &'a Arc<[T]>, dst: &mut BytesMut) -> Result<(), Self::Error> {
285        let item: &[T] = item.as_ref();
286        self.encode(item, dst)
287    }
288}
289
290/// Default maximum number of bytes decoders preallocate based on a length read from the input
291pub const DEFAULT_MAX_INITIAL_CAPACITY: usize = 1 << 20;
292
293/// [`core:vec`](https://webassembly.github.io/spec/core/binary/conventions.html#binary-vec) decoder
294///
295/// At most `MAX_INITIAL_CAPACITY` bytes are preallocated based on the vector length read from the input
296#[derive(Debug)]
297pub struct CoreVecDecoder<
298    T: Decoder,
299    const MAX_INITIAL_CAPACITY: usize = DEFAULT_MAX_INITIAL_CAPACITY,
300> {
301    dec: T,
302    ret: Vec<T::Item>,
303    cap: usize,
304}
305
306impl<T, const MAX_INITIAL_CAPACITY: usize> CoreVecDecoder<T, MAX_INITIAL_CAPACITY>
307where
308    T: Decoder,
309{
310    pub fn new(decoder: T) -> Self {
311        Self {
312            dec: decoder,
313            ret: Vec::default(),
314            cap: 0,
315        }
316    }
317
318    pub fn into_inner(self) -> T {
319        self.dec
320    }
321}
322
323impl<T, const MAX_INITIAL_CAPACITY: usize> CoreVecDecoder<T, MAX_INITIAL_CAPACITY>
324where
325    T: Decoder + Default,
326{
327    fn reset(&mut self) {
328        self.dec = T::default();
329        self.cap = 0;
330        self.ret = Vec::default();
331    }
332
333    fn decode_elements(
334        &mut self,
335        src: &mut BytesMut,
336        mut decode: impl FnMut(&mut T, &mut BytesMut) -> Result<Option<T::Item>, T::Error>,
337    ) -> Result<Option<Vec<T::Item>>, T::Error> {
338        if self.cap == 0 {
339            let Some(len) = Leb128DecoderU32.decode(src)? else {
340                return Ok(None);
341            };
342            if len == 0 {
343                return Ok(Some(Vec::default()));
344            }
345            let len = len
346                .try_into()
347                .map_err(|err| std::io::Error::new(std::io::ErrorKind::InvalidInput, err))?;
348            self.cap = len;
349            self.ret = Vec::with_capacity(
350                len.min(MAX_INITIAL_CAPACITY / mem::size_of::<T::Item>().max(1)),
351            );
352        }
353        while self.cap > 0 {
354            let v = match decode(&mut self.dec, src) {
355                Ok(Some(v)) => v,
356                Ok(None) => return Ok(None),
357                Err(err) => {
358                    self.reset();
359                    return Err(err);
360                }
361            };
362            self.ret.push(v);
363            self.cap = self.cap.saturating_sub(1);
364        }
365        Ok(Some(mem::take(&mut self.ret)))
366    }
367}
368
369impl<T, const MAX_INITIAL_CAPACITY: usize> Default for CoreVecDecoder<T, MAX_INITIAL_CAPACITY>
370where
371    T: Decoder + Default,
372{
373    fn default() -> Self {
374        Self::new(T::default())
375    }
376}
377
378impl<T, const MAX_INITIAL_CAPACITY: usize> Decoder for CoreVecDecoder<T, MAX_INITIAL_CAPACITY>
379where
380    T: Decoder + Default,
381{
382    type Item = Vec<T::Item>;
383    type Error = T::Error;
384
385    fn decode(&mut self, src: &mut BytesMut) -> Result<Option<Self::Item>, Self::Error> {
386        self.decode_elements(src, T::decode)
387    }
388
389    fn decode_eof(&mut self, src: &mut BytesMut) -> Result<Option<Self::Item>, Self::Error> {
390        match self.decode_elements(src, T::decode_eof)? {
391            Some(frame) => Ok(Some(frame)),
392            None if self.cap == 0 && src.is_empty() => Ok(None),
393            None => {
394                self.reset();
395                Err(std::io::Error::from(std::io::ErrorKind::UnexpectedEof).into())
396            }
397        }
398    }
399}
400
401/// [`core:vec`](https://webassembly.github.io/spec/core/binary/conventions.html#binary-vec)
402/// encoder optimized for vectors of byte-sized values
403#[derive(Copy, Clone, Debug, Default, Eq, PartialEq)]
404pub struct CoreVecEncoderBytes;
405
406impl<T: AsRef<[u8]>> Encoder<T> for CoreVecEncoderBytes {
407    type Error = std::io::Error;
408
409    fn encode(&mut self, item: T, dst: &mut BytesMut) -> Result<(), Self::Error> {
410        let item = item.as_ref();
411        let n = item.len();
412        let n = u32::try_from(n)
413            .map_err(|err| std::io::Error::new(std::io::ErrorKind::InvalidInput, err))?;
414        dst.reserve(item.len().saturating_add(5));
415        Leb128Encoder.encode(n, dst)?;
416        dst.extend_from_slice(item);
417        Ok(())
418    }
419}
420
421/// [`core:vec`](https://webassembly.github.io/spec/core/binary/conventions.html#binary-vec)
422/// decoder optimized for vectors of byte-sized values
423///
424/// At most `MAX_INITIAL_CAPACITY` bytes are preallocated based on the vector length read from the input
425#[derive(Debug)]
426pub struct CoreVecDecoderBytes<const MAX_INITIAL_CAPACITY: usize = DEFAULT_MAX_INITIAL_CAPACITY>(
427    usize,
428);
429
430impl<const MAX_INITIAL_CAPACITY: usize> Default for CoreVecDecoderBytes<MAX_INITIAL_CAPACITY> {
431    fn default() -> Self {
432        Self(0)
433    }
434}
435
436impl<const MAX_INITIAL_CAPACITY: usize> Decoder for CoreVecDecoderBytes<MAX_INITIAL_CAPACITY> {
437    type Item = Bytes;
438    type Error = std::io::Error;
439
440    fn decode(&mut self, src: &mut BytesMut) -> Result<Option<Self::Item>, Self::Error> {
441        if self.0 == 0 {
442            let Some(len) = Leb128DecoderU32.decode(src)? else {
443                return Ok(None);
444            };
445            if len == 0 {
446                return Ok(Some(Bytes::default()));
447            }
448            let len = len
449                .try_into()
450                .map_err(|err| std::io::Error::new(std::io::ErrorKind::InvalidInput, err))?;
451            self.0 = len;
452        }
453        if src.len() < self.0 {
454            src.reserve(self.0.saturating_sub(src.len()).min(MAX_INITIAL_CAPACITY));
455            return Ok(None);
456        }
457        let buf = src.split_to(self.0);
458        self.0 = 0;
459        Ok(Some(buf.freeze()))
460    }
461
462    fn decode_eof(&mut self, src: &mut BytesMut) -> Result<Option<Self::Item>, Self::Error> {
463        match self.decode(src)? {
464            Some(frame) => Ok(Some(frame)),
465            None => {
466                if self.0 == 0 && src.is_empty() {
467                    Ok(None)
468                } else {
469                    self.0 = 0;
470                    Err(std::io::ErrorKind::UnexpectedEof.into())
471                }
472            }
473        }
474    }
475}
476
477#[cfg(test)]
478mod tests {
479    use futures::{SinkExt as _, TryStreamExt as _};
480    use tokio_util::codec::{FramedRead, FramedWrite, LinesCodec};
481    use tracing::trace;
482
483    use super::*;
484
485    #[test_log::test]
486    fn vec_reset_on_eof() {
487        let mut dec = CoreVecDecoder::<CoreNameDecoder>::default();
488        let mut src = BytesMut::from(b"\x02\x01a\x02".as_slice());
489        let err = dec
490            .decode_eof(&mut src)
491            .expect_err("truncated vec must fail");
492        assert_eq!(err.kind(), std::io::ErrorKind::UnexpectedEof);
493        let mut src = BytesMut::from(b"\x01\x01b".as_slice());
494        assert_eq!(dec.decode(&mut src).unwrap().unwrap(), ["b"]);
495    }
496
497    #[test_log::test]
498    fn vec_inner_eof_value() {
499        let mut dec = CoreVecDecoder::<LinesCodec>::default();
500        let mut src = BytesMut::from(b"\x02a\nb".as_slice());
501        assert_eq!(dec.decode_eof(&mut src).unwrap().unwrap(), ["a", "b"]);
502
503        let mut dec = CoreVecDecoder::<crate::cm::U32Codec>::default();
504        let mut src = BytesMut::from(b"\x01\x80".as_slice());
505        let err = dec
506            .decode_eof(&mut src)
507            .expect_err("truncated vec must fail");
508        assert_eq!(err.kind(), std::io::ErrorKind::UnexpectedEof);
509    }
510
511    #[test_log::test]
512    fn bytes_reset_on_eof() {
513        let mut dec = <CoreVecDecoderBytes>::default();
514        let mut src = BytesMut::from(b"\x03ab".as_slice());
515        let err = dec
516            .decode_eof(&mut src)
517            .expect_err("truncated bytes must fail");
518        assert_eq!(err.kind(), std::io::ErrorKind::UnexpectedEof);
519        let mut src = BytesMut::from(b"\x01c".as_slice());
520        assert_eq!(dec.decode(&mut src).unwrap().unwrap(), "c");
521    }
522
523    #[test_log::test(tokio::test)]
524    async fn string() {
525        let mut s = String::new();
526        "\x04test"
527            .as_bytes()
528            .read_core_name(&mut s)
529            .await
530            .expect("failed to read string");
531        assert_eq!(s, "test");
532
533        let mut buf = vec![];
534        buf.write_core_name("test")
535            .await
536            .expect("failed to write string");
537        assert_eq!(buf, b"\x04test");
538
539        let mut tx = FramedWrite::new(Vec::new(), CoreNameEncoder);
540
541        trace!("sending `foo`");
542        tx.send("foo").await.expect("failed to send `foo`");
543
544        trace!("sending ``");
545        tx.send(String::default()).await.expect("failed to send ``");
546
547        trace!("sending `test`");
548        tx.send(&&&&&&"test").await.expect("failed to send `test`");
549
550        trace!("sending `bar`");
551        tx.send(Arc::from("bar"))
552            .await
553            .expect("failed to send `bar`");
554
555        trace!("sending `ƒ𐍈Ő`");
556        tx.send(&&String::from("ƒ𐍈Ő"))
557            .await
558            .expect("failed to send `ƒ𐍈Ő`");
559
560        trace!("sending `baz`");
561        tx.send(&&&Arc::from("baz"))
562            .await
563            .expect("failed to send `baz`");
564
565        let tx = tx.into_inner();
566        assert_eq!(
567            tx,
568            concat!("\x03foo", "\0", "\x04test", "\x03bar", "\x08ƒ𐍈Ő", "\x03baz").as_bytes()
569        );
570        let mut rx = FramedRead::new(tx.as_slice(), <CoreNameDecoder>::default());
571
572        trace!("reading `foo`");
573        let s = rx.try_next().await.expect("failed to get `foo`");
574        assert_eq!(s.as_deref(), Some("foo"));
575
576        trace!("reading ``");
577        let s = rx.try_next().await.expect("failed to get ``");
578        assert_eq!(s.as_deref(), Some(""));
579
580        trace!("reading `test`");
581        let s = rx.try_next().await.expect("failed to get `test`");
582        assert_eq!(s.as_deref(), Some("test"));
583
584        trace!("reading `bar`");
585        let s = rx.try_next().await.expect("failed to get `bar`");
586        assert_eq!(s.as_deref(), Some("bar"));
587
588        trace!("reading `ƒ𐍈Ő`");
589        let s = rx.try_next().await.expect("failed to get `ƒ𐍈Ő`");
590        assert_eq!(s.as_deref(), Some("ƒ𐍈Ő"));
591
592        trace!("reading `baz`");
593        let s = rx.try_next().await.expect("failed to get `baz`");
594        assert_eq!(s.as_deref(), Some("baz"));
595
596        let s = rx.try_next().await.expect("failed to get EOF");
597        assert_eq!(s, None);
598    }
599
600    #[test_log::test(tokio::test)]
601    async fn vec() {
602        let mut tx = FramedWrite::new(Vec::new(), CoreVecEncoder(CoreNameEncoder));
603
604        trace!("sending [`foo`, ``, `test`, `bar`, `ƒ𐍈Ő`, `baz`]");
605        tx.send(&["foo", "", "test", "bar", "ƒ𐍈Ő", "baz"])
606            .await
607            .expect("failed to send [`foo`, ``, `test`, `bar`, `ƒ𐍈Ő`, `baz`]");
608
609        trace!("sending [``]");
610        tx.send(&[""; 0]).await.expect("failed to send []");
611
612        trace!("sending [`test`]");
613        tx.send(&["test"]).await.expect("failed to send [`test`]");
614
615        trace!("sending [``]");
616        tx.send(&[""; 0]).await.expect("failed to send []");
617
618        let tx = tx.into_inner();
619        assert_eq!(
620            tx,
621            concat!(
622                concat!(
623                    "\x06",
624                    concat!("\x03foo", "\0", "\x04test", "\x03bar", "\x08ƒ𐍈Ő", "\x03baz")
625                ),
626                "\0",
627                concat!("\x01", "\x04test"),
628                "\0"
629            )
630            .as_bytes()
631        );
632        let mut rx = FramedRead::new(tx.as_slice(), CoreVecDecoder::<CoreNameDecoder>::default());
633
634        trace!("reading [`foo`, ``, `test`, `bar`, `baz`]");
635        let s = rx
636            .try_next()
637            .await
638            .expect("failed to get [`foo`, ``, `test`, `bar`, `baz`]");
639        assert_eq!(
640            s.as_deref(),
641            Some(
642                [
643                    "foo".to_string(),
644                    String::new(),
645                    "test".to_string(),
646                    "bar".to_string(),
647                    "ƒ𐍈Ő".to_string(),
648                    "baz".to_string()
649                ]
650                .as_slice()
651            )
652        );
653
654        trace!("reading []");
655        let s = rx.try_next().await.expect("failed to get []");
656        assert_eq!(s.as_deref(), Some([].as_slice()));
657
658        trace!("reading [`test`]");
659        let s = rx.try_next().await.expect("failed to get [`test`]");
660        assert_eq!(s.as_deref(), Some(["test".to_string()].as_slice()));
661
662        trace!("reading []");
663        let s = rx.try_next().await.expect("failed to get []");
664        assert_eq!(s.as_deref(), Some([].as_slice()));
665
666        let s = rx.try_next().await.expect("failed to get EOF");
667        assert_eq!(s, None);
668    }
669
670    #[test_log::test(tokio::test)]
671    async fn string_truncated() {
672        let mut s = String::from("x");
673        let err = b"\xff\xff\xff\xff\x0ftest"
674            .as_slice()
675            .read_core_name(&mut s)
676            .await
677            .expect_err("truncated string must fail");
678        assert_eq!(err.kind(), std::io::ErrorKind::UnexpectedEof);
679        assert_eq!(s, "x");
680    }
681
682    #[test]
683    fn vec_capped() {
684        let mut dec = CoreVecDecoder::<_, 64>::new(CoreNameDecoder::<64>::default());
685        let mut src = BytesMut::from(b"\xff\xff\xff\xff\x0f\xff\xff\xff\xff\x0f".as_slice());
686        assert!(dec.decode(&mut src).unwrap().is_none());
687        assert!(dec.ret.capacity() <= 64 / mem::size_of::<String>());
688        assert!(src.capacity() <= 128);
689    }
690
691    #[test]
692    fn vec_reset_on_error() {
693        let mut dec = CoreVecDecoder::<CoreNameDecoder>::default();
694        let mut src = BytesMut::from(b"\x03\x01a\x01\xff".as_slice());
695        dec.decode(&mut src).expect_err("invalid UTF-8 must fail");
696        assert_eq!(dec.ret.capacity(), 0);
697        let mut src = BytesMut::from(b"\x01\x01b".as_slice());
698        assert_eq!(dec.decode(&mut src).unwrap().unwrap(), ["b"]);
699    }
700}