<commit_before>use std::collections::VecDeque;
use std::fmt;
use term;
use time::precise_time_s;
use rustup::Notification;
use rustup_dist::Notification as In;
use rustup_utils::Notification as Un;
use rustup_utils::tty;

/// Keep track of this many past download amounts
const DOWNLOAD_TRACK_COUNT: usize = 5;

/// Tracks download progress and displays information about it to a terminal.
pub struct DownloadTracker {
    /// Content-Length of the to-be downloaded object.
    content_len: Option<u64>,
    /// Total data downloaded in bytes.
    total_downloaded: usize,
    /// Data downloaded this second.
    downloaded_this_sec: usize,
    /// Keeps track of amount of data downloaded every last few secs.
    /// Used for averaging the download speed.
    downloaded_last_few_secs: VecDeque<usize>,
    /// Time stamp of the last second
    last_sec: Option<f64>,
    /// How many seconds have elapsed since the download started
    seconds_elapsed: u32,
    /// The terminal we write the information to.
    term: Option<Box<term::StdoutTerminal>>,
    /// Whether we displayed progress for the download or not.
    ///
    /// If the download is quick enough, we don't have time to
    /// display the progress info.
    /// In that case, we do not want to do some cleanup stuff we normally do.
    displayed_progress: bool,
}

impl DownloadTracker {
    /// Creates a new DownloadTracker.
    pub fn new() -> Self {
        DownloadTracker {
            content_len: None,
            total_downloaded: 0,
            downloaded_this_sec: 0,
            downloaded_last_few_secs: VecDeque::with_capacity(DOWNLOAD_TRACK_COUNT),
            seconds_elapsed: 0,
            last_sec: None,
            term: term::stdout(),
            displayed_progress: false,
        }
    }

    pub fn handle_notification(&mut self, n: &Notification) -> bool {
        match *n {
            Notification::Install(In::Utils(Un::DownloadContentLengthReceived(content_len))) => {
                self.content_length_received(content_len);

                true
            }
            Notification::Install(In::Utils(Un::DownloadDataReceived(data))) => {
                if tty::stdout_isatty() && self.term.is_some() {
                    self.data_received(data.len());
                }
                true
            }
            Notification::Install(In::Utils(Un::DownloadFinished)) => {
                self.download_finished();
                true
            }
            _ => false,
        }
    }

    /// Notifies self that Content-Length information has been received.
    pub fn content_length_received(&mut self, content_len: u64) {
        self.content_len = Some(content_len);
    }
    /// Notifies self that data of size `len` has been received.
    pub fn data_received(&mut self, len: usize) {
        self.total_downloaded += len;
        self.downloaded_this_sec += len;

        let current_time = precise_time_s();

        match self.last_sec {
            None => self.last_sec = Some(current_time),
            Some(start) => {
                let elapsed = current_time - start;
                if elapsed >= 1.0 {
                    self.seconds_elapsed += 1;

                    self.display();
                    self.last_sec = Some(current_time);
                    if self.downloaded_last_few_secs.len() == DOWNLOAD_TRACK_COUNT {
                        self.downloaded_last_few_secs.pop_back();
                    }
                    self.downloaded_last_few_secs
                        .push_front(self.downloaded_this_sec);
                    self.downloaded_this_sec = 0;
                }
            }
        }
    }
    /// Notifies self that the download has finished.
    pub fn download_finished(&mut self) {
        if self.displayed_progress {
            // Display the finished state
            self.display();
            let _ = writeln!(self.term.as_mut().unwrap(), "");
        }
        self.prepare_for_new_download();
    }
    /// Resets the state to be ready for a new download.
    fn prepare_for_new_download(&mut self) {
        self.content_len = None;
        self.total_downloaded = 0;
        self.downloaded_this_sec = 0;
        self.downloaded_last_few_secs.clear();
        self.seconds_elapsed = 0;
        self.last_sec = None;
        self.displayed_progress = false;
    }
    /// Display the tracked download information to the terminal.
    fn display(&mut self) {
        let total_h = HumanReadable(self.total_downloaded as f64);
        let sum = self.downloaded_last_few_secs
            .iter()
            .fold(0., |a, &v| a + v as f64);
        let len = self.downloaded_last_few_secs.len();
        let speed = if len > 0 { sum / len as f64 } else { 0. };
        let speed_h = HumanReadable(speed);

        match self.content_len {
            Some(content_len) => {
                let content_len = content_len as f64;
                let percent = (self.total_downloaded as f64 / content_len) * 100.;
                let content_len_h = HumanReadable(content_len);
                let remaining = content_len - self.total_downloaded as f64;
                let eta_h = HumanReadable(remaining / speed);
                let _ = write!(
                    self.term.as_mut().unwrap(),
                    "{} / {} ({:3.0} %) {}/s ETA: {:#}",
                    total_h,
                    content_len_h,
                    percent,
                    speed_h,
                    eta_h
                );
            }
            None => {
                let _ = write!(
                    self.term.as_mut().unwrap(),
                    "Total: {} Speed: {}/s",
                    total_h,
                    speed_h
                );
            }
        }
        // delete_line() doesn't seem to clear the line properly.
        // Instead, let's just print some whitespace to clear it.
        let _ = write!(self.term.as_mut().unwrap(), "                ");
        let _ = self.term.as_mut().unwrap().flush();
        let _ = self.term.as_mut().unwrap().carriage_return();
        self.displayed_progress = true;
    }
}

/// Human readable representation of data size in bytes
struct HumanReadable(f64);

impl fmt::Display for HumanReadable {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        if f.alternate() {
            // repurposing the alternate mode for ETA
            let sec = self.0;

            if sec.is_infinite() {
                write!(f, "Unknown")
            } else if sec > 1e3 {
                let sec = self.0 as u64;
                let min = sec / 60;
                let sec = sec % 60;

                write!(f, "{:3} min {:2} s", min, sec) // XYZ min PQ s
            } else {
                write!(f, "{:3.0} s", self.0) // XYZ s
            }
        } else {
            const KIB: f64 = 1024.0;
            const MIB: f64 = KIB * KIB;
            let size = self.0;

            if size >= MIB {
                write!(f, "{:5.1} MiB", size / MIB) // XYZ.P MiB
            } else if size >= KIB {
                write!(f, "{:5.1} KiB", size / KIB)
            } else {
                write!(f, "{:3.0} B", size)
            }
        }
    }
}
<commit_msg>Improve formatting of longer download times in download tracker<commit_after>use std::collections::VecDeque;
use std::fmt;
use term;
use time::precise_time_s;
use rustup::Notification;
use rustup_dist::Notification as In;
use rustup_utils::Notification as Un;
use rustup_utils::tty;

/// Keep track of this many past download amounts
const DOWNLOAD_TRACK_COUNT: usize = 5;

/// Tracks download progress and displays information about it to a terminal.
pub struct DownloadTracker {
    /// Content-Length of the to-be downloaded object.
    content_len: Option<u64>,
    /// Total data downloaded in bytes.
    total_downloaded: usize,
    /// Data downloaded this second.
    downloaded_this_sec: usize,
    /// Keeps track of amount of data downloaded every last few secs.
    /// Used for averaging the download speed.
    downloaded_last_few_secs: VecDeque<usize>,
    /// Time stamp of the last second
    last_sec: Option<f64>,
    /// How many seconds have elapsed since the download started
    seconds_elapsed: u32,
    /// The terminal we write the information to.
    term: Option<Box<term::StdoutTerminal>>,
    /// Whether we displayed progress for the download or not.
    ///
    /// If the download is quick enough, we don't have time to
    /// display the progress info.
    /// In that case, we do not want to do some cleanup stuff we normally do.
    displayed_progress: bool,
}

impl DownloadTracker {
    /// Creates a new DownloadTracker.
    pub fn new() -> Self {
        DownloadTracker {
            content_len: None,
            total_downloaded: 0,
            downloaded_this_sec: 0,
            downloaded_last_few_secs: VecDeque::with_capacity(DOWNLOAD_TRACK_COUNT),
            seconds_elapsed: 0,
            last_sec: None,
            term: term::stdout(),
            displayed_progress: false,
        }
    }

