#![doc(html_root_url="https://briansmith.org/rustdoc/")]
#![allow(
missing_copy_implementations,
missing_debug_implementations,
)]
#![deny(
unused_qualifications,
)]
#![forbid(
anonymous_parameters,
box_pointers,
fat_ptr_transmutes,
legacy_directory_ownership,
missing_docs,
trivial_casts,
trivial_numeric_casts,
unsafe_code,
unstable_features,
unused_extern_crates,
unused_import_braces,
unused_results,
variant_size_differences,
warnings,
)]
#![no_std]
#[derive(Clone, Copy, Debug, Eq)]
pub struct Input<'a> {
value: no_panic::Slice<'a>
}
impl<'a> Input<'a> {
pub fn from(bytes: &'a [u8]) -> Input<'a> {
debug_assert!(bytes.len() < core::usize::MAX);
Input { value: no_panic::Slice::new(bytes) }
}
#[inline]
pub fn is_empty(&self) -> bool { self.value.is_empty() }
#[inline]
pub fn iter(&self) -> <&[u8] as IntoIterator>::IntoIter {
self.value.iter()
}
#[inline]
pub fn len(&self) -> usize { self.value.len() }
pub fn read_all<F, R, E>(&self, incomplete_read: E, read: F)
-> Result<R, E>
where F: FnOnce(&mut Reader<'a>) -> Result<R, E> {
let mut input = Reader::new(*self);
let result = try!(read(&mut input));
if input.at_end() {
Ok(result)
} else {
Err(incomplete_read)
}
}
pub fn read_all_mut<F, R, E>(&self, incomplete_read: E, mut read: F)
-> Result<R, E>
where F: FnMut(&mut Reader<'a>)
-> Result<R, E> {
let mut input = Reader::new(*self);
let result = try!(read(&mut input));
if input.at_end() {
Ok(result)
} else {
Err(incomplete_read)
}
}
#[inline]
pub fn as_slice_less_safe(&self) -> &'a [u8] {
self.value.as_slice_less_safe()
}
}
impl<'a, 'b> PartialEq<Input<'b>> for Input<'a> {
#[inline]
fn eq(&self, other: &Input<'b>) -> bool {
self.as_slice_less_safe() == other.as_slice_less_safe()
}
}
impl <'a, 'b> PartialEq<&'b [u8]> for Input<'a> {
#[inline]
fn eq(&self, other: &&[u8]) -> bool {
self.as_slice_less_safe() == *other
}
}
pub fn read_all_optional<F, R, E>(input: Option<Input>,
incomplete_read: E, read: F)
-> Result<R, E>
where F: FnOnce(Option<&mut Reader>)
-> Result<R, E> {
match input {
Some(input) => {
let mut input = Reader::new(input);
let result = try!(read(Some(&mut input)));
if input.at_end() {
Ok(result)
} else {
Err(incomplete_read)
}
},
None => read(None)
}
}
#[derive(Debug)]
pub struct Reader<'a> {
input: no_panic::Slice<'a>,
i: usize
}
pub struct Mark {
i: usize
}
impl<'a> Reader<'a> {
#[inline]
pub fn new(input: Input<'a>) -> Reader<'a> {
Reader { input: input.value, i: 0 }
}
#[inline]
pub fn at_end(&self) -> bool { self.i == self.input.len() }
#[inline]
pub fn get_input_between_marks(&self, mark1: Mark, mark2: Mark)
-> Result<Input<'a>, EndOfInput> {
self.input.get_slice(mark1.i..mark2.i)
.map(|subslice| Input { value: subslice })
.ok_or(EndOfInput)
}
#[inline]
pub fn mark(&self) -> Mark { Mark { i: self.i } }
pub fn peek(&self, b: u8) -> bool {
match self.input.get(self.i) {
Some(actual_b) => b == *actual_b,
None => false
}
}
pub fn read_byte(&mut self) -> Result<u8, EndOfInput> {
match self.input.get(self.i) {
Some(b) => {
self.i += 1; Ok(*b)
}
None => Err(EndOfInput)
}
}
pub fn skip(&mut self, num_bytes: usize) -> Result<(), EndOfInput> {
self.skip_and_get_input(num_bytes).map(|_| ())
}
pub fn skip_and_get_input(&mut self, num_bytes: usize)
-> Result<Input<'a>, EndOfInput> {
let new_i = try!(self.i.checked_add(num_bytes).ok_or(EndOfInput));
let ret = self.input.get_slice(self.i..new_i)
.map(|subslice| Input { value: subslice })
.ok_or(EndOfInput);
self.i = new_i;
ret
}
pub fn skip_to_end(&mut self) -> Input<'a> {
let to_skip = self.input.len() - self.i;
self.skip_and_get_input(to_skip).unwrap()
}
}
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
pub struct EndOfInput;
mod no_panic {
use core;
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
pub struct Slice<'a> {
bytes: &'a [u8]
}
impl<'a> Slice<'a> {
#[inline]
pub fn new(bytes: &'a [u8]) -> Slice<'a> {
Slice { bytes }
}
#[inline]
pub fn get(&self, i: usize) -> Option<&u8> { self.bytes.get(i) }
#[inline]
pub fn get_slice(&self, r: core::ops::Range<usize>)
-> Option<Slice<'a>> {
self.bytes.get(r).map(|bytes| Slice { bytes })
}
#[inline]
pub fn iter(&self) -> <&'a [u8] as IntoIterator>::IntoIter {
self.bytes.into_iter()
}
#[inline]
pub fn is_empty(&self) -> bool { self.bytes.is_empty() }
#[inline]
pub fn len(&self) -> usize { self.bytes.len() }
#[inline]
pub fn as_slice_less_safe(&self) -> &'a [u8] { self.bytes }
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_input_from() {
let _ = Input::from(b"foo");
}
#[test]
fn test_input_is_empty() {
let input = Input::from(b"");
assert!(input.is_empty());
let input = Input::from(b"foo");
assert!(!input.is_empty());
}
#[test]
fn test_input_len() {
let input = Input::from(b"foo");
assert_eq!(input.len(), 3);
}
#[test]
fn test_input_read_all() {
let input = Input::from(b"foo");
let result = input.read_all(EndOfInput, |input| {
assert_eq!(b'f', try!(input.read_byte()));
assert_eq!(b'o', try!(input.read_byte()));
assert_eq!(b'o', try!(input.read_byte()));
assert!(input.at_end());
Ok(())
});
assert_eq!(result, Ok(()));
}
#[test]
fn test_input_read_all_unconsume() {
let input = Input::from(b"foo");
let result = input.read_all(EndOfInput, |input| {
assert_eq!(b'f', try!(input.read_byte()));
assert!(!input.at_end());
Ok(())
});
assert_eq!(result, Err(EndOfInput));
}
#[test]
fn test_input_as_slice_less_safe() {
let slice = b"foo";
let input = Input::from(slice);
assert_eq!(input.as_slice_less_safe(), slice);
}
#[test]
fn test_input_as_iterator() {
let slice = b"foo";
let input = Input::from(slice);
let mut iter = input.iter();
assert_eq!(Some(&b'f'), iter.next());
assert_eq!(Some(&b'o'), iter.next());
assert_eq!(Some(&b'o'), iter.next());
assert_eq!(None, iter.next());
}
}