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

use hyper::Client;
use hyper::header::Connection;
use rustc_serialize::json::Json;
use url::percent_encoding;

use ::json;
use ::json::JsonPathElement::{Key, Only};

pub struct Wiki {
    hostname: String,
}

#[derive(Clone)]
pub struct Revision {
    pub revid: u64,
    pub parentid: u64,
    pub comment: String,
}

impl Wiki {
    /// Constructs a Wiki object representing the wiki at `hostname` (e.g. "en.wikipedia.org").
    pub fn new(hostname: &str) -> Wiki {
        Wiki { hostname: hostname.to_string() }
    }

    /// Calls the MediaWiki API with the given parameters and format=json. Returns the raw JSON.
    fn call_mediawiki_api(&self, parameters: Vec<(&str, &str)>) -> Result<String, String> {
        let post_body =
            parameters.into_iter().map(|p| format!("{}={}", p.0, p.1))
            .collect::<Vec<_>>().join("&") + "&format=json";

        let client = Client::new();
        let mut response = client.post(&format!("https://{}/w/api.php", self.hostname))
            .body(&post_body)
            .header(Connection::close())
            .send().unwrap();

        let mut body = String::new();
        response.read_to_string(&mut body).unwrap();
        Ok(body)
    }

    /// Returns the last `limit` revisions for the page `title`.
    pub fn get_revisions(&self, title: &str, limit: u64) -> Result<Vec<Revision>, String> {
        let json_str = self.call_mediawiki_api(
            vec![("action", "query"), ("prop", "revisions"), ("titles", title),
                 ("rvprop", "comment|ids"), ("rvlimit", &limit.to_string())]).unwrap();
        let json = Json::from_str(&json_str).unwrap();
        let revisions_json = try!(
            json::get_json_array(&json, &[Key("query"), Key("pages"), Only, Key("revisions")]));

        let mut revisions = Vec::with_capacity(revisions_json.len());
        for revision_json in revisions_json {
            revisions.push(
                Revision {
                    revid: try!(json::get_json_number(revision_json, &[Key("revid")])),
                    parentid: try!(json::get_json_number(revision_json, &[Key("parentid")])),
                    comment: try!(json::get_json_string(revision_json, &[Key("comment")])).to_string()
                });
        }
        Ok(revisions)
    }

    /// Returns the latest revision ID for the page `title`.
    pub fn get_latest_revision(&self, title: &str) -> Result<Revision, String> {
        // TODO: Can this be a one-liner? Does try!() work properly like that?
        let revisions = try!(self.get_revisions(title, 1));
        Ok(revisions[0].clone())
    }

    /// Returns the contents of the page `title` as of (i.e., immediately after) revision `id`.
    pub fn get_revision_content(&self, title: &str, id: u64) -> Result<String, String> {
        let json_str = self.call_mediawiki_api(
            vec![("action", "query"), ("prop", "revisions"), ("titles", title), ("rvprop", "content"),
                 ("rvlimit", "1"), ("rvstartid", &id.to_string())]).unwrap();
        let json = Json::from_str(&json_str).unwrap();
        match json::get_json_string(
            &json, &[Key("query"), Key("pages"), Only, Key("revisions"), Only, Key("*")]) {
            Ok(content) => Ok(content.to_string()),
            Err(msg) => Err(msg),
        }
    }

    /// Follows all redirects to find the canonical name of the page at `title`.
    pub fn get_canonical_title(&self, title: &str) -> Result<String, String> {
        let latest_revision_id = self.get_latest_revision(title).unwrap().revid;
        let page_contents = self.get_revision_content(title, latest_revision_id).unwrap();

        let regex = regex!(r"#REDIRECT \[\[([^]]+)\]\].*");
        match regex.captures(&page_contents) {
            Some(captures) => self.get_canonical_title(captures.at(1).unwrap()),
            None => {
                println!("Canonical page title is \"{}\"", title);
                Ok(title.to_string())
            },
        }
    }

    /// Parses the wikitext in `wikitext` as though it were the contents of the page `title`,
    /// returning the rendered HTML.
    pub fn parse_wikitext(&self, title: &str, wikitext: &str) -> Result<String, String> {
        let encoded_wikitext =
            percent_encoding::percent_encode(wikitext.as_bytes(), percent_encoding::QUERY_ENCODE_SET);
        let html = self.call_mediawiki_api(
            vec![("action", "parse"), ("prop", "text"), ("disablepp", ""), ("contentmodel", "wikitext"),
                 ("title", title), ("text", &encoded_wikitext)]).unwrap();
        // TODO: check return value
        let json = Json::from_str(&html).unwrap();
        match json::get_json_string(&json, &[Key("parse"), Key("text"), Key("*")]) {
            Ok(contents) => Ok(contents.to_string()),
            Err(message) => Err(message),
        }
    }

    /// Gets the current, fully-rendered (**HTML**) contents of the page `title`.
    pub fn get_current_page_content(title: &str) -> String {
        // TODO: should this struct be keeping a Client instead of creating new ones for each method
        // call, here and in call_mediawiki_api?
        let client = Client::new();
        let mut res = client.get(
            &format!("https://en.wikipedia.org/wiki/{}", title))
            .header(Connection::close())
            .send().unwrap();

        let mut body = String::new();
        res.read_to_string(&mut body).unwrap();

        body
    }
}
<commit_msg>Handle errors and ownership properly in Wiki::get_latest_revision.<commit_after>use std::io::Read;

use hyper::Client;
use hyper::header::Connection;
use rustc_serialize::json::Json;
use url::percent_encoding;

use ::json;
use ::json::JsonPathElement::{Key, Only};

pub struct Wiki {
    hostname: String,
}

#[derive(Clone)]
pub struct Revision {
    pub revid: u64,
    pub parentid: u64,
    pub comment: String,
}

impl Wiki {
    /// Constructs a Wiki object representing the wiki at `hostname` (e.g. "en.wikipedia.org").
    pub fn new(hostname: &str) -> Wiki {
        Wiki { hostname: hostname.to_string() }
    }

    /// Calls the MediaWiki API with the given parameters and format=json. Returns the raw JSON.
    fn call_mediawiki_api(&self, parameters: Vec<(&str, &str)>) -> Result<String, String> {
        let post_body =
            parameters.into_iter().map(|p| format!("{}={}", p.0, p.1))
            .collect::<Vec<_>>().join("&") + "&format=json";

        let client = Client::new();
        let mut response = client.post(&format!("https://{}/w/api.php", self.hostname))
            .body(&post_body)
            .header(Connection::close())
            .send().unwrap();

        let mut body = String::new();
        response.read_to_string(&mut body).unwrap();
        Ok(body)
    }

    /// Returns the last `limit` revisions for the page `title`.
    pub fn get_revisions(&self, title: &str, limit: u64) -> Result<Vec<Revision>, String> {
        let json_str = self.call_mediawiki_api(
            vec![("action", "query"), ("prop", "revisions"), ("titles", title),
                 ("rvprop", "comment|ids"), ("rvlimit", &limit.to_string())]).unwrap();
        let json = Json::from_str(&json_str).unwrap();
        let revisions_json = try!(
            json::get_json_array(&json, &[Key("query"), Key("pages"), Only, Key("revisions")]));

        let mut revisions = Vec::with_capacity(revisions_json.len());
        for revision_json in revisions_json {
            revisions.push(
                Revision {
                    revid: try!(json::get_json_number(revision_json, &[Key("revid")])),
                    parentid: try!(json::get_json_number(revision_json, &[Key("parentid")])),
                    comment: try!(json::get_json_string(revision_json, &[Key("comment")])).to_string()
                });
        }
        Ok(revisions)
    }

    /// Returns the latest revision ID for the page `title`.
    pub fn get_latest_revision(&self, title: &str) -> Result<Revision, String> {
        let mut revisions = try!(self.get_revisions(title, 1));
        if !revisions.is_empty() {
            Ok(revisions.pop().unwrap())
        } else {
            Err(format!("No revisions found for page \"{}\"", title))
        }
    }

    /// Returns the contents of the page `title` as of (i.e., immediately after) revision `id`.
    pub fn get_revision_content(&self, title: &str, id: u64) -> Result<String, String> {
        let json_str = self.call_mediawiki_api(
            vec![("action", "query"), ("prop", "revisions"), ("titles", title), ("rvprop", "content"),
                 ("rvlimit", "1"), ("rvstartid", &id.to_string())]).unwrap();
        let json = Json::from_str(&json_str).unwrap();
        match json::get_json_string(
            &json, &[Key("query"), Key("pages"), Only, Key("revisions"), Only, Key("*")]) {
            Ok(content) => Ok(content.to_string()),
            Err(msg) => Err(msg),
        }
    }

    /// Follows all redirects to find the canonical name of the page at `title`.
    pub fn get_canonical_title(&self, title: &str) -> Result<String, String> {
        let latest_revision_id = self.get_latest_revision(title).unwrap().revid;
        let page_contents = self.get_revision_content(title, latest_revision_id).unwrap();

        let regex = regex!(r"#REDIRECT \[\[([^]]+)\]\].*");
        match regex.captures(&page_contents) {
            Some(captures) => self.get_canonical_title(captures.at(1).unwrap()),
            None => {
                println!("Canonical page title is \"{}\"", title);
                Ok(title.to_string())
            },
        }
    }

