1
//! Internal: Declare the Writer type for tor-bytes
2

            
3
use crate::Writeable;
4
use crate::WriteableOnce;
5

            
6
/// A byte-oriented trait for writing to small arrays.
7
///
8
/// Unlike std::io::Write, this trait's methods are not allowed to
9
/// fail.  It's not for IO.
10
///
11
/// Most code will want to use the fact that Vec<u8> implements this trait.
12
/// To define a new implementation, just define the write_all method.
13
///
14
/// # Examples
15
///
16
/// You can use a Writer to add bytes explicitly:
17
/// ```
18
/// use tor_bytes::Writer;
19
/// let mut w: Vec<u8> = Vec::new(); // Vec<u8> implements Writer.
20
/// w.write_u32(0x12345);
21
/// w.write_u8(0x22);
22
/// w.write_zeros(3);
23
/// assert_eq!(w, &[0x00, 0x01, 0x23, 0x45, 0x22, 0x00, 0x00, 0x00]);
24
/// ```
25
///
26
/// You can also use a Writer to encode things that implement the
27
/// Writeable trait:
28
///
29
/// ```
30
/// use tor_bytes::{Writer,Writeable};
31
/// let mut w: Vec<u8> = Vec::new();
32
/// w.write(&4_u16); // The unsigned types all implement Writeable.
33
///
34
/// // We also provide Writeable implementations for several important types.
35
/// use std::net::Ipv4Addr;
36
/// let ip = Ipv4Addr::new(127, 0, 0, 1);
37
/// w.write(&ip);
38
///
39
/// assert_eq!(w, &[0x00, 0x04, 0x7f, 0x00, 0x00, 0x01]);
40
/// ```
41
pub trait Writer {
42
    /// Append a slice to the end of this writer.
43
    fn write_all(&mut self, b: &[u8]);
44

            
45
    /// Append a single u8 to this writer.
46
661
    fn write_u8(&mut self, x: u8) {
47
661
        self.write_all(&[x]);
48
661
    }
49
    /// Append a single u16 to this writer, encoded in big-endian order.
50
168134
    fn write_u16(&mut self, x: u16) {
51
168134
        self.write_all(&x.to_be_bytes());
52
168134
    }
53
    /// Append a single u32 to this writer, encoded in big-endian order.
54
56301
    fn write_u32(&mut self, x: u32) {
55
56301
        self.write_all(&x.to_be_bytes());
56
56301
    }
57
    /// Append a single u64 to this writer, encoded in big-endian order.
58
35
    fn write_u64(&mut self, x: u64) {
59
35
        self.write_all(&x.to_be_bytes());
60
35
    }
61
    /// Append a single u128 to this writer, encoded in big-endian order.
62
1
    fn write_u128(&mut self, x: u128) {
63
1
        self.write_all(&x.to_be_bytes());
64
1
    }
65
    /// Write n bytes to this writer, all with the value zero.
66
    ///
67
    /// NOTE: This implementation is somewhat inefficient, since it allocates
68
    /// a vector.  You should probably replace it if you can.
69
220
    fn write_zeros(&mut self, n: usize) {
70
220
        let v = vec![0_u8; n];
71
220
        self.write_all(&v[..]);
72
220
    }
73
    /// Encode a Writeable object onto this writer, using its
74
    /// write_onto method.
75
5245
    fn write<E: Writeable + ?Sized>(&mut self, e: &E) {
76
5245
        e.write_onto(self);
77
5245
    }
78
    /// Encode a WriteableOnce object onto this writer, using its
79
    /// write_into method.
80
38
    fn write_and_consume<E: WriteableOnce>(&mut self, e: E) {
81
38
        e.write_into(self);
82
38
    }
83
}
84

            
85
#[cfg(test)]
86
mod tests {
87
    use super::*;
88
    #[test]
89
    fn write_ints() {
90
        let mut b = bytes::BytesMut::new();
91
        b.write_u8(1);
92
        b.write_u16(2);
93
        b.write_u32(3);
94
        b.write_u64(4);
95
        b.write_u128(5);
96

            
97
        assert_eq!(
98
            &b[..],
99
            &[
100
                1, 0, 2, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
101
                0, 0, 5
102
            ]
103
        );
104
    }
105

            
106
    #[test]
107
    fn write_slice() {
108
        let mut v = Vec::new();
109
        v.write_u16(0x5468);
110
        v.write(&b"ey're good dogs, Bront"[..]);
111

            
112
        assert_eq!(&v[..], &b"They're good dogs, Bront"[..]);
113
    }
114

            
115
    #[test]
116
    fn writeable() {
117
        struct Sequence(u8);
118
        impl Writeable for Sequence {
119
            fn write_onto<B: Writer + ?Sized>(&self, b: &mut B) {
120
                for i in 0..self.0 {
121
                    b.write_u8(i);
122
                }
123
            }
124
        }
125

            
126
        let mut v = Vec::new();
127
        v.write(&Sequence(6));
128
        assert_eq!(&v[..], &[0, 1, 2, 3, 4, 5]);
129

            
130
        v.write_and_consume(Sequence(3));
131
        assert_eq!(&v[..], &[0, 1, 2, 3, 4, 5, 0, 1, 2]);
132
    }
133
}