<commit_before>use std::io::Read;
use std::net::SocketAddr;

use futures::done;
use futures::future::Future;
use futures::future::BoxFuture;
use futures::stream::Stream;
use futures::stream::BoxStream;

use tokio_io::io::read_exact;
use tokio_io::io::write_all;
use tokio_core::net::TcpStream;
use tokio_core::reactor;
use tokio_io::AsyncWrite;
use tokio_io::AsyncRead;

use solicit::HttpError;
use solicit::HttpResult;
use solicit::frame::FRAME_HEADER_LEN;
use solicit::frame::RawFrame;
use solicit::frame::RawFrameRef;
use solicit::frame::FrameIR;
use solicit::frame::unpack_header;
use solicit::frame::settings::SettingsFrame;
use solicit::frame::settings::HttpSetting;
use solicit::connection::HttpFrame;

pub type HttpFuture<T> = Box<Future<Item=T, Error=HttpError>>;
// Type is called `HttpFutureStream`, not just `HttpStream`
// to avoid confusion with streams from HTTP/2 spec
pub type HttpFutureStream<T> = Box<Stream<Item=T, Error=HttpError>>;

pub type HttpFutureSend<T> = BoxFuture<T, HttpError>;
pub type HttpFutureStreamSend<T> = BoxStream<T, HttpError>;

struct VecWithPos<T> {
    vec: Vec<T>,
    pos: usize,
}

impl<T> AsMut<[T]> for VecWithPos<T> {
    fn as_mut(&mut self) -> &mut [T] {
        &mut self.vec[self.pos..]
    }
}

pub fn recv_raw_frame<R : AsyncRead + Send + 'static>(read: R) -> HttpFuture<(R, RawFrame)> {
    let header = read_exact(read, [0; FRAME_HEADER_LEN]);
    let frame_buf = header.and_then(|(read, raw_header)| {
        let header = unpack_header(&raw_header);
        let total_len = FRAME_HEADER_LEN + header.length as usize;
        let mut full_frame = VecWithPos {
            vec: Vec::with_capacity(total_len),
            pos: 0,
        };

        full_frame.vec.extend(&raw_header);
        full_frame.vec.resize(total_len, 0);
        full_frame.pos = FRAME_HEADER_LEN;

        read_exact(read, full_frame)
    });
    let frame = frame_buf.map(|(read, frame_buf)| {
        (read, RawFrame::from(frame_buf.vec))
    });
    Box::new(frame
        .map_err(|e| e.into()))
}

pub fn recv_raw_frame_sync(read: &mut Read) -> HttpResult<RawFrame> {
    // TODO: copy-paste
    let mut raw_header = [0; FRAME_HEADER_LEN];
    read.read_exact(&mut raw_header)?;
    let header = unpack_header(&raw_header);

    let total_len = FRAME_HEADER_LEN + header.length as usize;
    let mut full_frame = Vec::new();
    full_frame.extend_from_slice(&raw_header);
    full_frame.resize(total_len, 0);

    read.read_exact(&mut full_frame[FRAME_HEADER_LEN..])?;

    Ok(RawFrame::from(full_frame))
}

pub fn recv_settings_frame<R : AsyncRead + Send + 'static>(read: R) -> HttpFuture<(R, SettingsFrame)> {
    Box::new(recv_raw_frame(read)
        .then(|result| {
            result.and_then(|(read, raw_frame)| {
                match HttpFrame::from_raw(&raw_frame) {
                    Ok(HttpFrame::Settings(f)) => Ok((read, f)),
                    Ok(f) => Err(HttpError::InvalidFrame(format!("unexpected frame, expected SETTINGS, got {:?}", f.frame_type()))),
                    Err(e) => Err(e),
                }
            })
        }))
}

pub fn recv_settings_frame_ack<R : AsyncRead + Send + 'static>(read: R) -> HttpFuture<(R, SettingsFrame)> {
    Box::new(recv_settings_frame(read).and_then(|(read, frame)| {
        if frame.is_ack() {
            Ok((read, frame))
        } else {
            Err(HttpError::InvalidFrame("expecting SETTINGS with ack, got without ack".to_owned()))
        }
    }))
}

pub fn recv_settings_frame_set<R : AsyncRead + Send + 'static>(read: R) -> HttpFuture<(R, SettingsFrame)> {
    Box::new(recv_settings_frame(read).and_then(|(read, frame)| {
        if !frame.is_ack() {
            Ok((read, frame))
        } else {
            Err(HttpError::InvalidFrame("expecting SETTINGS without ack, got with ack".to_owned()))
        }
    }))
}

#[allow(dead_code)]
pub fn send_raw_frame<W : AsyncWrite + Send + 'static>(write: W, frame: RawFrame) -> HttpFuture<W> {
    let bytes = frame.serialize();
    Box::new(write_all(write, bytes.clone())
        .map(|(w, _)| w)
        .map_err(|e| e.into()))
}

pub fn send_frame<W : AsyncWrite + Send + 'static, F : FrameIR>(write: W, frame: F) -> HttpFuture<W> {
    let buf = frame.serialize_into_vec();
    debug!("send frame {}", RawFrameRef { raw_content: &buf }.frame_type());
    Box::new(write_all(write, buf)
        .map(|(w, _)| w)
        .map_err(|e| e.into()))
}

static PREFACE: &'static [u8] = b"PRI * HTTP/2.0\r\n\r\nSM\r\n\r\n";

fn send_settings<W : AsyncWrite + Send + 'static>(conn: W) -> HttpFuture<W> {
    let settings = {
        let mut frame = SettingsFrame::new();
        frame.add_setting(HttpSetting::EnablePush(0));
        frame
    };

    Box::new(send_frame(conn, settings))
}

pub fn client_handshake<I : AsyncWrite + AsyncRead + Send + 'static>(conn: I) -> HttpFuture<I> {
    debug!("send PREFACE");
    let send_preface = write_all(conn, PREFACE)
        .map(|(conn, _)| conn)
        .map_err(|e| e.into());

    let send_settings = send_preface.and_then(send_settings);

    Box::new(send_settings)
}

pub fn server_handshake<I : AsyncRead + AsyncWrite + Send + 'static>(conn: I) -> HttpFuture<I> {
    let mut preface_buf = Vec::with_capacity(PREFACE.len());
    preface_buf.resize(PREFACE.len(), 0);
    let recv_preface = read_exact(conn, preface_buf)
        .map_err(|e| e.into())
        .and_then(|(conn, preface_buf)| {
            done(if preface_buf == PREFACE {
                Ok((conn))
            } else {
                Err(HttpError::InvalidFrame("wrong preface".to_owned()))
            })
        });

    let send_settings = recv_preface.and_then(send_settings);

    Box::new(send_settings)
}

pub fn connect_and_handshake(lh: &reactor::Handle, addr: &SocketAddr) -> HttpFuture<TcpStream> {
    let connect = TcpStream::connect(&addr, lh)
        .map_err(|e| e.into());

    let handshake = connect.and_then(client_handshake);

    Box::new(handshake)
}
<commit_msg>Reuse recv_raw_frame in recv_raw_frame_sync<commit_after>use std::io;
use std::io::Read;
use std::net::SocketAddr;

use futures::done;
use futures::future::Future;
use futures::future::BoxFuture;
use futures::stream::Stream;
use futures::stream::BoxStream;

use tokio_io::io::read_exact;
use tokio_io::io::write_all;
use tokio_core::net::TcpStream;
use tokio_core::reactor;
use tokio_io::AsyncWrite;
use tokio_io::AsyncRead;

use solicit::HttpError;
use solicit::HttpResult;
use solicit::frame::FRAME_HEADER_LEN;
use solicit::frame::RawFrame;
use solicit::frame::RawFrameRef;
use solicit::frame::FrameIR;
use solicit::frame::unpack_header;
use solicit::frame::settings::SettingsFrame;
use solicit::frame::settings::HttpSetting;
use solicit::connection::HttpFrame;

pub type HttpFuture<T> = Box<Future<Item=T, Error=HttpError>>;
// Type is called `HttpFutureStream`, not just `HttpStream`
// to avoid confusion with streams from HTTP/2 spec
pub type HttpFutureStream<T> = Box<Stream<Item=T, Error=HttpError>>;

pub type HttpFutureSend<T> = BoxFuture<T, HttpError>;
pub type HttpFutureStreamSend<T> = BoxStream<T, HttpError>;

struct VecWithPos<T> {
    vec: Vec<T>,
    pos: usize,
}

impl<T> AsMut<[T]> for VecWithPos<T> {
    fn as_mut(&mut self) -> &mut [T] {
        &mut self.vec[self.pos..]
    }
}

pub fn recv_raw_frame<'r, R : AsyncRead + 'r>(read: R)
    -> Box<Future<Item=(R, RawFrame), Error=HttpError> + 'r>
{
    let header = read_exact(read, [0; FRAME_HEADER_LEN]);
    let frame_buf = header.and_then(|(read, raw_header)| {
        let header = unpack_header(&raw_header);
        let total_len = FRAME_HEADER_LEN + header.length as usize;
        let mut full_frame = VecWithPos {
            vec: Vec::with_capacity(total_len),
            pos: 0,
        };

        full_frame.vec.extend(&raw_header);
        full_frame.vec.resize(total_len, 0);
        full_frame.pos = FRAME_HEADER_LEN;

        read_exact(read, full_frame)
    });
    let frame = frame_buf.map(|(read, frame_buf)| {
        (read, RawFrame::from(frame_buf.vec))
    });
    Box::new(frame
        .map_err(|e| e.into()))
}

struct SyncRead<'r, R : Read + ?Sized + 'r>(&'r mut R);

impl<'r, R : Read + ?Sized + 'r> Read for SyncRead<'r, R> {
    fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
        self.0.read(buf)
    }
}

impl<'r, R : Read + ?Sized + 'r> AsyncRead for SyncRead<'r, R> {
}

pub fn recv_raw_frame_sync(read: &mut Read) -> HttpResult<RawFrame> {
    Ok(recv_raw_frame(SyncRead(read)).wait()?.1)
}

pub fn recv_settings_frame<R : AsyncRead + Send + 'static>(read: R) -> HttpFuture<(R, SettingsFrame)> {
    Box::new(recv_raw_frame(read)
        .then(|result| {
            result.and_then(|(read, raw_frame)| {
                match HttpFrame::from_raw(&raw_frame) {
                    Ok(HttpFrame::Settings(f)) => Ok((read, f)),
                    Ok(f) => Err(HttpError::InvalidFrame(format!("unexpected frame, expected SETTINGS, got {:?}", f.frame_type()))),
                    Err(e) => Err(e),
                }
            })
        }))
}

pub fn recv_settings_frame_ack<R : AsyncRead + Send + 'static>(read: R) -> HttpFuture<(R, SettingsFrame)> {
    Box::new(recv_settings_frame(read).and_then(|(read, frame)| {
        if frame.is_ack() {
            Ok((read, frame))
        } else {
            Err(HttpError::InvalidFrame("expecting SETTINGS with ack, got without ack".to_owned()))
        }
    }))
}

pub fn recv_settings_frame_set<R : AsyncRead + Send + 'static>(read: R) -> HttpFuture<(R, SettingsFrame)> {
    Box::new(recv_settings_frame(read).and_then(|(read, frame)| {
        if !frame.is_ack() {
            Ok((read, frame))
        } else {
            Err(HttpError::InvalidFrame("expecting SETTINGS without ack, got with ack".to_owned()))
        }
    }))
}

