<commit_before>//! Handlers
//!  - Endpoint handlers
//!
use std::io::{self, Read, Write};
use std::path::PathBuf;
use std::ffi::OsStr;
use std::fs;
use std::env;
use std::time as std_time;
use std::fmt;
use std::thread;

use reqwest;
use url::Url;
use iron::prelude::*;
use iron::{self, status, modifiers, Handler};
use router::Router;
use params::Params;
use mime;
use chrono::{self, UTC};

use service::{Cache, Record};
use errors::*;

lazy_static! {
    static ref STATIC_ROOT: PathBuf = {
        let mut root = env::current_dir().expect("Failed to get the current directory");
        root.push("static/badges");
        root
    };
    static ref CACHE_LIFESPAN: chrono::Duration = chrono::Duration::seconds(43200);  // 43200s == 12hrs
    static ref CLEAN_INTERVAL: std_time::Duration = std_time::Duration::new(3600, 0);
    static ref SVG: mime::Mime = "image/svg+xml".parse().expect("failed parsing svg mimetype");
    static ref PNG: mime::Mime = "image/png".parse().expect("failed parsing png mimetype");
    static ref JPG: mime::Mime = "image/jpg".parse().expect("failed parsing jpg mimetype");
    static ref JSON: mime::Mime = "application/json".parse().expect("failed parsing json mimetype");
}

/// Badge type represents a `crate` badge or a generic customizable `label` badge
enum Badge {
    Crate,
    Label,
}
impl fmt::Display for Badge {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        use self::Badge::*;
        match *self {
            Crate => write!(f, "crate"),
            Label => write!(f, "label"),
        }
    }
}

/// `Url::parse_with_params` expects `&[(k, v), ...]`
type UrlParams = Vec<(String, String)>;

/// Cleans up the cache, deleting any expired files.
///
/// Errors:
///     * Unable to acquire mutex lock
fn wait_and_clear(wait_dur: &std_time::Duration, cache: &Cache) -> Result<usize> {
    thread::sleep(*wait_dur);
    let n_removed = {
        let mut cache = cache.lock().map_err(|e| Error::Msg(format!("[Cleaner] Error obtaining cache lock: {}", e)))?;
        let stale: Vec<String> = cache.iter().fold(vec![], |mut stale, (key, record)| {
            if let Some(ref record) = *record {
                // collect stale keys & delete files
                if UTC::now().signed_duration_since(record.last_refresh) > *CACHE_LIFESPAN {
                    stale.push(key.clone());
                    // ignore failed deletions, file may be missing, any skipped files will
                    // be cleaned up by the occasional cron
                    let _ = fs::remove_file(record.path_buf.clone());
                }
            }
            stale
        });
        for key in &stale {
            cache.remove(key);
        }
        stale.len()
    };
    Ok(n_removed)
}

/// Initialize a cleaning thread with cache access
pub fn init_cleaner(cache: Cache) {
    thread::spawn(move ||{
        let mut wait_dur = *CLEAN_INTERVAL;
        loop {
            match wait_and_clear(&wait_dur, &cache) {
                Ok(n) => {
                    wait_dur = *CLEAN_INTERVAL;
                    println!("[Cleaner]: Cleaned and deleted {} stale records", n);
                }
                Err(e) =>  {
                    // cleaner couldn't get a mutex lock, try again in a couple seconds
                    println!("[Cleaner]: {}", e);
                    wait_dur = std_time::Duration::new(30, 0);
                }
            }
        }
    });
}

/// Returns an appropriate mime type per file extension
fn mime_from_filetype(filetype: &str) -> Result<mime::Mime> {
    Ok(match filetype {
        "svg" => SVG.clone(),
        "png" => PNG.clone(),
        "jpg" => JPG.clone(),
        "json" => JSON.clone(),
        _ => return Err(Error::Nil),
    })
}

/// Downloads a fresh badge from shields.io and saves it to `badge_path`
/// Returns the contents of the downloaded file.
///
/// Errors:
///     * Url parse errors from generating a new shields.io url with querystring
///     * Network errors from reqwest
///     * Io errors from copying badge content or writing it to file
fn fetch_badge(badge_type: &Badge, badge_path: &PathBuf, name: &str, filetype: &str, params: &UrlParams) -> Result<Vec<u8>> {
    println!("[LOG]: fetching fresh badge ({}) -> {:?}", badge_type, badge_path);
    let url = match *badge_type {
        Badge::Crate => format!("https://img.shields.io/crates/v/{}.{}", name, filetype),
        Badge::Label => format!("https://img.shields.io/badge/{}.{}", name, filetype),
    };
    let url = Url::parse_with_params(&url, params)?;

    let mut client = reqwest::Client::new()?;
    client.timeout(std_time::Duration::new(3, 0));
    let mut resp = client.get(url.as_str())
        .form(params)
        .send()?;

    let mut bytes = Vec::new();
    io::copy(&mut resp, &mut bytes)?;

    let mut file = fs::File::create(badge_path)?;
    file.write_all(&bytes)?;

    Ok(bytes)
}

/// Create a new `PathBuf` for the given badge parameters in the `STATIC_ROOT`
fn create_badge_path(badge_type: &Badge, badge_key: &str, filetype: &str) -> PathBuf {
    let filename = format!("{}__{}.{}", badge_type, badge_key, filetype);
    let mut badge_path = PathBuf::from(&*STATIC_ROOT);
    badge_path.push(filename);
    badge_path
}

/// Returns bytes of the requested badge
/// Tries to find a cached file, falls back to fetching a fresh badge from shields.io
///
/// Errors:
///     * Io/Url/Reqwest errors from `fetch_badge`
fn get_badge(cache: Cache, badge_type: &Badge, name: &str, filetype: &str, params: &UrlParams) -> Result<Vec<u8>> {
    // build key for the cache and filename
    let mut s = String::from(name);
    s.push('_');
    s.push_str(filetype);
    let badge_key = params.iter().fold(s, |mut s, &(ref k, ref v)| {
        s.push('_');
        s.push_str(k);
        s.push('_');
        s.push_str(v);
        s
    });

    let mut cache = cache.lock().map_err(|e| Error::Msg(format!("Error acquiring mutex lock: {}", e)))?;

    let record = cache.entry(badge_key.clone()).or_insert(None);
    let mut new_record = None;
    let bytes = match *record {
        None => {
            // No cached `Record` found
            let new_badge_path = create_badge_path(badge_type, &badge_key, filetype);
            new_record = Some(Record::from_path_buf(&new_badge_path));
            fetch_badge(badge_type, &new_badge_path, name, filetype, params)
        }
        Some(ref r) => {
            // cached `Record` found
            if UTC::now().signed_duration_since(r.last_refresh) > *CACHE_LIFESPAN {
                // content is expired
                new_record = Some(Record::from_path_buf(&r.path_buf));
                fetch_badge(badge_type, &r.path_buf, name, filetype, params)
            } else {
                // content is still valid
                fs::File::open(&r.path_buf).and_then(|mut file| {
                    let mut bytes = Vec::new();
                    file.read_to_end(&mut bytes)?;
                    Ok(bytes)
                }).or_else(|_| {
                    // cached file is missing
                    new_record = Some(Record::from_path_buf(&r.path_buf));
                    fetch_badge(badge_type, &r.path_buf, name, filetype, params)
                })
            }
        }
    };
    if let Some(new_record) = new_record {
        *record = Some(new_record);
    }
    bytes
}

/// Returns the contents of a request badge defined by its `badge_type`, `name`,
/// and modifying `params`
/// If something goes wrong when loading/fetching bytes, redirects to shields.io
fn badge_or_redirect(badge_type: &Badge, name: &str, params: &UrlParams, cache: Cache) -> IronResult<Response> {
    let name = PathBuf::from(name);
    let filetype = name.extension().and_then(OsStr::to_str).unwrap_or("svg");
    let name = name.file_stem().and_then(OsStr::to_str).expect("Failed to extract filename");

    let mimetype = match mime_from_filetype(filetype) {
        Ok(m) => m,
        Err(_) => return Ok(Response::with((status::BadRequest, format!("Invalid filetype: {}. Accepted: [svg, png, jpg, json]", filetype)))),
    };
    match get_badge(cache, badge_type, name, filetype, params) {
        Err(_) => {
            // Failed to fetch a cached or fresh version, redirect to shields.io
            let url = match *badge_type {
                Badge::Crate => format!("https://img.shields.io/crates/v/{}.{}", name, filetype),
                Badge::Label => format!("https://img.shields.io/badge/{}.{}", name, filetype),
            };
            let url = Url::parse_with_params(&url, params).expect("invalid params");
            let url = iron::Url::from_generic_url(url).unwrap();
            Ok(Response::with((status::Found, modifiers::Redirect(url))))
        }
        Ok(bytes) => {
            Ok(Response::with((mimetype, status::Ok, bytes)))
        }
    }

}

#[derive(Clone)]
/// handle requests for
/// - /crate/:cratename
/// - /crates/v/:cratename
/// - /badge/:badgeinfo
pub struct BadgeHandler {
    cache: Cache,
}
impl Handler for BadgeHandler {
    fn handle(&self, req: &mut Request) -> IronResult<Response> {
        let (badge_type, name) = {
            let router_params = req.extensions.get::<Router>().expect("failed to extract router params");
            if let Some(crate_name) = router_params.find("cratename") {
                (Badge::Crate, crate_name.to_string())
            } else if let Some(badge_name) = router_params.find("badgeinfo") {
                (Badge::Label, badge_name.to_string())
            } else {
                unreachable!()
            }
        };
        let params = req.get_ref::<Params>().unwrap()
            .to_strict_map::<String>().unwrap();
        let params: UrlParams = params.iter().map(|(k, v)| (k.to_string(), v.to_string())).collect();

        badge_or_redirect(&badge_type, &name, &params, self.cache.clone())
    }
}

/// Collection of `struct`s that `impl` `iron::Handler`
pub struct Handlers {
    pub badge_handler: BadgeHandler,
}

/// Return `Handlers` initialized with `Cache` access
pub fn initialize(cache: Cache) -> Handlers {
    Handlers {
        badge_handler: BadgeHandler { cache: cache.clone() },
    }
}
<commit_msg>check shields.io response status<commit_after>//! Handlers
//!  - Endpoint handlers
//!
use std::io::{self, Read, Write};
use std::path::PathBuf;
use std::ffi::OsStr;
use std::fs;
use std::env;
use std::time as std_time;
use std::fmt;
use std::thread;

use reqwest;
use url::Url;
use iron::prelude::*;
use iron::{self, status, modifiers, Handler};
use router::Router;
use params::Params;
use mime;
use chrono::{self, UTC};

use service::{Cache, Record};
use errors::*;

lazy_static! {
    static ref STATIC_ROOT: PathBuf = {
        let mut root = env::current_dir().expect("Failed to get the current directory");
        root.push("static/badges");
        root
    };
    static ref CACHE_LIFESPAN: chrono::Duration = chrono::Duration::seconds(43200);  // 43200s == 12hrs
    static ref CLEAN_INTERVAL: std_time::Duration = std_time::Duration::new(3600, 0);
    static ref SVG: mime::Mime = "image/svg+xml".parse().expect("failed parsing svg mimetype");
    static ref PNG: mime::Mime = "image/png".parse().expect("failed parsing png mimetype");
    static ref JPG: mime::Mime = "image/jpg".parse().expect("failed parsing jpg mimetype");
    static ref JSON: mime::Mime = "application/json".parse().expect("failed parsing json mimetype");
}

/// Badge type represents a `crate` badge or a generic customizable `label` badge
enum Badge {
    Crate,
    Label,
}
impl fmt::Display for Badge {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        use self::Badge::*;
        match *self {
            Crate => write!(f, "crate"),
            Label => write!(f, "label"),
        }
    }
}

