<commit_before>#![feature(unique)]

//! Rust bindings for [libffi](https://sourceware.org/libffi/).
//!
//! The C libffi library provides two main facilities: assembling calls
//! to functions dynamically, and creating closures that can be called
//! as ordinary C functions. In Rust, the latter means that we can turn
//! a Rust lambda (or any object implementing `Fn`/`FnMut`) into an
//! ordinary C function pointer that we can pass as a callback to C.

//! The easiest way to use this library is via the
//! [`high`](high/index.html) layer module, but more flexibility (and
//! less checking) is provided by the [`middle`](middle/index.html) and
//! [`low`](low/index.html) layers.

//! # Usage/Warning
//!
//! This library is experimental/unstable and shouldn’t be used for
//! anything yet. If it does something you need or want to play with
//! then we should talk.
//!
//! It’s [on crates.io](https://crates.io/crates/libffi), so it can be
//! used by adding `libffi` to the dependencies in your project’s
//! `Cargo.toml`:
//!
//! ```toml
//! [dependencies]
//! libffi = "0.1"
//! ```
//!
//! However, to actually build it, you need to install [Rust
//! bindgen](https://crates.io/crates/bindgen) (0.18.0) and [C
//! libffi](https://sourceware.org/libffi/) (3.2.1) manually first.
//!
//! # Organization
//!
//! This library is organized in four layers, each of which attempts to
//! provide more safety and a simpler interface than the next layer
//! down. From top to bottom:
//!
//!   - The [`high`](high/index.html) layer provides safe(?) and
//!     automatic marshalling of Rust closures into C function pointers.
//!   - The [`middle`](middle/index.html) layer provides memory-managed
//!     abstractions for assembling calls and closures, but is unsafe
//!     because it doesn’t check argument types.
//!   - The [`low`](low/index.html) layer makes no attempts at safety,
//!     but provides a more idiomatically “Rusty” API than the underlying
//!     C library.
//!   - The [`raw`](raw/index.html) layer is a direct mapping of the
//!     C libffi library into Rust, generated by [Rust
//!     Bindgen](https://github.com/crabtw/rust-bindgen).
//!
//! It should be possible to use any layer without dipping into lower
//! layers (and it will be considered a bug to the extent that it
//! isn’t).
//!
//! # Example
//!
//! In this example, we convert a Rust lambda containing a free variable
//! into an ordinary C code pointer. The type of `fun` below is
//! `extern "C" fn(u64, u64) -> u64`.
//!
//! ```
//! use libffi::high::Closure2;
//!
//! let x = 5u64;
//! let f = |y: u64, z: u64| x + y + z;
//!
//! let closure = Closure2::new(&f);
//! let fun     = closure.code_ptr();
//!
//! assert_eq!(18, fun(6, 7));
//! ```

extern crate libc;

/// Unwrapped definitions imported from the C library (via bindgen).
pub mod raw;

pub mod high;
pub mod middle;
pub mod low;
<commit_msg>Doc tweaks.<commit_after>#![feature(unique)]

//! Rust bindings for [libffi](https://sourceware.org/libffi/).
//!
//! The C libffi library provides two main facilities: assembling calls
//! to functions dynamically, and creating closures that can be called
//! as ordinary C functions. In Rust, the latter means that we can turn
//! a Rust lambda (or any object implementing `Fn`/`FnMut`) into an
//! ordinary C function pointer that we can pass as a callback to C.

//! The easiest way to use this library is via the
//! [`high`](high/index.html) layer module, but more flexibility (and
//! less checking) is provided by the [`middle`](middle/index.html) and
//! [`low`](low/index.html) layers.

//! # Usage/Warning
//!
//! This library is experimental/unstable and shouldn’t be used for
//! anything yet. If it does something you need or want to play with
//! then we should talk.
//!
//! It’s [on crates.io](https://crates.io/crates/libffi), so it can be
//! used by adding `libffi` to the dependencies in your project’s
//! `Cargo.toml`:
//!
//! ```toml
//! [dependencies]
//! libffi = "0.1"
//! ```
//!
//! However, to actually build it, you need to install [Rust
//! bindgen](https://crates.io/crates/bindgen) (0.18.0) and [C
//! libffi](https://sourceware.org/libffi/) (3.2.1) manually first.
//!
//! # Organization
//!
//! This library is organized in four layers, each of which attempts to
//! provide more safety and a simpler interface than the next layer
//! down. From top to bottom:
//!
//!   - The [`high`](high/index.html) layer provides safe(?) and
//!     automatic marshalling of Rust closures into C function pointers.
//!   - The [`middle`](middle/index.html) layer provides memory-managed
//!     abstractions for assembling calls and closures, but is unsafe
//!     because it doesn’t check argument types.
//!   - The [`low`](low/index.html) layer makes no attempts at safety,
//!     but provides a more idiomatically “Rusty” API than the underlying
//!     C library.
//!   - The [`raw`](raw/index.html) layer is a direct mapping of the
//!     C libffi library into Rust, generated by
//!     [bindgen](https://crates.io/crates/bindgen).
//!
//! It should be possible to use any layer without dipping into lower
//! layers (and it will be considered a bug to the extent that it
//! isn’t).
//!
//! # Example
//!
//! In this example, we convert a Rust lambda containing a free variable
//! into an ordinary C code pointer. The type of `fun` below is
//! `extern "C" fn(u64, u64) -> u64`.
//!
//! ```
//! use libffi::high::Closure2;
//!
//! let x = 5u64;
//! let f = |y: u64, z: u64| x + y + z;
//!
//! let closure = Closure2::new(&f);
//! let fun     = closure.code_ptr();
//!
//! assert_eq!(18, fun(6, 7));
//! ```

extern crate libc;

/// Unwrapped definitions imported from the C library (via bindgen).
pub mod raw;

pub mod high;
pub mod middle;
pub mod low;
<|endoftext|>


<commit_before>#![crate_id = "couch#0.1-pre"]

#![comment = "Relaxing CouchDB client in Rust"]
#![license = "MIT/ASL2"]
#![crate_type = "dylib"]
#![crate_type = "rlib"]

extern crate http;
extern crate uuid;
extern crate semver;
extern crate serialize;

use uuid::Uuid;
use semver::Version;
use http::client::RequestWriter;
use http::method::{Get,Put,Delete};
use std::io::BufReader;
use std::io;
use serialize::{json, Encodable, Decodable};
use serialize::json::Json;
use serialize::json::Encoder;
use serialize::json::from_reader;
use std::io::IoResult;

#[deriving(Encodable,Decodable)]
pub struct VendorInfo {
  version: String,
  name: String
}

#[deriving(Encodable,Decodable)]
pub struct Info {
  couchdb: String,
  uuid: Uuid,
  version: String,
  vendor: VendorInfo
}

#[deriving(Encodable,Decodable)]
pub struct Okay {
  ok: bool
}

impl Info {
  pub fn version(self) -> Version {
    semver::parse(self.version.as_slice()).unwrap()
  }

  pub fn message(self) -> String {
    self.couchdb
  }
}

#[deriving(Clone)]
pub struct Server {
  host: String
}

impl Server {
  pub fn new(host: String) -> Server {
    Server { host: host }
  }

  fn get(&self, path: String) -> IoResult<Vec<u8>> {
    let request: RequestWriter =
              RequestWriter::new(Get,
              from_str(self.host.clone().append(path.as_slice()).as_slice()).expect("Invalid URL :-("))
              .unwrap();
    let mut response = request.read_response();
    match response {
      Ok(mut res) => { res.read_to_end() },
      Err(error) => { fail!("(C)ouch!") }
    }
  }

  fn put(&self, path: String, body: Option<&[u8]>) -> IoResult<Vec<u8>> {
    let mut request: RequestWriter =
              RequestWriter::new(Put,
              from_str(self.host.clone().append(path.as_slice()).as_slice()).expect("Invalid URL :-("))
              .unwrap();

    match body {
      Some(body) => {
        request.headers.content_length = Some(body.len());
        request.write(body);
      },
      None => {}
    }

    let mut response = request.read_response();
    match response {
      Ok(mut res) => { res.read_to_end() },
      Err(error) => { fail!("(C)ouch!") }
    }
  }

  fn delete(&self, path: String) -> IoResult<Vec<u8>> {
    let request: RequestWriter =
              RequestWriter::new(Delete,
              from_str(self.host.clone().append(path.as_slice()).as_slice()).expect("Invalid URL :-("))
              .unwrap();
    let mut response = request.read_response();
    match response {
      Ok(mut res) => { res.read_to_end() },
      Err(error) => { fail!("(C)ouch!") }
    }
  }

  pub fn create_database(&mut self, name: String) -> Database {
    let body = self.put(String::from_str("/").append(name.as_slice()), None).unwrap();

    let mut reader = BufReader::new(body.as_slice());
    let json = from_reader(&mut reader);
    let mut decoder = json::Decoder::new(json.unwrap());

    let result = Decodable::decode(&mut decoder);
    let ok: Okay = result.unwrap();
    if ok.ok {
      Database { name: name, server: self.clone() }
    } else {
      fail!("(C)ouch")
    }
  }

  pub fn delete_database(&mut self, name: String) -> bool {
    let result = self.delete(String::from_str("/").append(name.as_slice()));

    // TODO: Yes, don't do that, but for the sake of a quick hack
    match result {
      Ok(_) => { true },
      Err(_) => { false }
    }
    //let mut reader = BufReader::new(body.as_slice());
    //let json = from_reader(&mut reader);
    //let mut decoder = json::Decoder::new(json.unwrap());
    //
    //let result = Decodable::decode(&mut decoder);

  }

  pub fn info(self) -> Info {
    let body = self.get(String::from_str("/")).unwrap();

    let mut reader = BufReader::new(body.as_slice());
    let json = from_reader(&mut reader);
    let mut decoder = json::Decoder::new(json.unwrap());

    let result = Decodable::decode(&mut decoder);
    result.unwrap()
  }
}

pub struct Database {
  name: String,
  server: Server
}

pub trait Document {
  fn id(&self) -> String;
}

impl Database {
  pub fn name(self) -> String {
    self.name
  }

  pub fn put<'a, T: Document + Encodable<json::Encoder<'a>,io::IoError>>(&mut self, document: &T) {
    let url = format!("/{:s}/{:s}", self.name, document.id());
    let encoded_doc = json::Encoder::buffer_encode(document);
    self.server.put(url, Some(encoded_doc.as_slice()));
  }
}<commit_msg>Remove most warnings<commit_after>#![crate_id = "couch#0.1-pre"]

#![comment = "Relaxing CouchDB client in Rust"]
#![license = "MIT/ASL2"]
#![crate_type = "dylib"]
#![crate_type = "rlib"]

extern crate http;
extern crate uuid;
extern crate semver;
extern crate serialize;

use uuid::Uuid;
use semver::Version;
use http::client::RequestWriter;
use http::method::{Get,Put,Delete};
use std::io::BufReader;
use std::io;
use serialize::{json, Encodable, Decodable};
use serialize::json::Encoder;
use serialize::json::from_reader;
use std::io::IoResult;

#[deriving(Encodable,Decodable)]
pub struct VendorInfo {
  version: String,
  name: String
}

#[deriving(Encodable,Decodable)]
pub struct Info {
  couchdb: String,
  uuid: Uuid,
  version: String,
  vendor: VendorInfo
}

#[deriving(Encodable,Decodable)]
pub struct Okay {
  ok: bool
}

impl Info {
  pub fn version(self) -> Version {
    semver::parse(self.version.as_slice()).unwrap()
  }

  pub fn message(self) -> String {
    self.couchdb
  }
}

#[deriving(Clone)]
pub struct Server {
  host: String
}

