<commit_before>//! KDE Window decoration manager
//!
//! This interface allows a compositor to announce support for KDE's legacy server-side decorations.
//!
//! A client can use this protocol to request being decorated by a supporting compositor.
//!
//! ```
//! extern crate wayland_server;
//! extern crate smithay;
//!
//! use smithay::delegate_kde_decoration;
//! use smithay::wayland::shell::kde::decoration::{KdeDecorationHandler, KdeDecorationState};
//!
//! # struct State { kde_decoration_state: KdeDecorationState };
//! # let mut display = wayland_server::Display::<State>::new().unwrap();
//!
//! // Create the new KdeDecorationState.
//! let state = KdeDecorationState::new::<State, _>(&display.handle(), None);
//!
//! // Insert KdeDecorationState into your compositor state.
//! // …
//!
//! // Implement KDE server decoration handlers.
//! impl KdeDecorationHandler for State {
//!     fn kde_decoration_state(&self) -> &KdeDecorationState {
//!         &self.kde_decoration_state
//!     }
//! }
//!
//! delegate_kde_decoration!(State);
//! ```

use slog::Logger;
use wayland_protocols_misc::server_decoration::server::org_kde_kwin_server_decoration::{
    Mode, OrgKdeKwinServerDecoration,
};
use wayland_protocols_misc::server_decoration::server::org_kde_kwin_server_decoration_manager::{
    Mode as DefaultMode, OrgKdeKwinServerDecorationManager,
};
use wayland_server::backend::GlobalId;
use wayland_server::protocol::wl_surface::WlSurface;
use wayland_server::{Dispatch, DisplayHandle, GlobalDispatch, WEnum};

/// KDE server decoration handler.
pub trait KdeDecorationHandler {
    /// Return the KDE server decoration state.
    fn kde_decoration_state(&self) -> &KdeDecorationState;

    /// Handle new decoration object creation.
    ///
    /// Called whenever a new decoration object is created, usually this happens when a new window
    /// is opened.
    fn new_decoration(&mut self, _surface: &WlSurface, _decoration: &OrgKdeKwinServerDecoration) {}

    /// Handle surface decoration mode requests.
    ///
    /// Called when a surface requests a specific decoration mode or acknowledged the compositor's
    /// decoration request.
    ///
    /// **It is up to the compositor to prevent feedback loops**, a client is free to ignore modes
    /// suggested by [`OrgKdeKwinServerDecoration::mode`] and instead request their preferred mode
    /// instead.
    fn request_mode(
        &mut self,
        _surface: &WlSurface,
        decoration: &OrgKdeKwinServerDecoration,
        mode: WEnum<Mode>,
    ) {
        if let WEnum::Value(mode) = mode {
            decoration.mode(mode);
        }
    }

    /// Handle decoration object removal for a surface.
    fn release(&mut self, _decoration: &OrgKdeKwinServerDecoration, _surface: &WlSurface) {}
}

/// KDE server decoration state.
#[derive(Debug)]
pub struct KdeDecorationState {
    pub(crate) default_mode: DefaultMode,
    pub(crate) logger: Logger,

    kde_decoration_manager: GlobalId,
}

impl KdeDecorationState {
    /// Create a new KDE server decoration global.
    pub fn new<D, L>(display: &DisplayHandle, default_mode: DefaultMode, logger: L) -> Self
    where
        D: GlobalDispatch<OrgKdeKwinServerDecorationManager, ()>
            + Dispatch<OrgKdeKwinServerDecorationManager, ()>
            + Dispatch<OrgKdeKwinServerDecoration, WlSurface>
            + KdeDecorationHandler
            + 'static,
        L: Into<Option<Logger>>,
    {
        let kde_decoration_manager = display.create_global::<D, OrgKdeKwinServerDecorationManager, _>(1, ());
        let logger =
            crate::slog_or_fallback(logger).new(slog::o!("smithay_module" => "kde_decoration_handler"));

        Self {
            kde_decoration_manager,
            default_mode,
            logger,
        }
    }

    /// Returns the id of the [`OrgKdeKwinServerDecorationManager`] global.
    pub fn global(&self) -> GlobalId {
        self.kde_decoration_manager.clone()
    }
}

#[allow(missing_docs)] // TODO
#[macro_export]
macro_rules! delegate_kde_decoration {
    ($(@<$( $lt:tt $( : $clt:tt $(+ $dlt:tt )* )? ),+>)? $ty: ty) => {
        $crate::reexports::wayland_server::delegate_global_dispatch!($(@< $( $lt $( : $clt $(+ $dlt )* )? ),+ >)? $ty: [
            $crate::reexports::wayland_protocols_misc::server_decoration::server::org_kde_kwin_server_decoration_manager::OrgKdeKwinServerDecorationManager: ()
        ] => $crate::wayland::shell::kde::decoration::KdeDecorationState);

        $crate::reexports::wayland_server::delegate_dispatch!($(@< $( $lt $( : $clt $(+ $dlt )* )? ),+ >)? $ty: [
            $crate::reexports::wayland_protocols_misc::server_decoration::server::org_kde_kwin_server_decoration_manager::OrgKdeKwinServerDecorationManager: ()
        ] => $crate::wayland::shell::kde::decoration::KdeDecorationState);

        $crate::reexports::wayland_server::delegate_dispatch!($(@< $( $lt $( : $clt $(+ $dlt )* )? ),+ >)? $ty: [
            $crate::reexports::wayland_protocols_misc::server_decoration::server::org_kde_kwin_server_decoration::OrgKdeKwinServerDecoration: $crate::reexports::wayland_server::protocol::wl_surface::WlSurface
        ] => $crate::wayland::shell::kde::decoration::KdeDecorationState);
    };
}
<commit_msg>Fix tests<commit_after>//! KDE Window decoration manager
//!
//! This interface allows a compositor to announce support for KDE's legacy server-side decorations.
//!
//! A client can use this protocol to request being decorated by a supporting compositor.
//!
//! ```
//! extern crate wayland_server;
//! extern crate smithay;
//!
//! use smithay::delegate_kde_decoration;
//! use smithay::wayland::shell::kde::decoration::{KdeDecorationHandler, KdeDecorationState};
//! use wayland_protocols_misc::server_decoration::server::org_kde_kwin_server_decoration_manager::Mode;
//!
//! # struct State { kde_decoration_state: KdeDecorationState };
//! # let mut display = wayland_server::Display::<State>::new().unwrap();
//!
//! // Create the new KdeDecorationState.
//! let state = KdeDecorationState::new::<State, _>(&display.handle(), Mode::Server, None);
//!
//! // Insert KdeDecorationState into your compositor state.
//! // …
//!
//! // Implement KDE server decoration handlers.
//! impl KdeDecorationHandler for State {
//!     fn kde_decoration_state(&self) -> &KdeDecorationState {
//!         &self.kde_decoration_state
//!     }
//! }
//!
//! delegate_kde_decoration!(State);
//! ```

use slog::Logger;
use wayland_protocols_misc::server_decoration::server::org_kde_kwin_server_decoration::{
    Mode, OrgKdeKwinServerDecoration,
};
use wayland_protocols_misc::server_decoration::server::org_kde_kwin_server_decoration_manager::{
    Mode as DefaultMode, OrgKdeKwinServerDecorationManager,
};
use wayland_server::backend::GlobalId;
use wayland_server::protocol::wl_surface::WlSurface;
use wayland_server::{Dispatch, DisplayHandle, GlobalDispatch, WEnum};

/// KDE server decoration handler.
pub trait KdeDecorationHandler {
    /// Return the KDE server decoration state.
    fn kde_decoration_state(&self) -> &KdeDecorationState;

    /// Handle new decoration object creation.
    ///
    /// Called whenever a new decoration object is created, usually this happens when a new window
    /// is opened.
    fn new_decoration(&mut self, _surface: &WlSurface, _decoration: &OrgKdeKwinServerDecoration) {}

    /// Handle surface decoration mode requests.
    ///
    /// Called when a surface requests a specific decoration mode or acknowledged the compositor's
    /// decoration request.
    ///
    /// **It is up to the compositor to prevent feedback loops**, a client is free to ignore modes
    /// suggested by [`OrgKdeKwinServerDecoration::mode`] and instead request their preferred mode
    /// instead.
    fn request_mode(
        &mut self,
        _surface: &WlSurface,
        decoration: &OrgKdeKwinServerDecoration,
        mode: WEnum<Mode>,
    ) {
        if let WEnum::Value(mode) = mode {
            decoration.mode(mode);
        }
    }

    /// Handle decoration object removal for a surface.
    fn release(&mut self, _decoration: &OrgKdeKwinServerDecoration, _surface: &WlSurface) {}
}

/// KDE server decoration state.
#[derive(Debug)]
pub struct KdeDecorationState {
    pub(crate) default_mode: DefaultMode,
    pub(crate) logger: Logger,

    kde_decoration_manager: GlobalId,
}

impl KdeDecorationState {
    /// Create a new KDE server decoration global.
    pub fn new<D, L>(display: &DisplayHandle, default_mode: DefaultMode, logger: L) -> Self
    where
        D: GlobalDispatch<OrgKdeKwinServerDecorationManager, ()>
            + Dispatch<OrgKdeKwinServerDecorationManager, ()>
            + Dispatch<OrgKdeKwinServerDecoration, WlSurface>
            + KdeDecorationHandler
            + 'static,
        L: Into<Option<Logger>>,
    {
        let kde_decoration_manager = display.create_global::<D, OrgKdeKwinServerDecorationManager, _>(1, ());
        let logger =
            crate::slog_or_fallback(logger).new(slog::o!("smithay_module" => "kde_decoration_handler"));

        Self {
            kde_decoration_manager,
            default_mode,
            logger,
        }
    }

    /// Returns the id of the [`OrgKdeKwinServerDecorationManager`] global.
    pub fn global(&self) -> GlobalId {
        self.kde_decoration_manager.clone()
    }
}

#[allow(missing_docs)] // TODO
#[macro_export]
macro_rules! delegate_kde_decoration {
    ($(@<$( $lt:tt $( : $clt:tt $(+ $dlt:tt )* )? ),+>)? $ty: ty) => {
        $crate::reexports::wayland_server::delegate_global_dispatch!($(@< $( $lt $( : $clt $(+ $dlt )* )? ),+ >)? $ty: [
            $crate::reexports::wayland_protocols_misc::server_decoration::server::org_kde_kwin_server_decoration_manager::OrgKdeKwinServerDecorationManager: ()
        ] => $crate::wayland::shell::kde::decoration::KdeDecorationState);

        $crate::reexports::wayland_server::delegate_dispatch!($(@< $( $lt $( : $clt $(+ $dlt )* )? ),+ >)? $ty: [
            $crate::reexports::wayland_protocols_misc::server_decoration::server::org_kde_kwin_server_decoration_manager::OrgKdeKwinServerDecorationManager: ()
        ] => $crate::wayland::shell::kde::decoration::KdeDecorationState);

        $crate::reexports::wayland_server::delegate_dispatch!($(@< $( $lt $( : $clt $(+ $dlt )* )? ),+ >)? $ty: [
            $crate::reexports::wayland_protocols_misc::server_decoration::server::org_kde_kwin_server_decoration::OrgKdeKwinServerDecoration: $crate::reexports::wayland_server::protocol::wl_surface::WlSurface
        ] => $crate::wayland::shell::kde::decoration::KdeDecorationState);
    };
}
<|endoftext|>