    pub fn handle_notification(&mut self, n: &Notification) -> bool {
        match *n {
            Notification::Install(In::Utils(Un::DownloadContentLengthReceived(content_len))) => {
                self.content_length_received(content_len);

                true
            }
            Notification::Install(In::Utils(Un::DownloadDataReceived(data))) => {
                if tty::stdout_isatty() && self.term.is_some() {
                    self.data_received(data.len());
                }
                true
            }
            Notification::Install(In::Utils(Un::DownloadFinished)) => {
                self.download_finished();
                true
            }
            _ => false,
        }
    }

    /// Notifies self that Content-Length information has been received.
    pub fn content_length_received(&mut self, content_len: u64) {
        self.content_len = Some(content_len);
    }
    /// Notifies self that data of size `len` has been received.
    pub fn data_received(&mut self, len: usize) {
        self.total_downloaded += len;
        self.downloaded_this_sec += len;

        let current_time = precise_time_s();

        match self.last_sec {
            None => self.last_sec = Some(current_time),
            Some(start) => {
                let elapsed = current_time - start;
                if elapsed >= 1.0 {
                    self.seconds_elapsed += 1;

                    self.display();
                    self.last_sec = Some(current_time);
                    if self.downloaded_last_few_secs.len() == DOWNLOAD_TRACK_COUNT {
                        self.downloaded_last_few_secs.pop_back();
                    }
                    self.downloaded_last_few_secs
                        .push_front(self.downloaded_this_sec);
                    self.downloaded_this_sec = 0;
                }
            }
        }
    }
    /// Notifies self that the download has finished.
    pub fn download_finished(&mut self) {
        if self.displayed_progress {
            // Display the finished state
            self.display();
            let _ = writeln!(self.term.as_mut().unwrap(), "");
        }
        self.prepare_for_new_download();
    }
    /// Resets the state to be ready for a new download.
    fn prepare_for_new_download(&mut self) {
        self.content_len = None;
        self.total_downloaded = 0;
        self.downloaded_this_sec = 0;
        self.downloaded_last_few_secs.clear();
        self.seconds_elapsed = 0;
        self.last_sec = None;
        self.displayed_progress = false;
    }
    /// Display the tracked download information to the terminal.
    fn display(&mut self) {
        let total_h = HumanReadable(self.total_downloaded as f64);
        let sum = self.downloaded_last_few_secs
            .iter()
            .fold(0., |a, &v| a + v as f64);
        let len = self.downloaded_last_few_secs.len();
        let speed = if len > 0 { sum / len as f64 } else { 0. };
        let speed_h = HumanReadable(speed);

        match self.content_len {
            Some(content_len) => {
                let content_len = content_len as f64;
                let percent = (self.total_downloaded as f64 / content_len) * 100.;
                let content_len_h = HumanReadable(content_len);
                let remaining = content_len - self.total_downloaded as f64;
                let eta_h = HumanReadable(remaining / speed);
                let _ = write!(
                    self.term.as_mut().unwrap(),
                    "{} / {} ({:3.0} %) {}/s ETA: {:#}",
                    total_h,
                    content_len_h,
                    percent,
                    speed_h,
                    eta_h
                );
            }
            None => {
                let _ = write!(
                    self.term.as_mut().unwrap(),
                    "Total: {} Speed: {}/s",
                    total_h,
                    speed_h
                );
            }
        }
        // delete_line() doesn't seem to clear the line properly.
        // Instead, let's just print some whitespace to clear it.
        let _ = write!(self.term.as_mut().unwrap(), "                ");
        let _ = self.term.as_mut().unwrap().flush();
        let _ = self.term.as_mut().unwrap().carriage_return();
        self.displayed_progress = true;
    }
}

/// Human readable representation of data size in bytes
struct HumanReadable(f64);

impl fmt::Display for HumanReadable {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        if f.alternate() {
            // repurposing the alternate mode for ETA
            let sec = self.0;

            if sec.is_infinite() {
                write!(f, "Unknown")
            } else if sec > 48. * 3600. {
                let sec = self.0 as u64;
                let d = sec / (24. * 3600.);
                let h = sec % (24. * 3600.);
                let min = sec % 3600.;
                let sec = sec % 60.;

                write!(f, "{:3} days {:2} h {:2} min {:2} s", d, h, min, sec) // XYZ days PQ h RS min TU s
            } else if sec > 6_000. {
                let sec = self.0 as u64;
                let h = sec / 3600.;
                let min = sec % 3600.;
                let sec = sec % 60.;

                write!(f, "{:3} h {:2} min {:2} s", h, min, sec) // XYZ h PQ min RS s
            } else if sec > 100 {
                let sec = self.0 as u64;
                let min = sec / 60.;
                let sec = sec % 60.;

                write!(f, "{:3} min {:2} s", min, sec) // XYZ min PQ s
            } else {
                write!(f, "{:3.0} s", self.0) // XYZ s
            }
        } else {
            const KIB: f64 = 1024.0;
            const MIB: f64 = KIB * KIB;
            let size = self.0;

            if size >= MIB {
                write!(f, "{:5.1} MiB", size / MIB) // XYZ.P MiB
            } else if size >= KIB {
                write!(f, "{:5.1} KiB", size / KIB)
            } else {
                write!(f, "{:3.0} B", size)
            }
        }
    }
}
<|endoftext|>


<commit_before>pub use error::{Error, ErrorRefExt};

use server::{Request, Response};
use server_backend::status;

#[deriving(Show)]
pub struct NotMatchError;

impl Error for NotMatchError {
    fn name(&self) -> &'static str {
        return "NotMatchError";
    }
}

#[deriving(Show)]
pub struct NotFoundError;

impl Error for NotFoundError {
    fn name(&self) -> &'static str {
        return "NotFoundError";
    }
}

pub type HandleError = Box<Error>;
pub type HandleResult<T> = Result<T, HandleError>;
pub type HandleSuccessResult = HandleResult<()>;

pub trait BeforeMiddleware: Send + Sync {
    fn before(&self, &mut Request) -> HandleSuccessResult;
}

pub trait AfterMiddleware: Send + Sync {
    fn after(&self, &mut Request, &mut Response) -> HandleSuccessResult;
}

pub trait CatchMiddleware: Send + Sync {
    fn rescue(&self, &mut Request, err: &HandleError) -> HandleResult<Option<Response>>;
}

pub trait Handler: Send + Sync {
    fn call(&self, &str, &mut Request) -> HandleResult<Response>;
}

#[deriving(Send)]
pub struct Application {
    before: Vec<Box<BeforeMiddleware + Send + Sync>>,
    after: Vec<Box<AfterMiddleware + Send + Sync>>,
    catch: Vec<Box<CatchMiddleware + Send + Sync>>,
    handlers: Vec<Box<Handler + Send + Sync>>
}

impl Application {

    pub fn new() -> Application {
        Application {
            before: vec![],
            after: vec![],
            catch: vec![],
            handlers: vec![]
        }
    }

    pub fn call(&self, req: &mut Request) -> HandleResult<Response> {

        for mdw in self.before.iter() {
            match mdw.before(req) {
                Err(err) => {
                    match self.handle_error(req, err) {
                        Some(response) => return Ok(response),
                        None => ()
                    }
                },
                Ok(()) => ()
            }
        }

        let mut response: Option<Response> = None;
        let path = req.url.serialize_path().unwrap_or(String::new());

        for handler in self.handlers.iter() {
            match handler.call(path.as_slice(), req) {
                Ok(resp) => response = Some(resp),
                Err(err) => match err.downcast::<NotMatchError>() {
                    Some(_) => (),
                    None => match self.handle_error(req, err) {
                        Some(response) => return Ok(response),
                        None => ()
                    }
                }
            }
        }

        let mut exact_response = match response {
            Some(resp) => resp,
            None => return Ok(self.handle_error(req, NotFoundError.abstract()).unwrap())
        };

        for mdw in self.after.iter() {
            match mdw.after(req, &mut exact_response) {
                Err(err) => match self.handle_error(req, err) {
                    Some(response) => return Ok(response),
                    None => ()
                },
                Ok(()) => ()
            }
        }

        Ok(exact_response)

    }

