1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
//! Provides methods for reading and writing data both directly
//! (using [`BitStore`]) and indirectly
//! (using [`BitConvert`]).
//!
//! [`BitStore`]: http://docs.rs/bit_manager/0.5.3/bit_manager/data/trait.BitStore.html
//! [`BitConvert`]: http://docs.rs/bit_manager/0.5.3/bit_manager/data/trait.BitConvert.html

use io::*;
use buffer::*;

/// A trait for storing a value directly
///
/// ## Derive
///
/// `BitStore` can be derived using the [bit manager derive] crate.
///
/// ## Storage Primitives
/// * `bool`, `u8` (directly implemented)
/// * `u16`, `u32`, `u64`
/// * `i8`, `i16`, `i32`, `i64`
/// * `f32`, `f64`
/// * `String` (through [`StringConverter`])
/// * `Option<T>` where `T` can be stored
/// * `Result<T, F>` where `T` and `F` can be stored
/// * `[T; 0]` through `[T; 32]` where `T` can be stored
/// * `()` (the unit type) and all tuples with 2 through 26 storable values
///
/// [`StringConverter`]: http://docs.rs/bit_manager/0.5.3/bit_manager/data/enum.StringConverter.html
/// [bit manager derive]: http://docs.rs/bit_manager_derive
pub trait BitStore: Sized {
    /// Reads a value from the given reader.
    fn read_from<R: BitRead>(reader: &mut R) -> Result<Self>;

    /// Writes this value to the given writer.
    fn write_to<W: BitWrite>(&self, writer: &mut W) -> Result<()>;
}

/// A trait for a converter that allows the reading and writing of types though a converter
pub trait BitConvert<T>: Sized {
    /// Reads a value from the given reader.
    fn read_value_from<R: BitRead>(&self, reader: &mut R) -> Result<T>;

    /// Writes this value to the given writer.
    fn write_value_to<W: BitWrite>(&self, value: &T, writer: &mut W) -> Result<()>;
}

/// An enum that allows the reading and writing of strings using various methods
#[derive(Debug)]
pub enum StringConverter {
    /// Prefixes the string with length.
    ///
    /// This is the default option. The recommended number of bits for the prefix is 32.
    ///
    /// *Requires 2 bits to store converter for recommended number of bits, otherwise 7 bits to store*
    LengthPrefixed {
        /// The number of bits in the prefix
        prefix_bits: u8,
    },

    /// Terminates the string with a null character (`\0`). The string must not contain a null character.
    ///
    /// This option is recommended if it is possible to guarantee that the string will never contain a null character.
    ///
    /// *Requires 2 bits to store converter*
    NullTerminated,

    /// Writes a string with a specified fixed length. If the string is shorter, it will have
    /// null characters (`\0`) appended until it is the right length.
    ///
    /// This option is only recommended if it is known in advance how long the string will be.
    ///
    /// *Requires 34 bits to store converter*
    FixedLength {
        /// The length of the string
        length: u32,
    },
}

impl Default for StringConverter {
    fn default() -> Self {
        StringConverter::LengthPrefixed {
            prefix_bits: 32,
        }
    }
}

bit_store! {
    for StringConverter {
        (reader) => {
            Ok(
                if !reader.read_bit()? {
                    if !reader.read_bit()? {
                        StringConverter::LengthPrefixed {
                            prefix_bits: 32,
                        }
                    } else {
                        StringConverter::LengthPrefixed {
                            prefix_bits: reader.read_using(&BitMask::bits(5))?,
                        }
                    }
                } else if !reader.read_bit()? {
                    StringConverter::NullTerminated
                } else {
                    StringConverter::FixedLength {
                        length: reader.read::<u32>()?,
                    }
                }
            )
        },
        (self, writer) => {
            match self {
                &StringConverter::LengthPrefixed { prefix_bits: 32 } => {
                    writer.write_bit(false)?;
                    writer.write_bit(false)
                }
                &StringConverter::LengthPrefixed { prefix_bits } => {
                    writer.write_bit(false)?;
                    writer.write_bit(true)?;
                    writer.write_using(&prefix_bits, &BitMask::bits(5))
                },
                &StringConverter::NullTerminated => {
                    writer.write_bit(true)?;
                    writer.write_bit(false)
                },
                &StringConverter::FixedLength { length } => {
                    writer.write_bit(true)?;
                    writer.write_bit(true)?;
                    writer.write(&length)
                }
            }
        },
    };
}