/// `Url::parse_with_params` expects `&[(k, v), ...]`
type UrlParams = Vec<(String, String)>;

/// Cleans up the cache, deleting any expired files.
///
/// Errors:
///     * Unable to acquire mutex lock
fn wait_and_clear(wait_dur: &std_time::Duration, cache: &Cache) -> Result<usize> {
    thread::sleep(*wait_dur);
    let n_removed = {
        let mut cache = cache.lock().map_err(|e| Error::Msg(format!("[Cleaner] Error obtaining cache lock: {}", e)))?;
        let stale: Vec<String> = cache.iter().fold(vec![], |mut stale, (key, record)| {
            if let Some(ref record) = *record {
                // collect stale keys & delete files
                if UTC::now().signed_duration_since(record.last_refresh) > *CACHE_LIFESPAN {
                    stale.push(key.clone());
                    // ignore failed deletions, file may be missing, any skipped files will
                    // be cleaned up by the occasional cron
                    let _ = fs::remove_file(record.path_buf.clone());
                }
            }
            stale
        });
        for key in &stale {
            cache.remove(key);
        }
        stale.len()
    };
    Ok(n_removed)
}

/// Initialize a cleaning thread with cache access
pub fn init_cleaner(cache: Cache) {
    thread::spawn(move ||{
        let mut wait_dur = *CLEAN_INTERVAL;
        loop {
            match wait_and_clear(&wait_dur, &cache) {
                Ok(n) => {
                    wait_dur = *CLEAN_INTERVAL;
                    println!("[Cleaner]: Cleaned and deleted {} stale records", n);
                }
                Err(e) =>  {
                    // cleaner couldn't get a mutex lock, try again in a couple seconds
                    println!("[Cleaner]: {}", e);
                    wait_dur = std_time::Duration::new(30, 0);
                }
            }
        }
    });
}

/// Returns an appropriate mime type per file extension
fn mime_from_filetype(filetype: &str) -> Result<mime::Mime> {
    Ok(match filetype {
        "svg" => SVG.clone(),
        "png" => PNG.clone(),
        "jpg" => JPG.clone(),
        "json" => JSON.clone(),
        _ => return Err(Error::Nil),
    })
}

/// Downloads a fresh badge from shields.io and saves it to `badge_path`
/// Returns the contents of the downloaded file.
///
/// Errors:
///     * Url parse errors from generating a new shields.io url with querystring
///     * Network errors from reqwest
///     * Io errors from copying badge content or writing it to file
fn fetch_badge(badge_type: &Badge, badge_path: &PathBuf, name: &str, filetype: &str, params: &UrlParams) -> Result<Vec<u8>> {
    println!("[LOG]: fetching fresh badge ({}) -> {:?}", badge_type, badge_path);
    let url = match *badge_type {
        Badge::Crate => format!("https://img.shields.io/crates/v/{}.{}", name, filetype),
        Badge::Label => format!("https://img.shields.io/badge/{}.{}", name, filetype),
    };
    let url = Url::parse_with_params(&url, params)?;

    let mut client = reqwest::Client::new()?;
    client.timeout(std_time::Duration::new(3, 0));
    let mut resp = client.get(url.as_str())
        .form(params)
        .send()?;

    if !resp.status().is_success() { return Err(Error::Msg(format!("HTTP request not successful, status: {}", resp.status()))) }

    let mut bytes = Vec::new();
    io::copy(&mut resp, &mut bytes)?;

    let mut file = fs::File::create(badge_path)?;
    file.write_all(&bytes)?;

    Ok(bytes)
}

/// Create a new `PathBuf` for the given badge parameters in the `STATIC_ROOT`
fn create_badge_path(badge_type: &Badge, badge_key: &str, filetype: &str) -> PathBuf {
    let filename = format!("{}__{}.{}", badge_type, badge_key, filetype);
    let mut badge_path = PathBuf::from(&*STATIC_ROOT);
    badge_path.push(filename);
    badge_path
}

/// Returns bytes of the requested badge
/// Tries to find a cached file, falls back to fetching a fresh badge from shields.io
///
/// Errors:
///     * Io/Url/Reqwest errors from `fetch_badge`
fn get_badge(cache: Cache, badge_type: &Badge, name: &str, filetype: &str, params: &UrlParams) -> Result<Vec<u8>> {
    // build key for the cache and filename
    let mut s = String::from(name);
    s.push('_');
    s.push_str(filetype);
    let badge_key = params.iter().fold(s, |mut s, &(ref k, ref v)| {
        s.push('_');
        s.push_str(k);
        s.push('_');
        s.push_str(v);
        s
    });

    let mut cache = cache.lock().map_err(|e| Error::Msg(format!("Error acquiring mutex lock: {}", e)))?;

    let record = cache.entry(badge_key.clone()).or_insert(None);
    let mut new_record = None;
    let bytes = match *record {
        None => {
            // No cached `Record` found
            let new_badge_path = create_badge_path(badge_type, &badge_key, filetype);
            new_record = Some(Record::from_path_buf(&new_badge_path));
            fetch_badge(badge_type, &new_badge_path, name, filetype, params)
        }
        Some(ref r) => {
            // cached `Record` found
            if UTC::now().signed_duration_since(r.last_refresh) > *CACHE_LIFESPAN {
                // content is expired
                new_record = Some(Record::from_path_buf(&r.path_buf));
                fetch_badge(badge_type, &r.path_buf, name, filetype, params)
            } else {
                // content is still valid
                fs::File::open(&r.path_buf).and_then(|mut file| {
                    let mut bytes = Vec::new();
                    file.read_to_end(&mut bytes)?;
                    Ok(bytes)
                }).or_else(|_| {
                    // cached file is missing
                    new_record = Some(Record::from_path_buf(&r.path_buf));
                    fetch_badge(badge_type, &r.path_buf, name, filetype, params)
                })
            }
        }
    };
    if let Some(new_record) = new_record {
        *record = Some(new_record);
    }
    bytes
}

/// Returns the contents of a request badge defined by its `badge_type`, `name`,
/// and modifying `params`
/// If something goes wrong when loading/fetching bytes, redirects to shields.io
fn badge_or_redirect(badge_type: &Badge, name: &str, params: &UrlParams, cache: Cache) -> IronResult<Response> {
    let name = PathBuf::from(name);
    let filetype = name.extension().and_then(OsStr::to_str).unwrap_or("svg");
    let name = name.file_stem().and_then(OsStr::to_str).expect("Failed to extract filename");

    let mimetype = match mime_from_filetype(filetype) {
        Ok(m) => m,
        Err(_) => return Ok(Response::with((status::BadRequest, format!("Invalid filetype: {}. Accepted: [svg, png, jpg, json]", filetype)))),
    };
    match get_badge(cache, badge_type, name, filetype, params) {
        Err(_) => {
            // Failed to fetch a cached or fresh version, redirect to shields.io
            let url = match *badge_type {
                Badge::Crate => format!("https://img.shields.io/crates/v/{}.{}", name, filetype),
                Badge::Label => format!("https://img.shields.io/badge/{}.{}", name, filetype),
            };
            let url = Url::parse_with_params(&url, params).expect("invalid params");
            let url = iron::Url::from_generic_url(url).unwrap();
            Ok(Response::with((status::Found, modifiers::Redirect(url))))
        }
        Ok(bytes) => {
            Ok(Response::with((mimetype, status::Ok, bytes)))
        }
    }

}

#[derive(Clone)]
/// handle requests for
/// - /crate/:cratename
/// - /crates/v/:cratename
/// - /badge/:badgeinfo
pub struct BadgeHandler {
    cache: Cache,
}
impl Handler for BadgeHandler {
    fn handle(&self, req: &mut Request) -> IronResult<Response> {
        let (badge_type, name) = {
            let router_params = req.extensions.get::<Router>().expect("failed to extract router params");
            if let Some(crate_name) = router_params.find("cratename") {
                (Badge::Crate, crate_name.to_string())
            } else if let Some(badge_name) = router_params.find("badgeinfo") {
                (Badge::Label, badge_name.to_string())
            } else {
                unreachable!()
            }
        };
        let params = req.get_ref::<Params>().unwrap()
            .to_strict_map::<String>().unwrap();
        let params: UrlParams = params.iter().map(|(k, v)| (k.to_string(), v.to_string())).collect();

        badge_or_redirect(&badge_type, &name, &params, self.cache.clone())
    }
}

/// Collection of `struct`s that `impl` `iron::Handler`
pub struct Handlers {
    pub badge_handler: BadgeHandler,
}

/// Return `Handlers` initialized with `Cache` access
pub fn initialize(cache: Cache) -> Handlers {
    Handlers {
        badge_handler: BadgeHandler { cache: cache.clone() },
    }
}
<|endoftext|>


<commit_before>use connection::Connection;
use libproto::blockchain::{Block, Status};
use libproto::router::{MsgType, RoutingKey, SubModules};
use libproto::{Message, OperateType, SyncRequest, SyncResponse};
use protobuf::RepeatedField;
use rand::{thread_rng, Rng, ThreadRng};
use std::collections::{BTreeMap, VecDeque};
use std::convert::{Into, TryFrom, TryInto};
use std::sync::{mpsc, Arc};
use std::time::{Duration, Instant};
use std::u8;
use Source;

const SYNC_STEP: u64 = 200;
const SYNC_TIME_OUT: u64 = 60;

/// Get messages and determine if need to synchronize or broadcast the current node status
pub struct Synchronizer {
    tx_pub: mpsc::Sender<(String, Vec<u8>)>,
    con: Arc<Connection>,
    current_status: Status,
    global_status: Status,
    sync_end_height: u64, //current_status <= sync_end_status
    is_synchronizing: bool,
    latest_status_lists: BTreeMap<u64, VecDeque<u32>>,
    block_lists: BTreeMap<u64, Block>,
    rand: ThreadRng,
    remote_sync_time_out: Instant,
    /// local sync error
    local_sync_count: u8,
}

unsafe impl Sync for Synchronizer {}
unsafe impl Send for Synchronizer {}

impl Synchronizer {
    pub fn new(tx_pub: mpsc::Sender<(String, Vec<u8>)>, con: Arc<Connection>) -> Self {
        Synchronizer {
            tx_pub: tx_pub,
            con: con,
            current_status: Status::new(),
            global_status: Status::new(),
            latest_status_lists: BTreeMap::new(),
            sync_end_height: 0,
            is_synchronizing: true,
            block_lists: BTreeMap::new(),
            rand: thread_rng(),
            remote_sync_time_out: (Instant::now() - Duration::from_secs(SYNC_TIME_OUT)),
            local_sync_count: 0,
        }
    }

