<commit_before>extern crate tui;
extern crate termion;
extern crate nalgebra;
extern crate steering;
extern crate alga;

use std::io;
use std::thread;
use std::time;
use std::sync::mpsc;

use termion::event;
use termion::input::TermRead;

use tui::Terminal;
use tui::backend::TermionBackend;
use tui::widgets::{Widget, Block, border, SelectableList, List};
use tui::widgets::canvas::{Canvas, Map, MapResolution, Line};
use tui::layout::{Group, Direction, Size};
use tui::style::{Style, Color, Modifier};

use nalgebra::Vector3;
use alga::general::AbstractModule;
use steering::Steerable;
use steering::SteeringAcceleration;
use steering::Seek;
use steering::Flee;
use steering::Pursue;
use steering::SteeringAccelerationCalculator;
use steering::SteeringBehavior;

struct App<'a> {
    items: Vec<&'a str>,
    selected: usize,
    events: Vec<(&'a str, &'a str)>,
    info_style: Style,
    warning_style: Style,
    error_style: Style,
    critical_style: Style,
    v: Vehicle,
    behavior: Option<&'a mut SteeringAccelerationCalculator<f32>>,
    positions: Vec<String>,
}

impl<'a> App<'a> {
    fn new() -> App<'a> {
        App {
            items: vec!["Seek", "Flee", "Pursue"],
            selected: 0,
            events: vec![("Event1", "INFO"),
                         ("Event2", "INFO"),
                         ("Event3", "CRITICAL"),
                         ("Event4", "ERROR"),
                         ("Event5", "INFO"),
                         ("Event6", "INFO"),
                         ("Event7", "WARNING"),
                         ("Event8", "INFO"),
                         ("Event9", "INFO"),
                         ("Event10", "INFO"),
                         ("Event11", "CRITICAL"),
                         ("Event12", "INFO"),
                         ("Event13", "INFO"),
                         ("Event14", "INFO"),
                         ("Event15", "INFO"),
                         ("Event16", "INFO"),
                         ("Event17", "ERROR"),
                         ("Event18", "ERROR"),
                         ("Event19", "INFO"),
                         ("Event20", "INFO"),
                         ("Event21", "WARNING"),
                         ("Event22", "INFO"),
                         ("Event23", "INFO"),
                         ("Event24", "WARNING"),
                         ("Event25", "INFO"),
                         ("Event26", "INFO")],
            info_style: Style::default().fg(Color::White),
            warning_style: Style::default().fg(Color::Yellow),
            error_style: Style::default().fg(Color::Magenta),
            critical_style: Style::default().fg(Color::Red),
            v: Vehicle::new(),
            behavior: None,
            positions: vec![],
        }
    }

    fn advance(&mut self) {
        let event = self.events.pop().unwrap();
        self.events.insert(0, event);
        match self.behavior {
            Some(ref mut a) => self.v.advance(*a, 500f32),
            None => (),
        };
        self.positions.clear();
        self.positions.push(format!("{}:{}:{}",
                                    self.v.get_position().as_slice()[0],
                                    self.v.get_position().as_slice()[1],
                                    self.v.get_position().as_slice()[2]));
    }
}

enum Event {
    Input(event::Key),
    Tick,
}

struct Vehicle {
    linear_velocity: Vector3<f32>,
    position: Vector3<f32>,
    angular_velocity: f32,
    bounding_radius: f32,
}

impl Steerable<f32> for Vehicle {
    fn get_linear_velocity(&self) -> &Vector3<f32> {
        &self.linear_velocity
    }

    fn get_angular_velocity(&self) -> f32 {
        self.angular_velocity
    }

    fn get_bounding_radius(&self) -> f32 {
        self.bounding_radius
    }

    fn get_position(&self) -> &Vector3<f32> {
        &self.position
    }
}

impl Vehicle {
    fn new() -> Self {
        Vehicle {
            linear_velocity: Vector3::new(1.0, 0.0, 0.0),
            position: Vector3::new(-50.0, 50.0, 0.0),
            angular_velocity: 0.0,
            bounding_radius: 2.0,
        }
    }

    fn advance(&mut self, calc: &mut SteeringAccelerationCalculator<f32>, milis: f32) {
        let mut sa = SteeringAcceleration::default();
        calc.calculate_steering(&mut sa, self);
        self.linear_velocity += sa.linear;
        self.angular_velocity += sa.angular;
        self.position = self.position + self.linear_velocity.multiply_by(milis / 1000.0);
    }
}

fn main() {
    // Terminal initialization
    let backend = TermionBackend::new().unwrap();
    let mut terminal = Terminal::new(backend).unwrap();
    let (tx, rx) = mpsc::channel();
    let input_tx = tx.clone();
    let clock_tx = tx.clone();

    // Input
    thread::spawn(move || {
        let stdin = io::stdin();
        for c in stdin.keys() {
            let evt = c.unwrap();
            input_tx.send(Event::Input(evt)).unwrap();
            if evt == event::Key::Char('q') {
                break;
            }
        }
    });

    // Tick
    thread::spawn(move || {
        loop {
            clock_tx.send(Event::Tick).unwrap();
            thread::sleep(time::Duration::from_millis(500));
        }
    });

    // App
    let mut target = Vehicle {
        linear_velocity: Vector3::new(1.0, 0.0, 0.0),
        position: Vector3::new(0.0, 0.0, 0.0),
        angular_velocity: 0.0,
        bounding_radius: 2.0,
    };
    let mut behavior = Pursue {
        behavior: SteeringBehavior {
            enabled: true,
            limiter: None,
        },
        target: &target,
        max_prediction_time : 100.0f32,
    };
    let mut app = App::new();
    app.behavior = Some(&mut behavior);
    // First draw call
    terminal.clear().unwrap();
    terminal.hide_cursor().unwrap();
    draw(&mut terminal, &app, &target);

    loop {
        let evt = rx.recv().unwrap();
        match evt {
            Event::Input(input) => {
                match input {
                    event::Key::Char('q') => {
                        break;
                    }
                    event::Key::Down => {
                        app.selected += 1;
                        if app.selected > app.items.len() - 1 {
                            app.selected = 0;
                        }
                    }
                    event::Key::Up => {
                        if app.selected > 0 {
                            app.selected -= 1;
                        } else {
                            app.selected = app.items.len() - 1;
                        }
                    }
                    _ => {}
                }
            }
            Event::Tick => {
                // target.advance(,100.0f32);
                app.advance();
            }
        }
        draw(&mut terminal, &app, &target);
    }

    terminal.show_cursor().unwrap();
}

fn draw(t: &mut Terminal<TermionBackend>, app: &App, target: &Vehicle) {

    let size = t.size().unwrap();

    Group::default()
        .direction(Direction::Vertical)
        .sizes(&[Size::Percent(90), Size::Percent(10)])
        .render(t, &size, |t, chunks| {
            Group::default()
                .direction(Direction::Horizontal)
                .sizes(&[Size::Percent(15), Size::Percent(85)])
                .render(t, &chunks[0], |t, chunks| {
                    SelectableList::default()
                        .block(Block::default()
                                   .borders(border::ALL)
                                   .title("Steering Behaviors"))
                        .items(&app.items)
                        .select(app.selected)
                        .highlight_style(Style::default()
                                             .fg(Color::Yellow)
                                             .modifier(Modifier::Bold))
                        .highlight_symbol(">")
                        .render(t, &chunks[0]);

                    Canvas::default()
                        .block(Block::default()
                                   .borders(border::ALL)
                                   .title("Steering Actors"))
                        .paint(|ctx| {
                            /// draw steerable vehicle
                            ctx.draw(&Line {
                                x1: (app.v.get_position().as_slice()[0] - 10.0f32) as f64,
                                y1: (app.v.get_position().as_slice()[1] + 10.0f32) as f64,
                                x2: (app.v.get_position().as_slice()[0] + 10.0f32) as f64,
                                y2: (app.v.get_position().as_slice()[1] + 10.0f32) as f64,
                                color: Color::Red,
                            });
                            ctx.draw(&Line { x1: (app.v.get_position().as_slice()[0] + 10.0f32) as f64,
                                y1: (app.v.get_position().as_slice()[1] - 10.0f32) as f64,
                                x2: (app.v.get_position().as_slice()[0] + 10.0f32) as f64,
                                y2: (app.v.get_position().as_slice()[1] + 10.0f32) as f64,
                                color: Color::Red,
                            });
                            ctx.draw(&Line {
                                x1: (app.v.get_position().as_slice()[0] - 10.0f32) as f64,
                                y1: (app.v.get_position().as_slice()[1] - 10.0f32) as f64,
                                x2: (app.v.get_position().as_slice()[0] + 10.0f32) as f64,
                                y2: (app.v.get_position().as_slice()[1] - 10.0f32) as f64,
                                color: Color::Red,
                            });
                            ctx.draw(&Line {
                                x1: (app.v.get_position().as_slice()[0] - 10.0f32) as f64,
                                y1: (app.v.get_position().as_slice()[1] - 10.0f32) as f64,
                                x2: (app.v.get_position().as_slice()[0] - 10.0f32) as f64,
                                y2: (app.v.get_position().as_slice()[1] + 10.0f32) as f64,
                                color: Color::Red,
                            });
                            /// draw target
                            ctx.draw(&Line {
                                x1: (target.get_position().as_slice()[0] - 10.0f32) as f64,
                                y1: (target.get_position().as_slice()[1] + 10.0f32) as f64,
                                x2: (target.get_position().as_slice()[0] + 10.0f32) as f64,
                                y2: (target.get_position().as_slice()[1] + 10.0f32) as f64,
                                color: Color::Green,
                            });
                            ctx.draw(&Line {
                                x1: (target.get_position().as_slice()[0] + 10.0f32) as f64,
                                y1: (target.get_position().as_slice()[1] - 10.0f32) as f64,
                                x2: (target.get_position().as_slice()[0] + 10.0f32) as f64,
                                y2: (target.get_position().as_slice()[1] + 10.0f32) as f64,
                                color: Color::Green,
                            });
                            ctx.draw(&Line {
                                x1: (target.get_position().as_slice()[0] - 10.0f32) as f64,
                                y1: (target.get_position().as_slice()[1] - 10.0f32) as f64,
                                x2: (target.get_position().as_slice()[0] + 10.0f32) as f64,
                                y2: (target.get_position().as_slice()[1] - 10.0f32) as f64,
                                color: Color::Green,
                            });
                            ctx.draw(&Line {
                                x1: (target.get_position().as_slice()[0] - 10.0f32) as f64,
                                y1: (target.get_position().as_slice()[1] - 10.0f32) as f64,
                                x2: (target.get_position().as_slice()[0] - 10.0f32) as f64,
                                y2: (target.get_position().as_slice()[1] + 10.0f32) as f64,
                                color: Color::Green,
                            });

                        })
                        .x_bounds([-180.0, 180.0])
                        .y_bounds([-180.0, 180.0])
                        .render(t, &chunks[1]);
                });

            List::default()
                .block(Block::default()
                           .borders(border::ALL)
                           .title("Instructions")
                           .title_style(Style::default()
                                            .fg(Color::White)
                                            .bg(Color::Red)
                                            .modifier(Modifier::Bold)))
                .items(&app.positions
                           .iter()
                           .map(|evt| (format!("{}", evt), &app.error_style))
                           .collect::<Vec<(String, &Style)>>())
                .render(t, &chunks[1]);
        });

    t.draw().unwrap();
}
<commit_msg>changing behaviors implemented<commit_after>extern crate tui;
extern crate termion;
extern crate nalgebra;
extern crate steering;
extern crate alga;