#[allow(dead_code)]
pub fn send_raw_frame<W : AsyncWrite + Send + 'static>(write: W, frame: RawFrame) -> HttpFuture<W> {
    let bytes = frame.serialize();
    Box::new(write_all(write, bytes.clone())
        .map(|(w, _)| w)
        .map_err(|e| e.into()))
}

pub fn send_frame<W : AsyncWrite + Send + 'static, F : FrameIR>(write: W, frame: F) -> HttpFuture<W> {
    let buf = frame.serialize_into_vec();
    debug!("send frame {}", RawFrameRef { raw_content: &buf }.frame_type());
    Box::new(write_all(write, buf)
        .map(|(w, _)| w)
        .map_err(|e| e.into()))
}

static PREFACE: &'static [u8] = b"PRI * HTTP/2.0\r\n\r\nSM\r\n\r\n";

fn send_settings<W : AsyncWrite + Send + 'static>(conn: W) -> HttpFuture<W> {
    let settings = {
        let mut frame = SettingsFrame::new();
        frame.add_setting(HttpSetting::EnablePush(0));
        frame
    };

    Box::new(send_frame(conn, settings))
}

pub fn client_handshake<I : AsyncWrite + AsyncRead + Send + 'static>(conn: I) -> HttpFuture<I> {
    debug!("send PREFACE");
    let send_preface = write_all(conn, PREFACE)
        .map(|(conn, _)| conn)
        .map_err(|e| e.into());

    let send_settings = send_preface.and_then(send_settings);

    Box::new(send_settings)
}

pub fn server_handshake<I : AsyncRead + AsyncWrite + Send + 'static>(conn: I) -> HttpFuture<I> {
    let mut preface_buf = Vec::with_capacity(PREFACE.len());
    preface_buf.resize(PREFACE.len(), 0);
    let recv_preface = read_exact(conn, preface_buf)
        .map_err(|e| e.into())
        .and_then(|(conn, preface_buf)| {
            done(if preface_buf == PREFACE {
                Ok((conn))
            } else {
                Err(HttpError::InvalidFrame("wrong preface".to_owned()))
            })
        });

    let send_settings = recv_preface.and_then(send_settings);

    Box::new(send_settings)
}

pub fn connect_and_handshake(lh: &reactor::Handle, addr: &SocketAddr) -> HttpFuture<TcpStream> {
    let connect = TcpStream::connect(&addr, lh)
        .map_err(|e| e.into());

    let handshake = connect.and_then(client_handshake);

    Box::new(handshake)
}
<|endoftext|>


<commit_before>extern crate serialize;
extern crate time;
extern crate "rust-crypto" as rust_crypto;

use serialize::base64;
use serialize::base64::{ToBase64, URLSAFE_CHARS};
use serialize::hex::{FromHex, ToHex};
use serialize::json::ToJson;
use serialize::json;
use std::collections::TreeMap;
use rust_crypto::sha2::Sha256;
use rust_crypto::hmac::Hmac;

struct JwtHeader {
 alg: &'static str,
 typ: &'static str
}

struct JwtClaims {
  iss: &'static str,
  iat: int,
  exp: int,
  qsh: &'static str,
  sub: &'static str
}

impl ToJson for JwtHeader {
  fn to_json(&self) -> json::Json {
    let mut d = TreeMap::new();
    d.insert("alg".to_string(), self.alg.to_json());
    d.insert("typ".to_string(), self.typ.to_json());
    json::Object(d)
  }
}

impl ToJson for JwtClaims {
  fn to_json(&self) -> json::Json {
    let mut d = TreeMap::new();
    d.insert("iss", self.iss.to_json());
    d.insert("iat", self.iat.to_json());
    d.insert("exp", self.exp.to_json());
    d.insert("qsh", self.qsh.to_json());
    d.insert("sub", self.sub.to_json());
    json::Object(d)
  }
}

fn generate_jwt_token(request_url: &str, canonical_url: &str, key: &str, shared_secret: &str) -> &'static str {
  let iat = time::now().tm_nsec * 1000;
  let exp = iat + 180 * 1000;
  let qsh = get_query_string_hash(canonical_url);
  let claims = JwtClaims { iss: key, iat: iat, exp: exp, qsh: qsh };
  sign(claims, shared_secret)
}

fn sign(claims: JwtClaims, shared_secret: &str) -> &str {
  let signing_input = get_signing_input(claims, shared_secret);
  let signed256 = sign_hmac256(signing_input, shared_secret);
  signing_input.to_string() + "." + signed256.to_string()
}

fn get_signing_input(claims: JwtClaims, shared_secret: &str) -> &str {
  let header = JwtHeader { alg: "HS256", typ: "JWT" };

  let header_json_str = header.to_json();
  let claims_json_str = claims.to_json();

  let hb64_url_e_str = base64_url_encode(header_json_str.to_string().into_bytes()).to_string();
  let cb64_url_e_str = base64_url_encode(claims_json_str.to_string().into_bytes()).to_string();
  hb64_url_e_str + "." + cb64_url_e_str
}

fn sign_hmac256(signing_input: &str, shared_secret: &str) -> &'static str {
  let hmac = Hmac::new(Sha256::new(), shared_secret);
  hmac.input(signing_input);
  let result = hmac.result().code;
  base64_url_encode(result)
}

fn get_query_string_hash(canonical_url: &str) -> &str {
  let mut sh = Sha256::new();
  sh.input_str(canonical_url);
  sh.result_str()
}

fn base64_url_encode(bytes: [u8]) -> &'static str {
  bytes.to_base64(base64::URLSAFE_CHARS).as_slice()
}

// fn encode_hex_string(input: &str) -> &str {
//   input.to_string().into_bytes().to_hex() //as_slice()
// }
<commit_msg>compiles well<commit_after>extern crate serialize;
extern crate time;
extern crate "rust-crypto" as rust_crypto;

use serialize::base64;
use serialize::base64::{ToBase64};
use serialize::json::ToJson;
use serialize::json;
use std::collections::TreeMap;
use rust_crypto::sha2::Sha256;
use rust_crypto::hmac::Hmac;
use rust_crypto::digest::Digest;
use rust_crypto::mac::Mac;

struct JwtHeader<'a> {
 alg: &'a str,
 typ: &'a str
}

struct JwtClaims<'a> {
  iss: &'a str,
  iat: int,
  exp: int,
  qsh: &'a str,
  sub: &'a str,
}

impl<'a> JwtClaims<'a> {
  fn new(iss: &'a str, iat: int, exp: int, qsh: &'a str) -> JwtClaims<'a> {
    JwtClaims { iss: iss, iat: iat, exp: exp, qsh: qsh, sub: "" }
  }
}

impl<'a> ToJson for JwtHeader<'a> {
  fn to_json(&self) -> json::Json {
    let mut d = TreeMap::new();
    d.insert("alg".to_string(), self.alg.to_json());
    d.insert("typ".to_string(), self.typ.to_json());
    json::Object(d)
  }
}

impl<'a> ToJson for JwtClaims<'a> {
  fn to_json(&self) -> json::Json {
    let mut d = TreeMap::new();
    d.insert("iss".to_string(), self.iss.to_json());
    d.insert("iat".to_string(), self.iat.to_json());
    d.insert("exp".to_string(), self.exp.to_json());
    d.insert("qsh".to_string(), self.qsh.to_json());
    d.insert("sub".to_string(), self.sub.to_json());
    json::Object(d)
  }
}

fn generate_jwt_token(request_url: &str, canonical_url: &str, key: &str, shared_secret: &str) -> String {
  let iat = time::now().tm_nsec * 1000;
  let exp = iat + 180 * 1000;
  let qsh = get_query_string_hash(canonical_url);
  let claims = JwtClaims::new(key, iat as int, exp as int, qsh.as_slice());
  sign(claims, shared_secret)
}

fn sign(claims: JwtClaims, shared_secret: &str) -> String {
  let signing_input = get_signing_input(claims, shared_secret);
  let signed256 = sign_hmac256(signing_input.as_slice(), shared_secret);
  signing_input + "." + signed256
}

fn get_signing_input(claims: JwtClaims, shared_secret: &str) -> String {
  let header = JwtHeader { alg: "HS256", typ: "JWT" };

  let header_json_str = header.to_json();
  let claims_json_str = claims.to_json();

  let hb64_url_e_str = base64_url_encode(header_json_str.to_string().as_bytes()).to_string();
  let cb64_url_e_str = base64_url_encode(claims_json_str.to_string().as_bytes()).to_string();
  hb64_url_e_str + "." + cb64_url_e_str
}

fn sign_hmac256(signing_input: &str, shared_secret: &str) -> String {
  let mut hmac = Hmac::new(Sha256::new(), shared_secret.to_string().as_bytes());
  hmac.input(signing_input.to_string().as_bytes());
  let res = hmac.result();
  let cod = res.code();
  base64_url_encode(cod)
}

fn get_query_string_hash(canonical_url: &str) -> String {
  let mut sh = Sha256::new();
  sh.input_str(canonical_url);
  sh.result_str()
}

fn base64_url_encode(bytes: &[u8]) -> String {
  bytes.to_base64(base64::URL_SAFE)
}<|endoftext|>


<commit_before>use std::os::raw::c_void;

type Function = fn(data: *const c_void, n: i64, x: *const f64) -> f64;

#[repr(C)]
struct Closure {
    data: *const c_void,
    function: Function,
}

impl Closure {
    pub fn new<F>(function: &F) -> Closure where F: Fn(&[f64]) -> f64 {
        fn wrap<F>(closure: *const c_void, n: i64, x: *const f64) -> f64
                where F: Fn(&[f64]) -> f64 {
            use std::slice::from_raw_parts;
            let closure = closure as *const F;
            unsafe { (*closure)(from_raw_parts(x, n as usize)) }
        }
        Closure {data: &*function as *const _ as *const c_void, function: wrap::<F>}
    }
}

type FunctionMut = fn(data: *mut c_void, n: i64, x: *const f64) -> f64;

#[repr(C)]
struct ClosureMut {
    data: *mut c_void,
    function: FunctionMut,
}

impl ClosureMut {
    pub fn new<F>(function: &mut F) -> ClosureMut where F: FnMut(&[f64]) -> f64 {
        fn wrap<F>(closure: *mut c_void, n: i64, x: *const f64) -> f64
                where F: FnMut(&[f64]) -> f64 {
            use std::slice::from_raw_parts;
            let closure = closure as *mut F;
            unsafe { (*closure)(from_raw_parts(x, n as usize)) }
        }
        ClosureMut {data: &mut *function as *mut _ as *mut c_void, function: wrap::<F>}
    }
}

extern "C" {
    fn bobyqa_closure(function: *mut ClosureMut, n: i64, npt: i64, x: *mut f64,
        xl: *const f64, xu: *const f64, rhobeg: f64, rhoend: f64, maxfun: i64, w: *mut f64) -> f64;

    fn bobyqa_closure_const(function: *const Closure, n: i64, npt: i64, x: *mut f64,
        xl: *const f64, xu: *const f64, rhobeg: f64, rhoend: f64, maxfun: i64, w: *mut f64) -> f64;
}