    /// After receiving the `Chain >> Status`, it is processed as follows:
    /// 1. The chain height suddenly becomes lower than the original,
    ///    which means that the library is deleted, that is,
    ///    the synchronization is restarted from the received height.
    /// 2. The height of the chain is greater than or equal to the original height,
    ///    less than or equal to the height that the network has synchronized
    ///        - It is equal to the original height more than 2 times, indicating that
    ///          the data in the chain or executor is lost, and the block information is
    ///          sent again from the buffer. If no buffer exists, the data is requested again from other nodes.
    ///        - When the maximum height of data has been synchronized, a synchronization
    ///          request is sent to other nodes to confirm that the current node has successfully
    ///          completed the data synchronization work.
    /// 3. The height is greater than the maximum height that has been synchronized, ie it is the latest data itself.
    pub fn update_current_status(&mut self, latest_status: Status) {
        debug!(
            "sync: update_current_status: current height = {}, \
             before height = {}, \
             sync_end_height = {}",
            latest_status.get_height(),
            self.current_status.get_height(),
            self.sync_end_height
        );
        let old_height = self.current_status.get_height();
        let new_height = latest_status.get_height();

        if new_height == old_height && self.local_sync_count < u8::MAX {
            // Chain height does not increase
            self.local_sync_count += 1;
        }

        self.latest_status_lists = self
            .latest_status_lists
            .split_off(&(latest_status.get_height() + 1));
        self.current_status = latest_status;
        self.broadcast_status();
        self.prune_block_list_cache(new_height + 1);

        if new_height < old_height {
            // Chain error, may be a problem with the database, such as the database was deleted
            self.is_synchronizing = true;
            let start_height = new_height + 1;

            if self.block_lists.contains_key(&start_height) && !self.block_lists.is_empty() {
                self.submit_blocks();
            } else {
                self.start_sync_req(start_height, 0);
            }
        } else if new_height <= self.sync_end_height {
            // In synchronization, or loss of sync data, need to resend
            debug!(
                "Syncing: update_current_status: height = {}, block_lists len = {}",
                new_height,
                self.block_lists.len()
            );

            if !self.block_lists.is_empty() && new_height < self.sync_end_height {
                if self.local_sync_count >= 3 {
                    // Chain height does not increase, must loss data, send cache to executor and chain
                    self.submit_blocks();
                    self.local_sync_count = 0;
                }
            } else {
                // If the block height is equal to the maximum height that has already been synchronized,
                // perform the synchronization operation first to see if it is the latest in the chain
                self.start_sync_req(new_height + 1, 0);
            }

            self.remote_sync_time_out = Instant::now();
            self.is_synchronizing = true;
        } else {
            // Greater than the last sync height, expressed as the latest height
            self.sync_end_height = self.current_status.get_height();
            self.is_synchronizing = false;
        }
    }

    pub fn update_global_status(&mut self, status: &Status, origin: u32) {
        debug!(
            "sync: update_global_status: current height = {}, from node = {}, height = {}",
            self.current_status.get_height(),
            origin,
            status.get_height()
        );
        let current_height = self.current_status.get_height();
        let old_global_status = self.global_status.clone();
        if self.global_status.get_height() < status.get_height() {
            self.global_status = status.clone();
        }

        if status.get_height() < current_height + 1 {
            // The current node is the latest height and does not need to be synchronized
            self.is_synchronizing = false;
        } else if status.get_height() == current_height + 1 {
            // A node on the chain blocks out, synchronizing the latest block
            self.add_latest_sync_lists(status.get_height(), origin);

            if self.global_status.get_height() > old_global_status.get_height()
                && self.is_synchronizing
            {
                self.start_sync_req(status.get_height(), status.get_height());
            } else {
                self.is_synchronizing = false;
            }
        } else {
            // The node is far behind the data on the chain and initiates a synchronization request
            self.add_latest_sync_lists(status.get_height(), origin);

            if self.remote_sync_time_out.elapsed().as_secs() > SYNC_TIME_OUT
                || !self.is_synchronizing
            {
                self.remote_sync_time_out = Instant::now();
                self.start_sync_req(current_height + 1, status.get_height());
            } else if self.global_status.get_height() > old_global_status.get_height()
                && self.is_synchronizing
            {
                self.start_sync_req(status.get_height(), status.get_height());
            }

            self.is_synchronizing = true;
        }
    }

    pub fn is_synchronizing(&self) -> bool {
        self.is_synchronizing
    }

    pub fn process_sync(&mut self, mut blocks: SyncResponse) {
        let blocks = blocks.take_blocks();
        debug!("sync: process_sync: blocks len = {}", blocks.len());

        let mut heights = vec![];
        for block in blocks.into_iter() {
            heights.push(block.get_header().get_height());
            self.block_lists
                .insert(block.get_header().get_height(), block);
        }

        debug!("sync: process_sync: heights = {:?}", heights);
        self.submit_blocks();
    }

    pub fn receive(&mut self, _from: Source, payload: (String, Vec<u8>)) {
        let (key, body) = payload;
        let mut msg = Message::try_from(&body).unwrap();
        let origin = msg.get_origin();
        match RoutingKey::from(&key) {
            routing_key!(Chain >> Status) => {
                if let Some(status) = msg.take_status() {
                    self.update_current_status(status);
                };
            }
            routing_key!(Synchronizer >> Status) => {
                if let Some(status) = msg.take_status() {
                    self.update_global_status(&status, origin);
                };
            }
            routing_key!(Synchronizer >> SyncResponse) => {
                if let Some(blocks) = msg.take_sync_response() {
                    self.process_sync(blocks);
                };
            }
            _ => {
                error!("receive: unexpected data key = {:?}", key);
            }
        }
    }

    // Initiate a sync request
    fn start_sync_req(&mut self, start_height: u64, end_height: u64) {
        debug!(
            "sync: start_sync_req: start_height = {}, end_height = {},current height = {}",
            start_height,
            end_height,
            self.current_status.get_height()
        );
        let mut origin = 0;
        let mut end_height = end_height;
        let mut is_send = false;

        if let Some((height, origins)) = self
            .latest_status_lists
            .iter()
            .rfind(|&(_, origins)| origins.len() >= (2 / (3 * self.con.peers_pair.read().len())))
        {
            debug!(
                "sync: start_sync_req: height = {}, origins = {:?}",
                height, origins
            );
            if let Some(origins) = self.latest_status_lists.get(height) {
                if *height > self.current_status.get_height() {
                    origin = origins[self.rand.gen_range(0, origins.len())];
                    if end_height == 0 {
                        end_height = *height + 1;
                    }
                    is_send = true;
                }
            }
        }

        if is_send {
            self.sync_strategy(start_height, end_height, origin);
        }
    }

    fn sync_strategy(&self, start_height: u64, end_height: u64, origin: u32) {
        //current height = 155,start_height = 156, end height = 160, to origin = 1
        debug!(
            "sync: sync_strategy: current height = {}, \
             start_height = {}, \
             end height = {}, \
             to origin = {}",
            self.current_status.get_height(),
            start_height,
            end_height,
            origin
        );
        if start_height >= self.current_status.get_height() && start_height <= end_height {
            let mut start_height = start_height;
            let mut step_sum = SYNC_STEP;
            let mut heights = vec![];

            while start_height <= end_height {
                if step_sum == 0 {
                    step_sum = SYNC_STEP;
                    self.send_sync_req(heights, origin);
                    heights = vec![];
                }
                heights.push(start_height);

                step_sum -= 1;
                start_height += 1;
            }
            self.send_sync_req(heights, origin);
        }
    }

    fn send_sync_req(&self, heights: Vec<u64>, origin: u32) {
        if !heights.is_empty() {
            debug!(
                "sync: send_sync_req:current height = {}, \
                 heights = {:?}, \
                 origin {:?}, \
                 chain.sync: OperateType {:?}",
                self.current_status.get_height(),
                heights,
                origin,
                OperateType::Single
            );
            let mut sync_req = SyncRequest::new();
            sync_req.set_heights(heights);
            let msg = Message::init(OperateType::Single, origin, sync_req.into());
            self.con
                .broadcast(routing_key!(Synchronizer >> SyncRequest).into(), msg);
        }
    }

    fn broadcast_status(&mut self) {
        debug!(
            "sync: broadcast status {:?}, {:?} to other nodes",
            self.current_status.get_height(),
            self.current_status.get_hash()
        );
        let msg: Message = self.current_status.clone().into();
        self.con
            .broadcast(routing_key!(Synchronizer >> Status).into(), msg);
    }

    // Submit synchronization information
    fn submit_blocks(&mut self) {
        let mut height = self.current_status.get_height() + 1;
        debug!(
            "sync: submit_blocks:submit_height = {},\
             current height = {},\
             sync_end_height = {},\
             block_lists = {}",
            height,
            self.current_status.get_height(),
            self.sync_end_height,
            self.block_lists.len()
        );
        let mut blocks = vec![];
        let end_height = height + SYNC_STEP;

        loop {
            if height <= end_height {
                if let Some(block) = self.block_lists.get(&height) {
                    blocks.push(block.to_owned());
                } else {
                    break;
                }
            } else {
                break;
            }
            height += 1;
        }

        match blocks.last() {
            Some(block) => {
                if let Some(header) = block.header.as_ref() {
                    let height = header.get_height();

                    if height > self.sync_end_height {
                        self.sync_end_height = height;
                    }
                }
            }
            None => {}
        }

        if self.block_lists.contains_key(&::std::u64::MAX) {
            blocks.push(self.block_lists.remove(&::std::u64::MAX).unwrap());
        }

        self.pub_blocks(blocks);
    }

    fn pub_blocks(&mut self, blocks: Vec<Block>) {
        if !blocks.is_empty() {
            debug!(
                "sync: pub_blocks: current height = {}, \
                 sync_end_height = {}, \
                 len = {}, ",
                self.current_status.get_height(),
                self.sync_end_height,
                blocks.len()
            );
            let mut sync_res = SyncResponse::new();
            sync_res.set_blocks(RepeatedField::from_vec(blocks));
            let msg: Message = sync_res.into();
            self.tx_pub.send((
                routing_key!(Net >> SyncResponse).into(),
                msg.try_into().unwrap(),
            ));
        }
    }

    fn add_latest_sync_lists(&mut self, height: u64, origin: u32) {
        debug!(
            "sync: add_sync_lists: current height = {}, \
             from node = {}, \
             height = {}",
            self.current_status.get_height(),
            origin,
            height
        );
        self.latest_status_lists
            .entry(height)
            .or_insert_with(VecDeque::new)
            .push_back(origin);
    }

    /// Prune block on btreemap
    fn prune_block_list_cache(&mut self, height: u64) {
        self.block_lists = self.block_lists.split_off(&height);
    }
}
<commit_msg>fix network sync<commit_after>use connection::Connection;
use libproto::blockchain::{Block, Status};
use libproto::router::{MsgType, RoutingKey, SubModules};
use libproto::{Message, OperateType, SyncRequest, SyncResponse};
use protobuf::RepeatedField;
use rand::{thread_rng, Rng, ThreadRng};
use std::collections::{BTreeMap, HashSet, VecDeque};
use std::convert::{Into, TryFrom, TryInto};
use std::sync::{mpsc, Arc};
use std::time::{Duration, Instant};
use std::u8;
use Source;

const SYNC_STEP: u64 = 200;
const SYNC_TIME_OUT: u64 = 60;

/// Get messages and determine if need to synchronize or broadcast the current node status
pub struct Synchronizer {
    tx_pub: mpsc::Sender<(String, Vec<u8>)>,
    con: Arc<Connection>,
    current_status: Status,
    global_status: Status,
    sync_end_height: u64, //current_status <= sync_end_status
    is_synchronizing: bool,
    latest_status_lists: BTreeMap<u64, VecDeque<u32>>,
    block_lists: BTreeMap<u64, Block>,
    rand: ThreadRng,
    remote_sync_time_out: Instant,
    /// local sync error
    local_sync_count: u8,
}

unsafe impl Sync for Synchronizer {}
unsafe impl Send for Synchronizer {}

impl Synchronizer {
    pub fn new(tx_pub: mpsc::Sender<(String, Vec<u8>)>, con: Arc<Connection>) -> Self {
        Synchronizer {
            tx_pub: tx_pub,
            con: con,
            current_status: Status::new(),
            global_status: Status::new(),
            latest_status_lists: BTreeMap::new(),
            sync_end_height: 0,
            is_synchronizing: true,
            block_lists: BTreeMap::new(),
            rand: thread_rng(),
            remote_sync_time_out: (Instant::now() - Duration::from_secs(SYNC_TIME_OUT)),
            local_sync_count: 0,
        }
    }