use std::io;
use std::thread;
use std::time;
use std::sync::mpsc;

use termion::event;
use termion::input::TermRead;

use tui::Terminal;
use tui::backend::TermionBackend;
use tui::widgets::{Widget, Block, border, SelectableList, List};
use tui::widgets::canvas::{Canvas, Map, MapResolution, Line};
use tui::layout::{Group, Direction, Size};
use tui::style::{Style, Color, Modifier};

use nalgebra::Vector3;
use alga::general::AbstractModule;
use steering::Steerable;
use steering::SteeringAcceleration;
use steering::Seek;
use steering::Flee;
use steering::Pursue;
use steering::SteeringAccelerationCalculator;
use steering::SteeringBehavior;

struct App<'a> {
    items: Vec<&'a str>,
    selected: usize,
    events: Vec<(&'a str, &'a str)>,
    info_style: Style,
    warning_style: Style,
    error_style: Style,
    critical_style: Style,
    v: Vehicle,
    behavior: Option<&'a mut SteeringAccelerationCalculator<f32>>,
    positions: Vec<String>,
}

impl<'a> App<'a> {
    fn new() -> App<'a> {
        App {
            items: vec!["Seek", "Flee", "Pursue"],
            selected: 0,
            events: vec![("Event1", "INFO"),
                         ("Event2", "INFO"),
                         ("Event3", "CRITICAL"),
                         ("Event4", "ERROR"),
                         ("Event5", "INFO"),
                         ("Event6", "INFO"),
                         ("Event7", "WARNING"),
                         ("Event8", "INFO"),
                         ("Event9", "INFO"),
                         ("Event10", "INFO"),
                         ("Event11", "CRITICAL"),
                         ("Event12", "INFO"),
                         ("Event13", "INFO"),
                         ("Event14", "INFO"),
                         ("Event15", "INFO"),
                         ("Event16", "INFO"),
                         ("Event17", "ERROR"),
                         ("Event18", "ERROR"),
                         ("Event19", "INFO"),
                         ("Event20", "INFO"),
                         ("Event21", "WARNING"),
                         ("Event22", "INFO"),
                         ("Event23", "INFO"),
                         ("Event24", "WARNING"),
                         ("Event25", "INFO"),
                         ("Event26", "INFO")],
            info_style: Style::default().fg(Color::White),
            warning_style: Style::default().fg(Color::Yellow),
            error_style: Style::default().fg(Color::Magenta),
            critical_style: Style::default().fg(Color::Red),
            v: Vehicle::new(),
            behavior: None,
            positions: vec![],
        }
    }

    fn advance(&mut self) {
        let event = self.events.pop().unwrap();
        self.events.insert(0, event);
        match self.behavior {
            Some(ref mut a) => self.v.advance(*a, 500f32),
            None => (),
        };
        self.positions.clear();
        self.positions.push(format!("{}:{}:{}",
                                    self.v.get_position().as_slice()[0],
                                    self.v.get_position().as_slice()[1],
                                    self.v.get_position().as_slice()[2]));
    }
}

enum Event {
    Input(event::Key),
    Tick,
}

struct Vehicle {
    linear_velocity: Vector3<f32>,
    position: Vector3<f32>,
    angular_velocity: f32,
    bounding_radius: f32,
}

impl Steerable<f32> for Vehicle {
    fn get_linear_velocity(&self) -> &Vector3<f32> {
        &self.linear_velocity
    }

    fn get_angular_velocity(&self) -> f32 {
        self.angular_velocity
    }

    fn get_bounding_radius(&self) -> f32 {
        self.bounding_radius
    }

    fn get_position(&self) -> &Vector3<f32> {
        &self.position
    }
}

impl Vehicle {
    fn new() -> Self {
        Vehicle {
            linear_velocity: Vector3::new(1.0, 0.0, 0.0),
            position: Vector3::new(-50.0, 50.0, 0.0),
            angular_velocity: 0.0,
            bounding_radius: 2.0,
        }
    }

    fn advance(&mut self, calc: &mut SteeringAccelerationCalculator<f32>, milis: f32) {
        let mut sa = SteeringAcceleration::default();
        calc.calculate_steering(&mut sa, self);
        self.linear_velocity += sa.linear;
        self.angular_velocity += sa.angular;
        self.position = self.position + self.linear_velocity.multiply_by(milis / 1000.0);
    }
}

fn main() {
    // Terminal initialization
    let backend = TermionBackend::new().unwrap();
    let mut terminal = Terminal::new(backend).unwrap();
    let (tx, rx) = mpsc::channel();
    let input_tx = tx.clone();
    let clock_tx = tx.clone();

    // Input
    thread::spawn(move || {
        let stdin = io::stdin();
        for c in stdin.keys() {
            let evt = c.unwrap();
            input_tx.send(Event::Input(evt)).unwrap();
            if evt == event::Key::Char('q') {
                break;
            }
        }
    });

    // Tick
    thread::spawn(move || {
        loop {
            clock_tx.send(Event::Tick).unwrap();
            thread::sleep(time::Duration::from_millis(500));
        }
    });

    // App
    let mut target = Vehicle {
        linear_velocity: Vector3::new(1.0, 0.0, 0.0),
        position: Vector3::new(0.0, 0.0, 0.0),
        angular_velocity: 0.0,
        bounding_radius: 2.0,
    };

    let mut pursue  = Pursue {
        behavior: SteeringBehavior {
            enabled: true,
            limiter: None,
        },
        target: &target,
        max_prediction_time: 100.0f32,
    };
    let mut seek = Seek {
        behavior : SteeringBehavior {
            enabled : true,
            limiter : None,
        },
        target : &target,
    };
    let mut flee = Flee{
        behavior : SteeringBehavior {
            enabled : true,
            limiter : None,
        },
        target : &target,
    };
    let mut behaviors : Vec<&mut SteeringAccelerationCalculator<f32>> = vec![];
    behaviors.push(&mut seek);
    behaviors.push(&mut flee);
    behaviors.push(&mut pursue);

    let mut app = App::new();
    app.behavior = Some(behaviors[0].copy());
    // First draw call
    terminal.clear().unwrap();
    terminal.hide_cursor().unwrap();
    draw(&mut terminal, &app, &target);

    loop {
        let evt = rx.recv().unwrap();
        match evt {
            Event::Input(input) => {
                match input {
                    event::Key::Char('q') => {
                        break;
                    }
                    event::Key::Down => {
                        app.selected += 1;
                        if app.selected > app.items.len() - 1 {
                            app.selected = 0;
                        }
                    }
                    event::Key::Up => {
                        if app.selected > 0 {
                            app.selected -= 1;
                        } else {
                            app.selected = app.items.len() - 1;
                        }
                    }
                    _ => {}
                }
            }
            Event::Tick => {
                // target.advance(,100.0f32);
                app.advance();
            }
        }
        app.behavior = Some(behaviors[app.selected]);
        draw(&mut terminal, &app, &target);
    }

    terminal.show_cursor().unwrap();
}

