<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 https://mozilla.org/MPL/2.0/. */

//! Application entry point, runs the event loop.

use crate::browser::Browser;
use crate::embedder::EmbedderCallbacks;
use crate::window_trait::WindowPortsMethods;
use crate::events_loop::EventsLoop;
use crate::{headed_window, headless_window};
use servo::compositing::windowing::WindowEvent;
use servo::config::opts::{self, parse_url_or_filename};
use servo::servo_config::pref;
use servo::servo_url::ServoUrl;
use servo::{BrowserId, Servo};
use std::cell::{Cell, RefCell};
use std::env;
use std::mem;
use std::rc::Rc;

pub struct App {
    events_loop: Rc<RefCell<EventsLoop>>,
    window: Rc<dyn WindowPortsMethods>,
    servo: RefCell<Servo<dyn WindowPortsMethods>>,
    browser: RefCell<Browser<dyn WindowPortsMethods>>,
    event_queue: RefCell<Vec<WindowEvent>>,
    suspended: Cell<bool>,
}

impl App {
    pub fn run() {
        let events_loop = EventsLoop::new(opts::get().headless);

        // Implements window methods, used by compositor.
        let window = if opts::get().headless {
            headless_window::Window::new(opts::get().initial_window_size)
        } else {
            headed_window::Window::new(opts::get().initial_window_size, events_loop.borrow().as_winit())
        };

        // Implements embedder methods, used by libservo and constellation.
        let embedder = Box::new(EmbedderCallbacks::new(
            events_loop.clone(),
            window.gl(),
        ));

        // Handle browser state.
        let browser = Browser::new(window.clone());

        let mut servo = Servo::new(embedder, window.clone());
        let browser_id = BrowserId::new();
        servo.handle_events(vec![WindowEvent::NewBrowser(get_default_url(), browser_id)]);
        servo.setup_logging();

        let app = App {
            event_queue: RefCell::new(vec![]),
            events_loop,
            window: window,
            browser: RefCell::new(browser),
            servo: RefCell::new(servo),
            suspended: Cell::new(false),
        };

        app.run_loop();
    }

    fn get_events(&self) -> Vec<WindowEvent> {
        mem::replace(&mut *self.event_queue.borrow_mut(), Vec::new())
    }

    fn has_events(&self) -> bool {
        !self.event_queue.borrow().is_empty() || self.window.has_events()
    }

    fn winit_event_to_servo_event(&self, event: glutin::Event) {
        match event {
            // App level events
            glutin::Event::Suspended(suspended) => {
                self.suspended.set(suspended);
                if !suspended {
                    self.event_queue.borrow_mut().push(WindowEvent::Idle);
                }
            },
            glutin::Event::Awakened => {
                self.event_queue.borrow_mut().push(WindowEvent::Idle);
            },
            glutin::Event::DeviceEvent { .. } => {},

            // Window level events
            glutin::Event::WindowEvent {
                window_id, event, ..
            } => {
                if Some(window_id) != self.window.id() {
                    warn!("Got an event from unknown window");
                } else {
                    self.window.winit_event_to_servo_event(event);
                }
            },
        }
    }

    fn run_loop(self) {
        let mut stop = false;
        loop {
            let mut events_loop = self.events_loop.borrow_mut();
            if self.window.is_animating() && !self.suspended.get() {
                // We block on compositing (self.handle_events() ends up calling swap_buffers)
                events_loop.poll_events(|e| {
                    self.winit_event_to_servo_event(e);
                });
                stop = self.handle_events();
            } else {
                // We block on winit's event loop (window events)
                events_loop.run_forever(|e| {
                    self.winit_event_to_servo_event(e);
                    if self.has_events() && !self.suspended.get() {
                        stop = self.handle_events();
                    }
                    if stop || self.window.is_animating() && !self.suspended.get() {
                        glutin::ControlFlow::Break
                    } else {
                        glutin::ControlFlow::Continue
                    }
                });
            }
            if stop {
                break;
            }
        }

        self.servo.into_inner().deinit()
    }

    fn handle_events(&self) -> bool {
        let mut browser = self.browser.borrow_mut();
        let mut servo = self.servo.borrow_mut();

        let win_events = self.window.get_events();

        // FIXME: this could be handled by Servo. We don't need
        // a repaint_synchronously function exposed.
        let need_resize = win_events.iter().any(|e| match *e {
            WindowEvent::Resize => true,
            _ => false,
        });

        let mut app_events = self.get_events();
        app_events.extend(win_events);

        browser.handle_window_events(app_events);

        let mut servo_events = servo.get_events();
        loop {
            browser.handle_servo_events(servo_events);
            servo.handle_events(browser.get_events());
            if browser.shutdown_requested() {
                return true;
            }
            servo_events = servo.get_events();
            if servo_events.is_empty() {
                break;
            }
        }

        if need_resize {
            servo.repaint_synchronously();
        }
        false
    }
}

fn get_default_url() -> ServoUrl {
    // If the url is not provided, we fallback to the homepage in prefs,
    // or a blank page in case the homepage is not set either.
    let cwd = env::current_dir().unwrap();
    let cmdline_url = opts::get().url.clone();
    let pref_url = {
        let homepage_url = pref!(shell.homepage);
        parse_url_or_filename(&cwd, &homepage_url).ok()
    };
    let blank_url = ServoUrl::parse("about:blank").ok();

    cmdline_url.or(pref_url).or(blank_url).unwrap()
}

pub fn gl_version() -> glutin::GlRequest {
    if opts::get().angle {
        glutin::GlRequest::Specific(glutin::Api::OpenGlEs, (3, 0))
    } else {
        glutin::GlRequest::GlThenGles {
            opengl_version: (3, 2),
            opengles_version: (3, 0),
        }
    }
}
<commit_msg>Auto merge of #23574 - asajeffrey:glutin-reduce-borrow-duration, r=paulrouget<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 https://mozilla.org/MPL/2.0/. */

//! Application entry point, runs the event loop.

use crate::browser::Browser;
use crate::embedder::EmbedderCallbacks;
use crate::window_trait::WindowPortsMethods;
use crate::events_loop::EventsLoop;
use crate::{headed_window, headless_window};
use servo::compositing::windowing::WindowEvent;
use servo::config::opts::{self, parse_url_or_filename};
use servo::servo_config::pref;
use servo::servo_url::ServoUrl;
use servo::{BrowserId, Servo};
use std::cell::{Cell, RefCell};
use std::env;
use std::mem;
use std::rc::Rc;

pub struct App {
    events_loop: Rc<RefCell<EventsLoop>>,
    window: Rc<dyn WindowPortsMethods>,
    servo: RefCell<Servo<dyn WindowPortsMethods>>,
    browser: RefCell<Browser<dyn WindowPortsMethods>>,
    event_queue: RefCell<Vec<WindowEvent>>,
    suspended: Cell<bool>,
}

impl App {
    pub fn run() {
        let events_loop = EventsLoop::new(opts::get().headless);

        // Implements window methods, used by compositor.
        let window = if opts::get().headless {
            headless_window::Window::new(opts::get().initial_window_size)
        } else {
            headed_window::Window::new(opts::get().initial_window_size, events_loop.borrow().as_winit())
        };

        // Implements embedder methods, used by libservo and constellation.
        let embedder = Box::new(EmbedderCallbacks::new(
            events_loop.clone(),
            window.gl(),
        ));

        // Handle browser state.
        let browser = Browser::new(window.clone());

        let mut servo = Servo::new(embedder, window.clone());
        let browser_id = BrowserId::new();
        servo.handle_events(vec![WindowEvent::NewBrowser(get_default_url(), browser_id)]);
        servo.setup_logging();

        let app = App {
            event_queue: RefCell::new(vec![]),
            events_loop,
            window: window,
            browser: RefCell::new(browser),
            servo: RefCell::new(servo),
            suspended: Cell::new(false),
        };

        app.run_loop();
    }

    fn get_events(&self) -> Vec<WindowEvent> {
        mem::replace(&mut *self.event_queue.borrow_mut(), Vec::new())
    }

    // This function decides whether the event should be handled during `run_forever`.
    fn winit_event_to_servo_event(&self, event: glutin::Event) -> glutin::ControlFlow {
        match event {
            // App level events
            glutin::Event::Suspended(suspended) => {
                self.suspended.set(suspended);
                if !suspended {
                    self.event_queue.borrow_mut().push(WindowEvent::Idle);
                }
            },
            glutin::Event::Awakened => {
                self.event_queue.borrow_mut().push(WindowEvent::Idle);
            },
            glutin::Event::DeviceEvent { .. } => {},

            // Window level events
            glutin::Event::WindowEvent {
                window_id, event, ..
            } => {
                if Some(window_id) != self.window.id() {
                    warn!("Got an event from unknown window");
                } else {
                    // Resize events need to be handled during run_forever
                    let cont = if let glutin::WindowEvent::Resized(_) = event {
                        glutin::ControlFlow::Continue
                    } else {
                        glutin::ControlFlow::Break
                    };
                    self.window.winit_event_to_servo_event(event);
                    return cont;
                }
            },
        }
        glutin::ControlFlow::Break
    }

    fn run_loop(self) {
        loop {
            if !self.window.is_animating()  || self.suspended.get() {
                // If there's no animations running then we block on the window event loop.
                self.events_loop.borrow_mut().run_forever(|e| {
                    let cont = self.winit_event_to_servo_event(e);
                    if cont == glutin::ControlFlow::Continue {
                        // Note we need to be careful to make sure that any events
                        // that are handled during run_forever aren't re-entrant,
                        // since we are handling them while holding onto a mutable borrow
                        // of the events loop
                        self.handle_events();
                    }
                    cont
                });
            }
            // Grab any other events that may have happened
            self.events_loop.borrow_mut().poll_events(|e| {
                self.winit_event_to_servo_event(e);
            });
            // If animations are running, we block on compositing
            // (self.handle_events() ends up calling swap_buffers)
            let stop = self.handle_events();
            if stop {
                break;
            }
        }

        self.servo.into_inner().deinit()
    }

    fn handle_events(&self) -> bool {
        let mut browser = self.browser.borrow_mut();
        let mut servo = self.servo.borrow_mut();

        let win_events = self.window.get_events();

        // FIXME: this could be handled by Servo. We don't need
        // a repaint_synchronously function exposed.
        let need_resize = win_events.iter().any(|e| match *e {
            WindowEvent::Resize => true,
            _ => false,
        });

        let mut app_events = self.get_events();
        app_events.extend(win_events);

        browser.handle_window_events(app_events);

        let mut servo_events = servo.get_events();
        loop {
            browser.handle_servo_events(servo_events);
            servo.handle_events(browser.get_events());
            if browser.shutdown_requested() {
                return true;
            }
            servo_events = servo.get_events();
            if servo_events.is_empty() {
                break;
            }
        }

        if need_resize {
            servo.repaint_synchronously();
        }
        false
    }
}