<commit_before>use std::thread;
use std::ops::Range;

#[derive(Debug)]
struct Regs {
    r0: u16,
    r1: u16,
    r7: u16,
}

fn algorithm(regs: &mut Regs) {
    if regs.r0 == 0 {
        regs.r0 = regs.r1 + 1;
        return;
    } else if regs.r1 == 0 {
        regs.r0 = regs.r0 - 1;
        regs.r1 = regs.r7;

        algorithm(regs);
        return;
    } else {
        let tmp0 = regs.r0;
        regs.r1 = regs.r1 - 1;

        algorithm(regs);

        regs.r1 = regs.r0;
        regs.r0 = tmp0;
        regs.r0 = regs.r0 - 1;

        algorithm(regs);

        return;
    }
}

fn thread_body(range: Range<u16>) -> Vec<(u16, Regs)> {
    range.map(|r7| {
        let mut regs = Regs {
            r0: 4,
            r1: 1,
            r7: r7,
        };

        algorithm(&mut regs);

        (r7, regs)
    }).collect()
}

fn main() {
    let thread1 = thread::Builder::new()
        .name("bf-1".to_owned())
        .spawn(move || {
            thread_body(1..4682)
        }).unwrap();

    let thread2 = thread::Builder::new()
        .name("bf-2".to_owned())
        .spawn(move || {
            thread_body(4682..9363)
        }).unwrap();

    let thread3 = thread::Builder::new()
        .name("bf-3".to_owned())
        .spawn(move || {
            thread_body(9363..14044)
        }).unwrap();

    let thread4 = thread::Builder::new()
        .name("bf-4".to_owned())
        .spawn(move || {
            thread_body(14044..18725)
        }).unwrap();

    let thread5 = thread::Builder::new()
        .name("bf-5".to_owned())
        .spawn(move || {
            thread_body(18725..23406)
        }).unwrap();

    let thread6 = thread::Builder::new()
        .name("bf-6".to_owned())
        .spawn(move || {
            thread_body(23406..28087)
        }).unwrap();

    let thread7 = thread::Builder::new()
        .name("bf-7".to_owned())
        .spawn(move || {
            thread_body(28087..32767)
        }).unwrap();

    let vec1 = thread1.join().unwrap();
    let vec2 = thread2.join().unwrap();
    let vec3 = thread3.join().unwrap();
    let vec4 = thread4.join().unwrap();
    let vec5 = thread5.join().unwrap();
    let vec6 = thread6.join().unwrap();
    let vec7 = thread7.join().unwrap();

    for (r7, regs) in vec1 {
        println!("{: >5}: r0 = {: >5}", r7, regs.r0);
    }
    for (r7, regs) in vec2 {
        println!("{: >5}: r0 = {: >5}", r7, regs.r0);
    }
    for (r7, regs) in vec3 {
        println!("{: >5}: r0 = {: >5}", r7, regs.r0);
    }
    for (r7, regs) in vec4 {
        println!("{: >5}: r0 = {: >5}", r7, regs.r0);
    }
    for (r7, regs) in vec5 {
        println!("{: >5}: r0 = {: >5}", r7, regs.r0);
    }
    for (r7, regs) in vec6 {
        println!("{: >5}: r0 = {: >5}", r7, regs.r0);
    }
    for (r7, regs) in vec7 {
        println!("{: >5}: r0 = {: >5}", r7, regs.r0);
    }

}
<commit_msg>Added 8th register brute forcer<commit_after>use std::u16;
use std::ops::Add;
use std::collections::HashMap;
use std::convert::{Into, From};
use std::fmt;

#[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Clone, Copy, Hash)]
struct U15(u16);

const N: u16 = 1 << 15;
const N_SUB_1: U15 = U15(N - 1);
const ZERO_15: U15 = U15(0);
const ONE_15: U15 = U15(1);

impl fmt::Display for U15 {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "{}", self.0)
    }
}

impl From<u16> for U15 {
    fn from(x: u16) -> U15 {
        U15(x % N)
    }
}

impl Add for U15 {
    type Output = U15;

    fn add(self, other: U15) -> U15 {
        U15(self.0.wrapping_add(other.0) % N)
    }
}

impl<'a, 'b> Add<&'b U15> for &'a U15 {
    type Output = U15;

    fn add(self, other: &'b U15) -> U15 {
        U15(self.0.wrapping_add(other.0) % N)
    }
}

impl<'a> Add<&'a U15> for U15 {
    type Output = U15;

    fn add(self, other: &'a U15) -> U15 {
        U15(self.0.wrapping_add(other.0) % N)
    }
}

impl<'a> Add<U15> for &'a U15 {
    type Output = U15;

    fn add(self, other: U15) -> U15 {
        U15(self.0.wrapping_add(other.0) % N)
    }
}

struct AckermannCache {
    r7: U15,
    cache: HashMap<(U15, U15), U15>,
}

impl AckermannCache {
    fn new<T: Into<U15>>(r7: T) -> AckermannCache {
        AckermannCache {
            r7: r7.into(),
            cache: HashMap::new(),
        }
    }

    fn get<T: Into<U15>>(&mut self, m_: T, n_: T) -> U15 {
        let m = m_.into();
        let n = n_.into();

        if !self.cache.contains_key(&(m, n)) {
            let val = if m == ZERO_15 {
                n + ONE_15
            } else if n == ZERO_15 {
                let r7 = self.r7;
                self.get(m + N_SUB_1, r7)
            } else {
                let new_n = self.get(m, n + N_SUB_1);
                self.get(m + N_SUB_1, new_n)
            };
            self.cache.insert((m, n), val);
        }

        self.cache[&(m, n)]
    }
}

fn main() {
    for i in 1..N {
        let r7 = U15(i);
        let mut ac = AckermannCache::new(r7);
        let r0 = ac.get(4, 1);

        if r0 == 6.into() {
            println!("r7 = {: >5}, r0 = {: >5}", r7, r0);
        }
    }

}
<|endoftext|>


<commit_before>// Copyright:: Copyright (c) 2015-2016 The Habitat Maintainers
//
// The terms of the Evaluation Agreement (Habitat) between Chef Software Inc.
// and the party accessing this file ("Licensee") apply to Licensee's use of
// the Software until such time that the Software is made available under an
// open source license such as the Apache 2.0 License.

use std::path::PathBuf;

pub const ROOT_PATH: &'static str = "/opt/bldr";
pub const PACKAGE_HOME: &'static str = "/opt/bldr/pkgs";
pub const SERVICE_HOME: &'static str = "/opt/bldr/svc";
pub const SOURCE_CACHE: &'static str = "/opt/bldr/cache/src";
pub const PACKAGE_CACHE: &'static str = "/opt/bldr/cache/pkgs";
pub const GPG_CACHE: &'static str = "/opt/bldr/cache/gpg";
pub const KEY_CACHE: &'static str = "/opt/bldr/cache/keys";

pub fn service_path(service_name: &str) -> PathBuf {
    PathBuf::from(SERVICE_HOME).join(service_name)
}
<commit_msg>Use `HAB_CACHE_SRC_PATH` for default src download, extract, & compile.<commit_after>// Copyright:: Copyright (c) 2015-2016 The Habitat Maintainers
//
// The terms of the Evaluation Agreement (Habitat) between Chef Software Inc.
// and the party accessing this file ("Licensee") apply to Licensee's use of
// the Software until such time that the Software is made available under an
// open source license such as the Apache 2.0 License.

use std::path::PathBuf;

pub const ROOT_PATH: &'static str = "/opt/bldr";
pub const PACKAGE_HOME: &'static str = "/opt/bldr/pkgs";
pub const SERVICE_HOME: &'static str = "/opt/bldr/svc";
pub const PACKAGE_CACHE: &'static str = "/opt/bldr/cache/pkgs";
/// The default path where source artifacts are downloaded, extracted, & compiled
pub const CACHE_SRC_PATH: &'static str = "/opt/bldr/cache/src";
pub const GPG_CACHE: &'static str = "/opt/bldr/cache/gpg";
pub const KEY_CACHE: &'static str = "/opt/bldr/cache/keys";

pub fn service_path(service_name: &str) -> PathBuf {
    PathBuf::from(SERVICE_HOME).join(service_name)
}
<|endoftext|>


<commit_before>use analysis::ref_mode::RefMode;
use analysis::rust_type::*;
use config;
use env::Env;
use library::{self, Nullable};

#[derive(Clone, Debug, Default)]
pub struct Info {
    pub parameter: Option<library::Parameter>,
    pub base_tid: Option<library::TypeId>,  //Some only if need downcast
    pub commented: bool,
}

pub fn analyze(env: &Env, func: &library::Function, type_tid: library::TypeId,
               configured_functions: &[&config::functions::Function],
               used_types: &mut Vec<String>) -> Info {

    let mut parameter = if func.ret.typ == Default::default() { None } else {
        if let Ok(s) = used_rust_type(env, func.ret.typ) {
            used_types.push(s);
        }
        // Since GIRs are bad at specifying return value nullability, assume
        // any returned pointer is nullable unless overridden by the config.
        let mut nullable = func.ret.nullable;
        if !*nullable && can_be_nullable_return(env, func.ret.typ) {
            *nullable = true;
        }
        let nullable_override = configured_functions.iter()
            .filter_map(|f| f.ret.nullable)
            .next();
        if let Some(val) = nullable_override {
            nullable = val;
        }
        Some(library::Parameter {
                nullable: nullable,
                .. func.ret.clone()
            })
    };

    let commented = if func.ret.typ == Default::default() { false } else {
        parameter_rust_type(env, func.ret.typ, func.ret.direction, Nullable(false), RefMode::None).is_err()
    };

    let mut base_tid = None;

    if func.kind == library::FunctionKind::Constructor {
        if let Some(par) = parameter {
            if par.typ != type_tid {
                base_tid = Some(par.typ);
            }
            parameter = Some(library::Parameter {
                typ: type_tid,
                nullable: Nullable(false),
                ..par
            });
        }
    }

    Info {
        parameter: parameter,
        base_tid: base_tid,
        commented: commented,
    }
}

fn can_be_nullable_return(env: &Env, type_id: library::TypeId) -> bool
{
    use library::Type::*;
    use library::Fundamental::*;
    match *env.library.type_(type_id) {
        Fundamental(fund) => match fund {
            Pointer => true,
            Utf8 => true,
            Filename => true,
            _ => false,
        },
        Alias(ref alias) => can_be_nullable_return(env, alias.typ),
        Enumeration(_) => false,
        Bitfield(_) => false,
        Record(_) => false,
        Union(_) => false,
        Function(_) => true,
        Interface(_) => true,
        Class(_) => true,
        _ => true
    }
}
<commit_msg>Record return values are nullable<commit_after>use analysis::ref_mode::RefMode;
use analysis::rust_type::*;
use config;
use env::Env;
use library::{self, Nullable};

#[derive(Clone, Debug, Default)]
pub struct Info {
    pub parameter: Option<library::Parameter>,
    pub base_tid: Option<library::TypeId>,  //Some only if need downcast
    pub commented: bool,
}