fn draw(t: &mut Terminal<TermionBackend>, app: &App, target: &Vehicle) {

    let size = t.size().unwrap();

    Group::default()
        .direction(Direction::Vertical)
        .sizes(&[Size::Percent(90), Size::Percent(10)])
        .render(t, &size, |t, chunks| {
            Group::default()
                .direction(Direction::Horizontal)
                .sizes(&[Size::Percent(15), Size::Percent(85)])
                .render(t, &chunks[0], |t, chunks| {
                    SelectableList::default()
                        .block(Block::default()
                                   .borders(border::ALL)
                                   .title("Steering Behaviors"))
                        .items(&app.items)
                        .select(app.selected)
                        .highlight_style(Style::default()
                                             .fg(Color::Yellow)
                                             .modifier(Modifier::Bold))
                        .highlight_symbol(">")
                        .render(t, &chunks[0]);

                    Canvas::default()
                        .block(Block::default()
                                   .borders(border::ALL)
                                   .title("Steering Actors"))
                        .paint(|ctx| {
                            /// draw steerable vehicle
                            ctx.draw(&Line {
                                x1: (app.v.get_position().as_slice()[0] - 10.0f32) as f64,
                                y1: (app.v.get_position().as_slice()[1] + 10.0f32) as f64,
                                x2: (app.v.get_position().as_slice()[0] + 10.0f32) as f64,
                                y2: (app.v.get_position().as_slice()[1] + 10.0f32) as f64,
                                color: Color::Red,
                            });
                            ctx.draw(&Line {
                                x1: (app.v.get_position().as_slice()[0] + 10.0f32) as f64,
                                y1: (app.v.get_position().as_slice()[1] - 10.0f32) as f64,
                                x2: (app.v.get_position().as_slice()[0] + 10.0f32) as f64,
                                y2: (app.v.get_position().as_slice()[1] + 10.0f32) as f64,
                                color: Color::Red,
                            });
                            ctx.draw(&Line {
                                x1: (app.v.get_position().as_slice()[0] - 10.0f32) as f64,
                                y1: (app.v.get_position().as_slice()[1] - 10.0f32) as f64,
                                x2: (app.v.get_position().as_slice()[0] + 10.0f32) as f64,
                                y2: (app.v.get_position().as_slice()[1] - 10.0f32) as f64,
                                color: Color::Red,
                            });
                            ctx.draw(&Line {
                                x1: (app.v.get_position().as_slice()[0] - 10.0f32) as f64,
                                y1: (app.v.get_position().as_slice()[1] - 10.0f32) as f64,
                                x2: (app.v.get_position().as_slice()[0] - 10.0f32) as f64,
                                y2: (app.v.get_position().as_slice()[1] + 10.0f32) as f64,
                                color: Color::Red,
                            });
                            /// draw target
                            ctx.draw(&Line {
                                x1: (target.get_position().as_slice()[0] - 10.0f32) as f64,
                                y1: (target.get_position().as_slice()[1] + 10.0f32) as f64,
                                x2: (target.get_position().as_slice()[0] + 10.0f32) as f64,
                                y2: (target.get_position().as_slice()[1] + 10.0f32) as f64,
                                color: Color::Green,
                            });
                            ctx.draw(&Line {
                                x1: (target.get_position().as_slice()[0] + 10.0f32) as f64,
                                y1: (target.get_position().as_slice()[1] - 10.0f32) as f64,
                                x2: (target.get_position().as_slice()[0] + 10.0f32) as f64,
                                y2: (target.get_position().as_slice()[1] + 10.0f32) as f64,
                                color: Color::Green,
                            });
                            ctx.draw(&Line {
                                x1: (target.get_position().as_slice()[0] - 10.0f32) as f64,
                                y1: (target.get_position().as_slice()[1] - 10.0f32) as f64,
                                x2: (target.get_position().as_slice()[0] + 10.0f32) as f64,
                                y2: (target.get_position().as_slice()[1] - 10.0f32) as f64,
                                color: Color::Green,
                            });
                            ctx.draw(&Line {
                                x1: (target.get_position().as_slice()[0] - 10.0f32) as f64,
                                y1: (target.get_position().as_slice()[1] - 10.0f32) as f64,
                                x2: (target.get_position().as_slice()[0] - 10.0f32) as f64,
                                y2: (target.get_position().as_slice()[1] + 10.0f32) as f64,
                                color: Color::Green,
                            });

                        })
                        .x_bounds([-180.0, 180.0])
                        .y_bounds([-180.0, 180.0])
                        .render(t, &chunks[1]);
                });

            List::default()
                .block(Block::default()
                           .borders(border::ALL)
                           .title("Instructions")
                           .title_style(Style::default()
                                            .fg(Color::White)
                                            .bg(Color::Red)
                                            .modifier(Modifier::Bold)))
                .items(&app.positions
                           .iter()
                           .map(|evt| (format!("{}", evt), &app.error_style))
                           .collect::<Vec<(String, &Style)>>())
                .render(t, &chunks[1]);
        });

    t.draw().unwrap();
}
<|endoftext|>


<commit_before>use std::sync::mpsc;
use std::thread;

use hyper::server::Server as HyperServer;
use hyperlocal::UnixSocketServer;
use ruru::{Proc, VM};

use config::{BindingType, Config};
use handler::Handler;
use request_processor::RequestProcessor;

pub struct Server {
    config: Config,
}

impl Server {
    pub fn new(config: Config) -> Self {
        Server { config: config }
    }

    pub fn listen(self, ruby_handler: Proc) {
        println!("[rust] Start listening");

        let (request_sender, request_receiver) = mpsc::channel();
        let (response_sender, response_receiver) = mpsc::channel();

        let handler = Handler::new(request_sender, response_receiver);

        thread::spawn(move || {
            let handler_function = || -> () {
                match *self.config.binding_type() {
                    BindingType::Unix => {
                        UnixSocketServer::new("/tmp/trusted.sock").unwrap()
                            .handle(handler).unwrap();
                    },
                    BindingType::Tcp => {
                        HyperServer::http("localhost:3000").unwrap()
                            .handle(handler).unwrap();
                    }
                };
            };

            let unblock_function = || {
                ()
            };

            VM::thread_call_without_gvl(
                handler_function,
                Some(unblock_function)
            );
        });

        loop {
            println!("[rust] Trying to receive from sender");
            let request = request_receiver.recv().unwrap();

            println!("[rust] Sending to Ruby");
            let response = RequestProcessor::new(request, &ruby_handler).handle();

            println!("[rust] Received response from Ruby, sending back to Hyper");
            response_sender.send(response.into()).unwrap();
        }
    }
}
<commit_msg>Use listen_on when launching Hyper<commit_after>use std::sync::mpsc;
use std::thread;

use hyper::server::Server as HyperServer;
use hyperlocal::UnixSocketServer;
use ruru::{Proc, VM};

use config::{BindingType, Config};
use handler::Handler;
use request_processor::RequestProcessor;

pub struct Server {
    config: Config,
}

impl Server {
    pub fn new(config: Config) -> Self {
        Server { config: config }
    }

    pub fn listen(self, ruby_handler: Proc) {
        println!("[rust] Start listening");

        let (request_sender, request_receiver) = mpsc::channel();
        let (response_sender, response_receiver) = mpsc::channel();

        let handler = Handler::new(request_sender, response_receiver);

        thread::spawn(move || {
            let handler_function = || -> () {
                match *self.config.binding_type() {
                    BindingType::Unix => {
                        UnixSocketServer::new(self.config.listen_on()).unwrap()
                            .handle(handler).unwrap();
                    },
                    BindingType::Tcp => {
                        HyperServer::http(self.config.listen_on()).unwrap()
                            .handle(handler).unwrap();
                    }
                };
            };

            let unblock_function = || {
                ()
            };

            VM::thread_call_without_gvl(
                handler_function,
                Some(unblock_function)
            );
        });

        loop {
            println!("[rust] Trying to receive from sender");
            let request = request_receiver.recv().unwrap();

            println!("[rust] Sending to Ruby");
            let response = RequestProcessor::new(request, &ruby_handler).handle();

            println!("[rust] Received response from Ruby, sending back to Hyper");
            response_sender.send(response.into()).unwrap();
        }
    }
}
<|endoftext|>


<commit_before>use traits::*;

#[derive(PartialEq, Clone, Debug, Copy)]
pub enum BFTokenType {
    IncrementPtr(usize),      // >
    DecrementPtr(usize),      // <
    IncrementData(usize),     // +
    DecrementData(usize),     // -
    Output,                   // .
    Input,                    // ,

    // These store their corresponding tokens
    //  aka LoopStart stores the position of
    //  the matching LoopEnd and vice versa.
    LoopStart(usize),         // [
    LoopEnd(usize),           // ]

    // Optimised instructions
    SetCurrent(i8),           // Sets the current cell to value
    AddCurrentUp(usize),      // Adds current cell to cell in [current + value]
    AddCurrentDown(usize)     // Adds current cell to cell in [current - value]
}

#[derive(Clone, Debug, Copy)]
pub struct BFToken {
    pub token_type : BFTokenType,

    // Used for matching brackets
    pub pos : usize
}

pub struct BFLexer {
}

impl Lexer<Vec<BFToken>> for BFLexer {

    fn parse(input_string:String) -> LexResult<Vec<BFToken>> {
        // Import enum -> Allows for using enum values without
        //  BFTokenType:: prefix
        use self::BFTokenType::*;

        // Create empty vector
        let mut tokens : Vec<BFToken> = vec![];

        // Store the index of the token in the vector
        let mut pos : usize = 0;

        // This stores the positions of open brackets
        // This is used to match up bracket pairs
        //  so that they can jump to each other in O(1)
        let mut loop_stack : Vec<usize> = vec![];

        // Store the previous 5 tokens, these are used
        //  for optimisations.
        let mut last_tokens = [BFToken { pos : 0, token_type : Input }; 5];

        // Loop through each character
        for character in input_string.chars() {
            // Match our character to a TokenType.
            let token_type = match character {
                '>' => {
                    // Batch up all the '>' tokens
                    let mut new_x = 1;
                    if last_tokens[0].pos > 0 {
                        if let IncrementPtr(x) = last_tokens[0].token_type {
                            tokens.pop();
                            pos-=1;
                            new_x += x;
                        }
                    }
                    IncrementPtr(new_x)
                },
                '<' => {
                    let mut new_x = 1;
                    if last_tokens[0].pos > 0 {
                        if let DecrementPtr(x) = last_tokens[0].token_type {
                            tokens.pop();
                            pos-=1;
                            new_x += x;
                        }
                    }
                    DecrementPtr(new_x)
                },
                '+' =>  {
                    let mut new_x = 1;
                    if last_tokens[0].pos > 0 {
                        if let IncrementData(x) = last_tokens[0].token_type {
                            tokens.pop();
                            pos-=1;
                            new_x += x;
                        }
                    }
                    IncrementData(new_x)
                },
                '-' => {
                    let mut new_x = 1;
                    if last_tokens[0].pos > 0 {
                        if let DecrementData(x) = last_tokens[0].token_type {
                            tokens.pop();
                            pos-=1;
                            new_x += x;
                        }
                    }
                    DecrementData(new_x)
                },
                '.' => Output,
                ',' => Input,
                '[' => {
                    // Push this pos onto stack
                    loop_stack.push(pos);

                    // Store temp value of 0 for now - will be updated
                    //  once we know matching ]
                    LoopStart(0)
                },
                ']' => {

                    // Get matching bracket.
                    let index = loop_stack.pop().expect("Bracket mismatch");
                    let mut ret_token : BFTokenType = LoopEnd(index);

                    // Update it's data position to this ] token
                    tokens[index].token_type = LoopStart(pos);

                    match last_tokens[0].token_type {
                        // This currently checks for [-] or [+] and replaces
                        //  those with a set current cell to 0 instruction.
                        IncrementData(_)
                        | DecrementData(_) => {
                            if let LoopStart(_) = last_tokens[1].token_type {
                                ret_token = SetCurrent(0);
                                tokens.pop();
                                tokens.pop();
                                pos-=2;
                            }
                        },

                        // Optimisation for [-<+>] or [->+<] pattern.
                        // These loops will add the current cell value
                        //  to the cell value offset by the amount of
                        //  ptr increments '>' and '<'.
                        //
                        // Examples:
                        //
                        //  [->+<] adds mem[current] to mem[current+1]
                        //
                        //  [->>>>+<<<<<] adds mem[current] to mem[current+4]
                        //
                        // Note that due to the combination optimisation
                        //  this only needs to check for [->+<] or [-<+>]
                        DecrementPtr(x)
                        | IncrementPtr(x) => {
                            if let IncrementData(a) = last_tokens[1].token_type {
                                match last_tokens[2].token_type {
                                    IncrementPtr(y)
                                    | DecrementPtr(y) => {
                                        if x == y {
                                            if let DecrementData(b) = last_tokens[3].token_type  {
                                                if a == b {
                                                    if let LoopStart(_) = last_tokens[4].token_type {
                                                        if last_tokens[0].token_type == DecrementPtr(x) {
                                                            ret_token = AddCurrentUp(x);
                                                        } else {
                                                            ret_token = AddCurrentDown(x);
                                                        }
                                                        tokens.pop();
                                                        tokens.pop();
                                                        tokens.pop();
                                                        tokens.pop();
                                                        tokens.pop();
                                                        pos-=5;
                                                    }
                                                }
                                            }
                                        }
                                    },
                                    _ => { }
                                }
                            };
                        },

                        // Empty Loop
                        LoopStart(_) => {
                            tokens.pop();
                            pos-=1;
                            continue;
                        },

                        _ => { }
                    }

                    ret_token
                },

                // BF is a very simple language - if there is an
                //  unrecognised character, it is ignored.
                _ => continue
            };

            let mut i = 1;
            // Recopy last tokens instead of shifting as they
            //  may have chagned.
            while i < 5 && pos > i-1 {
                last_tokens[i] = tokens[pos-i].clone();
                i+=1;
            }

            pos+=1;

            // Add it to the list of tokens
            let token = BFToken { token_type : token_type, pos : pos};

            last_tokens[0] = token.clone();

            tokens.push(token);
        }

        // No way for this to currently fail.
        LexResult::Success(tokens)
    }
}
<commit_msg>Fixed typo in previous commit<commit_after>use traits::*;