fn get_default_url() -> ServoUrl {
    // If the url is not provided, we fallback to the homepage in prefs,
    // or a blank page in case the homepage is not set either.
    let cwd = env::current_dir().unwrap();
    let cmdline_url = opts::get().url.clone();
    let pref_url = {
        let homepage_url = pref!(shell.homepage);
        parse_url_or_filename(&cwd, &homepage_url).ok()
    };
    let blank_url = ServoUrl::parse("about:blank").ok();

    cmdline_url.or(pref_url).or(blank_url).unwrap()
}

pub fn gl_version() -> glutin::GlRequest {
    if opts::get().angle {
        glutin::GlRequest::Specific(glutin::Api::OpenGlEs, (3, 0))
    } else {
        glutin::GlRequest::GlThenGles {
            opengl_version: (3, 2),
            opengles_version: (3, 0),
        }
    }
}
<|endoftext|>


<commit_before>// Lumol, an extensible molecular simulation engine
// Copyright (C) Lumol's contributors — BSD license

//! Convert TOML values to Lumol types.
use toml::value::Table;

use FromToml;
use FromTomlWithData;
use error::{Error, Result};
use extract;

use lumol::energy::{BornMayerHuggins, Buckingham, Gaussian, MorsePotential, Torsion};
use lumol::energy::{CosineHarmonic, Harmonic, LennardJones, NullPotential, Mie};
use lumol::energy::{Ewald, Wolf};
use lumol::energy::{PairPotential, TableComputation};
use lumol::units;

impl FromToml for NullPotential {
    fn from_toml(_: &Table) -> Result<NullPotential> {
        Ok(NullPotential)
    }
}

impl FromToml for Harmonic {
    fn from_toml(table: &Table) -> Result<Harmonic> {
        let k = extract::str("k", table, "harmonic potential")?;
        let x0 = extract::str("x0", table, "harmonic potential")?;
        Ok(Harmonic {
            k: units::from_str(k)?,
            x0: units::from_str(x0)?,
        })
    }
}

impl FromToml for LennardJones {
    fn from_toml(table: &Table) -> Result<LennardJones> {
        let sigma = extract::str("sigma", table, "Lennard-Jones potential")?;
        let epsilon = extract::str("epsilon", table, "Lennard-Jones potential")?;
        Ok(LennardJones {
            sigma: units::from_str(sigma)?,
            epsilon: units::from_str(epsilon)?,
        })
    }
}

impl FromToml for Mie {
    fn from_toml(table: &Table) -> Result<Mie> {
        let sigma = try_extract_parameter!(table, "sigma", "Mie potential");
        let epsilon = try_extract_parameter!(table, "epsilon", "Mie potential");
        let m = try_extract_parameter!(table, "m", "Mie potential");
        let n = try_extract_parameter!(table, "n", "Mie potential");

        if let (Some(sigma), Some(epsilon), Some(m), Some(n)) =
            (sigma.as_str(), epsilon.as_str(), m.as_float(), n.as_float()) {
            let sigma = try!(::lumol::units::from_str(sigma));
            let epsilon = try!(::lumol::units::from_str(epsilon));
            Ok(Mie::new(sigma, epsilon, n, m))
        } else {
            Err(Error::from("'epsilon' and 'sigma' must be strings \
                            and 'm' and 'n' must be floats in Mie potential"))
        }
    }
}

impl FromToml for CosineHarmonic {
    fn from_toml(table: &Table) -> Result<CosineHarmonic> {
        let k = extract::str("k", table, "cosine harmonic potential")?;
        let x0 = extract::str("x0", table, "cosine harmonic potential")?;
        Ok(CosineHarmonic::new(units::from_str(k)?, units::from_str(x0)?))
    }
}

impl FromToml for Torsion {
    fn from_toml(table: &Table) -> Result<Torsion> {
        let n = extract::uint("n", table, "torsion potential")?;
        let k = extract::str("k", table, "torsion potential")?;
        let delta = extract::str("delta", table, "torsion potential")?;
        Ok(Torsion {
            n: n as usize,
            k: units::from_str(k)?,
            delta: units::from_str(delta)?,
        })
    }
}

impl FromToml for Buckingham {
    fn from_toml(table: &Table) -> Result<Buckingham> {
        let a = extract::str("A", table, "Buckingham potential")?;
        let c = extract::str("C", table, "Buckingham potential")?;
        let rho = extract::str("rho", table, "Buckingham potential")?;

        Ok(Buckingham {
            a: units::from_str(a)?,
            c: units::from_str(c)?,
            rho: units::from_str(rho)?,
        })
    }
}

impl FromToml for BornMayerHuggins {
    fn from_toml(table: &Table) -> Result<BornMayerHuggins> {
        let a = extract::str("A", table, "Born-Mayer-Huggins potential")?;
        let c = extract::str("C", table, "Born-Mayer-Huggins potential")?;
        let d = extract::str("D", table, "Born-Mayer-Huggins potential")?;
        let rho = extract::str("rho", table, "Born-Mayer-Huggins potential")?;
        let sigma = extract::str("sigma", table, "Born-Mayer-Huggins potential")?;

        Ok(BornMayerHuggins {
            a: units::from_str(a)?,
            c: units::from_str(c)?,
            d: units::from_str(d)?,
            sigma: units::from_str(sigma)?,
            rho: units::from_str(rho)?,
        })
    }
}

impl FromToml for MorsePotential {
    fn from_toml(table: &Table) -> Result<MorsePotential> {
        let a = extract::str("A", table, "Morse potential")?;
        let depth = extract::str("depth", table, "Morse potential")?;
        let x0 = extract::str("x0", table, "Morse potential")?;
        Ok(MorsePotential {
            a: units::from_str(a)?,
            depth: units::from_str(depth)?,
            x0: units::from_str(x0)?,
        })
    }
}

impl FromToml for Gaussian {
    fn from_toml(table: &Table) -> Result<Gaussian> {
        let a = units::from_str(extract::str("A", table, "Gaussian potential")?)?;
        let b = units::from_str(extract::str("B", table, "Gaussian potential")?)?;

        if b <= 0.0 {
            Err(Error::from("'B' parameter has to be positive in Gaussian potential"))
        } else {
            Ok(Gaussian::new(a, b))
        }
    }
}

impl FromTomlWithData for TableComputation {
    type Data = Box<PairPotential>;

    fn from_toml(table: &Table, potential: Box<PairPotential>) -> Result<TableComputation> {
        let table = try!(table["table"].as_table().ok_or(
            Error::from("'table' key in computation must be a TOML table")
        ));
        let n = extract::uint("n", table, "table computation")?;
        let max = extract::str("max", table, "table computation")?;
        Ok(TableComputation::new(potential, n as usize, units::from_str(max)?))
    }
}

impl FromToml for Wolf {
    fn from_toml(table: &Table) -> Result<Wolf> {
        let cutoff = extract::str("cutoff", table, "Wolf coulombic potential")?;
        Ok(Wolf::new(units::from_str(cutoff)?))
    }
}

impl FromToml for Ewald {
    fn from_toml(table: &Table) -> Result<Ewald> {
        let cutoff = extract::str("cutoff", table, "Ewald coulombic potential")?;
        let kmax = extract::uint("kmax", table, "Ewald coulombic potential")?;
        Ok(Ewald::new(units::from_str(cutoff)?, kmax as usize))
    }
}
<commit_msg>Added entry for reference<commit_after>// Lumol, an extensible molecular simulation engine
// Copyright (C) Lumol's contributors — BSD license

//! Convert TOML values to Lumol types.

use FromToml;
use FromTomlWithData;
use error::{Error, Result};
use extract;

use lumol::energy::{BornMayerHuggins, Buckingham, Gaussian, MorsePotential, Torsion};
use lumol::energy::{CosineHarmonic, Harmonic, LennardJones, NullPotential, Mie};
use lumol::energy::{Ewald, Wolf};
use lumol::energy::{PairPotential, TableComputation};
use lumol::units;
use toml::value::Table;

impl FromToml for NullPotential {
    fn from_toml(_: &Table) -> Result<NullPotential> {
        Ok(NullPotential)
    }
}

impl FromToml for Harmonic {
    fn from_toml(table: &Table) -> Result<Harmonic> {
        let k = extract::str("k", table, "harmonic potential")?;
        let x0 = extract::str("x0", table, "harmonic potential")?;
        Ok(Harmonic {
            k: units::from_str(k)?,
            x0: units::from_str(x0)?,
        })
    }
}

impl FromToml for LennardJones {
    fn from_toml(table: &Table) -> Result<LennardJones> {
        let sigma = extract::str("sigma", table, "Lennard-Jones potential")?;
        let epsilon = extract::str("epsilon", table, "Lennard-Jones potential")?;
        Ok(LennardJones {
            sigma: units::from_str(sigma)?,
            epsilon: units::from_str(epsilon)?,
        })
    }
}

impl FromToml for Mie {
    fn from_toml(table: &Table) -> Result<Mie> {
        let sigma = extract::str("sigma", table, "Mie potential")?;
        let epsilon = extract::str("epsilon", table, "Mie potential")?;
        let m = extract::number("m", table, "Mie potential")?;
        let n = extract::number("n", table, "Mie potential")?;
        Ok(Mie::new(units::from_str(sigma)?, units::from_str(epsilon)?, n as f64, m as f64))
    }
}

impl FromToml for CosineHarmonic {
    fn from_toml(table: &Table) -> Result<CosineHarmonic> {
        let k = extract::str("k", table, "cosine harmonic potential")?;
        let x0 = extract::str("x0", table, "cosine harmonic potential")?;
        Ok(CosineHarmonic::new(units::from_str(k)?, units::from_str(x0)?))
    }
}

impl FromToml for Torsion {
    fn from_toml(table: &Table) -> Result<Torsion> {
        let n = extract::uint("n", table, "torsion potential")?;
        let k = extract::str("k", table, "torsion potential")?;
        let delta = extract::str("delta", table, "torsion potential")?;
        Ok(Torsion {
            n: n as usize,
            k: units::from_str(k)?,
            delta: units::from_str(delta)?,
        })
    }
}

impl FromToml for Buckingham {
    fn from_toml(table: &Table) -> Result<Buckingham> {
        let a = extract::str("A", table, "Buckingham potential")?;
        let c = extract::str("C", table, "Buckingham potential")?;
        let rho = extract::str("rho", table, "Buckingham potential")?;

        Ok(Buckingham {
            a: units::from_str(a)?,
            c: units::from_str(c)?,
            rho: units::from_str(rho)?,
        })
    }
}

impl FromToml for BornMayerHuggins {
    fn from_toml(table: &Table) -> Result<BornMayerHuggins> {
        let a = extract::str("A", table, "Born-Mayer-Huggins potential")?;
        let c = extract::str("C", table, "Born-Mayer-Huggins potential")?;
        let d = extract::str("D", table, "Born-Mayer-Huggins potential")?;
        let rho = extract::str("rho", table, "Born-Mayer-Huggins potential")?;
        let sigma = extract::str("sigma", table, "Born-Mayer-Huggins potential")?;

        Ok(BornMayerHuggins {
            a: units::from_str(a)?,
            c: units::from_str(c)?,
            d: units::from_str(d)?,
            sigma: units::from_str(sigma)?,
            rho: units::from_str(rho)?,
        })
    }
}

