segsource/sources/
mod.rs

1use crate::{
2    error::{Error, Result},
3    segment::Segment,
4    Endidness,
5};
6#[cfg(not(feature = "std"))]
7use alloc::vec::Vec;
8#[cfg(feature = "std")]
9use std::path::Path;
10
11mod vec_source;
12pub use vec_source::VecSource;
13
14//mod segment_like;
15//pub use segment_like::*;
16
17#[cfg(feature = "with_bytes")]
18use bytes::Bytes;
19#[cfg(feature = "with_bytes")]
20mod bytes_source;
21
22#[cfg(feature = "with_bytes")]
23pub use bytes_source::BytesSource;
24
25#[cfg(feature = "memmap")]
26mod mmap;
27#[cfg(feature = "memmap")]
28pub use mmap::MappedFileSource;
29
30#[cfg(feature = "async")]
31use async_trait::async_trait;
32
33/// Sources own their own data and are used to generate [`Segment`]s. The following sources are
34/// included with segsource (although others can be implemented):
35///
36/// 1. [`VecSource`]: A source that stores its items as a simple `Vec`. This source is always
37///    available.
38/// 2. [`BytesSource`]: A source that uses a `Bytes` object from the wonderful `bytes` crate to
39///    store its data. This source can only use `u8`s as its item. Requires the `bytes` feature.
40/// 3. [`MappedFileSource`]: A source that stores its data using a memory mapped file. This source
41///    can only use `u8`s as its item. Requires the `mmap` feature.
42///
43/// When a [`Source`] creates a new [`Segment`], that segment will have the same initial offset and
44/// (if applicable) the same endidness as the source.
45pub trait Source: Sized + Sync + Send {
46    /// The type of item the [`Source`] and its generated [`Segment`]s will hold.
47    type Item;
48
49    /// Creates a new source using the data in the `Vec` for its data.
50    fn from_vec(items: Vec<Self::Item>) -> Result<Self> {
51        Self::from_vec_with_offset(items, 0)
52    }
53
54    /// Creates a new source with the provided initial offset, using the items in the`Vec` for its
55    /// data.
56    fn from_vec_with_offset(items: Vec<Self::Item>, initial_offset: usize) -> Result<Self>;
57
58    /// Checks to make sure that the provided offset is valid. If it is, then an `Ok(())` will be
59    /// returned. Otherwise, the appropriate error will be returned.
60    fn validate_offset(&self, offset: usize) -> Result<()> {
61        if offset < self.lower_offset_limit() {
62            Err(Error::OffsetTooSmall { offset })
63        } else if offset > self.upper_offset_limit() {
64            Err(Error::OffsetTooLarge { offset })
65        } else {
66            Ok(())
67        }
68    }
69
70    /// The amount of data in the reader. If the reader's size changes (which none of the
71    /// implementations currently do), then this should return how much data was *initially* in the
72    /// reader.
73    fn size(&self) -> usize;
74
75    /// The initial offset of the [`Source`]. For more information, see the **Offsets** section
76    /// of the [`Source`] documentation.
77    fn initial_offset(&self) -> usize;
78
79    /// Returns a single segment containing all data in the source.
80    fn all(&self) -> Result<Segment<Self::Item>> {
81        self.segment(self.lower_offset_limit(), self.upper_offset_limit())
82    }
83
84    /// Creates a segment from the start offset (inclusive) to the end offset (exclusive).
85    fn segment(&self, start: usize, end: usize) -> Result<Segment<Self::Item>>;
86
87    /// Gets a segment of n items, starting at the given offset.
88    fn get_n(&self, offset: usize, num_items: usize) -> Result<Segment<Self::Item>> {
89        self.validate_offset(offset)?;
90        self.validate_offset(offset + num_items)?;
91        self.segment(offset, offset + num_items)
92    }
93
94    /// Gets all items in the source before the provided offset (exclusive).
95    fn all_before(&self, offset: usize) -> Result<Segment<Self::Item>> {
96        self.validate_offset(offset)?;
97        self.get_n(self.lower_offset_limit(), offset)
98    }
99
100    /// Gets all items in the source after the provided offset (inclusive).
101    fn all_after(&self, offset: usize) -> Result<Segment<Self::Item>> {
102        self.validate_offset(offset)?;
103        self.get_n(offset, self.upper_offset_limit())
104    }
105
106    /// The lowest valid offset that can be requested.
107    #[inline]
108    fn lower_offset_limit(&self) -> usize {
109        self.initial_offset()
110    }
111
112    /// The highest valid offset that can be requested.
113    #[inline]
114    fn upper_offset_limit(&self) -> usize {
115        self.size() + self.initial_offset()
116    }
117}
118
119#[cfg_attr(feature = "async", async_trait)]
120/// Segsource is mostly meant to work with binary data (although it by no means has to). Because of
121/// this, sources can have some extra functionality when its item type is `u8`.
122pub trait U8Source: Source<Item = u8> {
123    /// The endidness of the source.
124    fn endidness(&self) -> Endidness;
125
126    /// Changes the default endidness. This does **not** change the endidness for any [`Segment`]s
127    /// that have already been created, but only for [`Segment`]s that are created in the future.
128    fn change_endidness(&mut self, endidness: Endidness);
129
130    /// Creates a new source using the the provided slice and [`Endidness`].
131    ///
132    /// Note: because sources own their data, this will copy the data from the provided slice.
133    #[inline]
134    fn from_u8_slice(slice: &[u8], endidness: Endidness) -> Result<Self> {
135        Self::from_u8_slice_with_offset(slice, 0, endidness)
136    }
137
138    /// Creates a new source using the the provided slice, [`Endidness`], and offset.
139    ///
140    /// Note: because sources own their data, this will copy the data from the provided slice.
141    fn from_u8_slice_with_offset(
142        slice: &[u8],
143        initial_offset: usize,
144        endidness: Endidness,
145    ) -> Result<Self>;
146
147    /// Creates a new source using the the provided vec and [`Endidness`].
148    #[inline]
149    fn from_u8_vec(items: Vec<u8>, endidness: Endidness) -> Result<Self> {
150        Self::from_u8_vec_with_offset(items, 0, endidness)
151    }
152
153    /// Creates a new source using the the provided vec, [`Endidness`], and offset.
154    #[inline]
155    fn from_u8_vec_with_offset(
156        items: Vec<u8>,
157        initial_offset: usize,
158        endidness: Endidness,
159    ) -> Result<Self> {
160        Self::from_u8_slice_with_offset(&items, initial_offset, endidness)
161    }
162
163    #[cfg(feature = "std")]
164    /// Creates a new source using the the provided file and [`Endidness`].
165    #[inline]
166    fn from_file<P: AsRef<Path>>(path: P, endidness: Endidness) -> Result<Self> {
167        Self::from_file_with_offset(path, 0, endidness)
168    }
169
170    #[cfg(feature = "std")]
171    /// Creates a new source using the the provided file, [`Endidness`], and offset.
172    fn from_file_with_offset<P: AsRef<Path>>(
173        path: P,
174        initial_offset: usize,
175        endidness: Endidness,
176    ) -> Result<Self>;
177
178    #[cfg(feature = "async")]
179    /// An async version of [`U8Source::from_file`].
180    #[inline]
181    async fn from_file_async<P>(path: P, endidness: Endidness) -> Result<Self>
182    where
183        P: AsRef<Path> + Sync + Send,
184    {
185        Self::from_file_with_offset_async(path, 0, endidness).await
186    }
187
188    #[cfg(feature = "async")]
189    /// An async version of [`U8Source::from_file_with_offset`].
190    async fn from_file_with_offset_async<P>(
191        path: P,
192        initial_offset: usize,
193        endidness: Endidness,
194    ) -> Result<Self>
195    where
196        P: AsRef<Path> + Sync + Send;
197
198    #[cfg(feature = "with_bytes")]
199    /// Creates a new source using the the provided Bytes and [`Endidness`].
200    #[inline]
201    fn from_bytes(bytes: Bytes, endidness: Endidness) -> Result<Self> {
202        Self::from_bytes_with_offset(bytes, 0, endidness)
203    }
204
205    #[cfg(feature = "with_bytes")]
206    /// Creates a new source using the the provided Bytes, [`Endidness`], and offset.
207    fn from_bytes_with_offset(
208        bytes: Bytes,
209        initial_offset: usize,
210        endidness: Endidness,
211    ) -> Result<Self>;
212}