#[derive(PartialEq, Clone, Debug, Copy)]
pub enum BFTokenType {
    IncrementPtr(usize),      // >
    DecrementPtr(usize),      // <
    IncrementData(usize),     // +
    DecrementData(usize),     // -
    Output,                   // .
    Input,                    // ,

    // These store their corresponding tokens
    //  aka LoopStart stores the position of
    //  the matching LoopEnd and vice versa.
    LoopStart(usize),         // [
    LoopEnd(usize),           // ]

    // Optimised instructions
    SetCurrent(i8),           // Sets the current cell to value
    AddCurrentUp(usize),      // Adds current cell to cell in [current + value]
    AddCurrentDown(usize)     // Adds current cell to cell in [current - value]
}

#[derive(Clone, Debug, Copy)]
pub struct BFToken {
    pub token_type : BFTokenType,

    // Used for matching brackets
    pub pos : usize
}

pub struct BFLexer {
}

impl Lexer<Vec<BFToken>> for BFLexer {

    fn parse(input_string:String) -> LexResult<Vec<BFToken>> {
        // Import enum -> Allows for using enum values without
        //  BFTokenType:: prefix
        use self::BFTokenType::*;

        // Create empty vector
        let mut tokens : Vec<BFToken> = vec![];

        // Store the index of the token in the vector
        let mut pos : usize = 0;

        // This stores the positions of open brackets
        // This is used to match up bracket pairs
        //  so that they can jump to each other in O(1)
        let mut loop_stack : Vec<usize> = vec![];

        // Store the previous 5 tokens, these are used
        //  for optimisations.
        let mut last_tokens = [BFToken { pos : 0, token_type : Input }; 5];

        // Loop through each character
        for character in input_string.chars() {
            // Match our character to a TokenType.
            let token_type = match character {
                '>' => {
                    // Batch up all the '>' tokens
                    let mut new_x = 1;
                    if last_tokens[0].pos > 0 {
                        if let IncrementPtr(x) = last_tokens[0].token_type {
                            tokens.pop();
                            pos-=1;
                            new_x += x;
                        }
                    }
                    IncrementPtr(new_x)
                },
                '<' => {
                    let mut new_x = 1;
                    if last_tokens[0].pos > 0 {
                        if let DecrementPtr(x) = last_tokens[0].token_type {
                            tokens.pop();
                            pos-=1;
                            new_x += x;
                        }
                    }
                    DecrementPtr(new_x)
                },
                '+' =>  {
                    let mut new_x = 1;
                    if last_tokens[0].pos > 0 {
                        if let IncrementData(x) = last_tokens[0].token_type {
                            tokens.pop();
                            pos-=1;
                            new_x += x;
                        }
                    }
                    IncrementData(new_x)
                },
                '-' => {
                    let mut new_x = 1;
                    if last_tokens[0].pos > 0 {
                        if let DecrementData(x) = last_tokens[0].token_type {
                            tokens.pop();
                            pos-=1;
                            new_x += x;
                        }
                    }
                    DecrementData(new_x)
                },
                '.' => Output,
                ',' => Input,
                '[' => {
                    // Push this pos onto stack
                    loop_stack.push(pos);

                    // Store temp value of 0 for now - will be updated
                    //  once we know matching ]
                    LoopStart(0)
                },
                ']' => {

                    // Get matching bracket.
                    let index = loop_stack.pop().expect("Bracket mismatch");
                    let mut ret_token : BFTokenType = LoopEnd(index);

                    // Update it's data position to this ] token
                    tokens[index].token_type = LoopStart(pos);

                    match last_tokens[0].token_type {
                        // This currently checks for [-] or [+] and replaces
                        //  those with a set current cell to 0 instruction.
                        IncrementData(_)
                        | DecrementData(_) => {
                            if let LoopStart(_) = last_tokens[1].token_type {
                                ret_token = SetCurrent(0);
                                tokens.pop();
                                tokens.pop();
                                pos-=2;
                            }
                        },

                        // Optimisation for [-<+>] or [->+<] pattern.
                        // These loops will add the current cell value
                        //  to the cell value offset by the amount of
                        //  ptr increments '>' and '<'.
                        //
                        // Examples:
                        //
                        //  [->+<]         adds mem[current] to mem[current+1]
                        //
                        //  [->>>>+<<<<]   adds mem[current] to mem[current+4]
                        //
                        // Note that due to the combination optimisation
                        //  this only needs to check for [->+<] or [-<+>]
                        DecrementPtr(x)
                        | IncrementPtr(x) => {
                            if let IncrementData(a) = last_tokens[1].token_type {
                                match last_tokens[2].token_type {
                                    IncrementPtr(y)
                                    | DecrementPtr(y) => {
                                        if x == y {
                                            if let DecrementData(b) = last_tokens[3].token_type  {
                                                if a == b {
                                                    if let LoopStart(_) = last_tokens[4].token_type {
                                                        if last_tokens[0].token_type == DecrementPtr(x) {
                                                            ret_token = AddCurrentUp(x);
                                                        } else {
                                                            ret_token = AddCurrentDown(x);
                                                        }
                                                        tokens.pop();
                                                        tokens.pop();
                                                        tokens.pop();
                                                        tokens.pop();
                                                        tokens.pop();
                                                        pos-=5;
                                                    }
                                                }
                                            }
                                        }
                                    },
                                    _ => { }
                                }
                            };
                        },

                        // Empty Loop
                        LoopStart(_) => {
                            tokens.pop();
                            pos-=1;
                            continue;
                        },

                        _ => { }
                    }

                    ret_token
                },

                // BF is a very simple language - if there is an
                //  unrecognised character, it is ignored.
                _ => continue
            };

            let mut i = 1;
            // Recopy last tokens instead of shifting as they
            //  may have chagned.
            while i < 5 && pos > i-1 {
                last_tokens[i] = tokens[pos-i].clone();
                i+=1;
            }

            pos+=1;

            // Add it to the list of tokens
            let token = BFToken { token_type : token_type, pos : pos};

            last_tokens[0] = token.clone();

            tokens.push(token);
        }

        // No way for this to currently fail.
        LexResult::Success(tokens)
    }
}
<|endoftext|>


<commit_before>//! Utility functions to standardize reading certificates, private keys, and root certificate stores
//! using `rustls`

use rustls::{internal::pemfile,
             Certificate,
             PrivateKey,
             RootCertStore};
use std::{fs,
          io::{self,
               Cursor},
          path::{Path,
                 PathBuf}};
use thiserror::Error;

#[derive(Error, Debug)]
pub enum Error {
    #[error("failed to read file {0}, err: {1}")]
    FailedToReadFile(PathBuf, io::Error),

    #[error("failed to read PEM certificates")]
    FailedToReadCerts,
    #[error("failed to read PEM certificates from file {0}")]
    FailedToReadCertsFromFile(PathBuf),

    #[error("failed to read PEM, PKCS8 private keys")]
    FailedToReadPrivateKeys,
    #[error("failed to read PEM, PKCS8 private keys from file {0}")]
    FailedToReadPrivateKeysFromFile(PathBuf),
    #[error("no PEM, PKCS8 private key")]
    NoPrivateKey,
    #[error("no PEM, PKCS8 private keys in file {0}")]
    NoPrivateKeyFromFile(PathBuf),

    #[error("failed to read PEM root certificate store")]
    FailedToReadRootCertificateStore,
    #[error("failed to read PEM root certificate store {0}")]
    FailedToReadRootCertificateStoreFromFile(PathBuf),
    #[error("failed to read {0} certificates from PEM root certificate store")]
    FailedToReadCertificatesFromRootStore(usize),
    #[error("failed to read {0} certificates from PEM root certificate store file {1}")]
    FailedToReadCertificatesFromRootStoreFile(usize, PathBuf),
}