impl FromToml for MorsePotential {
    fn from_toml(table: &Table) -> Result<MorsePotential> {
        let a = extract::str("A", table, "Morse potential")?;
        let depth = extract::str("depth", table, "Morse potential")?;
        let x0 = extract::str("x0", table, "Morse potential")?;
        Ok(MorsePotential {
            a: units::from_str(a)?,
            depth: units::from_str(depth)?,
            x0: units::from_str(x0)?,
        })
    }
}

impl FromToml for Gaussian {
    fn from_toml(table: &Table) -> Result<Gaussian> {
        let a = units::from_str(extract::str("A", table, "Gaussian potential")?)?;
        let b = units::from_str(extract::str("B", table, "Gaussian potential")?)?;

        if b <= 0.0 {
            Err(Error::from("'B' parameter has to be positive in Gaussian potential"))
        } else {
            Ok(Gaussian::new(a, b))
        }
    }
}

impl FromTomlWithData for TableComputation {
    type Data = Box<PairPotential>;

    fn from_toml(table: &Table, potential: Box<PairPotential>) -> Result<TableComputation> {
        let table = try!(table["table"]
            .as_table()
            .ok_or(Error::from("'table' key in computation must be a TOML table")));
        let n = extract::uint("n", table, "table computation")?;
        let max = extract::str("max", table, "table computation")?;
        Ok(TableComputation::new(potential, n as usize, units::from_str(max)?))
    }
}

impl FromToml for Wolf {
    fn from_toml(table: &Table) -> Result<Wolf> {
        let cutoff = extract::str("cutoff", table, "Wolf coulombic potential")?;
        Ok(Wolf::new(units::from_str(cutoff)?))
    }
}

impl FromToml for Ewald {
    fn from_toml(table: &Table) -> Result<Ewald> {
        let cutoff = extract::str("cutoff", table, "Ewald coulombic potential")?;
        let kmax = extract::uint("kmax", table, "Ewald coulombic potential")?;
        Ok(Ewald::new(units::from_str(cutoff)?, kmax as usize))
    }
}
<|endoftext|>


<commit_before>//! Exposes the `Iron` type, the main entrance point of the
//! `Iron` library.

use std::net::{ToSocketAddrs, SocketAddr};
use std::os;
use std::path::PathBuf;

pub use hyper::server::Listening;
use hyper::server::Server;
use hyper::net::Fresh;

use request::HttpRequest;
use response::HttpResponse;

use error::HttpResult;

use {Request, Handler};
use status;

/// The primary entrance point to `Iron`, a `struct` to instantiate a new server.
///
/// `Iron` contains the `Handler` which takes a `Request` and produces a
/// `Response`.
pub struct Iron<H> {
    /// Iron contains a `Handler`, which it uses to create responses for client
    /// requests.
    pub handler: H,

    /// Once listening, the local address that this server is bound to.
    pub addr: Option<SocketAddr>,

    /// Once listening, the protocol used to serve content.
    pub protocol: Option<Protocol>
}

/// Protocol used to serve content. Future versions of Iron may add new protocols
/// to this enum. Thus you should not exhaustively match on its variants.
#[derive(Clone)]
pub enum Protocol {
    /// Plaintext HTTP/1
    Http,
    /// HTTP/1 over SSL/TLS
    Https {
        /// Path to SSL certificate file
        certificate: PathBuf,
        /// Path to SSL private key file
        key: PathBuf
    }
}

impl Protocol {
    /// Return the name used for this protocol in a URI's scheme part.
    pub fn name(&self) -> &'static str {
        match *self {
            Protocol::Http => "http",
            Protocol::Https { .. } => "https"
        }
    }
}

impl<H: Handler> Iron<H> {
    /// Kick off the server process using the HTTP protocol.
    ///
    /// Call this once to begin listening for requests on the server.
    /// This consumes the Iron instance, but does the listening on
    /// another task, so is not blocking.
    ///
    /// Defaults to a threadpool of size `2 * num_cpus`.
    ///
    /// ## Panics
    ///
    /// Panics if the provided address does not parse. To avoid this
    /// call `to_socket_addrs` yourself and pass a parsed `SocketAddr`.
    pub fn http<A: ToSocketAddrs + 'static>(self, addr: A) -> HttpResult<Listening> {
        self.listen_with(addr, 2 * os::num_cpus(), Protocol::Http)
    }

    /// Kick off the server process using the HTTPS protocol.
    ///
    /// Call this once to begin listening for requests on the server.
    /// This consumes the Iron instance, but does the listening on
    /// another task, so is not blocking.
    ///
    /// Defaults to a threadpool of size `2 * num_cpus`.
    ///
    /// ## Panics
    ///
    /// Panics if the provided address does not parse. To avoid this
    /// call `to_socket_addrs` yourself and pass a parsed `SocketAddr`.
    pub fn https<A: ToSocketAddrs + 'static>(self, addr: A, certificate: PathBuf, key: PathBuf)
                                            -> HttpResult<Listening> {
        self.listen_with(addr, 2 * os::num_cpus(),
                         Protocol::Https { certificate: certificate, key: key })
    }

    /// Kick off the server process with X threads.
    ///
    /// ## Panics
    ///
    /// Panics if the provided address does not parse. To avoid this
    /// call `to_socket_addrs` yourself and pass a parsed `SocketAddr`.
    pub fn listen_with<A: ToSocketAddrs + 'static>(mut self, addr: A, threads: usize,
                                                  protocol: Protocol) -> HttpResult<Listening> {
        let sock_addr = addr.to_socket_addrs()
            .ok().and_then(|mut addrs| addrs.next()).expect("Could not parse socket address.");
        let ip = sock_addr.ip();
        let port = sock_addr.port();
        self.addr = Some(sock_addr);

        let server = match protocol {
            Protocol::Http => Server::http(self),
            Protocol::Https { ref certificate, ref key } =>
                Server::https(self, certificate, key)
        };

        self.protocol = Some(protocol.clone());

        Ok(try!(server.listen_threads(ip, port, threads)))
    }

    /// Instantiate a new instance of `Iron`.
    ///
    /// This will create a new `Iron`, the base unit of the server, using the
    /// passed in `Handler`.
    pub fn new(handler: H) -> Iron<H> {
        Iron { handler: handler, addr: None, protocol: None }
    }

    fn bad_request(&self, mut http_res: HttpResponse<Fresh>) {
        *http_res.status_mut() = status::BadRequest;

        let http_res = match http_res.start() {
            Ok(res) => res,
            // Would like this to work, but if not *shrug*
            Err(_) => return,
        };

        // We would like this to work, but can't do anything if it doesn't.
        let _ = http_res.end();
    }
}

impl<H: Handler> ::hyper::server::Handler for Iron<H> {
    fn handle(&self, http_req: HttpRequest, http_res: HttpResponse<Fresh>) {
        // Create `Request` wrapper.
        let mut req = match Request::from_http(http_req, self.addr.clone().unwrap(),
                                               self.protocol.as_ref().unwrap()) {
            Ok(req) => req,
            Err(e) => {
                error!("Error creating request:\n    {}", e);
                return self.bad_request(http_res);
            }
        };

        // Dispatch the request
        let res = self.handler.handle(&mut req);

        match res {
            // Write the response back to http_res
            Ok(res) => res.write_back(http_res),
            Err(e) => {
                error!("Error handling:\n{:?}\nError was: {:?}", req, e.error);
                e.response.write_back(http_res);
            }
        }
    }
}

<commit_msg>Fix write to struct that moved away<commit_after>//! Exposes the `Iron` type, the main entrance point of the
//! `Iron` library.

use std::net::{ToSocketAddrs, SocketAddr};
use std::os;
use std::path::PathBuf;

pub use hyper::server::Listening;
use hyper::server::Server;
use hyper::net::Fresh;

use request::HttpRequest;
use response::HttpResponse;

use error::HttpResult;

use {Request, Handler};
use status;

/// The primary entrance point to `Iron`, a `struct` to instantiate a new server.
///
/// `Iron` contains the `Handler` which takes a `Request` and produces a
/// `Response`.
pub struct Iron<H> {
    /// Iron contains a `Handler`, which it uses to create responses for client
    /// requests.
    pub handler: H,

    /// Once listening, the local address that this server is bound to.
    pub addr: Option<SocketAddr>,

    /// Once listening, the protocol used to serve content.
    pub protocol: Option<Protocol>
}

/// Protocol used to serve content. Future versions of Iron may add new protocols
/// to this enum. Thus you should not exhaustively match on its variants.
#[derive(Clone)]
pub enum Protocol {
    /// Plaintext HTTP/1
    Http,
    /// HTTP/1 over SSL/TLS
    Https {
        /// Path to SSL certificate file
        certificate: PathBuf,
        /// Path to SSL private key file
        key: PathBuf
    }
}

impl Protocol {
    /// Return the name used for this protocol in a URI's scheme part.
    pub fn name(&self) -> &'static str {
        match *self {
            Protocol::Http => "http",
            Protocol::Https { .. } => "https"
        }
    }
}

impl<H: Handler> Iron<H> {
    /// Kick off the server process using the HTTP protocol.
    ///
    /// Call this once to begin listening for requests on the server.
    /// This consumes the Iron instance, but does the listening on
    /// another task, so is not blocking.
    ///
    /// Defaults to a threadpool of size `2 * num_cpus`.
    ///
    /// ## Panics
    ///
    /// Panics if the provided address does not parse. To avoid this
    /// call `to_socket_addrs` yourself and pass a parsed `SocketAddr`.
    pub fn http<A: ToSocketAddrs + 'static>(self, addr: A) -> HttpResult<Listening> {
        self.listen_with(addr, 2 * os::num_cpus(), Protocol::Http)
    }

    /// Kick off the server process using the HTTPS protocol.
    ///
    /// Call this once to begin listening for requests on the server.
    /// This consumes the Iron instance, but does the listening on
    /// another task, so is not blocking.
    ///
    /// Defaults to a threadpool of size `2 * num_cpus`.
    ///
    /// ## Panics
    ///
    /// Panics if the provided address does not parse. To avoid this
    /// call `to_socket_addrs` yourself and pass a parsed `SocketAddr`.
    pub fn https<A: ToSocketAddrs + 'static>(self, addr: A, certificate: PathBuf, key: PathBuf)
                                            -> HttpResult<Listening> {
        self.listen_with(addr, 2 * os::num_cpus(),
                         Protocol::Https { certificate: certificate, key: key })
    }

    /// Kick off the server process with X threads.
    ///
    /// ## Panics
    ///
    /// Panics if the provided address does not parse. To avoid this
    /// call `to_socket_addrs` yourself and pass a parsed `SocketAddr`.
    pub fn listen_with<A: ToSocketAddrs + 'static>(mut self, addr: A, threads: usize,
                                                  protocol: Protocol) -> HttpResult<Listening> {
        let sock_addr = addr.to_socket_addrs()
            .ok().and_then(|mut addrs| addrs.next()).expect("Could not parse socket address.");
        let ip = sock_addr.ip();
        let port = sock_addr.port();
        self.addr = Some(sock_addr);

        self.protocol = Some(protocol.clone());

        let server = match protocol {
            Protocol::Http => Server::http(self),
            Protocol::Https { ref certificate, ref key } =>
                Server::https(self, certificate, key)
        };

        Ok(try!(server.listen_threads(ip, port, threads)))
    }

    /// Instantiate a new instance of `Iron`.
    ///
    /// This will create a new `Iron`, the base unit of the server, using the
    /// passed in `Handler`.
    pub fn new(handler: H) -> Iron<H> {
        Iron { handler: handler, addr: None, protocol: None }
    }

    fn bad_request(&self, mut http_res: HttpResponse<Fresh>) {
        *http_res.status_mut() = status::BadRequest;

        let http_res = match http_res.start() {
            Ok(res) => res,
            // Would like this to work, but if not *shrug*
            Err(_) => return,
        };

        // We would like this to work, but can't do anything if it doesn't.
        let _ = http_res.end();
    }
}