    /// Parses the wikitext in `wikitext` as though it were the contents of the page `title`,
    /// returning the rendered HTML.
    pub fn parse_wikitext(&self, title: &str, wikitext: &str) -> Result<String, String> {
        let encoded_wikitext =
            percent_encoding::percent_encode(wikitext.as_bytes(), percent_encoding::QUERY_ENCODE_SET);
        let html = self.call_mediawiki_api(
            vec![("action", "parse"), ("prop", "text"), ("disablepp", ""), ("contentmodel", "wikitext"),
                 ("title", title), ("text", &encoded_wikitext)]).unwrap();
        // TODO: check return value
        let json = Json::from_str(&html).unwrap();
        match json::get_json_string(&json, &[Key("parse"), Key("text"), Key("*")]) {
            Ok(contents) => Ok(contents.to_string()),
            Err(message) => Err(message),
        }
    }

    /// Gets the current, fully-rendered (**HTML**) contents of the page `title`.
    pub fn get_current_page_content(title: &str) -> String {
        // TODO: should this struct be keeping a Client instead of creating new ones for each method
        // call, here and in call_mediawiki_api?
        let client = Client::new();
        let mut res = client.get(
            &format!("https://en.wikipedia.org/wiki/{}", title))
            .header(Connection::close())
            .send().unwrap();

        let mut body = String::new();
        res.read_to_string(&mut body).unwrap();

        body
    }
}
<|endoftext|>


<commit_before>extern crate sdl2;

#[macro_use]
mod events;

use sdl2::render::Renderer;

pub fn spawn<F>(title: &str, init:F) where F: Fn( &mut Phi ) -> Box<View> {

    // initialize SDL2
    let sdl_context =  sdl2::init().unwrap();
    let video = sdl_context.video().unwrap();
    let mut timer = sdl_context.timer().unwrap();

    // create a new window
    let window = video.window(&title, 800, 600)
            .position_centered().opengl()
            .build().unwrap();

    let mut context = Phi{
        events: Events::new( sdl_context.event_pump().unwrap() ),
        renderer: window.renderer().accelerated().build().unwrap(),
    };

    let mut current_view = init(&mut context);

    // Frame timing

    let interval = 1_000 / 60;
    let mut before = timer.ticks();
    let mut last_second = timer.ticks();
    let mut fps = 0u16;

    loop {
        let now = timer.ticks();
        let delta = now - before;
        let elapsed = delta as f64 / 1_000.0;

        if delta < interval {
            timer.delay( interval - delta );
                continue;
        }

        before = now;
        fps += 1;

       if now - last_second > 1_000 {
           println!("FPS: {}", fps);
           last_second = now;
           fps = 0;
       }

        // pump spins the game loop 1 tick
        context.events.pump();

        // render returns a view action, which we match on
        match current_view.render( &mut context, elapsed ){
            ViewAction::None => context.renderer.present(),
            ViewAction::Quit => break,
            ViewAction::ChangeView(new_view) => current_view = new_view,
        }
    }

}

struct_events! {
    keyboard: {
        key_escape: Escape,
        key_up: Up,
        key_down: Down,
        key_space: Space,
        key_left: Left,
        key_right: Right
    },
    else: {
        quit: Quit { .. }
    }
}

/// Bundles the Phi abstractions in a single structur
/// to be passed easily
pub struct Phi<'window> {
    pub events: Events,
    pub renderer: Renderer<'window>
}

/// A Way for the currently executed View
/// to communicate with the game loop. It specifies
/// which action should be executed before the next rendering
pub enum ViewAction {
    None,
    Quit,
    ChangeView(Box<View>)
}

pub trait View {
    /// Called every fram to take care of both the logic
    /// and the rendering of the current view
    ///
    /// `elapsed` is expressed in seconds
    fn render(&mut self, context: &mut Phi, elapsed: f64) -> ViewAction;
}

<commit_msg>add a output size method to Phi<commit_after>extern crate sdl2;

#[macro_use]
mod events;

use sdl2::render::Renderer;

pub fn spawn<F>(title: &str, init:F) where F: Fn( &mut Phi ) -> Box<View> {

    // initialize SDL2
    let sdl_context =  sdl2::init().unwrap();
    let video = sdl_context.video().unwrap();
    let mut timer = sdl_context.timer().unwrap();

    // create a new window
    let window = video.window(&title, 800, 600)
            .position_centered().opengl().resizable()
            .build().unwrap();

    let mut context = Phi{
        events: Events::new( sdl_context.event_pump().unwrap() ),
        renderer: window.renderer().accelerated().build().unwrap(),
    };

    let mut current_view = init(&mut context);

    // Frame timing

    let interval = 1_000 / 60;
    let mut before = timer.ticks();
    let mut last_second = timer.ticks();
    let mut fps = 0u16;

    loop {
        let now = timer.ticks();
        let delta = now - before;
        let elapsed = delta as f64 / 1_000.0;

        if delta < interval {
            timer.delay( interval - delta );
                continue;
        }

        before = now;
        fps += 1;

       if now - last_second > 1_000 {
           println!("FPS: {}", fps);
           last_second = now;
           fps = 0;
       }

        // pump spins the game loop 1 tick
        context.events.pump( &mut context.renderer );

        // render returns a view action, which we match on
        match current_view.render( &mut context, elapsed ){
            ViewAction::None => context.renderer.present(),
            ViewAction::Quit => break,
            ViewAction::ChangeView(new_view) => current_view = new_view,
        }
    }

}

struct_events! {
    keyboard: {
        key_escape: Escape,
        key_up: Up,
        key_down: Down,
        key_space: Space,
        key_left: Left,
        key_right: Right
    },
    else: {
        quit: Quit { .. }
    }
}

/// Bundles the Phi abstractions in a single structur
/// to be passed easily
pub struct Phi<'window> {
    pub events: Events,
    pub renderer: Renderer<'window>
}

impl<`window> Phi<`window> {
    pub fn output_size(&self) -> ( f64, f64 ){
        let ( h, w ) = self.renderer.output_size().unwrap();
        ( w as f64, h as f64 )
    }
}

/// A Way for the currently executed View
/// to communicate with the game loop. It specifies
/// which action should be executed before the next rendering
pub enum ViewAction {
    None,
    Quit,
    ChangeView(Box<View>)
}

pub trait View {
    /// Called every fram to take care of both the logic
    /// and the rendering of the current view
    ///
    /// `elapsed` is expressed in seconds
    fn render(&mut self, context: &mut Phi, elapsed: f64) -> ViewAction;
}

<|endoftext|>


<commit_before>use libc;

extern {
    #[cfg(test)]
    fn highbd_dc_predictor(dst: *mut u16, stride: libc::ptrdiff_t, bw: libc::c_int,
                                           bh: libc::c_int, above: *const u16,
                           left: *const u16, bd: libc::c_int);
    fn highbd_dc_left_predictor(dst: *mut u16, stride: libc::ptrdiff_t, bw: libc::c_int,
                           bh: libc::c_int, above: *const u16,
                           left: *const u16, bd: libc::c_int);
    fn highbd_dc_top_predictor(dst: *mut u16, stride: libc::ptrdiff_t, bw: libc::c_int,
                           bh: libc::c_int, above: *const u16,
                           left: *const u16, bd: libc::c_int);
    fn highbd_h_predictor(dst: *mut u16, stride: libc::ptrdiff_t, bw: libc::c_int,
                           bh: libc::c_int, above: *const u16,
                           left: *const u16, bd: libc::c_int);
}

pub fn pred_dc_128(output: &mut [u16], stride: usize) {
    for y in 0..4 {
        for x in 0..4 {
            output[y*stride+x] = 128;
        }
    }
}

pub fn pred_dc_left_4x4(output: &mut [u16], stride: usize, above: &[u16], left: &[u16]) {
    unsafe {
        highbd_dc_left_predictor(output.as_mut_ptr(), stride as libc::ptrdiff_t, 4, 4, above.as_ptr(), left.as_ptr(), 8);
    }
}

pub fn pred_dc_top_4x4(output: &mut [u16], stride: usize, above: &[u16], left: &[u16]) {
    unsafe {
        highbd_dc_top_predictor(output.as_mut_ptr(), stride as libc::ptrdiff_t, 4, 4, above.as_ptr(), left.as_ptr(), 8);
    }
}

pub fn pred_h_4x4(output: &mut [u16], stride: usize, above: &[u16], left: &[u16]) {
    unsafe {
        highbd_h_predictor(output.as_mut_ptr(), stride as libc::ptrdiff_t, 4, 4, above.as_ptr(), left.as_ptr(), 8);
    }
}

pub fn pred_dc(output: &mut [u16], stride: usize, above: &[u16], left: &[u16]) {
    let edges = left.iter().chain(above.iter());
    let len = (left.len() + above.len()) as u32;
    let bw = above.len();
    let bh = left.len();
    let avg = (edges.fold(0, |acc, &v| acc + v as u32) + (len >> 1)) / len;

    for line in output.chunks_mut(stride).take(bh) {
        for v in &mut line[..bw] {
            *v = avg as u16;
        }
    }
}

#[cfg(test)]
pub fn pred_h(output: &mut [u16], stride: usize, left: &[u16], bh: usize) {
  let bw = left.len();

  let mut i = 0;
  for line in output.chunks_mut(stride).take(bh) {
    for v in &mut line[..bw] {
      *v = left[i];
    }
    i = i + 1;
  }
}

#[cfg(test)]
mod test {
    use super::*;
    use rand::{ChaChaRng, Rng};

    const MAX_ITER: usize = 1000;

    fn setup_pred(ra: &mut ChaChaRng) -> (Vec<u16>, Vec<u16>, Vec<u16>, Vec<u16>) {
        let output = vec![0u16; 32 * 32];
        let above: Vec<u16> = (0..32).map(|_| ra.gen()).collect();
        let left: Vec<u16> = (0..32).map(|_| ra.gen()).collect();

        let o1 = output.clone();
        let o2 = output.clone();

        (above, left, o1, o2)
    }