    pub fn handle_error(&self, req: &mut Request, err: HandleError) -> Option<Response> {
        for catcher in self.catch.iter() {
            match catcher.rescue(req, &err) {
                Ok(maybe_response) => {
                    match maybe_response {
                        Some(resp) => return Some(resp),
                        None => return None
                    }
                },
                Err(some) => ()
            }
        }

        let error_message = format!("{}", err);
        Some(Response::from_string(status::InternalServerError, error_message))
    }

    pub fn mount(&mut self, handler: Box<Handler + Send + Sync>) {
        self.handlers.push(handler);
    }
}

trait AfterMiddlewareSupport {
    fn using(&mut self, middleware: Box<AfterMiddleware + Send + Sync>);
}

trait BeforeMiddlewareSupport {
    fn using(&mut self, middleware: Box<BeforeMiddleware + Send + Sync>);
}

impl AfterMiddlewareSupport for Application {
    fn using(&mut self, middleware: Box<AfterMiddleware + Send + Sync>) {
        self.after.push(middleware);
    }
}

impl BeforeMiddlewareSupport for Application {
    fn using(&mut self, middleware: Box<BeforeMiddleware + Send + Sync>) {
        self.before.push(middleware);
    }
}

<commit_msg>feat: allow middleware to return a response<commit_after>pub use error::{Error, ErrorRefExt};

use server::{Request, Response};
use server_backend::status;

#[deriving(Show)]
pub struct NotMatchError;

impl Error for NotMatchError {
    fn name(&self) -> &'static str {
        return "NotMatchError";
    }
}

#[deriving(Show)]
pub struct NotFoundError;

impl Error for NotFoundError {
    fn name(&self) -> &'static str {
        return "NotFoundError";
    }
}

pub type HandleError = Box<Error>;
pub type HandleResult<T> = Result<T, HandleError>;
pub type HandleSuccessResult = HandleResult<()>;

pub trait BeforeMiddleware: Send + Sync {
    fn before(&self, &mut Request) -> HandleResult<Option<Response>>;
}

pub trait AfterMiddleware: Send + Sync {
    fn after(&self, &mut Request, &mut Response) -> HandleResult<Option<Response>>;
}

pub trait CatchMiddleware: Send + Sync {
    fn rescue(&self, &mut Request, err: &HandleError) -> HandleResult<Option<Response>>;
}

pub trait Handler: Send + Sync {
    fn call(&self, &str, &mut Request) -> HandleResult<Response>;
}

#[deriving(Send)]
pub struct Application {
    before: Vec<Box<BeforeMiddleware + Send + Sync>>,
    after: Vec<Box<AfterMiddleware + Send + Sync>>,
    catch: Vec<Box<CatchMiddleware + Send + Sync>>,
    handlers: Vec<Box<Handler + Send + Sync>>
}

impl Application {

    pub fn new() -> Application {
        Application {
            before: vec![],
            after: vec![],
            catch: vec![],
            handlers: vec![]
        }
    }

    pub fn call(&self, req: &mut Request) -> HandleResult<Response> {

        for mdw in self.before.iter() {
            match mdw.before(req) {
                Err(err) => {
                    match self.handle_error(req, err) {
                        Some(response) => return Ok(response),
                        None => ()
                    }
                },
                Ok(Some(response)) => return Ok(response),
                Ok(None) => ()
            }
        }

        let mut response: Option<Response> = None;
        let path = req.url.serialize_path().unwrap_or(String::new());

        for handler in self.handlers.iter() {
            match handler.call(path.as_slice(), req) {
                Ok(resp) => response = Some(resp),
                Err(err) => match err.downcast::<NotMatchError>() {
                    Some(_) => (),
                    None => match self.handle_error(req, err) {
                        Some(response) => return Ok(response),
                        None => ()
                    }
                }
            }
        }

        let mut exact_response = match response {
            Some(resp) => resp,
            None => return Ok(self.handle_error(req, NotFoundError.abstract()).unwrap())
        };

        for mdw in self.after.iter() {
            match mdw.after(req, &mut exact_response) {
                Err(err) => match self.handle_error(req, err) {
                    Some(response) => return Ok(response),
                    None => ()
                },
                Ok(Some(response)) => return Ok(response),
                Ok(None) => ()
            }
        }

        Ok(exact_response)

    }

    pub fn handle_error(&self, req: &mut Request, err: HandleError) -> Option<Response> {
        for catcher in self.catch.iter() {
            match catcher.rescue(req, &err) {
                Ok(maybe_response) => {
                    match maybe_response {
                        Some(resp) => return Some(resp),
                        None => return None
                    }
                },
                Err(some) => ()
            }
        }

        let error_message = format!("{}", err);
        Some(Response::from_string(status::InternalServerError, error_message))
    }

    pub fn mount(&mut self, handler: Box<Handler + Send + Sync>) {
        self.handlers.push(handler);
    }
}

trait AfterMiddlewareSupport {
    fn using(&mut self, middleware: Box<AfterMiddleware + Send + Sync>);
}

trait BeforeMiddlewareSupport {
    fn using(&mut self, middleware: Box<BeforeMiddleware + Send + Sync>);
}

impl AfterMiddlewareSupport for Application {
    fn using(&mut self, middleware: Box<AfterMiddleware + Send + Sync>) {
        self.after.push(middleware);
    }
}

impl BeforeMiddlewareSupport for Application {
    fn using(&mut self, middleware: Box<BeforeMiddleware + Send + Sync>) {
        self.before.push(middleware);
    }
}

<|endoftext|>


<commit_before>//! Eigenvalue decomposition for general matrices

use lapacke;
use num_traits::Zero;

use crate::error::*;
use crate::layout::MatrixLayout;
use crate::types::*;

use super::into_result;

/// Wraps `*geev` for real/complex
pub trait Eig_: Scalar {
    unsafe fn eig(calc_v: bool, l: MatrixLayout, a: &mut [Self]) -> Result<(Vec<Self::Complex>, Vec<Self::Complex>)>;
}

macro_rules! impl_eig_complex {
    ($scalar:ty, $ev:path) => {
        impl Eig_ for $scalar {
            unsafe fn eig(calc_v: bool, l: MatrixLayout, mut a: &mut [Self]) -> Result<(Vec<Self::Complex>, Vec<Self::Complex>)> {
                let (n, _) = l.size();
                let jobvr = if calc_v { b'V' } else { b'N' };
                let mut w = vec![Self::Complex::zero(); n as usize];
                let mut vl = Vec::new();
                let mut vr = vec![Self::Complex::zero(); (n * n) as usize];
                let info = $ev(l.lapacke_layout(), b'N', jobvr, n, &mut a, n, &mut w, &mut vl, n, &mut vr, n);
                into_result(info, (w, vr))
            }
        }
    };
}

macro_rules! impl_eig_real {
    ($scalar:ty, $ev:path) => {
        impl Eig_ for $scalar {
            unsafe fn eig(calc_v: bool, l: MatrixLayout, mut a: &mut [Self]) -> Result<(Vec<Self::Complex>, Vec<Self::Complex>)> {
                let (n, _) = l.size();
                let jobvr = if calc_v { b'V' } else { b'N' };
                let mut wr = vec![Self::Real::zero(); n as usize];
                let mut wi = vec![Self::Real::zero(); n as usize];
                let mut vl = Vec::new();
                let mut vr = vec![Self::Real::zero(); (n * n) as usize];
                let info = $ev(l.lapacke_layout(), b'N', jobvr, n, &mut a, n, &mut wr, &mut wi, &mut vl, n, &mut vr, n);
                let w: Vec<Self::Complex> = wr.iter().zip(wi.iter()).map(|(&r, &i)| Self::Complex::new(r, i)).collect();
                let n = n as usize;
                let mut conj = false;
                let mut v = vec![Self::Complex::zero(); n * n];
                for (i, c) in w.iter().enumerate() {
                    if conj {
                        for j in 0..n {
                            v[n*j+i] = Self::Complex::new(vr[n*j+i-1], -vr[n*j+i]);
                        }
                        conj = false;
                    } else if c.im != 0.0 {
                        conj = true;
                        for j in 0..n {
                            v[n*j+i] = Self::Complex::new(vr[n*j+i], vr[n*j+i+1]);
                        }
                    } else {
                        for j in 0..n {
                            v[n*j+i] = Self::Complex::new(vr[n*j+i], 0.0);
                        }
                    }
                }
                into_result(info, (w, v))
            }
        }
    };
}

