rlb.rs 2.4 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697
  1. use alloc::vec::Vec;
  2. use platform::{Pal, Sys};
  3. use platform::types::*;
  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: 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. pub fn next(&mut self) -> Line {
  31. // Remove last line
  32. if let Some(newline) = self.newline {
  33. self.buf.drain(..newline + 1);
  34. }
  35. loop {
  36. // Exit if newline was read already
  37. self.newline = self.buf.iter().position(|b| *b == b'\n');
  38. if self.newline.is_some() {
  39. break;
  40. }
  41. let len = self.buf.len();
  42. if len >= self.buf.capacity() {
  43. self.buf.reserve(1024);
  44. }
  45. // Create buffer of what's left in the vector, uninitialized memory
  46. unsafe {
  47. let capacity = self.buf.capacity();
  48. self.buf.set_len(capacity);
  49. }
  50. let read = Sys::read(self.fd, &mut self.buf[len..]);
  51. let read_usize = read.max(0) as usize;
  52. // Remove all uninitialized memory that wasn't read
  53. unsafe {
  54. self.buf.set_len(len + read_usize);
  55. }
  56. self.read += read_usize;
  57. if read == 0 {
  58. return Line::EOF;
  59. }
  60. if read < 0 {
  61. return Line::Error;
  62. }
  63. }
  64. let newline = self.newline.unwrap(); // safe because it doesn't break the loop otherwise
  65. Line::Some(&self.buf[..newline])
  66. }
  67. /// Return the byte position of the start of the line
  68. pub fn line_pos(&self) -> usize {
  69. self.read - self.buf.len()
  70. }
  71. /// Seek to a byte position in the file
  72. pub fn seek(&mut self, pos: usize) -> off_t {
  73. let ret = lseek(self.fd, pos as i64, SEEK_SET);
  74. if ret != !0 {
  75. self.read = pos;
  76. }
  77. ret
  78. }
  79. }