pub struct Bobyqa <'a> {
    variables_count: usize,
    number_of_interpolation_conditions: usize,
    initial_trust_region_radius: f64,
    final_trust_region_radius: f64,
    lower_bound: Option<&'a [f64]>,
    upper_bound: Option<&'a [f64]>,
    max_function_calls_count: usize,
    working_space: Vec<f64>,
}

impl <'a> Bobyqa <'a> {
    pub fn new() -> Bobyqa <'a> {
        use std::iter::repeat;
        const VARIABLES_COUNT: usize = 2;
        const NUMBER_OF_INTERPOLATION_CONDITIONS: usize = VARIABLES_COUNT + 2;
        static LOWER_BOUND: [f64; VARIABLES_COUNT] = [0.0, 0.0];
        static UPPER_BOUND: [f64; VARIABLES_COUNT] = [1.0, 1.0];
        let working_space_size = Bobyqa::working_space_size(
            VARIABLES_COUNT,
            NUMBER_OF_INTERPOLATION_CONDITIONS);
        Bobyqa {
            variables_count: VARIABLES_COUNT,
            number_of_interpolation_conditions: NUMBER_OF_INTERPOLATION_CONDITIONS,
            lower_bound: Some(&LOWER_BOUND),
            upper_bound: Some(&UPPER_BOUND),
            initial_trust_region_radius: 1e-6,
            final_trust_region_radius: 1e6,
            max_function_calls_count: 1000,
            working_space: repeat(0.0).take(working_space_size).collect::<_>(),
        }
    }

    pub fn variables_count(&mut self, value: usize) -> &mut Self {
        assert!(value >= 2);
        self.variables_count = value;
        if self.lower_bound.is_some() && self.lower_bound.unwrap().len() < self.variables_count {
            self.lower_bound = None;
        }
        if self.upper_bound.is_some() && self.upper_bound.unwrap().len() < self.variables_count {
            self.upper_bound = None;
        }
        self
    }

    pub fn number_of_interpolation_conditions(&mut self, value: usize) -> &mut Self {
        assert!(value >= 4);
        self.number_of_interpolation_conditions = value;
        self
    }

    pub fn lower_bound(&mut self, value: &'a [f64]) -> &mut Self {
        assert!(value.len() >= self.variables_count);
        self.lower_bound = Some(value);
        self
    }

    pub fn upper_bound(&mut self, value: &'a [f64]) -> &mut Self {
        assert!(value.len() >= self.variables_count);
        self.upper_bound = Some(value);
        self
    }

    pub fn initial_trust_region_radius(&mut self, value: f64) -> &mut Self {
        assert!(value <= self.final_trust_region_radius);
        self.initial_trust_region_radius = value;
        self
    }

    pub fn final_trust_region_radius(&mut self, value: f64) -> &mut Self {
        assert!(value >= self.initial_trust_region_radius);
        self.final_trust_region_radius = value;
        self
    }

    pub fn max_function_calls_count(&mut self, value: usize) -> &mut Self {
        self.max_function_calls_count = value;
        self
    }

    /// ```
    /// use bobyqa::Bobyqa;
    /// let mut x = [0.5, 0.5];
    /// let f = |x: &[f64]| -> f64 { x[0] + x[1] };
    /// assert_eq!(Bobyqa::new().perform(&mut x, &f), 0.0);
    /// assert_eq!(x, [0.0, 0.0]);
    /// ```
    pub fn perform<F>(&mut self, values: &mut [f64], function: &F) -> f64
            where F: Fn(&[f64]) -> f64 {
        self.check(values);
        self.resize_working_space();
        let closure = Closure::new(function);
        unsafe {
            bobyqa_closure_const(
                &closure as *const _,
                self.variables_count as i64,
                self.number_of_interpolation_conditions as i64,
                values.as_mut_ptr(),
                self.lower_bound.unwrap().as_ptr(),
                self.upper_bound.unwrap().as_ptr(),
                self.initial_trust_region_radius,
                self.final_trust_region_radius,
                self.max_function_calls_count as i64,
                self.working_space.as_mut_ptr(),
            )
        }
    }

    /// ```
    /// use bobyqa::Bobyqa;
    /// let mut c = Box::new(0_u64);
    /// let mut x = [0.5, 0.5];
    /// {
    ///     let mut f = |x: &[f64]| -> f64 { *c += 1; x[0] + x[1] };
    ///     assert_eq!(Bobyqa::new().perform_mut(&mut x, &mut f), 0.0);
    /// }
    /// assert_eq!(x, [0.0, 0.0]);
    /// assert_eq!(*c, 28);
    /// ```
    pub fn perform_mut<F>(&mut self, values: &mut [f64], function: &mut F) -> f64
            where F: FnMut(&[f64]) -> f64 {
        self.check(values);
        self.resize_working_space();
        let mut closure = ClosureMut::new(function);
        unsafe {
            bobyqa_closure(
                &mut closure as *mut _,
                self.variables_count as i64,
                self.number_of_interpolation_conditions as i64,
                values.as_mut_ptr(),
                self.lower_bound.unwrap().as_ptr(),
                self.upper_bound.unwrap().as_ptr(),
                self.initial_trust_region_radius,
                self.final_trust_region_radius,
                self.max_function_calls_count as i64,
                self.working_space.as_mut_ptr(),
            )
        }
    }

    fn check(&self, values: &[f64]) {
        assert!(values.len() >= self.variables_count);
        assert!(self.number_of_interpolation_conditions >= self.variables_count + 2);
        assert!(self.number_of_interpolation_conditions <=
            (self.variables_count + 1)*(self.variables_count + 2)/2);
        assert!(self.lower_bound.is_some());
        assert!(self.upper_bound.is_some());
        assert!(self.lower_bound.unwrap().len() >= self.variables_count);
        assert!(self.upper_bound.unwrap().len() >= self.variables_count);
    }

    fn resize_working_space(&mut self) {
        use std::iter::repeat;
        let working_space_size = Bobyqa::working_space_size(
            self.number_of_interpolation_conditions,
            self.variables_count);
        if self.working_space.len() != working_space_size {
            self.working_space = repeat(0.0).take(working_space_size).collect::<_>();
        }
    }

    fn working_space_size(number_of_interpolation_conditions: usize, variables_count: usize) -> usize {
        3*variables_count*(variables_count + 3)/2
        + (number_of_interpolation_conditions + 13)
            *(number_of_interpolation_conditions + variables_count)
    }
}

#[test]
fn test_pefrorm_mut_with_all_settings_should_succeed() {
    let mut calls_count = Box::new(0);
    let mut values = [1.0, -1.0, 0.0];
    let lower_bound = [-3.0, -2.0, -1.0];
    let upper_bound = [1.0, 2.0, 3.0];
    let result = {
        let mut function = |x: &[f64]| -> f64 {
            assert_eq!(x.len(), 3);
            *calls_count += 1;
            x[0] + x[1] + x[2]
        };
        Bobyqa::new()
            .variables_count(values.len())
            .number_of_interpolation_conditions((values.len() + 1)*(values.len() + 2)/2)
            .initial_trust_region_radius(1e-3)
            .final_trust_region_radius(1e3)
            .lower_bound(&lower_bound)
            .upper_bound(&upper_bound)
            .max_function_calls_count(25)
            .perform_mut(&mut values, &mut function)
    };
    assert_eq!(values, lower_bound);
    assert_eq!(result, -6.0);
    assert_eq!(*calls_count, 25);
}
<commit_msg>Derive Bobyqa from Clone<commit_after>use std::os::raw::c_void;

type Function = fn(data: *const c_void, n: i64, x: *const f64) -> f64;

#[repr(C)]
struct Closure {
    data: *const c_void,
    function: Function,
}

impl Closure {
    pub fn new<F>(function: &F) -> Closure where F: Fn(&[f64]) -> f64 {
        fn wrap<F>(closure: *const c_void, n: i64, x: *const f64) -> f64
                where F: Fn(&[f64]) -> f64 {
            use std::slice::from_raw_parts;
            let closure = closure as *const F;
            unsafe { (*closure)(from_raw_parts(x, n as usize)) }
        }
        Closure {data: &*function as *const _ as *const c_void, function: wrap::<F>}
    }
}

type FunctionMut = fn(data: *mut c_void, n: i64, x: *const f64) -> f64;

#[repr(C)]
struct ClosureMut {
    data: *mut c_void,
    function: FunctionMut,
}

impl ClosureMut {
    pub fn new<F>(function: &mut F) -> ClosureMut where F: FnMut(&[f64]) -> f64 {
        fn wrap<F>(closure: *mut c_void, n: i64, x: *const f64) -> f64
                where F: FnMut(&[f64]) -> f64 {
            use std::slice::from_raw_parts;
            let closure = closure as *mut F;
            unsafe { (*closure)(from_raw_parts(x, n as usize)) }
        }
        ClosureMut {data: &mut *function as *mut _ as *mut c_void, function: wrap::<F>}
    }
}

extern "C" {
    fn bobyqa_closure(function: *mut ClosureMut, n: i64, npt: i64, x: *mut f64,
        xl: *const f64, xu: *const f64, rhobeg: f64, rhoend: f64, maxfun: i64, w: *mut f64) -> f64;

    fn bobyqa_closure_const(function: *const Closure, n: i64, npt: i64, x: *mut f64,
        xl: *const f64, xu: *const f64, rhobeg: f64, rhoend: f64, maxfun: i64, w: *mut f64) -> f64;
}

#[derive(Clone)]
pub struct Bobyqa <'a> {
    variables_count: usize,
    number_of_interpolation_conditions: usize,
    initial_trust_region_radius: f64,
    final_trust_region_radius: f64,
    lower_bound: Option<&'a [f64]>,
    upper_bound: Option<&'a [f64]>,
    max_function_calls_count: usize,
    working_space: Vec<f64>,
}

