ax_io/seek/mod.rs
1use crate::Result;
2
3mod impls;
4
5/// Enumeration of possible methods to seek within an I/O object.
6///
7/// It is used by the [`Seek`] trait.
8#[derive(Copy, PartialEq, Eq, Clone, Debug)]
9pub enum SeekFrom {
10 /// Sets the offset to the provided number of bytes.
11 Start(u64),
12
13 /// Sets the offset to the size of this object plus the specified number of
14 /// bytes.
15 ///
16 /// It is possible to seek beyond the end of an object, but it's an error to
17 /// seek before byte 0.
18 End(i64),
19
20 /// Sets the offset to the current position plus the specified number of
21 /// bytes.
22 ///
23 /// It is possible to seek beyond the end of an object, but it's an error to
24 /// seek before byte 0.
25 Current(i64),
26}
27
28/// Default [`Seek::stream_len`] implementation.
29pub fn default_stream_len<T: Seek + ?Sized>(this: &mut T) -> Result<u64> {
30 let old_pos = this.stream_position()?;
31 let len = this.seek(SeekFrom::End(0))?;
32
33 // Avoid seeking a third time when we were already at the end of the
34 // stream. The branch is usually way cheaper than a seek operation.
35 if old_pos != len {
36 this.seek(SeekFrom::Start(old_pos))?;
37 }
38
39 Ok(len)
40}
41
42/// The `Seek` trait provides a cursor which can be moved within a stream of
43/// bytes.
44///
45/// See [`std::io::Seek`] for more details.
46pub trait Seek {
47 /// Seek to an offset, in bytes, in a stream.
48 ///
49 /// A seek beyond the end of a stream is allowed, but behavior is defined
50 /// by the implementation.
51 ///
52 /// If the seek operation completed successfully,
53 /// this method returns the new position from the start of the stream.
54 /// That position can be used later with [`SeekFrom::Start`].
55 fn seek(&mut self, pos: SeekFrom) -> Result<u64>;
56
57 /// Rewind to the beginning of a stream.
58 ///
59 /// This is a convenience method, equivalent to `seek(SeekFrom::Start(0))`.
60 fn rewind(&mut self) -> Result<()> {
61 self.seek(SeekFrom::Start(0))?;
62 Ok(())
63 }
64
65 /// Returns the current seek position from the start of the stream.
66 ///
67 /// This is equivalent to `self.seek(SeekFrom::Current(0))`.
68 fn stream_position(&mut self) -> Result<u64> {
69 self.seek(SeekFrom::Current(0))
70 }
71
72 /// Returns the length of this stream (in bytes).
73 fn stream_len(&mut self) -> Result<u64> {
74 default_stream_len(self)
75 }
76
77 /// Seeks relative to the current position.
78 fn seek_relative(&mut self, offset: i64) -> Result<()> {
79 self.seek(SeekFrom::Current(offset))?;
80 Ok(())
81 }
82}