pub fn analyze(env: &Env, func: &library::Function, type_tid: library::TypeId,
               configured_functions: &[&config::functions::Function],
               used_types: &mut Vec<String>) -> Info {

    let mut parameter = if func.ret.typ == Default::default() { None } else {
        if let Ok(s) = used_rust_type(env, func.ret.typ) {
            used_types.push(s);
        }
        // Since GIRs are bad at specifying return value nullability, assume
        // any returned pointer is nullable unless overridden by the config.
        let mut nullable = func.ret.nullable;
        if !*nullable && can_be_nullable_return(env, func.ret.typ) {
            *nullable = true;
        }
        let nullable_override = configured_functions.iter()
            .filter_map(|f| f.ret.nullable)
            .next();
        if let Some(val) = nullable_override {
            nullable = val;
        }
        Some(library::Parameter {
                nullable: nullable,
                .. func.ret.clone()
            })
    };

    let commented = if func.ret.typ == Default::default() { false } else {
        parameter_rust_type(env, func.ret.typ, func.ret.direction, Nullable(false), RefMode::None).is_err()
    };

    let mut base_tid = None;

    if func.kind == library::FunctionKind::Constructor {
        if let Some(par) = parameter {
            if par.typ != type_tid {
                base_tid = Some(par.typ);
            }
            parameter = Some(library::Parameter {
                typ: type_tid,
                nullable: Nullable(false),
                ..par
            });
        }
    }

    Info {
        parameter: parameter,
        base_tid: base_tid,
        commented: commented,
    }
}

fn can_be_nullable_return(env: &Env, type_id: library::TypeId) -> bool
{
    use library::Type::*;
    use library::Fundamental::*;
    match *env.library.type_(type_id) {
        Fundamental(fund) => match fund {
            Pointer => true,
            Utf8 => true,
            Filename => true,
            _ => false,
        },
        Alias(ref alias) => can_be_nullable_return(env, alias.typ),
        Enumeration(_) => false,
        Bitfield(_) => false,
        Record(_) => true,
        Union(_) => false,
        Function(_) => true,
        Interface(_) => true,
        Class(_) => true,
        _ => true
    }
}
<|endoftext|>


<commit_before>use std::path::Path;

use core::registry::PackageRegistry;
use core::{Package, PackageId, Resolve};
use ops;
use util::{CargoResult, Config, human, ChainError};

/// Executes `cargo fetch`.
pub fn fetch(manifest_path: &Path, config: &Config) -> CargoResult<()> {
    let package = try!(Package::for_path(manifest_path, config));
    let mut registry = PackageRegistry::new(config);
    let resolve = try!(ops::resolve_pkg(&mut registry, &package));
    let _ = get_resolved_packages(&resolve, &mut registry);
    Ok(())
}

pub fn get_resolved_packages(resolve: &Resolve, registry: &mut PackageRegistry)
                             -> CargoResult<Vec<Package>> {
    let ids: Vec<PackageId> = resolve.iter().cloned().collect();
    registry.get(&ids).chain_error(|| {
        human("unable to get packages from source")
    })
}
<commit_msg>Add a try! that I forgot<commit_after>use std::path::Path;

use core::registry::PackageRegistry;
use core::{Package, PackageId, Resolve};
use ops;
use util::{CargoResult, Config, human, ChainError};

/// Executes `cargo fetch`.
pub fn fetch(manifest_path: &Path, config: &Config) -> CargoResult<()> {
    let package = try!(Package::for_path(manifest_path, config));
    let mut registry = PackageRegistry::new(config);
    let resolve = try!(ops::resolve_pkg(&mut registry, &package));
    let _ = try!(get_resolved_packages(&resolve, &mut registry));
    Ok(())
}

pub fn get_resolved_packages(resolve: &Resolve, registry: &mut PackageRegistry)
                             -> CargoResult<Vec<Package>> {
    let ids: Vec<PackageId> = resolve.iter().cloned().collect();
    registry.get(&ids).chain_error(|| {
        human("unable to get packages from source")
    })
}
<|endoftext|>


<commit_before>//! Functions used for adding labels to the sounding plot
use app::AppContext;
use config;

use coords::ScreenCoords;

use cairo::{Context, Matrix, FontExtents, FontFace, FontSlant, FontWeight};

//
// TODO: Labeling is clunky. Rewrite this module to make a list of labels and rectangles. If a
// rectangle overlaps another label, it does not get added to the list. Make high priority labels
// first. Fill the rectangles with the background color and then draw the labels.
//

// Set up the font matrix, and set the font, etc.
pub fn prepare_to_label(cr: &Context, ac: &AppContext) {

    // Configure the font.
    let font_face = FontFace::toy_create(config::FONT_NAME, FontSlant::Normal, FontWeight::Bold);
    cr.set_font_face(font_face);

    set_font_size(config::LARGE_FONT_SIZE, cr, ac);
}

// Set the font size by reseting the font matrix
fn set_font_size(size_in_pnts: f64, cr: &Context, ac: &AppContext) {
    let dpi = match ac.get_dpi() {
        None => 72.0,
        Some(value) => value,
    };

    let font_size = size_in_pnts / 72.0 * dpi;
    let (font_size, _) = ac.convert_device_to_screen((font_size, 0.0));

    // Flip the y-coordinate so it displays the font right side up
    cr.set_font_matrix(Matrix {
        xx: 1.0 * font_size,
        yx: 0.0,
        xy: 0.0,
        yy: -1.0 * font_size, // Reflect it to be right side up!
        x0: 0.0,
        y0: 0.0,
    });
}

// Label the pressure, temperatures, etc lines.
pub fn draw_background_labels(cr: &Context, ac: &AppContext) {

    let (screen_x_min, screen_x_max, screen_max_p, screen_y_max) = calculate_label_boundaries(ac);

    // Used for checking overlap later with T
    let max_p_label_right_edge: f64 =
        label_isobars(cr, ac, screen_x_min, screen_x_max, screen_y_max);

    label_isotherms(
        cr,
        ac,
        screen_x_max,
        screen_y_max,
        screen_max_p,
        max_p_label_right_edge,
    );
}

fn calculate_label_boundaries(ac: &AppContext) -> (f64, f64, f64, f64) {

    // Get min/max screen coordinate values
    let (lower_left_screen, upper_right_screen) = ac.bounding_box_in_screen_coords();
    let (mut screen_x_min, _screen_y_min) = lower_left_screen;
    let (screen_x_max, screen_y_max) = upper_right_screen;

    // Get coordinates to keep labels from flowing off the chart.
    let (xmin, _ymin) = ac.convert_xy_to_screen((0.0, 0.0));
    let (_, mut screen_max_p) = ac.convert_screen_to_tp((0.0, 0.0));
    if screen_max_p > config::MAXP {
        screen_max_p = config::MAXP;
    }
    if xmin > screen_x_min {
        screen_x_min = xmin;
    }

    (screen_x_min, screen_x_max, screen_max_p, screen_y_max)
}

fn label_isobars(
    cr: &Context,
    ac: &AppContext,
    screen_x_min: f64,
    screen_x_max: f64,
    screen_y_max: f64,
) -> f64 {

    // Setup label colors
    let rgba = config::ISOBAR_RGBA;
    cr.set_source_rgba(rgba.0, rgba.1, rgba.2, 1.0);

    // For checking label overlap.
    let mut max_p_label_right_edge: f64 = 0.0; // Used for checking overlap later with T
    let mut last_label_y = ::std::f64::MIN; // Used for checking overlap between pressure labels

    for &p in config::ISOBARS.into_iter() {
        // Make the label text
        let label = format!("{}", p);

        // Calculate position of lower left edge for label
        let (_, mut screen_y) = ac.convert_tp_to_screen((0.0, p));
        screen_y += 0.005 * screen_y_max; // Lift off the pressure line slightly

        // Check for vertical overlap.
        let label_extents = cr.text_extents(&label);
        let (label_width, label_height) = (label_extents.width, label_extents.height);
        if screen_y < label_height + last_label_y {
            continue;
        }
        last_label_y = screen_y;

        // Update right edge for checking with T later.
        if label_width > max_p_label_right_edge {
            max_p_label_right_edge = label_width;
        }

        // Draw the label
        cr.move_to(screen_x_min + 0.01 * screen_x_max, screen_y);
        cr.show_text(&label);
    }
    // This is width, add position of left edge to get right edge
    max_p_label_right_edge += screen_x_min + 0.01 * screen_x_max;

    // Use this to make sure temperatures don't overlap
    max_p_label_right_edge
}

fn label_isotherms(
    cr: &Context,
    ac: &AppContext,
    screen_x_max: f64,
    screen_y_max: f64,
    screen_max_p: f64,
    max_p_label_right_edge: f64,
) {
    // Label isotherms
    let rgba = config::ISOTHERM_RGBA;
    let (mut last_label_x_max, mut last_label_x_min) = (0.0, 0.0);
    cr.set_source_rgba(rgba.0, rgba.1, rgba.2, 1.0);
    for &t in config::ISOTHERMS.into_iter() {
        // Make the label text
        let label = format!("{}", t);

        // Calculate position for lower left edge of label
        let (mut screen_x, mut screen_y) = ac.convert_tp_to_screen((t, screen_max_p));
        screen_y += 0.008 * screen_y_max;
        screen_x += 0.008 * screen_y_max;

        // Check for overlap with pressure labels
        if screen_x < max_p_label_right_edge {
            continue;
        }

        // Check for overlap with other T labels
        let extents_width = cr.text_extents(&label).width;
        let (x_min, x_max) = (screen_x, screen_x + extents_width);
        if (x_min > last_label_x_min && x_min < last_label_x_max) ||
            (x_max > last_label_x_min && x_max < last_label_x_max)
        {
            continue;
        }

        last_label_x_min = x_min - 0.008 * screen_x_max;
        last_label_x_max = x_max + 0.008 * screen_x_max;

        // Draw the label
        cr.move_to(screen_x, screen_y);
        cr.show_text(&label);
    }
}

// Add a description box
pub fn draw_legend(cr: &Context, ac: &AppContext) {
    if !ac.plottable() {
        return;
    }

    let mut upper_left = ac.convert_device_to_screen((5.0, 5.0));
    // Make sure we stay on the x-y coords domain
    let (xmin, ymax) = ac.convert_xy_to_screen((0.0, 1.0));
    if ymax - upper_left.0 < upper_left.1 {
        upper_left.1 = ymax - upper_left.0;
    }

    if xmin + upper_left.0 > upper_left.0 {
        upper_left.0 = xmin + upper_left.0;
    }

    let font_extents = cr.font_extents();

    let (source_name, valid_time, location) = build_label_strings(ac);

    let (box_width, box_height) =
        calculate_legend_box_size(cr, &font_extents, &source_name, &valid_time, &location);

    draw_legend_rectangle(cr, &upper_left, box_width, box_height);

    draw_legend_text(
        cr,
        &upper_left,
        &font_extents,
        &source_name,
        &valid_time,
        &location,
    );

}

