<commit_before>//! Complex numbers

#![cfg_attr(test, feature(core))]
#![deny(missing_docs)]
#![deny(warnings)]

extern crate approx;
extern crate onezero;
extern crate rand;

use std::fmt;
use std::num::Float;
use std::ops::{Add, Sub, Mul, Div, Neg};

use approx::{Abs, Ulp, Rel};
use rand::{Rand, Rng};
use onezero::{One, Zero};

mod ffi;
mod math;

pub mod f32;
pub mod f64;

/// A complex number in Cartesian form.
#[repr(C)]
#[derive(Clone, Copy, PartialEq)]
pub struct Complex<T> {
    /// The real part
    pub re: T,
    /// The imaginary part
    pub im: T,
}

/// Single precision complex number
#[allow(non_camel_case_types)]
pub type c64 = Complex<f32>;
/// Double precision complex number
#[allow(non_camel_case_types)]
pub type c128 = Complex<f64>;

impl<T> Complex<T> {
    /// Create a new complex number
    pub fn new(re: T, im: T) -> Complex<T> {
        Complex {
            im: im,
            re: re,
        }
    }
}

impl<T> Complex<T> where T: Add<Output=T> + Clone + Mul<Output=T> {
    fn norm_sqr(self) -> T {
        self.re.clone() * self.re + self.im.clone() * self.im
    }
}

impl<T> Add<T> for Complex<T> where T: Add<Output=T> + Clone {
    type Output = Complex<T>;

    fn add(self, rhs: T) -> Complex<T> {
        Complex {
            re: self.re + rhs,
            im: self.im.clone(),
        }
    }
}

impl<T> Add for Complex<T> where T: Add<Output=T> {
    type Output = Complex<T>;

    fn add(self, rhs: Complex<T>) -> Complex<T> {
        Complex {
            re: self.re + rhs.re,
            im: self.im + rhs.im,
        }
    }
}

impl Add<Complex<f32>> for f32 {
    type Output = Complex<f32>;

    fn add(self, rhs: Complex<f32>) -> Complex<f32> {
        rhs + self
    }
}

impl Add<Complex<f64>> for f64 {
    type Output = Complex<f64>;

    fn add(self, rhs: Complex<f64>) -> Complex<f64> {
        rhs + self
    }
}

impl<T> Div<T> for Complex<T> where T: Clone + Div<Output=T> {
    type Output = Complex<T>;

    fn div(self, rhs: T) -> Complex<T> {
        Complex {
            re: self.re / rhs.clone(),
            im: self.im / rhs,
        }
    }
}

impl<T> Div for Complex<T> where
    T: Add<Output=T> + Clone + Div<Output=T> + Mul<Output=T> + Sub<Output=T>
{
    type Output = Complex<T>;

    fn div(self, rhs: Complex<T>) -> Complex<T> {
        let den = rhs.clone().norm_sqr();

        Complex {
            re: {
                self.re.clone() * rhs.re.clone() + self.im.clone() * rhs.im.clone()
            } / den.clone(),
            im: (self.im * rhs.re - self.re * rhs.im) / den,
        }
    }
}

impl Div<Complex<f32>> for f32 {
    type Output = Complex<f32>;

    fn div(self, rhs: Complex<f32>) -> Complex<f32> {
        let den = rhs.norm_sqr();

        Complex {
            re: (self * rhs.re) / den,
            im: -(self * rhs.im) / den,
        }
    }
}

impl Div<Complex<f64>> for f64 {
    type Output = Complex<f64>;

    fn div(self, rhs: Complex<f64>) -> Complex<f64> {
        let den = rhs.norm_sqr();

        Complex {
            re: (self * rhs.re) / den,
            im: -(self * rhs.im) / den,
        }
    }
}

impl<T> Mul<T> for Complex<T> where T: Clone + Mul<Output=T> {
    type Output = Complex<T>;

    fn mul(self, rhs: T) -> Complex<T> {
        Complex {
            re: self.re * rhs.clone(),
            im: self.im * rhs,
        }
    }
}

impl<T> Mul for Complex<T> where
    T: Add<Output=T> + Clone + Mul<Output=T> + Sub<Output=T>,
{
    type Output = Complex<T>;

    fn mul(self, rhs: Complex<T>) -> Complex<T> {
        Complex {
            re: self.re.clone() * rhs.re.clone() - self.im.clone() * rhs.im.clone(),
            im: self.re * rhs.im + self.im * rhs.re,
        }
    }
}

impl Mul<Complex<f32>> for f32 {
    type Output = Complex<f32>;

    fn mul(self, rhs: Complex<f32>) -> Complex<f32> {
        rhs * self
    }
}

impl Mul<Complex<f64>> for f64 {
    type Output = Complex<f64>;

    fn mul(self, rhs: Complex<f64>) -> Complex<f64> {
        rhs * self
    }
}

impl<T> Neg for Complex<T> where T: Neg<Output=T> {
    type Output = Complex<T>;

    fn neg(self) -> Complex<T> {
        Complex {
            re: -self.re,
            im: -self.im,
        }
    }
}

impl<T> One for Complex<T> where T: One + Zero {
    fn one() -> Complex<T> {
        Complex {
            re: One::one(),
            im: Zero::zero(),
        }
    }
}

impl<T> Rand for Complex<T> where T: Rand {
    fn rand<R>(rng: &mut R) -> Complex<T> where R: Rng {
        Complex::new(rng.gen(), rng.gen())
    }
}

impl<T> Sub<T> for Complex<T> where T: Clone + Sub<Output=T> {
    type Output = Complex<T>;

    fn sub(self, rhs: T) -> Complex<T> {
        Complex {
            re: self.re - rhs,
            im: self.im.clone(),
        }
    }
}

impl<T> Sub for Complex<T> where T: Sub<Output=T> {
    type Output = Complex<T>;

    fn sub(self, rhs: Complex<T>) -> Complex<T> {
        Complex {
            re: self.re - rhs.re,
            im: self.im - rhs.im,
        }
    }
}

impl Sub<Complex<f32>> for f32 {
    type Output = Complex<f32>;

    fn sub(self, rhs: Complex<f32>) -> Complex<f32> {
        Complex {
            re: self - rhs.re,
            im: -rhs.im,
        }
    }
}

impl Sub<Complex<f64>> for f64 {
    type Output = Complex<f64>;

    fn sub(self, rhs: Complex<f64>) -> Complex<f64> {
        Complex {
            re: self - rhs.re,
            im: -rhs.im,
        }
    }
}

impl<T> Zero for Complex<T> where T: Zero {
    fn zero() -> Complex<T> {
        Complex {
            re: Zero::zero(),
            im: Zero::zero(),
        }
    }
}

impl<T, U> approx::Eq<Abs<T>> for Complex<U> where
    T: Float,
    U: approx::Eq<Abs<T>>,
{
    fn approx_eq(&self, rhs: &Complex<U>, tol: Abs<T>) -> bool {
        self.re.approx_eq(&rhs.re, tol) && self.im.approx_eq(&rhs.im, tol)
    }
}

impl<T, U> approx::Eq<Ulp<T>> for Complex<U> where
    T: Copy,
    U: approx::Eq<Ulp<T>>,
{
    fn approx_eq(&self, rhs: &Complex<U>, tol: Ulp<T>) -> bool {
        self.re.approx_eq(&rhs.re, tol) && self.im.approx_eq(&rhs.im, tol)
    }
}

impl<T, U> approx::Eq<Rel<T>> for Complex<U> where
    T: Float,
    U: approx::Eq<Rel<T>>,
{
    fn approx_eq(&self, rhs: &Complex<U>, tol: Rel<T>) -> bool {
        self.re.approx_eq(&rhs.re, tol) && self.im.approx_eq(&rhs.im, tol)
    }
}

impl<T> fmt::Debug for Complex<T> where T: PartialOrd + fmt::Debug + Zero {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        if self.im < Zero::zero() {
            write!(f, "{:?}-{:?}i", self.re, self.im)
        } else {
            write!(f, "{:?}+{:?}i", self.re, self.im)
        }
    }
}

/// Mathematical operations on complex numbers
// FIXME (AI) `T` should be an associated output type
pub trait Math {
    type Ty;

    /// Computes the complex absolute value (also called norm, modulus or magnitude)
    fn abs(self) -> Self::Ty;

    /// Computes the arc cosine
    fn acos(self) -> Self;

    /// Computes the arc hyperbolic cosine
    fn acosh(self) -> Self;

    /// Computes the argument (also called the phase angle)
    fn arg(self) -> Self::Ty;

    /// Computes the arc sine
    fn asin(self) -> Self;

    /// Computes the arc hyperbolic sine
    fn asinh(self) -> Self;

    /// Computes the arc tangent
    fn atan(self) -> Self;

    /// Computes the arc hyperbolic tangent
    fn atanh(self) -> Self;

    /// Computes the arc cosine
    fn cos(self) -> Self;

    /// Computes the arc hyperbolic cosine
    fn cosh(self) -> Self;

    /// Computes the complex base-e exponential
    fn exp(self) -> Self;

    /// Returns the imaginary part
    fn imag(self) -> Self::Ty;

    /// Computes the complex base-e logarithm
    fn log(self) -> Self;

    /// Computes the complex conjugate
    fn conj(self) -> Self;

    /// Computes the complex power
    fn pow(self, Self) -> Self;

    /// Computes the Riemann sphere projection
    fn proj(self) -> Self;

    /// Returns the real part
    fn real(self) -> Self::Ty;

    /// Computes the arc sine
    fn sin(self) -> Self;

    /// Computes the arc hyperbolic sine
    fn sinh(self) -> Self;

    /// Computes the square root
    fn sqrt(self) -> Self;

    /// Computes the arc tangent
    fn tan(self) -> Self;

    /// Computes the arc hyperbolic tangent
    fn tanh(self) -> Self;
}

#[cfg(test)]
mod test {
    macro_rules! test {
        ($($ty:ident),+) => {$(
            mod $ty {
                use Complex;
                use $ty::I;

                #[test]
                fn approx() {
                    let x = I + 1.;
                    let y = I + 1.;

                    assert!(::approx::eq(&x, &y, ::approx::Abs::tol(1e-5)));
                    assert!(::approx::eq(&x, &y, ::approx::Rel::tol(1e-5)));
                    assert!(::approx::eq(&x, &y, ::approx::Ulp::tol(1_000)));
                    assert!(::approx::eq(&&x, &&y, ::approx::Abs::tol(1e-5)));
                    assert!(::approx::eq(&&x, &&y, ::approx::Rel::tol(1e-5)));
                }

                #[test]
                fn constructor() {
                    assert_eq!(Complex::new(3., 4.), I * 4. + 3.)
                }
            })+
         }
    }

    test!(f32, f64);
}
<commit_msg>docs: document associated types<commit_after>//! Complex numbers

#![cfg_attr(test, feature(core))]
#![deny(missing_docs)]
#![deny(warnings)]

extern crate approx;
extern crate onezero;
extern crate rand;

use std::fmt;
use std::num::Float;
use std::ops::{Add, Sub, Mul, Div, Neg};

use approx::{Abs, Ulp, Rel};
use rand::{Rand, Rng};
use onezero::{One, Zero};

mod ffi;
mod math;

pub mod f32;
pub mod f64;

/// A complex number in Cartesian form.
#[repr(C)]
#[derive(Clone, Copy, PartialEq)]
pub struct Complex<T> {
    /// The real part
    pub re: T,
    /// The imaginary part
    pub im: T,
}

/// Single precision complex number
#[allow(non_camel_case_types)]
pub type c64 = Complex<f32>;
/// Double precision complex number
#[allow(non_camel_case_types)]
pub type c128 = Complex<f64>;

impl<T> Complex<T> {
    /// Create a new complex number
    pub fn new(re: T, im: T) -> Complex<T> {
        Complex {
            im: im,
            re: re,
        }
    }
}

impl<T> Complex<T> where T: Add<Output=T> + Clone + Mul<Output=T> {
    fn norm_sqr(self) -> T {
        self.re.clone() * self.re + self.im.clone() * self.im
    }
}

impl<T> Add<T> for Complex<T> where T: Add<Output=T> + Clone {
    type Output = Complex<T>;

    fn add(self, rhs: T) -> Complex<T> {
        Complex {
            re: self.re + rhs,
            im: self.im.clone(),
        }
    }
}

impl<T> Add for Complex<T> where T: Add<Output=T> {
    type Output = Complex<T>;

