io_at/
lib.rs

1#[cfg(test)]
2extern crate tempfile;
3
4pub use std::io::Result;
5
6use std::ops::{Deref, DerefMut};
7use std::convert::From;
8use std::sync::Mutex;
9use std::io::{SeekFrom, Seek, Read, Write};
10
11/**
12 * Read data at an offset
13 *
14 * Note that compared to Read::read, ReadAt::read_at does not borrow T mutably as it does not need
15 * to modify an internal cursor.
16 */
17pub trait ReadAt {
18    fn read_at(&self, buf: &mut[u8], offs: u64) -> Result<usize>;
19}
20
21/**
22 * Write data at an offset
23 */
24pub trait WriteAt {
25    fn write_at(&mut self, buf: &[u8], offs: u64) -> Result<usize>;
26
27    /* XXX: this impl is very similar to Write::write_all, is there some way to generalize? */
28    fn write_all_at(&mut self, mut buf: &[u8], mut offs: u64) -> Result<()> {
29        use std::io::{Error, ErrorKind};
30        while !buf.is_empty() {
31            match self.write_at(buf, offs) {
32                Ok(0) => return Err(Error::new(ErrorKind::WriteZero,
33                                               "failed to write whole buffer")),
34                Ok(n) => {
35                    buf = &buf[n..];
36                    offs += n as u64;
37                },
38                Err(ref e) if e.kind() == ErrorKind::Interrupted => {}
39                Err(e) => return Err(e),
40            }
41        }
42        Ok(())
43    }
44}
45
46
47/*
48 * Adaptors:
49 */
50/*
51pub struct<T: WriteAt> RateLimitWrite<T> {
52    ts : u64;
53    bytes_per_sec : u64;
54    inner: T;
55}
56*/
57
58/**
59 * Adapt a WriteAt and/or ReadAt to a Write and/or Read by tracking a single internal offset and
60 * modifying it.
61 */
62#[derive(Debug, Eq, PartialEq)]
63pub struct Cursor<T> {
64    offs: u64,
65    inner: T,
66}
67
68impl<T> Cursor<T> {
69    pub fn new(v: T, first_offs: u64) -> Self {
70        Cursor { inner: v, offs: first_offs }
71    }
72}
73
74impl<T: WriteAt> Write for Cursor<T> {
75    fn write(&mut self, buf: &[u8]) -> Result<usize> {
76        let r = self.inner.write_at(buf, self.offs);
77        if let Ok(v) = r {
78            self.offs += v as u64;
79        }
80        r
81    }
82
83    fn flush(&mut self) -> Result<()> {
84        Ok(())
85    }
86}
87
88impl<T: ReadAt> Read for Cursor<T> {
89    fn read(&mut self, buf: &mut [u8]) -> Result<usize> {
90        let r = self.inner.read_at(buf, self.offs);
91        if let Ok(v) = r {
92            self.offs += v as u64;
93        }
94        r
95    }
96}
97
98#[test]
99fn do_t_cursor() {
100    use tempfile;
101    let f = tempfile::tempfile().unwrap();
102    let _at = Cursor::new(LockedSeek::from(f), 5);
103
104    /* TODO: test it */
105}
106
107/**
108 * Limit the maximum offset of a WriteAt and/or ReadAt.
109 *
110 * This can be useful when trying to simulate a fixed size item (like a block device) with a normal
111 * file.
112 */
113#[derive(Debug, Eq, PartialEq)]
114pub struct Take<T> {
115    max_offs: u64,
116    inner: T,
117}
118
119impl<T> Take<T> {
120    pub fn new(v: T, max_offs: u64) -> Self {
121        Take { max_offs : max_offs, inner: v }
122    }
123
124    pub fn len(&self) -> u64 {
125        self.max_offs
126    }
127}
128
129impl<T: ReadAt> ReadAt for Take<T> {
130    fn read_at(&self, buf: &mut[u8], offs: u64) -> Result<usize> {
131        let last = std::cmp::min(buf.len() as u64 + offs, self.max_offs);
132        if offs > last {
133            Ok(0)
134        } else {
135            self.inner.read_at(&mut buf[..(last - offs) as usize], offs)
136        }
137    }
138}
139
140impl<T: WriteAt> WriteAt for Take<T> {
141    fn write_at(&mut self, buf: &[u8], offs: u64) -> Result<usize> {
142        let last = std::cmp::min(buf.len() as u64 + offs, self.max_offs);
143        if offs > last {
144            Ok(0)
145        } else {
146            self.inner.write_at(&buf[..(last - offs) as usize], offs)
147        }
148    }
149}
150
151impl<T> Deref for Take<T> {
152    type Target = T;
153    fn deref<'a>(&'a self) -> &'a T {
154        &self.inner
155    }
156}
157
158impl<T> DerefMut for Take<T> {
159    fn deref_mut<'a>(&'a mut self) -> &'a mut T {
160        &mut self.inner
161    }
162}
163
164#[test]
165fn take_test_impl() {
166    let f = vec![];
167    let at = Take::new(f, 100);
168    test_impl(at);
169}
170
171#[test]
172fn take_test_specifics() {
173    /* Partial write */
174    let mut at = Take::new(vec![], 5);
175    assert_eq!(at.write_at(&[11u8, 2, 3, 4], 4).unwrap(), 1);
176
177    /* Partial read */
178    let mut res = [0u8; 4];
179    assert_eq!(at.read_at(&mut res, 4).unwrap(), 1);
180    assert_eq!(&res[..1], &[11]);
181
182    /* At the end none write */
183    assert_eq!(at.write_at(&[12u8, 13], 5).unwrap(), 0);
184
185    /* At the end none read */
186    assert_eq!(at.read_at(&mut res, 5).unwrap(), 0);
187
188    /* Past the end none write */
189    assert_eq!(at.write_at(&[12u8, 13], 6).unwrap(), 0);
190
191    /* Past the end none read */
192    assert_eq!(at.read_at(&mut res, 6).unwrap(), 0);
193}
194
195/**
196 * Limit the amount of data accepted in a single call to WriteAt (ReadAt is unaffected)
197 *
198 * This is primarily useful for testing that handling of incomplete writes work properly.
199 */
200#[derive(Debug, Eq, PartialEq)]
201pub struct BlockLimitWrite<T: WriteAt> {
202    max_per_block: usize,
203    inner: T,
204}
205
206impl<T: WriteAt> BlockLimitWrite<T> {
207    pub fn new(v: T, max_per_block: usize) -> Self {
208        BlockLimitWrite { max_per_block: max_per_block, inner: v }
209    }
210}
211
212impl<T: WriteAt + ReadAt> ReadAt for BlockLimitWrite<T> {
213    fn read_at(&self, buf: &mut[u8], offs: u64) -> Result<usize> {
214        self.inner.read_at(buf, offs)
215    }
216}
217
218impl<T: WriteAt> WriteAt for BlockLimitWrite<T> {
219    fn write_at(&mut self, buf: &[u8], offs: u64) -> Result<usize> {
220        self.inner.write_at(&buf[..std::cmp::min(buf.len(), self.max_per_block)], offs)
221    }
222}
223
224impl<T: WriteAt> Deref for BlockLimitWrite<T> {
225    type Target = T;
226    fn deref<'a>(&'a self) -> &'a T {
227        &self.inner
228    }
229}
230
231impl<T: WriteAt> DerefMut for BlockLimitWrite<T> {
232    fn deref_mut<'a>(&'a mut self) -> &'a mut T {
233        &mut self.inner
234    }
235}
236
237#[test]
238fn do_t_block_limit() {
239    use tempfile;
240    let f = tempfile::tempfile().unwrap();
241    let at = BlockLimitWrite::new(LockedSeek::from(f), 2);
242    test_impl(at);
243
244    let f = tempfile::tempfile().unwrap();
245    let mut at = BlockLimitWrite::new(LockedSeek::from(f), 2);
246    assert_eq!(at.write_at(&[1u8, 2, 3], 0).unwrap(), 2);
247}
248
249/**
250 * Allow a Seek + (Read and/or Write) to impliment WriteAt and/or ReadAt
251 *
252 * While in most cases more specific adaptations will be more efficient, this allows any Seek to
253 * impliment WriteAt or ReadAt with not additional restrictions.
254 */
255pub struct LockedSeek<T: Seek> {
256    inner: Mutex<T>,
257}
258
259/* FIXME: only allow for if T is also Read || Write */
260impl<T: Seek> From<T> for LockedSeek<T> {
261    fn from(v: T) -> Self {
262        LockedSeek { inner: Mutex::new(v) }
263    }
264}
265
266impl<T: Seek + Read> ReadAt for LockedSeek<T> {
267    fn read_at(&self, buf: &mut[u8], offs: u64) -> Result<usize> {
268        let mut f = self.inner.lock().unwrap();
269        try!(f.seek(SeekFrom::Start(offs)));
270        f.read(buf)
271    }
272}
273
274impl<T: Seek + Write> WriteAt for LockedSeek<T> {
275    fn write_at(&mut self, buf: &[u8], offs: u64) -> Result<usize> {
276        let mut f = self.inner.lock().unwrap();
277        try!(f.seek(SeekFrom::Start(offs)));
278        f.write(buf)
279    }
280}
281
282#[test]
283fn do_t_locked_seek() {
284    use tempfile;
285    let f = tempfile::tempfile().unwrap();
286    let at = LockedSeek::from(f);
287    test_impl(at);
288}
289
290/// Use an offset as the base for all ReadAt and WriteAt accesses. Where `Take` modifies then end,
291/// `At` modifies the start.
292#[derive(Debug, Eq, PartialEq)]
293pub struct At<T> {
294    offs: u64,
295    inner: T,
296}
297
298impl<T> At<T> {
299    pub fn new(v: T, offs: u64) -> Self {
300        At { offs : offs, inner: v }
301    }
302}
303
304impl<T: ReadAt> ReadAt for At<T> {
305    fn read_at(&self, buf: &mut[u8], offs: u64) -> Result<usize> {
306        self.inner.read_at(buf, offs + self.offs)
307    }
308}
309
310impl<T: WriteAt> WriteAt for At<T> {
311    fn write_at(&mut self, buf: &[u8], offs: u64) -> Result<usize> {
312        self.inner.write_at(buf, offs + self.offs)
313    }
314}
315
316impl<T> Deref for At<T> {
317    type Target = T;
318    fn deref<'a>(&'a self) -> &'a T {
319        &self.inner
320    }
321}
322
323impl<T> DerefMut for At<T> {
324    fn deref_mut<'a>(&'a mut self) -> &'a mut T {
325        &mut self.inner
326    }
327}
328
329#[test]
330fn at_test_impl() {
331    let mut f = vec![1u8, 1];
332    {
333        let mut at = At::new(&mut f, 1);
334        test_impl(&mut at);
335    }
336
337    f[0] = 1;
338    f[1] = 1;
339
340    {
341        let mut at = At::new(&mut f, 1);
342        at.write_at(&[5], 0).unwrap();
343    }
344
345    assert_eq!(f[0], 1);
346    assert_eq!(f[1], 5);
347}
348
349#[cfg(test)]
350fn test_impl<T: ReadAt + WriteAt>(mut at: T) {
351    let x = [1u8, 4, 9, 5];
352
353    /* write at start */
354    at.write_all_at(&x, 0).unwrap();
355    let mut res = [0u8; 4];
356
357    /* read at start */
358    assert_eq!(at.read_at(&mut res, 0).unwrap(), 4);
359    assert_eq!(&res, &x);
360
361    /* read at middle */
362    assert_eq!(at.read_at(&mut res[0..3], 1).unwrap(), 3);
363    assert_eq!(&res[..3], &x[1..]);
364
365    /* write at middle */
366    at.write_all_at(&x, 1).unwrap();
367
368    assert_eq!(at.read_at(&mut res, 0).unwrap(), 4);
369    assert_eq!(&res, &[1u8, 1, 4, 9]);
370
371    assert_eq!(at.read_at(&mut res[0..1], 4).unwrap(), 1);
372    assert_eq!(&res[..1], &[5u8]);
373
374    at.write_all_at(&x, 10).unwrap();
375    assert_eq!(at.read_at(&mut res, 10).unwrap(), 4);
376    assert_eq!(&res, &[1u8, 4, 9, 5]);
377
378    at.write_all_at(&x, 9).unwrap();
379    assert_eq!(at.read_at(&mut res, 9).unwrap(), 4);
380    assert_eq!(&res, &[1u8, 4, 9, 5]);
381
382}
383
384/**
385 * OS specific implimentations of WriteAt and/or ReadAt
386 */
387#[cfg(any(unix, windows))]
388pub mod os;
389
390mod slice;
391mod vec;
392mod refs;