    /// After receiving the `Chain >> Status`, it is processed as follows:
    /// 1. The chain height suddenly becomes lower than the original,
    ///    which means that the library is deleted, that is,
    ///    the synchronization is restarted from the received height.
    /// 2. The height of the chain is greater than or equal to the original height,
    ///    less than or equal to the height that the network has synchronized
    ///        - It is equal to the original height more than 2 times, indicating that
    ///          the data in the chain or executor is lost, and the block information is
    ///          sent again from the buffer. If no buffer exists, the data is requested again from other nodes.
    ///        - When the maximum height of data has been synchronized, a synchronization
    ///          request is sent to other nodes to confirm that the current node has successfully
    ///          completed the data synchronization work.
    /// 3. The height is greater than the maximum height that has been synchronized, ie it is the latest data itself.
    pub fn update_current_status(&mut self, latest_status: Status) {
        debug!(
            "sync: update_current_status: current height = {}, \
             before height = {}, \
             sync_end_height = {}",
            latest_status.get_height(),
            self.current_status.get_height(),
            self.sync_end_height
        );
        let old_height = self.current_status.get_height();
        let new_height = latest_status.get_height();

        if new_height == old_height && self.local_sync_count < u8::MAX {
            // Chain height does not increase
            self.local_sync_count += 1;
        }

        self.latest_status_lists = self
            .latest_status_lists
            .split_off(&(latest_status.get_height() + 1));
        self.current_status = latest_status;
        self.broadcast_status();
        self.prune_block_list_cache(new_height + 1);

        if new_height < old_height {
            // Chain error, may be a problem with the database, such as the database was deleted
            self.is_synchronizing = true;
            let start_height = new_height + 1;

            if self.block_lists.contains_key(&start_height) && !self.block_lists.is_empty() {
                self.submit_blocks();
            } else {
                self.start_sync_req(start_height, 0);
            }
        } else if new_height <= self.sync_end_height {
            // In synchronization, or loss of sync data, need to resend
            debug!(
                "Syncing: update_current_status: height = {}, block_lists len = {}",
                new_height,
                self.block_lists.len()
            );

            if !self.block_lists.is_empty() && new_height < self.sync_end_height {
                if self.local_sync_count >= 3 {
                    // Chain height does not increase, must loss data, send cache to executor and chain
                    self.submit_blocks();
                    self.local_sync_count = 0;
                }
            } else {
                // If the block height is equal to the maximum height that has already been synchronized,
                // perform the synchronization operation first to see if it is the latest in the chain
                self.start_sync_req(new_height + 1, 0);
            }

            self.remote_sync_time_out = Instant::now();
            self.is_synchronizing = true;
        } else {
            // Greater than the last sync height, expressed as the latest height
            self.sync_end_height = self.current_status.get_height();
            self.is_synchronizing = false;
        }
    }

    pub fn update_global_status(&mut self, status: &Status, origin: u32) {
        debug!(
            "sync: update_global_status: current height = {}, from node = {}, height = {}",
            self.current_status.get_height(),
            origin,
            status.get_height()
        );
        let current_height = self.current_status.get_height();
        let old_global_status = self.global_status.clone();
        if self.global_status.get_height() < status.get_height() {
            self.global_status = status.clone();
        }

        if status.get_height() < current_height + 1 {
            // The current node is the latest height and does not need to be synchronized
            self.is_synchronizing = false;
        } else if status.get_height() == current_height + 1 {
            // A node on the chain blocks out, synchronizing the latest block
            self.add_latest_sync_lists(status.get_height(), origin);

            if self.global_status.get_height() > old_global_status.get_height()
                && self.is_synchronizing
            {
                self.start_sync_req(status.get_height(), status.get_height());
            } else if self.global_status.get_height() == old_global_status.get_height() {
                if self.remote_sync_time_out.elapsed().as_secs() > SYNC_TIME_OUT {
                    self.remote_sync_time_out = Instant::now();
                    self.start_sync_req(current_height + 1, status.get_height());
                    self.is_synchronizing = true;
                }
            } else {
                self.is_synchronizing = false;
            }
        } else {
            // The node is far behind the data on the chain and initiates a synchronization request
            self.add_latest_sync_lists(status.get_height(), origin);

            if self.remote_sync_time_out.elapsed().as_secs() > SYNC_TIME_OUT
                || !self.is_synchronizing
            {
                self.remote_sync_time_out = Instant::now();
                self.start_sync_req(current_height + 1, status.get_height());
            } else if self.global_status.get_height() > old_global_status.get_height()
                && self.is_synchronizing
            {
                self.start_sync_req(status.get_height(), status.get_height());
            }

            self.is_synchronizing = true;
        }
    }

    pub fn is_synchronizing(&self) -> bool {
        self.is_synchronizing
    }

    pub fn process_sync(&mut self, mut blocks: SyncResponse) {
        let blocks = blocks.take_blocks();
        debug!("sync: process_sync: blocks len = {}", blocks.len());

        let mut heights = vec![];
        for block in blocks.into_iter() {
            heights.push(block.get_header().get_height());
            self.block_lists
                .insert(block.get_header().get_height(), block);
        }

        debug!("sync: process_sync: heights = {:?}", heights);
        self.submit_blocks();
    }

    pub fn receive(&mut self, _from: Source, payload: (String, Vec<u8>)) {
        let (key, body) = payload;
        let mut msg = Message::try_from(&body).unwrap();
        let origin = msg.get_origin();
        match RoutingKey::from(&key) {
            routing_key!(Chain >> Status) => {
                if let Some(status) = msg.take_status() {
                    self.update_current_status(status);
                };
            }
            routing_key!(Synchronizer >> Status) => {
                if let Some(status) = msg.take_status() {
                    self.update_global_status(&status, origin);
                };
            }
            routing_key!(Synchronizer >> SyncResponse) => {
                if let Some(blocks) = msg.take_sync_response() {
                    self.process_sync(blocks);
                };
            }
            _ => {
                error!("receive: unexpected data key = {:?}", key);
            }
        }
    }

    // Initiate a sync request
    fn start_sync_req(&mut self, start_height: u64, end_height: u64) {
        debug!(
            "sync: start_sync_req: start_height = {}, end_height = {},current height = {}",
            start_height,
            end_height,
            self.current_status.get_height()
        );
        let mut origin = 0;
        let mut end_height = end_height;
        let mut is_send = false;

        if let Some((height, origins)) = self
            .latest_status_lists
            .iter()
            .rfind(|&(_, origins)| origins.len() >= (2 / (3 * self.con.peers_pair.read().len())))
        {
            debug!(
                "sync: start_sync_req: height = {}, origins = {:?}",
                height, origins
            );
            if let Some(origins) = self.latest_status_lists.get(height) {
                if *height > self.current_status.get_height() {
                    origin = origins[self.rand.gen_range(0, origins.len())];
                    if end_height == 0 {
                        end_height = *height + 1;
                    }
                    is_send = true;
                }
            }
        }

        if is_send {
            self.sync_strategy(start_height, end_height, origin);
        }
    }

    fn sync_strategy(&self, start_height: u64, end_height: u64, origin: u32) {
        //current height = 155,start_height = 156, end height = 160, to origin = 1
        debug!(
            "sync: sync_strategy: current height = {}, \
             start_height = {}, \
             end height = {}, \
             to origin = {}",
            self.current_status.get_height(),
            start_height,
            end_height,
            origin
        );
        if start_height >= self.current_status.get_height() && start_height <= end_height {
            let mut start_height = start_height;
            let mut step_sum = SYNC_STEP;
            let mut heights = vec![];

            while start_height <= end_height {
                if step_sum == 0 {
                    step_sum = SYNC_STEP;
                    self.send_sync_req(heights, origin);
                    heights = vec![];
                }
                heights.push(start_height);

                step_sum -= 1;
                start_height += 1;
            }
            self.send_sync_req(heights, origin);
        }
    }

    fn send_sync_req(&self, heights: Vec<u64>, origin: u32) {
        if !heights.is_empty() {
            debug!(
                "sync: send_sync_req:current height = {}, \
                 heights = {:?}, \
                 origin {:?}, \
                 chain.sync: OperateType {:?}",
                self.current_status.get_height(),
                heights,
                origin,
                OperateType::Single
            );
            let mut sync_req = SyncRequest::new();
            sync_req.set_heights(heights);
            let msg = Message::init(OperateType::Single, origin, sync_req.into());
            self.con
                .broadcast(routing_key!(Synchronizer >> SyncRequest).into(), msg);
        }
    }

    fn broadcast_status(&mut self) {
        debug!(
            "sync: broadcast status {:?}, {:?} to other nodes",
            self.current_status.get_height(),
            self.current_status.get_hash()
        );
        let msg: Message = self.current_status.clone().into();
        self.con
            .broadcast(routing_key!(Synchronizer >> Status).into(), msg);
    }

    // Submit synchronization information
    fn submit_blocks(&mut self) {
        let mut height = self.current_status.get_height() + 1;
        debug!(
            "sync: submit_blocks:submit_height = {},\
             current height = {},\
             sync_end_height = {},\
             block_lists = {}",
            height,
            self.current_status.get_height(),
            self.sync_end_height,
            self.block_lists.len()
        );
        let mut blocks = vec![];
        let end_height = height + SYNC_STEP;

        loop {
            if height <= end_height {
                if let Some(block) = self.block_lists.get(&height) {
                    blocks.push(block.to_owned());
                } else {
                    break;
                }
            } else {
                break;
            }
            height += 1;
        }

        match blocks.last() {
            Some(block) => {
                if let Some(header) = block.header.as_ref() {
                    let height = header.get_height();

                    if height > self.sync_end_height {
                        self.sync_end_height = height;
                    }
                }
            }
            None => {}
        }

        if self.block_lists.contains_key(&::std::u64::MAX) {
            blocks.push(self.block_lists.remove(&::std::u64::MAX).unwrap());
        }

        self.pub_blocks(blocks);
    }

    fn pub_blocks(&mut self, blocks: Vec<Block>) {
        if !blocks.is_empty() {
            debug!(
                "sync: pub_blocks: current height = {}, \
                 sync_end_height = {}, \
                 len = {}, ",
                self.current_status.get_height(),
                self.sync_end_height,
                blocks.len()
            );
            let mut sync_res = SyncResponse::new();
            sync_res.set_blocks(RepeatedField::from_vec(blocks));
            let msg: Message = sync_res.into();
            self.tx_pub.send((
                routing_key!(Net >> SyncResponse).into(),
                msg.try_into().unwrap(),
            ));
        }
    }

    fn add_latest_sync_lists(&mut self, height: u64, origin: u32) {
        debug!(
            "sync: add_sync_lists: current height = {}, \
             from node = {}, \
             height = {}",
            self.current_status.get_height(),
            origin,
            height
        );
        if self
            .latest_status_lists
            .entry(height)
            .or_insert_with(VecDeque::new)
            .iter()
            .fold(HashSet::new(), |mut set, item| {
                set.insert(item);
                set
            })
            .insert(&origin)
        {
            self.latest_status_lists
                .entry(height)
                .or_insert_with(VecDeque::new)
                .push_back(origin);
        }
    }

    /// Prune block on btreemap
    fn prune_block_list_cache(&mut self, height: u64) {
        self.block_lists = self.block_lists.split_off(&height);
    }
}
<|endoftext|>


<commit_before>extern crate mio;
use getopts::{Options,Matches};
use std::io::{Read,BufStream,BufRead};
use std::old_io::{LineBufferedWriter,stdio};