fn build_label_strings(ac: &AppContext) -> (Option<String>, Option<String>, Option<String>) {

    let source_name: Option<String> = ac.get_source_name();
    let mut valid_time: Option<String> = None;
    let mut location: Option<String> = None;
    if let Some(snd) = ac.get_sounding_for_display() {
        // Build the valid time part
        if let Some(vt) = snd.valid_time {
            use chrono::{Datelike, Timelike};
            valid_time = Some(format!(
                "Valid: {:02}/{:02}/{:04} {:02}Z",
                vt.month(),
                vt.day(),
                vt.year(),
                vt.hour()
            ));
        }

        // Build location part.
        if snd.lat.as_option().is_some() || snd.lon.as_option().is_some() ||
            snd.elevation.as_option().is_some()
        {
            location = Some("".to_owned());
            if let Some(ref mut loc) = location {
                if let Some(lat) = snd.lat.as_option() {
                    loc.push_str(&format!("{:.2}", lat));
                }
                if let Some(lon) = snd.lon.as_option() {
                    loc.push_str(&format!(", {:.2}", lon));
                }
                if let Some(el) = snd.elevation.as_option() {
                    loc.push_str(&format!(", {:.0}m ({:.0}ft)", el, el * 3.28084));
                }
            }
        }
    }

    (source_name, valid_time, location)
}

fn calculate_legend_box_size(
    cr: &Context,
    font_extents: &FontExtents,
    source_name: &Option<String>,
    valid_time: &Option<String>,
    location: &Option<String>,
) -> (f64, f64) {

    let mut box_width: f64 = 0.0;
    let mut box_height: f64 = 0.0;

    if let &Some(ref src) = source_name {
        let extents = cr.text_extents(src);
        if extents.width > box_width {
            box_width = extents.width;
        }
        box_height += extents.height;
    }

    if let &Some(ref vt) = valid_time {
        let extents = cr.text_extents(vt);
        if extents.width > box_width {
            box_width = extents.width;
        }
        box_height += extents.height;
        // Add line spacing if previous line was there.
        if source_name.is_some() {
            box_height += font_extents.height - extents.height;
        }
    }

    if let &Some(ref loc) = location {
        let extents = cr.text_extents(loc);
        if extents.width > box_width {
            box_width = extents.width;
        }
        box_height += extents.height;
        // Add line spacing if previous line was there.
        if valid_time.is_some() {
            box_height += font_extents.height - extents.height;
        }
    }

    // Add room for the last line's descent
    box_height += font_extents.descent;

    // Add padding last
    box_height += 2.0 * config::DEFAULT_PADDING;
    box_width += 2.0 * config::DEFAULT_PADDING;

    (box_width, box_height)
}

fn draw_legend_rectangle(cr: &Context, upper_left: &ScreenCoords, width: f64, height: f64) {
    cr.rectangle(upper_left.0, upper_left.1 - height, width, height);

    let rgb = config::ISOBAR_RGBA;
    cr.set_source_rgba(rgb.0, rgb.1, rgb.2, rgb.3);
    cr.set_line_width(cr.device_to_user_distance(3.0, 0.0).0);
    cr.stroke_preserve();
    let rgb = config::BACKGROUND_RGB;
    cr.set_source_rgb(rgb.0, rgb.1, rgb.2);
    cr.fill();
}

fn draw_legend_text(
    cr: &Context,
    upper_left: &ScreenCoords,
    font_extents: &FontExtents,
    source_name: &Option<String>,
    valid_time: &Option<String>,
    location: &Option<String>,
) {
    let rgb = config::ISOBAR_RGBA;
    cr.set_source_rgba(rgb.0, rgb.1, rgb.2, rgb.3);

    // Remember how many lines we have drawn so far for setting position of the next line.
    let mut num_lines_drawn = 0;

    // Get into the initial position
    cr.move_to(
        upper_left.0 + config::DEFAULT_PADDING,
        upper_left.1 - config::DEFAULT_PADDING - font_extents.ascent,
    );

    if let &Some(ref src) = source_name {
        cr.show_text(src);
        num_lines_drawn += 1;
        cr.move_to(
            upper_left.0 + config::DEFAULT_PADDING,
            upper_left.1 - config::DEFAULT_PADDING - font_extents.ascent -
                num_lines_drawn as f64 * font_extents.height,
        );
    }
    if let &Some(ref vt) = valid_time {
        cr.show_text(vt);
        num_lines_drawn += 1;
        cr.move_to(
            upper_left.0 + config::DEFAULT_PADDING,
            upper_left.1 - config::DEFAULT_PADDING - font_extents.ascent -
                num_lines_drawn as f64 * font_extents.height,
        );
    }
    if let &Some(ref loc) = location {
        cr.show_text(loc);
        num_lines_drawn += 1;
        cr.move_to(
            upper_left.0 + config::DEFAULT_PADDING,
            upper_left.1 - config::DEFAULT_PADDING - font_extents.ascent -
                num_lines_drawn as f64 * font_extents.height,
        );
    }
}
<commit_msg>Better labeling, more organized.<commit_after>//! Functions used for adding labels to the sounding plot
use app::AppContext;
use config;

use coords::ScreenCoords;

use cairo::{Context, Matrix, FontExtents, FontFace, FontSlant, FontWeight};

// Set up the font matrix, and set the font, etc.
pub fn prepare_to_label(cr: &Context, ac: &AppContext) {

    // Configure the font.
    let font_face = FontFace::toy_create(config::FONT_NAME, FontSlant::Normal, FontWeight::Bold);
    cr.set_font_face(font_face);

    set_font_size(config::LARGE_FONT_SIZE, cr, ac);
}

// Set the font size by reseting the font matrix
fn set_font_size(size_in_pnts: f64, cr: &Context, ac: &AppContext) {
    let dpi = match ac.get_dpi() {
        None => 72.0,
        Some(value) => value,
    };

    let font_size = size_in_pnts / 72.0 * dpi;
    let (font_size, _) = ac.convert_device_to_screen((font_size, 0.0));

    // Flip the y-coordinate so it displays the font right side up
    cr.set_font_matrix(Matrix {
        xx: 1.0 * font_size,
        yx: 0.0,
        xy: 0.0,
        yy: -1.0 * font_size, // Reflect it to be right side up!
        x0: 0.0,
        y0: 0.0,
    });
}

// Label the pressure, temperatures, etc lines.
pub fn draw_background_labels(cr: &Context, ac: &AppContext) {
    let labels = collect_labels(cr, ac);
    draw_labels(cr, labels);
}

// FIXME: Move this somewhere else in GUI? Seems more useful than just here.
#[derive(Clone, Copy)]
struct ScreenRect {
    lower_left: ScreenCoords,
    upper_right: ScreenCoords,
}

impl ScreenRect {
    fn overlaps(&self, other: &ScreenRect) -> bool {
        let (xmin_s, ymin_s) = self.lower_left;
        let (xmax_s, ymax_s) = self.upper_right;
        let (xmin_o, ymin_o) = other.lower_left;
        let (xmax_o, ymax_o) = other.upper_right;

        if xmin_s > xmax_o {
            return false;
        }
        if xmax_s < xmin_o {
            return false;
        }
        if ymin_s > ymax_o {
            return false;
        }
        if ymax_s < ymin_o {
            return false;
        }

        true
    }

    fn inside(&self, big_rect: &ScreenRect) -> bool {
        let (xmin_s, ymin_s) = self.lower_left;
        let (xmax_s, ymax_s) = self.upper_right;
        let (xmin_o, ymin_o) = big_rect.lower_left;
        let (xmax_o, ymax_o) = big_rect.upper_right;

        if xmin_s < xmin_o {
            return false;
        }
        if xmax_s > xmax_o {
            return false;
        }
        if ymin_s < ymin_o {
            return false;
        }
        if ymax_s > ymax_o {
            return false;
        }

        true
    }

    fn width(&self) -> f64 {
        self.upper_right.0 - self.lower_left.0
    }

    fn height(&self) -> f64 {
        self.upper_right.1 - self.lower_left.1
    }
}

fn calculate_plot_edges(ac: &AppContext) -> ScreenRect {

    let (lower_left_screen, upper_right_screen) = ac.bounding_box_in_screen_coords();
    let (mut screen_x_min, mut screen_y_min) = lower_left_screen;
    let (mut screen_x_max, mut screen_y_max) = upper_right_screen;

    // If screen area is bigger than plot area, labels will be clipped, keep them on the plot
    let (xmin, ymin) = ac.convert_xy_to_screen((0.0, 0.0));
    let (xmax, ymax) = ac.convert_xy_to_screen((1.0, 1.0));

    if xmin > screen_x_min {
        screen_x_min = xmin;
    }
    if xmax < screen_x_max {
        screen_x_max = xmax;
    }
    if ymax < screen_y_max {
        screen_y_max = ymax;
    }
    if ymin > screen_y_min {
        screen_y_min = ymin;
    }

    // Add some padding to keep away from the window edge
    screen_x_max -= config::DEFAULT_PADDING;
    screen_y_max -= config::DEFAULT_PADDING;
    screen_x_min += config::DEFAULT_PADDING;
    screen_y_min += config::DEFAULT_PADDING;

    ScreenRect {
        lower_left: (screen_x_min, screen_y_min),
        upper_right: (screen_x_max, screen_y_max),
    }
}

fn collect_labels(cr: &Context, ac: &AppContext) -> Vec<(String, ScreenRect)> {
    let mut labels = vec![];

    let screen_edges = calculate_plot_edges(ac);
    #[allow(unused_variables)]
    let ScreenRect {
        lower_left,
        upper_right,
    } = screen_edges;

    for &p in config::ISOBARS.into_iter() {

        let label = format!("{}", p);

        let extents = cr.text_extents(&label);

        let (_, screen_y) = ac.convert_tp_to_screen((0.0, p));
        let screen_y = screen_y - extents.height / 2.0;

        let label_lower_left = (lower_left.0, screen_y);
        let label_upper_right = (lower_left.0 + extents.width, screen_y + extents.height);

        let pair = (
            label,
            ScreenRect {
                lower_left: label_lower_left,
                upper_right: label_upper_right,
            },
        );

        check_overlap_then_add(&mut labels, &screen_edges, pair);
    }

    let (_, screen_max_p) = ac.convert_screen_to_tp(lower_left);
    for &t in config::ISOTHERMS.into_iter() {

        let label = format!("{}", t);

        let extents = cr.text_extents(&label);

        let (mut xpos, mut ypos) = ac.convert_tp_to_screen((t, screen_max_p));
        xpos -= extents.width / 2.0; // Center
        ypos -= extents.height / 2.0; // Center
        ypos += extents.height; // Move up off bottom axis.
        xpos += extents.height; // Move right for 45 degree angle from move up

        let label_lower_left = (xpos, ypos);
        let label_upper_right = (xpos + extents.width, ypos + extents.height);

        let pair = (
            label,
            ScreenRect {
                lower_left: label_lower_left,
                upper_right: label_upper_right,
            },
        );
        check_overlap_then_add(&mut labels, &screen_edges, pair);
    }

    labels
}

fn check_overlap_then_add(
    vector: &mut Vec<(String, ScreenRect)>,
    plot_edges: &ScreenRect,
    label_pair: (String, ScreenRect),
) {

    // Make sure itis on screen
    if !label_pair.1.inside(plot_edges) {
        return;
    }

    // Check for overlap
    for &(_, ref rect) in vector.iter() {
        if label_pair.1.overlaps(&rect) {
            return;
        }
    }

    vector.push(label_pair);
}