pub fn certificates_from_buf(buf: &[u8]) -> Result<Vec<Certificate>, Error> {
    let mut cursor = Cursor::new(buf);
    pemfile::certs(&mut cursor).map_err(|_| Error::FailedToReadCerts)
}

pub fn certificates_from_file(path: impl AsRef<Path>) -> Result<Vec<Certificate>, Error> {
    let buf =
        fs::read(path.as_ref()).map_err(|e| Error::FailedToReadFile(path.as_ref().into(), e))?;
    certificates_from_buf(&buf).map_err(|_| Error::FailedToReadCertsFromFile(path.as_ref().into()))
}

pub fn private_keys_from_buf(buf: &[u8]) -> Result<Vec<PrivateKey>, Error> {
    let mut cursor = Cursor::new(buf);
    pemfile::pkcs8_private_keys(&mut cursor).map_err(|_| Error::FailedToReadPrivateKeys)
}

pub fn private_keys_from_file(path: impl AsRef<Path>) -> Result<Vec<PrivateKey>, Error> {
    let buf =
        fs::read(path.as_ref()).map_err(|e| Error::FailedToReadFile(path.as_ref().into(), e))?;
    private_keys_from_buf(&buf).map_err(|_| {
                                   Error::FailedToReadPrivateKeysFromFile(path.as_ref().into())
                               })
}

pub fn private_key_from_buf(buf: &[u8]) -> Result<PrivateKey, Error> {
    private_keys_from_buf(buf)?.into_iter()
                               .next()
                               .ok_or_else(|| Error::NoPrivateKey)
}

pub fn private_key_from_file(path: impl AsRef<Path>) -> Result<PrivateKey, Error> {
    private_keys_from_file(path.as_ref())?.into_iter()
                                          .next()
                                          .ok_or_else(|| {
                                              Error::NoPrivateKeyFromFile(path.as_ref().into())
                                          })
}

pub fn root_certificate_store_from_buf(buf: &[u8]) -> Result<RootCertStore, Error> {
    let mut root_certificate_store = RootCertStore::empty();
    let mut cursor = Cursor::new(buf);
    let (_, failed) = root_certificate_store.add_pem_file(&mut cursor)
                                            .map_err(|_| Error::FailedToReadPrivateKeys)?;
    if failed > 0 {
        return Err(Error::FailedToReadCertificatesFromRootStore(failed));
    }
    Ok(root_certificate_store)
}

pub fn root_certificate_store_from_file(path: impl AsRef<Path>) -> Result<RootCertStore, Error> {
    let buf =
        fs::read(path.as_ref()).map_err(|e| Error::FailedToReadFile(path.as_ref().into(), e))?;
    root_certificate_store_from_buf(&buf).map_err(|e| {
        use Error::{FailedToReadCertificatesFromRootStore as ReadCertificates,
                    FailedToReadCertificatesFromRootStoreFile as ReadCertificatesFromFile,
                    FailedToReadRootCertificateStore as RootCertStore,
                    FailedToReadRootCertificateStoreFromFile as RootCertStoreFromFile};
        match e {
            RootCertStore => RootCertStoreFromFile(path.as_ref().into()),
            ReadCertificates(failed) => ReadCertificatesFromFile(failed, path.as_ref().into()),
            _ => e,
        }
    })
}
<commit_msg>[Refactor] Cleanup rustls readers<commit_after>//! Utility functions to standardize reading certificates, private keys, and root certificate stores
//! using `rustls`

use rustls::{internal::pemfile,
             Certificate,
             PrivateKey,
             RootCertStore};
use std::{fs,
          io::{self,
               BufReader},
          path::{Path,
                 PathBuf}};
use thiserror::Error;

#[derive(Error, Debug)]
pub enum Error {
    #[error("failed to read file {0}, err: {1}")]
    FailedToReadFile(PathBuf, io::Error),

    #[error("failed to read PEM certificates")]
    FailedToReadCerts,
    #[error("failed to read PEM certificates from file {0}")]
    FailedToReadCertsFromFile(PathBuf),

    #[error("failed to read PEM, PKCS8 private keys")]
    FailedToReadPrivateKeys,
    #[error("failed to read PEM, PKCS8 private keys from file {0}")]
    FailedToReadPrivateKeysFromFile(PathBuf),
    #[error("no PEM, PKCS8 private key")]
    NoPrivateKey,
    #[error("no PEM, PKCS8 private keys in file {0}")]
    NoPrivateKeyFromFile(PathBuf),

    #[error("failed to read PEM root certificate store")]
    FailedToReadRootCertificateStore,
    #[error("failed to read PEM root certificate store {0}")]
    FailedToReadRootCertificateStoreFromFile(PathBuf),
    #[error("failed to read {0} certificates from PEM root certificate store")]
    FailedToReadCertificatesFromRootStore(usize),
    #[error("failed to read {0} certificates from PEM root certificate store file {1}")]
    FailedToReadCertificatesFromRootStoreFile(usize, PathBuf),
}

fn certificates_from_buf(buf: &[u8]) -> Result<Vec<Certificate>, Error> {
    let mut cursor = BufReader::new(buf);
    pemfile::certs(&mut cursor).map_err(|_| Error::FailedToReadCerts)
}

pub fn certificates_from_file(path: impl AsRef<Path>) -> Result<Vec<Certificate>, Error> {
    let buf =
        fs::read(path.as_ref()).map_err(|e| Error::FailedToReadFile(path.as_ref().into(), e))?;
    certificates_from_buf(&buf).map_err(|_| Error::FailedToReadCertsFromFile(path.as_ref().into()))
}

fn private_keys_from_buf(buf: &[u8]) -> Result<Vec<PrivateKey>, Error> {
    let mut cursor = BufReader::new(buf);
    pemfile::pkcs8_private_keys(&mut cursor).map_err(|_| Error::FailedToReadPrivateKeys)
}

pub fn private_keys_from_file(path: impl AsRef<Path>) -> Result<Vec<PrivateKey>, Error> {
    let buf =
        fs::read(path.as_ref()).map_err(|e| Error::FailedToReadFile(path.as_ref().into(), e))?;
    private_keys_from_buf(&buf).map_err(|_| {
                                   Error::FailedToReadPrivateKeysFromFile(path.as_ref().into())
                               })
}

pub fn private_key_from_file(path: impl AsRef<Path>) -> Result<PrivateKey, Error> {
    private_keys_from_file(path.as_ref())?.into_iter()
                                          .next()
                                          .ok_or_else(|| {
                                              Error::NoPrivateKeyFromFile(path.as_ref().into())
                                          })
}

fn root_certificate_store_from_buf(buf: &[u8]) -> Result<RootCertStore, Error> {
    let mut root_certificate_store = RootCertStore::empty();
    let mut cursor = BufReader::new(buf);
    let (_, failed) = root_certificate_store.add_pem_file(&mut cursor)
                                            .map_err(|_| Error::FailedToReadPrivateKeys)?;
    if failed > 0 {
        return Err(Error::FailedToReadCertificatesFromRootStore(failed));
    }
    Ok(root_certificate_store)
}

pub fn root_certificate_store_from_file(path: impl AsRef<Path>) -> Result<RootCertStore, Error> {
    let buf =
        fs::read(path.as_ref()).map_err(|e| Error::FailedToReadFile(path.as_ref().into(), e))?;
    root_certificate_store_from_buf(&buf).map_err(|e| {
        use Error::{FailedToReadCertificatesFromRootStore as ReadCertificates,
                    FailedToReadCertificatesFromRootStoreFile as ReadCertificatesFromFile,
                    FailedToReadRootCertificateStore as RootCertStore,
                    FailedToReadRootCertificateStoreFromFile as RootCertStoreFromFile};
        match e {
            RootCertStore => RootCertStoreFromFile(path.as_ref().into()),
            ReadCertificates(failed) => ReadCertificatesFromFile(failed, path.as_ref().into()),
            _ => e,
        }
    })
}
<|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/. */

<%namespace name="helpers" file="/helpers.mako.rs" />

<% data.new_style_struct("List", inherited=True) %>

${helpers.single_keyword("list-style-position", "outside inside", animation_value_type="discrete",
                         spec="https://drafts.csswg.org/css-lists/#propdef-list-style-position")}

// TODO(pcwalton): Implement the full set of counter styles per CSS-COUNTER-STYLES [1] 6.1:
//
//     decimal-leading-zero, armenian, upper-armenian, lower-armenian, georgian, lower-roman,
//     upper-roman
//
// TODO(bholley): Missing quite a few gecko properties here as well.
//
// In gecko, {upper,lower}-{roman,alpha} are implemented as @counter-styles in the
// UA, however they can also be set from pres attrs. When @counter-style is supported
// we may need to look into this and handle these differently.
//
// [1]: http://dev.w3.org/csswg/css-counter-styles/
% if product == "servo":
    ${helpers.single_keyword("list-style-type", """
        disc none circle square decimal disclosure-open disclosure-closed lower-alpha upper-alpha
        arabic-indic bengali cambodian cjk-decimal devanagari gujarati gurmukhi kannada khmer lao
        malayalam mongolian myanmar oriya persian telugu thai tibetan cjk-earthly-branch
        cjk-heavenly-stem lower-greek hiragana hiragana-iroha katakana katakana-iroha""",
        animation_value_type="discrete",
        spec="https://drafts.csswg.org/css-lists/#propdef-list-style-type")}