use self::mio::*;
use self::mio::net::tcp::*;
use self::mio::buf::{ByteBuf};

const SERVER: Token = Token(1);
const CLIENT: Token = Token(2);

struct ServerHandler {
    conn: Option<NonBlock<TcpStream>>,
    sock: NonBlock<TcpListener>
}

impl ServerHandler {
    fn accept(&mut self, event_loop: &mut EventLoop<ServerHandler>) {
        match self.conn {
            Some(_) => {
                // already have connection, do nothing
            },
            None => {
                let conn = self.sock.accept();
                let stream = conn.unwrap().unwrap();
                self.conn = Some(stream);
                match self.conn {
                    Some(ref c) => {
                        event_loop.register(c, CLIENT);
                    },
                    None => { panic!("no ref??".to_string());
                    }
                }
            }
        }
    }
}

impl Handler for ServerHandler {
    type Timeout = usize;
    type Message = ();

    fn readable(&mut self, event_loop: &mut EventLoop<ServerHandler>, token: Token, _: ReadHint) {
        match token {
            SERVER => {
                // Call `accept` on our `tcp_handler`.
                self.accept(event_loop);
            },
            CLIENT => {
                let mut read_buf = ByteBuf::mut_with_capacity(2048);
                match self.conn {
                    Some(ref mut c) => {
                        match c.read(&mut read_buf) {
                            Ok(n) => {
                                // `_` would be the number of bytes read.
                                // `flip` will return a `ByteBuf` on which we can call
                                // `read_slice` to get the data available to be read.
                                // See http://carllerche.github.io/bytes/bytes/struct.ByteBuf.html
                                let mut buf = read_buf.flip();
                                let mut sl = [0; 2048];
                                buf.read_slice(&mut sl);
                                // Assuming what was written was encoded as UTF8, print what
                                // was read to STDOUT.
                                print!("{}", String::from_utf8(sl.to_vec()).unwrap());
                            }
                            Err(e) => {
                                // Probably because connection could not be established.
                                event_loop.shutdown();
                                panic!(e.to_string());
                            }
                        }
                    },
                    None => {
                        panic!("can't read".to_string());
                    }
                }
            },
            _ => {
                panic!("unexpected token".to_string());
            }
        }
    }
}

pub fn nc_listen(matches: &Matches) {
    // append port to localhost IP address
    let mut s = String::from_str("127.0.0.1:");
    s.push_str(matches.free[0].as_slice());
    let listener = TcpListener::bind(s.as_slice()).unwrap();
    // block until we get connection
    let mut writer = LineBufferedWriter::new(stdio::stdout());
    match listener.accept() {
        Ok((stream, socket_addr)) => {
            // nc doesn't handle multiple connections, so no need to do `handle_client`
            // in thread.
            handle_client(stream, &mut writer);
        },
        Err(f) => {
            panic!(f.to_string());
        }
    }
}

fn handle_client(stream: TcpStream, writer: &mut Writer) {
    let mut buf_stream = BufStream::new(stream);
    let mut read_buf = [0; 4096];
    loop {
        match(buf_stream.read(&mut read_buf)) {
            Ok(n) => {
                if n > 0 {
                    writer.write_all(&read_buf.slice_to(n)).unwrap();
                }
                else {
                    return;
                }
            }
            Err(f) => {
                panic!(f.to_string());
            }
        }
    }
}
<commit_msg>in listener, read from STDIN print to socket<commit_after>extern crate mio;
use getopts::{Options,Matches};
use std::io::{Read,BufStream,BufRead};
use std::old_io;

use self::mio::*;
use self::mio::net::tcp::*;
use self::mio::buf::{ByteBuf};

use std::net::{SocketAddr,ToSocketAddrs};
use std::str::FromStr;

use std::thread;

const SERVER: Token = Token(1);
const CLIENT: Token = Token(2);

struct ServerHandler {
    conn: Option<NonBlock<TcpStream>>,
    sock: NonBlock<TcpListener>
}

impl ServerHandler {
    fn accept(&mut self, event_loop: &mut EventLoop<ServerHandler>) {
        match self.conn {
            Some(_) => {
                // already have connection, do nothing
            },
            None => {
                let conn = self.sock.accept();
                let stream = conn.unwrap().unwrap();
                self.conn = Some(stream);
                match self.conn {
                    Some(ref c) => {
                        event_loop.register(c, CLIENT);
                    },
                    None => { panic!("no ref??".to_string());
                    }
                }
            }
        }
    }
}

impl Handler for ServerHandler {
    type Timeout = usize;
    type Message = String;

    fn readable(&mut self, event_loop: &mut EventLoop<ServerHandler>, token: Token, _: ReadHint) {
        match token {
            SERVER => {
                // Call `accept` on our `tcp_handler`.
                self.accept(event_loop);
            },
            CLIENT => {
                let mut read_buf = ByteBuf::mut_with_capacity(2048);
                match self.conn {
                    Some(ref mut c) => {
                        match c.read(&mut read_buf) {
                            Ok(n) => {
                                // `_` would be the number of bytes read.
                                // `flip` will return a `ByteBuf` on which we can call
                                // `read_slice` to get the data available to be read.
                                // See http://carllerche.github.io/bytes/bytes/struct.ByteBuf.html
                                let mut buf = read_buf.flip();
                                let mut sl = [0; 2048];
                                buf.read_slice(&mut sl);
                                // Assuming what was written was encoded as UTF8, print what
                                // was read to STDOUT.
                                print!("{}", String::from_utf8(sl.to_vec()).unwrap());
                            }
                            Err(e) => {
                                // Probably because connection could not be established.
                                event_loop.shutdown();
                                panic!(e.to_string());
                            }
                        }
                    },
                    None => {
                        panic!("can't read".to_string());
                    }
                }
            },
            _ => {
                panic!("unexpected token".to_string());
            }
        }
    }

    fn notify(&mut self, event_loop: &mut EventLoop<ServerHandler>, msg: String) {
        match self.conn {
            Some(ref mut c) => {
                c.write_slice(msg.as_bytes()).unwrap();
            },
            None => {
                panic!("??".to_string());
            }
        }
    }
}

pub fn nc_listen(matches: &Matches) {
    // append port to localhost IP address
    let mut s = String::from_str("127.0.0.1:");
    s.push_str(matches.free[0].as_slice());
    let addr: SocketAddr = FromStr::from_str(s.as_slice()).unwrap();

    println!("addr: {}", addr);
    let listener = v4().unwrap();
    listener.bind(&addr).unwrap();
    let listener = listener.listen(1).unwrap();

    let mut event_loop = EventLoop::new().unwrap();
    event_loop.register(&listener, SERVER).unwrap();

    let mut server_handler = ServerHandler {
        conn: None,
        sock: listener
    };

    let sender = event_loop.channel();
    thread::spawn(move || {
        readwrite_chan(&sender);
    });

    let _ = event_loop.run(&mut server_handler);
}

fn readwrite_chan(channel: &EventLoopSender<String>) {
    let mut stdin_reader = old_io::stdin();
    let mut read_buf = [0; 4096];
    loop {
        // Have to block here, so we can't immediately terminate if server closes socket.
        match stdin_reader.read(&mut read_buf) {
            Ok(n) => {
                let read = read_buf.slice_to(n);
                let byte_vec: Vec<u8> = read.to_vec();
                let message = String::from_utf8(byte_vec).unwrap();
                channel.send(message).unwrap();
            },
            Err(f) => {
                panic!(f.to_string());
            }
        }
    }
}
<|endoftext|>


<commit_before>extern crate bencode;

use self::bencode::{FromBencode, Bencode, StringFromBencodeError};
use self::bencode::util::ByteString;
use std::fs::File;
use std::io::Read;
use std::{convert, io};

#[derive(PartialEq, Debug)]
struct Metainfo {
    announce: String,
    created_by: String,
}

#[derive(Debug)]
enum MetainfoError {
    IoError(io::Error),
    DecodingError(bencode::streaming::Error),
    NotADict,
    DoesntContain(&'static str),
    NotAString(StringFromBencodeError),
}

impl convert::From<io::Error> for MetainfoError {
    fn from(err: io::Error) -> MetainfoError {
        MetainfoError::IoError(err)
    }
}

impl convert::From<bencode::streaming::Error> for MetainfoError {
    fn from(err: bencode::streaming::Error) -> MetainfoError {
        MetainfoError::DecodingError(err)
    }
}

impl convert::From<StringFromBencodeError> for MetainfoError {
    fn from(err: StringFromBencodeError) -> MetainfoError {
        MetainfoError::NotAString(err)
    }
}

impl FromBencode for Metainfo {
    type Err = MetainfoError;

    fn from_bencode(bencode: &bencode::Bencode) -> Result<Metainfo, MetainfoError> {
        match bencode {
            &Bencode::Dict(ref m) => {
                let announce = match m.get(&ByteString::from_str("announce")) {
                    Some(a) => try!(FromBencode::from_bencode(a)),
                    None => return Err(MetainfoError::DoesntContain("announce"))
                };

                let created_by = match m.get(&ByteString::from_str("created by")) {
                    Some(a) => try!(FromBencode::from_bencode(a)),
                    None => "".to_string()
                };

                Ok(Metainfo{ announce: announce, created_by: created_by })
            }
            _ => Err(MetainfoError::NotADict)
        }
    }
}

pub fn run() {
    let result = parse_torrent_file("test_data/flagfromserver.torrent");
    match result {
        Ok(s)  => println!("Yay, it worked: {:?}", s),
        Err(e) => println!("Oops, it failed: {:?}", e)
    }
}

fn parse_torrent_file(filename: &str) -> Result<Metainfo, MetainfoError> {
    // read the torrent file into a byte vector
    let mut f = try!(File::open(filename));
    let mut v = Vec::new();
    try!(f.read_to_end(&mut v));

    // decode the byte vector into a struct
    let bencode = try!(bencode::from_vec(v));
    let result = try!(FromBencode::from_bencode(&bencode));

    Ok(result)
}
<commit_msg>Cleanup.<commit_after>extern crate bencode;

use self::bencode::{FromBencode, Bencode, StringFromBencodeError};
use self::bencode::util::ByteString;
use std::fs::File;
use std::io::Read;
use std::{convert, io};

#[derive(PartialEq, Debug)]
struct Metainfo {
    announce: String,
    created_by: String,
}

impl FromBencode for Metainfo {
    type Err = MetainfoError;

    fn from_bencode(bencode: &bencode::Bencode) -> Result<Metainfo, MetainfoError> {
        match bencode {
            &Bencode::Dict(ref m) => {
                let announce = match m.get(&ByteString::from_str("announce")) {
                    Some(a) => try!(FromBencode::from_bencode(a)),
                    None => return Err(MetainfoError::DoesntContain("announce"))
                };

                let created_by = match m.get(&ByteString::from_str("created by")) {
                    Some(a) => try!(FromBencode::from_bencode(a)),
                    None => "".to_string()
                };

                Ok(Metainfo{ announce: announce, created_by: created_by })
            }
            _ => Err(MetainfoError::NotADict)
        }
    }
}

#[derive(Debug)]
enum MetainfoError {
    IoError(io::Error),
    DecodingError(bencode::streaming::Error),
    NotADict,
    DoesntContain(&'static str),
    NotAString(StringFromBencodeError),
}

impl convert::From<io::Error> for MetainfoError {
    fn from(err: io::Error) -> MetainfoError {
        MetainfoError::IoError(err)
    }
}

impl convert::From<bencode::streaming::Error> for MetainfoError {
    fn from(err: bencode::streaming::Error) -> MetainfoError {
        MetainfoError::DecodingError(err)
    }
}

impl convert::From<StringFromBencodeError> for MetainfoError {
    fn from(err: StringFromBencodeError) -> MetainfoError {
        MetainfoError::NotAString(err)
    }
}

pub fn run() {
    let result = parse_torrent_file("test_data/flagfromserver.torrent");
    match result {
        Ok(s)  => println!("Yay, it worked: {:?}", s),
        Err(e) => println!("Oops, it failed: {:?}", e)
    }
}

fn parse_torrent_file(filename: &str) -> Result<Metainfo, MetainfoError> {
    // read the torrent file into a byte vector
    let mut f = try!(File::open(filename));
    let mut v = Vec::new();
    try!(f.read_to_end(&mut v));

    // decode the byte vector into a struct
    let bencode = try!(bencode::from_vec(v));
    let result = try!(FromBencode::from_bencode(&bencode));

    Ok(result)
}
<|endoftext|>


<commit_before>extern crate gtk;

use gtk::prelude::*;
use gtk::{IconSize, Orientation, ReliefStyle, Widget};

struct Notebook {
    notebook: gtk::Notebook,
    tabs: Vec<gtk::Box>
}

impl Notebook {
    fn new() -> Notebook {
        Notebook {
            notebook: gtk::Notebook::new(),
            tabs: Vec::new()
        }
    }