fn draw_labels(cr: &Context, labels: Vec<(String, ScreenRect)>) {

    // FIXME: Move to config, and use when checking overlaps?
    const PADDING_PIXELS: f64 = 3.0;
    let (padding, _) = cr.device_to_user_distance(PADDING_PIXELS, PADDING_PIXELS);

    for (label, rect) in labels {
        // FIXME: Handle this by using better destructuring and an underscore
        #[allow(unused_variables)]
        let ScreenRect {
            lower_left,
            upper_right,
        } = rect;

        let rgb = config::BACKGROUND_RGB;
        cr.set_source_rgb(rgb.0, rgb.1, rgb.2);
        cr.rectangle(
            lower_left.0 - padding,
            lower_left.1 - padding,
            rect.width() + 2.0 * padding,
            rect.height() + 2.0 * padding,
        );
        cr.fill();

        // Setup label colors
        // FIXME: Better way of handling color
        let rgba = config::ISOBAR_RGBA;
        cr.set_source_rgba(rgba.0, rgba.1, rgba.2, 1.0);
        cr.move_to(lower_left.0, lower_left.1);
        cr.show_text(&label);
    }
}

// Add a description box
pub fn draw_legend(cr: &Context, ac: &AppContext) {
    if !ac.plottable() {
        return;
    }

    let mut upper_left = ac.convert_device_to_screen((5.0, 5.0));
    // Make sure we stay on the x-y coords domain
    let (xmin, ymax) = ac.convert_xy_to_screen((0.0, 1.0));
    if ymax - upper_left.0 < upper_left.1 {
        upper_left.1 = ymax - upper_left.0;
    }

    if xmin + upper_left.0 > upper_left.0 {
        upper_left.0 = xmin + upper_left.0;
    }

    let font_extents = cr.font_extents();

    let (source_name, valid_time, location) = build_legend_strings(ac);

    // FIXME: Use ScreenRect
    let (box_width, box_height) =
        calculate_legend_box_size(cr, &font_extents, &source_name, &valid_time, &location);

    draw_legend_rectangle(cr, &upper_left, box_width, box_height);

    // FIXME: Use ScreenRect
    draw_legend_text(
        cr,
        &upper_left,
        &font_extents,
        &source_name,
        &valid_time,
        &location,
    );
}

fn build_legend_strings(ac: &AppContext) -> (Option<String>, Option<String>, Option<String>) {

    let source_name: Option<String> = ac.get_source_name();
    let mut valid_time: Option<String> = None;
    let mut location: Option<String> = None;
    if let Some(snd) = ac.get_sounding_for_display() {
        // Build the valid time part
        if let Some(vt) = snd.valid_time {
            use chrono::{Datelike, Timelike};
            valid_time = Some(format!(
                "Valid: {:02}/{:02}/{:04} {:02}Z",
                vt.month(),
                vt.day(),
                vt.year(),
                vt.hour()
            ));
        }

        // Build location part.
        if snd.lat.as_option().is_some() || snd.lon.as_option().is_some() ||
            snd.elevation.as_option().is_some()
        {
            location = Some("".to_owned());
            if let Some(ref mut loc) = location {
                if let Some(lat) = snd.lat.as_option() {
                    loc.push_str(&format!("{:.2}", lat));
                }
                if let Some(lon) = snd.lon.as_option() {
                    loc.push_str(&format!(", {:.2}", lon));
                }
                if let Some(el) = snd.elevation.as_option() {
                    loc.push_str(&format!(", {:.0}m ({:.0}ft)", el, el * 3.28084));
                }
            }
        }
    }

    (source_name, valid_time, location)
}

fn calculate_legend_box_size(
    cr: &Context,
    font_extents: &FontExtents,
    source_name: &Option<String>,
    valid_time: &Option<String>,
    location: &Option<String>,
) -> (f64, f64) {

    let mut box_width: f64 = 0.0;
    let mut box_height: f64 = 0.0;

    if let &Some(ref src) = source_name {
        let extents = cr.text_extents(src);
        if extents.width > box_width {
            box_width = extents.width;
        }
        box_height += extents.height;
    }

    if let &Some(ref vt) = valid_time {
        let extents = cr.text_extents(vt);
        if extents.width > box_width {
            box_width = extents.width;
        }
        box_height += extents.height;
        // Add line spacing if previous line was there.
        if source_name.is_some() {
            box_height += font_extents.height - extents.height;
        }
    }

    if let &Some(ref loc) = location {
        let extents = cr.text_extents(loc);
        if extents.width > box_width {
            box_width = extents.width;
        }
        box_height += extents.height;
        // Add line spacing if previous line was there.
        if valid_time.is_some() {
            box_height += font_extents.height - extents.height;
        }
    }

    // Add room for the last line's descent
    box_height += font_extents.descent;

    // Add padding last
    box_height += 2.0 * config::DEFAULT_PADDING;
    box_width += 2.0 * config::DEFAULT_PADDING;

    (box_width, box_height)
}

// FIXME: Use ScreenRect
fn draw_legend_rectangle(cr: &Context, upper_left: &ScreenCoords, width: f64, height: f64) {
    cr.rectangle(upper_left.0, upper_left.1 - height, width, height);

    let rgb = config::ISOBAR_RGBA;
    cr.set_source_rgba(rgb.0, rgb.1, rgb.2, rgb.3);
    cr.set_line_width(cr.device_to_user_distance(3.0, 0.0).0);
    cr.stroke_preserve();
    let rgb = config::BACKGROUND_RGB;
    cr.set_source_rgb(rgb.0, rgb.1, rgb.2);
    cr.fill();
}

fn draw_legend_text(
    cr: &Context,
    upper_left: &ScreenCoords,
    font_extents: &FontExtents,
    source_name: &Option<String>,
    valid_time: &Option<String>,
    location: &Option<String>,
) {
    let rgb = config::ISOBAR_RGBA;
    cr.set_source_rgba(rgb.0, rgb.1, rgb.2, rgb.3);

    // Remember how many lines we have drawn so far for setting position of the next line.
    let mut num_lines_drawn = 0;

    // Get into the initial position
    cr.move_to(
        upper_left.0 + config::DEFAULT_PADDING,
        upper_left.1 - config::DEFAULT_PADDING - font_extents.ascent,
    );

    if let &Some(ref src) = source_name {
        cr.show_text(src);
        num_lines_drawn += 1;
        cr.move_to(
            upper_left.0 + config::DEFAULT_PADDING,
            upper_left.1 - config::DEFAULT_PADDING - font_extents.ascent -
                num_lines_drawn as f64 * font_extents.height,
        );
    }
    if let &Some(ref vt) = valid_time {
        cr.show_text(vt);
        num_lines_drawn += 1;
        cr.move_to(
            upper_left.0 + config::DEFAULT_PADDING,
            upper_left.1 - config::DEFAULT_PADDING - font_extents.ascent -
                num_lines_drawn as f64 * font_extents.height,
        );
    }
    if let &Some(ref loc) = location {
        cr.show_text(loc);
        num_lines_drawn += 1;
        cr.move_to(
            upper_left.0 + config::DEFAULT_PADDING,
            upper_left.1 - config::DEFAULT_PADDING - font_extents.ascent -
                num_lines_drawn as f64 * font_extents.height,
        );
    }
}
<|endoftext|>


<commit_before>
//! Combine transform to turn rel expressions into hir expressions

use super::rel::*;
use slp_lang_hir as hir;
use std::error;
use std::fmt;
use std::collections::HashMap;
use std::collections::hash_map::Entry;

#[derive(PartialEq, Debug, Clone)]
pub enum CombineError {
    FailedToResolveMultiPartExpression,
}

pub type CombineResult<T> = Result<T, CombineError>;

impl error::Error for CombineError {
    fn description(&self) -> &str {
        match *self {
            CombineError::FailedToResolveMultiPartExpression => {
                "expression too complex to resolve (rel parser internal error)"
            }
        }
    }
}

impl fmt::Display for CombineError {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "{}", error::Error::description(self))
    }
}

struct BuiltQueue(HashMap<BindId, hir::Expression>);

impl BuiltQueue {
    fn new() -> BuiltQueue {
        BuiltQueue(HashMap::new())
    }
    fn take(mut self, id: &BindId) -> Option<(BuiltQueue, hir::Expression)> {
        let expr = match self.0.entry(id.clone()) {
            Entry::Occupied(occupied) => occupied.remove(),
            Entry::Vacant(_) => return None,
        };
        Some((self, expr))
    }
    fn with_next(mut self, id: BindId, expr: hir::Expression) -> BuiltQueue {
        self.0.insert(id, expr);
        self
    }
    fn empty(&self) -> bool {
        self.0.len() == 0
    }
}

#[derive(PartialEq, Debug, Clone)]
pub enum CombinedExpression {
    Single(hir::Expression),
    Multi(Vec<hir::Statement>),
}