impl Server {
  pub fn new(host: String) -> Server {
    Server { host: host }
  }

  fn get(&self, path: String) -> IoResult<Vec<u8>> {
    let request: RequestWriter =
              RequestWriter::new(Get,
              from_str(self.host.clone().append(path.as_slice()).as_slice()).expect("Invalid URL :-("))
              .unwrap();
    let response = request.read_response();
    match response {
      Ok(mut res) => { res.read_to_end() },
      Err(error) => { fail!("(C)ouch! {:?}", error) }
    }
  }

  fn put(&self, path: String, body: Option<&[u8]>) -> IoResult<Vec<u8>> {
    let mut request: RequestWriter =
              RequestWriter::new(Put,
              from_str(self.host.clone().append(path.as_slice()).as_slice()).expect("Invalid URL :-("))
              .unwrap();

    match body {
      Some(body) => {
        request.headers.content_length = Some(body.len());
        request.write(body);
      },
      None => {}
    }

    let response = request.read_response();
    match response {
      Ok(mut res) => { res.read_to_end() },
      Err(error) => { fail!("(C)ouch! {:?}", error) }
    }
  }

  fn delete(&self, path: String) -> IoResult<Vec<u8>> {
    let request: RequestWriter =
              RequestWriter::new(Delete,
              from_str(self.host.clone().append(path.as_slice()).as_slice()).expect("Invalid URL :-("))
              .unwrap();
    let response = request.read_response();
    match response {
      Ok(mut res) => { res.read_to_end() },
      Err(error) => { fail!("(C)ouch! {:?}", error) }
    }
  }

  pub fn create_database(&mut self, name: String) -> Database {
    let body = self.put(String::from_str("/").append(name.as_slice()), None).unwrap();

    let mut reader = BufReader::new(body.as_slice());
    let json = from_reader(&mut reader);
    let mut decoder = json::Decoder::new(json.unwrap());

    let result = Decodable::decode(&mut decoder);
    let ok: Okay = result.unwrap();
    if ok.ok {
      Database { name: name, server: self.clone() }
    } else {
      fail!("(C)ouch")
    }
  }

  pub fn delete_database(&mut self, name: String) -> bool {
    let result = self.delete(String::from_str("/").append(name.as_slice()));

    // TODO: Yes, don't do that, but for the sake of a quick hack
    match result {
      Ok(_) => { true },
      Err(_) => { false }
    }
    //let mut reader = BufReader::new(body.as_slice());
    //let json = from_reader(&mut reader);
    //let mut decoder = json::Decoder::new(json.unwrap());
    //
    //let result = Decodable::decode(&mut decoder);

  }

  pub fn info(self) -> Info {
    let body = self.get(String::from_str("/")).unwrap();

    let mut reader = BufReader::new(body.as_slice());
    let json = from_reader(&mut reader);
    let mut decoder = json::Decoder::new(json.unwrap());

    let result = Decodable::decode(&mut decoder);
    result.unwrap()
  }
}

pub struct Database {
  name: String,
  server: Server
}

pub trait Document {
  fn id(&self) -> String;
}

impl Database {
  pub fn name(self) -> String {
    self.name
  }

  pub fn put<'a, T: Document + Encodable<json::Encoder<'a>,io::IoError>>(&mut self, document: &T) {
    let url = format!("/{:s}/{:s}", self.name, document.id());
    let encoded_doc = json::Encoder::buffer_encode(document);
    self.server.put(url, Some(encoded_doc.as_slice()));
  }
}<|endoftext|>


<commit_before>// (c) 2015-2016 Joost Yervante Damad <joost@damad.be>

use std::fmt;
use std::fs::File;
use std::io::Read;

extern crate rustysexp;
use rustysexp::Sexp;
use rustysexp::Atom;

type ERes<T> = Result<T, String>;

fn err<T>(msg: &str) -> ERes<T> {
    Err(String::from(msg))
}

#[derive(Debug)]
pub struct Module {
    name: String,
    elements: Vec<Element>
}

impl Module {
    fn new(name: &String) -> Module {
        Module { name: name.clone(), elements: vec![] }
    }
    fn append(&mut self, e: Element) {
        self.elements.push(e)
    }
}

impl fmt::Display for Module {
    fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
        try!(write!(f, "(module {}\n", self.name));
        for e in &self.elements {
            try!(write!(f, "{}\n", e))
        };
        write!(f, ")")
    }
}

#[derive(Debug)]
pub enum Element {
    Layer(String),
    Descr(String),
    FpText(FpText),
    Pad,
    FpPoly,
    FpLine,
    FpCircle
}

impl fmt::Display for Element {
    fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
        match *self {
            Element::Layer(ref s) => write!(f, "(layer {})", s),
            Element::Descr(ref s) => write!(f, "(descr \"{}\")", s),
            Element::FpText(ref p) => write!(f, "{}", p),
            Element::Pad => write!(f, "(pad)"),
            Element::FpPoly => write!(f, "(fp_poly)"),
            Element::FpLine => write!(f, "(fp_line)"),
            Element::FpCircle => write!(f, "(fp_circle)"),
        }
    }
}

#[derive(Debug)]
pub struct FpText {
    name: String,
    value: String,
    at: At,
    layer: String,
    effects: Effects,
    hide: bool,
}

impl FpText {
    fn new(name: &String, value: &String) -> FpText {
        FpText {
            name: name.clone(),
            value: value.clone(),
            at: At::new(0.,0.,0.),
            layer: String::from("cow"),
            effects: Effects::new(),
            hide: false
        }
    }
    fn set_at(&mut self, at: &At) {
        self.at.set(at)
    }
}

impl fmt::Display for FpText {
    fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
        write!(f, "(fp_text {} \"{}\" {} (layer {}){} {})", self.name, self.value, self.at, self.layer, if self.hide { " hide" } else { "" }, self.effects)
    }
}

#[derive(Debug)]
pub struct At {
    x: f64,
    y: f64,
    rot: f64
}

impl At {
    fn new(x:f64 ,y:f64, rot:f64) -> At {
        At { x:x, y:y, rot:rot }
    }
    fn set(&mut self, at: &At) {
        self.x = at.x;
        self.y = at.y;
        self.rot = at.rot;
    }
}

impl fmt::Display for At {
    fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
        write!(f, "(at {} {} {})", self.x, self.y, self.rot)
    }
}

#[derive(Debug)]
pub struct Effects {
    todo: String
}

impl Effects {
    fn new() -> Effects {
        Effects { todo: String::from("todo") }
    }
}

impl fmt::Display for Effects {
    fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
        write!(f, "(effects)")
    }
}

#[derive(Debug)]
pub enum XyType {
    Xy,
    Start,
    End,
}

#[derive(Debug)]
pub struct Xy {
    x: f64,
    y: f64,
    t: XyType,
}

impl fmt::Display for Xy {
    fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
        match self.t {
            XyType::Xy => write!(f,"(xy {} {})", self.x, self.y),
            XyType::Start => write!(f,"(start {} {})", self.x, self.y),
            XyType::End => write!(f,"(end {} {})", self.x, self.y),
        }
    }
}

#[derive(Debug)]
enum Part {
    At(At),
    Layer(String),
    Hide,
    Effects(Effects),
    Layers(Vec<String>),
    Width(f64),
    Xy(Xy),
    Pts(Vec<Xy>),
}

impl fmt::Display for Part {
    fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
        match *self {
            Part::At(ref at)           => write!(f, "{}", at),
            Part::Layer(ref layer)     => write!(f, "(layer {})", layer),
            Part::Hide                 => write!(f, "hide"),
            Part::Effects(ref effects) => write!(f, "{}", effects),
            Part::Layers(_)            => write!(f, "(layers TODO"),
            Part::Width(ref w)         => write!(f, "(width {}", w),
            Part::Xy(ref xy)           => write!(f, "{}", xy),
            Part::Pts(_)               => write!(f, "(pts TODO)"),

        }
    }
}

fn parse_part_at(v: &Vec<Sexp>) -> ERes<Part> {
    Ok(Part::Hide)
}

fn parse_part_layer(v: &Vec<Sexp>) -> ERes<Part> {
    Ok(Part::Hide)
}

fn parse_part_effects(v: &Vec<Sexp>) -> ERes<Part> {
    Ok(Part::Hide)
}

fn parse_part_layers(v: &Vec<Sexp>) -> ERes<Part> {
    Ok(Part::Hide)
}

fn parse_part_width(v: &Vec<Sexp>) -> ERes<Part> {
    Ok(Part::Hide)
}

fn parse_part_pts(v: &Vec<Sexp>) -> ERes<Part> {
    Ok(Part::Hide)
}

fn parse_part_xy(t: XyType, v: &Vec<Sexp>) -> ERes<Part> {
    Ok(Part::Hide)
}

fn parse_part_list(v: &Vec<Sexp>) -> ERes<Part> {
    match v[0] {
        Sexp::Atom(Atom::S(ref s)) => {
            match &s[..] {
                "at" => parse_part_at(v),
                "layer" => parse_part_layer(v),
                "effects" => parse_part_effects(v),
                "layers" => parse_part_layers(v),
                "width" => parse_part_width(v),
                "start" => parse_part_xy(XyType::Start, v),
                "end" => parse_part_xy(XyType::End, v),
                "pts" => parse_part_pts(v),
                x => Err(format!("unknown part {}", x))
            }
        }
        _ => err("expecting atom in part")
    }
}

fn parse_part(part: &Sexp) -> ERes<Part> {
    match *part {
        Sexp::Atom(Atom::S(ref s)) => {
            match &s[..] {
                "hide" => Ok(Part::Hide),
                x => Err(format!("unknown part in element: {}", x))
            }
        },
        Sexp::List(ref v) => parse_part_list(&v),
        ref x => Err(format!("unknown part in element: {}", x))
    }
}

fn parse_parts(v: &[Sexp]) -> ERes<Vec<Part>> {
    let mut res = Vec::new();
    for e in v {
        res.push(try!(parse_part(e)))
    }
    Ok(res)
}

fn parse_layer(v: &Vec<Sexp>) -> ERes<Element> {
    match v[1] {
        Sexp::Atom(Atom::S(ref s)) => {
            Ok(Element::Layer(s.clone()))
        }
        ref x => Err(format!("unexpected element in layer: {}", x))
    }
}

fn parse_descr(v: &Vec<Sexp>) -> ERes<Element> {
    match v[1] {
        Sexp::Atom(Atom::Q(ref s)) => {
            Ok(Element::Descr(s.clone()))
        }
        ref x => Err(format!("unexpected element in descr: {}", x))
    }
}
fn parse_fp_text(v: &Vec<Sexp>) -> ERes<Element> {
    let name = try!(match v[1] {
        Sexp::Atom(Atom::S(ref s)) => Ok(s),
        ref x => err("expecting name for fp_text")
    });
    let value = try!(match v[2] {
        Sexp::Atom(Atom::Q(ref s)) => Ok(s),
        ref x => err("expecting value for fp_text")
    });
    let mut fp = FpText::new(name, value);
    let parts = try!(parse_parts(&v[3..]));
    for part in &parts[..] {
        match *part {
            Part::At(ref at) => {
                fp.set_at(at)
            },
            Part::Layer(ref layer) => {
                fp.layer = layer.clone()
            }
            Part::Hide => {
                fp.hide = true
            },
            ref x => {
                println!("ignoring {}", x)
            }
        }
    }
    Ok(Element::FpText(fp))
}
fn parse_pad(v: &Vec<Sexp>) -> ERes<Element> {
    Ok(Element::Pad)
}
fn parse_fp_poly(v: &Vec<Sexp>) -> ERes<Element> {
    Ok(Element::FpPoly)
}
fn parse_fp_line(v: &Vec<Sexp>) -> ERes<Element> {
    Ok(Element::FpLine)
}
fn parse_fp_circle(v: &Vec<Sexp>) -> ERes<Element> {
    Ok(Element::FpCircle)
}