    fn create_tab(&mut self, title: &str, widget: Widget) -> u32 {
        let close_image = gtk::Image::new_from_icon_name("window-close",
                                                         IconSize::Button.into());
        let button = gtk::Button::new();
        let label = gtk::Label::new(Some(title));
        let tab = gtk::Box::new(Orientation::Horizontal, 0);

        button.set_relief(ReliefStyle::None);
        button.set_focus_on_click(false);
        button.add(&close_image);

        tab.pack_start(&label, false, false, 0);
        tab.pack_start(&button, false, false, 0);
        tab.show_all();

        let index = self.notebook.append_page(&widget, Some(&tab));

        let notebook_clone = self.notebook.clone();
        button.connect_clicked(move |_| {
            let index = notebook_clone.page_num(&widget).unwrap();
            notebook_clone.remove_page(Some(index));
        });

        self.tabs.push(tab);

        index
    }
}

fn main() {
    if gtk::init().is_err() {
        println!("Failed to initialize GTK.");
        return;
    }

    let window = gtk::Window::new(gtk::WindowType::Toplevel);

    window.set_title("Notebook");
    window.set_position(gtk::WindowPosition::Center);
    window.set_default_size(640, 480);

    window.connect_delete_event(|_, _| {
        gtk::main_quit();
        Inhibit(false)
    });

    let mut notebook = Notebook::new();

    for i in 1..4 {
        let title = format!("sheet {}", i);
        let label = gtk::Label::new(Some(&title));
        notebook.create_tab(&title, label.upcast());
    }

    window.add(&notebook.notebook);
    window.show_all();
    gtk::main();
}

<commit_msg>Prepare for `Into<Option<&str>>`<commit_after>extern crate gtk;

use gtk::prelude::*;
use gtk::{IconSize, Orientation, ReliefStyle, Widget};

struct Notebook {
    notebook: gtk::Notebook,
    tabs: Vec<gtk::Box>
}

impl Notebook {
    fn new() -> Notebook {
        Notebook {
            notebook: gtk::Notebook::new(),
            tabs: Vec::new()
        }
    }

    fn create_tab(&mut self, title: &str, widget: Widget) -> u32 {
        let close_image = gtk::Image::new_from_icon_name("window-close",
                                                         IconSize::Button.into());
        let button = gtk::Button::new();
        let label = gtk::Label::new(title);
        let tab = gtk::Box::new(Orientation::Horizontal, 0);

        button.set_relief(ReliefStyle::None);
        button.set_focus_on_click(false);
        button.add(&close_image);

        tab.pack_start(&label, false, false, 0);
        tab.pack_start(&button, false, false, 0);
        tab.show_all();

        let index = self.notebook.append_page(&widget, Some(&tab));

        let notebook_clone = self.notebook.clone();
        button.connect_clicked(move |_| {
            let index = notebook_clone.page_num(&widget).unwrap();
            notebook_clone.remove_page(Some(index));
        });

        self.tabs.push(tab);

        index
    }
}

fn main() {
    if gtk::init().is_err() {
        println!("Failed to initialize GTK.");
        return;
    }

    let window = gtk::Window::new(gtk::WindowType::Toplevel);

    window.set_title("Notebook");
    window.set_position(gtk::WindowPosition::Center);
    window.set_default_size(640, 480);

    window.connect_delete_event(|_, _| {
        gtk::main_quit();
        Inhibit(false)
    });

    let mut notebook = Notebook::new();

    for i in 1..4 {
        let title = format!("sheet {}", i);
        let label = gtk::Label::new(&*title);
        notebook.create_tab(&title, label.upcast());
    }

    window.add(&notebook.notebook);
    window.show_all();
    gtk::main();
}

<|endoftext|>


<commit_before>/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

//! Servo's compiler plugin/macro crate
//!
//! Attributes this crate provides:
//!
//!  - `#[derive(DenyPublicFields)]` : Forces all fields in a struct/enum to be private
//!  - `#[derive(JSTraceable)]` : Auto-derives an implementation of `JSTraceable` for a struct in the script crate
//!  - `#[must_root]` : Prevents data of the marked type from being used on the stack.
//!                     See the lints module for more details
//!  - `#[dom_struct]` : Implies #[derive(JSTraceable, DenyPublicFields)]`, and `#[must_root]`.
//!                       Use this for structs that correspond to a DOM type

#![deny(unsafe_code)]
#![feature(box_syntax, plugin, plugin_registrar, rustc_private)]

#[macro_use]
extern crate rustc;
extern crate rustc_plugin;
extern crate syntax;

use rustc_plugin::Registry;
use syntax::feature_gate::AttributeType::Whitelisted;

mod unrooted_must_root;
/// Utilities for writing plugins
mod utils;

#[plugin_registrar]
pub fn plugin_registrar(reg: &mut Registry) {
    reg.register_late_lint_pass(box unrooted_must_root::UnrootedPass::new());
    reg.register_attribute("allow_unrooted_interior".to_string(), Whitelisted);
    reg.register_attribute("must_root".to_string(), Whitelisted);
}
<commit_msg>Split feature gates into lines for easy grepping<commit_after>/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

//! Servo's compiler plugin/macro crate
//!
//! Attributes this crate provides:
//!
//!  - `#[derive(DenyPublicFields)]` : Forces all fields in a struct/enum to be private
//!  - `#[derive(JSTraceable)]` : Auto-derives an implementation of `JSTraceable` for a struct in the script crate
//!  - `#[must_root]` : Prevents data of the marked type from being used on the stack.
//!                     See the lints module for more details
//!  - `#[dom_struct]` : Implies #[derive(JSTraceable, DenyPublicFields)]`, and `#[must_root]`.
//!                       Use this for structs that correspond to a DOM type

#![deny(unsafe_code)]
#![feature(box_syntax)]
#![feature(plugin)]
#![feature(plugin_registrar)]
#![feature(rustc_private)]

#[macro_use]
extern crate rustc;
extern crate rustc_plugin;
extern crate syntax;

use rustc_plugin::Registry;
use syntax::feature_gate::AttributeType::Whitelisted;

mod unrooted_must_root;
/// Utilities for writing plugins
mod utils;

#[plugin_registrar]
pub fn plugin_registrar(reg: &mut Registry) {
    reg.register_late_lint_pass(box unrooted_must_root::UnrootedPass::new());
    reg.register_attribute("allow_unrooted_interior".to_string(), Whitelisted);
    reg.register_attribute("must_root".to_string(), Whitelisted);
}
<|endoftext|>


<commit_before>//! Utilities for defining a JSON parser.

use util::Id;

use std::cell::RefCell;
use std::collections::{ HashMap, HashSet };
use std::error::Error as StdError;
use std::fmt::{ Display, Debug, Error as FmtError, Formatter };
use std::hash::Hash;
use std::rc::Rc;
use std::sync::Arc;

use serde_json::error;
use serde::ser::{ Serialize, Serializer };
use serde_json;
pub use serde_json::value::Value as JSON;
use serde::de::Error;

/// Utility function: Make sure that we have consumed all the fields of an object.
pub fn check_fields(path: Path, json: &JSON) -> Result<(), ParseError> {
    if let JSON::Object(ref obj) = *json {
        if obj.is_empty() {
            Ok(())
        } else {
            Err(ParseError::unknown_fields(obj.keys().cloned().collect(), &path))
        }
    } else {
        Ok(())
    }
}

/// A path in the JSON tree. Used for displaying error messages.
#[derive(Clone, Debug)]
pub struct Path {
    buf: Rc<RefCell<String>>,
    len: usize,
}
impl Path {
    /// Create an empty Path.
    pub fn new() -> Self {
        Path {
            buf: Rc::new(RefCell::new(String::new())),
            len: 0,
        }
    }

    /// Push a suffix after a path.
    pub fn push_str<F, T>(&self, suffix: &str, cb: F) -> T
        where F: FnOnce(Path) -> T
    {
        let buf = self.buf.clone();
        let len;
        {
            let mut str = buf.borrow_mut();
            str.push_str(suffix);
            len = str.len();
        }
        let path = Path {
            buf: buf,
            len: len,
        };
        let result = cb(path);
        {
            let mut str = self.buf.borrow_mut();
            str.truncate(self.len)
        }
        result
    }

    pub fn push_index<F, T>(&self, index: usize, cb: F) -> T
        where F: FnOnce(Path) -> T
    {
        self.push_str(&format!("[{}]", index), cb)
    }

    pub fn push<F, T>(&self, suffix: &str, cb: F) -> T
        where F: FnOnce(Path) -> T
    {
        self.push_str(&format!(".{}", suffix), cb)
    }

    pub fn to_string(&self) -> String {
        let mut str = self.buf.borrow().clone();
        str.truncate(self.len);
        str
    }
}

/// An error during parsing.
#[derive(Debug)]
pub enum ParseError {
    JSON(JSONError),
    MissingField {
        name: String,
        at: String,
    },
    UnknownFields {
        names: Vec<String>,
        at: String,
    },
    TypeError {
        name: String,
        at: String,
        expected: String,
    },
    EmptyObject {
        at: String
    },
    UnknownConstant {
        at: String,
        constant: String,
    }
}

impl Display for ParseError {
    fn fmt(&self, formatter: &mut Formatter) -> Result<(), FmtError> {
        (self as &Debug).fmt(formatter)
    }
}
impl StdError for ParseError {
    fn description(&self) -> &str {
        "Error while parsing to JSON"
    }
}

impl ParseError {
    pub fn missing_field(name: &str, at: &Path) -> Self {
        ParseError::MissingField {
            name: name.to_owned(),
            at: at.to_string(),
        }
    }
    pub fn type_error(name: &str, at: &Path, expected: &str) -> Self {
        ParseError::TypeError {
            name: name.to_owned(),
            at: at.to_string(),
            expected: expected.to_owned()
        }
    }
    pub fn unknown_fields(names: Vec<String>, at: &Path) -> Self {
        ParseError::UnknownFields {
            names: names,
            at: at.to_string()
        }
    }
    pub fn unknown_constant(value: &str, at: &Path) -> Self {
        ParseError::UnknownConstant {
            constant: value.to_owned(),
            at: at.to_string()
        }
    }
    pub fn empty_object(at: &Path) -> Self {
        ParseError::EmptyObject {
            at: at.to_string(),
        }
    }
    pub fn json(error: error::Error) -> Self {
        ParseError::JSON(JSONError(error))
    }
}

#[derive(Debug)]
pub struct JSONError(error::Error);

impl Serialize for JSONError {
    fn serialize<S>(&self, serializer: &mut S) -> Result<(), S::Error>
        where S: Serializer
    {
        serializer.serialize_str(&format!("{:?}", self))
    }
}

/// An object that knows how to parse values from JSON into type T.
///
/// The JSON object is expected to be consumed along the way. A successful parse will
/// typically leave an empty JSON object.
pub trait Parser<T: Sized> {
    fn description() -> String;
    fn from_str(source: &str) -> Result<T, ParseError> {
        match serde_json::from_str(source) {
            Err(err) => Err(ParseError::json(err)),
            Ok(mut json) => Self::parse(Path::new(), &mut json)
        }
    }