    fn pred_dc_4x4(output: &mut [u16], stride: usize, above: &[u16], left: &[u16]) {
        unsafe {
            highbd_dc_predictor(output.as_mut_ptr(), stride as libc::ptrdiff_t, 4, 4, above.as_ptr(), left.as_ptr(), 8);
        }
    }

    fn do_dc_pred(ra: &mut ChaChaRng) -> (Vec<u16>, Vec<u16>) {
        let (above, left, mut o1, mut o2) = setup_pred(ra);

        pred_dc_4x4(&mut o1, 32, &above[..4], &left[..4]);
        pred_dc(&mut o2, 32, &above[..4], &left[..4]);

        (o1, o2)
    }

    fn do_h_pred(ra: &mut ChaChaRng) -> (Vec<u16>, Vec<u16>) {
        let (above, left, mut o1, mut o2) = setup_pred(ra);

        pred_h_4x4(&mut o1, 32, &above[..4], &left[..4]);
        pred_h(&mut o2, 32, &left[..4], 4);

        (o1, o2)
    }

    fn assert_same(o2: Vec<u16>) {
      for l in o2.chunks(32).take(4) {
        for v in l[..4].windows(2) {
          assert_eq!(v[0], v[1]);
        }
      }
    }

    #[test]
    fn pred_matches() {
        let mut ra = ChaChaRng::new_unseeded();
        for _ in 0..MAX_ITER {
            let (o1, o2) = do_dc_pred(&mut ra);
            assert_eq!(o1, o2);

            let (o1, o2) = do_h_pred(&mut ra);
            assert_eq!(o1, o2);
        }
    }

    #[test]
    fn pred_same() {
        let mut ra = ChaChaRng::new_unseeded();
        for _ in 0..MAX_ITER {
            let (_, o2) = do_dc_pred(&mut ra);

            assert_same(o2)
        }
    }

    #[test]
    fn pred_max() {
        let max12bit = 4096 - 1;
        let above = [max12bit; 32];
        let left = [max12bit; 32];

        let mut o = vec![0u16; 32 * 32];

        pred_dc(&mut o, 32, &above[..4], &left[..4]);

        for l in o.chunks(32).take(4) {
            for v in l[..4].iter() {
                assert_eq!(*v, max12bit);
            }
        }
    }
}
<commit_msg>Use zip for native h_pred<commit_after>use libc;

extern {
    #[cfg(test)]
    fn highbd_dc_predictor(dst: *mut u16, stride: libc::ptrdiff_t, bw: libc::c_int,
                                           bh: libc::c_int, above: *const u16,
                           left: *const u16, bd: libc::c_int);
    fn highbd_dc_left_predictor(dst: *mut u16, stride: libc::ptrdiff_t, bw: libc::c_int,
                           bh: libc::c_int, above: *const u16,
                           left: *const u16, bd: libc::c_int);
    fn highbd_dc_top_predictor(dst: *mut u16, stride: libc::ptrdiff_t, bw: libc::c_int,
                           bh: libc::c_int, above: *const u16,
                           left: *const u16, bd: libc::c_int);
    fn highbd_h_predictor(dst: *mut u16, stride: libc::ptrdiff_t, bw: libc::c_int,
                           bh: libc::c_int, above: *const u16,
                           left: *const u16, bd: libc::c_int);
}

pub fn pred_dc_128(output: &mut [u16], stride: usize) {
    for y in 0..4 {
        for x in 0..4 {
            output[y*stride+x] = 128;
        }
    }
}

pub fn pred_dc_left_4x4(output: &mut [u16], stride: usize, above: &[u16], left: &[u16]) {
    unsafe {
        highbd_dc_left_predictor(output.as_mut_ptr(), stride as libc::ptrdiff_t, 4, 4, above.as_ptr(), left.as_ptr(), 8);
    }
}

pub fn pred_dc_top_4x4(output: &mut [u16], stride: usize, above: &[u16], left: &[u16]) {
    unsafe {
        highbd_dc_top_predictor(output.as_mut_ptr(), stride as libc::ptrdiff_t, 4, 4, above.as_ptr(), left.as_ptr(), 8);
    }
}

pub fn pred_h_4x4(output: &mut [u16], stride: usize, above: &[u16], left: &[u16]) {
    unsafe {
        highbd_h_predictor(output.as_mut_ptr(), stride as libc::ptrdiff_t, 4, 4, above.as_ptr(), left.as_ptr(), 8);
    }
}

pub fn pred_dc(output: &mut [u16], stride: usize, above: &[u16], left: &[u16]) {
    let edges = left.iter().chain(above.iter());
    let len = (left.len() + above.len()) as u32;
    let bw = above.len();
    let bh = left.len();
    let avg = (edges.fold(0, |acc, &v| acc + v as u32) + (len >> 1)) / len;

    for line in output.chunks_mut(stride).take(bh) {
        for v in &mut line[..bw] {
            *v = avg as u16;
        }
    }
}

#[cfg(test)]
pub fn pred_h(output: &mut [u16], stride: usize, left: &[u16], bw: usize) {
  for (line, l) in output.chunks_mut(stride).zip(left) {
    for v in &mut line[..bw] {
      *v = *l;
    }
  }
}

#[cfg(test)]
mod test {
    use super::*;
    use rand::{ChaChaRng, Rng};

    const MAX_ITER: usize = 1000;

    fn setup_pred(ra: &mut ChaChaRng) -> (Vec<u16>, Vec<u16>, Vec<u16>, Vec<u16>) {
        let output = vec![0u16; 32 * 32];
        let above: Vec<u16> = (0..32).map(|_| ra.gen()).collect();
        let left: Vec<u16> = (0..32).map(|_| ra.gen()).collect();

        let o1 = output.clone();
        let o2 = output.clone();

        (above, left, o1, o2)
    }

    fn pred_dc_4x4(output: &mut [u16], stride: usize, above: &[u16], left: &[u16]) {
        unsafe {
            highbd_dc_predictor(output.as_mut_ptr(), stride as libc::ptrdiff_t, 4, 4, above.as_ptr(), left.as_ptr(), 8);
        }
    }

    fn do_dc_pred(ra: &mut ChaChaRng) -> (Vec<u16>, Vec<u16>) {
        let (above, left, mut o1, mut o2) = setup_pred(ra);

        pred_dc_4x4(&mut o1, 32, &above[..4], &left[..4]);
        pred_dc(&mut o2, 32, &above[..4], &left[..4]);

        (o1, o2)
    }

    fn do_h_pred(ra: &mut ChaChaRng) -> (Vec<u16>, Vec<u16>) {
        let (above, left, mut o1, mut o2) = setup_pred(ra);

        pred_h_4x4(&mut o1, 32, &above[..4], &left[..4]);
        pred_h(&mut o2, 32, &left[..4], 4);

        (o1, o2)
    }

    fn assert_same(o2: Vec<u16>) {
      for l in o2.chunks(32).take(4) {
        for v in l[..4].windows(2) {
          assert_eq!(v[0], v[1]);
        }
      }
    }

    #[test]
    fn pred_matches() {
        let mut ra = ChaChaRng::new_unseeded();
        for _ in 0..MAX_ITER {
            let (o1, o2) = do_dc_pred(&mut ra);
            assert_eq!(o1, o2);

            let (o1, o2) = do_h_pred(&mut ra);
            assert_eq!(o1, o2);
        }
    }

    #[test]
    fn pred_same() {
        let mut ra = ChaChaRng::new_unseeded();
        for _ in 0..MAX_ITER {
            let (_, o2) = do_dc_pred(&mut ra);

            assert_same(o2)
        }
    }

    #[test]
    fn pred_max() {
        let max12bit = 4096 - 1;
        let above = [max12bit; 32];
        let left = [max12bit; 32];

        let mut o = vec![0u16; 32 * 32];

        pred_dc(&mut o, 32, &above[..4], &left[..4]);

        for l in o.chunks(32).take(4) {
            for v in l[..4].iter() {
                assert_eq!(*v, max12bit);
            }
        }
    }
}
<|endoftext|>


<commit_before>use std::io::{IoError, Stream};
use std::io::net::ip;
use {Header, HTTPVersion, Method, Response, StatusCode};
use util::{AnyReader, AnyWriter};

/// Represents an HTTP request made by a client.
///
/// A `Request` object is what is produced by the server, and is your what
///  your code must analyse and answer.
///
/// This object implements the `Send` trait, therefore you can dispatch your requests to
///  worker threads.
///
/// # Pipelining
///
/// If a client sends multiple requests in a row (without waiting for the response), then you will
///  get multiple `Request` objects simultaneously. This is called *requests pipelining*.
/// Tiny-http automatically reorders the responses so that you don't need to worry about the order
///  in which you call `respond` or `into_writer`.
///
/// This mechanic is disabled if:
///
///  - The body of a request is large enough (handling requires pipelining requires storing the
///     body of the request in a buffer ; if the body is too big, tiny-http will avoid doing that)
///  - A request sends a `Expect: 100-continue` header (which means that the client waits to
///     know whether its body will be processed before sending it)
///  - A request sends a `Connection: close` header or `Connection: upgrade` header (used for
///     websockets), which indicates that this is the last request that will be received on this
///     connection
///
/// # Automatic cleanup
///
/// If a `Request` object is destroyed without `into_writer` or `respond` being called,
///  an empty response with a 500 status code (internal server error) will automatically be
///  sent back to the client.
/// This means that if your code fails during the handling of a request, this "internal server
///  error" response will automatically be sent during the stack unwinding.
#[unstable]
pub struct Request {
    // where to read the body from
    data_reader: Option<AnyReader>,

    // if this writer is empty, then the request has been answered
    response_writer: Option<AnyWriter>,

    remote_addr: ip::SocketAddr,

    method: Method,

    path: ::url::Path,

    http_version: HTTPVersion,

    headers: Vec<Header>,

    body_length: Option<uint>,