fn parse_element_list(v: &Vec<Sexp>) -> ERes<Element> {
    match v[0] {
        Sexp::Atom(Atom::S(ref s)) => {
            match &s[..] {
                "layer" => parse_layer(v),
                "descr" => parse_descr(v),
                "fp_text" => parse_fp_text(v),
                "pad" => parse_pad(v),
                "fp_poly" => parse_fp_poly(v),
                "fp_line" => parse_fp_line(v),
                "fp_circle" => parse_fp_circle(v),
                x => Err(format!("unknown element in module: {}", x))
            }
        }
        _ => err("expecting atom")
    }
}

fn parse_element(s: &Sexp) -> ERes<Element> {
    match *s {
        Sexp::List(ref v) => parse_element_list(&v),
        _ => err("expecting element list in module")
    }
}

fn parse_module_list(v: &Vec<Sexp>) -> ERes<Module> {
    let mut module = (match v[0] {
        Sexp::Atom(Atom::S(ref s)) if s == "module" => {
            match v[1] {
                Sexp::Atom(Atom::S(ref s)) => {
                    Ok(Module::new(s))
                }
                ref x => return Err(format!("expecting module name got {}", x))
            }
        }
        _ => err("expecting module")
    }).unwrap();
    for e in &v[2..] {
        let el = try!(parse_element(e));
        module.append(el)
    }
    Ok(module)
}

fn parse_module(s: Sexp) -> ERes<Module> {
    match s {
        Sexp::List(v) => parse_module_list(&v),
        _ => err("expecting top level list")
    }
}

fn parse(s: &str) -> ERes<Module> {
    match rustysexp::parse_str(s) {
        Ok(s) => parse_module(s),
        Err(x) => Err(format!("IOError: {}", x))
    }
}

fn read_file(name: &str) -> Result<String,std::io::Error> {
    let mut f = try!(File::open(name));
    let mut s = String::new();
    try!(f.read_to_string(&mut s));
    Ok(s)
}

pub fn parse_str(s: &str) -> Module {
    parse(s).unwrap()
}

pub fn parse_file(name: &str) -> Module {
    let s = read_file(name).unwrap();
    parse(&s[..]).unwrap()
}

<commit_msg>more parsing<commit_after>// (c) 2015-2016 Joost Yervante Damad <joost@damad.be>

use std::fmt;
use std::fs::File;
use std::io::Read;

extern crate rustysexp;
use rustysexp::Sexp;
use rustysexp::Atom;

type ERes<T> = Result<T, String>;

fn err<T>(msg: &str) -> ERes<T> {
    Err(String::from(msg))
}

#[derive(Debug)]
pub struct Module {
    name: String,
    elements: Vec<Element>
}

impl Module {
    fn new(name: &String) -> Module {
        Module { name: name.clone(), elements: vec![] }
    }
    fn append(&mut self, e: Element) {
        self.elements.push(e)
    }
}

impl fmt::Display for Module {
    fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
        try!(write!(f, "(module {}\n", self.name));
        for e in &self.elements {
            try!(write!(f, "{}\n", e))
        };
        write!(f, ")")
    }
}

#[derive(Debug)]
pub enum Element {
    Layer(String),
    Descr(String),
    FpText(FpText),
    Pad,
    FpPoly,
    FpLine,
    FpCircle
}

impl fmt::Display for Element {
    fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
        match *self {
            Element::Layer(ref s) => write!(f, "(layer {})", s),
            Element::Descr(ref s) => write!(f, "(descr \"{}\")", s),
            Element::FpText(ref p) => write!(f, "{}", p),
            Element::Pad => write!(f, "(pad)"),
            Element::FpPoly => write!(f, "(fp_poly)"),
            Element::FpLine => write!(f, "(fp_line)"),
            Element::FpCircle => write!(f, "(fp_circle)"),
        }
    }
}

#[derive(Debug)]
pub struct FpText {
    name: String,
    value: String,
    at: At,
    layer: String,
    effects: Effects,
    hide: bool,
}

impl FpText {
    fn new(name: &String, value: &String) -> FpText {
        FpText {
            name: name.clone(),
            value: value.clone(),
            at: At::new(0.,0.,0.),
            layer: String::from("cow"),
            effects: Effects::new(),
            hide: false
        }
    }
    fn set_at(&mut self, at: &At) {
        self.at.set(at)
    }
}

impl fmt::Display for FpText {
    fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
        write!(f, "(fp_text {} \"{}\" {} (layer {}){} {})", self.name, self.value, self.at, self.layer, if self.hide { " hide" } else { "" }, self.effects)
    }
}

#[derive(Debug)]
pub struct At {
    x: f64,
    y: f64,
    rot: f64
}

impl At {
    fn new(x:f64 ,y:f64, rot:f64) -> At {
        At { x:x, y:y, rot:rot }
    }
    fn set(&mut self, at: &At) {
        self.x = at.x;
        self.y = at.y;
        self.rot = at.rot;
    }
}

impl fmt::Display for At {
    fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
        if self.rot == 0.0 {
            write!(f, "(at {} {})", self.x, self.y)
        } else {
            write!(f, "(at {} {} {})", self.x, self.y, self.rot)
        }
    }
}

#[derive(Debug)]
pub struct Effects {
    todo: String
}

impl Effects {
    fn new() -> Effects {
        Effects { todo: String::from("todo") }
    }
}

impl fmt::Display for Effects {
    fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
        write!(f, "(effects)")
    }
}

#[derive(Debug)]
pub enum XyType {
    Xy,
    Start,
    End,
}

#[derive(Debug)]
pub struct Xy {
    x: f64,
    y: f64,
    t: XyType,
}

impl fmt::Display for Xy {
    fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
        match self.t {
            XyType::Xy => write!(f,"(xy {} {})", self.x, self.y),
            XyType::Start => write!(f,"(start {} {})", self.x, self.y),
            XyType::End => write!(f,"(end {} {})", self.x, self.y),
        }
    }
}

#[derive(Debug)]
enum Part {
    At(At),
    Layer(String),
    Hide,
    Effects(Effects),
    Layers(Vec<String>),
    Width(f64),
    Xy(Xy),
    Pts(Vec<Xy>),
}

impl fmt::Display for Part {
    fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
        match *self {
            Part::At(ref at)           => write!(f, "{}", at),
            Part::Layer(ref layer)     => write!(f, "(layer {})", layer),
            Part::Hide                 => write!(f, "hide"),
            Part::Effects(ref effects) => write!(f, "{}", effects),
            Part::Layers(_)            => write!(f, "(layers TODO"),
            Part::Width(ref w)         => write!(f, "(width {}", w),
            Part::Xy(ref xy)           => write!(f, "{}", xy),
            Part::Pts(_)               => write!(f, "(pts TODO)"),

        }
    }
}

// (at 0.0 -4.0) (at -2.575 -1.625 180)
fn parse_part_at(v: &Vec<Sexp>) -> ERes<Part> {
    match v.len() {
        3 => {
            let x = try!(try!(v[1].atom()).f());
            let y = try!(try!(v[2].atom()).f());
            Ok(Part::At(At::new(x, y, 0.0)))
        }
        4 => {
            let x = try!(try!(v[1].atom()).f());
            let y = try!(try!(v[2].atom()).f());
            let rot = try!(try!(v[4].atom()).f());
            Ok(Part::At(At::new(x, y, rot)))
        }
        _ => err("at with wrong length")
    }
}

fn parse_part_layer(v: &Vec<Sexp>) -> ERes<Part> {
    let layer = try!(try!(v[1].atom()).string());
    Ok(Part::Layer(layer))
}

fn parse_part_effects(v: &Vec<Sexp>) -> ERes<Part> {
    Ok(Part::Hide)
}

fn parse_part_layers(v: &Vec<Sexp>) -> ERes<Part> {
    Ok(Part::Hide)
}

fn parse_part_width(v: &Vec<Sexp>) -> ERes<Part> {
    Ok(Part::Hide)
}

fn parse_part_pts(v: &Vec<Sexp>) -> ERes<Part> {
    Ok(Part::Hide)
}

fn parse_part_xy(t: XyType, v: &Vec<Sexp>) -> ERes<Part> {
    Ok(Part::Hide)
}

fn parse_part_list(v: &Vec<Sexp>) -> ERes<Part> {
    match v[0] {
        Sexp::Atom(Atom::S(ref s)) => {
            match &s[..] {
                "at" => parse_part_at(v),
                "layer" => parse_part_layer(v),
                "effects" => parse_part_effects(v),
                "layers" => parse_part_layers(v),
                "width" => parse_part_width(v),
                "start" => parse_part_xy(XyType::Start, v),
                "end" => parse_part_xy(XyType::End, v),
                "pts" => parse_part_pts(v),
                x => Err(format!("unknown part {}", x))
            }
        }
        _ => err("expecting atom in part")
    }
}

fn parse_part(part: &Sexp) -> ERes<Part> {
    match *part {
        Sexp::Atom(Atom::S(ref s)) => {
            match &s[..] {
                "hide" => Ok(Part::Hide),
                x => Err(format!("unknown part in element: {}", x))
            }
        },
        Sexp::List(ref v) => parse_part_list(&v),
        ref x => Err(format!("unknown part in element: {}", x))
    }
}

fn parse_parts(v: &[Sexp]) -> ERes<Vec<Part>> {
    let mut res = Vec::new();
    for e in v {
        res.push(try!(parse_part(e)))
    }
    Ok(res)
}

fn parse_layer(v: &Vec<Sexp>) -> ERes<Element> {
    match v[1] {
        Sexp::Atom(Atom::S(ref s)) => {
            Ok(Element::Layer(s.clone()))
        }
        ref x => Err(format!("unexpected element in layer: {}", x))
    }
}

fn parse_descr(v: &Vec<Sexp>) -> ERes<Element> {
    match v[1] {
        Sexp::Atom(Atom::Q(ref s)) => {
            Ok(Element::Descr(s.clone()))
        }
        ref x => Err(format!("unexpected element in descr: {}", x))
    }
}
fn parse_fp_text(v: &Vec<Sexp>) -> ERes<Element> {
    let name = try!(match v[1] {
        Sexp::Atom(Atom::S(ref s)) => Ok(s),
        ref x => err("expecting name for fp_text")
    });
    let value = try!(match v[2] {
        Sexp::Atom(Atom::Q(ref s)) => Ok(s),
        ref x => err("expecting value for fp_text")
    });
    let mut fp = FpText::new(name, value);
    let parts = try!(parse_parts(&v[3..]));
    for part in &parts[..] {
        match *part {
            Part::At(ref at) => {
                fp.set_at(at)
            },
            Part::Layer(ref layer) => {
                fp.layer = layer.clone()
            }
            Part::Hide => {
                fp.hide = true
            },
            ref x => {
                println!("ignoring {}", x)
            }
        }
    }
    Ok(Element::FpText(fp))
}
fn parse_pad(v: &Vec<Sexp>) -> ERes<Element> {
    Ok(Element::Pad)
}
fn parse_fp_poly(v: &Vec<Sexp>) -> ERes<Element> {
    Ok(Element::FpPoly)
}
fn parse_fp_line(v: &Vec<Sexp>) -> ERes<Element> {
    Ok(Element::FpLine)
}
fn parse_fp_circle(v: &Vec<Sexp>) -> ERes<Element> {
    Ok(Element::FpCircle)
}