    /// Parse a single value from JSON, consuming as much as necessary from JSON.
    fn parse(path: Path, source: &mut JSON) -> Result<T, ParseError>;

    /// Parse a field from JSON, consuming it.
    fn take(path: Path, source: &mut JSON, field_name: &str) -> Result<T, ParseError> {
        match Self::take_opt(path.clone(), source, field_name) {
            Some(result) => result,
            None => Err(ParseError::missing_field(field_name, &path))
        }
    }

    /// Parse a field from JSON, consuming it.
    fn take_opt(path: Path, source: &mut JSON, field_name: &str) -> Option<Result<T, ParseError>> {
        if let JSON::Object(ref mut obj) = *source {
            if let Some(mut v) = obj.remove(field_name) {
                Some(Self::parse(path, &mut v))
            } else {
                None
            }
        } else {
            Some(Err(ParseError::type_error(field_name, &path, "object")))
        }
    }

    /// Parse a field containing an array from JSON, consuming the field.
    fn take_vec_opt(path: Path, source: &mut JSON, field_name: &str) -> Option<Result<Vec<T>, ParseError>>
    {
        if let JSON::Object(ref mut obj) = *source {
            if let Some(ref mut json) = obj.remove(field_name) {
                if let JSON::Array(ref mut vec) = *json {
                    let mut result = Vec::with_capacity(vec.len());
                    for (json, i) in vec.iter_mut().zip(0..) {
                        match path.push(&format!("[{}]", i),
                            |path| Self::parse(path, json)
                        ) {
                            Err(error) => return Some(Err(error)),
                            Ok(parsed) => result.push(parsed)
                        }
                    }
                    Some(Ok(result))
                } else {
                    Some(Err(ParseError::type_error(field_name, &path, "array")))
                }
            } else {
                None
            }
        } else {
            Some(Err(ParseError::missing_field(field_name, &path)))
        }
    }

    fn take_vec(path: Path, source: &mut JSON, field_name: &str) -> Result<Vec<T>, ParseError> {
        match Self::take_vec_opt(path.clone(), source, field_name) {
            Some(result) => result,
            None => Err(ParseError::missing_field(field_name, &path))
        }
    }
}

impl Parser<f64> for f64 {
    fn description() -> String {
        "Number".to_owned()
    }
    fn parse(path: Path, source: &mut JSON) -> Result<Self, ParseError> {
        match *source {
            JSON::I64(val) => Ok(val as f64),
            JSON::F64(val) => Ok(val),
            JSON::U64(val) => Ok(val as f64),
            _ => Err(ParseError::type_error("as float", &path, "number"))
        }
    }
}

impl Parser<bool> for bool {
    fn description() -> String {
        "bool".to_owned()
    }
    fn parse(path: Path, source: &mut JSON) -> Result<Self, ParseError> {
        match *source {
            JSON::Bool(ref b) => Ok(*b),
            JSON::U64(0) | JSON::I64(0) => Ok(false),
            JSON::U64(1) | JSON::I64(1) => Ok(true),
            JSON::String(ref str) if str == "true" => Ok(true),
            JSON::String(ref str) if str == "false" => Ok(false),
            _ => Err(ParseError::type_error("as bool", &path, "boolean"))
        }
    }
}

impl Parser<u8> for u8 {
    fn description() -> String {
        "byte".to_owned()
    }
    fn parse(path: Path, source: &mut JSON) -> Result<Self, ParseError> {
        match source.as_u64() {
            None => Err(ParseError::type_error("as byte", &path, "positive integer")),
            Some(ref val) if *val > u8::max_value() as u64 =>
                Err(ParseError::type_error("as byte", &path, "positive integer")),
            Some(ref val) => Ok(*val as u8)
        }
    }
}

impl<T> Parser<Vec<T>> for Vec<T> where T: Parser<T> {
    fn description() -> String {
        format!("Array<{}>", T::description())
    }
    fn parse(path: Path, source: &mut JSON) -> Result<Self, ParseError> {
        // Otherwise, parse as an actual array.
        match *source {
            JSON::Array(ref mut array) => {
                let mut result = Vec::with_capacity(array.len());
                for (source, i) in array.iter_mut ().zip(0..) {
                    let value = try!(path.push_index(i, |path| T::parse(path, source)));
                    result.push(value)
                }
                Ok(result)
            }
            JSON::Null => {
                // Accept `null` as an empty array.
                Ok(vec![])
            }
            _ => {
                // Attempt to promote the value to an array.
                let single = try!(path.push_str("", |path| T::parse(path, source)));
                Ok(vec![single])
            }
        }
    }
}

/*
impl<T, U> Parser<(T, U)> for (T, U) where T: Parser<T>, U: Parser<U> {
    fn description() -> String {
        format!("({}, {})", T::description(), U::description())
    }
    fn parse(path: Path, source: &mut JSON) -> Result<Self, ParseError> {
        match *source {
            JSON::Array(ref mut array) if array.len() == 2 => {
                let mut right = array.pop().unwrap(); // We just checked that length == 2
                let mut left = array.pop().unwrap(); // We just checked that length == 2
                let left_parsed = try!(path.push(&T::description() as &str, |path| {T::parse(path, &mut left)}));
                let right_parsed = try!(path.push(&U::description() as &str, |path| {U::parse(path, &mut right)}));
                Ok((left_parsed, right_parsed))
            }
            _ => Err(ParseError::type_error("pair of values", &path, "array"))
        }
    }
}
*/
impl Parser<String> for String {
    fn description() -> String {
        "String".to_owned()
    }
    fn parse(path: Path, source: &mut JSON) -> Result<Self, ParseError> {
        match source.as_string() {
            Some(str) => Ok(str.to_owned()),
            None => Err(ParseError::type_error("string", &path, "string"))
        }
    }
}

impl<T> Parser<Arc<T>> for Arc<T> where T: Parser<T> {
    fn description() -> String {
        T::description()
    }
    fn parse(path: Path, source: &mut JSON) -> Result<Self, ParseError> {
        Ok(Arc::new(try!(T::parse(path, source))))
    }
}

pub trait ToJSON {
    fn to_json(&self) -> JSON;
}

impl ToJSON for String {
    fn to_json(&self) -> JSON {
        JSON::String(self.clone())
    }
}

impl ToJSON for bool {
    fn to_json(&self) -> JSON {
        JSON::Bool(*self)
    }
}

impl ToJSON for f64 {
    fn to_json(&self) -> JSON {
        JSON::F64(*self)
    }
}

impl ToJSON for usize {
    fn to_json(&self) -> JSON {
        JSON::U64(*self as u64)
    }
}

impl ToJSON for JSON {
    fn to_json(&self) -> JSON {
        self.clone()
    }
}

impl<T> ToJSON for HashSet<T> where T: ToJSON + Eq + Hash {
    fn to_json(&self) -> JSON {
        JSON::Array((*self).iter().map(T::to_json).collect())
    }
}

impl<T> ToJSON for HashMap<String, T> where T: ToJSON {
    fn to_json(&self) -> JSON {
        JSON::Object(self.iter().map(|(k, v)| (k.clone(), T::to_json(v))).collect())
    }
}

impl<T> ToJSON for Vec<T> where T: ToJSON {
    fn to_json(&self) -> JSON {
        JSON::Array(self.iter().map(|x| x.to_json()).collect())
    }
}

impl<'a, T> ToJSON for Vec<(&'a str, T)> where T: ToJSON {
    fn to_json(&self) -> JSON {
        JSON::Object(self.iter().map(|&(ref k, ref v)| {
            ((*k).to_owned(), v.to_json())
        }).collect())
    }
}

impl <'a> ToJSON for &'a str {
    fn to_json(&self) -> JSON {
        JSON::String((*self).to_owned())
    }
}

impl<'a, T> ToJSON for &'a T where T: ToJSON {
    fn to_json(&self) -> JSON {
        (**self).to_json()
    }
}

impl<K, T, V> ToJSON for HashMap<Id<K>, Result<T, V>> where T: ToJSON, V: ToJSON {
    fn to_json(&self) -> JSON {
        JSON::Object(self.iter().map(|(k, result)| {
            let k = k.to_string();
            let result = match *result {
                Ok(ref ok) => ok.to_json(),
                Err(ref err) => vec![("Error", err)].to_json()
            };
            (k, result)
        }).collect())
    }
}

impl<T> ToJSON for Option<T> where T: ToJSON {
    fn to_json(&self) -> JSON {
        match *self {
            None => JSON::Null,
            Some(ref result) => result.to_json()
        }
    }
}

impl ToJSON for () {
    fn to_json(&self) -> JSON {
        JSON::Null
    }
}

/*
impl<T> Parser<T> for T where T: Deserialize {
    fn parse(_: Path, source: &mut JSON) -> Result<T, ParseError> {
        use serde_json;
        serde_json::from_value(source.clone()).map_err(ParseError::json)
    }
}
*/
<commit_msg>[fxbox/taxonomy] Implementing Parse::from_str_at<commit_after>//! Utilities for defining a JSON parser.

use util::Id;

use std::cell::RefCell;
use std::collections::{ HashMap, HashSet };
use std::error::Error as StdError;
use std::fmt::{ Display, Debug, Error as FmtError, Formatter };
use std::hash::Hash;
use std::rc::Rc;
use std::sync::Arc;

use serde_json::error;
use serde::ser::{ Serialize, Serializer };
use serde_json;
pub use serde_json::value::Value as JSON;
use serde::de::Error;

/// Utility function: Make sure that we have consumed all the fields of an object.
pub fn check_fields(path: Path, json: &JSON) -> Result<(), ParseError> {
    if let JSON::Object(ref obj) = *json {
        if obj.is_empty() {
            Ok(())
        } else {
            Err(ParseError::unknown_fields(obj.keys().cloned().collect(), &path))
        }
    } else {
        Ok(())
    }
}

/// A path in the JSON tree. Used for displaying error messages.
#[derive(Clone, Debug)]
pub struct Path {
    buf: Rc<RefCell<String>>,
    len: usize,
}
impl Path {
    /// Create an empty Path.
    pub fn new() -> Self {
        Path {
            buf: Rc::new(RefCell::new(String::new())),
            len: 0,
        }
    }

    /// Push a suffix after a path.
    pub fn push_str<F, T>(&self, suffix: &str, cb: F) -> T
        where F: FnOnce(Path) -> T
    {
        let buf = self.buf.clone();
        let len;
        {
            let mut str = buf.borrow_mut();
            str.push_str(suffix);
            len = str.len();
        }
        let path = Path {
            buf: buf,
            len: len,
        };
        let result = cb(path);
        {
            let mut str = self.buf.borrow_mut();
            str.truncate(self.len)
        }
        result
    }

    pub fn push_index<F, T>(&self, index: usize, cb: F) -> T
        where F: FnOnce(Path) -> T
    {
        self.push_str(&format!("[{}]", index), cb)
    }