impl_eig_real!(f64, lapacke::dgeev);
impl_eig_real!(f32, lapacke::sgeev);
impl_eig_complex!(c64, lapacke::zgeev);
impl_eig_complex!(c32, lapacke::cgeev);<commit_msg>rewrite a function collecting right eigenvector<commit_after>//! Eigenvalue decomposition for general matrices

use lapacke;
use num_traits::Zero;

use crate::error::*;
use crate::layout::MatrixLayout;
use crate::types::*;

use super::into_result;

/// Wraps `*geev` for real/complex
pub trait Eig_: Scalar {
    unsafe fn eig(calc_v: bool, l: MatrixLayout, a: &mut [Self]) -> Result<(Vec<Self::Complex>, Vec<Self::Complex>)>;
}

macro_rules! impl_eig_complex {
    ($scalar:ty, $ev:path) => {
        impl Eig_ for $scalar {
            unsafe fn eig(calc_v: bool, l: MatrixLayout, mut a: &mut [Self]) -> Result<(Vec<Self::Complex>, Vec<Self::Complex>)> {
                let (n, _) = l.size();
                let jobvr = if calc_v { b'V' } else { b'N' };
                let mut w = vec![Self::Complex::zero(); n as usize];
                let mut vl = Vec::new();
                let mut vr = vec![Self::Complex::zero(); (n * n) as usize];
                let info = $ev(l.lapacke_layout(), b'N', jobvr, n, &mut a, n, &mut w, &mut vl, n, &mut vr, n);
                into_result(info, (w, vr))
            }
        }
    };
}

macro_rules! impl_eig_real {
    ($scalar:ty, $ev:path) => {
        impl Eig_ for $scalar {
            unsafe fn eig(calc_v: bool, l: MatrixLayout, mut a: &mut [Self]) -> Result<(Vec<Self::Complex>, Vec<Self::Complex>)> {
                let (n, _) = l.size();
                let jobvr = if calc_v { b'V' } else { b'N' };
                let mut wr = vec![Self::Real::zero(); n as usize];
                let mut wi = vec![Self::Real::zero(); n as usize];
                let mut vl = Vec::new();
                let mut vr = vec![Self::Real::zero(); (n * n) as usize];
                let info = $ev(l.lapacke_layout(), b'N', jobvr, n, &mut a, n, &mut wr, &mut wi, &mut vl, n, &mut vr, n);
                let w: Vec<Self::Complex> = wr.iter().zip(wi.iter()).map(|(&r, &i)| Self::Complex::new(r, i)).collect();
                // If the j-th eigenvalue is real, then
                // eigenvector = [ vr[j], vr[j+n], vr[j+2*n], ... ].
                //
                // If the j-th and (j+1)-st eigenvalues form a complex conjugate pair,
                // eigenvector(j)   = [ vr[j] + i*vr[j+1], vr[j+n] + i*vr[j+n+1], vr[j+2*n] + i*vr[j+2*n+1], ... ] and
                // eigenvector(j+1) = [ vr[j] - i*vr[j+1], vr[j+n] - i*vr[j+n+1], vr[j+2*n] - i*vr[j+2*n+1], ... ].
                //
                // Therefore, if eigenvector(j) is written as [ v_{j0}, v_{j1}, v_{j2}, ... ],
                // you have to make
                // v = vec![ v_{00}, v_{10}, v_{20}, ..., v_{jk}, v_{(j+1)k}, v_{(j+2)k}, ... ] (v.len() = n*n)
                // based on wi and vr.
                // After that, v is converted to Array2 (see ../eig.rs).
                let n = n as usize;
                let mut flg = false;
                let conj: Vec<i8> = wi.iter().map(|&i| {
                    if flg {
                        flg = false;
                        -1
                    } else if i != 0.0 {
                        flg = true;
                        1
                    } else {
                        0
                    }
                }).collect();
                let v: Vec<Self::Complex> = (0..n*n).map(|i| {
                    let j = i % n;
                    match conj[j] {
                         1 => Self::Complex::new(vr[i], vr[i+1]),
                        -1 => Self::Complex::new(vr[i-1], -vr[i]),
                         _ => Self::Complex::new(vr[i], 0.0),
                    }
                }).collect();

                into_result(info, (w, v))
            }
        }
    };
}

impl_eig_real!(f64, lapacke::dgeev);
impl_eig_real!(f32, lapacke::sgeev);
impl_eig_complex!(c64, lapacke::zgeev);
impl_eig_complex!(c32, lapacke::cgeev);<|endoftext|>


<commit_before>use std::str::FromStr;
use std::io::{File};
use std::collections::BTreeMap;

use iron::prelude::*;
use iron::{AfterMiddleware, typemap};
use iron::modifier::Modifier;
use iron::status;
use iron::headers;

use glob::glob;

use handlebars::Handlebars;
use serialize::json::{ToJson, Json};

pub struct HandlebarsEngine {
    registry: Handlebars
}

pub struct Template {
    name: String,
    value: Json
}

impl Template {
    pub fn new(name: String, value: Json) -> Template{
        Template {
            name: name,
            value: value
        }
    }
}

impl Modifier<Response> for Template {
    fn modify(self, resp: &mut Response) {
        resp.extensions.insert::<HandlebarsEngine>(self);
    }
}

impl typemap::Key for HandlebarsEngine {
    type Value = Template;
}

impl HandlebarsEngine {
    fn new(prefix: &str, suffix: &str) -> HandlebarsEngine {
        let mut r = Handlebars::new();

        let mut pattern = String::new();
        pattern.push_str(prefix);
        pattern.push_str("**/*");
        pattern.push_str(suffix);

        for path in glob(pattern.as_slice()) {
            let disp = path.as_str().unwrap();
            let t = r.register_template_string(
                disp.slice(prefix.len(), disp.len()-suffix.len()),
                File::open(&path).ok()
                    .expect(format!("Failed to open file {}", disp).as_slice())
                    .read_to_string().unwrap());

            if t.is_err() {
                panic!("Failed to create template.");
            }
        }

        HandlebarsEngine {
            registry: r
        }
    }
}

impl AfterMiddleware for HandlebarsEngine {
    fn after(&self, _: &mut Request, resp: &mut Response) -> IronResult<()> {
        let page = match resp.extensions.get::<HandlebarsEngine>() {
            Some(h) => {
                let name = &h.name;
                let value = &h.value;
                let page = self.registry.render(name.as_slice(), value).unwrap();
                Some(page)
            },
            None => {
                None
            }
        };

        if page.is_some() {
            resp.headers.set(headers::ContentType(FromStr::from_str("text/html;charset=utf-8").unwrap()));
            resp.set_mut(status::Ok).set_mut(page.unwrap());
        }

        Ok(())
    }
}

fn hello_world(_: &mut Request) -> IronResult<Response> {
    let mut resp = Response::new();

    let mut data = BTreeMap::new();
    data.insert("title".to_string(), "Handlebars on Iron".to_json());

    Ok(resp.set(Template::new("index".to_string(), data.to_json())))
}

/*
fn main() {
let mut chain = ChainBuilder::new(hello_world);
chain.link_after(HandlebarsEngine::new());
Iron::new(chain).listen("localhost:3000").unwrap();
}
*/
<commit_msg>(feat) update template interface, added tests<commit_after>use std::str::FromStr;
use std::io::{File};

use iron::prelude::*;
use iron::{AfterMiddleware, typemap};
use iron::modifier::Modifier;
use iron::status;
use iron::headers;

use glob::glob;

use handlebars::Handlebars;
use serialize::json::{ToJson, Json};

pub struct HandlebarsEngine {
    registry: Handlebars
}

pub struct Template {
    name: String,
    value: Json
}

impl Template {
    pub fn new<T: ToJson>(name: &str, value: T) -> Template {
        Template {
            name: name.to_string(),
            value: value.to_json()
        }
    }
}

