multi_readers/_impl/
seek.rs

1use crate::MultiReaders;
2
3use std::io::{Seek, SeekFrom};
4impl<T: Seek> MultiReaders<T> {
5    fn len(&mut self) -> std::io::Result<u64> {
6        if self.len == 0 {
7            for r in &mut self.inner {
8                self.len += r.len()?;
9            }
10        }
11        Ok(self.len)
12    }
13
14    fn position(&mut self) -> std::io::Result<u64> {
15        let mut pos = 0;
16        for item in &mut self.inner[..self.pos] {
17            pos += item.len()?;
18        }
19        pos += self.inner[self.pos].stream_position()?;
20        Ok(pos)
21    }
22}
23
24impl<T: Seek> Seek for MultiReaders<T> {
25    fn seek(&mut self, pos: SeekFrom) -> std::io::Result<u64> {
26        if self.inner.len() == self.pos {
27            return Ok(0);
28        }
29        match pos {
30            SeekFrom::Start(s) => seek_start(self, s),
31            SeekFrom::End(e) => seek_end(self, e),
32            SeekFrom::Current(c) => seek_current(self, c),
33        }
34    }
35}
36
37fn seek_start<T: Seek>(r: &mut MultiReaders<T>, start: u64) -> std::io::Result<u64> {
38    let mut len = 0;
39    for i in 0..r.inner.len() {
40        let tmp = len;
41        len += r.inner[i].len()?;
42        if len >= start {
43            r.pos = i;
44            r.inner[i].seek(SeekFrom::Start(start - tmp))?;
45            for j in r.pos + 1..r.inner.len() {
46                r.inner[j].seek(SeekFrom::Start(0))?;
47            }
48            return Ok(start);
49        } else {
50            r.inner[i].seek(SeekFrom::End(0))?;
51        }
52    }
53    Ok(len)
54}
55
56fn seek_to_end<T: Seek>(r: &mut MultiReaders<T>) -> std::io::Result<u64> {
57    for item in &mut r.inner {
58        item.seek(SeekFrom::End(0))?;
59    }
60    r.len()
61}
62
63fn seek_end<T: Seek>(r: &mut MultiReaders<T>, end: i64) -> std::io::Result<u64> {
64    if end >= 0 {
65        seek_to_end(r)
66    } else {
67        let len = r.len()? as i64;
68        seek_start(r, (len + end) as _)
69    }
70}
71
72fn seek_current<T: Seek>(r: &mut MultiReaders<T>, current: i64) -> std::io::Result<u64> {
73    if current == 0 {
74        r.position()
75    } else {
76        let n = r.position()? as i64 + current;
77        let len = r.len()? as i64;
78        let n = n.max(0).min(len);
79        seek_start(r, n as u64)
80    }
81}