    fn add(self, rhs: Complex<T>) -> Complex<T> {
        Complex {
            re: self.re + rhs.re,
            im: self.im + rhs.im,
        }
    }
}

impl Add<Complex<f32>> for f32 {
    type Output = Complex<f32>;

    fn add(self, rhs: Complex<f32>) -> Complex<f32> {
        rhs + self
    }
}

impl Add<Complex<f64>> for f64 {
    type Output = Complex<f64>;

    fn add(self, rhs: Complex<f64>) -> Complex<f64> {
        rhs + self
    }
}

impl<T> Div<T> for Complex<T> where T: Clone + Div<Output=T> {
    type Output = Complex<T>;

    fn div(self, rhs: T) -> Complex<T> {
        Complex {
            re: self.re / rhs.clone(),
            im: self.im / rhs,
        }
    }
}

impl<T> Div for Complex<T> where
    T: Add<Output=T> + Clone + Div<Output=T> + Mul<Output=T> + Sub<Output=T>
{
    type Output = Complex<T>;

    fn div(self, rhs: Complex<T>) -> Complex<T> {
        let den = rhs.clone().norm_sqr();

        Complex {
            re: {
                self.re.clone() * rhs.re.clone() + self.im.clone() * rhs.im.clone()
            } / den.clone(),
            im: (self.im * rhs.re - self.re * rhs.im) / den,
        }
    }
}

impl Div<Complex<f32>> for f32 {
    type Output = Complex<f32>;

    fn div(self, rhs: Complex<f32>) -> Complex<f32> {
        let den = rhs.norm_sqr();

        Complex {
            re: (self * rhs.re) / den,
            im: -(self * rhs.im) / den,
        }
    }
}

impl Div<Complex<f64>> for f64 {
    type Output = Complex<f64>;

    fn div(self, rhs: Complex<f64>) -> Complex<f64> {
        let den = rhs.norm_sqr();

        Complex {
            re: (self * rhs.re) / den,
            im: -(self * rhs.im) / den,
        }
    }
}

impl<T> Mul<T> for Complex<T> where T: Clone + Mul<Output=T> {
    type Output = Complex<T>;

    fn mul(self, rhs: T) -> Complex<T> {
        Complex {
            re: self.re * rhs.clone(),
            im: self.im * rhs,
        }
    }
}

impl<T> Mul for Complex<T> where
    T: Add<Output=T> + Clone + Mul<Output=T> + Sub<Output=T>,
{
    type Output = Complex<T>;

    fn mul(self, rhs: Complex<T>) -> Complex<T> {
        Complex {
            re: self.re.clone() * rhs.re.clone() - self.im.clone() * rhs.im.clone(),
            im: self.re * rhs.im + self.im * rhs.re,
        }
    }
}

impl Mul<Complex<f32>> for f32 {
    type Output = Complex<f32>;

    fn mul(self, rhs: Complex<f32>) -> Complex<f32> {
        rhs * self
    }
}

impl Mul<Complex<f64>> for f64 {
    type Output = Complex<f64>;

    fn mul(self, rhs: Complex<f64>) -> Complex<f64> {
        rhs * self
    }
}

impl<T> Neg for Complex<T> where T: Neg<Output=T> {
    type Output = Complex<T>;

    fn neg(self) -> Complex<T> {
        Complex {
            re: -self.re,
            im: -self.im,
        }
    }
}

impl<T> One for Complex<T> where T: One + Zero {
    fn one() -> Complex<T> {
        Complex {
            re: One::one(),
            im: Zero::zero(),
        }
    }
}

impl<T> Rand for Complex<T> where T: Rand {
    fn rand<R>(rng: &mut R) -> Complex<T> where R: Rng {
        Complex::new(rng.gen(), rng.gen())
    }
}

impl<T> Sub<T> for Complex<T> where T: Clone + Sub<Output=T> {
    type Output = Complex<T>;

    fn sub(self, rhs: T) -> Complex<T> {
        Complex {
            re: self.re - rhs,
            im: self.im.clone(),
        }
    }
}

impl<T> Sub for Complex<T> where T: Sub<Output=T> {
    type Output = Complex<T>;

    fn sub(self, rhs: Complex<T>) -> Complex<T> {
        Complex {
            re: self.re - rhs.re,
            im: self.im - rhs.im,
        }
    }
}

impl Sub<Complex<f32>> for f32 {
    type Output = Complex<f32>;

    fn sub(self, rhs: Complex<f32>) -> Complex<f32> {
        Complex {
            re: self - rhs.re,
            im: -rhs.im,
        }
    }
}

impl Sub<Complex<f64>> for f64 {
    type Output = Complex<f64>;

    fn sub(self, rhs: Complex<f64>) -> Complex<f64> {
        Complex {
            re: self - rhs.re,
            im: -rhs.im,
        }
    }
}

impl<T> Zero for Complex<T> where T: Zero {
    fn zero() -> Complex<T> {
        Complex {
            re: Zero::zero(),
            im: Zero::zero(),
        }
    }
}

impl<T, U> approx::Eq<Abs<T>> for Complex<U> where
    T: Float,
    U: approx::Eq<Abs<T>>,
{
    fn approx_eq(&self, rhs: &Complex<U>, tol: Abs<T>) -> bool {
        self.re.approx_eq(&rhs.re, tol) && self.im.approx_eq(&rhs.im, tol)
    }
}

impl<T, U> approx::Eq<Ulp<T>> for Complex<U> where
    T: Copy,
    U: approx::Eq<Ulp<T>>,
{
    fn approx_eq(&self, rhs: &Complex<U>, tol: Ulp<T>) -> bool {
        self.re.approx_eq(&rhs.re, tol) && self.im.approx_eq(&rhs.im, tol)
    }
}

impl<T, U> approx::Eq<Rel<T>> for Complex<U> where
    T: Float,
    U: approx::Eq<Rel<T>>,
{
    fn approx_eq(&self, rhs: &Complex<U>, tol: Rel<T>) -> bool {
        self.re.approx_eq(&rhs.re, tol) && self.im.approx_eq(&rhs.im, tol)
    }
}

impl<T> fmt::Debug for Complex<T> where T: PartialOrd + fmt::Debug + Zero {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        if self.im < Zero::zero() {
            write!(f, "{:?}-{:?}i", self.re, self.im)
        } else {
            write!(f, "{:?}+{:?}i", self.re, self.im)
        }
    }
}

/// Mathematical operations on complex numbers
// FIXME (AI) `T` should be an associated output type
pub trait Math {
    /// The type of the real/imaginary parts
    type Ty;

    /// Computes the complex absolute value (also called norm, modulus or magnitude)
    fn abs(self) -> Self::Ty;

    /// Computes the arc cosine
    fn acos(self) -> Self;

    /// Computes the arc hyperbolic cosine
    fn acosh(self) -> Self;

    /// Computes the argument (also called the phase angle)
    fn arg(self) -> Self::Ty;

    /// Computes the arc sine
    fn asin(self) -> Self;

    /// Computes the arc hyperbolic sine
    fn asinh(self) -> Self;

    /// Computes the arc tangent
    fn atan(self) -> Self;

    /// Computes the arc hyperbolic tangent
    fn atanh(self) -> Self;

    /// Computes the arc cosine
    fn cos(self) -> Self;

    /// Computes the arc hyperbolic cosine
    fn cosh(self) -> Self;

    /// Computes the complex base-e exponential
    fn exp(self) -> Self;

    /// Returns the imaginary part
    fn imag(self) -> Self::Ty;

    /// Computes the complex base-e logarithm
    fn log(self) -> Self;

    /// Computes the complex conjugate
    fn conj(self) -> Self;

    /// Computes the complex power
    fn pow(self, Self) -> Self;

    /// Computes the Riemann sphere projection
    fn proj(self) -> Self;

    /// Returns the real part
    fn real(self) -> Self::Ty;

    /// Computes the arc sine
    fn sin(self) -> Self;

    /// Computes the arc hyperbolic sine
    fn sinh(self) -> Self;

    /// Computes the square root
    fn sqrt(self) -> Self;

    /// Computes the arc tangent
    fn tan(self) -> Self;

    /// Computes the arc hyperbolic tangent
    fn tanh(self) -> Self;
}

#[cfg(test)]
mod test {
    macro_rules! test {
        ($($ty:ident),+) => {$(
            mod $ty {
                use Complex;
                use $ty::I;

                #[test]
                fn approx() {
                    let x = I + 1.;
                    let y = I + 1.;

                    assert!(::approx::eq(&x, &y, ::approx::Abs::tol(1e-5)));
                    assert!(::approx::eq(&x, &y, ::approx::Rel::tol(1e-5)));
                    assert!(::approx::eq(&x, &y, ::approx::Ulp::tol(1_000)));
                    assert!(::approx::eq(&&x, &&y, ::approx::Abs::tol(1e-5)));
                    assert!(::approx::eq(&&x, &&y, ::approx::Rel::tol(1e-5)));
                }

                #[test]
                fn constructor() {
                    assert_eq!(Complex::new(3., 4.), I * 4. + 3.)
                }
            })+
         }
    }

    test!(f32, f64);
}
<|endoftext|>


<commit_before>//! Taken from http://www.itu.int/rec/T-REC-X.680-200811-I

#![allow(dead_code)] // Until parser is complete. Too noisy otherwise

#[macro_use]
extern crate nom;

extern crate regex;

use std::str::FromStr;
use nom::{IResult, Needed};

/// Returns `true` if the character is a newline character according to ASN.1.
///
/// Defined in X.680 §12.1.6
fn is_newline(ch: char) -> bool {
    match ch {
        // LINE FEED
        '\n' => true,

        // VERTICAL TABULATION
        '\x0B' => true,

        // FORM FEED
        '\x0C' => true,

        // CARRIAGE RETURN
        '\x0D' => true,
        _ => false,
    }
}

named!(newline<&str, &str>,
       alt!(
           tag_s!("\n") |
           tag_s!("\x0B") |
           tag_s!("\x0C") |
           tag_s!("\x0D")
       )
);

/// Returns `true` if the character is a whitespace character according to ASN.1.
///
/// Defined in X.680 §12.1.6
fn is_whitespace(ch: char) -> bool {
    match ch {
        ' ' | '\t' => true,

        // All newline characters are also whitespace
        _ if is_newline(ch) => true,
        _ => false,
    }
}

/// Takes input until it finds the end of a single-line comment. This will not consume the ending
/// character(s) of the comment.
fn take_until_single_line_comment_end(input: &str) -> IResult<&str, &str> {
    let mut offset = input.len();
    let mut chars = input.char_indices().peekable();
    loop {
        match chars.next() {
            Some((i, c)) => {
                match c {
                    '-' => {
                        match chars.peek() {
                            Some(&(_, pc)) => {
                                if pc == '-' {
                                    offset = i;
                                    break;
                                } else {
                                    // Safe to advance because we know that the peeked char is not
                                    // a dash.
                                    chars.next();
                                    continue;
                                }
                            },
                            // Got a single "-" at the end of the string. Consider it to be part of
                            // the comment.
                            None => {
                                // Normally, adding 1 to a byte offset in a `&str` could lead to an
                                // invalid access of a non-character boundary. In this case, we
                                // know that the last character was a "-", which is a single byte.
                                offset = i + 1;
                                break
                            }
                        }
                    },
                    _ if is_newline(c) => {
                        offset = i;
                        break
                    },
                    _ => continue,
                }
            },
            None => break,
        }
    }

    if offset < input.len() {
        IResult::Done(&input[offset..], &input[..offset])
    } else {
        IResult::Done("", input)
    }
}

/// Parse a single-line comment.
///
/// Defined in X.680 §12.6a
named!(single_line_comment<&str, &str>,
    delimited!(
        tag_s!("--"),
        take_until_single_line_comment_end,
        alt!(newline | tag_s!("--"))
    )
);

fn offset<T: AsRef<[u8]>>(base: T, sub: T) -> usize {
    let fst = base.as_ref().as_ptr();
    let snd = sub.as_ref().as_ptr();

    snd as usize - fst as usize
}

/// Version of `recognize!` macro that can be used for strings.
macro_rules! recognize_s (
  ($i:expr, $submac:ident!( $($args:tt)* )) => (
    {
      use ::nom::IResult;
      match $submac!($i, $($args)*) {
        IResult::Done(i,_) => {
          let index = offset($i, i);
          println!("dollar input: '{:?}', index: {}", $i, index);
          IResult::Done(i, &($i)[..index])
        },
        IResult::Error(e)      => return IResult::Error(e),
        IResult::Incomplete(i) => return IResult::Incomplete(i)
      }
    }
  );
  ($i:expr, $f:expr) => (
    recognize_s!($i, call!($f))
  );
);