fn combine_trivial(seq: &Sequence) -> Option<hir::Expression> {

    fn build_command(command: &Command, q: BuiltQueue) -> Option<(BuiltQueue, hir::Expression)> {
        match *command {
            Command::Literal(ref lit) => Some((q, hir::Expression::Literal(lit.clone()))),
            Command::Variable(ref var) => Some((q, hir::Expression::Variable(var.clone()))),
            Command::Global(ref id) => Some((q, hir::Expression::Global(id.clone()))),
            Command::ConstantVariable(ref id, ref name) => {
                let var = hir::Expression::ConstantVariable(id.clone(), name.clone());
                Some((q, var))
            }
            Command::Swizzle(ref val, ref swizzle) => {
                let (q, e) = match q.take(val) {
                    Some(res) => res,
                    None => return None,
                };
                Some((q, hir::Expression::Swizzle(Box::new(e), swizzle.clone())))
            }
            Command::ArraySubscript(ref arr_val, ref ind_val) => {
                let (q, arr) = match q.take(arr_val) {
                    Some((q, e)) => (q, Box::new(e)),
                    None => return None,
                };
                let (q, index) = match q.take(ind_val) {
                    Some((q, e)) => (q, Box::new(e)),
                    None => return None,
                };
                Some((q, hir::Expression::ArraySubscript(arr, index)))
            }
            Command::TextureIndex(_, _, _) => None,
            Command::Member(ref val, ref name) => {
                let (q, e) = match q.take(val) {
                    Some((q, e)) => (q, Box::new(e)),
                    None => return None,
                };
                Some((q, hir::Expression::Member(e, name.clone())))
            }
            Command::Call(ref id, ref params) => {
                let mut exprs = vec![];
                let mut q = q;
                for param in params {
                    match q.take(param) {
                        Some((next_q, e)) => {
                            q = next_q;
                            exprs.push(e);
                        }
                        None => return None,
                    };
                }
                Some((q, hir::Expression::Call(id.clone(), exprs)))
            }
            Command::NumericConstructor(ref dtyl, ref cons_slot) => {
                let mut slots = vec![];
                let mut q = q;
                for slot in cons_slot {
                    match q.take(&slot.expr) {
                        Some((next_q, e)) => {
                            q = next_q;
                            let out = hir::ConstructorSlot {
                                arity: slot.arity,
                                expr: e,
                            };
                            slots.push(out);
                        }
                        None => return None,
                    };
                }
                Some((q, hir::Expression::NumericConstructor(dtyl.clone(), slots)))
            }
            Command::Cast(ref ty, ref val) => {
                let (q, e) = match q.take(val) {
                    Some((q, e)) => (q, Box::new(e)),
                    None => return None,
                };
                Some((q, hir::Expression::Cast(ty.clone(), e)))
            }
            Command::Intrinsic0(ref i) => {
                let r = hir::Expression::Intrinsic0(i.clone());
                Some((q, r))
            }
            Command::Intrinsic1(ref i, ref p1) => {
                let (q, e1) = match q.take(p1) {
                    Some((q, e)) => (q, Box::new(e)),
                    None => return None,
                };
                let r = hir::Expression::Intrinsic1(i.clone(), e1);
                Some((q, r))
            }
            Command::Intrinsic2(ref i, ref p1, ref p2) => {
                let (q, e1) = match q.take(p1) {
                    Some((q, e)) => (q, Box::new(e)),
                    None => return None,
                };
                let (q, e2) = match q.take(p2) {
                    Some((q, e)) => (q, Box::new(e)),
                    None => return None,
                };
                let r = hir::Expression::Intrinsic2(i.clone(), e1, e2);
                Some((q, r))
            }
            Command::Intrinsic3(ref i, ref p1, ref p2, ref p3) => {
                let (q, e1) = match q.take(p1) {
                    Some((q, e)) => (q, Box::new(e)),
                    None => return None,
                };
                let (q, e2) = match q.take(p2) {
                    Some((q, e)) => (q, Box::new(e)),
                    None => return None,
                };
                let (q, e3) = match q.take(p3) {
                    Some((q, e)) => (q, Box::new(e)),
                    None => return None,
                };
                let r = hir::Expression::Intrinsic3(i.clone(), e1, e2, e3);
                Some((q, r))
            }
        }
    }

    fn build_bind_type(bind_type: &BindType,
                       q: BuiltQueue)
                       -> Option<(BuiltQueue, hir::Expression)> {
        match *bind_type {
            BindType::Direct(ref command) => build_command(command, q),
            BindType::Select(ref cond, ref lhs, ref rhs) => {
                let (q, cond_val) = match q.take(cond) {
                    Some(res) => res,
                    None => return None,
                };
                let lhs_val = match combine_trivial(lhs) {
                    Some(lhs_val) => lhs_val,
                    None => return None,
                };
                let rhs_val = match combine_trivial(rhs) {
                    Some(rhs_val) => rhs_val,
                    None => return None,
                };
                let cond_box = Box::new(cond_val);
                let lhs_val = Box::new(lhs_val);
                let rhs_val = Box::new(rhs_val);
                let expr = hir::Expression::TernaryConditional(cond_box, lhs_val, rhs_val);
                Some((q, expr))
            }
        }
    }

    fn build_bind(bind: &Bind, q: BuiltQueue) -> Option<BuiltQueue> {
        match build_bind_type(&bind.bind_type, q) {
            Some((q, e)) => Some(q.with_next(bind.id, e)),
            None => None,
        }
    }

    let mut queue = BuiltQueue::new();
    for bind in &seq.binds {
        queue = match build_bind(bind, queue) {
            Some(q) => q,
            None => return None,
        };
    }

    match build_bind_type(&seq.last, queue) {
        Some((q, e)) => {
            if q.empty() {
                Some(e)
            } else {
                None
            }
        }
        None => None,
    }
}

fn combine_complex(_: Sequence) -> CombineResult<Vec<hir::Statement>> {
    Err(CombineError::FailedToResolveMultiPartExpression)
}

pub fn combine(seq: Sequence) -> CombineResult<CombinedExpression> {
    match combine_trivial(&seq) {
        Some(exp) => return Ok(CombinedExpression::Single(exp)),
        None => {}
    }
    let parts = try!(combine_complex(seq));
    Ok(CombinedExpression::Multi(parts))
}

#[test]
fn test_combine_single_variable() {

    let var_ref = hir::VariableRef(hir::VariableId(0), hir::ScopeRef(0));
    let var_seq = Sequence {
        binds: vec![],
        last: BindType::Direct(Command::Variable(var_ref.clone())),
    };
    let var_expr = combine(var_seq).expect("combine failed");
    let var_0 = hir::Expression::Variable(var_ref);
    assert_eq!(var_expr, CombinedExpression::Single(var_0));
}

#[test]
fn test_combine_binary_operation() {
    let var_0_ref = hir::VariableRef(hir::VariableId(0), hir::ScopeRef(0));
    let var_1_ref = hir::VariableRef(hir::VariableId(1), hir::ScopeRef(0));
    let dty = hir::DataType(hir::DataLayout::Scalar(hir::ScalarType::Float),
                            hir::TypeModifier::default());
    let add = hir::Intrinsic2::Add(dty.clone());
    let bin_seq = Sequence {
        binds: vec![
            Bind::direct(0, Command::Variable(var_0_ref.clone())),
            Bind::direct(1, Command::Variable(var_1_ref.clone())),
        ],
        last: BindType::Direct(Command::Intrinsic2(add.clone(), BindId(0), BindId(1))),
    };
    let bin_expr = combine(bin_seq).expect("combine failed");
    let var_0 = hir::Expression::Variable(var_0_ref);
    let var_1 = hir::Expression::Variable(var_1_ref);
    let add = hir::Expression::Intrinsic2(add, Box::new(var_0), Box::new(var_1));
    assert_eq!(bin_expr, CombinedExpression::Single(add));
}
<commit_msg>Fix rel combine to only consume last pushed values<commit_after>
//! Combine transform to turn rel expressions into hir expressions

use super::rel::*;
use slp_lang_hir as hir;
use std::error;
use std::fmt;

#[derive(PartialEq, Debug, Clone)]
pub enum CombineError {
    FailedToResolveMultiPartExpression,
}

pub type CombineResult<T> = Result<T, CombineError>;

impl error::Error for CombineError {
    fn description(&self) -> &str {
        match *self {
            CombineError::FailedToResolveMultiPartExpression => {
                "expression too complex to resolve (rel parser internal error)"
            }
        }
    }
}

impl fmt::Display for CombineError {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "{}", error::Error::description(self))
    }
}

struct BuiltQueue(Vec<(BindId, hir::Expression)>);

impl BuiltQueue {
    fn new() -> BuiltQueue {
        BuiltQueue(Vec::new())
    }
    fn take(mut self, id: &BindId) -> Option<(BuiltQueue, hir::Expression)> {
        match self.0.pop() {
            Some((pop_id, expr)) => {
                if *id == pop_id {
                    Some((self, expr))
                } else {
                    None
                }
            }
            None => None,
        }
    }
    fn with_next(mut self, id: BindId, expr: hir::Expression) -> BuiltQueue {
        self.0.push((id, expr));
        self
    }
    fn empty(&self) -> bool {
        self.0.len() == 0
    }
}

#[derive(PartialEq, Debug, Clone)]
pub enum CombinedExpression {
    Single(hir::Expression),
    Multi(Vec<hir::Statement>),
}

fn combine_trivial(seq: &Sequence) -> Option<hir::Expression> {

    fn build_command(command: &Command, q: BuiltQueue) -> Option<(BuiltQueue, hir::Expression)> {
        match *command {
            Command::Literal(ref lit) => Some((q, hir::Expression::Literal(lit.clone()))),
            Command::Variable(ref var) => Some((q, hir::Expression::Variable(var.clone()))),
            Command::Global(ref id) => Some((q, hir::Expression::Global(id.clone()))),
            Command::ConstantVariable(ref id, ref name) => {
                let var = hir::Expression::ConstantVariable(id.clone(), name.clone());
                Some((q, var))
            }
            Command::Swizzle(ref val, ref swizzle) => {
                let (q, e) = match q.take(val) {
                    Some(res) => res,
                    None => return None,
                };
                Some((q, hir::Expression::Swizzle(Box::new(e), swizzle.clone())))
            }
            Command::ArraySubscript(ref arr_val, ref ind_val) => {
                let (q, index) = match q.take(ind_val) {
                    Some((q, e)) => (q, Box::new(e)),
                    None => return None,
                };
                let (q, arr) = match q.take(arr_val) {
                    Some((q, e)) => (q, Box::new(e)),
                    None => return None,
                };
                Some((q, hir::Expression::ArraySubscript(arr, index)))
            }
            Command::TextureIndex(_, _, _) => None,
            Command::Member(ref val, ref name) => {
                let (q, e) = match q.take(val) {
                    Some((q, e)) => (q, Box::new(e)),
                    None => return None,
                };
                Some((q, hir::Expression::Member(e, name.clone())))
            }
            Command::Call(ref id, ref params) => {
                let mut exprs = vec![];
                let mut q = q;
                for param in params.iter().rev() {
                    match q.take(param) {
                        Some((next_q, e)) => {
                            q = next_q;
                            exprs.push(e);
                        }
                        None => return None,
                    };
                }
                let exprs = exprs.into_iter().rev().collect::<Vec<_>>();
                Some((q, hir::Expression::Call(id.clone(), exprs)))
            }
            Command::NumericConstructor(ref dtyl, ref cons_slot) => {
                let mut slots = vec![];
                let mut q = q;
                for slot in cons_slot.iter().rev() {
                    match q.take(&slot.expr) {
                        Some((next_q, e)) => {
                            q = next_q;
                            let out = hir::ConstructorSlot {
                                arity: slot.arity,
                                expr: e,
                            };
                            slots.push(out);
                        }
                        None => return None,
                    };
                }
                let slots = slots.into_iter().rev().collect::<Vec<_>>();
                Some((q, hir::Expression::NumericConstructor(dtyl.clone(), slots)))
            }
            Command::Cast(ref ty, ref val) => {
                let (q, e) = match q.take(val) {
                    Some((q, e)) => (q, Box::new(e)),
                    None => return None,
                };
                Some((q, hir::Expression::Cast(ty.clone(), e)))
            }
            Command::Intrinsic0(ref i) => {
                let r = hir::Expression::Intrinsic0(i.clone());
                Some((q, r))
            }
            Command::Intrinsic1(ref i, ref p1) => {
                let (q, e1) = match q.take(p1) {
                    Some((q, e)) => (q, Box::new(e)),
                    None => return None,
                };
                let r = hir::Expression::Intrinsic1(i.clone(), e1);
                Some((q, r))
            }
            Command::Intrinsic2(ref i, ref p1, ref p2) => {
                let (q, e2) = match q.take(p2) {
                    Some((q, e)) => (q, Box::new(e)),
                    None => return None,
                };
                let (q, e1) = match q.take(p1) {
                    Some((q, e)) => (q, Box::new(e)),
                    None => return None,
                };
                let r = hir::Expression::Intrinsic2(i.clone(), e1, e2);
                Some((q, r))
            }
            Command::Intrinsic3(ref i, ref p1, ref p2, ref p3) => {
                let (q, e3) = match q.take(p3) {
                    Some((q, e)) => (q, Box::new(e)),
                    None => return None,
                };
                let (q, e2) = match q.take(p2) {
                    Some((q, e)) => (q, Box::new(e)),
                    None => return None,
                };
                let (q, e1) = match q.take(p1) {
                    Some((q, e)) => (q, Box::new(e)),
                    None => return None,
                };
                let r = hir::Expression::Intrinsic3(i.clone(), e1, e2, e3);
                Some((q, r))
            }
        }
    }

    fn build_bind_type(bind_type: &BindType,
                       q: BuiltQueue)
                       -> Option<(BuiltQueue, hir::Expression)> {
        match *bind_type {
            BindType::Direct(ref command) => build_command(command, q),
            BindType::Select(ref cond, ref lhs, ref rhs) => {
                let (q, cond_val) = match q.take(cond) {
                    Some(res) => res,
                    None => return None,
                };
                let lhs_val = match combine_trivial(lhs) {
                    Some(lhs_val) => lhs_val,
                    None => return None,
                };
                let rhs_val = match combine_trivial(rhs) {
                    Some(rhs_val) => rhs_val,
                    None => return None,
                };
                let cond_box = Box::new(cond_val);
                let lhs_val = Box::new(lhs_val);
                let rhs_val = Box::new(rhs_val);
                let expr = hir::Expression::TernaryConditional(cond_box, lhs_val, rhs_val);
                Some((q, expr))
            }
        }
    }

    fn build_bind(bind: &Bind, q: BuiltQueue) -> Option<BuiltQueue> {
        match build_bind_type(&bind.bind_type, q) {
            Some((q, e)) => Some(q.with_next(bind.id, e)),
            None => None,
        }
    }

    let mut queue = BuiltQueue::new();
    for bind in &seq.binds {
        queue = match build_bind(bind, queue) {
            Some(q) => q,
            None => return None,
        };
    }

    match build_bind_type(&seq.last, queue) {
        Some((q, e)) => {
            if q.empty() {
                Some(e)
            } else {
                None
            }
        }
        None => None,
    }
}