fn parse_element_list(v: &Vec<Sexp>) -> ERes<Element> {
    match v[0] {
        Sexp::Atom(Atom::S(ref s)) => {
            match &s[..] {
                "layer" => parse_layer(v),
                "descr" => parse_descr(v),
                "fp_text" => parse_fp_text(v),
                "pad" => parse_pad(v),
                "fp_poly" => parse_fp_poly(v),
                "fp_line" => parse_fp_line(v),
                "fp_circle" => parse_fp_circle(v),
                x => Err(format!("unknown element in module: {}", x))
            }
        }
        _ => err("expecting atom")
    }
}

fn parse_element(s: &Sexp) -> ERes<Element> {
    match *s {
        Sexp::List(ref v) => parse_element_list(&v),
        _ => err("expecting element list in module")
    }
}

fn parse_module_list(v: &Vec<Sexp>) -> ERes<Module> {
    let mut module = (match v[0] {
        Sexp::Atom(Atom::S(ref s)) if s == "module" => {
            match v[1] {
                Sexp::Atom(Atom::S(ref s)) => {
                    Ok(Module::new(s))
                }
                ref x => return Err(format!("expecting module name got {}", x))
            }
        }
        _ => err("expecting module")
    }).unwrap();
    for e in &v[2..] {
        let el = try!(parse_element(e));
        module.append(el)
    }
    Ok(module)
}

fn parse_module(s: Sexp) -> ERes<Module> {
    match s {
        Sexp::List(v) => parse_module_list(&v),
        _ => err("expecting top level list")
    }
}

fn parse(s: &str) -> ERes<Module> {
    match rustysexp::parse_str(s) {
        Ok(s) => parse_module(s),
        Err(x) => Err(format!("IOError: {}", x))
    }
}

fn read_file(name: &str) -> Result<String,std::io::Error> {
    let mut f = try!(File::open(name));
    let mut s = String::new();
    try!(f.read_to_string(&mut s));
    Ok(s)
}

pub fn parse_str(s: &str) -> Module {
    parse(s).unwrap()
}

pub fn parse_file(name: &str) -> Module {
    let s = read_file(name).unwrap();
    parse(&s[..]).unwrap()
}

<|endoftext|>


<commit_before>// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

/*!
 * The mac module defines the Message Authentication Code (Mac) trait.
 */

use util::fixed_time_eq;

/**
 * The Mac trait defines methods for a Message Authentication function.
 */
pub trait Mac {
    /**
     * Process input data.
     *
     * # Arguments
     * * data - The input data to process.
     *
     */
    fn input(&mut self, data: &[u8]);

    /**
     * Reset the Mac state to begin processing another input stream.
     */
    fn reset(&mut self);

    /**
     * Obtain the result of a Mac computation as a MacResult.
     */
    fn result(&mut self) -> MacResult;

    /**
     * Obtain the result of a Mac computation as [u8]. This method should be used very carefully
     * since incorrect use of the Mac code could result in permitting a timing attack which defeats
     * the security provided by a Mac function.
     */
    fn raw_result(&mut self, output: &mut [u8]);

    /**
     * Get the size of the Mac code, in bytes.
     */
    fn output_bytes(&self) -> uint;
}

/**
 * A MacResult wraps a Mac code and provides a safe Eq implementation that runs in fixed time.
 */
pub struct MacResult {
    code: Vec<u8>
}

impl MacResult {
    /**
     * Create a new MacResult.
     */
    pub fn new(code: &[u8]) -> MacResult {
        MacResult {
            code: code.to_vec()
        }
    }

    /**
     * Create a new MacResult taking ownership of the specified code value.
     */
    pub fn new_from_owned(code: Vec<u8>) -> MacResult {
        MacResult {
            code: code
        }
    }

    /**
     * Get the code value. Be very careful using this method, since incorrect use of the code value
     * may permit timing attacks which defeat the security provided by the Mac function.
     */
    pub fn code<'s>(&'s self) -> &'s [u8] {
        &self.code[]
    }
}

impl PartialEq for MacResult {
    fn eq(&self, x: &MacResult) -> bool {
        let lhs = self.code();
        let rhs = x.code();
        fixed_time_eq(lhs, rhs)
    }
}

impl Eq for MacResult { }
<commit_msg>Pick more appropriate int types for mac<commit_after>// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

/*!
 * The mac module defines the Message Authentication Code (Mac) trait.
 */

use util::fixed_time_eq;

/**
 * The Mac trait defines methods for a Message Authentication function.
 */
pub trait Mac {
    /**
     * Process input data.
     *
     * # Arguments
     * * data - The input data to process.
     *
     */
    fn input(&mut self, data: &[u8]);

    /**
     * Reset the Mac state to begin processing another input stream.
     */
    fn reset(&mut self);

    /**
     * Obtain the result of a Mac computation as a MacResult.
     */
    fn result(&mut self) -> MacResult;

    /**
     * Obtain the result of a Mac computation as [u8]. This method should be used very carefully
     * since incorrect use of the Mac code could result in permitting a timing attack which defeats
     * the security provided by a Mac function.
     */
    fn raw_result(&mut self, output: &mut [u8]);

    /**
     * Get the size of the Mac code, in bytes.
     */
    fn output_bytes(&self) -> usize;
}

/**
 * A MacResult wraps a Mac code and provides a safe Eq implementation that runs in fixed time.
 */
pub struct MacResult {
    code: Vec<u8>
}

impl MacResult {
    /**
     * Create a new MacResult.
     */
    pub fn new(code: &[u8]) -> MacResult {
        MacResult {
            code: code.to_vec()
        }
    }

    /**
     * Create a new MacResult taking ownership of the specified code value.
     */
    pub fn new_from_owned(code: Vec<u8>) -> MacResult {
        MacResult {
            code: code
        }
    }

    /**
     * Get the code value. Be very careful using this method, since incorrect use of the code value
     * may permit timing attacks which defeat the security provided by the Mac function.
     */
    pub fn code<'s>(&'s self) -> &'s [u8] {
        &self.code[]
    }
}

impl PartialEq for MacResult {
    fn eq(&self, x: &MacResult) -> bool {
        let lhs = self.code();
        let rhs = x.code();
        fixed_time_eq(lhs, rhs)
    }
}

impl Eq for MacResult { }
<|endoftext|>


<commit_before>// mod map

use std::collections::HashMap;
use std::str::FromStr;

pub type StringMap = HashMap<String, String>;

pub fn to_map(string: &str) -> StringMap {
    let pair_seperator = char::is_whitespace;
    let key_value_seperator = '=';
    let mut map = HashMap::new();

    let pairs = string.split(pair_seperator);
    for pair in pairs {
        let kv: Vec<&str> = pair.splitn(2, key_value_seperator).collect();
        if kv.len() < 2 {
            continue;
        }
        let key = kv[0].to_string();
        let value = kv[1].to_string();
        map.insert(key, value);
    }

    map
}

pub fn update_from_map<T>(map: &StringMap, key: &str, value: &mut T)
    where T: FromStr
{
    if let Some(v) = map.get(key) {
        let r: Result<T, _> = v.parse();
        match r {
            Ok(v) => {
                *value = v;
            }
            Err(_) => {}
        }
    }
}
<commit_msg>adding documentation and tests to map.rs<commit_after>//! map provides functions around StringMap (HashMap<String, String>).
//!
//! # Example
//! ```
//! use sqlib::map::{to_map, update_from_map};
//!
//! let map = to_map("key1=2");
//! let mut integer = 1i32;
//!
//! update_from_map(&map, "key1", &mut integer);
//!
//! assert_eq!(integer, 2);
//! ```

use std::collections::HashMap;
use std::str::FromStr;

/// A small newtype for a HashMap of Strings.
pub type StringMap = HashMap<String, String>;

/// creates a new StringMap from a &str.
///
/// # Example
/// ```
/// use sqlib::map::to_map;
///
/// let string = " key1=value1 key2=value2 ";
/// let map = to_map(string);
///
/// assert_eq!(map.get("key1").unwrap(), "value1");
/// assert_eq!(map.get("key2").unwrap(), "value2");
/// ```
pub fn to_map(string: &str) -> StringMap {
    let pair_seperator = char::is_whitespace;
    let key_value_seperator = '=';
    let mut map = HashMap::new();

    let pairs = string.split(pair_seperator);
    for pair in pairs {
        let kv: Vec<&str> = pair.splitn(2, key_value_seperator).collect();
        if kv.len() < 2 {
            continue;
        }
        let key = kv[0].to_string();
        let value = kv[1].to_string();
        map.insert(key, value);
    }

    map
}

/// This function gets the value to the key from the map, then parses it and mutates the given
/// pointer.
///
/// # Example
/// ```
/// use sqlib::map::{to_map, update_from_map};
///
/// let map = to_map("key1=2");
/// let mut integer = 1i32;
///
/// update_from_map(&map, "key1", &mut integer);
///
/// assert_eq!(integer, 2);
/// ```
pub fn update_from_map<T>(map: &StringMap, key: &str, value: &mut T)
    where T: FromStr
{
    if let Some(v) = map.get(key) {
        let r: Result<T, _> = v.parse();
        match r {
            Ok(v) => {
                *value = v;
            }
            Err(_) => {}
        }
    }
}
<|endoftext|>


<commit_before>//! Overrides modify a pod for use in a specific environment.
//!
//! This module has a plural name to avoid clashing with a keyword.

use project::Project;

/// An `Override` is a collection of extensions to a project's basic pods.
/// Overrides are typically used to represent deployment environments: test,
/// development and production.
///
/// (Right now, this is deliberately a very thin wrapper around the `name`
/// field, suitable for use as key in a BTreeMap.  If you add more fields,
/// you'll probably need to remove `PartialEq`, `Eq`, `PartialOrd`, `Ord`
/// from the `derive` list, and either implement them manually or redesign
/// the code that uses overlays as hash table keys.)
#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord)]
pub struct Override {
    /// The name of this environment.
    name: String,
}

impl Override {
    /// Create a new override with the specified name.
    pub fn new<S>(name: S) -> Override
        where S: Into<String>
    {
        Override { name: name.into() }
    }

    /// Get the name of this override.
    pub fn name(&self) -> &str {
        &self.name
    }

    /// Get a value for `docker-compose`'s `-p` argument for a given project.
    pub fn compose_project_name(&self, project: &Project) -> String {
        if self.name == "test" {
            format!("{}test", project.name())
        } else {
            project.name().to_owned()
        }
    }
}
<commit_msg>clippy: Fix markdown-related warning<commit_after>//! Overrides modify a pod for use in a specific environment.
//!
//! This module has a plural name to avoid clashing with a keyword.

use project::Project;

/// An `Override` is a collection of extensions to a project's basic pods.
/// Overrides are typically used to represent deployment environments: test,
/// development and production.
///
/// (Right now, this is deliberately a very thin wrapper around the `name`
/// field, suitable for use as key in a `BTreeMap`.  If you add more
/// fields, you'll probably need to remove `PartialEq`, `Eq`, `PartialOrd`,
/// `Ord` from the `derive` list, and either implement them manually or
/// redesign the code that uses overlays as hash table keys.)
#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord)]
pub struct Override {
    /// The name of this environment.
    name: String,
}

impl Override {
    /// Create a new override with the specified name.
    pub fn new<S>(name: S) -> Override
        where S: Into<String>
    {
        Override { name: name.into() }
    }

    /// Get the name of this override.
    pub fn name(&self) -> &str {
        &self.name
    }

    /// Get a value for `docker-compose`'s `-p` argument for a given project.
    pub fn compose_project_name(&self, project: &Project) -> String {
        if self.name == "test" {
            format!("{}test", project.name())
        } else {
            project.name().to_owned()
        }
    }
}
<|endoftext|>