impl <'a> Bobyqa <'a> {
    pub fn new() -> Bobyqa <'a> {
        use std::iter::repeat;
        const VARIABLES_COUNT: usize = 2;
        const NUMBER_OF_INTERPOLATION_CONDITIONS: usize = VARIABLES_COUNT + 2;
        static LOWER_BOUND: [f64; VARIABLES_COUNT] = [0.0, 0.0];
        static UPPER_BOUND: [f64; VARIABLES_COUNT] = [1.0, 1.0];
        let working_space_size = Bobyqa::working_space_size(
            VARIABLES_COUNT,
            NUMBER_OF_INTERPOLATION_CONDITIONS);
        Bobyqa {
            variables_count: VARIABLES_COUNT,
            number_of_interpolation_conditions: NUMBER_OF_INTERPOLATION_CONDITIONS,
            lower_bound: Some(&LOWER_BOUND),
            upper_bound: Some(&UPPER_BOUND),
            initial_trust_region_radius: 1e-6,
            final_trust_region_radius: 1e6,
            max_function_calls_count: 1000,
            working_space: repeat(0.0).take(working_space_size).collect::<_>(),
        }
    }

    pub fn variables_count(&mut self, value: usize) -> &mut Self {
        assert!(value >= 2);
        self.variables_count = value;
        if self.lower_bound.is_some() && self.lower_bound.unwrap().len() < self.variables_count {
            self.lower_bound = None;
        }
        if self.upper_bound.is_some() && self.upper_bound.unwrap().len() < self.variables_count {
            self.upper_bound = None;
        }
        self
    }

    pub fn number_of_interpolation_conditions(&mut self, value: usize) -> &mut Self {
        assert!(value >= 4);
        self.number_of_interpolation_conditions = value;
        self
    }

    pub fn lower_bound(&mut self, value: &'a [f64]) -> &mut Self {
        assert!(value.len() >= self.variables_count);
        self.lower_bound = Some(value);
        self
    }

    pub fn upper_bound(&mut self, value: &'a [f64]) -> &mut Self {
        assert!(value.len() >= self.variables_count);
        self.upper_bound = Some(value);
        self
    }

    pub fn initial_trust_region_radius(&mut self, value: f64) -> &mut Self {
        assert!(value <= self.final_trust_region_radius);
        self.initial_trust_region_radius = value;
        self
    }

    pub fn final_trust_region_radius(&mut self, value: f64) -> &mut Self {
        assert!(value >= self.initial_trust_region_radius);
        self.final_trust_region_radius = value;
        self
    }

    pub fn max_function_calls_count(&mut self, value: usize) -> &mut Self {
        self.max_function_calls_count = value;
        self
    }

    /// ```
    /// use bobyqa::Bobyqa;
    /// let mut x = [0.5, 0.5];
    /// let f = |x: &[f64]| -> f64 { x[0] + x[1] };
    /// assert_eq!(Bobyqa::new().perform(&mut x, &f), 0.0);
    /// assert_eq!(x, [0.0, 0.0]);
    /// ```
    pub fn perform<F>(&mut self, values: &mut [f64], function: &F) -> f64
            where F: Fn(&[f64]) -> f64 {
        self.check(values);
        self.resize_working_space();
        let closure = Closure::new(function);
        unsafe {
            bobyqa_closure_const(
                &closure as *const _,
                self.variables_count as i64,
                self.number_of_interpolation_conditions as i64,
                values.as_mut_ptr(),
                self.lower_bound.unwrap().as_ptr(),
                self.upper_bound.unwrap().as_ptr(),
                self.initial_trust_region_radius,
                self.final_trust_region_radius,
                self.max_function_calls_count as i64,
                self.working_space.as_mut_ptr(),
            )
        }
    }

    /// ```
    /// use bobyqa::Bobyqa;
    /// let mut c = Box::new(0_u64);
    /// let mut x = [0.5, 0.5];
    /// {
    ///     let mut f = |x: &[f64]| -> f64 { *c += 1; x[0] + x[1] };
    ///     assert_eq!(Bobyqa::new().perform_mut(&mut x, &mut f), 0.0);
    /// }
    /// assert_eq!(x, [0.0, 0.0]);
    /// assert_eq!(*c, 28);
    /// ```
    pub fn perform_mut<F>(&mut self, values: &mut [f64], function: &mut F) -> f64
            where F: FnMut(&[f64]) -> f64 {
        self.check(values);
        self.resize_working_space();
        let mut closure = ClosureMut::new(function);
        unsafe {
            bobyqa_closure(
                &mut closure as *mut _,
                self.variables_count as i64,
                self.number_of_interpolation_conditions as i64,
                values.as_mut_ptr(),
                self.lower_bound.unwrap().as_ptr(),
                self.upper_bound.unwrap().as_ptr(),
                self.initial_trust_region_radius,
                self.final_trust_region_radius,
                self.max_function_calls_count as i64,
                self.working_space.as_mut_ptr(),
            )
        }
    }

    fn check(&self, values: &[f64]) {
        assert!(values.len() >= self.variables_count);
        assert!(self.number_of_interpolation_conditions >= self.variables_count + 2);
        assert!(self.number_of_interpolation_conditions <=
            (self.variables_count + 1)*(self.variables_count + 2)/2);
        assert!(self.lower_bound.is_some());
        assert!(self.upper_bound.is_some());
        assert!(self.lower_bound.unwrap().len() >= self.variables_count);
        assert!(self.upper_bound.unwrap().len() >= self.variables_count);
    }

    fn resize_working_space(&mut self) {
        use std::iter::repeat;
        let working_space_size = Bobyqa::working_space_size(
            self.number_of_interpolation_conditions,
            self.variables_count);
        if self.working_space.len() != working_space_size {
            self.working_space = repeat(0.0).take(working_space_size).collect::<_>();
        }
    }

    fn working_space_size(number_of_interpolation_conditions: usize, variables_count: usize) -> usize {
        3*variables_count*(variables_count + 3)/2
        + (number_of_interpolation_conditions + 13)
            *(number_of_interpolation_conditions + variables_count)
    }
}

#[test]
fn test_pefrorm_mut_with_all_settings_should_succeed() {
    let mut calls_count = Box::new(0);
    let mut values = [1.0, -1.0, 0.0];
    let lower_bound = [-3.0, -2.0, -1.0];
    let upper_bound = [1.0, 2.0, 3.0];
    let result = {
        let mut function = |x: &[f64]| -> f64 {
            assert_eq!(x.len(), 3);
            *calls_count += 1;
            x[0] + x[1] + x[2]
        };
        Bobyqa::new()
            .variables_count(values.len())
            .number_of_interpolation_conditions((values.len() + 1)*(values.len() + 2)/2)
            .initial_trust_region_radius(1e-3)
            .final_trust_region_radius(1e3)
            .lower_bound(&lower_bound)
            .upper_bound(&upper_bound)
            .max_function_calls_count(25)
            .perform_mut(&mut values, &mut function)
    };
    assert_eq!(values, lower_bound);
    assert_eq!(result, -6.0);
    assert_eq!(*calls_count, 25);
}
<|endoftext|>


<commit_before>const DELTA: u32 = 0x9E3779B9;

fn to_bytes(v: &Vec<u32>, include_length: bool) -> Vec<u8> {
    let length: u32 = v.len() as u32;
    let mut n: u32 = length << 2;
    if include_length {
        let m = v[length as usize - 1];
        n = n - 4;
        assert!(((m < n-3) || (m > n)));
        n = m;
    }
    let mut bytes: Vec<u8> = vec![0; n as usize];
    for i in 0..n {
        bytes[i as usize] = (v[(i >> 2) as usize] >> ((i & 3) << 3)) as u8;
    }
    return bytes;
}

fn to_u32(bytes: &Vec<u8>, include_length: bool) -> Vec<u32> {
    let length: u32 = bytes.len() as u32;
    let mut n: u32 = length >> 2;
    if length&3 != 0 {
        n = n + 1;
    }
    let mut v;
    if include_length {
        v = vec![0; n as usize + 1];
        v[n as usize] = length;
    } else {
        v = vec![0; n as usize];
    }
    for i in 0..length {
        v[(i>>2) as usize] = (bytes[i as usize] as u32)<< ((i & 3) << 3) as u32;
    }
    return v
}
<commit_msg>update<commit_after>const DELTA: u32 = 0x9E3779B9;

fn to_bytes(v: &Vec<u32>, include_length: bool) -> Vec<u8> {
    let length: u32 = v.len() as u32;
    let mut n: u32 = length << 2;
    if include_length {
        let m = v[length as usize - 1];
        n = n - 4;
        assert!(((m < n-3) || (m > n)));
        n = m;
    }
    let mut bytes: Vec<u8> = vec![0; n as usize];
    for i in 0..n {
        bytes[i as usize] = (v[(i >> 2) as usize] >> ((i & 3) << 3)) as u8;
    }
    return bytes;
}

fn to_u32(bytes: &Vec<u8>, include_length: bool) -> Vec<u32> {
    let length: u32 = bytes.len() as u32;
    let mut n: u32 = length >> 2;
    if length&3 != 0 {
        n = n + 1;
    }
    let mut v;
    if include_length {
        v = vec![0; n as usize + 1];
        v[n as usize] = length;
    } else {
        v = vec![0; n as usize];
    }
    for i in 0..length {
        v[(i>>2) as usize] = (bytes[i as usize] as u32)<< ((i & 3) << 3) as u32;
    }
    return v
}

fn mx(sum: u32, y: u32, z: u32, p: u32, e: u32, k: &Vec<u32>) -> u32 {
    ((z>>5 ^ y<<2) + (y>>3 ^ z<<4)) ^ ((sum ^ y) + (k[(p&3^e) as usize] ^ z))
}

fn fixk(k: &Vec<u32>) -> Vec<u32> {
    let mut key = k.clone();
    if key.len() < 4 {
        let length = key.len();
        for i in length..4 {
            key.push(0)
        }
    }
    key
}
<|endoftext|>


<commit_before>#![allow(non_camel_case_types)]

extern crate libc;
use libc::{c_int, c_uint, c_char, c_uchar, c_void, c_double, int32_t, uint32_t, int16_t, uint16_t, int8_t};

pub const FREENECT_COUNTS_PER_G: 		c_int = 829;
pub const FREENECT_DEPTH_MM_MAX_VALUE: 	c_int = 10000;
pub const FREENECT_DEPTH_MM_NO_VALUE: 	c_int = 0;
pub const FREENECT_DEPTH_RAW_MAX_VALUE: c_int = 2048;
pub const FREENECT_DEPTH_RAW_NO_VALUE: 	c_int = 2047;

#[repr(C)] pub enum freenect_device_flags {
	FREENECT_DEVICE_MOTOR  = 0x01,
	FREENECT_DEVICE_CAMERA = 0x02,
	FREENECT_DEVICE_AUDIO  = 0x04,
}

#[repr(C)] pub struct freenect_device_attributes {
	pub next: *mut freenect_device_attributes,
	pub camera_serial: *const c_char,
}

#[repr(C)] pub enum freenect_resolution {
	FREENECT_RESOLUTION_LOW    = 0, // QVGA - 320x240
	FREENECT_RESOLUTION_MEDIUM = 1, // VGA  - 640x480
	FREENECT_RESOLUTION_HIGH   = 2, // SXGA - 1280x1024
	FREENECT_RESOLUTION_DUMMY  = 2147483647, // Dummy value to force enum to be 32 bits wide
}

#[repr(C)] pub enum freenect_video_format {
	FREENECT_VIDEO_RGB             = 0, // Decompressed RGB mode (demosaicing done by libfreenect)
	FREENECT_VIDEO_BAYER           = 1, // Bayer compressed mode (raw information from camera)
	FREENECT_VIDEO_IR_8BIT         = 2, // 8-bit IR mode
	FREENECT_VIDEO_IR_10BIT        = 3, // 10-bit IR mode
	FREENECT_VIDEO_IR_10BIT_PACKED = 4, // 10-bit packed IR mode
	FREENECT_VIDEO_YUV_RGB         = 5, // YUV RGB mode
	FREENECT_VIDEO_YUV_RAW         = 6, // YUV Raw mode
	FREENECT_VIDEO_DUMMY           = 2147483647, // Dummy value to force enum to be 32 bits wide
}

#[repr(C)] pub enum freenect_depth_format {
	FREENECT_DEPTH_11BIT        = 0, // 11 bit depth information in one uint16_t/pixel
	FREENECT_DEPTH_10BIT        = 1, // 10 bit depth information in one uint16_t/pixel
	FREENECT_DEPTH_11BIT_PACKED = 2, // 11 bit packed depth information
	FREENECT_DEPTH_10BIT_PACKED = 3, // 10 bit packed depth information
	FREENECT_DEPTH_REGISTERED   = 4, // processed depth data in mm, aligned to 640x480 RGB
	FREENECT_DEPTH_MM           = 5, // depth to each pixel in mm, but left unaligned to RGB image
	FREENECT_DEPTH_DUMMY        = 2147483647, // Dummy value to force enum to be 32 bits wide
}

