positioned_io/
byteio.rs

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