<commit_before>//! The functions in this section provide optimized copying to persistent memory
//!
//! The `copy`, `copy_nonoverlapping`, and `write_bytes`, provide the same memory copying as
//! `memmove(3)`, `memcpy(3)`, and `memset(3)`, and ensure that the result has been flushed to persistence before returning.
//!
//! > **Warning:** Using these functions where `is_pmem(1)` returns false may not do anything useful.
//! >              Use the normal libc functions in that case.

use ::std::mem;
use ::std::io;
use ::std::marker::PhantomData;

use ::libc::{c_void, c_int};
use ::libc::size_t;
use ::pmem_sys as ffi;

use pmap::PersistentMap;

/// Persistent memory virtual pointer
///
/// This pointer is safe to store.
pub struct PmemConstVirtualPtr<T: ?Sized> {
    poolid: usize,
    offset: usize,
    _t: PhantomData<T>,
}

impl<T: ?Sized> PmemConstVirtualPtr<T> {
    pub unsafe fn new(poolid: usize, offset: usize) -> Self {
        assert!(poolid != 0, "Poolid 0 is reserved for null pointers");
        PmemConstVirtualPtr { poolid: poolid, offset: offset, _t: PhantomData }
    }

    pub fn null() -> Self { PmemConstVirtualPtr { poolid: 0, offset: 0, _t: PhantomData } }

    pub fn is_null(&self) -> bool { self.poolid == 0 }
}

impl<T> PmemConstVirtualPtr<T> {
    pub unsafe fn offset(&self, count: isize) -> Self {
        if self.is_null() {
            PmemConstVirtualPtr::null()
        } else {
            let new_offset = self.offset as isize + mem::size_of::<T>() as isize * count;
            PmemConstVirtualPtr { poolid: self.poolid, offset: new_offset as usize, _t: self._t }
        }
    }

    pub unsafe fn link(self, pool: &PersistentMap) -> PmemConstPtr<T> {
        PmemConstPtr { virt: self, pool: pool.as_ptr() }
    }
}

/// Persistent memory virtual mutable pointer
///
/// This pointer is safe to store.
pub struct PmemMutVirtualPtr<T: ?Sized> {
    poolid: usize,
    offset: usize,
    _t: PhantomData<T>,
}

impl<T: ?Sized> PmemMutVirtualPtr<T> {
    pub unsafe fn new(poolid: usize, offset: usize) -> Self {
        assert!(poolid != 0, "Poolid 0 is reserved for null pointers");
        PmemMutVirtualPtr { poolid: poolid, offset: offset, _t: PhantomData }
    }

    pub fn null() -> Self { PmemMutVirtualPtr { poolid: 0, offset: 0, _t: PhantomData } }

    pub fn is_null(&self) -> bool { self.poolid == 0 }
}

impl<T> PmemMutVirtualPtr<T> {
    pub unsafe fn offset(&self, count: isize) -> Self {
        if self.is_null() {
            PmemMutVirtualPtr::null()
        } else {
            let new_offset = self.offset as isize + mem::size_of::<T>() as isize * count;
            PmemMutVirtualPtr { poolid: self.poolid, offset: new_offset as usize, _t: self._t }
        }
    }

    pub unsafe fn link(self, pool: &mut PersistentMap) -> PmemMutPtr<T> {
        PmemMutPtr { virt: self, pool: pool.as_mut_ptr() }
    }
}

/// Direct `*const T` pointer to a pmem location
///
/// # Safety
///
/// This pointer is **not** safe to store directly on pmem.
/// You can get a _safe_ virtual pointer using `as_virtual()`.
pub struct PmemConstPtr<T: ?Sized> {
    virt: PmemConstVirtualPtr<T>,
    pool: *const T,
}

impl<T> PmemConstPtr<T> {
    pub unsafe fn direct(&self) -> *const T {
        self.pool.offset(self.virt.offset as isize) as *const T
    }

    pub fn as_virtual(self) -> PmemConstVirtualPtr<T> {
        self.virt
    }

    pub unsafe fn offset(&self, count: isize) -> Self {
        let new_virt = self.virt.offset(count);
        PmemConstPtr { virt: new_virt, pool: self.pool }
    }
}

/// Direct `*mut T` pointer to a pmem location
///
/// # Safety
///
/// This pointer is **not** safe to store directly on pmem.
/// You can get a _safe_ virtual pointer using `as_virtual()`.
pub struct PmemMutPtr<T: ?Sized> {
    virt: PmemMutVirtualPtr<T>,
    pool: *mut T,
}

impl<T> PmemMutPtr<T> {
    pub unsafe fn direct(&self) -> *mut T {
        self.pool.offset(self.virt.offset as isize) as *mut T
    }

    pub fn as_virtual(self) -> PmemMutVirtualPtr<T> {
        self.virt
    }

    pub unsafe fn offset(&self, count: isize) -> Self {
        let new_virt = self.virt.offset(count);
        PmemMutPtr { virt: new_virt, pool: self.pool }
    }
}

/// Copies `count * size_of<T>` bytes from `src` to `pmemdest`. The source and destination may overlap.
///
/// `copy` is semantically equivalent to C's `memmove` and is optimized for persitent memory.
///
/// Ensures that the result has been flushed to persistence before returning.
///
/// # Safety
///
/// Care must be taken with the ownership of `src` and `pmemdest`.
/// This method semantically moves the values of `src` into `pmemdest`.
/// However it does not drop the contents of `pmemdest`, or prevent the contents of `src` from being dropped or used.
pub unsafe fn copy<T>(src: *const T, pmemdest: *mut T, count: usize) {
    let len = mem::size_of::<T>() * count;
    ffi::pmem_memmove_persist(pmemdest as *mut c_void, src as *const c_void, len as size_t);
}

/// Copies `count * size_of<T>` bytes from `src` to `pmemdest`. The source and destination may _not_ overlap.
///
/// `copy_nonoverlapping` is semantically equivalent to C's `memcpy` and is optimized for persitent memory.
///
/// Ensures that the result has been flushed to persistence before returning.
///
/// # Safety
///
/// Beyond requiring that the program must be allowed to access both regions of memory,
/// it is _Undefined Behavior_ for source and destination to overlap.
/// Care must also be taken with the ownership of `src` and `pmemdest`.
/// This method semantically moves the values of `src` into `pmemdest`.
/// However it does not drop the contents of `pmemdest`, or prevent the contents of `src` from being dropped or used.
pub unsafe fn copy_nonoverlapping<T>(src: *const T, pmemdest: *mut T, count: usize) {
    let len = mem::size_of::<T>() * count;
    ffi::pmem_memcpy_persist(pmemdest as *mut c_void, src as *const c_void, len as size_t);
}

/// Invokes memset on the specified pointer, setting `count * size_of::<T>()` bytes of memory starting at `pmemdest` to `val`.
///
/// Ensures that the result has been flushed to persistence before returning.
pub unsafe fn write_bytes<T>(pmemdest: *mut T, val: u8, count: usize) {
    let len = mem::size_of::<T>() * count;
    ffi::pmem_memset_persist(pmemdest as *mut c_void, val as c_int, len as size_t);
}

/// Overwrites a memory location with the given value without reading or dropping the old value.
///
/// Ensures that the result has been flushed to persistence before returning.
///
/// # Safety
///
/// This operation is marked unsafe because it accepts a raw pointer.
///
/// It does not drop the contents of dst. This is safe, but it could leak allocations or resources,
/// so care must be taken not to overwrite an object that should be dropped.
///
/// This is appropriate for initializing uninitialized memory, or overwriting memory that has previously been read from.
pub unsafe fn write<T>(pmemdest: *mut T, val: T) { copy_nonoverlapping(&val as *const _, pmemdest, 1) }

pub unsafe fn msync<T>(pmemdest: *const T, count: usize) -> Result<(), io::Error> {
    let len = count * mem::size_of::<T>();
    let r = ffi::pmem_msync(pmemdest as *const c_void, len as size_t);
    if r == -1 {
        Err(io::Error::last_os_error())
    } else {
        Ok(())
    }
}
<commit_msg>feat: add casting<commit_after>//! The functions in this section provide optimized copying to persistent memory
//!
//! The `copy`, `copy_nonoverlapping`, and `write_bytes`, provide the same memory copying as
//! `memmove(3)`, `memcpy(3)`, and `memset(3)`, and ensure that the result has been flushed to persistence before returning.
//!
//! > **Warning:** Using these functions where `is_pmem(1)` returns false may not do anything useful.
//! >              Use the normal libc functions in that case.

use ::std::mem;
use ::std::io;
use ::std::marker::PhantomData;

use ::libc::{c_void, c_int};
use ::libc::size_t;
use ::pmem_sys as ffi;

use pmap::PersistentMap;

/// Persistent memory virtual pointer
///
/// This pointer is safe to store.
pub struct PmemConstVirtualPtr<T: ?Sized> {
    poolid: usize,
    offset: usize,
    _t: PhantomData<T>,
}

impl<T: ?Sized> PmemConstVirtualPtr<T> {
    pub unsafe fn new(poolid: usize, offset: usize) -> Self {
        assert!(poolid != 0, "Poolid 0 is reserved for null pointers");
        PmemConstVirtualPtr { poolid: poolid, offset: offset, _t: PhantomData }
    }

    pub fn null() -> Self { PmemConstVirtualPtr { poolid: 0, offset: 0, _t: PhantomData } }

    pub fn is_null(&self) -> bool { self.poolid == 0 }

    pub unsafe fn as_type<U>(self) -> PmemConstVirtualPtr<U> {
        PmemConstVirtualPtr { poolid: self.poolid, offset: self.offset, _t: PhantomData }
    }
}

impl<T> PmemConstVirtualPtr<T> {
    pub unsafe fn offset(&self, count: isize) -> Self {
        if self.is_null() {
            PmemConstVirtualPtr::null()
        } else {
            let new_offset = self.offset as isize + mem::size_of::<T>() as isize * count;
            PmemConstVirtualPtr { poolid: self.poolid, offset: new_offset as usize, _t: self._t }
        }
    }

    pub unsafe fn link(self, pool: &PersistentMap) -> PmemConstPtr<T> {
        PmemConstPtr { virt: self, pool: pool.as_ptr() }
    }
}

/// Persistent memory virtual mutable pointer
///
/// This pointer is safe to store.
pub struct PmemMutVirtualPtr<T: ?Sized> {
    poolid: usize,
    offset: usize,
    _t: PhantomData<T>,
}

impl<T: ?Sized> PmemMutVirtualPtr<T> {
    pub unsafe fn new(poolid: usize, offset: usize) -> Self {
        assert!(poolid != 0, "Poolid 0 is reserved for null pointers");
        PmemMutVirtualPtr { poolid: poolid, offset: offset, _t: PhantomData }
    }

    pub fn null() -> Self { PmemMutVirtualPtr { poolid: 0, offset: 0, _t: PhantomData } }

    pub fn is_null(&self) -> bool { self.poolid == 0 }

    pub unsafe fn as_type<U>(self) -> PmemMutVirtualPtr<U> {
        PmemMutVirtualPtr { poolid: self.poolid, offset: self.offset, _t: PhantomData }
    }
}

impl<T> PmemMutVirtualPtr<T> {
    pub unsafe fn offset(&self, count: isize) -> Self {
        if self.is_null() {
            PmemMutVirtualPtr::null()
        } else {
            let new_offset = self.offset as isize + mem::size_of::<T>() as isize * count;
            PmemMutVirtualPtr { poolid: self.poolid, offset: new_offset as usize, _t: self._t }
        }
    }

    pub unsafe fn link(self, pool: &mut PersistentMap) -> PmemMutPtr<T> {
        PmemMutPtr { virt: self, pool: pool.as_mut_ptr() }
    }
}