impl<H: Handler> ::hyper::server::Handler for Iron<H> {
    fn handle(&self, http_req: HttpRequest, http_res: HttpResponse<Fresh>) {
        // Create `Request` wrapper.
        let mut req = match Request::from_http(http_req, self.addr.clone().unwrap(),
                                               self.protocol.as_ref().unwrap()) {
            Ok(req) => req,
            Err(e) => {
                error!("Error creating request:\n    {}", e);
                return self.bad_request(http_res);
            }
        };

        // Dispatch the request
        let res = self.handler.handle(&mut req);

        match res {
            // Write the response back to http_res
            Ok(res) => res.write_back(http_res),
            Err(e) => {
                error!("Error handling:\n{:?}\nError was: {:?}", req, e.error);
                e.response.write_back(http_res);
            }
        }
    }
}

<|endoftext|>


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

use enum_primitive::FromPrimitive;
use byteorder::{NetworkEndian, ReadBytesExt};
use tokio_core::io::EasyBuf;

use ::protocol::{Magic, Command, DataType};

enum_from_primitive! {
    #[derive(Debug, PartialEq)]
    /// Response status variants
    pub enum Status {
        Ok = 0x0000,
        KeyNotFound = 0x0001,
        KeyExists = 0x0002,
        ValueTooLarge = 0x0003,
        InvalidArguments = 0x0004,
        ItemNotStored = 0x0005,
        IncrDecrOnNonNumericValue = 0x0006,
        VBucketBelongsToAnotherServer = 0x0007,
        AuthenticationError = 0x0008,
        AuthenticationContinue = 0x0009,
        UnknownCommand = 0x0081,
        OutOfMemory = 0x0082,
        NotSupported = 0x00083,
        InternalError = 0x0084,
        Busy = 0x0085,
        TemporaryFailure = 0x0086,
    }
}

/// Parsed `memcached` response.
pub struct Response {
    // We are not storing `magic` byte, because it is always the same and is not required by clients
    opcode: Command,
    key_length: u16,
    extras_length: u8,
    data_type: DataType,
    status: Status,
    body_length: u32,
    opaque: u32,
    cas: u64,
    body: Vec<u8>,
}

impl Response {
    pub fn command(&self) -> &Command {
        &self.opcode
    }

    pub fn status(&self) -> &Status {
        &self.status
    }

    pub fn data_type(&self) -> &DataType {
        &self.data_type
    }

    pub fn opaque(&self) -> &u32 {
        &self.opaque
    }

    pub fn cas(&self) -> &u64 {
        &self.cas
    }

    pub fn extras(&self) -> Option<&[u8]> {
        if self.extras_length > 0 {
            let end = self.extras_length as usize;
            return Some(&self.body[..end]);
        }
        None
    }

    pub fn key(&self) -> Option<&[u8]> {
        if self.key_length > 0 {
            let start = self.extras_length as usize;
            let end = start + self.key_length as usize;

            return Some(&self.body[start..end]);
        }

        None
    }

    pub fn value(&self) -> Option<&[u8]> {
        let start: usize = self.extras_length as usize + self.key_length as usize;
        if self.body_length as usize > start {
            return Some(&self.body[start..]);
        }

        None
    }

    /// Trying to create a `Response` from the bytes array.
    ///
    /// If `raw` is incomplete, returns `Ok(None)`, otherwise returns `Ok(Response)`,
    /// so it will be compatible with a `tokio_core.io.Codec`.
    pub fn try_from(raw: &mut EasyBuf) -> io::Result<Option<Response>> {
        let length = raw.len();

        // Quick checking if we have at least a response header
        if length < 24 {
            return Ok(None);
        }

        let header_buf = raw.drain_to(24);
        let mut header = header_buf.as_ref();
        let magic = header.read_u8()?;
        if magic != Magic::Response as u8 {
            return Err(io::Error::new(io::ErrorKind::InvalidData, "Invalid packet received"));
        }

        let mut response = Response {
            // TODO: Get rid of `unwrap` here
            opcode: Command::from_u8(header.read_u8()?).unwrap(),
            key_length: header.read_u16::<NetworkEndian>()?,
            extras_length: header.read_u8()?,
            // TODO: Get rid of `unwrap` here
            data_type: DataType::from_u8(header.read_u8()?).unwrap(),
            // TODO: Get rid of `unwrap` here
            status: Status::from_u16(header.read_u16::<NetworkEndian>()?).unwrap(),
            body_length: header.read_u32::<NetworkEndian>()?,
            opaque: header.read_u32::<NetworkEndian>()?,
            cas: header.read_u64::<NetworkEndian>()?,
            body: vec![],
        };

        if response.body_length > 0 {
            let body = raw.drain_to(response.body_length as usize);
            response.body.extend_from_slice(body.as_slice());
        }

        Ok(Some(response))
    }
}

impl fmt::Debug for Response {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        f.debug_struct("Response")
            .field("command", &self.opcode)
            .field("status", &self.status)
            .finish()
    }
}
<commit_msg>Couple doc-fixes and TODOs<commit_after>use std::io;
use std::fmt;

use enum_primitive::FromPrimitive;
use byteorder::{NetworkEndian, ReadBytesExt};
use tokio_core::io::EasyBuf;

use ::protocol::{Magic, Command, DataType};

enum_from_primitive! {
    /// Response status variants
    #[derive(Debug, PartialEq)]
    pub enum Status {
        Ok = 0x0000,
        KeyNotFound = 0x0001,
        KeyExists = 0x0002,
        ValueTooLarge = 0x0003,
        InvalidArguments = 0x0004,
        ItemNotStored = 0x0005,
        IncrDecrOnNonNumericValue = 0x0006,
        VBucketBelongsToAnotherServer = 0x0007,
        AuthenticationError = 0x0008,
        AuthenticationContinue = 0x0009,
        UnknownCommand = 0x0081,
        OutOfMemory = 0x0082,
        NotSupported = 0x00083,
        InternalError = 0x0084,
        Busy = 0x0085,
        TemporaryFailure = 0x0086,
    }
}

/// Parsed `memcached` response.
pub struct Response {
    // We are not storing `magic` byte, because it is always the same and is not required by clients
    opcode: Command,
    key_length: u16,
    extras_length: u8,
    data_type: DataType,
    status: Status,
    body_length: u32,
    opaque: u32,
    cas: u64,
    body: Vec<u8>,
}

impl Response {
    pub fn command(&self) -> &Command {
        &self.opcode
    }

    pub fn status(&self) -> &Status {
        &self.status
    }

    pub fn data_type(&self) -> &DataType {
        &self.data_type
    }

    pub fn opaque(&self) -> &u32 {
        &self.opaque
    }

    pub fn cas(&self) -> &u64 {
        &self.cas
    }

    pub fn extras(&self) -> Option<&[u8]> {
        if self.extras_length > 0 {
            let end = self.extras_length as usize;
            return Some(&self.body[..end]);
        }
        None
    }

    pub fn key(&self) -> Option<&[u8]> {
        if self.key_length > 0 {
            let start = self.extras_length as usize;
            let end = start + self.key_length as usize;

            return Some(&self.body[start..end]);
        }

        None
    }

    pub fn value(&self) -> Option<&[u8]> {
        let start: usize = self.extras_length as usize + self.key_length as usize;
        if self.body_length as usize > start {
            return Some(&self.body[start..]);
        }

        None
    }

    /// Trying to create a `Response` from the bytes array.
    ///
    /// If `raw` is incomplete, returns `Ok(None)`, otherwise returns `Ok(Some(Response))`,
    /// so it will be compatible with a `tokio_core.io.Codec`.
    pub fn try_from(raw: &mut EasyBuf) -> io::Result<Option<Response>> {
        let length = raw.len();

        // Quick checking if we have at least a response header
        if length < 24 {
            return Ok(None);
        }

        // TODO: Buffer must not be drained before we checked that both header and body are received
        let header_buf = raw.drain_to(24);
        let mut header = header_buf.as_ref();
        let magic = header.read_u8()?;
        if magic != Magic::Response as u8 {
            return Err(io::Error::new(io::ErrorKind::InvalidData, "Invalid packet received"));
        }

        let mut response = Response {
            // TODO: Get rid of `unwrap` here
            opcode: Command::from_u8(header.read_u8()?).unwrap(),
            key_length: header.read_u16::<NetworkEndian>()?,
            extras_length: header.read_u8()?,
            // TODO: Get rid of `unwrap` here
            data_type: DataType::from_u8(header.read_u8()?).unwrap(),
            // TODO: Get rid of `unwrap` here
            status: Status::from_u16(header.read_u16::<NetworkEndian>()?).unwrap(),
            body_length: header.read_u32::<NetworkEndian>()?,
            opaque: header.read_u32::<NetworkEndian>()?,
            cas: header.read_u64::<NetworkEndian>()?,
            body: vec![],
        };

        if response.body_length > 0 {
            let body = raw.drain_to(response.body_length as usize);
            response.body.extend_from_slice(body.as_slice());
        }

        Ok(Some(response))
    }
}

impl fmt::Debug for Response {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        f.debug_struct("Response")
            .field("command", &self.opcode)
            .field("status", &self.status)
            .finish()
    }
}
<|endoftext|>


<commit_before><commit_msg>Removed unneeded copy<commit_after><|endoftext|>


<commit_before>use {ffi, ColumnDescriptor, Raii, Return, Handle, Statement, Result, Prepared, Allocated,
     NoResult, ResultSetState};
use odbc_safe::AutocommitMode;

