1use std::{
2 cmp,
3 io::{Read, Result, Write},
4 ptr,
5};
6
7use super::{Buffer, Token, TokenType};
8
9fn copy_memory(src: &[u8], dst: &mut [u8]) {
10 let len_src = src.len();
11 assert!(dst.len() >= len_src);
12 unsafe {
15 ptr::copy_nonoverlapping(src.as_ptr(), dst.as_mut_ptr(), len_src);
16 }
17}
18
19pub struct TokenReader<'a, I: IntoIterator<Item = Token>> {
25 iter: I::IntoIter,
26 src: Option<&'a str>,
27 buf: Vec<u8>,
28 ofs: usize,
29}
30
31impl<'a, I: IntoIterator<Item = Token>> TokenReader<'a, I> {
32 pub fn new(iter: I, source: Option<&'a str>) -> TokenReader<'a, I> {
40 TokenReader {
41 iter: iter.into_iter(),
42 src: source,
43 buf: Vec::with_capacity(128),
44 ofs: 0,
45 }
46 }
47}
48
49impl<'a, I: IntoIterator<Item = Token>> Read for TokenReader<'a, I> {
50 fn read(&mut self, buf: &mut [u8]) -> Result<usize> {
51 if buf.is_empty() {
52 return Ok(0);
53 }
54
55 let mut bl = buf.len();
57 if !self.buf.is_empty() {
58 let btc = cmp::min(self.buf.len() - self.ofs, buf.len());
59 copy_memory(&self.buf[self.ofs..self.ofs + btc], buf);
60 bl -= btc;
61 self.ofs += btc;
62 if self.ofs == self.buf.len() {
63 self.buf.clear();
64 self.ofs = 0;
65 }
66 }
67 if bl == 0 {
68 return Ok(buf.len());
69 }
70
71 while bl > 0 {
73 match self.iter.next() {
74 None => return Ok(buf.len() - bl),
75 Some(t) => {
76 let bytes: &[u8] = match t.kind {
77 TokenType::String | TokenType::Number => match t.buf {
78 Buffer::MultiByte(ref b) => &b,
79 Buffer::Span(ref s) => match self.src {
80 Some(b) => b[s.first as usize..s.end as usize].as_bytes(),
81 None => panic!("Must set source if tokens don't provide byter buffers"),
82 },
83 },
84 TokenType::Invalid => b"",
85 _ => t.kind.as_ref().as_bytes(),
86 };
87 let btc = cmp::min(bytes.len(), bl);
88 let ofs = buf.len() - bl;
89 copy_memory(&bytes[..btc], &mut buf[ofs..ofs + btc]);
90 bl -= btc;
91
92 if btc < bytes.len() {
93 debug_assert!(bl == 0);
94 self.buf.write_all(&bytes[btc..])?;
95 }
96
97 if bl == 0 {
98 return Ok(buf.len());
99 }
100 }
101 } } unreachable!();
104 }
105}