bit_convert! {
    for StringConverter: String {
        (self, reader) => {
            let mut string = Vec::new();
            match *self {
                StringConverter::LengthPrefixed { prefix_bits } => {
                    let mask = BitMask::bits(prefix_bits);
                    let bytes: u32 = reader.read_using(&mask)?;
                    for _ in 0..bytes {
                        string.push(reader.read_byte()?);
                    }
                },
                StringConverter::NullTerminated => {
                    loop {
                        let byte = reader.read_byte()?;
                        if byte == 0 {
                            break;
                        } else {
                            string.push(byte);
                        }
                    }
                },
                StringConverter::FixedLength { length } => {
                    for _ in 0..length {
                        string.push(reader.read_byte()?);
                    }
                },
            }
            String::from_utf8(string).map_err(|_| Error::ConversionFailed)
        },
        (self, value, writer) => {
            if value.len() > u32::max_value() as usize {
                return Err(Error::ConversionFailed);
            }
            match *self {
                StringConverter::LengthPrefixed { prefix_bits } => {
                    let mask = BitMask::bits(prefix_bits);
                    writer.write_using(&(value.len() as u32), &mask)?;
                    for byte in value.as_bytes() {
                        writer.write_byte(*byte)?;
                    }
                    Ok(())
                },
                StringConverter::NullTerminated => {
                    for byte in value.as_bytes() {
                        if *byte == 0 {
                            return Err(Error::ConversionFailed);
                        }
                        writer.write_byte(*byte)?;
                    }
                    writer.write_byte(0)
                },
                StringConverter::FixedLength { length } => {
                    let bytes = length as usize;
                    if value.len() > bytes {
                        return Err(Error::ConversionFailed);
                    }
                    let extra = bytes-value.len();
                    for byte in value.as_bytes() {
                        writer.write_byte(*byte)?;
                    }
                    for _ in 0..extra {
                        writer.write_byte(0)?;
                    }
                    Ok(())
                },
            }
        },
    };
}

/// A struct that allows the reading and writing of non-bit-length numbers
#[derive(Debug)]
pub struct BitMask {
    bits: u8,
}

impl BitMask {
    /// Creates a mask with the given number of bits.
    pub fn bits(bits: u8) -> BitMask {
        BitMask {
            bits,
        }
    }

    /// Creates a mask with the given number of bytes.
    pub fn bytes(bytes: u8) -> BitMask {
        BitMask {
            bits: bytes*8,
        }
    }
}

bit_store! {
    for BitMask {
        (reader) => {
            match reader.read_byte() {
                Ok(bits) => Ok(BitMask { bits }),
                Err(e) => Err(e),
            }
        },
        (self, writer) => {
            writer.write_byte(self.bits)
        },
    };
}

macro_rules! impl_bit_mask {
    ($( $u: ident $b: expr ),+) => { $(
        bit_convert! {
            for BitMask: $u {
                (self, reader) => {
                    if self.bits > $b {
                        return Err(Error::BitOverflow { bits: self.bits, expected: $b } );
                    } else if self.bits == 0 {
                        return Ok(0);
                    }
                    let mut int = 0;
                    let bytes = self.bits/8;
                    for index in 0..bytes {
                        let read = reader.read_byte()?;
                        if read != 0 {
                            int |= (read as $u) << (self.bits - index*8 - 8);
                        }
                    }
                    let bits = self.bits%8;
                    for index in 0..bits {
                        let read = reader.read_bit()?;
                        if read {
                            int |= 1 << (bits - index - 1);
                        }
                    }
                    Ok(int)
                },
                (self, value, writer) => {
                    if self.bits != 0 {
                        let int = *value as u64;
                        if self.bits > $b {
                            return Err(Error::BitOverflow { bits: self.bits, expected: $b } );
                        }
                        if int >> self.bits != 0 {
                            return Err(Error::ConversionFailed);
                        }
                        let bytes = self.bits/8;
                        for index in 0..bytes {
                            writer.write_byte((int >> (self.bits - 8*index - 8)) as u8)?;
                        }
                        let bits = self.bits%8;
                        for index in 0..bits {
                            writer.write_bit((int >> (bits - index - 1)) & 1 == 1)?;
                        }
                    }
                    Ok(())
                },
            };
        }
    )+ }
}

impl_bit_mask!(u64 64, u32 32, u16 16, u8 8);

/// Redirects to [`BitStore`]
///
/// [`BitStore`]: http://docs.rs/bit_manager/0.5.3/bit_manager/data/trait.BitStore.html
pub struct DefaultConverter;

bit_const! {
    const DefaultConverter {
        Ok(DefaultConverter),
        Ok(()),
    };
}

bit_convert! {
    impl<T: BitStore> for DefaultConverter: T {
        (self, reader) => { T::read_from(reader) },
        (self, value, writer) => { value.write_to(writer) },
    };
}