positioned_io2/
byteio.rs

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