1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
use super::*;

// # Safety:
//
//   - basic delegation
//
//   - `read_into_uninit_exact` is not overriden
unsafe
impl<R : ReadIntoUninit + ?Sized> ReadIntoUninit for &'_ mut R {
    #[inline]
    fn read_into_uninit<'buf> (
        self: &'_ mut Self,
        buf: Out<'buf, [u8]>,
    ) -> io::Result<&'buf mut [u8]>
    {
        (**self).read_into_uninit(buf)
    }
}

// # Safety
//
//   - `read_into_uninit` does return a prefix slice on success;
//
//   - `read_into_uninit_exact` is not overriden
unsafe
impl ReadIntoUninit for &'_ [u8] {
    #[inline]
    fn read_into_uninit<'buf> (
        self: &'_ mut Self,
        buf: Out<'buf, [u8]>,
    ) -> io::Result<&'buf mut [u8]>
    {
        let count = ::std::cmp::min(buf.len(), self.len());
        let (to_copy, remaining) = self.split_at(count);
        *self = remaining;

        // Taken from stdlib:
        // "First check if the amount of bytes we want to read is small:
        // `copy_from_slice` will generally expand to a call to `memcpy`, and
        // for a single byte the overhead is significant."
        if count == 1 {
            Ok( slice::from_mut(buf.get_out(0).unwrap().write(to_copy[0])) )
        } else {
            Ok( buf.get_out(.. count).unwrap().copy_from_slice(to_copy) )
        }
    }
}

macro_rules! impl_ReadIntoUninit_for_impl_BufRead {(
    $(
        for [$($generics:tt)*]
            $T:ty
        $(where {
            $($wc:tt)*
        })? ;
    )*
) => (
    $(
        // # Safety:
        //
        //   - delegates to `<&'_ [u8] as ReadIntoUninit>::read_into_uninit`
        //
        //   - `read_into_uninit_exact` is not overriden
        unsafe
        impl<$($generics)*> ReadIntoUninit
            for $T
        $(where
            $($wc)*
        )?
        {
            #[inline]
            fn read_into_uninit<'buf> (
                self: &'_ mut Self,
                buf: Out<'buf, [u8]>,
            ) -> io::Result<&'buf mut [u8]>
            {
                let buf = {
                    let mut read_buf: &[u8] = io::BufRead::fill_buf(self)?;
                    read_buf.read_into_uninit(buf)?
                };
                io::BufRead::consume(self, buf.len());
                Ok(buf)
            }

        }
    )*
)}

impl_ReadIntoUninit_for_impl_BufRead! {
    for [R : io::Read]
        io::BufReader<R>
    ;
    for [T : AsRef<[u8]>]
        io::Cursor<T>
    ;
    for []
        io::Empty
    ;
    for []
        io::StdinLock<'_>
    ;
    for [T : io::BufRead]
        io::Take<T>
    ;
}

// # Safety:
//
//   - basic delegation
//
//   - `read_into_uninit_exact` is not overriden
unsafe
impl<R : ReadIntoUninit + ?Sized> ReadIntoUninit for Box<R> {
    #[inline]
    fn read_into_uninit<'buf> (
        self: &'_ mut Self,
        buf: Out<'buf, [u8]>,
    ) -> io::Result<&'buf mut [u8]>
    {
        (**self).read_into_uninit(buf)
    }
}