fn combine_complex(_: Sequence) -> CombineResult<Vec<hir::Statement>> {
    Err(CombineError::FailedToResolveMultiPartExpression)
}

pub fn combine(seq: Sequence) -> CombineResult<CombinedExpression> {
    match combine_trivial(&seq) {
        Some(exp) => return Ok(CombinedExpression::Single(exp)),
        None => {}
    }
    let parts = try!(combine_complex(seq));
    Ok(CombinedExpression::Multi(parts))
}

#[test]
fn test_combine_single_variable() {

    let var_ref = hir::VariableRef(hir::VariableId(0), hir::ScopeRef(0));
    let var_seq = Sequence {
        binds: vec![],
        last: BindType::Direct(Command::Variable(var_ref.clone())),
    };
    let var_expr = combine(var_seq).expect("combine failed");
    let var_0 = hir::Expression::Variable(var_ref);
    assert_eq!(var_expr, CombinedExpression::Single(var_0));
}

#[test]
fn test_combine_binary_operation() {
    let var_0_ref = hir::VariableRef(hir::VariableId(0), hir::ScopeRef(0));
    let var_1_ref = hir::VariableRef(hir::VariableId(1), hir::ScopeRef(0));
    let dty = hir::DataType(hir::DataLayout::Scalar(hir::ScalarType::Float),
                            hir::TypeModifier::default());
    let add = hir::Intrinsic2::Add(dty.clone());
    let bin_seq = Sequence {
        binds: vec![
            Bind::direct(0, Command::Variable(var_0_ref.clone())),
            Bind::direct(1, Command::Variable(var_1_ref.clone())),
        ],
        last: BindType::Direct(Command::Intrinsic2(add.clone(), BindId(0), BindId(1))),
    };
    let bin_expr = combine(bin_seq).expect("combine failed");
    let var_0 = hir::Expression::Variable(var_0_ref);
    let var_1 = hir::Expression::Variable(var_1_ref);
    let add = hir::Expression::Intrinsic2(add, Box::new(var_0), Box::new(var_1));
    assert_eq!(bin_expr, CombinedExpression::Single(add));
}
<|endoftext|>


<commit_before>use super::{
    general::{cfg_deprecated, doc_hidden, version_condition},
    signal_body,
    trampoline::{self, func_string},
};
use crate::{
    analysis,
    chunk::Chunk,
    consts::TYPE_PARAMETERS_START,
    env::Env,
    library,
    nameutil::use_glib_type,
    writer::{primitives::tabs, ToCode},
};
use std::io::{Result, Write};

pub fn generate(
    w: &mut dyn Write,
    env: &Env,
    analysis: &analysis::signals::Info,
    in_trait: bool,
    only_declaration: bool,
    indent: usize,
) -> Result<()> {
    let commented = analysis.trampoline.is_err();
    let comment_prefix = if commented { "//" } else { "" };
    let pub_prefix = if in_trait { "" } else { "pub " };

    let function_type = function_type_string(env, analysis, true);
    let declaration = declaration(analysis, &function_type);
    let suffix = if only_declaration { ";" } else { " {" };

    writeln!(w)?;
    if !in_trait || only_declaration {
        cfg_deprecated(w, env, analysis.deprecated_version, commented, indent)?;
    }
    version_condition(w, env, analysis.version, commented, indent)?;
    doc_hidden(w, analysis.doc_hidden, comment_prefix, indent)?;
    writeln!(
        w,
        "{}{}{}{}{}",
        tabs(indent),
        comment_prefix,
        pub_prefix,
        declaration,
        suffix
    )?;

    if !only_declaration {
        if !commented {
            if let Ok(ref trampoline) = analysis.trampoline {
                trampoline::generate(w, env, trampoline, in_trait, 2)?;
            }
        }
        match function_type {
            Some(_) => {
                let body = body(analysis, in_trait).to_code(env);
                for s in body {
                    writeln!(w, "{}{}", tabs(indent), s)?;
                }
            }
            _ => {
                if let Err(ref errors) = analysis.trampoline {
                    for error in errors {
                        writeln!(w, "{}{}\t{}", tabs(indent), comment_prefix, error)?;
                    }
                    writeln!(w, "{}{}}}", tabs(indent), comment_prefix)?;
                } else {
                    writeln!(
                        w,
                        "{}{}\tTODO: connect to trampoline\n{0}{1}}}",
                        tabs(indent),
                        comment_prefix
                    )?;
                }
            }
        }
    }

    if function_type.is_none() {
        // Signal incomplete, can't generate emit
        return Ok(());
    }

    if let Some(ref emit_name) = analysis.action_emit_name {
        writeln!(w)?;
        if !in_trait || only_declaration {
            cfg_deprecated(w, env, analysis.deprecated_version, commented, indent)?;
        }
        version_condition(w, env, analysis.version, commented, indent)?;

        let function_type = function_type_string(env, analysis, false);

        writeln!(
            w,
            "{}{}{}fn {}{}{}",
            tabs(indent),
            comment_prefix,
            pub_prefix,
            emit_name,
            function_type.unwrap(),
            suffix
        )?;

        if !only_declaration {
            let trampoline = analysis.trampoline.as_ref().unwrap_or_else(|_| {
                panic!(
                    "Internal error: can't find trampoline for signal '{}'",
                    analysis.signal_name,
                )
            });
            let mut args = String::with_capacity(100);

            for (pos, par) in trampoline.parameters.rust_parameters.iter().enumerate() {
                // Skip the self parameter
                if pos == 0 {
                    continue;
                }

                if pos > 1 {
                    args.push_str(", ");
                }
                args.push('&');
                args.push_str(&par.name);
            }

            writeln!(
                w,
                "{}let {} = unsafe {{ glib::Object::from_glib_borrow(self.as_ptr() as *mut {}).emit(\"{}\", &[{}]).unwrap() }};",
                tabs(indent + 1),
                if trampoline.ret.typ != Default::default() {
                    "res"
                } else {
                    "_"
                },
                use_glib_type(env, "gobject_ffi::GObject"),
                analysis.signal_name,
                args,
            )?;

            if trampoline.ret.typ != Default::default() {
                let unwrap = if trampoline.ret.nullable == library::Nullable(true) {
                    ""
                } else {
                    ".unwrap()"
                };

                writeln!(
                    w,
                    "{}res.unwrap().get().expect(\"Return Value for `{}`\"){}",
                    tabs(indent + 1),
                    emit_name,
                    unwrap,
                )?;
            }
            writeln!(w, "{}}}", tabs(indent))?;
        }
    }

    Ok(())
}

fn function_type_string(
    env: &Env,
    analysis: &analysis::signals::Info,
    closure: bool,
) -> Option<String> {
    if analysis.trampoline.is_err() {
        return None;
    }

    let trampoline = analysis.trampoline.as_ref().unwrap_or_else(|_| {
        panic!(
            "Internal error: can't find trampoline for signal '{}'",
            analysis.signal_name
        )
    });

    let type_ = func_string(
        env,
        trampoline,
        if closure {
            Some((TYPE_PARAMETERS_START, "Self"))
        } else {
            Some((TYPE_PARAMETERS_START, "self"))
        },
        closure,
    );
    Some(type_)
}

fn declaration(analysis: &analysis::signals::Info, function_type: &Option<String>) -> String {
    let bounds = bounds(function_type);
    let param_str = "&self, f: F";
    let return_str = " -> SignalHandlerId";
    format!(
        "fn {}<{}>({}){}",
        analysis.connect_name, bounds, param_str, return_str
    )
}

fn bounds(function_type: &Option<String>) -> String {
    match *function_type {
        Some(ref type_) => format!("F: {}", type_),
        _ => "Unsupported or ignored types".to_owned(),
    }
}

fn body(analysis: &analysis::signals::Info, in_trait: bool) -> Chunk {
    let mut builder = signal_body::Builder::new();

    builder
        .signal_name(&analysis.signal_name)
        .trampoline_name(&analysis.trampoline.as_ref().unwrap().name)
        .in_trait(in_trait);

    builder.generate()
}
<commit_msg>signals: rename emit to emit_by_name<commit_after>use super::{
    general::{cfg_deprecated, doc_hidden, version_condition},
    signal_body,
    trampoline::{self, func_string},
};
use crate::{
    analysis,
    chunk::Chunk,
    consts::TYPE_PARAMETERS_START,
    env::Env,
    library,
    nameutil::use_glib_type,
    writer::{primitives::tabs, ToCode},
};
use std::io::{Result, Write};