/// Direct `*const T` pointer to a pmem location
///
/// # Safety
///
/// This pointer is **not** safe to store directly on pmem.
/// You can get a _safe_ virtual pointer using `as_virtual()`.
pub struct PmemConstPtr<T: ?Sized> {
    virt: PmemConstVirtualPtr<T>,
    pool: *const T,
}

impl<T> PmemConstPtr<T> {
    pub unsafe fn direct(&self) -> *const T {
        self.pool.offset(self.virt.offset as isize) as *const T
    }

    pub fn as_virtual(self) -> PmemConstVirtualPtr<T> {
        self.virt
    }

    pub unsafe fn offset(&self, count: isize) -> Self {
        let new_virt = self.virt.offset(count);
        PmemConstPtr { virt: new_virt, pool: self.pool }
    }

    pub unsafe fn as_type<U>(self) -> PmemConstPtr<U> {
        let new_virt = self.virt.as_type();
        PmemConstPtr { virt: new_virt, pool: self.pool as *mut U }
    }
}

/// Direct `*mut T` pointer to a pmem location
///
/// # Safety
///
/// This pointer is **not** safe to store directly on pmem.
/// You can get a _safe_ virtual pointer using `as_virtual()`.
pub struct PmemMutPtr<T: ?Sized> {
    virt: PmemMutVirtualPtr<T>,
    pool: *mut T,
}

impl<T> PmemMutPtr<T> {
    pub unsafe fn direct(&self) -> *mut T {
        self.pool.offset(self.virt.offset as isize) as *mut T
    }

    pub fn as_virtual(self) -> PmemMutVirtualPtr<T> {
        self.virt
    }

    pub unsafe fn offset(&self, count: isize) -> Self {
        let new_virt = self.virt.offset(count);
        PmemMutPtr { virt: new_virt, pool: self.pool }
    }

    pub unsafe fn as_type<U>(self) -> PmemMutPtr<U> {
        let new_virt = self.virt.as_type();
        PmemMutPtr { virt: new_virt, pool: self.pool as *mut U }
    }
}

/// Copies `count * size_of<T>` bytes from `src` to `pmemdest`. The source and destination may overlap.
///
/// `copy` is semantically equivalent to C's `memmove` and is optimized for persitent memory.
///
/// Ensures that the result has been flushed to persistence before returning.
///
/// # Safety
///
/// Care must be taken with the ownership of `src` and `pmemdest`.
/// This method semantically moves the values of `src` into `pmemdest`.
/// However it does not drop the contents of `pmemdest`, or prevent the contents of `src` from being dropped or used.
pub unsafe fn copy<T>(src: *const T, pmemdest: *mut T, count: usize) {
    let len = mem::size_of::<T>() * count;
    ffi::pmem_memmove_persist(pmemdest as *mut c_void, src as *const c_void, len as size_t);
}

/// Copies `count * size_of<T>` bytes from `src` to `pmemdest`. The source and destination may _not_ overlap.
///
/// `copy_nonoverlapping` is semantically equivalent to C's `memcpy` and is optimized for persitent memory.
///
/// Ensures that the result has been flushed to persistence before returning.
///
/// # Safety
///
/// Beyond requiring that the program must be allowed to access both regions of memory,
/// it is _Undefined Behavior_ for source and destination to overlap.
/// Care must also be taken with the ownership of `src` and `pmemdest`.
/// This method semantically moves the values of `src` into `pmemdest`.
/// However it does not drop the contents of `pmemdest`, or prevent the contents of `src` from being dropped or used.
pub unsafe fn copy_nonoverlapping<T>(src: *const T, pmemdest: *mut T, count: usize) {
    let len = mem::size_of::<T>() * count;
    ffi::pmem_memcpy_persist(pmemdest as *mut c_void, src as *const c_void, len as size_t);
}

/// Invokes memset on the specified pointer, setting `count * size_of::<T>()` bytes of memory starting at `pmemdest` to `val`.
///
/// Ensures that the result has been flushed to persistence before returning.
pub unsafe fn write_bytes<T>(pmemdest: *mut T, val: u8, count: usize) {
    let len = mem::size_of::<T>() * count;
    ffi::pmem_memset_persist(pmemdest as *mut c_void, val as c_int, len as size_t);
}

/// Overwrites a memory location with the given value without reading or dropping the old value.
///
/// Ensures that the result has been flushed to persistence before returning.
///
/// # Safety
///
/// This operation is marked unsafe because it accepts a raw pointer.
///
/// It does not drop the contents of dst. This is safe, but it could leak allocations or resources,
/// so care must be taken not to overwrite an object that should be dropped.
///
/// This is appropriate for initializing uninitialized memory, or overwriting memory that has previously been read from.
pub unsafe fn write<T>(pmemdest: *mut T, val: T) { copy_nonoverlapping(&val as *const _, pmemdest, 1) }

pub unsafe fn msync<T>(pmemdest: *const T, count: usize) -> Result<(), io::Error> {
    let len = count * mem::size_of::<T>();
    let r = ffi::pmem_msync(pmemdest as *const c_void, len as size_t);
    if r == -1 {
        Err(io::Error::last_os_error())
    } else {
        Ok(())
    }
}
<|endoftext|>


<commit_before>use std::io::{self, Write, Read, Cursor};
use std::net::{TcpStream, Shutdown};
use std::time::Duration;
use std::borrow::BorrowMut;
use byteorder::{BigEndian, WriteBytesExt};
use bincode::rustc_serialize::{encode, decode};
use bincode::SizeLimit;
use enum_primitive::FromPrimitive;
use {Function, Reason, Result, ExceptionCode, Error, Coil, binary, Client};

const MODBUS_PROTOCOL_TCP: u16 = 0x0000;
const MODBUS_TCP_DEFAULT_PORT: u16 = 502;
const MODBUS_HEADER_SIZE: usize = 7;
const MODBUS_MAX_PACKET_SIZE: usize = 260;

#[derive(RustcEncodable, RustcDecodable)]
#[repr(packed)]
struct Header {
    tid: u16,
    pid: u16,
    len: u16,
    uid: u8,
}

impl Header {
    fn new(transport: &mut Transport, len: u16) -> Header {
        Header {
            tid: transport.new_tid(),
            pid: MODBUS_PROTOCOL_TCP,
            len: len - MODBUS_HEADER_SIZE as u16,
            uid: transport.uid,
        }
    }
}

/// Context object which holds state for all modbus operations.
pub struct Transport {
    tid: u16,
    uid: u8,
    stream: TcpStream,
}

impl Transport {
    /// Create a new context context object and connect it to `addr` on modbus-tcp default
    /// port (502)
    pub fn new(addr: &str) -> io::Result<Transport> {
        Self::new_with_port(addr, MODBUS_TCP_DEFAULT_PORT)
    }

    /// Create a new context object and connect it to `addr` on port `port`
    pub fn new_with_port(addr: &str, port: u16) -> io::Result<Transport> {
        match TcpStream::connect((addr, port)) {
            Ok(s) => {
                // set some sane tcp socket options
                let t = Duration::from_secs(5);
                try!(s.set_read_timeout(Some(t)));
                try!(s.set_write_timeout(Some(t)));
                //                try!(s.set_nodelay(true));
                //                try!(s.set_keepalive(None));
                Ok(Transport {
                    tid: 0,
                    uid: 1,
                    stream: s,
                })
            }
            Err(e) => Err(e),
        }
    }

    // Create a new transaction Id, incrementing the previous one.
    // The Id is wrapping around if the Id reaches `u16::MAX`.
    fn new_tid(&mut self) -> u16 {
        self.tid = self.tid.wrapping_add(1);
        self.tid
    }

    fn read(self: &mut Self, fun: Function) -> Result<Vec<u8>> {
        let packed_size = |v: u16| {
            v / 8 +
            if v % 8 > 0 {
                1
            } else {
                0
            }
        };
        let (addr, count, expected_bytes) = match fun {
            Function::ReadCoils(a, c) => (a, c, packed_size(c) as usize),
            Function::ReadDiscreteInputs(a, c) => (a, c, packed_size(c) as usize),
            Function::ReadHoldingRegisters(a, c) => (a, c, 2 * c as usize),
            Function::ReadInputRegisters(a, c) => (a, c, 2 * c as usize),
            _ => return Err(Error::InvalidFunction),
        };

        if count < 1 {
            return Err(Error::InvalidData(Reason::RecvBufferEmpty));
        }

        if count as usize > MODBUS_MAX_PACKET_SIZE {
            return Err(Error::InvalidData(Reason::UnexpectedReplySize));
        }

        let header = Header::new(self, MODBUS_HEADER_SIZE as u16 + 6u16);
        let mut buff = try!(encode(&header, SizeLimit::Infinite));
        try!(buff.write_u8(fun.code()));
        try!(buff.write_u16::<BigEndian>(addr));
        try!(buff.write_u16::<BigEndian>(count));

        match self.stream.write_all(&buff[..]) {
            Ok(_s) => {
                let mut reply = vec![0; MODBUS_HEADER_SIZE + expected_bytes + 2];
                match self.stream.read(&mut reply) {
                    Ok(_s) => {
                        let resp_hd = try!(decode(&reply[..MODBUS_HEADER_SIZE]));
                        try!(Transport::validate_response_header(&header, &resp_hd));
                        try!(Transport::validate_response_code(&buff, &reply[..]));
                        Transport::get_reply_data(&reply, expected_bytes)
                    }
                    Err(e) => Err(Error::Io(e)),
                }
            }
            Err(e) => Err(Error::Io(e)),
        }
    }

    fn validate_response_header(req: &Header, resp: &Header) -> Result<()> {
        if req.tid != resp.tid || resp.pid != MODBUS_PROTOCOL_TCP {
            Err(Error::InvalidResponse)
        } else {
            Ok(())
        }
    }

    fn validate_response_code(req: &[u8], resp: &[u8]) -> Result<()> {
        if req[7] + 0x80 == resp[7] {
            match ExceptionCode::from_u8(resp[8]) {
                Some(code) => Err(Error::Exception(code)),
                None => Err(Error::InvalidResponse),
            }
        } else if req[7] != resp[7] {
            Err(Error::InvalidResponse)
        } else {
            Ok(())
        }
    }

    fn get_reply_data(reply: &[u8], expected_bytes: usize) -> Result<Vec<u8>> {
        if reply[8] as usize != expected_bytes ||
           reply.len() != MODBUS_HEADER_SIZE + expected_bytes + 2 {
            Err(Error::InvalidData(Reason::UnexpectedReplySize))
        } else {
            let mut d = Vec::new();
            d.extend(reply[MODBUS_HEADER_SIZE + 2..].iter());
            Ok(d)
        }
    }

    fn write_single(self: &mut Self, fun: Function) -> Result<()> {
        let (addr, value) = match fun {
            Function::WriteSingleCoil(a, v) => (a, v),
            Function::WriteSingleRegister(a, v) => (a, v),
            _ => return Err(Error::InvalidFunction),
        };

        let mut buff = vec![0; MODBUS_HEADER_SIZE];  // Header gets filled in later
        try!(buff.write_u8(fun.code()));
        try!(buff.write_u16::<BigEndian>(addr));
        try!(buff.write_u16::<BigEndian>(value));
        self.write(&mut buff)
    }

    fn write_multiple(self: &mut Self, fun: Function) -> Result<()> {
        let (addr, quantity, values) = match fun {
            Function::WriteMultipleCoils(a, q, v) => (a, q, v),
            Function::WriteMultipleRegisters(a, q, v) => (a, q, v),
            _ => return Err(Error::InvalidFunction),
        };

        let mut buff = vec![0; MODBUS_HEADER_SIZE];  // Header gets filled in later
        try!(buff.write_u8(fun.code()));
        try!(buff.write_u16::<BigEndian>(addr));
        try!(buff.write_u16::<BigEndian>(quantity));
        try!(buff.write_u8(values.len() as u8));
        for v in values {
            try!(buff.write_u8(*v));
        }
        self.write(&mut buff)
    }