#[repr(C)] pub enum freenect_flag {
	// values written to the CMOS register
	FREENECT_AUTO_EXPOSURE      = 1 << 14,
	FREENECT_AUTO_WHITE_BALANCE = 1 << 1,
	FREENECT_RAW_COLOR          = 1 << 4,
	// registers to be written with 0 or 1
	FREENECT_MIRROR_DEPTH       = 0x0017,
	FREENECT_MIRROR_VIDEO       = 0x0047,
}

#[repr(C)] pub enum freenect_flag_value {
	FREENECT_OFF = 0,
	FREENECT_ON  = 1,
}

#[repr(C)] pub struct freenect_frame_mode {
	pub reserved: uint32_t,              // unique ID used internally.  The meaning of values may change without notice.  Don't touch or depend on the contents of this field.  We mean it.
	pub resolution: freenect_resolution, // Resolution this freenect_frame_mode describes, should you want to find it again with freenect_find_*_frame_mode().
	pub dummy: int32_t,                  // The video or depth format that this freenect_frame_mode describes.  The caller should know which of video_format or depth_format to use, since they called freenect_get_*_frame_mode()
	pub bytes: int32_t,                  // Total buffer size in bytes to hold a single frame of data.  Should be equivalent to width * height * (data_bits_per_pixel+padding_bits_per_pixel) / 8
	pub width: int16_t,                  // Width of the frame, in pixels
	pub height: int16_t,                 // Height of the frame, in pixels
	pub data_bits_per_pixel: int8_t,     // Number of bits of information needed for each pixel
	pub padding_bits_per_pixel: int8_t,  // Number of bits of padding for alignment used for each pixel
	pub framerate: int8_t,               // Approximate expected frame rate, in Hz
	pub is_valid: int8_t,                // If 0, this freenect_frame_mode is invalid and does not describe a supported mode.  Otherwise, the frame_mode is valid.
}

#[repr(C)] pub enum freenect_led_option {
	LED_OFF              = 0, // Turn LED off
	LED_GREEN            = 1, // Turn LED to Green
	LED_RED              = 2, // Turn LED to Red
	LED_YELLOW           = 3, // Turn LED to Yellow
	LED_BLINK_GREEN      = 4, // Make LED blink Green
	// 5 is same as 4, LED blink Green
	LED_BLINK_RED_YELLOW = 6, // Make LED blink Red/Yellow
}

#[repr(C)] pub enum freenect_tilt_status_code {
	TILT_STATUS_STOPPED = 0x00, // Tilt motor is stopped
	TILT_STATUS_LIMIT   = 0x01, // Tilt motor has reached movement limit
	TILT_STATUS_MOVING  = 0x04, // Tilt motor is currently moving to new position
}

#[repr(C)] pub struct freenect_raw_tilt_state {
	pub accelerometer_x: int16_t                  , // Raw accelerometer data for X-axis, see FREENECT_COUNTS_PER_G for conversion
	pub accelerometer_y: int16_t                  , // Raw accelerometer data for Y-axis, see FREENECT_COUNTS_PER_G for conversion
	pub accelerometer_z: int16_t                  , // Raw accelerometer data for Z-axis, see FREENECT_COUNTS_PER_G for conversion
	pub tilt_angle:      int8_t                   , // Raw tilt motor angle encoder information
	pub tilt_status: 	 freenect_tilt_status_code, // State of the tilt motor (stopped, moving, etc...)
}

pub enum freenect_context {}

pub enum freenect_device {}

pub enum freenect_usb_context {}

#[repr(C)] pub enum freenect_loglevel {
	FREENECT_LOG_FATAL = 0,     // Log for crashing/non-recoverable errors
	FREENECT_LOG_ERROR,         // Log for major errors
	FREENECT_LOG_WARNING,       // Log for warning messages
	FREENECT_LOG_NOTICE,        // Log for important messages
	FREENECT_LOG_INFO,          // Log for normal messages
	FREENECT_LOG_DEBUG,         // Log for useful development messages
	FREENECT_LOG_SPEW,          // Log for slightly less useful messages
	FREENECT_LOG_FLOOD,         // Log EVERYTHING. May slow performance.
}

pub type freenect_log_cb   = extern fn(dev: *mut freenect_context, level: freenect_loglevel, msg: *const c_char);
pub type freenect_depth_cb = extern fn(dev: *mut freenect_device, depth: *mut c_void, timestamp: uint32_t);
pub type freenect_video_cb = extern fn(dev: *mut freenect_device, video: *mut c_void, timestamp: uint32_t);

#[link(name = "freenect")]
extern "C" {
    pub fn freenect_init(ctx: *mut *mut freenect_context, usb_ctx: *mut freenect_usb_context) -> c_int;
	pub fn freenect_shutdown(ctx: *mut freenect_context) -> c_int;
	pub fn freenect_set_log_level(ctx: *mut freenect_context, level: freenect_loglevel);
	pub fn freenect_set_log_callback(ctx: *mut freenect_context, cb: freenect_log_cb);
	pub fn freenect_process_events(ctx: *mut freenect_context) -> c_int;
	pub fn freenect_process_events_timeout(ctx: *mut freenect_context, timeout: libc::timeval) -> c_int;
	pub fn freenect_num_devices(ctx: *mut freenect_context) -> c_int;
	pub fn freenect_list_device_attributes(ctx: *mut freenect_context, attribute_list: *mut *mut freenect_device_attributes) -> c_int;
	pub fn freenect_free_device_attributes(attribute_list: *mut freenect_device_attributes);
	pub fn freenect_supported_subdevices() -> c_int;
	pub fn freenect_select_subdevices(ctx: *mut freenect_context, subdevs: u32); // Not enum type as bitfield can have multiple choices
	pub fn freenect_enabled_subdevices(ctx: *mut freenect_context) -> freenect_device_flags;
	pub fn freenect_open_device(ctx: *mut freenect_context, dev: *mut *mut freenect_device, index: c_int) -> c_int;
	pub fn freenect_open_device_by_camera_serial(ctx: *mut freenect_context, dev: *mut *mut freenect_device, camera_serial: *const c_char) -> c_int;
	pub fn freenect_close_device(dev: *mut freenect_device) -> c_int;
	pub fn freenect_set_user(dev: *mut freenect_device, user: *mut c_void);
	pub fn freenect_get_user(dev: *mut freenect_device) -> *mut c_void;
	pub fn freenect_set_depth_callback(dev: *mut freenect_device, cb: freenect_depth_cb);
	pub fn freenect_set_video_callback(dev: *mut freenect_device, cb: freenect_video_cb);
	pub fn freenect_set_depth_buffer(dev: *mut freenect_device, buf: *mut c_void) -> c_int;
	pub fn freenect_set_video_buffer(dev: *mut freenect_device, buf: *mut c_void) -> c_int;
	pub fn freenect_start_depth(dev: *mut freenect_device) -> c_int;
	pub fn freenect_start_video(dev: *mut freenect_device) -> c_int;
	pub fn freenect_stop_depth(dev: *mut freenect_device) -> c_int;
	pub fn freenect_stop_video(dev: *mut freenect_device) -> c_int;
	pub fn freenect_update_tilt_state(dev: *mut freenect_device) -> c_int;
	pub fn freenect_get_tilt_state(dev: *mut freenect_device) -> *mut freenect_raw_tilt_state;
	pub fn freenect_get_tilt_degs(state: *mut freenect_raw_tilt_state) -> c_double;
	pub fn freenect_set_tilt_degs(dev: *mut freenect_device, angle: c_double) -> c_int;
	pub fn freenect_get_tilt_status(state: *mut freenect_raw_tilt_state) -> freenect_tilt_status_code;
	pub fn freenect_set_led(dev: *mut freenect_device, option: freenect_led_option) -> c_int;
	pub fn freenect_get_mks_accel(state: *mut freenect_raw_tilt_state, x: *mut c_double, y: *mut c_double, z: *mut c_double);
	pub fn freenect_get_video_mode_count() -> c_int;
	pub fn freenect_get_video_mode(mode_num: c_int) -> freenect_frame_mode;
	pub fn freenect_get_current_video_mode(dev: *mut freenect_device) -> freenect_frame_mode;
	pub fn freenect_find_video_mode(res: freenect_resolution, fmt: freenect_video_format) -> freenect_frame_mode;
	pub fn freenect_set_video_mode(dev: *mut freenect_device, mode: freenect_frame_mode) -> c_int;
	pub fn freenect_get_depth_mode_count() -> c_int;
	pub fn freenect_get_depth_mode(mode_num: c_int) -> freenect_frame_mode;
	pub fn freenect_get_current_depth_mode(dev: *mut freenect_device) -> freenect_frame_mode;
	pub fn freenect_find_depth_mode(res: freenect_resolution, fmt: freenect_depth_format) -> freenect_frame_mode;
	pub fn freenect_set_depth_mode(dev: *mut freenect_device, mode: freenect_frame_mode) -> c_int;
	pub fn freenect_set_flag(dev: *mut freenect_device, flag: freenect_flag, value: freenect_flag_value) -> c_int;
}
<commit_msg>Apply cosmetic tweaks<commit_after>#![allow(non_camel_case_types)]

extern crate libc;
use libc::{
	c_void,
	c_char,
	c_uchar,
	c_int,
	c_uint,
	int8_t,
	int16_t,
	uint16_t,
	int32_t,
	uint32_t,
	c_double,
};

pub const FREENECT_COUNTS_PER_G: 		c_int = 829;
pub const FREENECT_DEPTH_MM_MAX_VALUE: 	c_int = 10000;
pub const FREENECT_DEPTH_MM_NO_VALUE: 	c_int = 0;
pub const FREENECT_DEPTH_RAW_MAX_VALUE: c_int = 2048;
pub const FREENECT_DEPTH_RAW_NO_VALUE: 	c_int = 2047;

#[repr(C)] pub enum freenect_device_flags {
	FREENECT_DEVICE_MOTOR  = 0x01,
	FREENECT_DEVICE_CAMERA = 0x02,
	FREENECT_DEVICE_AUDIO  = 0x04,
}

#[repr(C)] pub struct freenect_device_attributes {
	pub next: *mut freenect_device_attributes,
	pub camera_serial: *const c_char,
}

#[repr(C)] pub enum freenect_resolution {
	FREENECT_RESOLUTION_LOW    = 0, // QVGA - 320x240
	FREENECT_RESOLUTION_MEDIUM = 1, // VGA  - 640x480
	FREENECT_RESOLUTION_HIGH   = 2, // SXGA - 1280x1024
	FREENECT_RESOLUTION_DUMMY  = 2147483647, // Dummy value to force enum to be 32 bits wide
}

#[repr(C)] pub enum freenect_video_format {
	FREENECT_VIDEO_RGB             = 0, // Decompressed RGB mode (demosaicing done by libfreenect)
	FREENECT_VIDEO_BAYER           = 1, // Bayer compressed mode (raw information from camera)
	FREENECT_VIDEO_IR_8BIT         = 2, // 8-bit IR mode
	FREENECT_VIDEO_IR_10BIT        = 3, // 10-bit IR mode
	FREENECT_VIDEO_IR_10BIT_PACKED = 4, // 10-bit packed IR mode
	FREENECT_VIDEO_YUV_RGB         = 5, // YUV RGB mode
	FREENECT_VIDEO_YUV_RAW         = 6, // YUV Raw mode
	FREENECT_VIDEO_DUMMY           = 2147483647, // Dummy value to force enum to be 32 bits wide
}

