rlb.rs 2.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102
  1. use alloc::vec::Vec;
  2. use platform::types::*;
  3. use platform::{Pal, Sys};
  4. use header::unistd::{lseek, SEEK_SET};
  5. /// Implements an `Iterator` which returns on either newline or EOF.
  6. #[derive(Clone)]
  7. pub struct RawLineBuffer {
  8. pub fd: c_int,
  9. buf: Vec<u8>,
  10. newline: Option<usize>,
  11. read: usize,
  12. }
  13. #[derive(PartialEq)]
  14. pub enum Line<'a> {
  15. Error,
  16. EOF,
  17. Some(&'a [u8]),
  18. }
  19. impl RawLineBuffer {
  20. pub const fn new(fd: c_int) -> Self {
  21. Self {
  22. fd,
  23. buf: Vec::new(),
  24. newline: None,
  25. read: 0,
  26. }
  27. }
  28. // Can't use iterators because we want to return a reference.
  29. // See https://stackoverflow.com/a/30422716/5069285
  30. #[allow(clippy::should_implement_trait)]
  31. pub fn next(&mut self) -> Line {
  32. // Remove last line
  33. if let Some(newline) = self.newline {
  34. self.buf.drain(..=newline);
  35. }
  36. loop {
  37. // Exit if newline was read already
  38. self.newline = self.buf.iter().position(|b| *b == b'\n');
  39. if self.newline.is_some() {
  40. break;
  41. }
  42. let len = self.buf.len();
  43. if len >= self.buf.capacity() {
  44. self.buf.reserve(1024);
  45. }
  46. // Create buffer of what's left in the vector, uninitialized memory
  47. unsafe {
  48. let capacity = self.buf.capacity();
  49. self.buf.set_len(capacity);
  50. }
  51. let read = Sys::read(self.fd, &mut self.buf[len..]);
  52. let read_usize = read.max(0) as usize;
  53. // Remove all uninitialized memory that wasn't read
  54. unsafe {
  55. self.buf.set_len(len + read_usize);
  56. }
  57. self.read += read_usize;
  58. if read == 0 {
  59. return if self.buf.is_empty() {
  60. Line::EOF
  61. } else {
  62. Line::Some(&self.buf)
  63. };
  64. }
  65. if read < 0 {
  66. return Line::Error;
  67. }
  68. }
  69. let newline = self.newline.unwrap(); // safe because it doesn't break the loop otherwise
  70. Line::Some(&self.buf[..newline])
  71. }
  72. /// Return the byte position of the start of the line
  73. pub fn line_pos(&self) -> usize {
  74. self.read - self.buf.len()
  75. }
  76. /// Seek to a byte position in the file
  77. pub fn seek(&mut self, pos: usize) -> off_t {
  78. let ret = lseek(self.fd, pos as i64, SEEK_SET);
  79. if ret != !0 {
  80. self.read = pos;
  81. }
  82. ret
  83. }
  84. }