impl Modifier<Response> for Template {
    fn modify(self, resp: &mut Response) {
        resp.extensions.insert::<HandlebarsEngine>(self);
    }
}

impl typemap::Key for HandlebarsEngine {
    type Value = Template;
}

impl HandlebarsEngine {
    pub fn new(prefix: &str, suffix: &str) -> HandlebarsEngine {
        let mut r = Handlebars::new();

        let mut pattern = String::new();
        pattern.push_str(prefix);
        pattern.push_str("**/*");
        pattern.push_str(suffix);

        for path in glob(pattern.as_slice()) {
            let disp = path.as_str().unwrap();
            let t = r.register_template_string(
                disp.slice(prefix.len(), disp.len()-suffix.len()),
                File::open(&path).ok()
                    .expect(format!("Failed to open file {}", disp).as_slice())
                    .read_to_string().unwrap());

            if t.is_err() {
                panic!("Failed to create template.");
            }
        }

        HandlebarsEngine {
            registry: r
        }
    }
}

impl AfterMiddleware for HandlebarsEngine {
    fn after(&self, _: &mut Request, resp: &mut Response) -> IronResult<()> {
        let page = match resp.extensions.get::<HandlebarsEngine>() {
            Some(h) => {
                let name = &h.name;
                let value = &h.value;
                let page = self.registry.render(name.as_slice(), value).unwrap();
                Some(page)
            },
            None => {
                None
            }
        };

        if page.is_some() {
            resp.headers.set(headers::ContentType(FromStr::from_str("text/html;charset=utf-8").unwrap()));
            resp.set_mut(status::Ok).set_mut(page.unwrap());
        }

        Ok(())
    }
}

#[cfg(test)]
mod test {
    use serialize::json::ToJson;
    use std::collections::BTreeMap;
    use iron::prelude::*;
    use middleware::*;

    fn hello_world() -> IronResult<Response> {
        let resp = Response::new();

        let mut data = BTreeMap::new();
        data.insert("title".to_string(), "Handlebars on Iron".to_json());

        Ok(resp.set(Template::new("index", data)))
    }

    #[test]
    fn test_resp_set() {
        let resp = hello_world().ok().expect("response expected");

        match resp.extensions.get::<HandlebarsEngine>() {
            Some(h) => {
                assert_eq!(h.name, "index".to_string());
                assert_eq!(h.value.as_object().unwrap()
                           .get(&"title".to_string()).unwrap()
                           .as_string().unwrap(),
                           "Handlebars on Iron");
            },
            None => panic!("template expected")
        }
    }
}

/*
fn main() {
let mut chain = ChainBuilder::new(hello_world);
chain.link_after(HandlebarsEngine::new());
Iron::new(chain).listen("localhost:3000").unwrap();
}
*/
<|endoftext|>


<commit_before>#![crate_name = "foo"]

// ignore-tidy-linelength

// @has foo/struct.Foo.html '//*[@class="docblock"]/p/a[@href="https://doc.rust-lang.org/nightly/std/primitive.u32.html"]' 'u32'
// @has foo/struct.Foo.html '//*[@class="docblock"]/p/a[@href="https://doc.rust-lang.org/nightly/std/primitive.i64.html"]' 'i64'
// @has foo/struct.Foo.html '//*[@class="docblock"]/p/a[@href="https://doc.rust-lang.org/nightly/std/primitive.i32.html"]' 'std::primitive::i32'
// @has foo/struct.Foo.html '//*[@class="docblock"]/p/a[@href="https://doc.rust-lang.org/nightly/std/primitive.str.html"]' 'std::primitive::str'

// FIXME: this doesn't resolve
// @ has foo/struct.Foo.html '//*[@class="docblock"]/p/a[@href="https://doc.rust-lang.org/nightly/std/primitive.i32.html#associatedconstant.MAX"]' 'std::primitive::i32::MAX'

/// It contains [`u32`] and [i64].
/// It also links to [std::primitive::i32], [std::primitive::str],
/// and [`std::primitive::i32::MAX`].
pub struct Foo;
<commit_msg>Re-enable test case<commit_after>#![crate_name = "foo"]

// ignore-tidy-linelength

// @has foo/struct.Foo.html '//*[@class="docblock"]/p/a[@href="https://doc.rust-lang.org/nightly/std/primitive.u32.html"]' 'u32'
// @has foo/struct.Foo.html '//*[@class="docblock"]/p/a[@href="https://doc.rust-lang.org/nightly/std/primitive.i64.html"]' 'i64'
// @has foo/struct.Foo.html '//*[@class="docblock"]/p/a[@href="https://doc.rust-lang.org/nightly/std/primitive.i32.html"]' 'std::primitive::i32'
// @has foo/struct.Foo.html '//*[@class="docblock"]/p/a[@href="https://doc.rust-lang.org/nightly/std/primitive.str.html"]' 'std::primitive::str'

// @has foo/struct.Foo.html '//*[@class="docblock"]/p/a[@href="https://doc.rust-lang.org/nightly/std/primitive.i32.html#associatedconstant.MAX"]' 'std::primitive::i32::MAX'

/// It contains [`u32`] and [i64].
/// It also links to [std::primitive::i32], [std::primitive::str],
/// and [`std::primitive::i32::MAX`].
pub struct Foo;
<|endoftext|>


<commit_before>// Copyright (C) 2016 Élisabeth HENRY.
//
// This file is part of Crowbook.
//
// Crowbook is free software: you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as published
// by the Free Software Foundation, either version 2.1 of the License, or
// (at your option) any later version.
//
// Caribon is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU Lesser General Public License for more details.
//
// You should have received ba copy of the GNU Lesser General Public License
// along with Crowbook.  If not, see <http://www.gnu.org/licenses/>.

use token::Token;
use error::{Result,Error, Source};

use std::mem;
use std::fs::File;
use std::path::Path;
use std::convert::AsRef;
use std::io::Read;
use std::collections::HashMap;

use cmark::{Parser as CMParser, Event, Tag, Options, OPTION_ENABLE_FOOTNOTES, OPTION_ENABLE_TABLES};

/// A parser that reads markdown and convert it to AST (a vector of `Token`s)
///
/// This AST can then be used by various renderes.
///
/// As this Parser uses Pulldown-cmark's one, it should be able to parse most
/// *valid* CommonMark variant of Markdown.
///
/// Compared to other Markdown parser, it might fail more often on invalid code, e.g.
/// footnotes references that are not defined anywhere.
///
/// # Examples
///
/// ```
/// use crowbook::Parser;
/// let mut parser = Parser::new();
/// let result = parser.parse("Some *valid* Markdown[^1]\n\n[^1]: with a valid footnote");
/// assert!(result.is_ok());
/// ```
///
/// ```
/// use crowbook::Parser;
/// let mut parser = Parser::new();
/// let result = parser.parse("Some footnote pointing to nothing[^1] ");
/// assert!(result.is_err());
/// ```
pub struct Parser {
    footnotes: HashMap<String, Vec<Token>>,
    source: Source,
}

impl Parser {
    /// Creates a parser
    pub fn new() -> Parser {
        Parser {
            footnotes: HashMap::new(),
            source: Source::empty(),
        }
    }

    /// Sets a parser's source file
    pub fn set_source_file(&mut self, s: &str) {
        self.source = Source::new(s);
    }

    /// Parse a file and returns an AST or an error
    pub fn parse_file<P: AsRef<Path>>(&mut self, filename: P) -> Result<Vec<Token>> {
        let path: &Path = filename.as_ref();
        let mut f = try!(File::open(path).map_err(|_| Error::file_not_found(&self.source,
                                                                                "markdown file",
                                                                                format!("{}", path.display()))));
        let mut s = String::new();

        try!(f.read_to_string(&mut s).map_err(|_| Error::parser(&self.source,
                                                                    format!("file {} contains invalid UTF-8, could not parse it", path.display()))));
        self.parse(&s)
    }

    /// Parse a string and returns an AST, or an Error.
    pub fn parse(&mut self, s: &str) -> Result<Vec<Token>> {
        let mut opts = Options::empty();
        opts.insert(OPTION_ENABLE_TABLES);
        opts.insert(OPTION_ENABLE_FOOTNOTES);
        let mut p = CMParser::new_ext(s, opts);

        let mut res = vec!();
        try!(self.parse_events(&mut p, &mut res, None));

        try!(self.parse_footnotes(&mut res));

        collapse(&mut res);

        find_standalone(&mut res);
        Ok(res)
    }