#[repr(C)] pub enum freenect_depth_format {
	FREENECT_DEPTH_11BIT        = 0, // 11 bit depth information in one uint16_t/pixel
	FREENECT_DEPTH_10BIT        = 1, // 10 bit depth information in one uint16_t/pixel
	FREENECT_DEPTH_11BIT_PACKED = 2, // 11 bit packed depth information
	FREENECT_DEPTH_10BIT_PACKED = 3, // 10 bit packed depth information
	FREENECT_DEPTH_REGISTERED   = 4, // processed depth data in mm, aligned to 640x480 RGB
	FREENECT_DEPTH_MM           = 5, // depth to each pixel in mm, but left unaligned to RGB image
	FREENECT_DEPTH_DUMMY        = 2147483647, // Dummy value to force enum to be 32 bits wide
}

#[repr(C)] pub enum freenect_flag {
	FREENECT_AUTO_EXPOSURE      = 1 << 14,
	FREENECT_AUTO_WHITE_BALANCE = 1 << 1,
	FREENECT_RAW_COLOR          = 1 << 4,
	FREENECT_MIRROR_DEPTH       = 0x0017,
	FREENECT_MIRROR_VIDEO       = 0x0047,
}

#[repr(C)] pub enum freenect_flag_value {
	FREENECT_OFF = 0,
	FREENECT_ON  = 1,
}

#[repr(C)] pub struct freenect_frame_mode {
	pub reserved: uint32_t,              // unique ID used internally.  The meaning of values may change without notice.  Don't touch or depend on the contents of this field.  We mean it.
	pub resolution: freenect_resolution, // Resolution this freenect_frame_mode describes, should you want to find it again with freenect_find_*_frame_mode().
	pub dummy: int32_t,                  // The video or depth format that this freenect_frame_mode describes.  The caller should know which of video_format or depth_format to use, since they called freenect_get_*_frame_mode()
	pub bytes: int32_t,                  // Total buffer size in bytes to hold a single frame of data.  Should be equivalent to width * height * (data_bits_per_pixel+padding_bits_per_pixel) / 8
	pub width: int16_t,                  // Width of the frame, in pixels
	pub height: int16_t,                 // Height of the frame, in pixels
	pub data_bits_per_pixel: int8_t,     // Number of bits of information needed for each pixel
	pub padding_bits_per_pixel: int8_t,  // Number of bits of padding for alignment used for each pixel
	pub framerate: int8_t,               // Approximate expected frame rate, in Hz
	pub is_valid: int8_t,                // If 0, this freenect_frame_mode is invalid and does not describe a supported mode.  Otherwise, the frame_mode is valid.
}

#[repr(C)] pub enum freenect_led_option {
	LED_OFF              = 0, // Turn LED off
	LED_GREEN            = 1, // Turn LED to Green
	LED_RED              = 2, // Turn LED to Red
	LED_YELLOW           = 3, // Turn LED to Yellow
	LED_BLINK_GREEN      = 4, // Make LED blink Green
	// 5 is same as 4, LED blink Green
	LED_BLINK_RED_YELLOW = 6, // Make LED blink Red/Yellow
}

#[repr(C)] pub enum freenect_tilt_status_code {
	TILT_STATUS_STOPPED = 0x00, // Tilt motor is stopped
	TILT_STATUS_LIMIT   = 0x01, // Tilt motor has reached movement limit
	TILT_STATUS_MOVING  = 0x04, // Tilt motor is currently moving to new position
}

#[repr(C)] pub struct freenect_raw_tilt_state {
	pub accelerometer_x: int16_t                  , // Raw accelerometer data for X-axis, see FREENECT_COUNTS_PER_G for conversion
	pub accelerometer_y: int16_t                  , // Raw accelerometer data for Y-axis, see FREENECT_COUNTS_PER_G for conversion
	pub accelerometer_z: int16_t                  , // Raw accelerometer data for Z-axis, see FREENECT_COUNTS_PER_G for conversion
	pub tilt_angle:      int8_t                   , // Raw tilt motor angle encoder information
	pub tilt_status: 	 freenect_tilt_status_code, // State of the tilt motor (stopped, moving, etc...)
}

pub enum freenect_context {}

pub enum freenect_device {}

pub enum freenect_usb_context {}

#[repr(C)] pub enum freenect_loglevel {
	FREENECT_LOG_FATAL = 0,     // Log for crashing/non-recoverable errors
	FREENECT_LOG_ERROR,         // Log for major errors
	FREENECT_LOG_WARNING,       // Log for warning messages
	FREENECT_LOG_NOTICE,        // Log for important messages
	FREENECT_LOG_INFO,          // Log for normal messages
	FREENECT_LOG_DEBUG,         // Log for useful development messages
	FREENECT_LOG_SPEW,          // Log for slightly less useful messages
	FREENECT_LOG_FLOOD,         // Log EVERYTHING. May slow performance.
}

pub type freenect_log_cb   = extern fn(dev: *mut freenect_context, level: freenect_loglevel, msg: *const c_char);
pub type freenect_depth_cb = extern fn(dev: *mut freenect_device, depth: *mut c_void, timestamp: uint32_t);
pub type freenect_video_cb = extern fn(dev: *mut freenect_device, video: *mut c_void, timestamp: uint32_t);

#[link(name = "freenect")]
extern "C" {
    pub fn freenect_init(ctx: *mut *mut freenect_context, usb_ctx: *mut freenect_usb_context) -> c_int;
	pub fn freenect_shutdown(ctx: *mut freenect_context) -> c_int;
	pub fn freenect_set_log_level(ctx: *mut freenect_context, level: freenect_loglevel);
	pub fn freenect_set_log_callback(ctx: *mut freenect_context, cb: freenect_log_cb);
	pub fn freenect_process_events(ctx: *mut freenect_context) -> c_int;
	pub fn freenect_process_events_timeout(ctx: *mut freenect_context, timeout: libc::timeval) -> c_int;
	pub fn freenect_num_devices(ctx: *mut freenect_context) -> c_int;
	pub fn freenect_list_device_attributes(ctx: *mut freenect_context, attribute_list: *mut *mut freenect_device_attributes) -> c_int;
	pub fn freenect_free_device_attributes(attribute_list: *mut freenect_device_attributes);
	pub fn freenect_supported_subdevices() -> c_int;
	pub fn freenect_select_subdevices(ctx: *mut freenect_context, subdevs: u32); // Not enum type as bitfield can have multiple choices
	pub fn freenect_enabled_subdevices(ctx: *mut freenect_context) -> freenect_device_flags;
	pub fn freenect_open_device(ctx: *mut freenect_context, dev: *mut *mut freenect_device, index: c_int) -> c_int;
	pub fn freenect_open_device_by_camera_serial(ctx: *mut freenect_context, dev: *mut *mut freenect_device, camera_serial: *const c_char) -> c_int;
	pub fn freenect_close_device(dev: *mut freenect_device) -> c_int;
	pub fn freenect_set_user(dev: *mut freenect_device, user: *mut c_void);
	pub fn freenect_get_user(dev: *mut freenect_device) -> *mut c_void;
	pub fn freenect_set_depth_callback(dev: *mut freenect_device, cb: freenect_depth_cb);
	pub fn freenect_set_video_callback(dev: *mut freenect_device, cb: freenect_video_cb);
	pub fn freenect_set_depth_buffer(dev: *mut freenect_device, buf: *mut c_void) -> c_int;
	pub fn freenect_set_video_buffer(dev: *mut freenect_device, buf: *mut c_void) -> c_int;
	pub fn freenect_start_depth(dev: *mut freenect_device) -> c_int;
	pub fn freenect_start_video(dev: *mut freenect_device) -> c_int;
	pub fn freenect_stop_depth(dev: *mut freenect_device) -> c_int;
	pub fn freenect_stop_video(dev: *mut freenect_device) -> c_int;
	pub fn freenect_update_tilt_state(dev: *mut freenect_device) -> c_int;
	pub fn freenect_get_tilt_state(dev: *mut freenect_device) -> *mut freenect_raw_tilt_state;
	pub fn freenect_get_tilt_degs(state: *mut freenect_raw_tilt_state) -> c_double;
	pub fn freenect_set_tilt_degs(dev: *mut freenect_device, angle: c_double) -> c_int;
	pub fn freenect_get_tilt_status(state: *mut freenect_raw_tilt_state) -> freenect_tilt_status_code;
	pub fn freenect_set_led(dev: *mut freenect_device, option: freenect_led_option) -> c_int;
	pub fn freenect_get_mks_accel(state: *mut freenect_raw_tilt_state, x: *mut c_double, y: *mut c_double, z: *mut c_double);
	pub fn freenect_get_video_mode_count() -> c_int;
	pub fn freenect_get_video_mode(mode_num: c_int) -> freenect_frame_mode;
	pub fn freenect_get_current_video_mode(dev: *mut freenect_device) -> freenect_frame_mode;
	pub fn freenect_find_video_mode(res: freenect_resolution, fmt: freenect_video_format) -> freenect_frame_mode;
	pub fn freenect_set_video_mode(dev: *mut freenect_device, mode: freenect_frame_mode) -> c_int;
	pub fn freenect_get_depth_mode_count() -> c_int;
	pub fn freenect_get_depth_mode(mode_num: c_int) -> freenect_frame_mode;
	pub fn freenect_get_current_depth_mode(dev: *mut freenect_device) -> freenect_frame_mode;
	pub fn freenect_find_depth_mode(res: freenect_resolution, fmt: freenect_depth_format) -> freenect_frame_mode;
	pub fn freenect_set_depth_mode(dev: *mut freenect_device, mode: freenect_frame_mode) -> c_int;
	pub fn freenect_set_flag(dev: *mut freenect_device, flag: freenect_flag, value: freenect_flag_value) -> c_int;
}
<|endoftext|>


<commit_before>#![feature(rustc_private)]
#![feature(plugin_registrar, quote)]
extern crate rustc;
extern crate syntax;

use rustc::plugin::Registry;
use syntax::ast::{self, TokenTree};
use syntax::codemap::DUMMY_SP;
use syntax::codemap::Span;
use syntax::ext::base::{ExtCtxt, MacItems, MacResult};
use syntax::ext::build::AstBuilder;
use syntax::parse::token;
use syntax::parse::tts_to_parser;

use generator::Generate;

mod block;
mod parser;
mod generator;

#[plugin_registrar]
pub fn plugin_registrar(reg: &mut Registry) {
    reg.register_macro("speculate", expand_speculate);
}