impl<'a, 'b, AC: AutocommitMode> Statement<'a, 'b, Allocated, NoResult, AC> {
    /// Prepares a statement for execution. Executing a prepared statement is faster than directly
    /// executing an unprepared statement, since it is already compiled into an Access Plan. This
    /// makes preparing statement a good idea if you want to repeatedly execute a query with a
    /// different set of parameters and care about performance.
    ///
    /// # Example
    ///
    /// ```rust
    /// # use odbc::*;
    /// # fn doc() -> Result<()>{
    /// let env = create_environment_v3().map_err(|e| e.unwrap())?;
    /// let conn = env.connect("TestDataSource", "", "")?;
    /// let stmt = Statement::with_parent(&conn)?;
    /// let mut stmt = stmt.prepare("SELECT TITLE FROM MOVIES WHERE YEAR = ?")?;
    ///
    /// fn print_one_movie_from<'a> (year: u16, stmt: Statement<'a,'a, Prepared, NoResult, safe::AutocommitOn>) -> Result<Statement<'a, 'a, Prepared, NoResult, safe::AutocommitOn>>{
    ///    let stmt = stmt.bind_parameter(1, &year)?;
    ///    let stmt = if let Data(mut stmt) = stmt.execute()?{
    ///        if let Some(mut cursor) = stmt.fetch()?{
    ///            println!("{}", cursor.get_data::<String>(1)?.unwrap());
    ///        }
    ///        stmt.close_cursor()?
    ///    } else {
    ///       panic!("SELECT statement returned no result set");
    ///    };
    ///    stmt.reset_parameters()
    /// };
    ///
    /// for year in 1990..2010{
    ///     stmt = print_one_movie_from(year, stmt)?
    /// }
    ///
    /// # Ok(())
    /// # }
    /// ```
    pub fn prepare(mut self, sql_text: &str) -> Result<Statement<'a, 'b, Prepared, NoResult, AC>> {
        self.raii.prepare(sql_text).into_result(&mut self)?;
        Ok(Statement::with_raii(self.raii))
    }

    /// Prepares a statement for execution. Executing a prepared statement is faster than directly
    /// executing an unprepared statement, since it is already compiled into an Access Plan. This
    /// makes preparing statement a good idea if you want to repeatedly execute a query with a
    /// different set of parameters and care about performance.
    ///
    /// # Example
    ///
    /// ```rust
    /// # use odbc::*;
    /// # fn doc() -> Result<()>{
    /// let env = create_environment_v3().map_err(|e| e.unwrap())?;
    /// let conn = env.connect("TestDataSource", "", "")?;
    /// let stmt = Statement::with_parent(&conn)?;
    /// // need encode_rs crate
    /// // let mut stmt = stmt.prepare_bytes(&GB2312.encode("select '你好' as hello").0)?;
    ///
    /// # Ok(())
    /// # }
    /// ```
    pub fn prepare_bytes(mut self, bytes: &[u8]) -> Result<Statement<'a, 'b, Prepared, NoResult, AC>> {
        self.raii.prepare_byte(bytes).into_result(&mut self)?;
        Ok(Statement::with_raii(self.raii))
    }
}

impl<'a, 'b, AC: AutocommitMode> Statement<'a, 'b, Prepared, NoResult, AC> {
    /// The number of columns in a result set
    ///
    /// Can be called successfully only when the statement is in the prepared, executed, or
    /// positioned state. If the statement does not return columns the result will be 0.
    pub fn num_result_cols(&self) -> Result<i16> {
        self.raii.num_result_cols().into_result(self)
    }

    /// Returns description struct for result set column with a given index. Note: indexing is starting from 1.
    pub fn describe_col(&self, idx: u16) -> Result<ColumnDescriptor> {
        self.raii.describe_col(idx).into_result(self)
    }

    /// Executes a prepared statement.
    pub fn execute(mut self) -> Result<ResultSetState<'a, 'b, Prepared, AC>> {
        if self.raii.execute().into_result(&mut self)? {
            let num_cols = self.raii.num_result_cols().into_result(&self)?;
            if num_cols > 0 {
                Ok(ResultSetState::Data(Statement::with_raii(self.raii)))
            } else {
                Ok(ResultSetState::NoData(Statement::with_raii(self.raii)))
            }
        } else {
            Ok(ResultSetState::NoData(Statement::with_raii(self.raii)))
        }
    }
}

impl Raii<ffi::Stmt> {
    fn prepare(&mut self, sql_text: &str) -> Return<()> {
        let bytes = unsafe { crate::environment::DB_ENCODING }.encode(sql_text).0;
        match unsafe {
            ffi::SQLPrepare(
                self.handle(),
                bytes.as_ptr(),
                bytes.len() as ffi::SQLINTEGER,
            )
        } {
            ffi::SQL_SUCCESS => Return::Success(()),
            ffi::SQL_SUCCESS_WITH_INFO => Return::SuccessWithInfo(()),
            ffi::SQL_ERROR => Return::Error,
            r => panic!("SQLPrepare returned unexpected result: {:?}", r),
        }
    }

    fn prepare_byte(&mut self, bytes: &[u8]) -> Return<()> {
        match unsafe {
            ffi::SQLPrepare(
                self.handle(),
                bytes.as_ptr(),
                bytes.len() as ffi::SQLINTEGER,
            )
        } {
            ffi::SQL_SUCCESS => Return::Success(()),
            ffi::SQL_SUCCESS_WITH_INFO => Return::SuccessWithInfo(()),
            ffi::SQL_ERROR => Return::Error,
            r => panic!("SQLPrepare returned unexpected result: {:?}", r),
        }
    }

    fn execute(&mut self) -> Return<bool> {
        match unsafe { ffi::SQLExecute(self.handle()) } {
            ffi::SQL_SUCCESS => Return::Success(true),
            ffi::SQL_SUCCESS_WITH_INFO => Return::SuccessWithInfo(true),
            ffi::SQL_ERROR => Return::Error,
            ffi::SQL_NO_DATA => Return::Success(false),
            r => panic!("SQLExecute returned unexpected result: {:?}", r),
        }
    }
}
<commit_msg>Update prepare.rs<commit_after>use {ffi, ColumnDescriptor, Raii, Return, Handle, Statement, Result, Prepared, Allocated,
     NoResult, ResultSetState};
use odbc_safe::AutocommitMode;

impl<'a, 'b, AC: AutocommitMode> Statement<'a, 'b, Allocated, NoResult, AC> {
    /// Prepares a statement for execution. Executing a prepared statement is faster than directly
    /// executing an unprepared statement, since it is already compiled into an Access Plan. This
    /// makes preparing statement a good idea if you want to repeatedly execute a query with a
    /// different set of parameters and care about performance.
    ///
    /// # Example
    ///
    /// ```rust
    /// # use odbc::{*, safe};
    /// # fn doc() -> Result<()>{
    /// let env = create_environment_v3().map_err(|e| e.unwrap())?;
    /// let conn = env.connect("TestDataSource", "", "")?;
    /// let stmt = Statement::with_parent(&conn)?;
    /// let mut stmt = stmt.prepare("SELECT TITLE FROM MOVIES WHERE YEAR = ?")?;
    ///
    /// fn print_one_movie_from<'a> (year: u16, stmt: Statement<'a,'a, Prepared, NoResult, safe::AutocommitOn>) -> Result<Statement<'a, 'a, Prepared, NoResult, safe::AutocommitOn>>{
    ///    let stmt = stmt.bind_parameter(1, &year)?;
    ///    let stmt = if let Data(mut stmt) = stmt.execute()?{
    ///        if let Some(mut cursor) = stmt.fetch()?{
    ///            println!("{}", cursor.get_data::<String>(1)?.unwrap());
    ///        }
    ///        stmt.close_cursor()?
    ///    } else {
    ///       panic!("SELECT statement returned no result set");
    ///    };
    ///    stmt.reset_parameters()
    /// };
    ///
    /// for year in 1990..2010{
    ///     stmt = print_one_movie_from(year, stmt)?
    /// }
    ///
    /// # Ok(())
    /// # }
    /// ```
    pub fn prepare(mut self, sql_text: &str) -> Result<Statement<'a, 'b, Prepared, NoResult, AC>> {
        self.raii.prepare(sql_text).into_result(&mut self)?;
        Ok(Statement::with_raii(self.raii))
    }

    /// Prepares a statement for execution. Executing a prepared statement is faster than directly
    /// executing an unprepared statement, since it is already compiled into an Access Plan. This
    /// makes preparing statement a good idea if you want to repeatedly execute a query with a
    /// different set of parameters and care about performance.
    ///
    /// # Example
    ///
    /// ```rust
    /// # use odbc::*;
    /// # fn doc() -> Result<()>{
    /// let env = create_environment_v3().map_err(|e| e.unwrap())?;
    /// let conn = env.connect("TestDataSource", "", "")?;
    /// let stmt = Statement::with_parent(&conn)?;
    /// // need encode_rs crate
    /// // let mut stmt = stmt.prepare_bytes(&GB2312.encode("select '你好' as hello").0)?;
    ///
    /// # Ok(())
    /// # }
    /// ```
    pub fn prepare_bytes(mut self, bytes: &[u8]) -> Result<Statement<'a, 'b, Prepared, NoResult, AC>> {
        self.raii.prepare_byte(bytes).into_result(&mut self)?;
        Ok(Statement::with_raii(self.raii))
    }
}

impl<'a, 'b, AC: AutocommitMode> Statement<'a, 'b, Prepared, NoResult, AC> {
    /// The number of columns in a result set
    ///
    /// Can be called successfully only when the statement is in the prepared, executed, or
    /// positioned state. If the statement does not return columns the result will be 0.
    pub fn num_result_cols(&self) -> Result<i16> {
        self.raii.num_result_cols().into_result(self)
    }

    /// Returns description struct for result set column with a given index. Note: indexing is starting from 1.
    pub fn describe_col(&self, idx: u16) -> Result<ColumnDescriptor> {
        self.raii.describe_col(idx).into_result(self)
    }

    /// Executes a prepared statement.
    pub fn execute(mut self) -> Result<ResultSetState<'a, 'b, Prepared, AC>> {
        if self.raii.execute().into_result(&mut self)? {
            let num_cols = self.raii.num_result_cols().into_result(&self)?;
            if num_cols > 0 {
                Ok(ResultSetState::Data(Statement::with_raii(self.raii)))
            } else {
                Ok(ResultSetState::NoData(Statement::with_raii(self.raii)))
            }
        } else {
            Ok(ResultSetState::NoData(Statement::with_raii(self.raii)))
        }
    }
}

impl Raii<ffi::Stmt> {
    fn prepare(&mut self, sql_text: &str) -> Return<()> {
        let bytes = unsafe { crate::environment::DB_ENCODING }.encode(sql_text).0;
        match unsafe {
            ffi::SQLPrepare(
                self.handle(),
                bytes.as_ptr(),
                bytes.len() as ffi::SQLINTEGER,
            )
        } {
            ffi::SQL_SUCCESS => Return::Success(()),
            ffi::SQL_SUCCESS_WITH_INFO => Return::SuccessWithInfo(()),
            ffi::SQL_ERROR => Return::Error,
            r => panic!("SQLPrepare returned unexpected result: {:?}", r),
        }
    }

    fn prepare_byte(&mut self, bytes: &[u8]) -> Return<()> {
        match unsafe {
            ffi::SQLPrepare(
                self.handle(),
                bytes.as_ptr(),
                bytes.len() as ffi::SQLINTEGER,
            )
        } {
            ffi::SQL_SUCCESS => Return::Success(()),
            ffi::SQL_SUCCESS_WITH_INFO => Return::SuccessWithInfo(()),
            ffi::SQL_ERROR => Return::Error,
            r => panic!("SQLPrepare returned unexpected result: {:?}", r),
        }
    }