/// Parse a multi-line comment. Multi-line comments in ASN.1 can be nested arbitrarily, so the
/// following is a valid comment:
///
/// ```notrust
/// /* Outer
///  * /* Inner */
///  * Still a comment
///  */
/// ```
///
/// Multi-line comments must be closed. If the end of the file is reached before the closing tag is
/// found, this is an error.
///
/// Defined in X.680 §12.6b
fn multi_line_comment(input: &str) -> IResult<&str, &str> {
    let mut offset = input.len();

    let (inside_comment, _) = try_parse!(input, tag_s!("/*"));
    let mut chars = inside_comment.char_indices().peekable();

    // The previous `try_parse!` has already consumed an opening tag, so the beginning nesting
    // level is 1.
    let mut nest_level: u32 = 1;
    loop {
        let next_char = chars.next();
        println!("next_char: '{:?}'", next_char);
        match next_char {
            Some((i, c)) => {
                match c {
                    '/' => {
                        match chars.peek() {
                            Some(&(_, pc)) => {
                                if pc == '*' {
                                    nest_level += 1;
                                } else {
                                    continue;
                                }
                            },
                            // Got a single "/" at the end of the string. This is a parse error, as
                            // all multi-line comments must be closed.
                            None => {
                                return IResult::Incomplete(Needed::Unknown);
                            }
                        }
                    },
                    '*' => {
                        match chars.peek() {
                            Some(&(_, pc)) => {
                                if pc == '/' {
                                    // About to close the comment.
                                    if nest_level == 1 {
                                        offset = i;
                                        break;
                                    }
                                    nest_level -= 1;
                                } else {
                                    continue;
                                }
                            },
                            // Got a single "*" at the end of the string. This is a parse error, as
                            // all multi-line comments must be closed.
                            None => {
                                return IResult::Incomplete(Needed::Size(1));
                            }
                        }
                    }
                    _ => continue,
                }
            },
            None => break,
        }
    }

    println!("inside_comment: '{:?}', offset: {:?}", inside_comment, offset);
    if offset + 2 <= inside_comment.len() {
        // Consume the closing comment characters
        IResult::Done(&inside_comment[(offset + 2)..], &inside_comment[..offset])
    } else {
        IResult::Done("", inside_comment)
    }
}

/// Parse a comment.
///
/// Defined in X.680 §12.6
named!(comment<&str, &str>,
    alt!(
        single_line_comment |
        multi_line_comment
    )
);

/// Parse an integer.
///
/// Defined in X.680 §12.8
named!(number<&str, u64>,
    map_res!(
        re_find!(r"^(0|[1-9]\d*)"),
        FromStr::from_str
    )
);

/// Parse an `f64`.
///
/// Defined in X.680 §12.9
named!(realnumber<&str, f64>,
   map_res!(
       re_find!(r"^\d+(\.\d*)?([eE]-?(0|[1-9]\d*))?"),
       FromStr::from_str
   )
);

#[cfg(test)]
mod tests {

    use super::{number, realnumber, single_line_comment, take_until_single_line_comment_end,
                newline, multi_line_comment};
    use nom::IResult::{Done, Incomplete};
    use nom::{IResult, Needed};

    /// Simple way of specifying an `IResult::Done` with no remaining input.
    macro_rules! done_result (
        ($res:expr) => (
            IResult::Done("", $res)
        )
    );

    #[test]
    fn test_newline() {
        assert_eq!(newline("\n"), done_result!("\n"));
        assert_eq!(newline("\x0B"), done_result!("\x0B"));
    }

    #[test]
    fn test_take_until_single_line_comment_end() {
        assert_eq!(take_until_single_line_comment_end(" thing\nmore"), Done("\nmore", " thing"));
        assert_eq!(take_until_single_line_comment_end(" thing\n"), Done("\n", " thing"));
        assert_eq!(take_until_single_line_comment_end(" thing--"), Done("--", " thing"));
        assert_eq!(take_until_single_line_comment_end(" dash-in-middle--"),
                   Done("--", " dash-in-middle"));
        assert_eq!(take_until_single_line_comment_end(" dash-in-middle\x0C"),
                   Done("\x0C", " dash-in-middle"));

        // Empty comments
        assert_eq!(take_until_single_line_comment_end("\n"), Done("\n", ""));
        assert_eq!(take_until_single_line_comment_end("--"), Done("--", ""));

        assert_eq!(take_until_single_line_comment_end("stuff-"), done_result!("stuff-"));
        assert_eq!(take_until_single_line_comment_end("-"), done_result!("-"));
    }

    #[test]
    fn test_single_line_comment() {
        assert_eq!(single_line_comment("-- thing\nmore"), Done("more", " thing"));
        assert_eq!(single_line_comment("-- thing--"), done_result!(" thing"));
        assert_eq!(single_line_comment("-- thing\n"), done_result!(" thing"));
        assert_eq!(single_line_comment("-- dash-in-middle--"), done_result!(" dash-in-middle"));
        assert_eq!(single_line_comment("-- dash-in-middle\x0C"), done_result!(" dash-in-middle"));
        assert_eq!(single_line_comment("--\n"), done_result!(""));
        assert_eq!(single_line_comment("----"), done_result!(""));
    }

    #[test]
    fn test_multi_line_comment() {
        assert_eq!(multi_line_comment("/* stuff */"), done_result!(" stuff "));
        assert_eq!(multi_line_comment("/* line1\nline2 */"), done_result!(" line1\nline2 "));
        assert_eq!(multi_line_comment("/**/"), done_result!(""));

        // Incomplete
        assert_eq!(multi_line_comment("/*/"), Incomplete(Needed::Unknown));
        assert_eq!(multi_line_comment("/**"), Incomplete(Needed::Size(1)));

        // Nested comments
        assert_eq!(multi_line_comment("/* Outer /* Inner */ Outer again */"),
                   done_result!(" Outer /* Inner */ Outer again "));
        assert_eq!(multi_line_comment("/* Out /* In */ Out2 /* In2 */ Out3 */"),
                   done_result!(" Out /* In */ Out2 /* In2 */ Out3 "));
        assert_eq!(multi_line_comment("/* Out /* In */ Out */ Extra */"),
                   Done(" Extra */", " Out /* In */ Out "));
    }

    #[test]
    fn test_number() {
        assert_eq!(number("0"), done_result!(0));
        assert_eq!(number("1"), done_result!(1));

        // Matches the first zero, but considers the second digit to be leftover input.
        assert_eq!(number("01"), Done("1", 0));
    }

    #[test]
    fn test_realnumber() {
        assert_eq!(realnumber("1"), done_result!(1.0));
        assert_eq!(realnumber("0"), done_result!(0.0));

        // Can have a leading zero
        assert_eq!(realnumber("00"), done_result!(0.0));
        assert_eq!(realnumber("01"), done_result!(1.0));

        // Can have a trailing period without a factional part
        assert_eq!(realnumber("1."), done_result!(1.0));
        assert_eq!(realnumber("1.0"), done_result!(1.0));
        assert_eq!(realnumber("1.001"), done_result!(1.001));

        // Exponents
        assert_eq!(realnumber("1.1e3"), done_result!(1100.0));
        assert_eq!(realnumber("1.1e-3"), done_result!(0.0011));
        assert_eq!(realnumber("1.e3"), done_result!(1000.0));
        assert_eq!(realnumber("1e3"), done_result!(1000.0));
        assert_eq!(realnumber("1.1E3"), done_result!(1100.0));
        assert_eq!(realnumber("1.1E-3"), done_result!(0.0011));

        // Leading zero in exponent
        assert_eq!(realnumber("1.1E-03"), Done("3", 1.1));
        assert_eq!(realnumber("1.1E03"), Done("3", 1.1));
    }

}
<commit_msg>Parser for `comment`<commit_after>//! Taken from http://www.itu.int/rec/T-REC-X.680-200811-I

#![allow(dead_code)] // Until parser is complete. Too noisy otherwise

#[macro_use]
extern crate nom;

extern crate regex;

use std::str::FromStr;
use nom::{IResult, Needed};

/// Returns `true` if the character is a newline character according to ASN.1.
///
/// Defined in X.680 §12.1.6
fn is_newline(ch: char) -> bool {
    match ch {
        // LINE FEED
        '\n' => true,

        // VERTICAL TABULATION
        '\x0B' => true,

        // FORM FEED
        '\x0C' => true,

        // CARRIAGE RETURN
        '\x0D' => true,
        _ => false,
    }
}

named!(newline<&str, &str>,
       alt!(
           tag_s!("\n") |
           tag_s!("\x0B") |
           tag_s!("\x0C") |
           tag_s!("\x0D")
       )
);

/// Returns `true` if the character is a whitespace character according to ASN.1.
///
/// Defined in X.680 §12.1.6
fn is_whitespace(ch: char) -> bool {
    match ch {
        ' ' | '\t' => true,

        // All newline characters are also whitespace
        _ if is_newline(ch) => true,
        _ => false,
    }
}

/// Takes input until it finds the end of a single-line comment. This will not consume the ending
/// character(s) of the comment.
fn take_until_single_line_comment_end(input: &str) -> IResult<&str, &str> {
    let mut offset = input.len();
    let mut chars = input.char_indices().peekable();
    loop {
        match chars.next() {
            Some((i, c)) => {
                match c {
                    '-' => {
                        match chars.peek() {
                            Some(&(_, pc)) => {
                                if pc == '-' {
                                    offset = i;
                                    break;
                                } else {
                                    // Safe to advance because we know that the peeked char is not
                                    // a dash.
                                    chars.next();
                                    continue;
                                }
                            },
                            // Got a single "-" at the end of the string. Consider it to be part of
                            // the comment.
                            None => {
                                // Normally, adding 1 to a byte offset in a `&str` could lead to an
                                // invalid access of a non-character boundary. In this case, we
                                // know that the last character was a "-", which is a single byte.
                                offset = i + 1;
                                break
                            }
                        }
                    },
                    _ if is_newline(c) => {
                        offset = i;
                        break
                    },
                    _ => continue,
                }
            },
            None => break,
        }
    }

    if offset < input.len() {
        IResult::Done(&input[offset..], &input[..offset])
    } else {
        IResult::Done("", input)
    }
}

/// Parse a single-line comment.
///
/// Defined in X.680 §12.6a
named!(single_line_comment<&str, &str>,
    delimited!(
        tag_s!("--"),
        take_until_single_line_comment_end,
        alt!(newline | tag_s!("--"))
    )
);

fn offset<T: AsRef<[u8]>>(base: T, sub: T) -> usize {
    let fst = base.as_ref().as_ptr();
    let snd = sub.as_ref().as_ptr();

    snd as usize - fst as usize
}

/// Version of `recognize!` macro that can be used for strings.
macro_rules! recognize_s (
  ($i:expr, $submac:ident!( $($args:tt)* )) => (
    {
      use ::nom::IResult;
      match $submac!($i, $($args)*) {
        IResult::Done(i,_) => {
          let index = offset($i, i);
          println!("dollar input: '{:?}', index: {}", $i, index);
          IResult::Done(i, &($i)[..index])
        },
        IResult::Error(e)      => return IResult::Error(e),
        IResult::Incomplete(i) => return IResult::Incomplete(i)
      }
    }
  );
  ($i:expr, $f:expr) => (
    recognize_s!($i, call!($f))
  );
);