    fn write(self: &mut Self, buff: &mut [u8]) -> Result<()> {
        if buff.len() < 1 {
            return Err(Error::InvalidData(Reason::SendBufferEmpty));
        }

        if buff.len() > MODBUS_MAX_PACKET_SIZE {
            return Err(Error::InvalidData(Reason::SendBufferTooBig));
        }

        let header = Header::new(self, buff.len() as u16 + 1u16);
        let head_buff = try!(encode(&header, SizeLimit::Infinite));
        {
            let mut start = Cursor::new(buff.borrow_mut());
            try!(start.write(&head_buff[..]));
        }
        match self.stream.write_all(&buff[..]) {
            Ok(_s) => {
                let reply = &mut [0; 12];
                match self.stream.read(reply) {
                    Ok(_s) => {
                        let resp_hd = try!(decode(&reply[..MODBUS_HEADER_SIZE]));
                        try!(Transport::validate_response_header(&header, &resp_hd));
                        Transport::validate_response_code(&buff, reply)
                    }
                    Err(e) => Err(Error::Io(e)),
                }
            }
            Err(e) => Err(Error::Io(e)),
        }
    }

    pub fn close(self: &mut Self) -> Result<()> {
        self.stream.shutdown(Shutdown::Both).map_err(Error::Io)
    }

}

impl Client for Transport {
    /// Read `count` bits starting at address `addr`.
    fn read_coils(self: &mut Self, addr: u16, count: u16) -> Result<Vec<Coil>> {
        let bytes = try!(self.read(Function::ReadCoils(addr, count)));
        Ok(binary::unpack_bits(&bytes, count))
    }

    /// Read `count` input bits starting at address `addr`.
    fn read_discrete_inputs(self: &mut Self, addr: u16, count: u16) -> Result<Vec<Coil>> {
        let bytes = try!(self.read(Function::ReadDiscreteInputs(addr, count)));
        Ok(binary::unpack_bits(&bytes, count))
    }

    /// Read `count` 16bit registers starting at address `addr`.
    fn read_holding_registers(self: &mut Self, addr: u16, count: u16) -> Result<Vec<u16>> {
        let bytes = try!(self.read(Function::ReadHoldingRegisters(addr, count)));
        binary::pack_bytes(&bytes[..])
    }

    /// Read `count` 16bit input registers starting at address `addr`.
    fn read_input_registers(self: &mut Self, addr: u16, count: u16) -> Result<Vec<u16>> {
        let bytes = try!(self.read(Function::ReadInputRegisters(addr, count)));
        binary::pack_bytes(&bytes[..])
    }

    /// Write a single coil (bit) to address `addr`.
    fn write_single_coil(self: &mut Self, addr: u16, value: Coil) -> Result<()> {
        self.write_single(Function::WriteSingleCoil(addr, value.code()))
    }

    /// Write a single 16bit register to address `addr`.
    fn write_single_register(self: &mut Self, addr: u16, value: u16) -> Result<()> {
        self.write_single(Function::WriteSingleRegister(addr, value))
    }

    /// Write a multiple coils (bits) starting at address `addr`.
    fn write_multiple_coils(self: &mut Self, addr: u16, values: &[Coil]) -> Result<()> {
        let bytes = binary::pack_bits(values);
        self.write_multiple(Function::WriteMultipleCoils(addr, values.len() as u16, &bytes[..]))
    }

    /// Write a multiple 16bit registers starting at address `addr`.
    fn write_multiple_registers(self: &mut Self, addr: u16, values: &[u16]) -> Result<()> {
        let bytes = binary::unpack_bytes(values);
        self.write_multiple(Function::WriteMultipleRegisters(addr, values.len() as u16, &bytes[..]))
    }
}
<commit_msg>Heeding some clippy hints<commit_after>use std::io::{self, Write, Read, Cursor};
use std::net::{TcpStream, Shutdown};
use std::time::Duration;
use std::borrow::BorrowMut;
use byteorder::{BigEndian, WriteBytesExt};
use bincode::rustc_serialize::{encode, decode};
use bincode::SizeLimit;
use enum_primitive::FromPrimitive;
use {Function, Reason, Result, ExceptionCode, Error, Coil, binary, Client};

const MODBUS_PROTOCOL_TCP: u16 = 0x0000;
const MODBUS_TCP_DEFAULT_PORT: u16 = 502;
const MODBUS_HEADER_SIZE: usize = 7;
const MODBUS_MAX_PACKET_SIZE: usize = 260;

#[derive(RustcEncodable, RustcDecodable)]
#[repr(packed)]
struct Header {
    tid: u16,
    pid: u16,
    len: u16,
    uid: u8,
}

impl Header {
    fn new(transport: &mut Transport, len: u16) -> Header {
        Header {
            tid: transport.new_tid(),
            pid: MODBUS_PROTOCOL_TCP,
            len: len - MODBUS_HEADER_SIZE as u16,
            uid: transport.uid,
        }
    }
}

/// Context object which holds state for all modbus operations.
pub struct Transport {
    tid: u16,
    uid: u8,
    stream: TcpStream,
}

impl Transport {
    /// Create a new context context object and connect it to `addr` on modbus-tcp default
    /// port (502)
    pub fn new(addr: &str) -> io::Result<Transport> {
        Self::new_with_port(addr, MODBUS_TCP_DEFAULT_PORT)
    }

    /// Create a new context object and connect it to `addr` on port `port`
    pub fn new_with_port(addr: &str, port: u16) -> io::Result<Transport> {
        match TcpStream::connect((addr, port)) {
            Ok(s) => {
                // set some sane tcp socket options
                let t = Duration::from_secs(5);
                try!(s.set_read_timeout(Some(t)));
                try!(s.set_write_timeout(Some(t)));
                //                try!(s.set_nodelay(true));
                //                try!(s.set_keepalive(None));
                Ok(Transport {
                    tid: 0,
                    uid: 1,
                    stream: s,
                })
            }
            Err(e) => Err(e),
        }
    }

    // Create a new transaction Id, incrementing the previous one.
    // The Id is wrapping around if the Id reaches `u16::MAX`.
    fn new_tid(&mut self) -> u16 {
        self.tid = self.tid.wrapping_add(1);
        self.tid
    }

    fn read(self: &mut Self, fun: Function) -> Result<Vec<u8>> {
        let packed_size = |v: u16| {
            v / 8 +
            if v % 8 > 0 {
                1
            } else {
                0
            }
        };
        let (addr, count, expected_bytes) = match fun {
            Function::ReadCoils(a, c) |
            Function::ReadDiscreteInputs(a, c) => (a, c, packed_size(c) as usize),
            Function::ReadHoldingRegisters(a, c) |
            Function::ReadInputRegisters(a, c) => (a, c, 2 * c as usize),
            _ => return Err(Error::InvalidFunction),
        };

        if count < 1 {
            return Err(Error::InvalidData(Reason::RecvBufferEmpty));
        }

        if count as usize > MODBUS_MAX_PACKET_SIZE {
            return Err(Error::InvalidData(Reason::UnexpectedReplySize));
        }

        let header = Header::new(self, MODBUS_HEADER_SIZE as u16 + 6u16);
        let mut buff = try!(encode(&header, SizeLimit::Infinite));
        try!(buff.write_u8(fun.code()));
        try!(buff.write_u16::<BigEndian>(addr));
        try!(buff.write_u16::<BigEndian>(count));

        match self.stream.write_all(&buff[..]) {
            Ok(_s) => {
                let mut reply = vec![0; MODBUS_HEADER_SIZE + expected_bytes + 2];
                match self.stream.read(&mut reply) {
                    Ok(_s) => {
                        let resp_hd = try!(decode(&reply[..MODBUS_HEADER_SIZE]));
                        try!(Transport::validate_response_header(&header, &resp_hd));
                        try!(Transport::validate_response_code(&buff, &reply[..]));
                        Transport::get_reply_data(&reply, expected_bytes)
                    }
                    Err(e) => Err(Error::Io(e)),
                }
            }
            Err(e) => Err(Error::Io(e)),
        }
    }

    fn validate_response_header(req: &Header, resp: &Header) -> Result<()> {
        if req.tid != resp.tid || resp.pid != MODBUS_PROTOCOL_TCP {
            Err(Error::InvalidResponse)
        } else {
            Ok(())
        }
    }

    fn validate_response_code(req: &[u8], resp: &[u8]) -> Result<()> {
        if req[7] + 0x80 == resp[7] {
            match ExceptionCode::from_u8(resp[8]) {
                Some(code) => Err(Error::Exception(code)),
                None => Err(Error::InvalidResponse),
            }
        } else if req[7] != resp[7] {
            Err(Error::InvalidResponse)
        } else {
            Ok(())
        }
    }

    fn get_reply_data(reply: &[u8], expected_bytes: usize) -> Result<Vec<u8>> {
        if reply[8] as usize != expected_bytes ||
           reply.len() != MODBUS_HEADER_SIZE + expected_bytes + 2 {
            Err(Error::InvalidData(Reason::UnexpectedReplySize))
        } else {
            let mut d = Vec::new();
            d.extend(reply[MODBUS_HEADER_SIZE + 2..].iter());
            Ok(d)
        }
    }

    fn write_single(self: &mut Self, fun: Function) -> Result<()> {
        let (addr, value) = match fun {
            Function::WriteSingleCoil(a, v) |
            Function::WriteSingleRegister(a, v) => (a, v),
            _ => return Err(Error::InvalidFunction),
        };

        let mut buff = vec![0; MODBUS_HEADER_SIZE];  // Header gets filled in later
        try!(buff.write_u8(fun.code()));
        try!(buff.write_u16::<BigEndian>(addr));
        try!(buff.write_u16::<BigEndian>(value));
        self.write(&mut buff)
    }

    fn write_multiple(self: &mut Self, fun: Function) -> Result<()> {
        let (addr, quantity, values) = match fun {
            Function::WriteMultipleCoils(a, q, v) |
            Function::WriteMultipleRegisters(a, q, v) => (a, q, v),
            _ => return Err(Error::InvalidFunction),
        };

        let mut buff = vec![0; MODBUS_HEADER_SIZE];  // Header gets filled in later
        try!(buff.write_u8(fun.code()));
        try!(buff.write_u16::<BigEndian>(addr));
        try!(buff.write_u16::<BigEndian>(quantity));
        try!(buff.write_u8(values.len() as u8));
        for v in values {
            try!(buff.write_u8(*v));
        }
        self.write(&mut buff)
    }

    fn write(self: &mut Self, buff: &mut [u8]) -> Result<()> {
        if buff.len() < 1 {
            return Err(Error::InvalidData(Reason::SendBufferEmpty));
        }

        if buff.len() > MODBUS_MAX_PACKET_SIZE {
            return Err(Error::InvalidData(Reason::SendBufferTooBig));
        }

        let header = Header::new(self, buff.len() as u16 + 1u16);
        let head_buff = try!(encode(&header, SizeLimit::Infinite));
        {
            let mut start = Cursor::new(buff.borrow_mut());
            try!(start.write(&head_buff[..]));
        }
        match self.stream.write_all(&buff[..]) {
            Ok(_s) => {
                let reply = &mut [0; 12];
                match self.stream.read(reply) {
                    Ok(_s) => {
                        let resp_hd = try!(decode(&reply[..MODBUS_HEADER_SIZE]));
                        try!(Transport::validate_response_header(&header, &resp_hd));
                        Transport::validate_response_code(&buff, reply)
                    }
                    Err(e) => Err(Error::Io(e)),
                }
            }
            Err(e) => Err(Error::Io(e)),
        }
    }