% else:
    <%helpers:longhand name="list-style-type" animation_value_type="none" boxed="True"
                       spec="https://drafts.csswg.org/css-lists/#propdef-list-style-type">
        use values::CustomIdent;
        use values::computed::ComputedValueAsSpecified;
        use values::generics::CounterStyleOrNone;

        pub use self::computed_value::T as SpecifiedValue;

        pub mod computed_value {
            use values::generics::CounterStyleOrNone;

            /// <counter-style> | <string> | none
            #[derive(Debug, Clone, Eq, PartialEq, ToCss)]
            pub enum T {
                CounterStyle(CounterStyleOrNone),
                String(String),
            }
        }

        impl ComputedValueAsSpecified for SpecifiedValue {}
        no_viewport_percentage!(SpecifiedValue);

        #[cfg(feature = "gecko")]
        impl SpecifiedValue {
            /// Convert from gecko keyword to list-style-type.
            ///
            /// This should only be used for mapping type attribute to
            /// list-style-type, and thus only values possible in that
            /// attribute is considered here.
            pub fn from_gecko_keyword(value: u32) -> Self {
                use gecko_bindings::structs;
                SpecifiedValue::CounterStyle(if value == structs::NS_STYLE_LIST_STYLE_NONE {
                    CounterStyleOrNone::None
                } else {
                    <%
                        values = """disc circle square decimal lower-roman
                                    upper-roman lower-alpha upper-alpha""".split()
                    %>
                    CounterStyleOrNone::Name(CustomIdent(match value {
                        % for style in values:
                        structs::NS_STYLE_LIST_STYLE_${style.replace('-', '_').upper()} => atom!("${style}"),
                        % endfor
                        _ => unreachable!("Unknown counter style keyword value"),
                    }))
                })
            }
        }

        #[inline]
        pub fn get_initial_value() -> computed_value::T {
            computed_value::T::CounterStyle(CounterStyleOrNone::disc())
        }

        #[inline]
        pub fn get_initial_specified_value() -> SpecifiedValue {
            SpecifiedValue::CounterStyle(CounterStyleOrNone::disc())
        }

        pub fn parse<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>)
                             -> Result<SpecifiedValue, ParseError<'i>> {
            Ok(if let Ok(style) = input.try(|i| CounterStyleOrNone::parse(context, i)) {
                SpecifiedValue::CounterStyle(style)
            } else {
                SpecifiedValue::String(input.expect_string()?.as_ref().to_owned())
            })
        }
    </%helpers:longhand>
% endif

<%helpers:longhand name="list-style-image" animation_value_type="discrete"
                   boxed="${product == 'gecko'}"
                   spec="https://drafts.csswg.org/css-lists/#propdef-list-style-image">
    use values::computed::ComputedValueAsSpecified;
    use values::specified::UrlOrNone;
    pub use self::computed_value::T as SpecifiedValue;

    pub mod computed_value {
        use values::specified::UrlOrNone;

        #[cfg_attr(feature = "servo", derive(HeapSizeOf))]
        #[derive(Debug, Clone, PartialEq, ToCss)]
        pub struct T(pub UrlOrNone);
    }

    impl ComputedValueAsSpecified for SpecifiedValue {}
    no_viewport_percentage!(SpecifiedValue);

    #[inline]
    pub fn get_initial_value() -> computed_value::T {
        computed_value::T(Either::Second(None_))
    }
    #[inline]
    pub fn get_initial_specified_value() -> SpecifiedValue {
        SpecifiedValue(Either::Second(None_))
    }
    pub fn parse<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>)
                         -> Result<SpecifiedValue,ParseError<'i>> {
        % if product == "gecko":
        let mut value = input.try(|input| UrlOrNone::parse(context, input))?;
        if let Either::First(ref mut url) = value {
            url.build_image_value();
        }
        % else :
        let value = input.try(|input| UrlOrNone::parse(context, input))?;
        % endif

        return Ok(SpecifiedValue(value));
    }
</%helpers:longhand>

<%helpers:longhand name="quotes" animation_value_type="discrete"
                   spec="https://drafts.csswg.org/css-content/#propdef-quotes">
    use cssparser::serialize_string;
    use std::fmt;
    use style_traits::ToCss;
    use values::computed::ComputedValueAsSpecified;

    pub use self::computed_value::T as SpecifiedValue;

    pub mod computed_value {
        #[derive(Debug, Clone, PartialEq)]
        #[cfg_attr(feature = "servo", derive(HeapSizeOf))]
        pub struct T(pub Vec<(String,String)>);
    }

    impl ComputedValueAsSpecified for SpecifiedValue {}
    no_viewport_percentage!(SpecifiedValue);

    impl ToCss for SpecifiedValue {
        fn to_css<W>(&self, dest: &mut W) -> fmt::Result where W: fmt::Write {
            if self.0.is_empty() {
                return dest.write_str("none")
            }

            let mut first = true;
            for pair in &self.0 {
                if !first {
                    dest.write_str(" ")?;
                }
                first = false;
                serialize_string(&*pair.0, dest)?;
                dest.write_str(" ")?;
                serialize_string(&*pair.1, dest)?;
            }
            Ok(())
        }
    }

    #[inline]
    pub fn get_initial_value() -> computed_value::T {
        computed_value::T(vec![
            ("\u{201c}".to_owned(), "\u{201d}".to_owned()),
            ("\u{2018}".to_owned(), "\u{2019}".to_owned()),
        ])
    }

    pub fn parse<'i, 't>(_: &ParserContext, input: &mut Parser<'i, 't>)
                         -> Result<SpecifiedValue,ParseError<'i>> {
        if input.try(|input| input.expect_ident_matching("none")).is_ok() {
            return Ok(SpecifiedValue(Vec::new()))
        }

        let mut quotes = Vec::new();
        loop {
            let first = match input.next() {
                Ok(&Token::QuotedString(ref value)) => value.as_ref().to_owned(),
                Ok(t) => return Err(BasicParseError::UnexpectedToken(t.clone()).into()),
                Err(_) => break,
            };
            let second = match input.next() {
                Ok(&Token::QuotedString(ref value)) => value.as_ref().to_owned(),
                Ok(t) => return Err(BasicParseError::UnexpectedToken(t.clone()).into()),
                Err(e) => return Err(e.into()),
            };
            quotes.push((first, second))
        }
        if !quotes.is_empty() {
            Ok(SpecifiedValue(quotes))
        } else {
            Err(StyleParseError::UnspecifiedError.into())
        }
    }
</%helpers:longhand>

${helpers.predefined_type("-moz-image-region",
                          "ClipRectOrAuto",
                          "computed::ClipRectOrAuto::auto()",
                          animation_value_type="ComputedValue",
                          products="gecko",
                          boxed="True",
                          spec="Nonstandard (https://developer.mozilla.org/en-US/docs/Web/CSS/-moz-image-region)")}
<commit_msg>Make list-style-type animatable.<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/. */

<%namespace name="helpers" file="/helpers.mako.rs" />

<% data.new_style_struct("List", inherited=True) %>

${helpers.single_keyword("list-style-position", "outside inside", animation_value_type="discrete",
                         spec="https://drafts.csswg.org/css-lists/#propdef-list-style-position")}

// TODO(pcwalton): Implement the full set of counter styles per CSS-COUNTER-STYLES [1] 6.1:
//
//     decimal-leading-zero, armenian, upper-armenian, lower-armenian, georgian, lower-roman,
//     upper-roman
//
// TODO(bholley): Missing quite a few gecko properties here as well.
//
// In gecko, {upper,lower}-{roman,alpha} are implemented as @counter-styles in the
// UA, however they can also be set from pres attrs. When @counter-style is supported
// we may need to look into this and handle these differently.
//
// [1]: http://dev.w3.org/csswg/css-counter-styles/
% if product == "servo":
    ${helpers.single_keyword("list-style-type", """
        disc none circle square decimal disclosure-open disclosure-closed lower-alpha upper-alpha
        arabic-indic bengali cambodian cjk-decimal devanagari gujarati gurmukhi kannada khmer lao
        malayalam mongolian myanmar oriya persian telugu thai tibetan cjk-earthly-branch
        cjk-heavenly-stem lower-greek hiragana hiragana-iroha katakana katakana-iroha""",
        animation_value_type="discrete",
        spec="https://drafts.csswg.org/css-lists/#propdef-list-style-type")}
% else:
    <%helpers:longhand name="list-style-type" animation_value_type="discrete" boxed="True"
                       spec="https://drafts.csswg.org/css-lists/#propdef-list-style-type">
        use values::CustomIdent;
        use values::computed::ComputedValueAsSpecified;
        use values::generics::CounterStyleOrNone;

        pub use self::computed_value::T as SpecifiedValue;

        pub mod computed_value {
            use values::generics::CounterStyleOrNone;

            /// <counter-style> | <string> | none
            #[derive(Debug, Clone, Eq, PartialEq, ToCss)]
            pub enum T {
                CounterStyle(CounterStyleOrNone),
                String(String),
            }
        }

        impl ComputedValueAsSpecified for SpecifiedValue {}
        no_viewport_percentage!(SpecifiedValue);

        #[cfg(feature = "gecko")]
        impl SpecifiedValue {
            /// Convert from gecko keyword to list-style-type.
            ///
            /// This should only be used for mapping type attribute to
            /// list-style-type, and thus only values possible in that
            /// attribute is considered here.
            pub fn from_gecko_keyword(value: u32) -> Self {
                use gecko_bindings::structs;
                SpecifiedValue::CounterStyle(if value == structs::NS_STYLE_LIST_STYLE_NONE {
                    CounterStyleOrNone::None
                } else {
                    <%
                        values = """disc circle square decimal lower-roman
                                    upper-roman lower-alpha upper-alpha""".split()
                    %>
                    CounterStyleOrNone::Name(CustomIdent(match value {
                        % for style in values:
                        structs::NS_STYLE_LIST_STYLE_${style.replace('-', '_').upper()} => atom!("${style}"),
                        % endfor
                        _ => unreachable!("Unknown counter style keyword value"),
                    }))
                })
            }
        }

        #[inline]
        pub fn get_initial_value() -> computed_value::T {
            computed_value::T::CounterStyle(CounterStyleOrNone::disc())
        }

        #[inline]
        pub fn get_initial_specified_value() -> SpecifiedValue {
            SpecifiedValue::CounterStyle(CounterStyleOrNone::disc())
        }

        pub fn parse<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>)
                             -> Result<SpecifiedValue, ParseError<'i>> {
            Ok(if let Ok(style) = input.try(|i| CounterStyleOrNone::parse(context, i)) {
                SpecifiedValue::CounterStyle(style)
            } else {
                SpecifiedValue::String(input.expect_string()?.as_ref().to_owned())
            })
        }
    </%helpers:longhand>
% endif

