positioned_io_preview/
byteio.rs

1use std::marker::PhantomData;
2use std::io;
3use std::io::{Read, Write};
4
5use byteorder::{ByteOrder, ReadBytesExt, WriteBytesExt};
6
7use super::{ReadAt, WriteAt};
8
9/// Extends `ReadAt` with methods for reading numbers at offsets.
10///
11/// For most of these methods, you need to explicitly add a `ByteOrder`
12/// type parameter. Similar to [`byteorder::ReadBytesExt`][byteorder].
13///
14/// # Examples
15///
16/// Read an integer from the middle of a byte array:
17///
18/// ```rust
19/// # extern crate positioned_io_preview as positioned_io;
20/// # extern crate byteorder;
21/// # use std::io;
22/// use byteorder::BigEndian;
23/// use positioned_io::ReadBytesAtExt;
24///
25/// # fn try_main() -> io::Result<()> {
26/// let buf = [0, 5, 254, 212, 0, 3];
27/// let n = buf.as_ref().read_i16_at::<BigEndian>(2)?;
28/// assert_eq!(n, -300);
29/// # Ok(())
30/// # }
31/// # fn main() { try_main().unwrap() }
32/// ```
33///
34/// [byteorder]: https://docs.rs/byteorder/1.2/byteorder/trait.ReadBytesExt.html
35pub trait ReadBytesAtExt: ReadAt {
36    /// Reads an unsigned 8-bit integer at an offset.
37    #[inline]
38    fn read_u8_at(&self, pos: u64) -> io::Result<u8> {
39        let mut buf = [0; 1];
40        self.read_exact_at(pos, &mut buf)?;
41        Ok(buf[0])
42    }
43
44    /// Reads a signed 8-bit integer at an offset.
45    #[inline]
46    fn read_i8_at(&self, pos: u64) -> io::Result<i8> {
47        let mut buf = [0; 1];
48        self.read_exact_at(pos, &mut buf)?;
49        Ok(buf[0] as i8)
50    }
51
52    /// Reads an unsigned 16-bit integer at an offset.
53    #[inline]
54    fn read_u16_at<T: ByteOrder>(&self, pos: u64) -> io::Result<u16> {
55        let mut buf = [0; 2];
56        self.read_exact_at(pos, &mut buf)?;
57        Ok(T::read_u16(&buf))
58    }
59
60    /// Reads a signed 16-bit integer at an offset.
61    #[inline]
62    fn read_i16_at<T: ByteOrder>(&self, pos: u64) -> io::Result<i16> {
63        let mut buf = [0; 2];
64        self.read_exact_at(pos, &mut buf)?;
65        Ok(T::read_i16(&buf))
66    }
67
68    /// Reads an unsigned 32-bit integer at an offset.
69    #[inline]
70    fn read_u32_at<T: ByteOrder>(&self, pos: u64) -> io::Result<u32> {
71        let mut buf = [0; 4];
72        self.read_exact_at(pos, &mut buf)?;
73        Ok(T::read_u32(&buf))
74    }
75
76    /// Reads a signed 32-bit integer at an offset.
77    #[inline]
78    fn read_i32_at<T: ByteOrder>(&self, pos: u64) -> io::Result<i32> {
79        let mut buf = [0; 4];
80        self.read_exact_at(pos, &mut buf)?;
81        Ok(T::read_i32(&buf))
82    }
83
84    /// Reads an unsigned 64-bit integer at an offset.
85    #[inline]
86    fn read_u64_at<T: ByteOrder>(&self, pos: u64) -> io::Result<u64> {
87        let mut buf = [0; 8];
88        self.read_exact_at(pos, &mut buf)?;
89        Ok(T::read_u64(&buf))
90    }
91
92    /// Reads a signed 64-bit integer at an offset.
93    #[inline]
94    fn read_i64_at<T: ByteOrder>(&self, pos: u64) -> io::Result<i64> {
95        let mut buf = [0; 8];
96        self.read_exact_at(pos, &mut buf)?;
97        Ok(T::read_i64(&buf))
98    }
99
100    /// Reads an unsigned `nbytes`-bit integer at an offset.
101    #[inline]
102    fn read_uint_at<T: ByteOrder>(&self, pos: u64, nbytes: usize) -> io::Result<u64> {
103        let mut buf = [0; 8];
104        self.read_exact_at(pos, &mut buf[..nbytes])?;
105        Ok(T::read_uint(&buf[..nbytes], nbytes))
106    }
107
108    /// Reads a signed `nbytes`-bit integer at an offset.
109    #[inline]
110    fn read_int_at<T: ByteOrder>(&self, pos: u64, nbytes: usize) -> io::Result<i64> {
111        let mut buf = [0; 8];
112        self.read_exact_at(pos, &mut buf[..nbytes])?;
113        Ok(T::read_int(&buf[..nbytes], nbytes))
114    }
115
116    /// Reads a single-precision floating point number at an offset.
117    #[inline]
118    fn read_f32_at<T: ByteOrder>(&self, pos: u64) -> io::Result<f32> {
119        let mut buf = [0; 4];
120        self.read_exact_at(pos, &mut buf)?;
121        Ok(T::read_f32(&buf))
122    }
123
124    /// Reads a double-precision floating point number at an offset.
125    #[inline]
126    fn read_f64_at<T: ByteOrder>(&self, pos: u64) -> io::Result<f64> {
127        let mut buf = [0; 8];
128        self.read_exact_at(pos, &mut buf)?;
129        Ok(T::read_f64(&buf))
130    }
131}
132
133/// Extends `WriteAt` with methods for writing numbers at offsets.
134///
135/// For most of these methods, you need to explicitly add a `ByteOrder` type
136/// parameter. Similar to [`byteorder::WriteBytesExt`][byteorder].
137///
138/// # Examples
139///
140/// Write an integer to the middle of a byte array:
141///
142/// ```rust
143/// # extern crate positioned_io_preview as positioned_io;
144/// # extern crate byteorder;
145/// # use std::io;
146/// use byteorder::BigEndian;
147/// use positioned_io::WriteBytesAtExt;
148///
149/// # fn try_main() -> io::Result<()> {
150/// let mut buf = [0; 6];
151/// buf.as_mut().write_u16_at::<BigEndian>(2, 300)?;
152/// assert_eq!(buf, [0, 0, 1, 44, 0, 0]);
153/// # Ok(())
154/// # }
155/// # fn main() { try_main().unwrap() }
156/// ```
157///
158/// [byteorder]: https://docs.rs/byteorder/1.2/byteorder/trait.WriteBytesExt.html
159pub trait WriteBytesAtExt: WriteAt {
160    /// Writes an unsigned 8-bit integer to an offset.
161    #[inline]
162    fn write_u8_at(&mut self, pos: u64, n: u8) -> io::Result<()> {
163        self.write_all_at(pos, &[n])
164    }
165
166    /// Writes a signed 8-bit integer to an offset.
167    #[inline]
168    fn write_i8_at(&mut self, pos: u64, n: i8) -> io::Result<()> {
169        self.write_all_at(pos, &[n as u8])
170    }
171
172    /// Writes an unsigned 16-bit integer to an offset.
173    #[inline]
174    fn write_u16_at<T: ByteOrder>(&mut self, pos: u64, n: u16) -> io::Result<()> {
175        let mut buf = [0; 2];
176        T::write_u16(&mut buf, n);
177        self.write_all_at(pos, &buf)
178    }
179
180    /// Writes a signed 16-bit integer to an offset.
181    #[inline]
182    fn write_i16_at<T: ByteOrder>(&mut self, pos: u64, n: i16) -> io::Result<()> {
183        let mut buf = [0; 2];
184        T::write_i16(&mut buf, n);
185        self.write_all_at(pos, &buf)
186    }
187
188    /// Writes an unsigned 32-bit integer to an offset.
189    #[inline]
190    fn write_u32_at<T: ByteOrder>(&mut self, pos: u64, n: u32) -> io::Result<()> {
191        let mut buf = [0; 4];
192        T::write_u32(&mut buf, n);
193        self.write_all_at(pos, &buf)
194    }
195
196    /// Writes a signed 32-bit integer to an offset.
197    #[inline]
198    fn write_i32_at<T: ByteOrder>(&mut self, pos: u64, n: i32) -> io::Result<()> {
199        let mut buf = [0; 4];
200        T::write_i32(&mut buf, n);
201        self.write_all_at(pos, &buf)
202    }
203
204    /// Writes an unsigned 64-bit integer to an offset.
205    #[inline]
206    fn write_u64_at<T: ByteOrder>(&mut self, pos: u64, n: u64) -> io::Result<()> {
207        let mut buf = [0; 8];
208        T::write_u64(&mut buf, n);
209        self.write_all_at(pos, &buf)
210    }
211
212    /// Writes a signed 64-bit integer to an offset.
213    #[inline]
214    fn write_i64_at<T: ByteOrder>(&mut self, pos: u64, n: i64) -> io::Result<()> {
215        let mut buf = [0; 8];
216        T::write_i64(&mut buf, n);
217        self.write_all_at(pos, &buf)
218    }
219
220    /// Writes an unsigned `nbytes`-bit integer to an offset.
221    #[inline]
222    fn write_uint_at<T: ByteOrder>(&mut self, pos: u64, n: u64, nbytes: usize) -> io::Result<()> {
223        let mut buf = [0; 8];
224        T::write_uint(&mut buf, n, nbytes);
225        self.write_all_at(pos, &buf[..nbytes])
226    }
227
228    /// Writes a signed `nbytes`-bit integer to an offset.
229    #[inline]
230    fn write_int_at<T: ByteOrder>(&mut self, pos: u64, n: i64, nbytes: usize) -> io::Result<()> {
231        let mut buf = [0; 8];
232        T::write_int(&mut buf, n, nbytes);
233        self.write_all_at(pos, &buf[..nbytes])
234    }
235
236    /// Writes a single-precision floating point number to an offset.
237    #[inline]
238    fn write_f32_at<T: ByteOrder>(&mut self, pos: u64, n: f32) -> io::Result<()> {
239        let mut buf = [0; 4];
240        T::write_f32(&mut buf, n);
241        self.write_all_at(pos, &buf)
242    }
243
244    /// Writes a double-precision floating point number to an offset.
245    #[inline]
246    fn write_f64_at<T: ByteOrder>(&mut self, pos: u64, n: f64) -> io::Result<()> {
247        let mut buf = [0; 8];
248        T::write_f64(&mut buf, n);
249        self.write_all_at(pos, &buf)
250    }
251}
252
253// Implement for everything that does positioned I/O.
254impl<R: ReadAt> ReadBytesAtExt for R {}
255impl<W: WriteAt> WriteBytesAtExt for W {}
256
257/// Read or write with a given inherent byte-order.
258///
259/// If you know that you'll always be using a single endianness, an instance of
260/// `ByteIo` will allow you to omit the endian specifier on every read or write.
261///
262/// # Examples
263///
264/// ```rust
265/// # extern crate byteorder;
266/// # extern crate positioned_io_preview as positioned_io;
267/// #
268/// # use std::io;
269/// #
270/// # fn try_main() -> io::Result<()> {
271/// use byteorder::BigEndian;
272/// use positioned_io::ByteIo;
273///
274/// let mut buf = [0; 8];
275///
276/// {
277///     let mut io : ByteIo<_, BigEndian> = ByteIo::new(&mut buf[..]);
278///     // All writes will automatically be BigEndian.
279///     io.write_u16(300)?;
280///     io.write_u32(1_000_000)?;
281///     io.write_i16(-1)?;
282/// }
283///
284/// assert_eq!(buf, [1, 44, 0, 15, 66, 64, 255, 255]);
285/// #     Ok(())
286/// # }
287/// #
288/// # fn main() {
289/// #     try_main().unwrap()
290/// # }
291/// ```
292#[derive(Debug, Clone)]
293pub struct ByteIo<I, E: ByteOrder> {
294    io: I,
295    endianness: PhantomData<E>,
296}
297
298impl<I, E: ByteOrder> ByteIo<I, E> {
299    /// Create a new `ByteIo` from some sort of reader or writer.
300    ///
301    /// You will need to specify the byte-order when creating a `ByteIo`.
302    ///
303    /// # Examples
304    ///
305    /// ```rust
306    /// # extern crate positioned_io_preview as positioned_io;
307    /// # extern crate byteorder;
308    /// use byteorder::BigEndian;
309    /// use positioned_io::ByteIo;
310    ///
311    /// # fn main() {
312    /// let buf = [0; 10];
313    /// // Add a type specifier for the byte order.
314    /// let io : ByteIo<_, BigEndian> = ByteIo::new(&buf[..]);
315    /// # }
316    /// ```
317    #[inline]
318    pub fn new(io: I) -> Self {
319        ByteIo { io, endianness: PhantomData }
320    }
321
322    /// Returns the underlying reader or writer.
323    #[inline]
324    pub fn into_inner(self) -> I {
325        self.io
326    }
327
328    /// Borrows the underlying reader or writer.
329    #[inline]
330    pub fn get_ref(&self) -> &I {
331        &self.io
332    }
333
334    /// Mutably borrows the underlying reader or writer.
335    #[inline]
336    pub fn get_mut(&mut self) -> &mut I {
337        &mut self.io
338    }
339}
340
341impl<I: Read, E: ByteOrder> Read for ByteIo<I, E> {
342    #[inline]
343    fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
344        self.io.read(buf)
345    }
346}
347
348impl<I: Write, E: ByteOrder> Write for ByteIo<I, E> {
349    #[inline]
350    fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
351        self.io.write(buf)
352    }
353
354    #[inline]
355    fn flush(&mut self) -> io::Result<()> {
356        self.io.flush()
357    }
358}
359
360impl<I: ReadAt, E: ByteOrder> ReadAt for ByteIo<I, E> {
361    #[inline]
362    fn read_at(&self, pos: u64, buf: &mut [u8]) -> io::Result<usize> {
363        self.io.read_at(pos, buf)
364    }
365}
366
367impl<I: WriteAt, E: ByteOrder> WriteAt for ByteIo<I, E> {
368    #[inline]
369    fn write_at(&mut self, pos: u64, buf: &[u8]) -> io::Result<usize> {
370        self.io.write_at(pos, buf)
371    }
372
373    #[inline]
374    fn flush(&mut self) -> io::Result<()> {
375        self.io.flush()
376    }
377}
378
379impl<I: Read, E: ByteOrder> ByteIo<I, E> {
380    #[inline]
381    pub fn read_u8(&mut self) -> io::Result<u8> {
382        self.io.read_u8()
383    }
384
385    #[inline]
386    pub fn read_i8(&mut self) -> io::Result<i8> {
387        self.io.read_i8()
388    }
389
390    #[inline]
391    pub fn read_u16(&mut self) -> io::Result<u16> {
392        self.io.read_u16::<E>()
393    }
394
395    #[inline]
396    pub fn read_i16(&mut self) -> io::Result<i16> {
397        self.io.read_i16::<E>()
398    }
399
400    #[inline]
401    pub fn read_u32(&mut self) -> io::Result<u32> {
402        self.io.read_u32::<E>()
403    }
404
405    #[inline]
406    pub fn read_i32(&mut self) -> io::Result<i32> {
407        self.io.read_i32::<E>()
408    }
409
410    #[inline]
411    pub fn read_u64(&mut self) -> io::Result<u64> {
412        self.io.read_u64::<E>()
413    }
414
415    #[inline]
416    pub fn read_i64(&mut self) -> io::Result<i64> {
417        self.io.read_i64::<E>()
418    }
419
420    #[inline]
421    pub fn read_uint(&mut self, nbytes: usize) -> io::Result<u64> {
422        self.io.read_uint::<E>(nbytes)
423    }
424
425    #[inline]
426    pub fn read_int(&mut self, nbytes: usize) -> io::Result<i64> {
427        self.io.read_int::<E>(nbytes)
428    }
429
430    #[inline]
431    pub fn read_f32(&mut self) -> io::Result<f32> {
432        self.io.read_f32::<E>()
433    }
434
435    #[inline]
436    pub fn read_f64(&mut self) -> io::Result<f64> {
437        self.io.read_f64::<E>()
438    }
439}
440
441impl<I: Write, E: ByteOrder> ByteIo<I, E> {
442    #[inline]
443    pub fn write_u8(&mut self, n: u8) -> io::Result<()> {
444        self.io.write_u8(n)
445    }
446
447    #[inline]
448    pub fn write_i8(&mut self, n: i8) -> io::Result<()> {
449        self.io.write_i8(n)
450    }
451
452    #[inline]
453    pub fn write_u16(&mut self, n: u16) -> io::Result<()> {
454        self.io.write_u16::<E>(n)
455    }
456
457    #[inline]
458    pub fn write_i16(&mut self, n: i16) -> io::Result<()> {
459        self.io.write_i16::<E>(n)
460    }
461
462    #[inline]
463    pub fn write_u32(&mut self, n: u32) -> io::Result<()> {
464        self.io.write_u32::<E>(n)
465    }
466
467    #[inline]
468    pub fn write_i32(&mut self, n: i32) -> io::Result<()> {
469        self.io.write_i32::<E>(n)
470    }
471
472    #[inline]
473    pub fn write_u64(&mut self, n: u64) -> io::Result<()> {
474        self.io.write_u64::<E>(n)
475    }
476
477    #[inline]
478    pub fn write_i64(&mut self, n: i64) -> io::Result<()> {
479        self.io.write_i64::<E>(n)
480    }
481
482    #[inline]
483    pub fn write_uint(&mut self, n: u64, nbytes: usize) -> io::Result<()> {
484        self.io.write_uint::<E>(n, nbytes)
485    }
486
487    #[inline]
488    pub fn write_int(&mut self, n: i64, nbytes: usize) -> io::Result<()> {
489        self.io.write_int::<E>(n, nbytes)
490    }
491
492    #[inline]
493    pub fn write_f32(&mut self, n: f32) -> io::Result<()> {
494        self.io.write_f32::<E>(n)
495    }
496
497    #[inline]
498    pub fn write_f64(&mut self, n: f64) -> io::Result<()> {
499        self.io.write_f64::<E>(n)
500    }
501}
502
503impl<I: ReadAt, E: ByteOrder> ByteIo<I, E> {
504    #[inline]
505    pub fn read_u8_at(&self, pos: u64) -> io::Result<u8> {
506        self.io.read_u8_at(pos)
507    }
508
509    #[inline]
510    pub fn read_i8_at(&self, pos: u64) -> io::Result<i8> {
511        self.io.read_i8_at(pos)
512    }
513
514    #[inline]
515    pub fn read_u16_at(&self, pos: u64) -> io::Result<u16> {
516        self.io.read_u16_at::<E>(pos)
517    }
518
519    #[inline]
520    pub fn read_i16_at(&self, pos: u64) -> io::Result<i16> {
521        self.io.read_i16_at::<E>(pos)
522    }
523
524    #[inline]
525    pub fn read_u32_at(&self, pos: u64) -> io::Result<u32> {
526        self.io.read_u32_at::<E>(pos)
527    }
528
529    #[inline]
530    pub fn read_i32_at(&self, pos: u64) -> io::Result<i32> {
531        self.io.read_i32_at::<E>(pos)
532    }
533
534    #[inline]
535    pub fn read_u64_at(&self, pos: u64) -> io::Result<u64> {
536        self.io.read_u64_at::<E>(pos)
537    }
538
539    #[inline]
540    pub fn read_i64_at(&self, pos: u64) -> io::Result<i64> {
541        self.io.read_i64_at::<E>(pos)
542    }
543
544    #[inline]
545    pub fn read_uint_at(&self, pos: u64, nbytes: usize) -> io::Result<u64> {
546        self.io.read_uint_at::<E>(pos, nbytes)
547    }
548
549    #[inline]
550    pub fn read_int_at(&self, pos: u64, nbytes: usize) -> io::Result<i64> {
551        self.io.read_int_at::<E>(pos, nbytes)
552    }
553
554    #[inline]
555    pub fn read_f32_at(&self, pos: u64) -> io::Result<f32> {
556        self.io.read_f32_at::<E>(pos)
557    }
558
559    #[inline]
560    pub fn read_f64_at(&self, pos: u64) -> io::Result<f64> {
561        self.io.read_f64_at::<E>(pos)
562    }
563}
564
565impl<I: WriteAt, E: ByteOrder> ByteIo<I, E> {
566    #[inline]
567    pub fn write_u8_at(&mut self, pos: u64, n: u8) -> io::Result<()> {
568        self.io.write_u8_at(pos, n)
569    }
570
571    #[inline]
572    pub fn write_i8_at(&mut self, pos: u64, n: i8) -> io::Result<()> {
573        self.io.write_i8_at(pos, n)
574    }
575
576    #[inline]
577    pub fn write_u16_at(&mut self, pos: u64, n: u16) -> io::Result<()> {
578        self.io.write_u16_at::<E>(pos, n)
579    }
580
581    #[inline]
582    pub fn write_i16_at(&mut self, pos: u64, n: i16) -> io::Result<()> {
583        self.io.write_i16_at::<E>(pos, n)
584    }
585
586    #[inline]
587    pub fn write_u32_at(&mut self, pos: u64, n: u32) -> io::Result<()> {
588        self.io.write_u32_at::<E>(pos, n)
589    }
590
591    #[inline]
592    pub fn write_i32_at(&mut self, pos: u64, n: i32) -> io::Result<()> {
593        self.io.write_i32_at::<E>(pos, n)
594    }
595
596    #[inline]
597    pub fn write_u64_at(&mut self, pos: u64, n: u64) -> io::Result<()> {
598        self.io.write_u64_at::<E>(pos, n)
599    }
600
601    #[inline]
602    pub fn write_i64_at(&mut self, pos: u64, n: i64) -> io::Result<()> {
603        self.io.write_i64_at::<E>(pos, n)
604    }
605
606    #[inline]
607    pub fn write_uint_at(&mut self, pos: u64, n: u64, nbytes: usize) -> io::Result<()> {
608        self.io.write_uint_at::<E>(pos, n, nbytes)
609    }
610
611    #[inline]
612    pub fn write_int_at(&mut self, pos: u64, n: i64, nbytes: usize) -> io::Result<()> {
613        self.io.write_int_at::<E>(pos, n, nbytes)
614    }
615
616    #[inline]
617    pub fn write_f32_at(&mut self, pos: u64, n: f32) -> io::Result<()> {
618        self.io.write_f32_at::<E>(pos, n)
619    }
620
621    #[inline]
622    pub fn write_f64_at(&mut self, pos: u64, n: f64) -> io::Result<()> {
623        self.io.write_f64_at::<E>(pos, n)
624    }
625}