pub fn generate(
    w: &mut dyn Write,
    env: &Env,
    analysis: &analysis::signals::Info,
    in_trait: bool,
    only_declaration: bool,
    indent: usize,
) -> Result<()> {
    let commented = analysis.trampoline.is_err();
    let comment_prefix = if commented { "//" } else { "" };
    let pub_prefix = if in_trait { "" } else { "pub " };

    let function_type = function_type_string(env, analysis, true);
    let declaration = declaration(analysis, &function_type);
    let suffix = if only_declaration { ";" } else { " {" };

    writeln!(w)?;
    if !in_trait || only_declaration {
        cfg_deprecated(w, env, analysis.deprecated_version, commented, indent)?;
    }
    version_condition(w, env, analysis.version, commented, indent)?;
    doc_hidden(w, analysis.doc_hidden, comment_prefix, indent)?;
    writeln!(
        w,
        "{}{}{}{}{}",
        tabs(indent),
        comment_prefix,
        pub_prefix,
        declaration,
        suffix
    )?;

    if !only_declaration {
        if !commented {
            if let Ok(ref trampoline) = analysis.trampoline {
                trampoline::generate(w, env, trampoline, in_trait, 2)?;
            }
        }
        match function_type {
            Some(_) => {
                let body = body(analysis, in_trait).to_code(env);
                for s in body {
                    writeln!(w, "{}{}", tabs(indent), s)?;
                }
            }
            _ => {
                if let Err(ref errors) = analysis.trampoline {
                    for error in errors {
                        writeln!(w, "{}{}\t{}", tabs(indent), comment_prefix, error)?;
                    }
                    writeln!(w, "{}{}}}", tabs(indent), comment_prefix)?;
                } else {
                    writeln!(
                        w,
                        "{}{}\tTODO: connect to trampoline\n{0}{1}}}",
                        tabs(indent),
                        comment_prefix
                    )?;
                }
            }
        }
    }

    if function_type.is_none() {
        // Signal incomplete, can't generate emit
        return Ok(());
    }

    if let Some(ref emit_name) = analysis.action_emit_name {
        writeln!(w)?;
        if !in_trait || only_declaration {
            cfg_deprecated(w, env, analysis.deprecated_version, commented, indent)?;
        }
        version_condition(w, env, analysis.version, commented, indent)?;

        let function_type = function_type_string(env, analysis, false);

        writeln!(
            w,
            "{}{}{}fn {}{}{}",
            tabs(indent),
            comment_prefix,
            pub_prefix,
            emit_name,
            function_type.unwrap(),
            suffix
        )?;

        if !only_declaration {
            let trampoline = analysis.trampoline.as_ref().unwrap_or_else(|_| {
                panic!(
                    "Internal error: can't find trampoline for signal '{}'",
                    analysis.signal_name,
                )
            });
            let mut args = String::with_capacity(100);

            for (pos, par) in trampoline.parameters.rust_parameters.iter().enumerate() {
                // Skip the self parameter
                if pos == 0 {
                    continue;
                }

                if pos > 1 {
                    args.push_str(", ");
                }
                args.push('&');
                args.push_str(&par.name);
            }

            writeln!(
                w,
                "{}let {} = unsafe {{ glib::Object::from_glib_borrow(self.as_ptr() as *mut {}).emit_by_name(\"{}\", &[{}]).unwrap() }};",
                tabs(indent + 1),
                if trampoline.ret.typ != Default::default() {
                    "res"
                } else {
                    "_"
                },
                use_glib_type(env, "gobject_ffi::GObject"),
                analysis.signal_name,
                args,
            )?;

            if trampoline.ret.typ != Default::default() {
                let unwrap = if trampoline.ret.nullable == library::Nullable(true) {
                    ""
                } else {
                    ".unwrap()"
                };

                writeln!(
                    w,
                    "{}res.unwrap().get().expect(\"Return Value for `{}`\"){}",
                    tabs(indent + 1),
                    emit_name,
                    unwrap,
                )?;
            }
            writeln!(w, "{}}}", tabs(indent))?;
        }
    }

    Ok(())
}

fn function_type_string(
    env: &Env,
    analysis: &analysis::signals::Info,
    closure: bool,
) -> Option<String> {
    if analysis.trampoline.is_err() {
        return None;
    }

    let trampoline = analysis.trampoline.as_ref().unwrap_or_else(|_| {
        panic!(
            "Internal error: can't find trampoline for signal '{}'",
            analysis.signal_name
        )
    });

    let type_ = func_string(
        env,
        trampoline,
        if closure {
            Some((TYPE_PARAMETERS_START, "Self"))
        } else {
            Some((TYPE_PARAMETERS_START, "self"))
        },
        closure,
    );
    Some(type_)
}

fn declaration(analysis: &analysis::signals::Info, function_type: &Option<String>) -> String {
    let bounds = bounds(function_type);
    let param_str = "&self, f: F";
    let return_str = " -> SignalHandlerId";
    format!(
        "fn {}<{}>({}){}",
        analysis.connect_name, bounds, param_str, return_str
    )
}

fn bounds(function_type: &Option<String>) -> String {
    match *function_type {
        Some(ref type_) => format!("F: {}", type_),
        _ => "Unsupported or ignored types".to_owned(),
    }
}

fn body(analysis: &analysis::signals::Info, in_trait: bool) -> Chunk {
    let mut builder = signal_body::Builder::new();

    builder
        .signal_name(&analysis.signal_name)
        .trampoline_name(&analysis.trampoline.as_ref().unwrap().name)
        .in_trait(in_trait);

    builder.generate()
}
<|endoftext|>


<commit_before>use leveldb::database::Database as LevelDatabase;
use leveldb::iterator::{LevelDBIterator, Iterable};
use leveldb::error::Error as LevelDBError;
use leveldb::database::snapshots::Snapshot as LevelSnapshot;
use leveldb::options::{WriteOptions, ReadOptions};
use leveldb::database::batch::Writebatch;
use leveldb::batch::Batch;
use leveldb::snapshots::Snapshots;

use std::fs;
use std::io;
use std::mem;
use std::path::Path;
use std::error;
use std::sync::Arc;

pub use leveldb::options::Options as LevelDBOptions;

use super::{Database, Iter, Snapshot, Error, Patch, Change, Result};

const LEVELDB_READ_OPTIONS: ReadOptions<'static> = ReadOptions {
    verify_checksums: false,
    fill_cache: true,
    snapshot: None,
};

const LEVELDB_WRITE_OPTIONS: WriteOptions = WriteOptions { sync: false };

#[derive(Clone)]
pub struct LevelDB {
    db: Arc<LevelDatabase>,
}

struct LevelDBSnapshot {
    _db: Arc<LevelDatabase>,
    snapshot: LevelSnapshot<'static>,
}

impl From<LevelDBError> for Error {
    fn from(err: LevelDBError) -> Self {
        Error::new(error::Error::description(&err))
    }
}

impl From<io::Error> for Error {
    fn from(err: io::Error) -> Self {
        Error::new(error::Error::description(&err))
    }
}

impl LevelDB {
    // TODO: configurate LRU cache
    pub fn open(path: &Path, options: LevelDBOptions) -> Result<LevelDB> {
        if options.create_if_missing {
            fs::create_dir_all(path)?;
        }
        let database = LevelDatabase::open(path, options)?;
        Ok(LevelDB { db: Arc::new(database) })
    }
}

impl Database for LevelDB {
    fn clone(&self) -> Box<Database> {
        Box::new(Clone::clone(self))
    }

    fn snapshot(&self) -> Box<Snapshot> {
        Box::new(LevelDBSnapshot {
                     _db: self.db.clone(),
                     snapshot: unsafe { mem::transmute(self.db.snapshot()) },
                 })
    }

    fn merge(&mut self, patch: Patch) -> Result<()> {
        let mut batch = Writebatch::new();
        for (key, change) in patch {
            match change {
                Change::Put(ref v) => batch.put(key, v),
                Change::Delete => batch.delete(key),
            }
        }
        self.db
            .write(LEVELDB_WRITE_OPTIONS, &batch)
            .map_err(Into::into)
    }
}

impl Snapshot for LevelDBSnapshot {
    fn get(&self, key: &[u8]) -> Option<Vec<u8>> {
        match self.snapshot.get(LEVELDB_READ_OPTIONS, key) {
            Ok(value) => value,
            Err(err) => panic!(err),
        }
    }

    fn iter<'a>(&'a self, from: &[u8]) -> Iter<'a> {
        let iter = self.snapshot.iter(LEVELDB_READ_OPTIONS);
        iter.seek(from);
        Box::new(iter)
    }
}

impl ::std::fmt::Debug for LevelDB {
    fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result {
        write!(f, "LevelDB(..)")
    }
}

impl ::std::fmt::Debug for LevelDBSnapshot {
    fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result {
        write!(f, "LevelDBSnapshot(..)")
    }
}
<commit_msg>Add flame profiling for leveldb<commit_after>use profiler;

use leveldb::database::Database as _LevelDB;
use leveldb::iterator::{LevelDBIterator as _LevelDBIterator, Iterator as _Iterator, Iterable};
use leveldb::error::Error as _Error;
use leveldb::database::snapshots::Snapshot as _Snapshot;
use leveldb::options::{WriteOptions, ReadOptions};
use leveldb::database::batch::Writebatch;
use leveldb::batch::Batch;
use leveldb::snapshots::Snapshots;

use std::fs;
use std::io;
use std::mem;
use std::path::Path;
use std::error;
use std::sync::Arc;
use std::iter::Iterator;

pub use leveldb::options::Options as LevelDBOptions;

use super::{Database, Iter, Snapshot, Error, Patch, Change, Result};

const LEVELDB_READ_OPTIONS: ReadOptions<'static> = ReadOptions {
    verify_checksums: false,
    fill_cache: true,
    snapshot: None,
};

const LEVELDB_WRITE_OPTIONS: WriteOptions = WriteOptions { sync: false };

#[derive(Clone)]
pub struct LevelDB {
    db: Arc<_LevelDB>,
}

struct LevelDBSnapshot {
    _db: Arc<_LevelDB>,
    snapshot: _Snapshot<'static>,
}

struct LevelDBIterator<'a> {
    iter: _Iterator<'a>
}

impl From<_Error> for Error {
    fn from(err: _Error) -> Self {
        Error::new(error::Error::description(&err))
    }
}

impl From<io::Error> for Error {
    fn from(err: io::Error) -> Self {
        Error::new(error::Error::description(&err))
    }
}

impl LevelDB {
    // TODO: configurate LRU cache
    pub fn open(path: &Path, options: LevelDBOptions) -> Result<LevelDB> {
        if options.create_if_missing {
            fs::create_dir_all(path)?;
        }
        let database = _LevelDB::open(path, options)?;
        Ok(LevelDB { db: Arc::new(database) })
    }
}

impl Database for LevelDB {
    fn clone(&self) -> Box<Database> {
        Box::new(Clone::clone(self))
    }

    fn snapshot(&self) -> Box<Snapshot> {
        let _p = profiler::ProfilerSpan::new("LevelDB::snapshot");
        Box::new(LevelDBSnapshot {
                     _db: self.db.clone(),
                     snapshot: unsafe { mem::transmute(self.db.snapshot()) },
                 })
    }

    fn merge(&mut self, patch: Patch) -> Result<()> {
        let _p = profiler::ProfilerSpan::new("LevelDB::merge");
        let mut batch = Writebatch::new();
        for (key, change) in patch {
            match change {
                Change::Put(ref v) => batch.put(key, v),
                Change::Delete => batch.delete(key),
            }
        }
        self.db
            .write(LEVELDB_WRITE_OPTIONS, &batch)
            .map_err(Into::into)
    }
}

impl Snapshot for LevelDBSnapshot {
    fn get(&self, key: &[u8]) -> Option<Vec<u8>> {
        let _p = profiler::ProfilerSpan::new("LevelDBSnapshot::get");
        match self.snapshot.get(LEVELDB_READ_OPTIONS, key) {
            Ok(value) => value,
            Err(err) => panic!(err),
        }
    }

    fn iter<'a>(&'a self, from: &[u8]) -> Iter<'a> {
        let _p = profiler::ProfilerSpan::new("LevelDBSnapshot::iter");
        let iter = self.snapshot.iter(LEVELDB_READ_OPTIONS);
        iter.seek(from);
        Box::new(LevelDBIterator { iter: iter })
    }
}

impl<'a> Iterator for LevelDBIterator<'a> {
    type Item = (&'a [u8], &'a [u8]);

    fn next(&mut self) -> Option<Self::Item> {
        let _p = profiler::ProfilerSpan::new("LevelDBIterator::next");
        self.iter.next()
    }
}

impl ::std::fmt::Debug for LevelDB {
    fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result {
        write!(f, "LevelDB(..)")
    }
}

impl ::std::fmt::Debug for LevelDBSnapshot {
    fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result {
        write!(f, "LevelDBSnapshot(..)")
    }
}
<|endoftext|>