/// Parse a multi-line comment. Multi-line comments in ASN.1 can be nested arbitrarily, so the
/// following is a valid comment:
///
/// ```notrust
/// /* Outer
///  * /* Inner */
///  * Still a comment
///  */
/// ```
///
/// Multi-line comments must be closed. If the end of the file is reached before the closing tag is
/// found, this is an error.
///
/// Defined in X.680 §12.6b
fn multi_line_comment(input: &str) -> IResult<&str, &str> {
    let mut offset = input.len();

    let (inside_comment, _) = try_parse!(input, tag_s!("/*"));
    let mut chars = inside_comment.char_indices().peekable();

    // The previous `try_parse!` has already consumed an opening tag, so the beginning nesting
    // level is 1.
    let mut nest_level: u32 = 1;
    loop {
        let next_char = chars.next();
        println!("next_char: '{:?}'", next_char);
        match next_char {
            Some((i, c)) => {
                match c {
                    '/' => {
                        match chars.peek() {
                            Some(&(_, pc)) => {
                                if pc == '*' {
                                    nest_level += 1;
                                } else {
                                    continue;
                                }
                            },
                            // Got a single "/" at the end of the string. This is a parse error, as
                            // all multi-line comments must be closed.
                            None => {
                                return IResult::Incomplete(Needed::Unknown);
                            }
                        }
                    },
                    '*' => {
                        match chars.peek() {
                            Some(&(_, pc)) => {
                                if pc == '/' {
                                    // About to close the comment.
                                    if nest_level == 1 {
                                        offset = i;
                                        break;
                                    }
                                    nest_level -= 1;
                                } else {
                                    continue;
                                }
                            },
                            // Got a single "*" at the end of the string. This is a parse error, as
                            // all multi-line comments must be closed.
                            None => {
                                return IResult::Incomplete(Needed::Size(1));
                            }
                        }
                    }
                    _ => continue,
                }
            },
            None => break,
        }
    }

    println!("inside_comment: '{:?}', offset: {:?}", inside_comment, offset);
    if offset + 2 <= inside_comment.len() {
        // Consume the closing comment characters
        IResult::Done(&inside_comment[(offset + 2)..], &inside_comment[..offset])
    } else {
        IResult::Done("", inside_comment)
    }
}

/// Parse a comment.
///
/// Defined in X.680 §12.6
named!(comment<&str, &str>,
    alt!(
        single_line_comment |
        multi_line_comment
    )
);

/// Parse an integer.
///
/// Defined in X.680 §12.8
named!(number<&str, u64>,
    map_res!(
        re_find!(r"^(0|[1-9]\d*)"),
        FromStr::from_str
    )
);

/// Parse an `f64`.
///
/// Defined in X.680 §12.9
named!(realnumber<&str, f64>,
   map_res!(
       re_find!(r"^\d+(\.\d*)?([eE]-?(0|[1-9]\d*))?"),
       FromStr::from_str
   )
);

#[cfg(test)]
mod tests {

    use super::{number, realnumber, single_line_comment, take_until_single_line_comment_end,
                newline, multi_line_comment, comment};
    use nom::IResult::{Done, Incomplete};
    use nom::{IResult, Needed};

    /// Simple way of specifying an `IResult::Done` with no remaining input.
    macro_rules! done_result (
        ($res:expr) => (
            IResult::Done("", $res)
        )
    );

    #[test]
    fn test_newline() {
        assert_eq!(newline("\n"), done_result!("\n"));
        assert_eq!(newline("\x0B"), done_result!("\x0B"));
    }

    #[test]
    fn test_take_until_single_line_comment_end() {
        assert_eq!(take_until_single_line_comment_end(" thing\nmore"), Done("\nmore", " thing"));
        assert_eq!(take_until_single_line_comment_end(" thing\n"), Done("\n", " thing"));
        assert_eq!(take_until_single_line_comment_end(" thing--"), Done("--", " thing"));
        assert_eq!(take_until_single_line_comment_end(" dash-in-middle--"),
                   Done("--", " dash-in-middle"));
        assert_eq!(take_until_single_line_comment_end(" dash-in-middle\x0C"),
                   Done("\x0C", " dash-in-middle"));

        // Empty comments
        assert_eq!(take_until_single_line_comment_end("\n"), Done("\n", ""));
        assert_eq!(take_until_single_line_comment_end("--"), Done("--", ""));

        assert_eq!(take_until_single_line_comment_end("stuff-"), done_result!("stuff-"));
        assert_eq!(take_until_single_line_comment_end("-"), done_result!("-"));
    }

    fn single_line_comment_tests<F>(parser: F)
        where F : Fn(&str) -> IResult<&str, &str> {

        assert_eq!(parser("-- thing\nmore"), Done("more", " thing"));
        assert_eq!(parser("-- thing--"), done_result!(" thing"));
        assert_eq!(parser("-- thing\n"), done_result!(" thing"));
        assert_eq!(parser("-- dash-in-middle--"), done_result!(" dash-in-middle"));
        assert_eq!(parser("-- dash-in-middle\x0C"), done_result!(" dash-in-middle"));

        // "/*" and "*/ have no special meaning in single-line comment.
        assert_eq!(single_line_comment("--/* still\nsingle"), Done("single", "/* still"));
        assert_eq!(single_line_comment("--*/* still\nsingle"), Done("single", "*/* still"));
        assert_eq!(single_line_comment("--*/ *//* still\nsingle"),
                   Done("single", "*/ *//* still"));

        assert_eq!(single_line_comment("--\n"), done_result!(""));
        assert_eq!(single_line_comment("----"), done_result!(""));
    }

    #[test]
    fn test_single_line_comment() {
        single_line_comment_tests(single_line_comment);
    }

    fn multi_line_comment_tests<F>(parser: F)
        where F : Fn(&str) -> IResult<&str, &str> {

        assert_eq!(parser("/* stuff */"), done_result!(" stuff "));
        assert_eq!(parser("/* line1\nline2 */"), done_result!(" line1\nline2 "));
        assert_eq!(parser("/**/"), done_result!(""));

        // "--" in multi-line comment has no special meaning.
        assert_eq!(parser("/* -- */"), done_result!(" -- "));

        // Incomplete
        assert_eq!(parser("/*/"), Incomplete(Needed::Unknown));
        assert_eq!(parser("/**"), Incomplete(Needed::Size(1)));

        // Nested comments
        assert_eq!(parser("/* Outer /* Inner */ Outer again */"),
                   done_result!(" Outer /* Inner */ Outer again "));
        assert_eq!(parser("/* Out /* In */ Out2 /* In2 */ Out3 */"),
                   done_result!(" Out /* In */ Out2 /* In2 */ Out3 "));
        assert_eq!(parser("/* Out /* In */ Out */ Extra */"),
                   Done(" Extra */", " Out /* In */ Out "));
    }

    #[test]
    fn test_multi_line_comment() {
        multi_line_comment_tests(multi_line_comment);
    }

    #[test]
    fn test_comment() {
        single_line_comment_tests(comment);
        multi_line_comment_tests(comment);
    }

    #[test]
    fn test_number() {
        assert_eq!(number("0"), done_result!(0));
        assert_eq!(number("1"), done_result!(1));

        // Matches the first zero, but considers the second digit to be leftover input.
        assert_eq!(number("01"), Done("1", 0));
    }

    #[test]
    fn test_realnumber() {
        assert_eq!(realnumber("1"), done_result!(1.0));
        assert_eq!(realnumber("0"), done_result!(0.0));

        // Can have a leading zero
        assert_eq!(realnumber("00"), done_result!(0.0));
        assert_eq!(realnumber("01"), done_result!(1.0));

        // Can have a trailing period without a factional part
        assert_eq!(realnumber("1."), done_result!(1.0));
        assert_eq!(realnumber("1.0"), done_result!(1.0));
        assert_eq!(realnumber("1.001"), done_result!(1.001));

        // Exponents
        assert_eq!(realnumber("1.1e3"), done_result!(1100.0));
        assert_eq!(realnumber("1.1e-3"), done_result!(0.0011));
        assert_eq!(realnumber("1.e3"), done_result!(1000.0));
        assert_eq!(realnumber("1e3"), done_result!(1000.0));
        assert_eq!(realnumber("1.1E3"), done_result!(1100.0));
        assert_eq!(realnumber("1.1E-3"), done_result!(0.0011));

        // Leading zero in exponent
        assert_eq!(realnumber("1.1E-03"), Done("3", 1.1));
        assert_eq!(realnumber("1.1E03"), Done("3", 1.1));
    }

}
<|endoftext|>


<commit_before>#![doc(html_logo_url = "https://zzeroo.github.io/share/zzeroo-logo.png",
       html_favicon_url = "https://zzeroo.github.io/share/favicon.ico",
html_root_url = "https://zzeroo.com/")]
//! This is an 'hopefully' safe Rust interface for the [libmodbus](http://libmodbus.org/) C library from
//! http://libmodbus.org/.
//!
//! [libmodbus](http://libmodbus.org/) is a library to send/receive data with a device which respects the Modbus
//! protocol.
//! This library contains various backends to communicate over different networks (eg. serial in RTU mode or Ethernet
//! in TCP/IPv6).
//! The http://www.modbus.org site provides documentation about the protocol at http://www.modbus.org/specs.php.
//!
//! libmodbus provides an abstraction of the lower communication layers and offers the same API on all supported
//! platforms.
//!
//! This documentation presents an overview of libmodbus concepts, describes how libmodbus abstracts Modbus
//! communication with
//! different hardware and platforms and provides a reference manual for the functions provided by the libmodbus
//! library.
//!
//! **This project hosts the original libmodbus documentation, used here, as well.**

//! Please have a look at: [libmodbus/libmodbus.html](../libmodbus/libmodbus.html)
//!
//! ## Contexts
//!
//! The Modbus protocol contains many variants (eg. serial RTU or Ehternet TCP), to ease the implementation of a
//! variant, the library was designed to use a backend for each variant.
//!
//! **libmodbus-rs provides traits and matching implementations for these variants.** See
//! [ModbusRTU](trait.ModbusRTU.html) (trait), [Modbus::new_rtu()](struct.Modbus.html#method.new_rtu) (implementation)
//! or [ModbusTCP](trait.ModbusTCP.html) (trait).
//!
//! The backends are also a convenient way to fulfill other requirements (eg. real-time operations). Each backend
//! offers a specific function to create a new modbus_t context.
//! The modbus_t context is an opaque structure containing all necessary information to establish a connection with
//! others Modbus devices according to the selected variant.
//!
//! You can choose the best context for your needs among:
//!
//! * [RTU Context](trait.ModbusRTU.html)
//! * [TCP (IPv4) Context](trait.ModbusTCP.html)
//! * [TCP PI (IPv4 and IPv6) Context](trait.ModbusTCPPI.html)
//!
//! ### [RTU Context](trait.ModbusRTU.html)
//!
//! The RTU backend (Remote Terminal Unit) is used in serial communication and makes use of a compact, binary
//! representation of the data for protocol communication.
//! The RTU format follows the commands/data with a cyclic redundancy check checksum as an error check mechanism to
//! ensure the reliability of data.
//! Modbus RTU is the most common implementation available for Modbus. A Modbus RTU message must be transmitted
//! continuously without inter-character hesitations
//! (extract from Wikipedia, Modbus, http://en.wikipedia.org/wiki/Modbus (as of Mar. 13, 2011, 20:51 GMT).
//!
//! The Modbus RTU framing calls a slave, a device/service which handle Modbus requests, and a master, a client which
//! send requests. The communication is always initiated by the master.
//!
//! Many Modbus devices can be connected together on the same physical link so before sending a message, you must set
//! the slave (receiver) with modbus_set_slave(3).
//! If you’re running a slave, its slave number will be used to filter received messages.
//!
//! The libmodbus implementation of RTU isn’t time based as stated in original Modbus specification,
//! instead all bytes are sent as fast as possible and a response or an indication is considered complete when all
//! expected characters have been received.
//! This implementation offers very fast communication but you must take care to set a response timeout of slaves less
//! than response timeout of master
//! (ortherwise other slaves may ignore master requests when one of the slave is not responding).
//!
//! * Create a Modbus RTU context
//!     - [`new_rtu()`](struct.Modbus.html#method.new_rtu)
//!
//! * Set the serial mode
//! - [`rtu_get_serial_mode()`](struct.Modbus.html#method.rtu_get_serial_mode),
//! [`rtu_set_serial_mode()`](struct.Modbus.html#method.rtu_set_serial_mode),
//! [`rtu_get_rts()`](struct.Modbus.html#method.rtu_get_rts), [`rtu_set_rts()`](struct.Modbus.html#method.rtu_set_rts),
//! [`rtu_set_custom_rts()`](struct.Modbus.html#method.rtu_set_custom_rts),
//! [`rtu_get_rts_delay()`](struct.Modbus.html#method.rtu_get_rts_delay),
//! [`rtu_set_rts_delay()`](struct.Modbus.html#method.rtu_set_rts_delay)
//!
//! ### [TCP (IPv4) Context](trait.ModbusTCP.html)
//! The TCP backend implements a Modbus variant used for communications over TCP/IPv4 networks.
//! It does not require a checksum calculation as lower layer takes care of the same.
//!
//! * Create a Modbus TCP context
//!     - [`new_tcp()`](struct.Modbus.html#method.new_tcp)
//!
//! ### [TCP PI (IPv4 and IPv6) Context](trait.ModbusTCPPI.html)
//! The TCP PI (Protocol Independent) backend implements a Modbus variant used for communications over TCP IPv4 and
//! IPv6 networks.
//! It does not require a checksum calculation as lower layer takes care of the same.
//!
//! Contrary to the TCP IPv4 only backend, the TCP PI backend offers hostname resolution but it consumes about 1Kb of
//! additional memory.
//!
//! * Create a Modbus TCP context
//!     - [`new_tcp_pi()`](struct.Modbus.html#method.new_tcp_pi)
//!
//! ### Common
//!
//! Common methods to modify or change the current modbus context. Some of these function are not nessesary in Rust (e.g. because the Drop trait and so on)
//!
//! * Free libmodbus context
//!     - [`free()`](struct.Modbus.html#method.free) **It should normaly not nessesary to call this function.**