    // true if a `100 Continue` response must be sent when `as_reader()` is called
    must_send_continue: bool,
}

/// Error that can happen when building a `Request` object.
pub enum RequestCreationError {
    ExpectationFailed,
    CreationIoError(IoError),
}

// this trait is to make sure that Request implements Send
#[doc(hidden)]
trait MustBeSendDummy : Send {}
#[doc(hidden)]
impl MustBeSendDummy for Request {}

/// Builds a new request
pub fn new_request<R: Reader + Send, W: Writer + Send>(method: Method, path: ::url::Path,
                             version: HTTPVersion, headers: Vec<Header>,
                             remote_addr: ip::SocketAddr, mut source_data: R, writer: W)
    -> Result<Request, RequestCreationError>
{
    // finding the transfer-encoding header
    let transfer_encoding = headers.iter()
        .find(|h: &&Header| h.field.equiv(&"Transfer-Encoding"))
        .map(|h| h.value.clone());

    // finding the content-length header
    let content_length = if transfer_encoding.is_some() {
        // if transfer-encoding is specified, the Content-Length
        //  header must be ignored (RFC2616 #4.4)
        None

    } else {
        headers.iter()
            .find(|h: &&Header| h.field.equiv(&"Content-Length"))
            .and_then(|h| from_str::<uint>(h.value.as_slice()))
    };

    // true if the client sent a `Expect: 100-continue` header
    let expects_continue = {
        use std::ascii::StrAsciiExt;

        match headers.iter().find(|h: &&Header| h.field.equiv(&"Expect")) {
            None => false,
            Some(h) if h.value.as_slice().eq_ignore_ascii_case("100-continue")
                => true,
            _ => return Err(ExpectationFailed)
        }
    };

    // building the reader depending on
    //  transfer-encoding and content-length
    let reader =
        if content_length.is_some() {
            let content_length = content_length.as_ref().unwrap().clone();

            if content_length == 0 {
                use std::io::util::NullReader;
                box NullReader as Box<Reader + Send>

            } else if content_length <= 1024 && !expects_continue {
                use std::io::MemReader;
                let data = try!(source_data.read_exact(content_length)
                    .map_err(|e| CreationIoError(e)));
                box MemReader::new(data) as Box<Reader + Send>

            } else {
                use util::EqualReader;
                let (data_reader, _) = EqualReader::new(source_data, content_length);   // TODO:
                box data_reader as Box<Reader + Send>
            }

        } else if transfer_encoding.is_some() {
            // if a transfer-encoding was specified, then "chunked"
            //  is ALWAYS applied over the message (RFC2616 #3.6)
            use util::ChunksDecoder;
            box ChunksDecoder::new(source_data) as Box<Reader + Send>

        } else {
            // if we have neither a Content-Length nor a Transfer-Encoding,
            //  assuming that we have no data
            // TODO: could also be multipart/byteranges
            use std::io::util::NullReader;
            box NullReader as Box<Reader + Send>
        };

    Ok(Request {
        data_reader: Some(AnyReader::new(reader)),
        response_writer: Some(AnyWriter::new(box writer as Box<Writer + Send>)),
        remote_addr: remote_addr,
        method: method,
        path: path,
        http_version: version,
        headers: headers,
        body_length: content_length,
        must_send_continue: expects_continue,
    })
}

impl Request {
    /// Returns the method requested by the client (eg. `GET`, `POST`, etc.).
    #[stable]
    #[inline]
    pub fn get_method(&self) -> &Method {
        &self.method
    }

    /// Returns the resource requested by the client.
    #[unstable]
    #[inline]
    pub fn get_url(&self) -> &::url::Path {
        &self.path
    }

    /// Returns a list of all headers sent by the client.
    #[stable]
    #[inline]
    pub fn get_headers(&self) -> &[Header] {
        self.headers.as_slice()
    }

    /// Returns the HTTP version of the request.
    #[unstable]
    #[inline]
    pub fn get_http_version(&self) -> &HTTPVersion {
        &self.http_version
    }

    /// Returns the length of the body in bytes.
    ///
    /// Returns `None` if the length is unknown.
    #[unstable]
    #[inline]
    pub fn get_body_length(&self) -> Option<uint> {
        self.body_length
    }

    /// Returns the length of the body in bytes.
    #[stable]
    #[inline]
    pub fn get_remote_addr(&self) -> &ip::SocketAddr {
        &self.remote_addr
    }

    /// Sends a response with a `Connection: upgrade` header, then turns the `Request` into a `Stream`.
    ///
    /// The main purpose of this function is to support websockets.
    /// If you detect that the request wants to use some kind of protocol upgrade, you can
    ///  call this function to obtain full control of the socket stream.
    ///
    /// If you call this on a non-websocket request, tiny-http will wait until this `Stream` object
    ///  is destroyed before continuing to read or write on the socket. Therefore you should always
    ///  destroy it as soon as possible.
    #[unstable]
    pub fn upgrade<R: Reader>(mut self, protocol: &str, response: Response<R>) -> Box<Stream + Send> {
        use util::CustomStream;

        response.raw_print(self.response_writer.as_mut().unwrap().by_ref(), self.http_version,
            self.headers.as_slice(), false, Some(protocol)).ok();   // TODO: unused result

        let stream = CustomStream::new(self.into_reader_impl(), self.into_writer_impl());
        box stream as Box<Stream + Send>
    }

    /// Allows to read the body of the request.
    ///
    /// # Example
    ///
    /// ```
    /// let request = server.recv();
    ///
    /// if get_content_type(&request) == "application/json" {
    ///     let json: Json = from_str(request.as_reader().read_to_string()).unwrap();
    /// }
    /// ```
    ///
    /// If the client sent a `Expect: 100-continue` header with the request, calling this
    ///  function will send back a `100 Continue` response.
    #[unstable]
    #[inline]
    pub fn as_reader(&mut self) -> &mut Reader {
        if self.must_send_continue {
            let msg = Response::new_empty(StatusCode(100));
            msg.raw_print(self.response_writer.as_mut().unwrap().by_ref(),
                self.http_version, self.headers.as_slice(), true, None).ok();
            self.response_writer.as_mut().unwrap().flush().ok();
            self.must_send_continue = false;
        }

        fn passthrough<'a>(r: &'a mut Reader) -> &'a mut Reader { r }
        passthrough(self.data_reader.as_mut().unwrap())
    }

    /// Turns the `Request` into a writer.
    ///
    /// The writer has a raw access to the stream to the user.
    /// This function is useful for things like CGI.
    ///
    /// Note that the destruction of the `Writer` object may trigger
    ///  some events. For exemple if a client has sent multiple requests and the requests
    ///  have been processed in parallel, the destruction of a writer will trigger
    ///  the writing of the next response.
    /// Therefore you should always destroy the `Writer` as soon as possible.
    #[stable]
    #[inline]
    pub fn into_writer(mut self) -> Box<Writer + Send> {
        self.into_writer_impl().unwrap()
    }

    fn into_writer_impl(&mut self) -> AnyWriter {
        use std::mem;

        assert!(self.response_writer.is_some());

        let mut writer = None;
        mem::swap(&mut self.response_writer, &mut writer);
        writer.unwrap()
    }

    fn into_reader_impl(&mut self) -> AnyReader {
        use std::mem;

        assert!(self.data_reader.is_some());

        let mut reader = None;
        mem::swap(&mut self.data_reader, &mut reader);
        reader.unwrap()
    }

    /// Sends a response to this request.
    #[unstable]
    #[inline]
    pub fn respond<R: Reader>(mut self, response: Response<R>) {
        self.respond_impl(response)
    }

    fn respond_impl<R: Reader>(&mut self, response: Response<R>) {
        use std::io;

        let mut writer = self.into_writer_impl();

        let do_not_send_body = self.method.equiv(&"HEAD");

        match response.raw_print(writer.by_ref(),
                                self.http_version, self.headers.as_slice(),
                                do_not_send_body, None)
        {
            Ok(_) => (),
            Err(ref err) if err.kind == io::Closed => (),
            Err(ref err) if err.kind == io::BrokenPipe => (),
            Err(ref err) if err.kind == io::ConnectionAborted => (),
            Err(ref err) if err.kind == io::ConnectionRefused => (),
            Err(ref err) if err.kind == io::ConnectionReset => (),
            Err(ref err) =>
                println!("error while sending answer: {}", err)     // TODO: handle better?
        };

        writer.flush().ok();
    }
}

impl ::std::fmt::Show for Request {
    fn fmt(&self, formatter: &mut ::std::fmt::Formatter)
        -> Result<(), ::std::fmt::FormatError>
    {
        (format!("Request({} {} from {})",
            self.method, self.path, self.remote_addr.ip)).fmt(formatter)
    }
}

impl Drop for Request {
    fn drop(&mut self) {
        if self.response_writer.is_some() {
            let response = Response::new_empty(StatusCode(500));
            self.respond_impl(response);
        }
    }
}
<commit_msg>Fix issues with websockets<commit_after>use std::io::{IoError, Stream};
use std::io::net::ip;
use {Header, HTTPVersion, Method, Response, StatusCode};
use util::{AnyReader, AnyWriter};