    /// Parse an inline string and returns a list of `Token`.
    ///
    /// This function removes the outermost `Paragraph` in most of the
    /// cases, as it is meant to be used for an inline string (e.g. metadata)
    pub fn parse_inline(&mut self, s: &str) -> Result<Vec<Token>> {
        let mut tokens = try!(self.parse(s));
        // Unfortunately, parser will put all this in a paragraph, so we might need to remove it.
        if tokens.len() == 1 {
            let res = match tokens[0] {
                Token::Paragraph(ref mut v) => {
                    Some(mem::replace(v, vec!()))
                },
                _ => None,
            };
            match res {
                Some(tokens) => Ok(tokens),
                _ => Ok(tokens),
            }
        } else {
            Ok(tokens)
        }
    }

    /// Replace footnote reference with their definition
    fn parse_footnotes(&mut self, v: &mut Vec<Token>) ->Result<()> {
        for token in v {
            match *token {
                Token::Footnote(ref mut content) => {
                    let reference = if let Token::Str(ref text) = content[0] {
                        text.clone()
                    } else {
                        panic!("Reference is not a vector of a single Token::Str");
                    };
                    if let Some(in_vec) = self.footnotes.get(&reference) {
                        *content = in_vec.clone();
                    } else {
                        return Err(Error::parser(&self.source,
                                                 format!("footnote reference {} does not have a matching definition", &reference)));
                    }
                },
                Token::Paragraph(ref mut vec) | Token::Header(_, ref mut vec) | Token::Emphasis(ref mut vec)
                    | Token::Strong(ref mut vec) | Token::Code(ref mut vec) | Token::BlockQuote(ref mut vec)
                    | Token::CodeBlock(_, ref mut vec) | Token::List(ref mut vec) | Token::OrderedList(_, ref mut vec)
                    | Token::Item(ref mut vec) | Token::Table(_, ref mut vec) | Token::TableHead(ref mut vec)
                    | Token::TableRow(ref mut vec) | Token::TableCell(ref mut vec) | Token::Link(_, _, ref mut vec)
                    | Token::Image(_, _, ref mut vec) => try!(self.parse_footnotes(vec)),
                _ => (),
            }
        }
        Ok(())
    }

    fn parse_events<'a>(&mut self, p: &mut CMParser<'a>, v: &mut Vec<Token>, current_tag: Option<&Tag>) -> Result<()> {
        while let Some(event) = p.next() {
            match event {
                Event::Html(text) | Event::InlineHtml(text) | Event::Text(text) => {
                    v.push(Token::Str(text.into_owned()));
                },
                Event::Start(tag) => try!(self.parse_tag(p, v, tag)),
                Event::End(tag) => {
                    debug_assert!(format!("{:?}", Some(&tag)) == format!("{:?}", current_tag),
                                  format!("Error: opening and closing tags mismatch!\n{:?} ≠ {:?}",
                                          tag,
                                          current_tag));
                    break;
                },
                Event::SoftBreak => v.push(Token::SoftBreak),
                Event::HardBreak => v.push(Token::HardBreak),
                Event::FootnoteReference(text) => v.push(Token::Footnote(vec!(Token::Str(text.into_owned())))),
            }
        }
        Ok(())
    }

    fn parse_tag<'a>(&mut self, p: &mut CMParser<'a>, v: &mut Vec<Token>, tag: Tag<'a>) -> Result<()> {
        let mut res = vec!();

        try!(self.parse_events(p, &mut res, Some(&tag)));

        let token = match tag {
            Tag::Paragraph => Token::Paragraph(res),
            Tag::Emphasis => Token::Emphasis(res),
            Tag::Strong => Token::Strong(res),
            Tag::Code => Token::Code(res),
            Tag::Header(x) => Token::Header(x, res),
            Tag::Link(url, title) => Token::Link(url.into_owned(), title.into_owned(), res),
            Tag::Image(url, title) => Token::Image(url.into_owned(), title.into_owned(), res),
            Tag::Rule => Token::Rule,
            Tag::List(opt) => {
                if let Some(n) = opt {
                    Token::OrderedList(n, res)
                } else {
                    Token::List(res)
                }},
            Tag::Item => Token::Item(res),
            Tag::BlockQuote => Token::BlockQuote(res),
            Tag::CodeBlock(language) => Token::CodeBlock(language.into_owned(), res),
            Tag::Table(n) => Token::Table(n, res),
            Tag::TableHead => Token::TableHead(res),
            Tag::TableRow => Token::TableRow(res),
            Tag::TableCell => Token::TableCell(res),
            Tag::FootnoteDefinition(reference) => {
                if self.footnotes.contains_key(reference.as_ref()) {
                    println!("Warning: footnote definition for {} but previous definition already exist, overriding it", reference);
                }
                self.footnotes.insert(reference.into_owned(), res);
                Token::SoftBreak
            },
        };
        v.push(token);
        Ok(())
    }
}

/// Replace consecutives Strs by a Str of both, collapse soft breaks to previous std and so on
fn collapse(ast: &mut Vec<Token>) {
    if ast.len() < 2 {
        return;
    }

    let mut i = 0;
    while i < ast.len() {
        if ast[i].is_str() {
            if i < ast.len() - 1 {
                if ast[i+1].is_str() {
                    // Two consecutives Str, concatenate them
                    let token = ast.remove(i+1);
                    if let (&mut Token::Str(ref mut dest), Token::Str(ref source)) = (&mut ast[i], token) {
                        dest.push(' ');
                        dest.push_str(source);
                        continue;
                    } else {
                        unreachable!();
                    }
                } else if ast[i+1] == Token::SoftBreak {
                    ast.remove(i+1);
                    if let &mut Token::Str(ref mut dest) = &mut ast[i] {
                        dest.push(' ');
                        continue;
                    } else {
                        unreachable!();
                    }
                }
            }
        }

        // If token is containing others, recurse into them
        if let Some(ref mut inner) = ast[i].inner_mut() {
            collapse(inner);
        }
        i += 1;
    }
}

/// Replace images which are alone in a paragraph by standalone images
fn find_standalone(ast: &mut Vec<Token>) {
    for token in ast {
        let res = if let &mut Token::Paragraph(ref mut inner) = token {
            if inner.len() == 1 {
                if inner[0].is_image() {
                    if let Token::Image(source, title, inner) = mem::replace(&mut inner[0], Token::Rule) {
                        Token::StandaloneImage(source, title, inner)
                    } else {
                        unreachable!();
                    }
                } else {
                    continue;
                }
            } else {
                continue;
            }
        } else {
            continue;
        };

        *token = res;
    }
}
<commit_msg>Fix collapse of SoftBreak to actually do nothing<commit_after>// Copyright (C) 2016 Élisabeth HENRY.
//
// This file is part of Crowbook.
//
// Crowbook is free software: you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as published
// by the Free Software Foundation, either version 2.1 of the License, or
// (at your option) any later version.
//
// Caribon is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU Lesser General Public License for more details.
//
// You should have received ba copy of the GNU Lesser General Public License
// along with Crowbook.  If not, see <http://www.gnu.org/licenses/>.

use token::Token;
use error::{Result,Error, Source};

use std::mem;
use std::fs::File;
use std::path::Path;
use std::convert::AsRef;
use std::io::Read;
use std::collections::HashMap;

use cmark::{Parser as CMParser, Event, Tag, Options, OPTION_ENABLE_FOOTNOTES, OPTION_ENABLE_TABLES};

/// A parser that reads markdown and convert it to AST (a vector of `Token`s)
///
/// This AST can then be used by various renderes.
///
/// As this Parser uses Pulldown-cmark's one, it should be able to parse most
/// *valid* CommonMark variant of Markdown.
///
/// Compared to other Markdown parser, it might fail more often on invalid code, e.g.
/// footnotes references that are not defined anywhere.
///
/// # Examples
///
/// ```
/// use crowbook::Parser;
/// let mut parser = Parser::new();
/// let result = parser.parse("Some *valid* Markdown[^1]\n\n[^1]: with a valid footnote");
/// assert!(result.is_ok());
/// ```
///
/// ```
/// use crowbook::Parser;
/// let mut parser = Parser::new();
/// let result = parser.parse("Some footnote pointing to nothing[^1] ");
/// assert!(result.is_err());
/// ```
pub struct Parser {
    footnotes: HashMap<String, Vec<Token>>,
    source: Source,
}