    fn execute(&mut self) -> Return<bool> {
        match unsafe { ffi::SQLExecute(self.handle()) } {
            ffi::SQL_SUCCESS => Return::Success(true),
            ffi::SQL_SUCCESS_WITH_INFO => Return::SuccessWithInfo(true),
            ffi::SQL_ERROR => Return::Error,
            ffi::SQL_NO_DATA => Return::Success(false),
            r => panic!("SQLExecute returned unexpected result: {:?}", r),
        }
    }
}
<|endoftext|>


<commit_before>//! Contains information for keybindings.

use std::collections::HashMap;
use std::sync::{Arc, RwLock};
use std::hash::{Hash, Hasher};

use rustwlc::xkb::{Keysym, NameFlags};
use rustwlc::types::*; // Need * for bitflags...

use super::layout::tree;
use super::lua;

/// Register default keypresses to a map
macro_rules! register_defaults {
    ( $map:expr; $($func:expr, $press:expr);+ ) => {
        $(
            let _ = $map.insert($press, Arc::new(Box::new($func)));
            )+
    }
}

/// Generate switch_workspace methods and register them in $map
macro_rules! gen_switch_workspace {
    ($map:expr; $($b:ident, $n:expr);+) => {
        $(fn $b() {
            trace!("Switching to workspace {}", $n);
            tree::switch_workspace(&$n.to_string())
                .expect("Could not switch to a work-space");
                }
          register_defaults!( $map; $b, keypress!("Alt", $n) );
          )+
    };
}

lazy_static! {
    static ref BINDINGS: RwLock<HashMap<KeyPress, KeyEvent>> = {
        let mut map = HashMap::<KeyPress, KeyEvent>::new();

        gen_switch_workspace!(map; switch_workspace_1, "1";
                              switch_workspace_2, "2";
                              switch_workspace_3, "3";
                              switch_workspace_4, "4";
                              switch_workspace_5, "5";
                              switch_workspace_6, "6";
                              switch_workspace_7, "7";
                              switch_workspace_8, "8";
                              switch_workspace_9, "9";
                              switch_workspace_0, "0");

        register_defaults! {
            map;
            quit_fn, keypress!("Alt", "Escape");
            terminal_fn, keypress!("Alt", "Return");
            dmenu_fn, keypress!("Alt", "d");
            pointer_fn, keypress!("Alt", "p")
        }

        RwLock::new(map)
    };
}

fn terminal_fn() {
    use std::process::Command;
    Command::new("sh")
        .arg("-c")
        .arg("weston-terminal")
        .spawn().expect("Error launching terminal");
}

fn dmenu_fn() {
    use std::process::Command;
    Command::new("sh")
        .arg("-c")
        .arg("dmenu_run")
        .spawn().expect("Error launching terminal");
}

fn pointer_fn() {
    use lua::LuaQuery;
    let code = "if wm == nil then print('wm table does not exist')\n\
                elseif wm.pointer == nil then print('wm.pointer table does not exist')\n\
                else\n\
                print('get_position is a func, preparing execution')
                local x, y = wm.pointer.get_position()\n\
                print('The cursor is at ' .. x .. ', ' .. y)\n\
                end".to_string();
    lua::send(LuaQuery::Execute(code))
        .expect("Error telling Lua to get pointer coords");
}

fn quit_fn() {
    info!("handler: Esc keypress!");
    ::rustwlc::terminate();
}

#[derive(Eq, PartialEq, Clone, Debug)]
pub struct KeyPress {
    modifiers: KeyMod,
    keys: Vec<Keysym>
}

/// Parses a KeyMod from key names.
pub fn keymod_from_names(keys: Vec<&str>) -> Result<KeyMod, String> {
    let mut result = KeyMod::empty();
    for key in keys {
        match key.to_lowercase().as_str() {
            "shift"            => result = result | MOD_SHIFT,
            "control" | "ctrl" => result = result | MOD_CTRL,
            "alt"              => result = result | MOD_ALT,
            "mod2"             => result = result | MOD_MOD2,
            "mod3"             => result = result | MOD_MOD3,
            "mod4" | "super" | "logo" => result = result | MOD_MOD4,
            "mod5" | "5mod5me" => result = result | MOD_MOD5,
            err => return Err(format!("Invalid modifier: {}", err))
        }
    }
    return Ok(result);
}

impl KeyPress {
    /// Creates a new KeyPress struct from a list of modifier and key names
    pub fn from_key_names(mods: Vec<&str>, keys: Vec<&str>) -> Result<KeyPress, String> {
        keymod_from_names(mods).and_then(|mods| {
            let mut syms: Vec<Keysym> = Vec::with_capacity(keys.len());
            for name in keys {
                // Parse a keysym for each given key
                if let Some(sym) = Keysym::from_name(name.to_string(),
                                                     NameFlags::None) {
                    syms.push(sym);
                }
                // If lowercase cannot be parsed, try case insensitive
                else if let Some(sym) = Keysym::from_name(name.to_string(),
                                                          NameFlags::CaseInsensitive) {
                    syms.push(sym);
                }
                else {
                    return Err(format!("Invalid key: {}", name));
                }
            }
            // Sort and dedup to make sure hashes are the same
            syms.sort_by_key(|s| s.get_code());
            syms.dedup();
            return Ok(KeyPress { modifiers: mods, keys: syms });
        })
    }

    /// Creates a KeyPress from keys that are pressed at the moment
    pub fn new(mods: KeyMod, mut keys: Vec<Keysym>) -> KeyPress {
        // Sort and dedup to make sure hashes are the same
        keys.sort_by_key(|k| k.get_code());
        keys.dedup();

        KeyPress { modifiers: mods, keys: keys }
    }
}

impl Hash for KeyPress {
    fn hash<H: Hasher>(&self, hasher: &mut H) {
        hasher.write_u32(self.modifiers.bits());
        for ref sym in &self.keys {
            hasher.write_u32(sym.get_code());
        }
    }
}

/// The type of function a key press handler is.
pub type KeyEvent = Arc<Box<Fn() + Send + Sync>>;

/// Get a key mapping from the list.
pub fn get(key: &KeyPress) -> Option<KeyEvent> {
    let bindings = BINDINGS.read()
        .expect("Keybindings/get: unable to lock keybindings");
    match bindings.get(key) {
        None => None,
        Some(val) => Some(val.clone())
    }
}

/// Register a new set of key mappings
#[allow(dead_code)]
pub fn register(values: Vec<(KeyPress, KeyEvent)>) {
    let mut bindings = BINDINGS.write()
        .expect("Keybindings/register: unable to lock keybindings");
    for value in values {
        bindings.insert(value.0, value.1);
    }
}

#[cfg(test)]
mod tests {
    use super::*;
    use std::sync::Arc;

    fn test_cmd() {
        assert!(true);
    }

    fn keypress() -> KeyPress {
        keypress!("Ctrl", "t")
    }

    #[test]
    fn add_key() {
        register(vec![(keypress(), Arc::new(Box::new(test_cmd)))]);
        assert!(get(&keypress()).is_some(), "Key not registered");
    }
}
<commit_msg>Remove unneeded Box from KeyEvent<commit_after>//! Contains information for keybindings.

use std::collections::HashMap;
use std::sync::{Arc, RwLock};
use std::hash::{Hash, Hasher};

use rustwlc::xkb::{Keysym, NameFlags};
use rustwlc::types::*; // Need * for bitflags...

use super::layout::tree;
use super::lua;

/// Register default keypresses to a map
macro_rules! register_defaults {
    ( $map:expr; $($func:expr, $press:expr);+ ) => {
        $(
            let _ = $map.insert($press, Arc::new($func));
            )+
    }
}

/// Generate switch_workspace methods and register them in $map
macro_rules! gen_switch_workspace {
    ($map:expr; $($b:ident, $n:expr);+) => {
        $(fn $b() {
            trace!("Switching to workspace {}", $n);
            tree::switch_workspace(&$n.to_string())
                .expect("Could not switch to a work-space");
                }
          register_defaults!( $map; $b, keypress!("Alt", $n) );
          )+
    };
}

lazy_static! {
    static ref BINDINGS: RwLock<HashMap<KeyPress, KeyEvent>> = {
        let mut map = HashMap::<KeyPress, KeyEvent>::new();

        gen_switch_workspace!(map; switch_workspace_1, "1";
                              switch_workspace_2, "2";
                              switch_workspace_3, "3";
                              switch_workspace_4, "4";
                              switch_workspace_5, "5";
                              switch_workspace_6, "6";
                              switch_workspace_7, "7";
                              switch_workspace_8, "8";
                              switch_workspace_9, "9";
                              switch_workspace_0, "0");

        register_defaults! {
            map;
            quit_fn, keypress!("Alt", "Escape");
            terminal_fn, keypress!("Alt", "Return");
            dmenu_fn, keypress!("Alt", "d");
            pointer_fn, keypress!("Alt", "p")
        }

        RwLock::new(map)
    };
}

fn terminal_fn() {
    use std::process::Command;
    Command::new("sh")
        .arg("-c")
        .arg("weston-terminal")
        .spawn().expect("Error launching terminal");
}

fn dmenu_fn() {
    use std::process::Command;
    Command::new("sh")
        .arg("-c")
        .arg("dmenu_run")
        .spawn().expect("Error launching terminal");
}

fn pointer_fn() {
    use lua::LuaQuery;
    let code = "if wm == nil then print('wm table does not exist')\n\
                elseif wm.pointer == nil then print('wm.pointer table does not exist')\n\
                else\n\
                print('get_position is a func, preparing execution')
                local x, y = wm.pointer.get_position()\n\
                print('The cursor is at ' .. x .. ', ' .. y)\n\
                end".to_string();
    lua::send(LuaQuery::Execute(code))
        .expect("Error telling Lua to get pointer coords");
}

fn quit_fn() {
    info!("handler: Esc keypress!");
    ::rustwlc::terminate();
}

#[derive(Eq, PartialEq, Clone, Debug)]
pub struct KeyPress {
    modifiers: KeyMod,
    keys: Vec<Keysym>
}

/// Parses a KeyMod from key names.
pub fn keymod_from_names(keys: Vec<&str>) -> Result<KeyMod, String> {
    let mut result = KeyMod::empty();
    for key in keys {
        match key.to_lowercase().as_str() {
            "shift"            => result = result | MOD_SHIFT,
            "control" | "ctrl" => result = result | MOD_CTRL,
            "alt"              => result = result | MOD_ALT,
            "mod2"             => result = result | MOD_MOD2,
            "mod3"             => result = result | MOD_MOD3,
            "mod4" | "super" | "logo" => result = result | MOD_MOD4,
            "mod5" | "5mod5me" => result = result | MOD_MOD5,
            err => return Err(format!("Invalid modifier: {}", err))
        }
    }
    return Ok(result);
}

impl KeyPress {
    /// Creates a new KeyPress struct from a list of modifier and key names
    pub fn from_key_names(mods: Vec<&str>, keys: Vec<&str>) -> Result<KeyPress, String> {
        keymod_from_names(mods).and_then(|mods| {
            let mut syms: Vec<Keysym> = Vec::with_capacity(keys.len());
            for name in keys {
                // Parse a keysym for each given key
                if let Some(sym) = Keysym::from_name(name.to_string(),
                                                     NameFlags::None) {
                    syms.push(sym);
                }
                // If lowercase cannot be parsed, try case insensitive
                else if let Some(sym) = Keysym::from_name(name.to_string(),
                                                          NameFlags::CaseInsensitive) {
                    syms.push(sym);
                }
                else {
                    return Err(format!("Invalid key: {}", name));
                }
            }
            // Sort and dedup to make sure hashes are the same
            syms.sort_by_key(|s| s.get_code());
            syms.dedup();
            return Ok(KeyPress { modifiers: mods, keys: syms });
        })
    }