/// Represents an HTTP request made by a client.
///
/// A `Request` object is what is produced by the server, and is your what
///  your code must analyse and answer.
///
/// This object implements the `Send` trait, therefore you can dispatch your requests to
///  worker threads.
///
/// # Pipelining
///
/// If a client sends multiple requests in a row (without waiting for the response), then you will
///  get multiple `Request` objects simultaneously. This is called *requests pipelining*.
/// Tiny-http automatically reorders the responses so that you don't need to worry about the order
///  in which you call `respond` or `into_writer`.
///
/// This mechanic is disabled if:
///
///  - The body of a request is large enough (handling requires pipelining requires storing the
///     body of the request in a buffer ; if the body is too big, tiny-http will avoid doing that)
///  - A request sends a `Expect: 100-continue` header (which means that the client waits to
///     know whether its body will be processed before sending it)
///  - A request sends a `Connection: close` header or `Connection: upgrade` header (used for
///     websockets), which indicates that this is the last request that will be received on this
///     connection
///
/// # Automatic cleanup
///
/// If a `Request` object is destroyed without `into_writer` or `respond` being called,
///  an empty response with a 500 status code (internal server error) will automatically be
///  sent back to the client.
/// This means that if your code fails during the handling of a request, this "internal server
///  error" response will automatically be sent during the stack unwinding.
#[unstable]
pub struct Request {
    // where to read the body from
    data_reader: Option<AnyReader>,

    // if this writer is empty, then the request has been answered
    response_writer: Option<AnyWriter>,

    remote_addr: ip::SocketAddr,

    method: Method,

    path: ::url::Path,

    http_version: HTTPVersion,

    headers: Vec<Header>,

    body_length: Option<uint>,

    // true if a `100 Continue` response must be sent when `as_reader()` is called
    must_send_continue: bool,
}

/// Error that can happen when building a `Request` object.
pub enum RequestCreationError {
    ExpectationFailed,
    CreationIoError(IoError),
}

// this trait is to make sure that Request implements Send
#[doc(hidden)]
trait MustBeSendDummy : Send {}
#[doc(hidden)]
impl MustBeSendDummy for Request {}

/// Builds a new request
pub fn new_request<R: Reader + Send, W: Writer + Send>(method: Method, path: ::url::Path,
                             version: HTTPVersion, headers: Vec<Header>,
                             remote_addr: ip::SocketAddr, mut source_data: R, writer: W)
    -> Result<Request, RequestCreationError>
{
    // finding the transfer-encoding header
    let transfer_encoding = headers.iter()
        .find(|h: &&Header| h.field.equiv(&"Transfer-Encoding"))
        .map(|h| h.value.clone());

    // finding the content-length header
    let content_length = if transfer_encoding.is_some() {
        // if transfer-encoding is specified, the Content-Length
        //  header must be ignored (RFC2616 #4.4)
        None

    } else {
        headers.iter()
            .find(|h: &&Header| h.field.equiv(&"Content-Length"))
            .and_then(|h| from_str::<uint>(h.value.as_slice()))
    };

    // true if the client sent a `Expect: 100-continue` header
    let expects_continue = {
        use std::ascii::StrAsciiExt;

        match headers.iter().find(|h: &&Header| h.field.equiv(&"Expect")) {
            None => false,
            Some(h) if h.value.as_slice().eq_ignore_ascii_case("100-continue")
                => true,
            _ => return Err(ExpectationFailed)
        }
    };

    // true if the client sent a `Connection: upgrade` header
    let connection_upgrade = {
        use std::ascii::StrAsciiExt;

        match headers.iter().find(|h: &&Header| h.field.equiv(&"Connection")) {
            None => false,
            Some(h) if h.value.as_slice().eq_ignore_ascii_case("upgrade")
                => true,
            _ => false
        }
    };

    // building the reader depending on
    //  transfer-encoding and content-length
    let reader =
        if connection_upgrade {
            // if we have a `Connection: upgrade`, always keeping the whole reader
            box source_data as Box<Reader + Send>

        } else if content_length.is_some() {
            let content_length = content_length.as_ref().unwrap().clone();

            if content_length == 0 {
                use std::io::util::NullReader;
                box NullReader as Box<Reader + Send>

            } else if content_length <= 1024 && !expects_continue {
                use std::io::MemReader;
                let data = try!(source_data.read_exact(content_length)
                    .map_err(|e| CreationIoError(e)));
                box MemReader::new(data) as Box<Reader + Send>

            } else {
                use util::EqualReader;
                let (data_reader, _) = EqualReader::new(source_data, content_length);   // TODO:
                box data_reader as Box<Reader + Send>
            }

        } else if transfer_encoding.is_some() {
            // if a transfer-encoding was specified, then "chunked"
            //  is ALWAYS applied over the message (RFC2616 #3.6)
            use util::ChunksDecoder;
            box ChunksDecoder::new(source_data) as Box<Reader + Send>

        } else {
            // if we have neither a Content-Length nor a Transfer-Encoding,
            //  assuming that we have no data
            // TODO: could also be multipart/byteranges
            use std::io::util::NullReader;
            box NullReader as Box<Reader + Send>
        };

    Ok(Request {
        data_reader: Some(AnyReader::new(reader)),
        response_writer: Some(AnyWriter::new(box writer as Box<Writer + Send>)),
        remote_addr: remote_addr,
        method: method,
        path: path,
        http_version: version,
        headers: headers,
        body_length: content_length,
        must_send_continue: expects_continue,
    })
}

impl Request {
    /// Returns the method requested by the client (eg. `GET`, `POST`, etc.).
    #[stable]
    #[inline]
    pub fn get_method(&self) -> &Method {
        &self.method
    }

    /// Returns the resource requested by the client.
    #[unstable]
    #[inline]
    pub fn get_url(&self) -> &::url::Path {
        &self.path
    }

    /// Returns a list of all headers sent by the client.
    #[stable]
    #[inline]
    pub fn get_headers(&self) -> &[Header] {
        self.headers.as_slice()
    }

    /// Returns the HTTP version of the request.
    #[unstable]
    #[inline]
    pub fn get_http_version(&self) -> &HTTPVersion {
        &self.http_version
    }

    /// Returns the length of the body in bytes.
    ///
    /// Returns `None` if the length is unknown.
    #[unstable]
    #[inline]
    pub fn get_body_length(&self) -> Option<uint> {
        self.body_length
    }

    /// Returns the length of the body in bytes.
    #[stable]
    #[inline]
    pub fn get_remote_addr(&self) -> &ip::SocketAddr {
        &self.remote_addr
    }

    /// Sends a response with a `Connection: upgrade` header, then turns the `Request` into a `Stream`.
    ///
    /// The main purpose of this function is to support websockets.
    /// If you detect that the request wants to use some kind of protocol upgrade, you can
    ///  call this function to obtain full control of the socket stream.
    ///
    /// If you call this on a non-websocket request, tiny-http will wait until this `Stream` object
    ///  is destroyed before continuing to read or write on the socket. Therefore you should always
    ///  destroy it as soon as possible.
    #[unstable]
    pub fn upgrade<R: Reader>(mut self, protocol: &str, response: Response<R>) -> Box<Stream + Send> {
        use util::CustomStream;

        response.raw_print(self.response_writer.as_mut().unwrap().by_ref(), self.http_version,
            self.headers.as_slice(), false, Some(protocol)).ok();   // TODO: unused result

        self.response_writer.as_mut().unwrap().flush().ok();    // TODO: unused result

        let stream = CustomStream::new(self.into_reader_impl(), self.into_writer_impl());
        box stream as Box<Stream + Send>
    }

    /// Allows to read the body of the request.
    ///
    /// # Example
    ///
    /// ```
    /// let request = server.recv();
    ///
    /// if get_content_type(&request) == "application/json" {
    ///     let json: Json = from_str(request.as_reader().read_to_string()).unwrap();
    /// }
    /// ```
    ///
    /// If the client sent a `Expect: 100-continue` header with the request, calling this
    ///  function will send back a `100 Continue` response.
    #[unstable]
    #[inline]
    pub fn as_reader(&mut self) -> &mut Reader {
        if self.must_send_continue {
            let msg = Response::new_empty(StatusCode(100));
            msg.raw_print(self.response_writer.as_mut().unwrap().by_ref(),
                self.http_version, self.headers.as_slice(), true, None).ok();
            self.response_writer.as_mut().unwrap().flush().ok();
            self.must_send_continue = false;
        }

        fn passthrough<'a>(r: &'a mut Reader) -> &'a mut Reader { r }
        passthrough(self.data_reader.as_mut().unwrap())
    }

    /// Turns the `Request` into a writer.
    ///
    /// The writer has a raw access to the stream to the user.
    /// This function is useful for things like CGI.
    ///
    /// Note that the destruction of the `Writer` object may trigger
    ///  some events. For exemple if a client has sent multiple requests and the requests
    ///  have been processed in parallel, the destruction of a writer will trigger
    ///  the writing of the next response.
    /// Therefore you should always destroy the `Writer` as soon as possible.
    #[stable]
    #[inline]
    pub fn into_writer(mut self) -> Box<Writer + Send> {
        self.into_writer_impl().unwrap()
    }

    fn into_writer_impl(&mut self) -> AnyWriter {
        use std::mem;

        assert!(self.response_writer.is_some());

        let mut writer = None;
        mem::swap(&mut self.response_writer, &mut writer);
        writer.unwrap()
    }

    fn into_reader_impl(&mut self) -> AnyReader {
        use std::mem;

        assert!(self.data_reader.is_some());

        let mut reader = None;
        mem::swap(&mut self.data_reader, &mut reader);
        reader.unwrap()
    }

    /// Sends a response to this request.
    #[unstable]
    #[inline]
    pub fn respond<R: Reader>(mut self, response: Response<R>) {
        self.respond_impl(response)
    }

    fn respond_impl<R: Reader>(&mut self, response: Response<R>) {
        use std::io;

        let mut writer = self.into_writer_impl();

        let do_not_send_body = self.method.equiv(&"HEAD");

        match response.raw_print(writer.by_ref(),
                                self.http_version, self.headers.as_slice(),
                                do_not_send_body, None)
        {
            Ok(_) => (),
            Err(ref err) if err.kind == io::Closed => (),
            Err(ref err) if err.kind == io::BrokenPipe => (),
            Err(ref err) if err.kind == io::ConnectionAborted => (),
            Err(ref err) if err.kind == io::ConnectionRefused => (),
            Err(ref err) if err.kind == io::ConnectionReset => (),
            Err(ref err) =>
                println!("error while sending answer: {}", err)     // TODO: handle better?
        };

        writer.flush().ok();
    }
}