fn expand_speculate(cx: &mut ExtCtxt, _sp: Span, tokens: &[TokenTree]) -> Box<MacResult + 'static> {
    let mut parser = tts_to_parser(cx.parse_sess(), tokens.to_vec(), cx.cfg());
    let block = parser::parse(&mut parser);
    let item = block.generate(cx, None);

    let attrs = vec![
        cx.attribute(
            DUMMY_SP,
            cx.meta_list(
                DUMMY_SP,
                token::InternedString::new("allow"),
                vec![
                    cx.meta_word(
                        DUMMY_SP,
                        token::InternedString::new("non_snake_case"))
                ]
            )
        )
    ];

    let pub_use_super_star = cx.item_use_glob(DUMMY_SP,
                                              ast::Visibility::Public,
                                              vec![cx.ident_of("super")]);

    let module = cx.item_mod(DUMMY_SP, DUMMY_SP, cx.ident_of("sup"),
                             attrs, vec![pub_use_super_star, item]);

    MacItems::new(Some(module).into_iter())
}
<commit_msg>Fix for `rustc 1.0.0-dev (1cc8b6ec6 2015-03-02) (built 2015-03-02)`.<commit_after>#![feature(rustc_private)]
#![feature(plugin_registrar, quote)]
extern crate rustc;
extern crate syntax;

use rustc::plugin::Registry;
use syntax::ast::{self, TokenTree};
use syntax::codemap::DUMMY_SP;
use syntax::codemap::Span;
use syntax::ext::base::{ExtCtxt, MacEager, MacResult};
use syntax::ext::build::AstBuilder;
use syntax::parse::token;
use syntax::parse::tts_to_parser;
use syntax::util::small_vector::SmallVector;

use generator::Generate;

mod block;
mod parser;
mod generator;

#[plugin_registrar]
pub fn plugin_registrar(reg: &mut Registry) {
    reg.register_macro("speculate", expand_speculate);
}

fn expand_speculate(cx: &mut ExtCtxt, _sp: Span, tokens: &[TokenTree]) -> Box<MacResult + 'static> {
    let mut parser = tts_to_parser(cx.parse_sess(), tokens.to_vec(), cx.cfg());
    let block = parser::parse(&mut parser);
    let item = block.generate(cx, None);

    let attrs = vec![
        cx.attribute(
            DUMMY_SP,
            cx.meta_list(
                DUMMY_SP,
                token::InternedString::new("allow"),
                vec![
                    cx.meta_word(
                        DUMMY_SP,
                        token::InternedString::new("non_snake_case"))
                ]
            )
        )
    ];

    let pub_use_super_star = cx.item_use_glob(DUMMY_SP,
                                              ast::Visibility::Public,
                                              vec![cx.ident_of("super")]);

    let module = cx.item_mod(DUMMY_SP, DUMMY_SP, cx.ident_of("sup"),
                             attrs, vec![pub_use_super_star, item]);

    MacEager::items(SmallVector::one(module))
}
<|endoftext|>


<commit_before>#![feature(plugin_registrar, rustc_private, convert, slice_patterns)]

extern crate rustc;
extern crate syntax;

use std::rc::Rc;

use syntax::codemap::Span;
use syntax::parse::{PResult, token};
use syntax::ast::{Delimited, TokenTree, TtDelimited, TtToken};
use syntax::ext::base::{ExtCtxt, MacResult, DummyResult, MacEager};
use syntax::ext::quote::rt::ToTokens;
use syntax::util::small_vector::SmallVector;
use rustc::plugin::Registry;

fn tt_vec(tts: &[TokenTree]) -> Vec<TokenTree> {
    tts.iter().map(|tt| tt.clone()).collect()
}

fn ident_of_ctx_and_span(cx: &mut ExtCtxt, span: Span, ident: &str) -> TokenTree {
    TtToken(span, token::Ident(cx.ident_of(ident), token::Plain))
}

fn build_string_from_idents(target: &mut String, tts: &[TokenTree]) -> Result<(), Span> {
    for t in tts {
        match t {
            &TtToken(_, token::Ident(ref i, _)) => {
                target.extend(i.as_str().chars());
            },
            &TtToken(_, token::Comma) => (),
            &TtDelimited(delim_span, ref delim) => {
                if delim.delim != token::DelimToken::Bracket {
                    return Err(delim_span);
                }
                try!(build_string_from_idents(target, &delim.tts[..]));
            }
            ref tt => return Err(tt.get_span()),
        }
    }
    Ok(())
}

fn fnconcat(cx: &mut ExtCtxt, sp: Span, args: &[TokenTree])
            -> Box<MacResult + 'static> {
    if args.is_empty() {
        cx.span_err(sp, "fnconcat! can't be called with nothing");
        return DummyResult::any(sp);
    }
    let mut fn_tokens = tt_vec(args);
    fn_tokens[0] = if let &TtDelimited(delim_span, ref delim) = &fn_tokens[0] {
        if delim.delim != token::DelimToken::Bracket {
            cx.span_err(delim_span, "use square brackets (i.e. [..]) in place of the function name");
            return DummyResult::any(delim_span);
        }
        let mut concatenated = String::new();
        match build_string_from_idents(&mut concatenated, &delim.tts) {
            Ok(()) => (),
            Err(err_span) => {
                cx.span_err(err_span, "non-ident, non-comma token");
                return DummyResult::any(err_span);
            },
        }
        if concatenated.is_empty() {
            cx.span_err(delim_span, "empty identifier");
            return DummyResult::any(delim_span);
        }
        ident_of_ctx_and_span(cx, delim_span, concatenated.as_str())
    } else {
        cx.span_err(sp, "use square brackets (i.e. [..]) in place of the function name");
        return DummyResult::any(sp);
    };
    fn_tokens.insert(0, ident_of_ctx_and_span(cx, sp, "fn"));
    let mut p = cx.new_parser_from_tts(&fn_tokens[..]);
    if let Some(i) = p.parse_item() {
        return MacEager::items(SmallVector::one(i));
    }
    cx.span_err(sp, "couldn't parse a fn");
    return DummyResult::any(sp);
}

fn pull_tts_from_paren_groups(tts: &[TokenTree]) -> PResult<Vec<(Span, Vec<TokenTree>)>> {
    let mut ret = Vec::new();
    for t in tts {
        match t {
            &TtDelimited(delim_span, ref delim) if delim.delim == token::DelimToken::Paren => {
                ret.push((delim_span, tt_vec(&delim.tts[..])));
            },
            _ => {

            },
        }
    }
    Ok(ret)
}

fn parse_pats_and_types(cx: &mut ExtCtxt, span: Span, tts: Vec<TokenTree>) -> PResult<Vec<Vec<TokenTree>>> {
    let mut ret = Vec::new();
    let mut parser = cx.new_parser_from_tts(&tts[..]);
    loop {
        let pat = try!(parser.parse_pat_nopanic());
        try!(parser.expect(&token::Colon));
        let ty = try!(parser.parse_ty_nopanic());
        let mut pat = pat.to_tokens(cx);
        pat.push(TtToken(span, token::Colon));
        pat.extend(ty.to_tokens(cx).into_iter());
        ret.push(pat);
        if !try!(parser.eat(&token::Comma)) {
            break;
        }
    }
    Ok(ret)
}

fn parse_exprs(cx: &mut ExtCtxt, tts: Vec<TokenTree>) -> PResult<Vec<Vec<TokenTree>>> {
    let mut ret = Vec::new();
    let mut parser = cx.new_parser_from_tts(&tts[..]);
    loop {
        ret.push(try!(parser.parse_expr_nopanic()).to_tokens(cx));
        if !try!(parser.eat(&token::Comma)) {
            break;
        }
    }
    Ok(ret)
}

fn let_of_pat_and_expr(cx: &mut ExtCtxt, span: Span, pat: Vec<TokenTree>, expr: Vec<TokenTree>) -> Vec<TokenTree> {
    let mut ret = vec![ident_of_ctx_and_span(cx, span, "let")];
    ret.extend(pat.into_iter());
    ret.push(TtToken(span, token::Eq));
    ret.extend(expr.into_iter());
    ret.push(TtToken(span, token::Semi));
    ret
}

fn test_fn_of_ident_and_block(cx: &mut ExtCtxt, span: Span, ident: String, block: Vec<TokenTree>) -> Vec<TokenTree> {
    vec![
        TtToken(span, token::Pound),
        TtDelimited(span, Rc::new(Delimited {
            delim: token::Bracket,
            open_span: span,
            tts: vec![ident_of_ctx_and_span(cx, span, "test")],
            close_span: span,
        })),
        ident_of_ctx_and_span(cx, span, "fn"),
        ident_of_ctx_and_span(cx, span, ident.as_str()),
        TtDelimited(span, Rc::new(Delimited {
            delim: token::Paren,
            open_span: span,
            tts: Vec::new(),
            close_span: span,
        })),
        TtDelimited(span, Rc::new(Delimited {
            delim: token::Brace,
            open_span: span,
            tts: block,
            close_span: span,
        })),
    ]
}

fn do_parametrization(cx: &mut ExtCtxt, span: Span, base_name: String, params: &Delimited, block: Vec<TokenTree>)
                      -> PResult<Box<MacResult + 'static>> {
    let mut tokens = Vec::new();
    let mut groups = try!(pull_tts_from_paren_groups(&params.tts[..]));
    let param_types = try!(parse_pats_and_types(cx, span, groups.remove(0).1));
    let param_exprs_vec: Vec<(Span, Vec<Vec<TokenTree>>)> =
        try!(groups.into_iter().map(|(span, tts)| parse_exprs(cx, tts).map(|parsed| (span, parsed))).collect());
    let codemap = cx.codemap();
    for (e, (exprs_span, exprs)) in param_exprs_vec.into_iter().enumerate() {
        let mut fn_block = Vec::new();
        for (pat, expr) in param_types.iter().cloned().zip(exprs.into_iter()) {
            fn_block.extend(let_of_pat_and_expr(cx, span, pat, expr).into_iter());
        }
        let mut fn_name = format!("{}_{}", base_name, e);
        match codemap.span_to_lines(exprs_span).map(|lines| lines.lines.iter().map(|li| li.line_index).min()) {
            Ok(Some(line)) => fn_name.extend(format!("_line_{}", line).chars()),
            _ => (),
        }
        fn_block.extend(block.iter().cloned());
        tokens.extend(test_fn_of_ident_and_block(cx, span, fn_name, fn_block).into_iter());
    }
    let mut parser = cx.new_parser_from_tts(&tokens[..]);
    let mut items = Vec::new();
    loop {
        match parser.parse_item() {
            Some(i) => items.push(i),
            None => break,
        }
    }
    Ok(MacEager::items(SmallVector::many(items)))
}

fn parametrize_test(cx: &mut ExtCtxt, sp: Span, args: &[TokenTree])
                    -> Box<MacResult + 'static> {
    match args {
        [ref name,
         TtToken(_, token::Comma),
         TtDelimited(params_span, ref params),
         TtToken(_, token::Comma),
         TtDelimited(block_span, ref block)] => {
            if params.delim != token::DelimToken::Bracket {
                cx.span_err(params_span, "need square brackets around parameters");
                return DummyResult::any(params_span);
            }
            if block.delim != token::DelimToken::Brace {
                cx.span_err(block_span, "need curly braces around block");
                return DummyResult::any(block_span);
            }
            if params.tts.len() < 2 {
                cx.span_err(params_span, "need at least param types and one param");
                return DummyResult::any(params_span);
            }
            let mut concatenated = String::new();
            match build_string_from_idents(&mut concatenated, &[name.clone()]) {
                Ok(()) => (),
                Err(err_span) => {
                    cx.span_err(err_span, "non-ident, non-comma token");
                    return DummyResult::any(err_span);
                },
            }
            if concatenated.is_empty() {
                let name_span = name.get_span();
                cx.span_err(name_span, "empty identifier");
                return DummyResult::any(name_span);
            }
            match do_parametrization(cx, sp, concatenated, params, block.tts.clone()) {
                Ok(r) => return r,
                Err(_) => {
                    cx.span_err(sp, "error while parsing");
                    return DummyResult::any(sp);
                }
            }
        },
        _ => {
            cx.span_err(sp, "badly-structured parametrize_test!");
            return DummyResult::any(sp);
        }
    }
}