<%helpers:longhand name="list-style-image" animation_value_type="discrete"
                   boxed="${product == 'gecko'}"
                   spec="https://drafts.csswg.org/css-lists/#propdef-list-style-image">
    use values::computed::ComputedValueAsSpecified;
    use values::specified::UrlOrNone;
    pub use self::computed_value::T as SpecifiedValue;

    pub mod computed_value {
        use values::specified::UrlOrNone;

        #[cfg_attr(feature = "servo", derive(HeapSizeOf))]
        #[derive(Debug, Clone, PartialEq, ToCss)]
        pub struct T(pub UrlOrNone);
    }

    impl ComputedValueAsSpecified for SpecifiedValue {}
    no_viewport_percentage!(SpecifiedValue);

    #[inline]
    pub fn get_initial_value() -> computed_value::T {
        computed_value::T(Either::Second(None_))
    }
    #[inline]
    pub fn get_initial_specified_value() -> SpecifiedValue {
        SpecifiedValue(Either::Second(None_))
    }
    pub fn parse<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>)
                         -> Result<SpecifiedValue,ParseError<'i>> {
        % if product == "gecko":
        let mut value = input.try(|input| UrlOrNone::parse(context, input))?;
        if let Either::First(ref mut url) = value {
            url.build_image_value();
        }
        % else :
        let value = input.try(|input| UrlOrNone::parse(context, input))?;
        % endif

        return Ok(SpecifiedValue(value));
    }
</%helpers:longhand>

<%helpers:longhand name="quotes" animation_value_type="discrete"
                   spec="https://drafts.csswg.org/css-content/#propdef-quotes">
    use cssparser::serialize_string;
    use std::fmt;
    use style_traits::ToCss;
    use values::computed::ComputedValueAsSpecified;

    pub use self::computed_value::T as SpecifiedValue;

    pub mod computed_value {
        #[derive(Debug, Clone, PartialEq)]
        #[cfg_attr(feature = "servo", derive(HeapSizeOf))]
        pub struct T(pub Vec<(String,String)>);
    }

    impl ComputedValueAsSpecified for SpecifiedValue {}
    no_viewport_percentage!(SpecifiedValue);

    impl ToCss for SpecifiedValue {
        fn to_css<W>(&self, dest: &mut W) -> fmt::Result where W: fmt::Write {
            if self.0.is_empty() {
                return dest.write_str("none")
            }

            let mut first = true;
            for pair in &self.0 {
                if !first {
                    dest.write_str(" ")?;
                }
                first = false;
                serialize_string(&*pair.0, dest)?;
                dest.write_str(" ")?;
                serialize_string(&*pair.1, dest)?;
            }
            Ok(())
        }
    }

    #[inline]
    pub fn get_initial_value() -> computed_value::T {
        computed_value::T(vec![
            ("\u{201c}".to_owned(), "\u{201d}".to_owned()),
            ("\u{2018}".to_owned(), "\u{2019}".to_owned()),
        ])
    }

    pub fn parse<'i, 't>(_: &ParserContext, input: &mut Parser<'i, 't>)
                         -> Result<SpecifiedValue,ParseError<'i>> {
        if input.try(|input| input.expect_ident_matching("none")).is_ok() {
            return Ok(SpecifiedValue(Vec::new()))
        }

        let mut quotes = Vec::new();
        loop {
            let first = match input.next() {
                Ok(&Token::QuotedString(ref value)) => value.as_ref().to_owned(),
                Ok(t) => return Err(BasicParseError::UnexpectedToken(t.clone()).into()),
                Err(_) => break,
            };
            let second = match input.next() {
                Ok(&Token::QuotedString(ref value)) => value.as_ref().to_owned(),
                Ok(t) => return Err(BasicParseError::UnexpectedToken(t.clone()).into()),
                Err(e) => return Err(e.into()),
            };
            quotes.push((first, second))
        }
        if !quotes.is_empty() {
            Ok(SpecifiedValue(quotes))
        } else {
            Err(StyleParseError::UnspecifiedError.into())
        }
    }
</%helpers:longhand>

${helpers.predefined_type("-moz-image-region",
                          "ClipRectOrAuto",
                          "computed::ClipRectOrAuto::auto()",
                          animation_value_type="ComputedValue",
                          products="gecko",
                          boxed="True",
                          spec="Nonstandard (https://developer.mozilla.org/en-US/docs/Web/CSS/-moz-image-region)")}
<|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/. */

<%namespace name="helpers" file="/helpers.mako.rs" />
<% from data import Method %>

<% data.new_style_struct("Text",
                         inherited=False,
                         gecko_name="TextReset",
                         additional_methods=[Method("has_underline", "bool"),
                                             Method("has_overline", "bool"),
                                             Method("has_line_through", "bool")]) %>

<%helpers:longhand name="text-overflow" animatable="False"
                   spec="https://drafts.csswg.org/css-ui/#propdef-text-overflow">
    use std::fmt;
    use style_traits::ToCss;
    use values::NoViewportPercentage;
    use values::computed::ComputedValueAsSpecified;

    impl ComputedValueAsSpecified for SpecifiedValue {}
    impl NoViewportPercentage for SpecifiedValue {}

    #[derive(PartialEq, Eq, Clone, Debug)]
    #[cfg_attr(feature = "servo", derive(HeapSizeOf))]
    pub enum Side {
        Clip,
        Ellipsis,
        String(String),
    }

    #[derive(PartialEq, Eq, Clone, Debug)]
    #[cfg_attr(feature = "servo", derive(HeapSizeOf))]
    pub struct SpecifiedValue {
        pub first: Side,
        pub second: Option<Side>
    }

    pub mod computed_value {
        pub type T = super::SpecifiedValue;
    }

    #[inline]
    pub fn get_initial_value() -> computed_value::T {
        SpecifiedValue {
            first: Side::Clip,
            second: None
        }
    }
    pub fn parse(context: &ParserContext, input: &mut Parser) -> Result<SpecifiedValue, ()> {
        let first = try!(Side::parse(context, input));
        let second = Side::parse(context, input).ok();
        Ok(SpecifiedValue {
            first: first,
            second: second,
        })
    }
    impl Parse for Side {
        fn parse(_context: &ParserContext, input: &mut Parser) -> Result<Side, ()> {
            if let Ok(ident) = input.try(|input| input.expect_ident()) {
                match_ignore_ascii_case! { ident,
                    "clip" => Ok(Side::Clip),
                    "ellipsis" => Ok(Side::Ellipsis),
                    _ => Err(())
                }
            } else {
                Ok(Side::String(try!(input.expect_string()).into_owned()))
            }
        }
    }

    impl ToCss for Side {
        fn to_css<W>(&self, dest: &mut W) -> fmt::Result where W: fmt::Write {
            match *self {
                Side::Clip => dest.write_str("clip"),
                Side::Ellipsis => dest.write_str("ellipsis"),
                Side::String(ref s) => dest.write_str(s)
            }
        }
    }

    impl ToCss for SpecifiedValue {
        fn to_css<W>(&self, dest: &mut W) -> fmt::Result where W: fmt::Write {
            try!(self.first.to_css(dest));
            if let Some(ref second) = self.second {
                try!(dest.write_str(" "));
                try!(second.to_css(dest));
            }
            Ok(())
        }
    }
</%helpers:longhand>

${helpers.single_keyword("unicode-bidi",
                         "normal embed isolate bidi-override isolate-override plaintext",
                         animatable=False,
                         spec="https://drafts.csswg.org/css-writing-modes/#propdef-unicode-bidi")}

// FIXME: This prop should be animatable.
<%helpers:longhand name="${'text-decoration' if product == 'servo' else 'text-decoration-line'}"
                   custom_cascade="${product == 'servo'}"
                   animatable="False"
                   disable_when_testing="True",
                   spec="https://drafts.csswg.org/css-text-decor/#propdef-text-decoration-line">
    use std::fmt;
    use style_traits::ToCss;
    use values::NoViewportPercentage;
    use values::computed::ComputedValueAsSpecified;

    impl ComputedValueAsSpecified for SpecifiedValue {}
    impl NoViewportPercentage for SpecifiedValue {}

    #[derive(PartialEq, Eq, Copy, Clone, Debug)]
    #[cfg_attr(feature = "servo", derive(HeapSizeOf))]
    pub struct SpecifiedValue {
        pub underline: bool,
        pub overline: bool,
        pub line_through: bool,
        pub blink: bool,
    }

    impl ToCss for SpecifiedValue {
        fn to_css<W>(&self, dest: &mut W) -> fmt::Result where W: fmt::Write {
            let mut space = false;
            if self.underline {
                try!(dest.write_str("underline"));
                space = true;
            }
            if self.overline {
                if space {
                    try!(dest.write_str(" "));
                }
                try!(dest.write_str("overline"));
                space = true;
            }
            if self.line_through {
                if space {
                    try!(dest.write_str(" "));
                }
                try!(dest.write_str("line-through"));
                space = true;
            }
            if self.blink {
                if space {
                    try!(dest.write_str(" "));
                }
                try!(dest.write_str("blink"));
            }
            Ok(())
        }
    }
    pub mod computed_value {
        pub type T = super::SpecifiedValue;
        #[allow(non_upper_case_globals)]
        pub const none: T = super::SpecifiedValue {
            underline: false, overline: false, line_through: false, blink: false
        };
    }
    #[inline] pub fn get_initial_value() -> computed_value::T {
        computed_value::none
    }
    /// none | [ underline || overline || line-through || blink ]
    pub fn parse(_context: &ParserContext, input: &mut Parser) -> Result<SpecifiedValue, ()> {
        let mut result = SpecifiedValue {
            underline: false, overline: false, line_through: false, blink: false
        };
        if input.try(|input| input.expect_ident_matching("none")).is_ok() {
            return Ok(result)
        }
        let mut empty = true;

        while input.try(|input| {
                if let Ok(ident) = input.expect_ident() {
                    match_ignore_ascii_case! { ident,
                        "underline" => if result.underline { return Err(()) }
                                       else { empty = false; result.underline = true },
                        "overline" => if result.overline { return Err(()) }
                                      else { empty = false; result.overline = true },
                        "line-through" => if result.line_through { return Err(()) }
                                          else { empty = false; result.line_through = true },
                        "blink" => if result.blink { return Err(()) }
                                   else { empty = false; result.blink = true },
                        _ => return Err(())
                    }
                } else {
                    return Err(());
                }
                Ok(())
            }).is_ok() {
        }

        if !empty { Ok(result) } else { Err(()) }
    }

    % if product == "servo":
        fn cascade_property_custom(_declaration: &PropertyDeclaration,
                                   _inherited_style: &ComputedValues,
                                   context: &mut computed::Context,
                                   _seen: &mut PropertyBitField,
                                   _cacheable: &mut bool,
                                   _error_reporter: &mut StdBox<ParseErrorReporter + Send>) {
                longhands::_servo_text_decorations_in_effect::derive_from_text_decoration(context);
        }
    % endif