impl ::std::fmt::Show for Request {
    fn fmt(&self, formatter: &mut ::std::fmt::Formatter)
        -> Result<(), ::std::fmt::FormatError>
    {
        (format!("Request({} {} from {})",
            self.method, self.path, self.remote_addr.ip)).fmt(formatter)
    }
}

impl Drop for Request {
    fn drop(&mut self) {
        if self.response_writer.is_some() {
            let response = Response::new_empty(StatusCode(500));
            self.respond_impl(response);
        }
    }
}
<|endoftext|>


<commit_before>pub mod builtins;

use std::collections::HashMap;
use std::path::PathBuf;
use std::io;
use std::io::{Read, Write};
use std::collections::hash_map::Entry;

#[derive(PartialEq, Debug, Clone)]
pub struct State {
    cwd: PathBuf,
    environment: HashMap<String, String>,
    aliases: HashMap<String, String>,
    argv: Vec<String>,
    argc: usize,
}

impl State {
    pub fn new(cwd: String) -> State {
        State {
            cwd: PathBuf::from(cwd),
            environment: HashMap::new(),
            aliases: HashMap::new(),
            argv: Vec::new(),
            argc: 0,
        }
    }
}

pub fn run(initial_state: State) {
    let mut builtins = builtins::load();
    let mut s = initial_state.clone();

    println!("Welcome to rsh! {:?}", s);

    loop {

        print!("\n");
        print!("{} -> ", s.cwd.to_str().unwrap());

        // this forces the prompt to print
        io::stdout().flush();

        // read the user input
        let mut input = String::new();
        io::stdin().read_line(&mut input).unwrap();

        s.argv = parse_args(&input);
        s.argc = s.argv.len();

        print!("\n");
        println!("Input: {}\nState: {:?}", input, s);

        let first_arg = s.argv.get(0).unwrap().clone();
        if let Entry::Occupied(f) = builtins.entry(String::from(first_arg)) {
            let bn = f.get();
            s = bn(s.clone());
        }
    }
}

fn parse_args(args: &String) -> Vec<String> {
    let mut result: Vec<String> = vec!["test".to_string()];
    result
}

#[test]
fn parse_args_test() {
    let args = String::from("echo -n \"Hello World\"");
    let result = parse_args(&args);
    let expected = vec!["echo".to_string(), "-n".into(), "\"Hello World\"".into()];
    assert_eq!(result, expected);
}
<commit_msg>Update parse_args to handle many situations<commit_after>pub mod builtins;

use std::collections::HashMap;
use std::path::PathBuf;
use std::io;
use std::io::{Read, Write};
use std::collections::hash_map::Entry;

#[derive(PartialEq, Debug, Clone)]
pub struct State {
    cwd: PathBuf,
    environment: HashMap<String, String>,
    aliases: HashMap<String, String>,
    argv: Vec<String>,
    argc: usize,
}

impl State {
    pub fn new(cwd: String) -> State {
        State {
            cwd: PathBuf::from(cwd),
            environment: HashMap::new(),
            aliases: HashMap::new(),
            argv: Vec::new(),
            argc: 0,
        }
    }
}

pub fn run(initial_state: State) {
    let mut builtins = builtins::load();
    let mut s = initial_state.clone();

    println!("Welcome to rsh! {:?}", s);

    loop {

        print!("\n");
        print!("{} -> ", s.cwd.to_str().unwrap());

        // this forces the prompt to print
        io::stdout().flush();

        // read the user input
        let mut input = String::new();
        io::stdin().read_line(&mut input).unwrap();

        s.argv = parse_args(&input);
        s.argc = s.argv.len();

        print!("\n");
        println!("Input: {}\nState: {:?}", input, s);

        let first_arg = s.argv.get(0).unwrap().clone();
        if let Entry::Occupied(f) = builtins.entry(String::from(first_arg)) {
            let bn = f.get();
            s = bn(s.clone());
        }
    }
}

fn parse_args(args: &String) -> Vec<String> {
    let mut result: Vec<String> = Vec::new();

    if args.len() == 0 {
        return result
    }

    let mut building_string: bool = false;
    let mut build_string: String = String::from("");
    for string in args.split_whitespace() {
        if string.starts_with("\"") {
            if string.ends_with("\"") {
                build_string.push_str(string);
                result.push(build_string);

                building_string = false;
                build_string = String::from("");
            } else {
                building_string = true;

                build_string.push_str(string);
                build_string.push(' ');
            }
        } else if string.ends_with("\"") {
            build_string.push_str(string);
            result.push(build_string);

            building_string = false;
            build_string = String::from("");
        } else {
            if building_string {
                build_string.push_str(string);
                build_string.push(' ');
            } else {
                result.push(string.to_string());
            }
        }
    }

    result
}

#[test]
fn parse_args_test() {
    // parse empty string
    {
        let expected: Vec<String> = Vec::new();
        let result = parse_args(&String::from(""));
        assert_eq!(result, expected);
    }

    // parse single-word string
    {
        let expected: Vec<String> = vec!["echo".to_string()];
        let result = parse_args(&String::from("echo"));
        assert_eq!(result, expected);
    }

    // parse single-word string inside parens
    {
        let expected = vec!["\"echo\"".to_string()];
        let result = parse_args(&String::from("\"echo\""));
        assert_eq!(result, expected);
    }

    // parse multi-word string with closed parens section
    {
        let expected = vec!["echo".to_string(), "-n".into(), "\"Hello Dear World\"".into()];
        let result = parse_args(&String::from("echo -n \"Hello Dear World\""));
        assert_eq!(result, expected);
    }

    // parse multi-word string with multiple closed parents sections
    {
        let expected = vec!["echo".to_string(), "\"Hello\"".into(), "\"Dear World\"".into()];
        let result = parse_args(&String::from("echo \"Hello\" \"Dear World\""));
        assert_eq!(result, expected);
    }
}
<|endoftext|>


<commit_before>#![crate_name = "tee"]
#![feature(collections, core, old_io, old_path, rustc_private)]

