Push a byte slice onto the ring-buffer. Either the entire source slice will be pushed to the ring-buffer, or none of it, if there isn't enough room, in which case `Err(Error::TxBufFull)` is returned.
(&mut self, src: &[u8])
| 48 | /// there isn't enough room, in which case `Err(Error::TxBufFull)` is returned. |
| 49 | /// |
| 50 | pub fn push(&mut self, src: &[u8]) -> Result<()> { |
| 51 | // Error out if there's no room to push the entire slice. |
| 52 | if self.len() + src.len() > Self::SIZE { |
| 53 | return Err(Error::TxBufFull); |
| 54 | } |
| 55 | |
| 56 | let data = self |
| 57 | .data |
| 58 | .get_or_insert_with(|| vec![0u8; Self::SIZE].into_boxed_slice()); |
| 59 | |
| 60 | // Buffer head, as an offset into the data slice. |
| 61 | let head_ofs = self.head.0 as usize % Self::SIZE; |
| 62 | |
| 63 | // Pushing a slice to this buffer can take either one or two slice copies: - one copy, |
| 64 | // if the slice fits between `head_ofs` and `Self::SIZE`; or - two copies, if the |
| 65 | // ring-buffer head wraps around. |
| 66 | |
| 67 | // First copy length: we can only go from the head offset up to the total buffer size. |
| 68 | let len = std::cmp::min(Self::SIZE - head_ofs, src.len()); |
| 69 | data[head_ofs..(head_ofs + len)].copy_from_slice(&src[..len]); |
| 70 | |
| 71 | // If the slice didn't fit, the buffer head will wrap around, and pushing continues |
| 72 | // from the start of the buffer (`&self.data[0]`). |
| 73 | if len < src.len() { |
| 74 | data[..(src.len() - len)].copy_from_slice(&src[len..]); |
| 75 | } |
| 76 | |
| 77 | // Either way, we've just pushed exactly `src.len()` bytes, so that's the amount by |
| 78 | // which the (wrapping) buffer head needs to move forward. |
| 79 | self.head += Wrapping(src.len() as u32); |
| 80 | |
| 81 | Ok(()) |
| 82 | } |
| 83 | |
| 84 | /// Flush the contents of the ring-buffer to a writable stream. |
| 85 | /// |