</%helpers:longhand>

${helpers.single_keyword("text-decoration-style",
                         "solid double dotted dashed wavy -moz-none",
                         products="gecko",
                         animatable=False,
                         spec="https://drafts.csswg.org/css-text-decor/#propdef-text-decoration-style")}

${helpers.predefined_type(
    "text-decoration-color", "CSSColor",
    "CSSParserColor::RGBA(RGBA { red: 0.0, green: 0.0, blue: 0.0, alpha: 1.0 })",
    complex_color=True,
    products="gecko",
    animatable=True,
    spec="https://drafts.csswg.org/css-text-decor/#propdef-text-decoration-color")}
<commit_msg>Serialize text-decoration-line to none if nothing specified<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/. */

<%namespace name="helpers" file="/helpers.mako.rs" />
<% from data import Method %>

<% data.new_style_struct("Text",
                         inherited=False,
                         gecko_name="TextReset",
                         additional_methods=[Method("has_underline", "bool"),
                                             Method("has_overline", "bool"),
                                             Method("has_line_through", "bool")]) %>

<%helpers:longhand name="text-overflow" animatable="False"
                   spec="https://drafts.csswg.org/css-ui/#propdef-text-overflow">
    use std::fmt;
    use style_traits::ToCss;
    use values::NoViewportPercentage;
    use values::computed::ComputedValueAsSpecified;

    impl ComputedValueAsSpecified for SpecifiedValue {}
    impl NoViewportPercentage for SpecifiedValue {}

    #[derive(PartialEq, Eq, Clone, Debug)]
    #[cfg_attr(feature = "servo", derive(HeapSizeOf))]
    pub enum Side {
        Clip,
        Ellipsis,
        String(String),
    }

    #[derive(PartialEq, Eq, Clone, Debug)]
    #[cfg_attr(feature = "servo", derive(HeapSizeOf))]
    pub struct SpecifiedValue {
        pub first: Side,
        pub second: Option<Side>
    }

    pub mod computed_value {
        pub type T = super::SpecifiedValue;
    }

    #[inline]
    pub fn get_initial_value() -> computed_value::T {
        SpecifiedValue {
            first: Side::Clip,
            second: None
        }
    }
    pub fn parse(context: &ParserContext, input: &mut Parser) -> Result<SpecifiedValue, ()> {
        let first = try!(Side::parse(context, input));
        let second = Side::parse(context, input).ok();
        Ok(SpecifiedValue {
            first: first,
            second: second,
        })
    }
    impl Parse for Side {
        fn parse(_context: &ParserContext, input: &mut Parser) -> Result<Side, ()> {
            if let Ok(ident) = input.try(|input| input.expect_ident()) {
                match_ignore_ascii_case! { ident,
                    "clip" => Ok(Side::Clip),
                    "ellipsis" => Ok(Side::Ellipsis),
                    _ => Err(())
                }
            } else {
                Ok(Side::String(try!(input.expect_string()).into_owned()))
            }
        }
    }

    impl ToCss for Side {
        fn to_css<W>(&self, dest: &mut W) -> fmt::Result where W: fmt::Write {
            match *self {
                Side::Clip => dest.write_str("clip"),
                Side::Ellipsis => dest.write_str("ellipsis"),
                Side::String(ref s) => dest.write_str(s)
            }
        }
    }

    impl ToCss for SpecifiedValue {
        fn to_css<W>(&self, dest: &mut W) -> fmt::Result where W: fmt::Write {
            try!(self.first.to_css(dest));
            if let Some(ref second) = self.second {
                try!(dest.write_str(" "));
                try!(second.to_css(dest));
            }
            Ok(())
        }
    }
</%helpers:longhand>

${helpers.single_keyword("unicode-bidi",
                         "normal embed isolate bidi-override isolate-override plaintext",
                         animatable=False,
                         spec="https://drafts.csswg.org/css-writing-modes/#propdef-unicode-bidi")}

// FIXME: This prop should be animatable.
<%helpers:longhand name="${'text-decoration' if product == 'servo' else 'text-decoration-line'}"
                   custom_cascade="${product == 'servo'}"
                   animatable="False"
                   disable_when_testing="True",
                   spec="https://drafts.csswg.org/css-text-decor/#propdef-text-decoration-line">
    use std::fmt;
    use style_traits::ToCss;
    use values::NoViewportPercentage;
    use values::computed::ComputedValueAsSpecified;

    impl ComputedValueAsSpecified for SpecifiedValue {}
    impl NoViewportPercentage for SpecifiedValue {}

    #[derive(PartialEq, Eq, Copy, Clone, Debug)]
    #[cfg_attr(feature = "servo", derive(HeapSizeOf))]
    pub struct SpecifiedValue {
        pub underline: bool,
        pub overline: bool,
        pub line_through: bool,
        pub blink: bool,
    }

    impl ToCss for SpecifiedValue {
        fn to_css<W>(&self, dest: &mut W) -> fmt::Result where W: fmt::Write {
            let mut has_any = false;
            macro_rules! write_value {
                ($line:ident => $css:expr) => {
                    if self.$line {
                        if has_any {
                            dest.write_str(" ")?;
                        }
                        dest.write_str($css)?;
                        has_any = true;
                    }
                }
            }
            write_value!(underline => "underline");
            write_value!(overline => "overline");
            write_value!(line_through => "line-through");
            write_value!(blink => "blink");
            if !has_any {
                dest.write_str("none")?;
            }
            Ok(())
        }
    }
    pub mod computed_value {
        pub type T = super::SpecifiedValue;
        #[allow(non_upper_case_globals)]
        pub const none: T = super::SpecifiedValue {
            underline: false, overline: false, line_through: false, blink: false
        };
    }
    #[inline] pub fn get_initial_value() -> computed_value::T {
        computed_value::none
    }
    /// none | [ underline || overline || line-through || blink ]
    pub fn parse(_context: &ParserContext, input: &mut Parser) -> Result<SpecifiedValue, ()> {
        let mut result = SpecifiedValue {
            underline: false, overline: false, line_through: false, blink: false
        };
        if input.try(|input| input.expect_ident_matching("none")).is_ok() {
            return Ok(result)
        }
        let mut empty = true;

        while input.try(|input| {
                if let Ok(ident) = input.expect_ident() {
                    match_ignore_ascii_case! { ident,
                        "underline" => if result.underline { return Err(()) }
                                       else { empty = false; result.underline = true },
                        "overline" => if result.overline { return Err(()) }
                                      else { empty = false; result.overline = true },
                        "line-through" => if result.line_through { return Err(()) }
                                          else { empty = false; result.line_through = true },
                        "blink" => if result.blink { return Err(()) }
                                   else { empty = false; result.blink = true },
                        _ => return Err(())
                    }
                } else {
                    return Err(());
                }
                Ok(())
            }).is_ok() {
        }

        if !empty { Ok(result) } else { Err(()) }
    }

    % if product == "servo":
        fn cascade_property_custom(_declaration: &PropertyDeclaration,
                                   _inherited_style: &ComputedValues,
                                   context: &mut computed::Context,
                                   _seen: &mut PropertyBitField,
                                   _cacheable: &mut bool,
                                   _error_reporter: &mut StdBox<ParseErrorReporter + Send>) {
                longhands::_servo_text_decorations_in_effect::derive_from_text_decoration(context);
        }
    % endif
</%helpers:longhand>

${helpers.single_keyword("text-decoration-style",
                         "solid double dotted dashed wavy -moz-none",
                         products="gecko",
                         animatable=False,
                         spec="https://drafts.csswg.org/css-text-decor/#propdef-text-decoration-style")}

${helpers.predefined_type(
    "text-decoration-color", "CSSColor",
    "CSSParserColor::RGBA(RGBA { red: 0.0, green: 0.0, blue: 0.0, alpha: 1.0 })",
    complex_color=True,
    products="gecko",
    animatable=True,
    spec="https://drafts.csswg.org/css-text-decor/#propdef-text-decoration-color")}
<|endoftext|>


<commit_before>#![feature(core)]
#![feature(path_ext)]
#![feature(convert)]

extern crate term;
extern crate itertools;

mod version;
mod paths;
mod downloader;
mod builder;
mod reporter;

use std::rc::Rc;

use paths::Paths;
use downloader::Downloader;
use builder::Builder;

fn main() {
   dump_env();

   let paths = Paths::new();
   let paths_rc = Rc::new(paths);

   let nginx_downloader = Downloader::new(paths_rc.clone());
   nginx_downloader.download();

   let nginx_builder = Builder::new(paths_rc.clone());
   nginx_builder.build();
}

fn dump_env() {
   use std::env;
   use reporter::report;

   report("Dumping", "Environment");

   for (key, value) in env::vars() {
       println!("{:>30}: {}", key, value);
   }
}
<commit_msg>Suppressing compilation warnings until better solution is found.<commit_after>#![feature(core)]
#![feature(path_ext)]
#![feature(convert)]

#![allow(deprecated)]

extern crate term;
extern crate itertools;

mod version;
mod paths;
mod downloader;
mod builder;
mod reporter;

use std::rc::Rc;

use paths::Paths;
use downloader::Downloader;
use builder::Builder;

fn main() {
   dump_env();

   let paths = Paths::new();
   let paths_rc = Rc::new(paths);

   let nginx_downloader = Downloader::new(paths_rc.clone());
   nginx_downloader.download();

   let nginx_builder = Builder::new(paths_rc.clone());
   nginx_builder.build();
}

fn dump_env() {
   use std::env;
   use reporter::report;

   report("Dumping", "Environment");

   for (key, value) in env::vars() {
       println!("{:>30}: {}", key, value);
   }
}
<|endoftext|>