/*
 * This file is part of the uutils coreutils package.
 *
 * (c) Aleksander Bielawski <pabzdzdzwiagief@gmail.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

extern crate getopts;
#[macro_use] extern crate log;

use std::old_io::{println, stdin, stdout, Append, File, Truncate, Write};
use std::old_io::{IoResult};
use std::old_io::util::{copy, NullWriter, MultiWriter};
use getopts::{getopts, optflag, usage};

static NAME: &'static str = "tee";
static VERSION: &'static str = "1.0.0";

pub fn uumain(args: Vec<String>) -> i32 {
    match options(args.as_slice()).and_then(exec) {
        Ok(_) => 0,
        Err(_) => 1
    }
}

#[allow(dead_code)]
struct Options {
    program: String,
    append: bool,
    ignore_interrupts: bool,
    print_and_exit: Option<String>,
    files: Box<Vec<Path>>
}

fn options(args: &[String]) -> Result<Options, ()> {
    let opts = [
        optflag("a", "append", "append to the given FILEs, do not overwrite"),
        optflag("i", "ignore-interrupts", "ignore interrupt signals"),
        optflag("h", "help", "display this help and exit"),
        optflag("V", "version", "output version information and exit"),
    ];

    let args: Vec<String> = args.iter().map(|x| x.to_string()).collect();

    getopts(args.tail(), &opts).map_err(|e| format!("{}", e)).and_then(|m| {
        let version = format!("{} {}", NAME, VERSION);
        let program = args[0].as_slice();
        let arguments = "[OPTION]... [FILE]...";
        let brief = "Copy standard input to each FILE, and also to standard output.";
        let comment = "If a FILE is -, copy again to standard output.";
        let help = format!("{}\n\nUsage:\n  {} {}\n\n{}\n{}",
                           version, program, arguments, usage(brief, &opts),
                           comment);
        let mut names = m.free.clone().into_iter().collect::<Vec<String>>();
        names.push("-".to_string());
        let to_print = if m.opt_present("help") { Some(help) }
                       else if m.opt_present("version") { Some(version) }
                       else { None };
        Ok(Options {
            program: program.to_string(),
            append: m.opt_present("append"),
            ignore_interrupts: m.opt_present("ignore-interrupts"),
            print_and_exit: to_print,
            files: Box::new(names.iter().map(|name| Path::new(name.clone())).collect())
        })
    }).map_err(|message| warn(message.as_slice()))
}

fn exec(options: Options) -> Result<(), ()> {
    match options.print_and_exit {
        Some(text) => Ok(println(text.as_slice())),
        None => tee(options)
    }
}

fn tee(options: Options) -> Result<(), ()> {
    let writers = options.files.iter().map(|path| open(path, options.append)).collect();
    let output = &mut MultiWriter::new(writers);
    let input = &mut NamedReader { inner: Box::new(stdin()) as Box<Reader> };
    if copy(input, output).is_err() || output.flush().is_err() {
        Err(())
    } else {
        Ok(())
    }
}

fn open(path: &Path, append: bool) -> Box<Writer+'static> {
    let inner = if *path == Path::new("-") {
        Box::new(stdout()) as Box<Writer>
    } else {
        let mode = if append { Append } else { Truncate };
        match File::open_mode(path, mode, Write) {
            Ok(file) => Box::new(file) as Box<Writer>,
            Err(_) => Box::new(NullWriter) as Box<Writer>
        }
    };
    Box::new(NamedWriter { inner: inner, path: Box::new(path.clone()) }) as Box<Writer>
}

struct NamedWriter {
    inner: Box<Writer+'static>,
    path: Box<Path>
}

impl Writer for NamedWriter {
    fn write_all(&mut self, buf: &[u8]) -> IoResult<()> {
        with_path(&*self.path.clone(), || {
            let val = self.inner.write_all(buf);
            if val.is_err() {
                self.inner = Box::new(NullWriter) as Box<Writer>;
            }
            val
        })
    }

    fn flush(&mut self) -> IoResult<()> {
        with_path(&*self.path.clone(), || {
            let val = self.inner.flush();
            if val.is_err() {
                self.inner = Box::new(NullWriter) as Box<Writer>;
            }
            val
        })
    }
}

struct NamedReader {
    inner: Box<Reader+'static>
}

impl Reader for NamedReader {
    fn read(&mut self, buf: &mut [u8]) -> IoResult<usize> {
        with_path(&Path::new("stdin"), || {
            self.inner.read(buf)
        })
    }
}

fn with_path<F, T>(path: &Path, mut cb: F) -> IoResult<T> where F: FnMut() -> IoResult<T> {
    match cb() {
        Err(f) => { warn(format!("{}: {}", path.display(), f.to_string()).as_slice()); Err(f) }
        okay => okay
    }
}

fn warn(message: &str) {
    error!("tee: {}", message);
}
<commit_msg>Rewrite tee.<commit_after>#![crate_name = "tee"]
#![feature(rustc_private)]

/*
 * This file is part of the uutils coreutils package.
 *
 * (c) Aleksander Bielawski <pabzdzdzwiagief@gmail.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

extern crate getopts;
#[macro_use] extern crate log;

use std::fs::OpenOptions;
use std::io::{copy, Error, ErrorKind, Read, Result, sink, stdin, stdout, Write};
use std::path::{Path, PathBuf};
use getopts::{getopts, optflag, usage};

static NAME: &'static str = "tee";
static VERSION: &'static str = "1.0.0";

pub fn uumain(args: Vec<String>) -> i32 {
    match options(&args).and_then(exec) {
        Ok(_) => 0,
        Err(_) => 1
    }
}

#[allow(dead_code)]
struct Options {
    program: String,
    append: bool,
    ignore_interrupts: bool,
    print_and_exit: Option<String>,
    files: Vec<String>
}

fn options(args: &Vec<String>) -> Result<Options> {
    let opts = [
        optflag("a", "append", "append to the given FILEs, do not overwrite"),
        optflag("i", "ignore-interrupts", "ignore interrupt signals"),
        optflag("h", "help", "display this help and exit"),
        optflag("V", "version", "output version information and exit"),
    ];

    getopts(&args[1..], &opts).map_err(|e| Error::new(ErrorKind::Other, format!("{}", e))).and_then(|m| {
        let version = format!("{} {}", NAME, VERSION);
        let program = &args[0][..];
        let arguments = "[OPTION]... [FILE]...";
        let brief = "Copy standard input to each FILE, and also to standard output.";
        let comment = "If a FILE is -, copy again to standard output.";
        let help = format!("{}\n\nUsage:\n  {} {}\n\n{}\n{}",
                           version, program, arguments, usage(brief, &opts),
                           comment);
        let mut names: Vec<String> = m.free.clone().into_iter().collect();
        names.push("-".to_string());
        let to_print = if m.opt_present("help") { Some(help) }
                       else if m.opt_present("version") { Some(version) }
                       else { None };
        Ok(Options {
            program: program.to_string(),
            append: m.opt_present("append"),
            ignore_interrupts: m.opt_present("ignore-interrupts"),
            print_and_exit: to_print,
            files: names
        })
    }).map_err(|message| warn(format!("{}", message).as_ref()))
}

fn exec(options: Options) -> Result<()> {
    match options.print_and_exit {
        Some(text) => Ok(println!("{}", text)),
        None => tee(options)
    }
}

fn tee(options: Options) -> Result<()> {
    let writers: Vec<Box<Write>> = options.files.clone().into_iter().map(|file| open(file, options.append)).collect();
    let output = &mut MultiWriter { writers: writers };
    let input = &mut NamedReader { inner: Box::new(stdin()) as Box<Read> };
    if copy(input, output).is_err() || output.flush().is_err() {
        Err(Error::new(ErrorKind::Other, ""))
    } else {
        Ok(())
    }
}

fn open(name: String, append: bool) -> Box<Write> {
    let is_stdout = name == "-";
    let path = PathBuf::from(name);
    let inner: Box<Write> = if is_stdout {
        Box::new(stdout())
    } else {
        let mut options = OpenOptions::new();
        let mode = if append { options.append(true) } else { options.truncate(true) };
        match mode.write(true).create(true).open(path.as_path()) {
            Ok(file) => Box::new(file),
            Err(_) => Box::new(sink())
        }
    };
    Box::new(NamedWriter { inner: inner, path: path }) as Box<Write>
}

struct MultiWriter {
    writers: Vec<Box<Write>>
}

impl Write for MultiWriter {
    fn write(&mut self, buf: &[u8]) -> Result<usize> {
        for writer in self.writers.iter_mut() {
            try!(writer.write_all(buf));
        }
        Ok(buf.len())
    }

    fn flush(&mut self) -> Result<()> {
        for writer in self.writers.iter_mut() {
            try!(writer.flush());
        }
        Ok(())
    }
}

struct NamedWriter {
    inner: Box<Write>,
    path: PathBuf
}

impl Write for NamedWriter {
    fn write(&mut self, buf: &[u8]) -> Result<usize> {
        match self.inner.write(buf) {
            Err(f) => {
                self.inner = Box::new(sink()) as Box<Write>;
                warn(format!("{}: {}", self.path.display(), f.to_string()).as_ref());
                Err(f)
            }
            okay => okay
        }
    }

    fn flush(&mut self) -> Result<()> {
        match self.inner.flush() {
            Err(f) => {
                self.inner = Box::new(sink()) as Box<Write>;
                warn(format!("{}: {}", self.path.display(), f.to_string()).as_ref());
                Err(f)
            }
            okay => okay
        }
    }
}

struct NamedReader {
    inner: Box<Read>
}

impl Read for NamedReader {
    fn read(&mut self, buf: &mut [u8]) -> Result<usize> {
        match self.inner.read(buf) {
            Err(f) => {
                warn(format!("{}: {}", Path::new("stdin").display(), f.to_string()).as_ref());
                Err(f)
            }
            okay => okay
        }
    }
}

fn warn(message: &str) -> Error {
    error!("tee: {}", message);
    Error::new(ErrorKind::Other, format!("tee: {}", message))
}
<|endoftext|>


<commit_before>pub use luminance::{Depth32F, Dim2, Flat, R32F, RGBA32F, Sampler, Texture};
use image;
use std::ops::Deref;
use std::path::Path;

use resource::{Load, LoadError, Reload, ResCache, Result};

// Common texture aliases.
pub type TextureRGBA32F = Texture<Flat, Dim2, RGBA32F>;
pub type TextureDepth32F = Texture<Flat, Dim2, Depth32F>;

/// Load an RGBA texture from an image at a path.
///
/// The `linearizer` argument is an option that gives the factor to apply to linearize if needed. Pass
/// `None` if the texture is already linearized.
pub fn load_rgba_texture<P, L>(path: P, sampler: &Sampler, linearizer: L) -> Result<TextureRGBA32F> where P: AsRef<Path>, L: Into<Option<f32>> {
  info!("loading texture image: \x1b[35m{:?}", path.as_ref());

  let img = image::open(path).map_err(|e| LoadError::ConversionFailed(format!("{:?}", e)))?.to_rgba();
  let dim = img.dimensions();
  let linearizer = linearizer.into();
  let raw: Vec<f32> = img.into_raw().into_iter().map(|x| {
    let y = x as f32 / 255.;
    linearizer.map_or(y, |factor| y.powf(1. / factor))
  }).collect();

  let tex = Texture::new(dim, 0, sampler).map_err(|e| LoadError::ConversionFailed(format!("{:?}", e)))?;
  tex.upload_raw(false, &raw);

  Ok(tex)
}

/// Save an RGBA image on disk.
pub fn save_rgba_texture<P>(texture: &TextureRGBA32F, path: P) where P: AsRef<Path> {
  info!("saving texture image to: \x1b[35m{:?}", path.as_ref());

  let texels = texture.get_raw_texels();
  let (w, h) = texture.size();
  let mut output = Vec::with_capacity((w * h) as usize);

  for texel in &texels {
    output.push((texel * 255.) as u8);
  }

  let _ = image::save_buffer(path, &output, w, h, image::ColorType::RGBA(8));
}

pub struct TextureImage {
  pub texture: TextureRGBA32F,
  sampler: Sampler,
  linearizer: Option<f32>,
}

impl Deref for TextureImage {
  type Target = TextureRGBA32F;

  fn deref(&self) -> &Self::Target {
    &self.texture
  }
}

impl Load for TextureImage {
  type Args = (Sampler, Option<f32>);

  const TY_STR: &'static str = "textures";

  fn load<P>(path: P, _: &mut ResCache, (sampler, linearizer): Self::Args) -> Result<Self> where P: AsRef<Path> {
    load_rgba_texture(path, &sampler, linearizer)
      .map(|tex| TextureImage {
        texture: tex,
        sampler: sampler,
        linearizer: linearizer
      })
  }
}

impl Reload for TextureImage {
  fn reload_args(&self) -> Self::Args {
    (self.sampler, self.linearizer)
  }
}
<commit_msg>Textures are now correctly flipped at loading.<commit_after>pub use luminance::{Depth32F, Dim2, Flat, R32F, RGBA32F, Sampler, Texture};
use image;
use std::ops::Deref;
use std::path::Path;

use resource::{Load, LoadError, Reload, ResCache, Result};

// Common texture aliases.
pub type TextureRGBA32F = Texture<Flat, Dim2, RGBA32F>;
pub type TextureDepth32F = Texture<Flat, Dim2, Depth32F>;

/// Load an RGBA texture from an image at a path.
///
/// The `linearizer` argument is an option that gives the factor to apply to linearize if needed. Pass
/// `None` if the texture is already linearized.
pub fn load_rgba_texture<P, L>(path: P, sampler: &Sampler, linearizer: L) -> Result<TextureRGBA32F> where P: AsRef<Path>, L: Into<Option<f32>> {
  info!("loading texture image: \x1b[35m{:?}", path.as_ref());

  let img = image::open(path).map_err(|e| LoadError::ConversionFailed(format!("{:?}", e)))?.flipv().to_rgba();
  let dim = img.dimensions();
  let linearizer = linearizer.into();
  let raw: Vec<f32> = img.into_raw().into_iter().map(|x| {
    let y = x as f32 / 255.;
    linearizer.map_or(y, |factor| y.powf(1. / factor))
  }).collect();

  let tex = Texture::new(dim, 0, sampler).map_err(|e| LoadError::ConversionFailed(format!("{:?}", e)))?;
  tex.upload_raw(false, &raw);

  Ok(tex)
}

/// Save an RGBA image on disk.
pub fn save_rgba_texture<P>(texture: &TextureRGBA32F, path: P) where P: AsRef<Path> {
  info!("saving texture image to: \x1b[35m{:?}", path.as_ref());

  let texels = texture.get_raw_texels();
  let (w, h) = texture.size();
  let mut output = Vec::with_capacity((w * h) as usize);

  for texel in &texels {
    output.push((texel * 255.) as u8);
  }

  let _ = image::save_buffer(path, &output, w, h, image::ColorType::RGBA(8));
}

pub struct TextureImage {
  pub texture: TextureRGBA32F,
  sampler: Sampler,
  linearizer: Option<f32>,
}

impl Deref for TextureImage {
  type Target = TextureRGBA32F;

  fn deref(&self) -> &Self::Target {
    &self.texture
  }
}

impl Load for TextureImage {
  type Args = (Sampler, Option<f32>);

  const TY_STR: &'static str = "textures";

  fn load<P>(path: P, _: &mut ResCache, (sampler, linearizer): Self::Args) -> Result<Self> where P: AsRef<Path> {
    load_rgba_texture(path, &sampler, linearizer)
      .map(|tex| TextureImage {
        texture: tex,
        sampler: sampler,
        linearizer: linearizer
      })
  }
}

impl Reload for TextureImage {
  fn reload_args(&self) -> Self::Args {
    (self.sampler, self.linearizer)
  }
}
<|endoftext|>


<commit_before>use std::{env, thread, time};
use std::sync::mpsc;
use std::cell::Cell;

use crossbeam;

use bot;
use command_handler::CommandHandler;
use update::Update;

const BASE_URL: &'static str = "https://api.telegram.org/bot";
thread_local!(pub static RUNNING: Cell<bool> = Cell::new(false));

pub struct Updater {
    token: String,
    last_update_id: i32,
    pub is_idle: bool,
}

impl Updater {
    /// Creates a new Updater struct.
    pub fn start(token: Option<String>,
                 poll_interval: Option<u64>,
                 timeout: Option<i32>,
                 network_delay: Option<i32>,
                 command_handler: CommandHandler) {
        let token = token.or_else(|| env::var("TELEGRAM_BOT_TOKEN").ok())
            .expect("You should pass in a token to new or set the TELEGRAM_BOT_TOKEN env var");

        let updater = Updater {
            token: token,
            last_update_id: 0,
            is_idle: false,
        };

        updater.start_polling(poll_interval, timeout, network_delay, command_handler);
    }

    pub fn stop() {
        RUNNING.with(|s| s.set(false));
    }

    fn start_polling(mut self,
                     poll_interval: Option<u64>,
                     timeout: Option<i32>,
                     network_delay: Option<i32>,
                     mut command_handler: CommandHandler) {
        if !RUNNING.with(|s| s.get()) {
            RUNNING.with(|s| s.set(true));

            let (tx, rx) = mpsc::channel();
            let bot = bot::Bot::new([BASE_URL, &self.token].concat()).unwrap();

            // Spawn scoped threads
            crossbeam::scope(|scope| {
                scope.spawn(|| {
                    self.start_polling_thread(poll_interval, timeout, network_delay, &bot, tx)
                });
                scope.spawn(|| {
                    command_handler.start_command_handling(rx, &bot);
                });
            });
        }
    }

    fn start_polling_thread(&mut self,
                            poll_interval: Option<u64>,
                            timeout: Option<i32>,
                            network_delay: Option<i32>,
                            bot: &bot::Bot,
                            tx: mpsc::Sender<Update>) {
        let poll_interval = time::Duration::from_secs(poll_interval.unwrap_or(0));

        while RUNNING.with(|s| s.get()) {
            let updates = bot.get_updates(self.last_update_id, None, timeout, network_delay);

            match updates {
                Ok(Some(ref v)) => {
                    if let Some(u) = v.last() {
                        for update in v {
                            tx.send(update.clone()).unwrap();
                        }
                        let update_id_store = u.update_id + 1;
                        self.last_update_id = update_id_store as i32;
                    } else {
                        // Do nothing, the vector is empty
                        continue;
                    }
                }
                Ok(None) => {
                    // Do nothing, we have nothing
                    continue;
                }
                Err(err) => {
                    // Handle error
                    continue;
                }
            };

            thread::sleep(poll_interval);
        }
    }
}
<commit_msg>Moved to native threads and made some architecture changes<commit_after>use std::{env, thread, time};
use std::sync::mpsc;
use std::cell::Cell;
use std::sync::Arc;
use std::sync::atomic::{AtomicBool, ATOMIC_BOOL_INIT, Ordering};
use std::thread::JoinHandle;
use std::io::Result;

use crossbeam;

use bot;
use command_handler::CommandHandler;
use update::Update;

const BASE_URL: &'static str = "https://api.telegram.org/bot";

pub struct Updater {
    token: String,
    updater_thread: Option<JoinHandle<()>>,
    dispatch_thread: Option<JoinHandle<()>>,
    pub is_running: Arc<AtomicBool>,
    pub is_idle: Arc<AtomicBool>,
}

impl Updater {
    /// Creates a new Updater struct.
    pub fn start(token: Option<String>,
                 poll_interval: Option<u64>,
                 timeout: Option<i32>,
                 network_delay: Option<i32>,
                 command_handler: CommandHandler)
                 -> Updater {
        let token = token.or_else(|| env::var("TELEGRAM_BOT_TOKEN").ok())
            .expect("You should pass in a token to new or set the TELEGRAM_BOT_TOKEN env var");

        let mut updater = Updater {
            token: token,
            updater_thread: None,
            dispatch_thread: None,
            is_running: Arc::new(ATOMIC_BOOL_INIT),
            is_idle: Arc::new(ATOMIC_BOOL_INIT),
        };

        updater.start_polling(poll_interval, timeout, network_delay, command_handler);
        updater
    }

    pub fn stop(&self) {
        self.is_running.store(false, Ordering::SeqCst);
    }

    fn start_polling(&mut self,
                     poll_interval: Option<u64>,
                     timeout: Option<i32>,
                     network_delay: Option<i32>,
                     mut command_handler: CommandHandler) {
        if !self.is_running.load(Ordering::Relaxed) {
            self.is_running.store(true, Ordering::SeqCst);

            let (tx, rx) = mpsc::channel();
            let bot = Arc::new(bot::Bot::new([BASE_URL, &self.token].concat()).unwrap());
            let updater_running = self.is_running.clone();
            let dispatcher_running = self.is_running.clone();
            let updater_bot = bot.clone();
            let dispatcher_bot = bot.clone();

            println!("Going to run threads");
            // Spawn scoped threads
            self.updater_thread = Some(thread::Builder::new()
                .name("updater".to_string())
                .spawn(move || {
                    Self::start_polling_thread(updater_running,
                                               poll_interval,
                                               timeout,
                                               network_delay,
                                               updater_bot,
                                               tx);
                })
                .unwrap());
            self.dispatch_thread = Some(thread::Builder::new()
                .name("dispatcher".to_string())
                .spawn(move || {
                    command_handler.start_command_handling(dispatcher_running, rx, dispatcher_bot);
                })
                .unwrap());
        }
    }

    fn start_polling_thread(is_running: Arc<AtomicBool>,
                            poll_interval: Option<u64>,
                            timeout: Option<i32>,
                            network_delay: Option<i32>,
                            bot: Arc<bot::Bot>,
                            tx: mpsc::Sender<Update>) {
        let poll_interval = time::Duration::from_secs(poll_interval.unwrap_or(0));
        let mut last_update_id = 0;

        while is_running.load(Ordering::SeqCst) {
            let updates = bot.get_updates(last_update_id, None, timeout, network_delay);

            match updates {
                Ok(Some(ref v)) => {
                    if let Some(u) = v.last() {
                        println!("There is an update!");
                        for update in v {
                            tx.send(update.clone()).unwrap();
                        }
                        last_update_id = (u.update_id + 1) as i32;
                    } else {
                        println!("There is no update!");
                        // Do nothing, the vector is empty
                        continue;
                    }
                }
                Ok(None) => {
                    println!("There is nothing update!");
                    // Do nothing, we have nothing
                    continue;
                }
                Err(err) => {
                    println!("There is an error!");
                    // Handle error
                    continue;
                }
            };

            thread::sleep(poll_interval);
        }
    }
}
<|endoftext|>