//!     Memory handling under Rust controlls the [`Drop trait`](https://doc.rust-lang.org/std/ops/trait.Drop.html) in "the book" you find [more information about](https://doc.rust-lang.org/book/ffi.html#destructors).
//! * Set slave ID
//!     - [`set_slave()`](struct.Modbus.html#method.set_slave)
//! * Enable debug mode
//!     - [`set_debug()`](struct.Modbus.html#method.set_debug)
//! * Timeout settings
//!     - [`get_byte_timeout()`](struct.Modbus.html#method.get_byte_timeout) [`set_byte_timeout()`](struct.Modbus.html#method.set_byte_timeout) [`get_response_timeout()`](struct.Modbus.html#method.get_response_timeout) [`set_response_timeout()`](struct.Modbus.html#method.set_response_timeout)
//! * Error recovery mod
//!     - [`set_error_recovery()`](struct.Modbus.html#method.set_error_recovery)
//! * Setter/getter of internal socket
//!     - [`set_socket()`](struct.Modbus.html#method.set_socket) [`get_socket()`](struct.Modbus.html#method.get_socket)
//! * Information about header
//!     - [`get_header_length()`](struct.Modbus.html#method.get_header_length)
//!
//! ### Connection
//!
//! ### [`Client`](trait.ModbusClient.html)
//!
//! The Modbus protocol defines different data types and functions to read and write them from/to remote devices.
//! The following functions are used by the clients to send Modbus requests:
//!
//! * Read data
//! - [`read_bits()`](struct.Modbus.html#method.read_bits),
//! [`read_input_bits()`](struct.Modbus.html#method.read_input_bits),
//! [`read_registers()`](struct.Modbus.html#method.read_registers),
//! [`read_input_registers()`](struct.Modbus.html#method.read_input_registers),
//! [`report_slave_id()`](struct.Modbus.html#method.report_slave_id)
//! * Write data
//! - [`write_bit()`](struct.Modbus.html#method.write_bit),
//! [`write_register()`](struct.Modbus.html#method.write_register),
//! [`write_bits()`](struct.Modbus.html#method.write_bits),
//! [`write_registers()`](struct.Modbus.html#method.write_registers)
//! * Write and read data
//!     - [`write_and_read_registers()`](struct.Modbus.html#method.write_and_read_registers)
//! * Raw requests
//! - [`send_raw_request()`](struct.Modbus.html#method.send_raw_request),
//! [`receive_confirmation()`](struct.Modbus.html#method.receive_confirmation)
//! * Reply an exception
//!     - [`reply_exception()`](struct.Modbus.html#method.reply_exception)
//!
//! ### [`Server`](trait.ModbusServer.html)
//!
//! The server is waiting for request from clients and must answer when it is concerned by the request.
//!
//! In TCP , you must not use the usual [`connect()`](struct.Modbus.html#method.connect) to establish the connection
//! but a pair of accept/listen calls
//!
//! * [`tcp_listen()`](struct.Modbus.html#method.tcp_listen), [`tcp_accept()`](struct.Modbus.html#method.tcp_accept),
//! [`tcp_pi_listen`()](struct.Modbus.html#method.tcp_pi_listen),
//! [`tcp_pi_accept`()](struct.Modbus.html#method.tcp_pi_accept)
//!
//! then the data can be received with
//!
//! * [`receive()`](struct.Modbus.html#method.receive)
//!
//! and a response can be send with
//!
//! * [`reply()`](struct.Modbus.html#method.reply), [`reply_exception()`](struct.Modbus.html#method.reply_exception)
//!
//! To handle the mapping of your Modbus data, you must use a [`ModbusMapping`](struct.ModbusMapping.html) struct:
//! [`ModbusMapping::new()`](struct.ModbusMapping.html#method.new)
//!

// `error_chain!` can recurse deeply(3)
#![recursion_limit = "1024"]

extern crate libc;
extern crate libmodbus_sys;
#[macro_use]
extern crate error_chain;

mod enums;
mod modbus_client;
mod modbus_mapping;
mod modbus_rtu;
mod modbus_server;
mod modbus_tcp_pi;
mod modbus_tcp;
mod modbus;
pub mod errors;

pub use self::enums::{ErrorRecoveryMode, Exception, FunctionCode};
pub use self::modbus_client::ModbusClient;
pub use self::modbus_mapping::ModbusMapping;
pub use self::modbus_rtu::{ModbusRTU, RequestToSendMode, SerialMode};
pub use self::modbus_server::ModbusServer;
pub use self::modbus_tcp_pi::ModbusTCPPI;
pub use self::modbus_tcp::ModbusTCP;
pub use self::modbus::Modbus;
pub use self::modbus::{set_bits_from_byte, set_bits_from_bytes, get_byte_from_bits,
    get_float_abcd, set_float_abcd, get_float_badc, set_float_badc,
    get_float_cdab, set_float_cdab, get_float_dcba, set_float_dcba,
};

pub use libmodbus_sys::MODBUS_TCP_DEFAULT_PORT;
pub use libmodbus_sys::MODBUS_TCP_MAX_ADU_LENGTH;
pub use libmodbus_sys::MODBUS_MAX_ADU_LENGTH;
pub use libmodbus_sys::MODBUS_MAX_PDU_LENGTH;
<commit_msg>Add more libmodbus constants<commit_after>#![doc(html_logo_url = "https://zzeroo.github.io/share/zzeroo-logo.png",
       html_favicon_url = "https://zzeroo.github.io/share/favicon.ico",
html_root_url = "https://zzeroo.com/")]
//! This is an 'hopefully' safe Rust interface for the [libmodbus](http://libmodbus.org/) C library from
//! http://libmodbus.org/.
//!
//! [libmodbus](http://libmodbus.org/) is a library to send/receive data with a device which respects the Modbus
//! protocol.
//! This library contains various backends to communicate over different networks (eg. serial in RTU mode or Ethernet
//! in TCP/IPv6).
//! The http://www.modbus.org site provides documentation about the protocol at http://www.modbus.org/specs.php.
//!
//! libmodbus provides an abstraction of the lower communication layers and offers the same API on all supported
//! platforms.
//!
//! This documentation presents an overview of libmodbus concepts, describes how libmodbus abstracts Modbus
//! communication with
//! different hardware and platforms and provides a reference manual for the functions provided by the libmodbus
//! library.
//!
//! **This project hosts the original libmodbus documentation, used here, as well.**

//! Please have a look at: [libmodbus/libmodbus.html](../libmodbus/libmodbus.html)
//!
//! ## Contexts
//!
//! The Modbus protocol contains many variants (eg. serial RTU or Ehternet TCP), to ease the implementation of a
//! variant, the library was designed to use a backend for each variant.
//!
//! **libmodbus-rs provides traits and matching implementations for these variants.** See
//! [ModbusRTU](trait.ModbusRTU.html) (trait), [Modbus::new_rtu()](struct.Modbus.html#method.new_rtu) (implementation)
//! or [ModbusTCP](trait.ModbusTCP.html) (trait).
//!
//! The backends are also a convenient way to fulfill other requirements (eg. real-time operations). Each backend
//! offers a specific function to create a new modbus_t context.
//! The modbus_t context is an opaque structure containing all necessary information to establish a connection with
//! others Modbus devices according to the selected variant.
//!
//! You can choose the best context for your needs among:
//!
//! * [RTU Context](trait.ModbusRTU.html)
//! * [TCP (IPv4) Context](trait.ModbusTCP.html)
//! * [TCP PI (IPv4 and IPv6) Context](trait.ModbusTCPPI.html)
//!
//! ### [RTU Context](trait.ModbusRTU.html)
//!
//! The RTU backend (Remote Terminal Unit) is used in serial communication and makes use of a compact, binary
//! representation of the data for protocol communication.
//! The RTU format follows the commands/data with a cyclic redundancy check checksum as an error check mechanism to
//! ensure the reliability of data.
//! Modbus RTU is the most common implementation available for Modbus. A Modbus RTU message must be transmitted
//! continuously without inter-character hesitations
//! (extract from Wikipedia, Modbus, http://en.wikipedia.org/wiki/Modbus (as of Mar. 13, 2011, 20:51 GMT).
//!
//! The Modbus RTU framing calls a slave, a device/service which handle Modbus requests, and a master, a client which
//! send requests. The communication is always initiated by the master.
//!
//! Many Modbus devices can be connected together on the same physical link so before sending a message, you must set
//! the slave (receiver) with modbus_set_slave(3).
//! If you’re running a slave, its slave number will be used to filter received messages.
//!
//! The libmodbus implementation of RTU isn’t time based as stated in original Modbus specification,
//! instead all bytes are sent as fast as possible and a response or an indication is considered complete when all
//! expected characters have been received.
//! This implementation offers very fast communication but you must take care to set a response timeout of slaves less
//! than response timeout of master
//! (ortherwise other slaves may ignore master requests when one of the slave is not responding).
//!
//! * Create a Modbus RTU context
//!     - [`new_rtu()`](struct.Modbus.html#method.new_rtu)
//!
//! * Set the serial mode
//! - [`rtu_get_serial_mode()`](struct.Modbus.html#method.rtu_get_serial_mode),
//! [`rtu_set_serial_mode()`](struct.Modbus.html#method.rtu_set_serial_mode),
//! [`rtu_get_rts()`](struct.Modbus.html#method.rtu_get_rts), [`rtu_set_rts()`](struct.Modbus.html#method.rtu_set_rts),
//! [`rtu_set_custom_rts()`](struct.Modbus.html#method.rtu_set_custom_rts),
//! [`rtu_get_rts_delay()`](struct.Modbus.html#method.rtu_get_rts_delay),
//! [`rtu_set_rts_delay()`](struct.Modbus.html#method.rtu_set_rts_delay)
//!
//! ### [TCP (IPv4) Context](trait.ModbusTCP.html)
//! The TCP backend implements a Modbus variant used for communications over TCP/IPv4 networks.
//! It does not require a checksum calculation as lower layer takes care of the same.
//!
//! * Create a Modbus TCP context
//!     - [`new_tcp()`](struct.Modbus.html#method.new_tcp)
//!
//! ### [TCP PI (IPv4 and IPv6) Context](trait.ModbusTCPPI.html)
//! The TCP PI (Protocol Independent) backend implements a Modbus variant used for communications over TCP IPv4 and
//! IPv6 networks.
//! It does not require a checksum calculation as lower layer takes care of the same.
//!
//! Contrary to the TCP IPv4 only backend, the TCP PI backend offers hostname resolution but it consumes about 1Kb of
//! additional memory.
//!
//! * Create a Modbus TCP context
//!     - [`new_tcp_pi()`](struct.Modbus.html#method.new_tcp_pi)
//!
//! ### Common
//!
//! Common methods to modify or change the current modbus context. Some of these function are not nessesary in Rust (e.g. because the Drop trait and so on)
//!
//! * Free libmodbus context
//!     - [`free()`](struct.Modbus.html#method.free) **It should normaly not nessesary to call this function.**