impl Parser {
    /// Creates a parser
    pub fn new() -> Parser {
        Parser {
            footnotes: HashMap::new(),
            source: Source::empty(),
        }
    }

    /// Sets a parser's source file
    pub fn set_source_file(&mut self, s: &str) {
        self.source = Source::new(s);
    }

    /// Parse a file and returns an AST or an error
    pub fn parse_file<P: AsRef<Path>>(&mut self, filename: P) -> Result<Vec<Token>> {
        let path: &Path = filename.as_ref();
        let mut f = try!(File::open(path).map_err(|_| Error::file_not_found(&self.source,
                                                                                "markdown file",
                                                                                format!("{}", path.display()))));
        let mut s = String::new();

        try!(f.read_to_string(&mut s).map_err(|_| Error::parser(&self.source,
                                                                    format!("file {} contains invalid UTF-8, could not parse it", path.display()))));
        self.parse(&s)
    }

    /// Parse a string and returns an AST, or an Error.
    pub fn parse(&mut self, s: &str) -> Result<Vec<Token>> {
        let mut opts = Options::empty();
        opts.insert(OPTION_ENABLE_TABLES);
        opts.insert(OPTION_ENABLE_FOOTNOTES);
        let mut p = CMParser::new_ext(s, opts);

        let mut res = vec!();
        try!(self.parse_events(&mut p, &mut res, None));

        try!(self.parse_footnotes(&mut res));

        collapse(&mut res);

        find_standalone(&mut res);
        Ok(res)
    }

    /// Parse an inline string and returns a list of `Token`.
    ///
    /// This function removes the outermost `Paragraph` in most of the
    /// cases, as it is meant to be used for an inline string (e.g. metadata)
    pub fn parse_inline(&mut self, s: &str) -> Result<Vec<Token>> {
        let mut tokens = try!(self.parse(s));
        // Unfortunately, parser will put all this in a paragraph, so we might need to remove it.
        if tokens.len() == 1 {
            let res = match tokens[0] {
                Token::Paragraph(ref mut v) => {
                    Some(mem::replace(v, vec!()))
                },
                _ => None,
            };
            match res {
                Some(tokens) => Ok(tokens),
                _ => Ok(tokens),
            }
        } else {
            Ok(tokens)
        }
    }

    /// Replace footnote reference with their definition
    fn parse_footnotes(&mut self, v: &mut Vec<Token>) ->Result<()> {
        for token in v {
            match *token {
                Token::Footnote(ref mut content) => {
                    let reference = if let Token::Str(ref text) = content[0] {
                        text.clone()
                    } else {
                        panic!("Reference is not a vector of a single Token::Str");
                    };
                    if let Some(in_vec) = self.footnotes.get(&reference) {
                        *content = in_vec.clone();
                    } else {
                        return Err(Error::parser(&self.source,
                                                 format!("footnote reference {} does not have a matching definition", &reference)));
                    }
                },
                Token::Paragraph(ref mut vec) | Token::Header(_, ref mut vec) | Token::Emphasis(ref mut vec)
                    | Token::Strong(ref mut vec) | Token::Code(ref mut vec) | Token::BlockQuote(ref mut vec)
                    | Token::CodeBlock(_, ref mut vec) | Token::List(ref mut vec) | Token::OrderedList(_, ref mut vec)
                    | Token::Item(ref mut vec) | Token::Table(_, ref mut vec) | Token::TableHead(ref mut vec)
                    | Token::TableRow(ref mut vec) | Token::TableCell(ref mut vec) | Token::Link(_, _, ref mut vec)
                    | Token::Image(_, _, ref mut vec) => try!(self.parse_footnotes(vec)),
                _ => (),
            }
        }
        Ok(())
    }

    fn parse_events<'a>(&mut self, p: &mut CMParser<'a>, v: &mut Vec<Token>, current_tag: Option<&Tag>) -> Result<()> {
        while let Some(event) = p.next() {
            match event {
                Event::Html(text) | Event::InlineHtml(text) | Event::Text(text) => {
                    v.push(Token::Str(text.into_owned()));
                },
                Event::Start(tag) => try!(self.parse_tag(p, v, tag)),
                Event::End(tag) => {
                    debug_assert!(format!("{:?}", Some(&tag)) == format!("{:?}", current_tag),
                                  format!("Error: opening and closing tags mismatch!\n{:?} ≠ {:?}",
                                          tag,
                                          current_tag));
                    break;
                },
                Event::SoftBreak => v.push(Token::SoftBreak),
                Event::HardBreak => v.push(Token::HardBreak),
                Event::FootnoteReference(text) => v.push(Token::Footnote(vec!(Token::Str(text.into_owned())))),
            }
        }
        Ok(())
    }

    fn parse_tag<'a>(&mut self, p: &mut CMParser<'a>, v: &mut Vec<Token>, tag: Tag<'a>) -> Result<()> {
        let mut res = vec!();

        try!(self.parse_events(p, &mut res, Some(&tag)));

        let token = match tag {
            Tag::Paragraph => Token::Paragraph(res),
            Tag::Emphasis => Token::Emphasis(res),
            Tag::Strong => Token::Strong(res),
            Tag::Code => Token::Code(res),
            Tag::Header(x) => Token::Header(x, res),
            Tag::Link(url, title) => Token::Link(url.into_owned(), title.into_owned(), res),
            Tag::Image(url, title) => Token::Image(url.into_owned(), title.into_owned(), res),
            Tag::Rule => Token::Rule,
            Tag::List(opt) => {
                if let Some(n) = opt {
                    Token::OrderedList(n, res)
                } else {
                    Token::List(res)
                }},
            Tag::Item => Token::Item(res),
            Tag::BlockQuote => Token::BlockQuote(res),
            Tag::CodeBlock(language) => Token::CodeBlock(language.into_owned(), res),
            Tag::Table(n) => Token::Table(n, res),
            Tag::TableHead => Token::TableHead(res),
            Tag::TableRow => Token::TableRow(res),
            Tag::TableCell => Token::TableCell(res),
            Tag::FootnoteDefinition(reference) => {
                if self.footnotes.contains_key(reference.as_ref()) {
                    println!("Warning: footnote definition for {} but previous definition already exist, overriding it", reference);
                }
                self.footnotes.insert(reference.into_owned(), res);
                Token::SoftBreak
            },
        };
        v.push(token);
        Ok(())
    }
}

/// Replace consecutives Strs by a Str of both, collapse soft breaks to previous std and so on
fn collapse(ast: &mut Vec<Token>) {
    if ast.len() < 2 {
        return;
    }

    let mut i = 0;
    while i < ast.len() {
        if ast[i].is_str() {
            if i < ast.len() - 1 {
                if ast[i+1].is_str() {
                    // Two consecutives Str, concatenate them
                    let token = ast.remove(i+1);
                    if let (&mut Token::Str(ref mut dest), Token::Str(ref source)) = (&mut ast[i], token) {
//                        dest.push(' ');
                        dest.push_str(source);
                        continue;
                    } else {
                        unreachable!();
                    }
                } else if ast[i+1] == Token::SoftBreak {
                    ast.remove(i+1);
                    if let &mut Token::Str(ref mut dest) = &mut ast[i] {
                        dest.push(' ');
                        continue;
                    } else {
                        unreachable!();
                    }
                }
            }
        }

        // If token is containing others, recurse into them
        if let Some(ref mut inner) = ast[i].inner_mut() {
            collapse(inner);
        }
        i += 1;
    }
}