    /// Creates a KeyPress from keys that are pressed at the moment
    pub fn new(mods: KeyMod, mut keys: Vec<Keysym>) -> KeyPress {
        // Sort and dedup to make sure hashes are the same
        keys.sort_by_key(|k| k.get_code());
        keys.dedup();

        KeyPress { modifiers: mods, keys: keys }
    }
}

impl Hash for KeyPress {
    fn hash<H: Hasher>(&self, hasher: &mut H) {
        hasher.write_u32(self.modifiers.bits());
        for ref sym in &self.keys {
            hasher.write_u32(sym.get_code());
        }
    }
}

/// The type of function a key press handler is.
pub type KeyEvent = Arc<Fn() + Send + Sync>;

/// Get a key mapping from the list.
pub fn get(key: &KeyPress) -> Option<KeyEvent> {
    let bindings = BINDINGS.read()
        .expect("Keybindings/get: unable to lock keybindings");
    match bindings.get(key) {
        None => None,
        Some(val) => Some(val.clone())
    }
}

/// Register a new set of key mappings
#[allow(dead_code)]
pub fn register(values: Vec<(KeyPress, KeyEvent)>) {
    let mut bindings = BINDINGS.write()
        .expect("Keybindings/register: unable to lock keybindings");
    for value in values {
        bindings.insert(value.0, value.1);
    }
}

#[cfg(test)]
mod tests {
    use super::*;
    use std::sync::Arc;

    fn test_cmd() {
        assert!(true);
    }

    fn keypress() -> KeyPress {
        keypress!("Ctrl", "t")
    }

    #[test]
    fn add_key() {
        register(vec![(keypress(), Arc::new(test_cmd))]);
        assert!(get(&keypress()).is_some(), "Key not registered");
    }
}
<|endoftext|>


<commit_before>use af;
use af::Array;

use error::HALError;

/// Return a vector form of the l2 error
/// (y - x) * (y - x)
pub fn l2_vec(pred: &Array, target: &Array) -> Array{
  let diff = af::sub(pred, target, false);
  af::mul(&diff, &diff, false)
}

/// Return a vector form of the mean squared error
/// 0.5 * (y - x) * (y - x)
pub fn mse_vec(pred: &Array, target: &Array) -> Array {
  af::mul(&l2_vec(pred, target), &0.5f32, false)
}

/// Return a vector form of cross entropy
/// -ylnx - [1-y]ln[1-x]
pub fn cross_entropy_vec(pred: &Array, target: &Array) -> Array {
  let pos = af::mul(&af::mul(&-1.0, target, false)
                    , &af::log(&pred), false); // -ylnx
  let neg = af::mul(&af::sub(&1.0, target, false)       //[1-y]ln[1-x]
                    , &af::log(&(af::sub(&1.0, pred, false))), false);
  af::sub(&pos, &neg, false)
}

/// Provide a reduced form the L2 loss (single scalar)
pub fn l2(pred: &Array, target: &Array) -> f32 {
  af::sum_all(&l2_vec(pred, target)).0 as f32
}

/// Provide a reduced form the mean squared error loss (single scalar)
pub fn mse(pred: &Array, target: &Array) -> f32 {
  0.5f32 * af::mean_all(&l2_vec(pred, target)).0 as f32
}

/// Provide a reduced form the cross-entropy loss (single scalar)
pub fn cross_entropy(pred: &Array, target: &Array) -> f32 {
  // y: true target, x: prediction
  // E = sum(-ylnx - [1-y]ln[1-x])
  af::sum_all(&cross_entropy_vec(pred, target)).0 as f32
}

/// Provides the vector derivative of the mean squared error
pub fn mse_derivative(pred: &Array, target: &Array) -> Array {
  af::sub(pred, target, false)
}
/// Provides the vector derivative of the l2 error
pub fn l2_derivative(pred: &Array, target: &Array) -> Array {
  af::mul(&mse_derivative(pred, target), &2.0f32, false)
}

/// Provides the vector derivative of the cross-entropy error
pub fn cross_entropy_derivative(pred: &Array, target: &Array) -> Array {
  mse_derivative(pred, target)
}

/// Helper to provide a loss from a string
pub fn get_loss(name: &str, pred: &Array, target: &Array) -> Result<f32, HALError> {
  match name {
    "l2"            => Ok(l2(pred, target)),
    "mse"           => Ok(mse(pred, target)),
    "cross_entropy" => Ok(cross_entropy(pred, target)),
    _               => Err(HALError::UNKNOWN),
  }
}

/// Helper to provide a loss vector from a string
pub fn get_loss_vec(name: &str, pred: &Array, target: &Array) -> Result<Array, HALError> {
  match name {
    "l2"            => Ok(l2_vec(pred, target)),
    "mse"           => Ok(mse_vec(pred, target)),
    "cross_entropy" => Ok(cross_entropy_vec(pred, target)),
    _               => Err(HALError::UNKNOWN),
  }
}

/// Helper to provide a loss derivative from a string
pub fn get_loss_derivative(name: &str, pred: &Array, target: &Array) -> Result<Array, HALError> {
  match name {
    "l2"            => Ok(l2_derivative(pred, target)),
    "mse"           => Ok(mse_derivative(pred, target)),
    "cross_entropy" => Ok(cross_entropy_derivative(pred, target)),
    _               => Err(HALError::UNKNOWN),
  }
}
<commit_msg>fix double issue with xentropy<commit_after>use af;
use af::Array;

use error::HALError;

/// Return a vector form of the l2 error
/// (y - x) * (y - x)
pub fn l2_vec(pred: &Array, target: &Array) -> Array{
  let diff = af::sub(pred, target, false);
  af::mul(&diff, &diff, false)
}

/// Return a vector form of the mean squared error
/// 0.5 * (y - x) * (y - x)
pub fn mse_vec(pred: &Array, target: &Array) -> Array {
  af::mul(&l2_vec(pred, target), &0.5f32, false)
}

/// Return a vector form of cross entropy
/// -ylnx - [1-y]ln[1-x]
pub fn cross_entropy_vec(pred: &Array, target: &Array) -> Array {
  let pos = af::mul(&af::mul(&-1.0f32, target, false)
                    , &af::log(&pred), false); // -ylnx
  let neg = af::mul(&af::sub(&1.0f32, target, false)       //[1-y]ln[1-x]
                    , &af::log(&(af::sub(&1.0f32, pred, false))), false);
  af::sub(&pos, &neg, false)
}

/// Provide a reduced form the L2 loss (single scalar)
pub fn l2(pred: &Array, target: &Array) -> f32 {
  af::sum_all(&l2_vec(pred, target)).0 as f32
}

/// Provide a reduced form the mean squared error loss (single scalar)
pub fn mse(pred: &Array, target: &Array) -> f32 {
  0.5f32 * af::mean_all(&l2_vec(pred, target)).0 as f32
}

/// Provide a reduced form the cross-entropy loss (single scalar)
pub fn cross_entropy(pred: &Array, target: &Array) -> f32 {
  // y: true target, x: prediction
  // E = sum(-ylnx - [1-y]ln[1-x])
  af::sum_all(&cross_entropy_vec(pred, target)).0 as f32
}

/// Provides the vector derivative of the mean squared error
pub fn mse_derivative(pred: &Array, target: &Array) -> Array {
  af::sub(pred, target, false)
}
/// Provides the vector derivative of the l2 error
pub fn l2_derivative(pred: &Array, target: &Array) -> Array {
  af::mul(&mse_derivative(pred, target), &2.0f32, false)
}

/// Provides the vector derivative of the cross-entropy error
pub fn cross_entropy_derivative(pred: &Array, target: &Array) -> Array {
  mse_derivative(pred, target)
}

/// Helper to provide a loss from a string
pub fn get_loss(name: &str, pred: &Array, target: &Array) -> Result<f32, HALError> {
  match name {
    "l2"            => Ok(l2(pred, target)),
    "mse"           => Ok(mse(pred, target)),
    "cross_entropy" => Ok(cross_entropy(pred, target)),
    _               => Err(HALError::UNKNOWN),
  }
}

/// Helper to provide a loss vector from a string
pub fn get_loss_vec(name: &str, pred: &Array, target: &Array) -> Result<Array, HALError> {
  match name {
    "l2"            => Ok(l2_vec(pred, target)),
    "mse"           => Ok(mse_vec(pred, target)),
    "cross_entropy" => Ok(cross_entropy_vec(pred, target)),
    _               => Err(HALError::UNKNOWN),
  }
}

/// Helper to provide a loss derivative from a string
pub fn get_loss_derivative(name: &str, pred: &Array, target: &Array) -> Result<Array, HALError> {
  match name {
    "l2"            => Ok(l2_derivative(pred, target)),
    "mse"           => Ok(mse_derivative(pred, target)),
    "cross_entropy" => Ok(cross_entropy_derivative(pred, target)),
    _               => Err(HALError::UNKNOWN),
  }
}
<|endoftext|>


<commit_before><commit_msg>Fix values for Solaris<commit_after><|endoftext|>


<commit_before>use proc_macro::TokenStream;
use quote::quote;
use std::{fs::File, io::BufWriter, path::PathBuf};
use syn::{parse_macro_input, Data, DataStruct, DeriveInput};

use crate::to_adoc::ToAdoc;

pub fn derive(input: TokenStream) -> TokenStream {
    let input = parse_macro_input!(input as DeriveInput);

    let r#struct = Struct {
        name: input.ident.to_string(),
        docs: collect_docs_from_attrs(&input.attrs),
        fields: collect_fields(&input.data),
    };
    let adoc = adoc_output_path(&input.ident);
    let mut file =
        BufWriter::new(File::create(&adoc).expect(&format!("cannot write to {}", adoc.display())));
    r#struct.write_adoc(&mut file).expect(&format!(
        "cannot write {} as asciidoc to {}",
        r#struct.name,
        adoc.display()
    ));

    TokenStream::from(quote! {})
}

#[derive(Debug)]
pub(crate) struct Struct {
    pub(crate) name: String,
    pub(crate) docs: String,
    pub(crate) fields: Vec<Field>,
}

#[derive(Debug)]
pub(crate) struct Field {
    pub(crate) name: String,
    pub(crate) docs: String,
    pub(crate) required: bool,
    pub(crate) r#type: Type,
}

#[derive(Debug)]
pub(crate) enum Type {
    Flat(TypeName),
    Nested {
        container_name: TypeName,
        nested: Vec<Type>,
    },
}

#[derive(Debug)]
pub enum TypeName {
    Primitive(String),
    Link(String),
}