//!     Memory handling under Rust controlls the [`Drop trait`](https://doc.rust-lang.org/std/ops/trait.Drop.html) in "the book" you find [more information about](https://doc.rust-lang.org/book/ffi.html#destructors).
//! * Set slave ID
//!     - [`set_slave()`](struct.Modbus.html#method.set_slave)
//! * Enable debug mode
//!     - [`set_debug()`](struct.Modbus.html#method.set_debug)
//! * Timeout settings
//!     - [`get_byte_timeout()`](struct.Modbus.html#method.get_byte_timeout) [`set_byte_timeout()`](struct.Modbus.html#method.set_byte_timeout) [`get_response_timeout()`](struct.Modbus.html#method.get_response_timeout) [`set_response_timeout()`](struct.Modbus.html#method.set_response_timeout)
//! * Error recovery mod
//!     - [`set_error_recovery()`](struct.Modbus.html#method.set_error_recovery)
//! * Setter/getter of internal socket
//!     - [`set_socket()`](struct.Modbus.html#method.set_socket) [`get_socket()`](struct.Modbus.html#method.get_socket)
//! * Information about header
//!     - [`get_header_length()`](struct.Modbus.html#method.get_header_length)
//!
//! ### Connection
//!
//! ### [`Client`](trait.ModbusClient.html)
//!
//! The Modbus protocol defines different data types and functions to read and write them from/to remote devices.
//! The following functions are used by the clients to send Modbus requests:
//!
//! * Read data
//! - [`read_bits()`](struct.Modbus.html#method.read_bits),
//! [`read_input_bits()`](struct.Modbus.html#method.read_input_bits),
//! [`read_registers()`](struct.Modbus.html#method.read_registers),
//! [`read_input_registers()`](struct.Modbus.html#method.read_input_registers),
//! [`report_slave_id()`](struct.Modbus.html#method.report_slave_id)
//! * Write data
//! - [`write_bit()`](struct.Modbus.html#method.write_bit),
//! [`write_register()`](struct.Modbus.html#method.write_register),
//! [`write_bits()`](struct.Modbus.html#method.write_bits),
//! [`write_registers()`](struct.Modbus.html#method.write_registers)
//! * Write and read data
//!     - [`write_and_read_registers()`](struct.Modbus.html#method.write_and_read_registers)
//! * Raw requests
//! - [`send_raw_request()`](struct.Modbus.html#method.send_raw_request),
//! [`receive_confirmation()`](struct.Modbus.html#method.receive_confirmation)
//! * Reply an exception
//!     - [`reply_exception()`](struct.Modbus.html#method.reply_exception)
//!
//! ### [`Server`](trait.ModbusServer.html)
//!
//! The server is waiting for request from clients and must answer when it is concerned by the request.
//!
//! In TCP , you must not use the usual [`connect()`](struct.Modbus.html#method.connect) to establish the connection
//! but a pair of accept/listen calls
//!
//! * [`tcp_listen()`](struct.Modbus.html#method.tcp_listen), [`tcp_accept()`](struct.Modbus.html#method.tcp_accept),
//! [`tcp_pi_listen`()](struct.Modbus.html#method.tcp_pi_listen),
//! [`tcp_pi_accept`()](struct.Modbus.html#method.tcp_pi_accept)
//!
//! then the data can be received with
//!
//! * [`receive()`](struct.Modbus.html#method.receive)
//!
//! and a response can be send with
//!
//! * [`reply()`](struct.Modbus.html#method.reply), [`reply_exception()`](struct.Modbus.html#method.reply_exception)
//!
//! To handle the mapping of your Modbus data, you must use a [`ModbusMapping`](struct.ModbusMapping.html) struct:
//! [`ModbusMapping::new()`](struct.ModbusMapping.html#method.new)
//!

// `error_chain!` can recurse deeply(3)
#![recursion_limit = "1024"]

extern crate libc;
extern crate libmodbus_sys;
#[macro_use]
extern crate error_chain;

mod enums;
mod modbus_client;
mod modbus_mapping;
mod modbus_rtu;
mod modbus_server;
mod modbus_tcp_pi;
mod modbus_tcp;
mod modbus;
pub mod errors;

pub use self::enums::{ErrorRecoveryMode, Exception, FunctionCode};
pub use self::modbus_client::ModbusClient;
pub use self::modbus_mapping::ModbusMapping;
pub use self::modbus_rtu::{ModbusRTU, RequestToSendMode, SerialMode};
pub use self::modbus_server::ModbusServer;
pub use self::modbus_tcp_pi::ModbusTCPPI;
pub use self::modbus_tcp::ModbusTCP;
pub use self::modbus::Modbus;
pub use self::modbus::{set_bits_from_byte, set_bits_from_bytes, get_byte_from_bits,
    get_float_abcd, set_float_abcd, get_float_badc, set_float_badc,
    get_float_cdab, set_float_cdab, get_float_dcba, set_float_dcba,
};

pub use libmodbus_sys::MODBUS_MAX_PDU_LENGTH;
pub use libmodbus_sys::MODBUS_MAX_ADU_LENGTH;
pub use libmodbus_sys::MODBUS_ENOBASE;
pub use libmodbus_sys::MODBUS_TCP_DEFAULT_PORT;
pub use libmodbus_sys::MODBUS_TCP_SLAVE;
pub use libmodbus_sys::MODBUS_TCP_MAX_ADU_LENGTH;
pub use libmodbus_sys::MODBUS_RTU_MAX_ADU_LENGTH;
<|endoftext|>


<commit_before>//! This crate provides native rust implementations of
//! Image encoders and decoders and basic image manipulation
//! functions.

#![crate_name = "image"]
#![crate_type = "rlib"]

#![warn(missing_docs)]
#![warn(unused_qualifications)]
#![warn(unused_typecasts)]
#![feature(macro_rules)]
#![feature(if_let)]
// necessary for Primitive trait
#![feature(default_type_params)]

extern crate flate;

pub use color::ColorType as ColorType;
pub use traits::Primitive;

pub use color::ColorType:: {
    Grey,
    RGB,
    Palette,
    GreyA,
    RGBA,
};
pub use color:: {
    Pixel,

    Luma,
    LumaA,
    Rgb,
    Rgba,
};

pub use image::ImageDecoder as ImageDecoder;
pub use image::ImageError as ImageError;
pub use image::ImageResult as ImageResult;
pub use image::ImageFormat as ImageFormat;
pub use imageops::FilterType as FilterType;

pub use imageops:: {
    Triangle,
    Nearest,
    CatmullRom,
    Gaussian,
    Lanczos3
};

pub use image::ImageFormat:: {
    PNG,
    JPEG,
    GIF,
    WEBP,
    PPM
};

//Image Types
pub use image::SubImage as SubImage;
pub use image::ImageBuf as ImageBuf;
pub use dynimage::DynamicImage as DynamicImage;

//Traits
pub use image::GenericImage as GenericImage;

//Iterators
pub use image::Pixels as Pixels;
pub use image::MutPixels as MutPixels;

///opening and loading images
pub use dynimage:: {
    open,
    load,
    load_from_memory,
    save_buffer,
};
pub use dynimage::DynamicImage:: {
    ImageRgb8,
    ImageRgba8,
    ImageLuma8,
    ImageLumaA8,
};

//Image Processing Functions
pub mod imageops;

//Image Codecs
pub mod webp;
pub mod ppm;
pub mod png;
pub mod jpeg;
pub mod gif;
pub mod tiff;
pub mod tga;

mod image;
mod dynimage;
mod color;
mod traits;
<commit_msg>Do not enable if_let explicitly<commit_after>//! This crate provides native rust implementations of
//! Image encoders and decoders and basic image manipulation
//! functions.

#![crate_name = "image"]
#![crate_type = "rlib"]

#![warn(missing_docs)]
#![warn(unused_qualifications)]
#![warn(unused_typecasts)]
#![feature(macro_rules)]
// necessary for Primitive trait
#![feature(default_type_params)]

extern crate flate;

pub use color::ColorType as ColorType;
pub use traits::Primitive;

pub use color::ColorType:: {
    Grey,
    RGB,
    Palette,
    GreyA,
    RGBA,
};
pub use color:: {
    Pixel,

    Luma,
    LumaA,
    Rgb,
    Rgba,
};

pub use image::ImageDecoder as ImageDecoder;
pub use image::ImageError as ImageError;
pub use image::ImageResult as ImageResult;
pub use image::ImageFormat as ImageFormat;
pub use imageops::FilterType as FilterType;

pub use imageops:: {
    Triangle,
    Nearest,
    CatmullRom,
    Gaussian,
    Lanczos3
};

pub use image::ImageFormat:: {
    PNG,
    JPEG,
    GIF,
    WEBP,
    PPM
};

//Image Types
pub use image::SubImage as SubImage;
pub use image::ImageBuf as ImageBuf;
pub use dynimage::DynamicImage as DynamicImage;

//Traits
pub use image::GenericImage as GenericImage;

//Iterators
pub use image::Pixels as Pixels;
pub use image::MutPixels as MutPixels;

///opening and loading images
pub use dynimage:: {
    open,
    load,
    load_from_memory,
    save_buffer,
};
pub use dynimage::DynamicImage:: {
    ImageRgb8,
    ImageRgba8,
    ImageLuma8,
    ImageLumaA8,
};

//Image Processing Functions
pub mod imageops;

//Image Codecs
pub mod webp;
pub mod ppm;
pub mod png;
pub mod jpeg;
pub mod gif;
pub mod tiff;
pub mod tga;

mod image;
mod dynimage;
mod color;
mod traits;
<|endoftext|>


<commit_before>//! Chomp is an alternative parser combinator library for the Rust programming language. It was
//! written as the culmination of the experiments detailed in these blog posts:
//!
//! * [Part 1](http://m4rw3r.github.io/parser-combinator-experiments-rust/)
//! * [Part 2](http://m4rw3r.github.io/parser-combinator-experiments-errors)
//! * [Part 3](http://m4rw3r.github.io/parser-combinator-experiments-part-3)
//!
//! For its current capabilities, you will find that Chomp performs consistently as well, if not
//! better, than optimized C parsers, while being vastly more expressive. For an example that
//! builds a performant HTTP parser out of smaller parsers, see
//! [http_parser.rs](examples/http_parser.rs).
//!
//! # Example
//!
//! ```
//! # #[macro_use] extern crate chomp;
//! # fn main() {
//! use chomp::{Input, ParseResult, Error};
//! use chomp::{take_while1, token};
//!
//! let i = Input::new("martin wernstål\n".as_bytes());
//!
//! #[derive(Debug, Eq, PartialEq)]
//! struct Name<'a> {
//!     first: &'a [u8],
//!     last:  &'a [u8],
//! }
//!
//! fn name(i: Input<u8>) -> ParseResult<u8, Name, Error<u8>> {
//!     parse!{i;
//!         let first = take_while1(|c| c != b' ');
//!                     token(b' ');  // skipping this char
//!         let last  = take_while1(|c| c != b'\n');
//!
//!         ret Name{
//!             first: first,
//!             last:  last,
//!         }
//!     }
//! }
//!
//! assert_eq!(name(i).unwrap(), Name{first: b"martin", last: "wernstål".as_bytes()});
//! # }
//! ```
//!
//! # Usage
//!
//! Chomp's functionality is split between three modules:
//!
//! * `parsers` contains the basic parsers used to parse streams of input.
//! * `combinators` contains functions which take parsers and return new ones.
//! * `internal` contains the building blocks used to make new parsers. This is advanced usage and
//!   is far more involved than using the pre-existing parsers, but is sometimes unavoidable.
//!
//! A parser is, at its simplest, a function that takes a slice of input and returns a
//! `ParserResult<'a, I, T, E>`, where `I`, `T`, and `E` are the input, output, and error types,
//! respectively. Parsers are usually parameterized over values or other parsers as well, so these
//! appear as extra arguments in the parsing function. As an example, here is the signature of the
//! `token` parser, which matches a particular input.
//!
//! ```ignore
//! fn token<'a, I: 'a + Copy + Eq>(i: Input<'a, I>, t: I) -> SimpleResult<'a, I, I> {...}
//! ```
//!
//! Notice that the first argument is an `Input<'a, I>`, and the second argument is some `I`.
//! `Input<'a,I>` is just a datatype over the current state of the parser and a slice of input `I`,
//! and prevents the parser writer from accidentally mutating the state of the parser. Later, when
//! we introduce the `parse!` macro, we will see that using a parser in this macro just means
//! supplying all of the arguments but the input, as so:
//!
//! ```ignore
//! token(b'T');
//! ```
//!
//! Note that you cannot do this outside of the `parse!` macro. `SimpleResult<'a, I, T>` is a
//! convenience type alias over `Result<'a, I, T, Error<u8>>`, and `Error<I>` is just a convenient
//! "default" error type that will be sufficient for most uses. For more sophisticated usage, one
//! can always write a custom error type.
//!
//! A very useful parser is the `satisfy` parser:
//!
//! ```ignore
//! fn satisfy<'a, I: 'a + Copy, F>(i: Input<'a, I>, f: F) -> SimpleResult<'a, I, I>
//!    where F: FnOnce(I) -> bool { ... }
//! ```
//!
//! Besides the input state, satisfy's only parameter is a predicate function and will succeed only
//! if the next piece of input satisfies the supplied predicate. Here's an example that might be
//! used in the `parse!` macro:
//!
//! ```
//! # #[macro_use] extern crate chomp;
//! # fn main() {
//! # use chomp::{Input, satisfy};
//! # let r = parse!{Input::new(b"h");
//! satisfy(|c| {
//!     match c {
//!         b'c' | b'h' | b'a' | b'r' => true,
//!         _ => false,
//!     }
//! })
//! # };
//! # assert_eq!(r.unwrap(), b'h');
//! # }
//! ```
//!
//! This parser will only succeed if the character is one of the characters in "char".
//!
//! Lastly, here is the parser combinator `count`, which will attempt to run a parser a number of
//! times on its input.
//!
//! ```ignore
//! pub fn count<'a, I, T, E, F, U>(i: Input<'a, I>, num: usize, p: F) -> ParseResult<'a, I, T, E>
//!   where I: Copy,
//!         U: 'a,
//!         F: FnMut(Input<'a, I>) -> ParseResult<'a, I, U, E>,
//!         T: FromIterator<U> { ... }
//! ```
//!
//! Using parsers is almost entirely done using the `parse!` macro, which enables us to do three
//! distinct things:
//!
//! * Sequence parsers over the remaining input
//! * Store intermediate results into datatypes
//! * Return a datatype at the end, which may be the result of any arbitrary computation over the
//! intermediate results.
//!
//! In other words, just as a normal Rust function usually looks something like this:
//!
//! ```
//! # fn launch_missiles() {}
//! fn f() -> (u8, u8, u8) {
//!     let a = 3;
//!     let b = 3;
//!     launch_missiles();
//!     return (a, b, a + b);
//! }
//! ```
//!
//! A Chomp parser with a similar structure looks like this:
//!
//! ```
//! # #[macro_use] extern crate chomp;
//! # use chomp::{Input, string, token, U8Result};
//! fn f(i: Input<u8>) -> U8Result<(u8, u8, u8)> {
//!     parse!{i;
//!         let a = token(b'3');
//!         let b = token(b'3');
//!         string(b"missiles");
//!         ret (a, b, a + b)
//!     }
//! }
//! # fn main() {
//! #     let r = f(Input::new(b"33missiles"));
//! #     assert_eq!(r.unwrap(), (b'3', b'3', b'f')); // b'3' + b'3' == b'f'
//! # }
//! ```
//!
//! Readers familiar with Haskell or F# will recognize this as a "monadic computation" or
//! "computation expression".
//!
//! You use the `parse!` macro as follows:
//!
//! - Write the input parameter first, with a semicolon.
//! - Write any number of valid parser actions or identifier bindings, where:
//!    - a parser action takes the form `parser(params*)`, with the input parameter omitted.
//!    - an identifier binding takes the form `let identifer = parser(params*);`, with the input
//!      parameter omitted.
//! - Write the final line of the macro, which must always be either a parser action, or a return
//!   statement which takes the form `ret expression`. The type of `expression` becomes the return
//!   type of the entire parser, should it succeed.
//!
//! The entire grammar for the macro is listed elsewhere in this documentation.