    pub fn push<F, T>(&self, suffix: &str, cb: F) -> T
        where F: FnOnce(Path) -> T
    {
        self.push_str(&format!(".{}", suffix), cb)
    }

    pub fn to_string(&self) -> String {
        let mut str = self.buf.borrow().clone();
        str.truncate(self.len);
        str
    }
}

/// An error during parsing.
#[derive(Debug)]
pub enum ParseError {
    JSON(JSONError),
    MissingField {
        name: String,
        at: String,
    },
    UnknownFields {
        names: Vec<String>,
        at: String,
    },
    TypeError {
        name: String,
        at: String,
        expected: String,
    },
    EmptyObject {
        at: String
    },
    UnknownConstant {
        at: String,
        constant: String,
    }
}

impl Display for ParseError {
    fn fmt(&self, formatter: &mut Formatter) -> Result<(), FmtError> {
        (self as &Debug).fmt(formatter)
    }
}
impl StdError for ParseError {
    fn description(&self) -> &str {
        "Error while parsing to JSON"
    }
}

impl ParseError {
    pub fn missing_field(name: &str, at: &Path) -> Self {
        ParseError::MissingField {
            name: name.to_owned(),
            at: at.to_string(),
        }
    }
    pub fn type_error(name: &str, at: &Path, expected: &str) -> Self {
        ParseError::TypeError {
            name: name.to_owned(),
            at: at.to_string(),
            expected: expected.to_owned()
        }
    }
    pub fn unknown_fields(names: Vec<String>, at: &Path) -> Self {
        ParseError::UnknownFields {
            names: names,
            at: at.to_string()
        }
    }
    pub fn unknown_constant(value: &str, at: &Path) -> Self {
        ParseError::UnknownConstant {
            constant: value.to_owned(),
            at: at.to_string()
        }
    }
    pub fn empty_object(at: &Path) -> Self {
        ParseError::EmptyObject {
            at: at.to_string(),
        }
    }
    pub fn json(error: error::Error) -> Self {
        ParseError::JSON(JSONError(error))
    }
}

#[derive(Debug)]
pub struct JSONError(error::Error);

impl Serialize for JSONError {
    fn serialize<S>(&self, serializer: &mut S) -> Result<(), S::Error>
        where S: Serializer
    {
        serializer.serialize_str(&format!("{:?}", self))
    }
}

/// An object that knows how to parse values from JSON into type T.
///
/// The JSON object is expected to be consumed along the way. A successful parse will
/// typically leave an empty JSON object.
pub trait Parser<T: Sized> {
    fn description() -> String;
    fn from_str(source: &str) -> Result<T, ParseError> {
        Self::from_str_at(Path::new(), source)
    }
    fn from_str_at(path: Path, source: &str) -> Result<T, ParseError> {
        match serde_json::from_str(source) {
            Err(err) => Err(ParseError::json(err)),
            Ok(mut json) => Self::parse(path, &mut json)
        }
    }

    /// Parse a single value from JSON, consuming as much as necessary from JSON.
    fn parse(path: Path, source: &mut JSON) -> Result<T, ParseError>;

    /// Parse a field from JSON, consuming it.
    fn take(path: Path, source: &mut JSON, field_name: &str) -> Result<T, ParseError> {
        match Self::take_opt(path.clone(), source, field_name) {
            Some(result) => result,
            None => Err(ParseError::missing_field(field_name, &path))
        }
    }

    /// Parse a field from JSON, consuming it.
    fn take_opt(path: Path, source: &mut JSON, field_name: &str) -> Option<Result<T, ParseError>> {
        if let JSON::Object(ref mut obj) = *source {
            if let Some(mut v) = obj.remove(field_name) {
                Some(Self::parse(path, &mut v))
            } else {
                None
            }
        } else {
            Some(Err(ParseError::type_error(field_name, &path, "object")))
        }
    }

    /// Parse a field containing an array from JSON, consuming the field.
    fn take_vec_opt(path: Path, source: &mut JSON, field_name: &str) -> Option<Result<Vec<T>, ParseError>>
    {
        if let JSON::Object(ref mut obj) = *source {
            if let Some(ref mut json) = obj.remove(field_name) {
                if let JSON::Array(ref mut vec) = *json {
                    let mut result = Vec::with_capacity(vec.len());
                    for (json, i) in vec.iter_mut().zip(0..) {
                        match path.push(&format!("[{}]", i),
                            |path| Self::parse(path, json)
                        ) {
                            Err(error) => return Some(Err(error)),
                            Ok(parsed) => result.push(parsed)
                        }
                    }
                    Some(Ok(result))
                } else {
                    Some(Err(ParseError::type_error(field_name, &path, "array")))
                }
            } else {
                None
            }
        } else {
            Some(Err(ParseError::missing_field(field_name, &path)))
        }
    }

    fn take_vec(path: Path, source: &mut JSON, field_name: &str) -> Result<Vec<T>, ParseError> {
        match Self::take_vec_opt(path.clone(), source, field_name) {
            Some(result) => result,
            None => Err(ParseError::missing_field(field_name, &path))
        }
    }
}

impl Parser<f64> for f64 {
    fn description() -> String {
        "Number".to_owned()
    }
    fn parse(path: Path, source: &mut JSON) -> Result<Self, ParseError> {
        match *source {
            JSON::I64(val) => Ok(val as f64),
            JSON::F64(val) => Ok(val),
            JSON::U64(val) => Ok(val as f64),
            _ => Err(ParseError::type_error("as float", &path, "number"))
        }
    }
}

impl Parser<bool> for bool {
    fn description() -> String {
        "bool".to_owned()
    }
    fn parse(path: Path, source: &mut JSON) -> Result<Self, ParseError> {
        match *source {
            JSON::Bool(ref b) => Ok(*b),
            JSON::U64(0) | JSON::I64(0) => Ok(false),
            JSON::U64(1) | JSON::I64(1) => Ok(true),
            JSON::String(ref str) if str == "true" => Ok(true),
            JSON::String(ref str) if str == "false" => Ok(false),
            _ => Err(ParseError::type_error("as bool", &path, "boolean"))
        }
    }
}

impl Parser<u8> for u8 {
    fn description() -> String {
        "byte".to_owned()
    }
    fn parse(path: Path, source: &mut JSON) -> Result<Self, ParseError> {
        match source.as_u64() {
            None => Err(ParseError::type_error("as byte", &path, "positive integer")),
            Some(ref val) if *val > u8::max_value() as u64 =>
                Err(ParseError::type_error("as byte", &path, "positive integer")),
            Some(ref val) => Ok(*val as u8)
        }
    }
}

impl<T> Parser<Vec<T>> for Vec<T> where T: Parser<T> {
    fn description() -> String {
        format!("Array<{}>", T::description())
    }
    fn parse(path: Path, source: &mut JSON) -> Result<Self, ParseError> {
        // Otherwise, parse as an actual array.
        match *source {
            JSON::Array(ref mut array) => {
                let mut result = Vec::with_capacity(array.len());
                for (source, i) in array.iter_mut ().zip(0..) {
                    let value = try!(path.push_index(i, |path| T::parse(path, source)));
                    result.push(value)
                }
                Ok(result)
            }
            JSON::Null => {
                // Accept `null` as an empty array.
                Ok(vec![])
            }
            _ => {
                // Attempt to promote the value to an array.
                let single = try!(path.push_str("", |path| T::parse(path, source)));
                Ok(vec![single])
            }
        }
    }
}

/*
impl<T, U> Parser<(T, U)> for (T, U) where T: Parser<T>, U: Parser<U> {
    fn description() -> String {
        format!("({}, {})", T::description(), U::description())
    }
    fn parse(path: Path, source: &mut JSON) -> Result<Self, ParseError> {
        match *source {
            JSON::Array(ref mut array) if array.len() == 2 => {
                let mut right = array.pop().unwrap(); // We just checked that length == 2
                let mut left = array.pop().unwrap(); // We just checked that length == 2
                let left_parsed = try!(path.push(&T::description() as &str, |path| {T::parse(path, &mut left)}));
                let right_parsed = try!(path.push(&U::description() as &str, |path| {U::parse(path, &mut right)}));
                Ok((left_parsed, right_parsed))
            }
            _ => Err(ParseError::type_error("pair of values", &path, "array"))
        }
    }
}
*/
impl Parser<String> for String {
    fn description() -> String {
        "String".to_owned()
    }
    fn parse(path: Path, source: &mut JSON) -> Result<Self, ParseError> {
        match source.as_string() {
            Some(str) => Ok(str.to_owned()),
            None => Err(ParseError::type_error("string", &path, "string"))
        }
    }
}

impl<T> Parser<Arc<T>> for Arc<T> where T: Parser<T> {
    fn description() -> String {
        T::description()
    }
    fn parse(path: Path, source: &mut JSON) -> Result<Self, ParseError> {
        Ok(Arc::new(try!(T::parse(path, source))))
    }
}

pub trait ToJSON {
    fn to_json(&self) -> JSON;
}

impl ToJSON for String {
    fn to_json(&self) -> JSON {
        JSON::String(self.clone())
    }
}

impl ToJSON for bool {
    fn to_json(&self) -> JSON {
        JSON::Bool(*self)
    }
}

impl ToJSON for f64 {
    fn to_json(&self) -> JSON {
        JSON::F64(*self)
    }
}

impl ToJSON for usize {
    fn to_json(&self) -> JSON {
        JSON::U64(*self as u64)
    }
}

impl ToJSON for JSON {
    fn to_json(&self) -> JSON {
        self.clone()
    }
}

impl<T> ToJSON for HashSet<T> where T: ToJSON + Eq + Hash {
    fn to_json(&self) -> JSON {
        JSON::Array((*self).iter().map(T::to_json).collect())
    }
}

impl<T> ToJSON for HashMap<String, T> where T: ToJSON {
    fn to_json(&self) -> JSON {
        JSON::Object(self.iter().map(|(k, v)| (k.clone(), T::to_json(v))).collect())
    }
}

impl<T> ToJSON for Vec<T> where T: ToJSON {
    fn to_json(&self) -> JSON {
        JSON::Array(self.iter().map(|x| x.to_json()).collect())
    }
}

impl<'a, T> ToJSON for Vec<(&'a str, T)> where T: ToJSON {
    fn to_json(&self) -> JSON {
        JSON::Object(self.iter().map(|&(ref k, ref v)| {
            ((*k).to_owned(), v.to_json())
        }).collect())
    }
}

impl <'a> ToJSON for &'a str {
    fn to_json(&self) -> JSON {
        JSON::String((*self).to_owned())
    }
}

impl<'a, T> ToJSON for &'a T where T: ToJSON {
    fn to_json(&self) -> JSON {
        (**self).to_json()
    }
}

impl<K, T, V> ToJSON for HashMap<Id<K>, Result<T, V>> where T: ToJSON, V: ToJSON {
    fn to_json(&self) -> JSON {
        JSON::Object(self.iter().map(|(k, result)| {
            let k = k.to_string();
            let result = match *result {
                Ok(ref ok) => ok.to_json(),
                Err(ref err) => vec![("Error", err)].to_json()
            };
            (k, result)
        }).collect())
    }
}

impl<T> ToJSON for Option<T> where T: ToJSON {
    fn to_json(&self) -> JSON {
        match *self {
            None => JSON::Null,
            Some(ref result) => result.to_json()
        }
    }
}

impl ToJSON for () {
    fn to_json(&self) -> JSON {
        JSON::Null
    }
}

/*
impl<T> Parser<T> for T where T: Deserialize {
    fn parse(_: Path, source: &mut JSON) -> Result<T, ParseError> {
        use serde_json;
        serde_json::from_value(source.clone()).map_err(ParseError::json)
    }
}
*/
<|endoftext|>