/// Replace images which are alone in a paragraph by standalone images
fn find_standalone(ast: &mut Vec<Token>) {
    for token in ast {
        let res = if let &mut Token::Paragraph(ref mut inner) = token {
            if inner.len() == 1 {
                if inner[0].is_image() {
                    if let Token::Image(source, title, inner) = mem::replace(&mut inner[0], Token::Rule) {
                        Token::StandaloneImage(source, title, inner)
                    } else {
                        unreachable!();
                    }
                } else {
                    continue;
                }
            } else {
                continue;
            }
        } else {
            continue;
        };

        *token = res;
    }
}
<|endoftext|>


<commit_before>use std::collections::HashMap;
use std::net::TcpStream;
use rust_ofp::ofp_controller::openflow0x01::OF0x01Controller;
use rust_ofp::openflow0x01::{Action, PacketIn, PacketOut, Pattern, PseudoPort, SwitchFeatures};
use rust_ofp::openflow0x01::message::{add_flow, parse_payload};

/// Implements L2 learning switch functionality. Switches forward packets to the
/// learning controller, which will examine the packet and learn the source-port
/// mapping. If the controller already knows the destination location, it pushes
/// a flow entry down to the switch that matches traffic between the packet's
/// source and destination.
///
/// Abstractly, a learning switch can be thought of in terms of two logically
/// distinct components.
///
///  - A _Learning Module_ that builds a map from host MAC addresses to the
///    switch port on which they are connected.
///
///  - A _Routing Module_ that performs traffic routing. If the switch receives
///    a packet which the learning module has learned of the destination location,
///    it forwards the packet directly on the associated port. If the location of
///    the destination is unknown, it floods the packet out all ports.
pub struct LearningSwitch {
    known_hosts: HashMap<u64, u16>,
}

impl LearningSwitch {
    fn learning_packet_in(&mut self, pkt: &PacketIn) {
        let pk = parse_payload(&pkt.input_payload);
        self.known_hosts.insert(pk.dl_src, pkt.port);
    }

    fn routing_packet_in(&mut self, sw: u64, pkt: PacketIn, stream: &mut TcpStream) {
        let pk = parse_payload(&pkt.input_payload);
        let pkt_dst = pk.dl_dst;
        let pkt_src = pk.dl_src;
        let out_port = self.known_hosts.get(&pkt_dst);
        match out_port {
            Some(p) => {
                let src_port = pkt.port;
                let mut src_dst_match = Pattern::match_all();
                src_dst_match.dl_dst = Some(pkt_dst);
                src_dst_match.dl_src = Some(pkt_src);
                let mut dst_src_match = Pattern::match_all();
                dst_src_match.dl_dst = Some(pkt_src);
                dst_src_match.dl_src = Some(pkt_dst);
                println!("Installing rule for host {:?} to {:?}.", pkt_src, pkt_dst);
                let actions = vec![Action::Output(PseudoPort::PhysicalPort(*p))];
                Self::send_flow_mod(sw, 0, add_flow(10, src_dst_match, actions), stream);
                println!("Installing rule for host {:?} to {:?}.", pkt_dst, pkt_src);
                let actions = vec![Action::Output(PseudoPort::PhysicalPort(src_port))];
                Self::send_flow_mod(sw, 0, add_flow(10, dst_src_match, actions), stream);
                let pkt_out = PacketOut {
                    output_payload: pkt.input_payload,
                    port_id: None,
                    apply_actions: vec![Action::Output(PseudoPort::PhysicalPort(*p))],
                };
                Self::send_packet_out(sw, 0, pkt_out, stream)
            }
            None => {
                println!("Known Hosts:\t{:?}", self.known_hosts);
                println!("Flooding to {:?}", pkt_dst);
                let pkt_out = PacketOut {
                    output_payload: pkt.input_payload,
                    port_id: None,
                    apply_actions: vec![Action::Output(PseudoPort::AllPorts)],
                };
                Self::send_packet_out(sw, 0, pkt_out, stream)
            }
        }
    }
}

impl OF0x01Controller for LearningSwitch {
    fn new() -> LearningSwitch {
        LearningSwitch { known_hosts: HashMap::new() }
    }

    fn switch_connected(&mut self, _: u64, _: SwitchFeatures, _: &mut TcpStream) {}

    fn switch_disconnected(&mut self, _: u64) {}

    fn packet_in(&mut self, sw: u64, _: u32, pkt: PacketIn, stream: &mut TcpStream) {
        println!("{:?}", pkt);
        self.learning_packet_in(&pkt);
        self.routing_packet_in(sw, pkt, stream);
    }
}
<commit_msg>Remove debug printouts<commit_after>use std::collections::HashMap;
use std::net::TcpStream;
use rust_ofp::ofp_controller::openflow0x01::OF0x01Controller;
use rust_ofp::openflow0x01::{Action, PacketIn, PacketOut, Pattern, PseudoPort, SwitchFeatures};
use rust_ofp::openflow0x01::message::{add_flow, parse_payload};

/// Implements L2 learning switch functionality. Switches forward packets to the
/// learning controller, which will examine the packet and learn the source-port
/// mapping. If the controller already knows the destination location, it pushes
/// a flow entry down to the switch that matches traffic between the packet's
/// source and destination.
///
/// Abstractly, a learning switch can be thought of in terms of two logically
/// distinct components.
///
///  - A _Learning Module_ that builds a map from host MAC addresses to the
///    switch port on which they are connected.
///
///  - A _Routing Module_ that performs traffic routing. If the switch receives
///    a packet which the learning module has learned of the destination location,
///    it forwards the packet directly on the associated port. If the location of
///    the destination is unknown, it floods the packet out all ports.
pub struct LearningSwitch {
    known_hosts: HashMap<u64, u16>,
}

impl LearningSwitch {
    fn learning_packet_in(&mut self, pkt: &PacketIn) {
        let pk = parse_payload(&pkt.input_payload);
        self.known_hosts.insert(pk.dl_src, pkt.port);
    }

    fn routing_packet_in(&mut self, sw: u64, pkt: PacketIn, stream: &mut TcpStream) {
        let pk = parse_payload(&pkt.input_payload);
        let pkt_dst = pk.dl_dst;
        let pkt_src = pk.dl_src;
        let out_port = self.known_hosts.get(&pkt_dst);
        match out_port {
            Some(p) => {
                let src_port = pkt.port;
                let mut src_dst_match = Pattern::match_all();
                src_dst_match.dl_dst = Some(pkt_dst);
                src_dst_match.dl_src = Some(pkt_src);
                let mut dst_src_match = Pattern::match_all();
                dst_src_match.dl_dst = Some(pkt_src);
                dst_src_match.dl_src = Some(pkt_dst);
                println!("Installing rule for host {:?} to {:?}.", pkt_src, pkt_dst);
                let actions = vec![Action::Output(PseudoPort::PhysicalPort(*p))];
                Self::send_flow_mod(sw, 0, add_flow(10, src_dst_match, actions), stream);
                println!("Installing rule for host {:?} to {:?}.", pkt_dst, pkt_src);
                let actions = vec![Action::Output(PseudoPort::PhysicalPort(src_port))];
                Self::send_flow_mod(sw, 0, add_flow(10, dst_src_match, actions), stream);
                let pkt_out = PacketOut {
                    output_payload: pkt.input_payload,
                    port_id: None,
                    apply_actions: vec![Action::Output(PseudoPort::PhysicalPort(*p))],
                };
                Self::send_packet_out(sw, 0, pkt_out, stream)
            }
            None => {
                println!("Flooding to {:?}", pkt_dst);
                let pkt_out = PacketOut {
                    output_payload: pkt.input_payload,
                    port_id: None,
                    apply_actions: vec![Action::Output(PseudoPort::AllPorts)],
                };
                Self::send_packet_out(sw, 0, pkt_out, stream)
            }
        }
    }
}

impl OF0x01Controller for LearningSwitch {
    fn new() -> LearningSwitch {
        LearningSwitch { known_hosts: HashMap::new() }
    }

    fn switch_connected(&mut self, _: u64, _: SwitchFeatures, _: &mut TcpStream) {}

    fn switch_disconnected(&mut self, _: u64) {}

    fn packet_in(&mut self, sw: u64, _: u32, pkt: PacketIn, stream: &mut TcpStream) {
        self.learning_packet_in(&pkt);
        self.routing_packet_in(sw, pkt, stream);
    }
}
<|endoftext|>