#[macro_use]
extern crate bitflags;
extern crate conv;

#[macro_use]
mod macros;
mod input;
mod parse_result;

pub mod ascii;
pub mod buffer;
pub mod internal;
pub mod parsers;
pub mod combinators;

pub use combinators::{
    count,
    option,
    or,
    many,
    many1,
    skip_many,
};
pub use parsers::{
    any,
    eof,
    not_token,
    peek,
    satisfy,
    scan,
    string,
    take,
    take_remainder,
    take_till,
    take_while,
    take_while1,
    token,
};
pub use err::Error;
pub use internal::iter::Iter;
pub use input::Input;
pub use parse_result::{
    U8Result,
    SimpleResult,
    ParseResult,
};

#[cfg(feature = "verbose_error")]
mod err {
    //! This is a private module to contain the more verbose error type as well as adapters for
    //! using it.
    //!
    //! All adapters are #[inline(always)] and will construct the appropriate error type.
    use std::any;
    use std::error;
    use std::fmt;

    use {Input, ParseResult};

    #[derive(Clone, Debug, Eq, PartialEq, Ord, PartialOrd, Hash)]
    pub enum Error<I> {
        Expected(I),
        Unexpected,
        String(Vec<I>),
    }

    impl<I> fmt::Display for Error<I>
      where I: fmt::Debug {
        fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
            match *self {
                Error::Expected(ref c) => write!(f, "expected {:?}", *c),
                Error::Unexpected      => write!(f, "unexpected"),
                Error::String(ref s)   => write!(f, "expected {:?}", *s),
            }
        }
    }

    impl<I: any::Any + fmt::Debug> error::Error for Error<I> {
        fn description(&self) -> &str {
            match *self {
                Error::Expected(_) => "expected a certain token, received another",
                Error::Unexpected  => "received an unexpected token",
                Error::String(_)   =>
                    "expected a certain string of tokens, encountered an unexpected token",
            }
        }
    }

    #[inline(always)]
    pub fn unexpected<I>() -> Error<I> {
        Error::Unexpected
    }

    #[inline(always)]
    pub fn expected<'a, I>(i: I) -> Error<I> {
        Error::Expected(i)
    }

    #[inline(always)]
    pub fn string<'a, 'b, I, T>(i: Input<'a, I>, _offset: usize, expected: &'b [I])
        -> ParseResult<'a, I, T, Error<I>>
      where I: Copy {
        i.err(Error::String(expected.to_vec()))
    }
}

#[cfg(not(feature = "verbose_error"))]
mod err {
    //! This is a private module to contain the smaller error type as well as adapters for using
    //! it.
    //!
    //! All adapters are #[inline(always)], and will just noop the data.
    use std::any;
    use std::error;
    use std::fmt;

    use std::marker::PhantomData;

    use {Input, ParseResult};

    #[derive(Clone, Debug, Eq, PartialEq, Ord, PartialOrd, Hash)]
    pub struct Error<I>(PhantomData<I>);

    impl<I: fmt::Debug> fmt::Display for Error<I> {
        fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
            write!(f, "generic parse error (chomp was compiled without --feature verbose_error)")
        }
    }

    impl<I: any::Any + fmt::Debug> error::Error for Error<I> {
        fn description(&self) -> &str {
            "generic parse error (chomp was compiled without --feature verbose_error)"
        }
    }

    #[inline(always)]
    pub fn unexpected<I>() -> Error<I> {
        Error(PhantomData)
    }

    #[inline(always)]
    pub fn expected<'a, I>(_: I) -> Error<I> {
        Error(PhantomData)
    }

    #[inline(always)]
    pub fn string<'a, 'b, I, T>(i: Input<'a, I>, offset: usize, _expected: &'b [I])
        -> ParseResult<'a, I, T, Error<I>>
      where I: Copy {
        use internal::InputModify;
        let b = i.buffer();

        i.replace(&b[offset..]).err(Error(PhantomData))
    }
}
<commit_msg>Removed reexport of internal::Iter<commit_after>//! Chomp is an alternative parser combinator library for the Rust programming language. It was
//! written as the culmination of the experiments detailed in these blog posts:
//!
//! * [Part 1](http://m4rw3r.github.io/parser-combinator-experiments-rust/)
//! * [Part 2](http://m4rw3r.github.io/parser-combinator-experiments-errors)
//! * [Part 3](http://m4rw3r.github.io/parser-combinator-experiments-part-3)
//!
//! For its current capabilities, you will find that Chomp performs consistently as well, if not
//! better, than optimized C parsers, while being vastly more expressive. For an example that
//! builds a performant HTTP parser out of smaller parsers, see
//! [http_parser.rs](examples/http_parser.rs).
//!
//! # Example
//!
//! ```
//! # #[macro_use] extern crate chomp;
//! # fn main() {
//! use chomp::{Input, ParseResult, Error};
//! use chomp::{take_while1, token};
//!
//! let i = Input::new("martin wernstål\n".as_bytes());
//!
//! #[derive(Debug, Eq, PartialEq)]
//! struct Name<'a> {
//!     first: &'a [u8],
//!     last:  &'a [u8],
//! }
//!
//! fn name(i: Input<u8>) -> ParseResult<u8, Name, Error<u8>> {
//!     parse!{i;
//!         let first = take_while1(|c| c != b' ');
//!                     token(b' ');  // skipping this char
//!         let last  = take_while1(|c| c != b'\n');
//!
//!         ret Name{
//!             first: first,
//!             last:  last,
//!         }
//!     }
//! }
//!
//! assert_eq!(name(i).unwrap(), Name{first: b"martin", last: "wernstål".as_bytes()});
//! # }
//! ```
//!
//! # Usage
//!
//! Chomp's functionality is split between three modules:
//!
//! * `parsers` contains the basic parsers used to parse streams of input.
//! * `combinators` contains functions which take parsers and return new ones.
//! * `internal` contains the building blocks used to make new parsers. This is advanced usage and
//!   is far more involved than using the pre-existing parsers, but is sometimes unavoidable.
//!
//! A parser is, at its simplest, a function that takes a slice of input and returns a
//! `ParserResult<'a, I, T, E>`, where `I`, `T`, and `E` are the input, output, and error types,
//! respectively. Parsers are usually parameterized over values or other parsers as well, so these
//! appear as extra arguments in the parsing function. As an example, here is the signature of the
//! `token` parser, which matches a particular input.
//!
//! ```ignore
//! fn token<'a, I: 'a + Copy + Eq>(i: Input<'a, I>, t: I) -> SimpleResult<'a, I, I> {...}
//! ```
//!
//! Notice that the first argument is an `Input<'a, I>`, and the second argument is some `I`.
//! `Input<'a,I>` is just a datatype over the current state of the parser and a slice of input `I`,
//! and prevents the parser writer from accidentally mutating the state of the parser. Later, when
//! we introduce the `parse!` macro, we will see that using a parser in this macro just means
//! supplying all of the arguments but the input, as so:
//!
//! ```ignore
//! token(b'T');
//! ```
//!
//! Note that you cannot do this outside of the `parse!` macro. `SimpleResult<'a, I, T>` is a
//! convenience type alias over `Result<'a, I, T, Error<u8>>`, and `Error<I>` is just a convenient
//! "default" error type that will be sufficient for most uses. For more sophisticated usage, one
//! can always write a custom error type.
//!
//! A very useful parser is the `satisfy` parser:
//!
//! ```ignore
//! fn satisfy<'a, I: 'a + Copy, F>(i: Input<'a, I>, f: F) -> SimpleResult<'a, I, I>
//!    where F: FnOnce(I) -> bool { ... }
//! ```
//!
//! Besides the input state, satisfy's only parameter is a predicate function and will succeed only
//! if the next piece of input satisfies the supplied predicate. Here's an example that might be
//! used in the `parse!` macro:
//!
//! ```
//! # #[macro_use] extern crate chomp;
//! # fn main() {
//! # use chomp::{Input, satisfy};
//! # let r = parse!{Input::new(b"h");
//! satisfy(|c| {
//!     match c {
//!         b'c' | b'h' | b'a' | b'r' => true,
//!         _ => false,
//!     }
//! })
//! # };
//! # assert_eq!(r.unwrap(), b'h');
//! # }
//! ```
//!
//! This parser will only succeed if the character is one of the characters in "char".
//!
//! Lastly, here is the parser combinator `count`, which will attempt to run a parser a number of
//! times on its input.
//!
//! ```ignore
//! pub fn count<'a, I, T, E, F, U>(i: Input<'a, I>, num: usize, p: F) -> ParseResult<'a, I, T, E>
//!   where I: Copy,
//!         U: 'a,
//!         F: FnMut(Input<'a, I>) -> ParseResult<'a, I, U, E>,
//!         T: FromIterator<U> { ... }
//! ```
//!
//! Using parsers is almost entirely done using the `parse!` macro, which enables us to do three
//! distinct things:
//!
//! * Sequence parsers over the remaining input
//! * Store intermediate results into datatypes
//! * Return a datatype at the end, which may be the result of any arbitrary computation over the
//! intermediate results.
//!
//! In other words, just as a normal Rust function usually looks something like this:
//!
//! ```
//! # fn launch_missiles() {}
//! fn f() -> (u8, u8, u8) {
//!     let a = 3;
//!     let b = 3;
//!     launch_missiles();
//!     return (a, b, a + b);
//! }
//! ```
//!
//! A Chomp parser with a similar structure looks like this:
//!
//! ```
//! # #[macro_use] extern crate chomp;
//! # use chomp::{Input, string, token, U8Result};
//! fn f(i: Input<u8>) -> U8Result<(u8, u8, u8)> {
//!     parse!{i;
//!         let a = token(b'3');
//!         let b = token(b'3');
//!         string(b"missiles");
//!         ret (a, b, a + b)
//!     }
//! }
//! # fn main() {
//! #     let r = f(Input::new(b"33missiles"));
//! #     assert_eq!(r.unwrap(), (b'3', b'3', b'f')); // b'3' + b'3' == b'f'
//! # }
//! ```
//!
//! Readers familiar with Haskell or F# will recognize this as a "monadic computation" or
//! "computation expression".
//!
//! You use the `parse!` macro as follows:
//!
//! - Write the input parameter first, with a semicolon.
//! - Write any number of valid parser actions or identifier bindings, where:
//!    - a parser action takes the form `parser(params*)`, with the input parameter omitted.
//!    - an identifier binding takes the form `let identifer = parser(params*);`, with the input
//!      parameter omitted.
//! - Write the final line of the macro, which must always be either a parser action, or a return
//!   statement which takes the form `ret expression`. The type of `expression` becomes the return
//!   type of the entire parser, should it succeed.
//!
//! The entire grammar for the macro is listed elsewhere in this documentation.