fn adoc_output_path(name: &syn::Ident) -> PathBuf {
    let target = std::env::var("COLLECT_DOCS_TARGET").unwrap_or("./docs/generated".into());
    std::fs::create_dir_all(&target).expect(&format!("could not create directory {}", target));
    PathBuf::from(&target)
        .join(name.to_string())
        .with_extension("adoc")
}

fn collect_fields(data: &Data) -> Vec<Field> {
    match data {
        Data::Struct(DataStruct {
            fields: syn::Fields::Unit,
            ..
        }) => vec![],
        Data::Struct(DataStruct {
            fields: syn::Fields::Unnamed(..),
            ..
        }) => vec![],
        Data::Struct(DataStruct {
            fields: syn::Fields::Named(fields),
            ..
        }) => fields
            .named
            .iter()
            .map(|field| {
                let (required, r#type) = Type::toplevel_from_syn(&field.ty);
                Field {
                    name: field
                        .ident
                        .as_ref()
                        .expect(&format!("struct field `{:?}` has no name", field))
                        .to_string(),
                    docs: collect_docs_from_attrs(&field.attrs),
                    required,
                    r#type,
                }
            })
            .collect(),
        _ => unimplemented!("Can only collect docs for structs for now"),
    }
}

fn collect_docs_from_attrs(attrs: &[syn::Attribute]) -> String {
    attrs
        .iter()
        .filter(|attr| attr.path.is_ident("doc"))
        .fold(String::new(), |mut res, attr| {
            use once_cell::sync::Lazy;
            use regex::Regex;
            use std::fmt::Write;

            let doc = TokenStream::from(attr.tokens.clone()).to_string();

            static RE: Lazy<Regex> =
                Lazy::new(|| regex::Regex::new(r#"^\s*=\s*"\s?(?P<content>.*?)"\s*$"#).unwrap());
            let doc = RE.replace_all(&doc, "$content");

            let doc = doc.replace("\\\"", "\"").replace("\\'", "'");
            writeln!(&mut res, "{}", doc).unwrap();
            res
        })
}

impl TypeName {
    fn from_ident(ident: &str) -> Self {
        match ident {
            "bool" | "u8" | "i8" | "u16" | "i16" | "u32" | "i32" | "u64" | "i64" | "usize"
            | "isize" | "String" | "PathBuf" | "Vec" | "HashMap" | "BTreeMap" | "T" => {
                Self::Primitive(ident.to_string())
            }
            _ => Self::Link(ident.to_string()),
        }
    }
}

impl Type {
    fn toplevel_from_syn(t: &syn::Type) -> (bool, Type) {
        use syn::Type as T;
        let mut required = true;

        let type_name = match t {
            T::Path(syn::TypePath {
                path: syn::Path { segments, .. },
                ..
            }) => {
                let syn::PathSegment { ident, arguments } =
                    segments.last().expect("type path was empty");

                // Do a little dance to not print the other `Option` wrapper but emit `required=false`
                if ident == "Option" {
                    required = false;
                    match arguments {
                        syn::PathArguments::AngleBracketed(
                            syn::AngleBracketedGenericArguments { args, .. },
                        ) => {
                            let type_arg = args
                                .iter()
                                .filter_map(|arg| {
                                    if let syn::GenericArgument::Type(t) = arg {
                                        Some(t)
                                    } else {
                                        None
                                    }
                                })
                                .next()
                                .expect("no type param on `Option`");
                            Type::from_syn(&type_arg)
                        }
                        _ => unimplemented!(
                            "only type paths with regular `<T>`-style generics implemented so far"
                        ),
                    }
                } else {
                    Type::from_syn(t)
                }
            }
            _ => unimplemented!("only type paths implemented so far"),
        };

        (required, type_name)
    }

    fn from_syn(t: &syn::Type) -> Self {
        use syn::Type as T;

        match t {
            T::Path(syn::TypePath {
                path: syn::Path { segments, .. },
                ..
            }) => {
                let syn::PathSegment { ident, arguments } =
                    segments.last().expect("type path was empty");

                let args = match arguments {
                    syn::PathArguments::None => vec![],
                    syn::PathArguments::AngleBracketed(syn::AngleBracketedGenericArguments {
                        args,
                        ..
                    }) => args
                        .iter()
                        .filter_map(|arg| {
                            if let syn::GenericArgument::Type(t) = arg {
                                Some(t)
                            } else {
                                None
                            }
                        })
                        .map(Type::from_syn)
                        .collect::<Vec<_>>(),
                    _ => unimplemented!(
                        "only type paths with regular `<T>`-style generics implemented so far"
                    ),
                };

                let name = TypeName::from_ident(&ident.to_string());

                if args.is_empty() {
                    Type::Flat(name)
                } else {
                    Type::Nested {
                        container_name: name,
                        nested: args,
                    }
                }
            }
            _ => unimplemented!("only type paths implemented so far"),
        }
    }
}
<commit_msg>CollectDocs: Unescape double backslash<commit_after>use proc_macro::TokenStream;
use quote::quote;
use std::{fs::File, io::BufWriter, path::PathBuf};
use syn::{parse_macro_input, Data, DataStruct, DeriveInput};

use crate::to_adoc::ToAdoc;

pub fn derive(input: TokenStream) -> TokenStream {
    let input = parse_macro_input!(input as DeriveInput);

    let r#struct = Struct {
        name: input.ident.to_string(),
        docs: collect_docs_from_attrs(&input.attrs),
        fields: collect_fields(&input.data),
    };
    let adoc = adoc_output_path(&input.ident);
    let mut file =
        BufWriter::new(File::create(&adoc).expect(&format!("cannot write to {}", adoc.display())));
    r#struct.write_adoc(&mut file).expect(&format!(
        "cannot write {} as asciidoc to {}",
        r#struct.name,
        adoc.display()
    ));

    TokenStream::from(quote! {})
}

#[derive(Debug)]
pub(crate) struct Struct {
    pub(crate) name: String,
    pub(crate) docs: String,
    pub(crate) fields: Vec<Field>,
}

#[derive(Debug)]
pub(crate) struct Field {
    pub(crate) name: String,
    pub(crate) docs: String,
    pub(crate) required: bool,
    pub(crate) r#type: Type,
}

#[derive(Debug)]
pub(crate) enum Type {
    Flat(TypeName),
    Nested {
        container_name: TypeName,
        nested: Vec<Type>,
    },
}

#[derive(Debug)]
pub enum TypeName {
    Primitive(String),
    Link(String),
}

fn adoc_output_path(name: &syn::Ident) -> PathBuf {
    let target = std::env::var("COLLECT_DOCS_TARGET").unwrap_or("./docs/generated".into());
    std::fs::create_dir_all(&target).expect(&format!("could not create directory {}", target));
    PathBuf::from(&target)
        .join(name.to_string())
        .with_extension("adoc")
}

fn collect_fields(data: &Data) -> Vec<Field> {
    match data {
        Data::Struct(DataStruct {
            fields: syn::Fields::Unit,
            ..
        }) => vec![],
        Data::Struct(DataStruct {
            fields: syn::Fields::Unnamed(..),
            ..
        }) => vec![],
        Data::Struct(DataStruct {
            fields: syn::Fields::Named(fields),
            ..
        }) => fields
            .named
            .iter()
            .map(|field| {
                let (required, r#type) = Type::toplevel_from_syn(&field.ty);
                Field {
                    name: field
                        .ident
                        .as_ref()
                        .expect(&format!("struct field `{:?}` has no name", field))
                        .to_string(),
                    docs: collect_docs_from_attrs(&field.attrs),
                    required,
                    r#type,
                }
            })
            .collect(),
        _ => unimplemented!("Can only collect docs for structs for now"),
    }
}

fn collect_docs_from_attrs(attrs: &[syn::Attribute]) -> String {
    attrs
        .iter()
        .filter(|attr| attr.path.is_ident("doc"))
        .fold(String::new(), |mut res, attr| {
            use once_cell::sync::Lazy;
            use regex::Regex;
            use std::fmt::Write;

            let doc = TokenStream::from(attr.tokens.clone()).to_string();

            static RE: Lazy<Regex> =
                Lazy::new(|| regex::Regex::new(r#"^\s*=\s*"\s?(?P<content>.*?)"\s*$"#).unwrap());
            let doc = RE.replace_all(&doc, "$content");

            let doc = doc
                .replace("\\\"", "\"")
                .replace("\\'", "'")
                .replace(r"\\", r"\");
            writeln!(&mut res, "{}", doc).unwrap();
            res
        })
}

impl TypeName {
    fn from_ident(ident: &str) -> Self {
        match ident {
            "bool" | "u8" | "i8" | "u16" | "i16" | "u32" | "i32" | "u64" | "i64" | "usize"
            | "isize" | "String" | "PathBuf" | "Vec" | "HashMap" | "BTreeMap" | "T" => {
                Self::Primitive(ident.to_string())
            }
            _ => Self::Link(ident.to_string()),
        }
    }
}

impl Type {
    fn toplevel_from_syn(t: &syn::Type) -> (bool, Type) {
        use syn::Type as T;
        let mut required = true;

        let type_name = match t {
            T::Path(syn::TypePath {
                path: syn::Path { segments, .. },
                ..
            }) => {
                let syn::PathSegment { ident, arguments } =
                    segments.last().expect("type path was empty");

                // Do a little dance to not print the other `Option` wrapper but emit `required=false`
                if ident == "Option" {
                    required = false;
                    match arguments {
                        syn::PathArguments::AngleBracketed(
                            syn::AngleBracketedGenericArguments { args, .. },
                        ) => {
                            let type_arg = args
                                .iter()
                                .filter_map(|arg| {
                                    if let syn::GenericArgument::Type(t) = arg {
                                        Some(t)
                                    } else {
                                        None
                                    }
                                })
                                .next()
                                .expect("no type param on `Option`");
                            Type::from_syn(&type_arg)
                        }
                        _ => unimplemented!(
                            "only type paths with regular `<T>`-style generics implemented so far"
                        ),
                    }
                } else {
                    Type::from_syn(t)
                }
            }
            _ => unimplemented!("only type paths implemented so far"),
        };

        (required, type_name)
    }

    fn from_syn(t: &syn::Type) -> Self {
        use syn::Type as T;

        match t {
            T::Path(syn::TypePath {
                path: syn::Path { segments, .. },
                ..
            }) => {
                let syn::PathSegment { ident, arguments } =
                    segments.last().expect("type path was empty");

                let args = match arguments {
                    syn::PathArguments::None => vec![],
                    syn::PathArguments::AngleBracketed(syn::AngleBracketedGenericArguments {
                        args,
                        ..
                    }) => args
                        .iter()
                        .filter_map(|arg| {
                            if let syn::GenericArgument::Type(t) = arg {
                                Some(t)
                            } else {
                                None
                            }
                        })
                        .map(Type::from_syn)
                        .collect::<Vec<_>>(),
                    _ => unimplemented!(
                        "only type paths with regular `<T>`-style generics implemented so far"
                    ),
                };

                let name = TypeName::from_ident(&ident.to_string());

                if args.is_empty() {
                    Type::Flat(name)
                } else {
                    Type::Nested {
                        container_name: name,
                        nested: args,
                    }
                }
            }
            _ => unimplemented!("only type paths implemented so far"),
        }
    }
}
<|endoftext|>