#[plugin_registrar]
pub fn plugin_registrar(reg: &mut Registry) {
    reg.register_macro("fnconcat", fnconcat);
    reg.register_macro("parametrize_test", parametrize_test);
}
<commit_msg>Simplify/abstract error handling.<commit_after>#![feature(plugin_registrar, rustc_private, convert, slice_patterns)]

extern crate rustc;
extern crate syntax;

use std::rc::Rc;

use syntax::codemap::Span;
use syntax::diagnostic::FatalError;
use syntax::parse::token;
use syntax::ast::{Delimited, TokenTree, TtDelimited, TtToken};
use syntax::ext::base::{ExtCtxt, MacResult, DummyResult, MacEager};
use syntax::ext::quote::rt::ToTokens;
use syntax::util::small_vector::SmallVector;
use rustc::plugin::Registry;

macro_rules! fail {
    ($expr:expr) => (
        return Err(::std::convert::From::from($expr));
    )
}

#[derive(PartialEq, Eq, Clone, Debug)]
enum Error {
    OverSpan(Span, String),
    FatalParseError,
}

impl Error {
    fn as_mac_result(self, cx: &mut ExtCtxt, whole_span: Span) -> Box<MacResult + 'static> {
        let (span, message) = match self {
            Error::OverSpan(span, message) => (span, message),
            Error::FatalParseError => (whole_span, "fatal parse error".to_string()),
        };
        cx.span_err(span, message.as_str());
        DummyResult::any(span)
    }
}

impl From<(Span, &'static str)> for Error {
    fn from((err_span, err_string): (Span, &'static str)) -> Error {
        Error::OverSpan(err_span, err_string.to_string())
    }
}

impl From<FatalError> for Error {
    fn from(_: FatalError) -> Error {
        Error::FatalParseError
    }
}

type LocalResult<T> = Result<T, Error>;

fn tt_vec(tts: &[TokenTree]) -> Vec<TokenTree> {
    tts.iter().map(|tt| tt.clone()).collect()
}

fn ident_of_ctx_and_span(cx: &mut ExtCtxt, span: Span, ident: &str) -> TokenTree {
    TtToken(span, token::Ident(cx.ident_of(ident), token::Plain))
}

fn build_string_from_idents(target: &mut String, tts: &[TokenTree]) -> LocalResult<()> {
    for t in tts {
        match t {
            &TtToken(_, token::Ident(ref i, _)) => {
                target.extend(i.as_str().chars());
            },
            &TtToken(_, token::Comma) => (),
            &TtDelimited(delim_span, ref delim) => {
                if delim.delim != token::DelimToken::Bracket {
                    fail!((delim_span, "non-bracket delimiter"));
                }
                try!(build_string_from_idents(target, &delim.tts[..]));
            }
            ref tt => fail!((tt.get_span(), "non-ident, non-comma token")),
        }
    }
    Ok(())
}

fn fnconcat_impl(cx: &mut ExtCtxt, sp: Span, args: &[TokenTree]) -> LocalResult<Box<MacResult + 'static>> {
    if args.is_empty() {
        fail!((sp, "fnconcat! can't be called with nothing"));
    }
    let mut fn_tokens = tt_vec(args);
    fn_tokens[0] = if let &TtDelimited(delim_span, ref delim) = &fn_tokens[0] {
        if delim.delim != token::DelimToken::Bracket {
            fail!((delim_span, "use square brackets (i.e. [..]) in place of the function name"));
        }
        let mut concatenated = String::new();
        try!(build_string_from_idents(&mut concatenated, &delim.tts));
        if concatenated.is_empty() {
            fail!((delim_span, "empty identifier"));
        }
        ident_of_ctx_and_span(cx, delim_span, concatenated.as_str())
    } else {
        fail!((fn_tokens[0].get_span(), "use square brackets (i.e. [..]) in place of the function name"));
    };
    fn_tokens.insert(0, ident_of_ctx_and_span(cx, sp, "fn"));
    let mut p = cx.new_parser_from_tts(&fn_tokens[..]);
    if let Some(i) = p.parse_item() {
        return Ok(MacEager::items(SmallVector::one(i)));
    }
    fail!((sp, "couldn't parse a fn"));
}

fn fnconcat(cx: &mut ExtCtxt, sp: Span, args: &[TokenTree]) -> Box<MacResult + 'static> {
    match fnconcat_impl(cx, sp, args) {
        Ok(r) => r,
        Err(e) => e.as_mac_result(cx, sp),
    }
}

fn pull_tts_from_paren_groups(tts: &[TokenTree]) -> LocalResult<Vec<(Span, Vec<TokenTree>)>> {
    let mut ret = Vec::new();
    for t in tts {
        match t {
            &TtDelimited(delim_span, ref delim) if delim.delim == token::DelimToken::Paren => {
                ret.push((delim_span, tt_vec(&delim.tts[..])));
            },
            &TtToken(_, token::Comma) => (),
            ref tt => fail!((tt.get_span(), "parenthesized group expected")),
        }
    }
    Ok(ret)
}

fn parse_pats_and_types(cx: &mut ExtCtxt, span: Span, tts: Vec<TokenTree>) -> LocalResult<Vec<Vec<TokenTree>>> {
    let mut ret = Vec::new();
    let mut parser = cx.new_parser_from_tts(&tts[..]);
    loop {
        let pat = try!(parser.parse_pat_nopanic());
        try!(parser.expect(&token::Colon));
        let ty = try!(parser.parse_ty_nopanic());
        let mut pat = pat.to_tokens(cx);
        pat.push(TtToken(span, token::Colon));
        pat.extend(ty.to_tokens(cx).into_iter());
        ret.push(pat);
        if !try!(parser.eat(&token::Comma)) {
            break;
        }
    }
    Ok(ret)
}

fn parse_exprs(cx: &mut ExtCtxt, tts: Vec<TokenTree>) -> LocalResult<Vec<Vec<TokenTree>>> {
    let mut ret = Vec::new();
    let mut parser = cx.new_parser_from_tts(&tts[..]);
    loop {
        ret.push(try!(parser.parse_expr_nopanic()).to_tokens(cx));
        if !try!(parser.eat(&token::Comma)) {
            break;
        }
    }
    Ok(ret)
}

fn let_of_pat_and_expr(cx: &mut ExtCtxt, span: Span, pat: Vec<TokenTree>, expr: Vec<TokenTree>) -> Vec<TokenTree> {
    let mut ret = vec![ident_of_ctx_and_span(cx, span, "let")];
    ret.extend(pat.into_iter());
    ret.push(TtToken(span, token::Eq));
    ret.extend(expr.into_iter());
    ret.push(TtToken(span, token::Semi));
    ret
}

fn test_fn_of_ident_and_block(cx: &mut ExtCtxt, span: Span, ident: String, block: Vec<TokenTree>) -> Vec<TokenTree> {
    vec![
        TtToken(span, token::Pound),
        TtDelimited(span, Rc::new(Delimited {
            delim: token::Bracket,
            open_span: span,
            tts: vec![ident_of_ctx_and_span(cx, span, "test")],
            close_span: span,
        })),
        ident_of_ctx_and_span(cx, span, "fn"),
        ident_of_ctx_and_span(cx, span, ident.as_str()),
        TtDelimited(span, Rc::new(Delimited {
            delim: token::Paren,
            open_span: span,
            tts: Vec::new(),
            close_span: span,
        })),
        TtDelimited(span, Rc::new(Delimited {
            delim: token::Brace,
            open_span: span,
            tts: block,
            close_span: span,
        })),
    ]
}

fn do_parametrization(cx: &mut ExtCtxt, span: Span, base_name: String, params: &Delimited, block: Vec<TokenTree>)
                      -> LocalResult<Box<MacResult + 'static>> {
    let mut tokens = Vec::new();
    let mut groups = try!(pull_tts_from_paren_groups(&params.tts[..]));
    let param_types = try!(parse_pats_and_types(cx, span, groups.remove(0).1));
    let param_exprs_vec: Vec<(Span, Vec<Vec<TokenTree>>)> =
        try!(groups.into_iter().map(|(span, tts)| parse_exprs(cx, tts).map(|parsed| (span, parsed))).collect());
    let codemap = cx.codemap();
    for (e, (exprs_span, exprs)) in param_exprs_vec.into_iter().enumerate() {
        let mut fn_block = Vec::new();
        for (pat, expr) in param_types.iter().cloned().zip(exprs.into_iter()) {
            fn_block.extend(let_of_pat_and_expr(cx, span, pat, expr).into_iter());
        }
        let mut fn_name = format!("{}_{}", base_name, e);
        match codemap.span_to_lines(exprs_span).map(|lines| lines.lines.iter().map(|li| li.line_index).min()) {
            Ok(Some(line)) => fn_name.extend(format!("_line_{}", line).chars()),
            _ => (),
        }
        fn_block.extend(block.iter().cloned());
        tokens.extend(test_fn_of_ident_and_block(cx, span, fn_name, fn_block).into_iter());
    }
    let mut parser = cx.new_parser_from_tts(&tokens[..]);
    let mut items = Vec::new();
    loop {
        match parser.parse_item() {
            Some(i) => items.push(i),
            None => break,
        }
    }
    Ok(MacEager::items(SmallVector::many(items)))
}

fn parametrize_test_impl(cx: &mut ExtCtxt, sp: Span, args: &[TokenTree]) -> LocalResult<Box<MacResult + 'static>> {
    match args {
        [ref name,
         TtToken(_, token::Comma),
         TtDelimited(params_span, ref params),
         TtToken(_, token::Comma),
         TtDelimited(block_span, ref block)] => {
            if params.delim != token::DelimToken::Bracket {
                fail!((params_span, "need square brackets around parameters"));
            }
            if block.delim != token::DelimToken::Brace {
                fail!((block_span, "need curly braces around block"));
            }
            if params.tts.len() < 2 {
                fail!((params_span, "need at least param types and one param"));
            }
            let mut concatenated = String::new();
            try!(build_string_from_idents(&mut concatenated, &[name.clone()]));
            if concatenated.is_empty() {
                fail!((name.get_span(), "empty identifier"));
            }
            do_parametrization(cx, sp, concatenated, params, block.tts.clone())
        },
        _ => fail!((sp, "badly-structured parametrize_test!")),
    }
}

fn parametrize_test(cx: &mut ExtCtxt, sp: Span, args: &[TokenTree]) -> Box<MacResult + 'static> {
    match parametrize_test_impl(cx, sp, args) {
        Ok(r) => r,
        Err(e) => e.as_mac_result(cx, sp),
    }
}

#[plugin_registrar]
pub fn plugin_registrar(reg: &mut Registry) {
    reg.register_macro("fnconcat", fnconcat);
    reg.register_macro("parametrize_test", parametrize_test);
}
<|endoftext|>