    pub fn close(self: &mut Self) -> Result<()> {
        self.stream.shutdown(Shutdown::Both).map_err(Error::Io)
    }

}

impl Client for Transport {
    /// Read `count` bits starting at address `addr`.
    fn read_coils(self: &mut Self, addr: u16, count: u16) -> Result<Vec<Coil>> {
        let bytes = try!(self.read(Function::ReadCoils(addr, count)));
        Ok(binary::unpack_bits(&bytes, count))
    }

    /// Read `count` input bits starting at address `addr`.
    fn read_discrete_inputs(self: &mut Self, addr: u16, count: u16) -> Result<Vec<Coil>> {
        let bytes = try!(self.read(Function::ReadDiscreteInputs(addr, count)));
        Ok(binary::unpack_bits(&bytes, count))
    }

    /// Read `count` 16bit registers starting at address `addr`.
    fn read_holding_registers(self: &mut Self, addr: u16, count: u16) -> Result<Vec<u16>> {
        let bytes = try!(self.read(Function::ReadHoldingRegisters(addr, count)));
        binary::pack_bytes(&bytes[..])
    }

    /// Read `count` 16bit input registers starting at address `addr`.
    fn read_input_registers(self: &mut Self, addr: u16, count: u16) -> Result<Vec<u16>> {
        let bytes = try!(self.read(Function::ReadInputRegisters(addr, count)));
        binary::pack_bytes(&bytes[..])
    }

    /// Write a single coil (bit) to address `addr`.
    fn write_single_coil(self: &mut Self, addr: u16, value: Coil) -> Result<()> {
        self.write_single(Function::WriteSingleCoil(addr, value.code()))
    }

    /// Write a single 16bit register to address `addr`.
    fn write_single_register(self: &mut Self, addr: u16, value: u16) -> Result<()> {
        self.write_single(Function::WriteSingleRegister(addr, value))
    }

    /// Write a multiple coils (bits) starting at address `addr`.
    fn write_multiple_coils(self: &mut Self, addr: u16, values: &[Coil]) -> Result<()> {
        let bytes = binary::pack_bits(values);
        self.write_multiple(Function::WriteMultipleCoils(addr, values.len() as u16, &bytes[..]))
    }

    /// Write a multiple 16bit registers starting at address `addr`.
    fn write_multiple_registers(self: &mut Self, addr: u16, values: &[u16]) -> Result<()> {
        let bytes = binary::unpack_bytes(values);
        self.write_multiple(Function::WriteMultipleRegisters(addr, values.len() as u16, &bytes[..]))
    }
}
<|endoftext|>


<commit_before>extern crate libc;

use std;
use libc::c_char;

use std::io::Write;
use std::io::stdout;

use nom::*;

use tls_parser::tls::{TlsMessage,TlsPlaintext,TlsMessageHandshake,tls_parser_many};
use tls_parser::tls_ciphers::TlsCipherSuite;
use tls_parser::tls_extensions::parse_tls_extensions;
use der_parser::der::parse_der;

pub struct TlsParserState<'a> {
    pub o: Option<&'a[u8]>,
    m: Option<Vec<TlsPlaintext<'a>>>,
}

impl<'a> TlsParserState<'a> {
    pub fn new(i: &'a[u8], m:Option<Vec<TlsPlaintext<'a>>>) -> TlsParserState<'a> {
        TlsParserState{o:Some(i),m:m}
    }

    fn send(&self, value: i32) -> bool {
        println!("=============================================================");
        println!("inner send: {}", value);
        println!("m: {:?}", self.m);
        println!("=============================================================");
        let _ = stdout().flush();
        true
    }
}

impl<'a> Drop for TlsParserState<'a> {
    fn drop(&mut self) {
        println!("DROP");
    }
}

#[no_mangle]
pub extern "C" fn rusticata_new_tls_parser_state<'a>() -> Box<TlsParserState<'a>> {
    Box::new(TlsParserState::new(b"blah",None))
}

#[no_mangle]
pub extern fn rusticata_free_tls_parser_state<'a>(_: Box<TlsParserState<'a>>)
{
    println!("rusticata_free_tls_parser_state()");
}

#[no_mangle]
pub extern fn rusticata_use_tls_parser_state<'a>(this: &TlsParserState<'a>, value: i32) -> bool
{
    println!("rusticata_use_tls_parser_state({:?})", value);
    this.send(value)
}

#[no_mangle]
pub extern "C" fn rusticata_parse_der(value: *const c_char, len: u32) -> i32 {
    SCLogDebug!("[rust] rusticata_parse_der");

    let data_len = len as usize;
    let data : &[u8] = unsafe { std::slice::from_raw_parts(value as *mut u8, data_len) };

    let d = parse_der(data);
    SCLogDebug!(format!("d: {:?}", d).as_str());

    0
}

#[no_mangle]
pub extern "C" fn rusticata_tls_decode<'a>(direction: u8, value: *const c_char, len: u32) -> Box<TlsParserState<'a>> {
    SCLogDebug!("[rust] suri_tls_decode");

    let data_len = len as usize;
    let data : &[u8] = unsafe { std::slice::from_raw_parts(value as *mut u8, data_len) };

    SCLogDebug!(format!("  direction: {}\0", direction).as_str());
    SCLogDebug!(format!("  len: {}\0", data_len).as_str());
    SCLogDebug!(format!("  data: {:?}\0", data).as_str());

    let d = tls_parser_many(data);
    SCLogDebug!(format!("d: {:?}\0", d).as_str());

    // XXX match d with nom::IResult::Done, check if ServerHello, and print selected cipher
    let r =
    match d {
        IResult::Done(rem,p) => {
            SCLogDebug!(format!("TLS parser successful {} element(s)\0", p.len()).as_str());
            for ref record in &p {
                SCLogDebug!(format!("{:?}\0", record).as_str());
                match record.msg {
                    TlsMessage::Handshake(ref m) => {
                        match *m {
                            TlsMessageHandshake::ClientHello(ref content) => {
                                let blah = parse_tls_extensions(content.ext);
                                SCLogDebug!(format!("ext {:?}\0", blah).as_str());
                            },
                            TlsMessageHandshake::ServerHello(ref content) => {
                                let lu /* cipher */ : TlsCipherSuite = content.cipher.into();
                                SCLogDebug!(format!("Selected cipher: {:?}\0", lu).as_str());
                                let blah = parse_tls_extensions(content.ext);
                                SCLogDebug!(format!("ext {:?}\0", blah).as_str());
                            },
                            _ => (),
                        }
                    },
                    _ => (),
                }
            }
            if rem.len() > 0 { SCLogWarning!(format!("** unparsed ** {:?}\0",rem).as_str()); };
            Some(p)
        },
        IResult::Error(e) => {SCLogError!(format!("TLS parser reported an error: {:?}\0", e).as_str());None},
        IResult::Incomplete(e) => {SCLogError!(format!("TLS parser reported incomplete input: {:?}\0", e).as_str());None},
    };

    Box::new(TlsParserState::new(b"blah",r))
}

#[cfg(test)]
mod tests {
    #[test]
    fn it_works() {
    }
}
<commit_msg>Store TLS parser context in Suricata, update it after parsing<commit_after>extern crate libc;

use std;
use libc::c_char;

use std::io::Write;
use std::io::stdout;

use nom::*;

use tls_parser::tls::{TlsMessage,TlsMessageHandshake,tls_parser_many};
use tls_parser::tls_ciphers::TlsCipherSuite;
use tls_parser::tls_extensions::parse_tls_extensions;
use der_parser::der::parse_der;

pub struct TlsParserState<'a> {
    pub o: Option<&'a[u8]>,

    cipher: u16,
}

impl<'a> TlsParserState<'a> {
    pub fn new(i: &'a[u8]) -> TlsParserState<'a> {
        TlsParserState{o:Some(i),cipher:0}
    }

    fn send(&self, value: i32) -> bool {
        println!("=============================================================");
        println!("inner send: {}", value);
        println!("o: {:?}", self.o);
        println!("cipher: {:?}", self.cipher);
        println!("=============================================================");
        let _ = stdout().flush();
        true
    }
}

impl<'a> Drop for TlsParserState<'a> {
    fn drop(&mut self) {
        println!("DROP");
    }
}

#[no_mangle]
pub extern "C" fn rusticata_new_tls_parser_state<'a>() -> Box<TlsParserState<'a>> {
    Box::new(TlsParserState::new(b"blah"))
}

#[no_mangle]
pub extern fn rusticata_free_tls_parser_state<'a>(_: Box<TlsParserState<'a>>)
{
    println!("rusticata_free_tls_parser_state()");
}

#[no_mangle]
pub extern fn rusticata_use_tls_parser_state<'a>(this: &TlsParserState<'a>, value: i32) -> bool
{
    println!("rusticata_use_tls_parser_state({:?})", value);
    this.send(value)
}

#[no_mangle]
pub extern "C" fn rusticata_parse_der(value: *const c_char, len: u32) -> i32 {
    SCLogDebug!("[rust] rusticata_parse_der");

    let data_len = len as usize;
    let data : &[u8] = unsafe { std::slice::from_raw_parts(value as *mut u8, data_len) };

    let d = parse_der(data);
    SCLogDebug!(format!("d: {:?}", d).as_str());

    0
}

#[no_mangle]
pub extern "C" fn rusticata_tls_decode<'a>(direction: u8, value: *const c_char, len: u32, this: &'a mut TlsParserState<'a>) -> &'a mut TlsParserState<'a> {
    SCLogDebug!("[rust] suri_tls_decode");

    let data_len = len as usize;
    let data : &[u8] = unsafe { std::slice::from_raw_parts(value as *mut u8, data_len) };

    SCLogDebug!(format!("  direction: {}\0", direction).as_str());
    SCLogDebug!(format!("  len: {}\0", data_len).as_str());
    SCLogDebug!(format!("  data: {:?}\0", data).as_str());

    let d = tls_parser_many(data);
    SCLogDebug!(format!("d: {:?}\0", d).as_str());

    // XXX match d with nom::IResult::Done, check if ServerHello, and print selected cipher
    match d {
        IResult::Done(rem,p) => {
            SCLogDebug!(format!("TLS parser successful {} element(s)\0", p.len()).as_str());
            for ref record in &p {
                SCLogDebug!(format!("{:?}\0", record).as_str());
                match record.msg {
                    TlsMessage::Handshake(ref m) => {
                        match *m {
                            TlsMessageHandshake::ClientHello(ref content) => {
                                let blah = parse_tls_extensions(content.ext);
                                SCLogDebug!(format!("ext {:?}\0", blah).as_str());
                            },
                            TlsMessageHandshake::ServerHello(ref content) => {
                                this.cipher = content.cipher;
                                let lu /* cipher */ : TlsCipherSuite = content.cipher.into();
                                SCLogDebug!(format!("Selected cipher: {:?}\0", lu).as_str());
                                let blah = parse_tls_extensions(content.ext);
                                SCLogDebug!(format!("ext {:?}\0", blah).as_str());
                            },
                            _ => (),
                        }
                    },
                    _ => (),
                }
            }
            if rem.len() > 0 { SCLogWarning!(format!("** unparsed ** {:?}\0",rem).as_str()); };
        },
        IResult::Error(e) => SCLogError!(format!("TLS parser reported an error: {:?}\0", e).as_str()),
        IResult::Incomplete(e) => SCLogError!(format!("TLS parser reported incomplete input: {:?}\0", e).as_str()),
    };

    this
}
<|endoftext|>


<commit_before><commit_msg>examples/ping: clarify listen_multiplex() as an example main loop<commit_after><|endoftext|>