#[macro_use]
extern crate bitflags;
extern crate conv;

#[macro_use]
mod macros;
mod input;
mod parse_result;

pub mod ascii;
pub mod buffer;
pub mod internal;
pub mod parsers;
pub mod combinators;

pub use combinators::{
    count,
    option,
    or,
    many,
    many1,
    skip_many,
};
pub use parsers::{
    any,
    eof,
    not_token,
    peek,
    satisfy,
    scan,
    string,
    take,
    take_remainder,
    take_till,
    take_while,
    take_while1,
    token,
};
pub use err::Error;
pub use input::Input;
pub use parse_result::{
    U8Result,
    SimpleResult,
    ParseResult,
};

#[cfg(feature = "verbose_error")]
mod err {
    //! This is a private module to contain the more verbose error type as well as adapters for
    //! using it.
    //!
    //! All adapters are #[inline(always)] and will construct the appropriate error type.
    use std::any;
    use std::error;
    use std::fmt;

    use {Input, ParseResult};

    #[derive(Clone, Debug, Eq, PartialEq, Ord, PartialOrd, Hash)]
    pub enum Error<I> {
        Expected(I),
        Unexpected,
        String(Vec<I>),
    }

    impl<I> fmt::Display for Error<I>
      where I: fmt::Debug {
        fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
            match *self {
                Error::Expected(ref c) => write!(f, "expected {:?}", *c),
                Error::Unexpected      => write!(f, "unexpected"),
                Error::String(ref s)   => write!(f, "expected {:?}", *s),
            }
        }
    }

    impl<I: any::Any + fmt::Debug> error::Error for Error<I> {
        fn description(&self) -> &str {
            match *self {
                Error::Expected(_) => "expected a certain token, received another",
                Error::Unexpected  => "received an unexpected token",
                Error::String(_)   =>
                    "expected a certain string of tokens, encountered an unexpected token",
            }
        }
    }

    #[inline(always)]
    pub fn unexpected<I>() -> Error<I> {
        Error::Unexpected
    }

    #[inline(always)]
    pub fn expected<'a, I>(i: I) -> Error<I> {
        Error::Expected(i)
    }

    #[inline(always)]
    pub fn string<'a, 'b, I, T>(i: Input<'a, I>, _offset: usize, expected: &'b [I])
        -> ParseResult<'a, I, T, Error<I>>
      where I: Copy {
        i.err(Error::String(expected.to_vec()))
    }
}

#[cfg(not(feature = "verbose_error"))]
mod err {
    //! This is a private module to contain the smaller error type as well as adapters for using
    //! it.
    //!
    //! All adapters are #[inline(always)], and will just noop the data.
    use std::any;
    use std::error;
    use std::fmt;

    use std::marker::PhantomData;

    use {Input, ParseResult};

    #[derive(Clone, Debug, Eq, PartialEq, Ord, PartialOrd, Hash)]
    pub struct Error<I>(PhantomData<I>);

    impl<I: fmt::Debug> fmt::Display for Error<I> {
        fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
            write!(f, "generic parse error (chomp was compiled without --feature verbose_error)")
        }
    }

    impl<I: any::Any + fmt::Debug> error::Error for Error<I> {
        fn description(&self) -> &str {
            "generic parse error (chomp was compiled without --feature verbose_error)"
        }
    }

    #[inline(always)]
    pub fn unexpected<I>() -> Error<I> {
        Error(PhantomData)
    }

    #[inline(always)]
    pub fn expected<'a, I>(_: I) -> Error<I> {
        Error(PhantomData)
    }

    #[inline(always)]
    pub fn string<'a, 'b, I, T>(i: Input<'a, I>, offset: usize, _expected: &'b [I])
        -> ParseResult<'a, I, T, Error<I>>
      where I: Copy {
        use internal::InputModify;
        let b = i.buffer();

        i.replace(&b[offset..]).err(Error(PhantomData))
    }
}
<|endoftext|>


<commit_before>#[macro_use]
extern crate nom;
use std::ffi::CStr;
use std::os::raw::c_char;

use nom::{le_u64,le_u32};
use nom::IResult;

#[allow(non_camel_case_types)]
pub type cpu_type_t = usize;
#[allow(non_camel_case_types)]
pub type cpu_subtype_t = usize;
#[allow(non_camel_case_types)]
pub type vm_prot_t = usize;

#[derive(Debug)]
pub struct MachHeader {
    pub header: MachHeader_,
    pub segments: Vec<SegmentCommand>,
}

#[derive(Debug)]
pub struct MachHeader_ {
    pub magic: u32,
    pub cputype: cpu_type_t,
    pub cpusubtype: cpu_subtype_t,
    pub filetype: u32,
    pub ncmds: u32,
    pub sizeofcmds: u32,
    pub flags: u32,
}

impl MachHeader {
    pub fn parse(bytes: &[u8]) -> Option<MachHeader> {
        if let IResult::Done(_rest, header) = mach_header(bytes) {
            let mut rest = _rest;
            let mut segments = vec![];
            for _ in [0.. header.ncmds].iter() {
                if let IResult::Done(_rest, cmd) = segment_command(rest) {
                    rest = _rest;
                    segments.push(cmd);
                } else {
                    return None
                }
            }

            Some(MachHeader {
                header: header,
                segments: segments,
            })
        } else {
            return None
        }
    }
}

#[derive(Debug)]
pub struct SegmentCommand {
    pub cmd: u32,
    pub cmdsize: u32,
    pub segname: String,
    pub vmaddr: u32,
    pub vmsize: u32,
    pub fileoff: u32,
    pub filesize: u32,
    pub maxprot: vm_prot_t,
    pub initprot: vm_prot_t,
    pub nsects: u32,
    pub flags: u32,
}

named!(mach_header<&[u8], MachHeader_>,
       chain!(
           magic: le_u32 ~
           // TODO this is presumably broken on 32bit
           cputype: le_u64 ~
           cpusubtype: le_u64 ~
           filetype: le_u32 ~
           ncmds: le_u32 ~
           sizeofcmds: le_u32 ~
           flags: le_u32 ,

           || {
               MachHeader_ {
                   magic: magic,
                   cputype: cputype as usize,
                   cpusubtype: cpusubtype as usize,
                   filetype: filetype,
                   ncmds: ncmds,
                   sizeofcmds: sizeofcmds,
                   flags: flags,
               }
           }
           )
       );

named!(segment_command<&[u8], SegmentCommand>,
       chain!(
           cmd: le_u32 ~
           cmdsize: le_u32 ~
           segname: take!(16) ~
           vmaddr: le_u32 ~
           vmsize: le_u32 ~
           fileoff: le_u32 ~
           filesize: le_u32 ~
           maxprot: le_u64 ~
           initprot: le_u64 ~
           nsects: le_u32 ~
           flags: le_u32 ,

           || {

               let slice = unsafe { CStr::from_ptr(segname.as_ptr() as *const c_char) };
               let name = std::str::from_utf8(slice.to_bytes()).unwrap().to_string();

               SegmentCommand {
                   cmd: cmd,
                   cmdsize: cmdsize,
                   segname: name,
                   vmaddr: vmaddr,
                   vmsize: vmsize,
                   fileoff: fileoff,
                   filesize: filesize,
                   maxprot: maxprot as usize,
                   initprot: initprot as usize,
                   nsects: nsects,
                   flags: flags,
               }
           }
        )
    );

<commit_msg>Enough to parse mach-o headers on 64 bit<commit_after>#[macro_use]
extern crate nom;
use std::ffi::CStr;
use std::os::raw::c_char;

use nom::{le_u64,le_u32,le_i32};
use nom::IResult;

// These are all integer_t, aka int
#[allow(non_camel_case_types)]
pub type cpu_type_t = i32;
#[allow(non_camel_case_types)]
pub type cpu_subtype_t = i32;
#[allow(non_camel_case_types)]
pub type vm_prot_t = i32;

#[derive(Debug)]
pub struct MachHeader {
    pub header: MachHeader_,
    pub segments: Vec<SegmentCommand>,
}

#[derive(Debug)]
pub struct MachHeader_ {
    pub magic: u32,
    pub cputype: cpu_type_t,
    pub cpusubtype: cpu_subtype_t,
    pub filetype: u32,
    pub ncmds: u32,
    pub sizeofcmds: u32,
    pub flags: u32,
    reserved :u32,
}

impl MachHeader {
    pub fn parse(bytes: &[u8]) -> Option<MachHeader> {
        if let IResult::Done(_rest, header) = mach_header(bytes) {
            let mut rest = _rest;
            let mut segments = vec![];
            for _ in 0.. header.ncmds {
                if let IResult::Done(_rest, cmd) = segment_command(rest) {
                    rest = _rest;
                    segments.push(cmd);
                } else {
                    return None
                }
            }

            Some(MachHeader {
                header: header,
                segments: segments,
            })
        } else {
            return None
        }
    }
}

#[derive(Debug)]
pub struct SegmentCommand {
    pub cmd: u32,
    pub cmdsize: u32,
    pub segname: String,
    pub vmaddr: u32,
    pub vmsize: u32,
    pub fileoff: u32,
    pub filesize: u32,
    pub maxprot: vm_prot_t,
    pub initprot: vm_prot_t,
    pub nsects: u32,
    pub flags: u32,
}

named!(mach_header<&[u8], MachHeader_>,
       chain!(
           magic: le_u32 ~
           cputype: le_i32 ~
           cpusubtype: le_i32 ~
           filetype: le_u32 ~
           ncmds: le_u32 ~
           sizeofcmds: le_u32 ~
           flags: le_u32 ~
           reserved: le_u32,

           || {
               assert_eq!(0xfeedfacf, magic);
               MachHeader_ {
                   magic: magic,
                   cputype: cputype,
                   cpusubtype: cpusubtype,
                   filetype: filetype,
                   ncmds: ncmds,
                   sizeofcmds: sizeofcmds,
                   flags: flags,
                   reserved: reserved,
               }
           }
           )
       );

named!(segment_command<&[u8], SegmentCommand>,
       chain!(
           cmd: le_u32 ~
           cmdsize: le_u32 ~
           segname: take!(16) ~
           vmaddr: le_u32 ~
           vmsize: le_u32 ~
           fileoff: le_u32 ~
           filesize: le_u32 ~
           maxprot: le_i32 ~
           initprot: le_i32 ~
           nsects: le_u32 ~
           flags: le_u32 ,

           || {

               let slice = unsafe { CStr::from_ptr(segname.as_ptr() as *const c_char) };
               let name = std::str::from_utf8(slice.to_bytes()).unwrap().to_string();

               SegmentCommand {
                   cmd: cmd,
                   cmdsize: cmdsize,
                   segname: name,
                   vmaddr: vmaddr,
                   vmsize: vmsize,
                   fileoff: fileoff,
                   filesize: filesize,
                   maxprot: maxprot,
                   initprot: initprot,
                   nsects: nsects,
                   flags: flags,
               }
           }
        )
    );

<|endoftext|>