<commit_before>extern crate clap;
extern crate adapton_lab;

use std::rc::Rc;
use std::io::BufReader;
use std::io::BufWriter;
use std::io::Write;
use std::io::BufRead;
use std::fs::File;
use std::collections::HashMap;

use adapton_lab::labviz::{Div,WriteHTML};

// Temp: Make this better at some point?
type Graph = HashMap<Rc<String>, Vec<Rc<String>>>;
type NodeSet = HashMap<Rc<String>,()>;

struct St {
    nodes: NodeSet,
    leaves:NodeSet,
    roots: NodeSet,
    graph: Graph,
    edges: Vec<(Rc<String>, Rc<String>)>,
    rev_graph:Graph,
}

impl St {
    fn new() -> Self {
        St {
            nodes: HashMap::new(),
            leaves:HashMap::new(),
            roots: HashMap::new(),
            graph: HashMap::new(),
            edges: Vec::new(),
            rev_graph:HashMap::new()
        }
    }
    fn process_nodes(self:&mut Self) {
        self.leaves=HashMap::new();
        self.roots=HashMap::new();
        for (node,_) in self.nodes.iter() {
            match self.graph.get(node) {
                None => { self.leaves.insert(node.clone(),()); },
                Some(_out) => {}
            };
            match self.rev_graph.get(node) {
                None => { self.roots.insert(node.clone(),()); },
                Some(_out) => {}
            };
        }
    }
    fn add_edge(self:&mut Self, src:Rc<String>, tgt:Rc<String>) {
        self.nodes.insert(src.clone(), ());
        self.nodes.insert(tgt.clone(), ());
        let edge = if false {
            //(Rc::new(v[0].to_string()), Rc::new(v[1].to_string()))
            (src, tgt)
        } else {
            //(Rc::new(v[1].to_string()), Rc::new(v[0].to_string()))
            (tgt, src)
        };
        self.edges.push(edge.clone());

        let inserted : bool = match self.graph.get_mut(&edge.0) {
            None => { false }
            Some(out) => {
                out.push(edge.1.clone());
                true
            },
        };
        if !inserted {
            self.graph.insert(edge.0.clone(), vec![ edge.1.clone() ]);
        };

        let inserted : bool = match self.rev_graph.get_mut(&edge.1) {
            None => { false }
            Some(out) => {
                out.push(edge.0.clone());
                true
            },
        };
        if !inserted {
            self.rev_graph.insert(edge.1, vec![ edge.0 ]);
        };
    }
}

fn main() {
  let args = clap::App::new("dep-viz")
        .version("0.1")
        .author("Matthew Hammer <matthew.hammer@colorado.edu>")
        .about("Consumes Rustc dependency information; Produces visualizations")
        .args_from_usage("\
            -i, --infile=[infile]     'name for input file'
            -o, --outfile=[outfile]   'name for output file'")
    .get_matches();
    let infile_name = args.value_of("infile").unwrap_or("dep_graph.txt");
    let outfile_name = args.value_of("outfile").unwrap_or("dep_graph.html");
    let f = File::open(infile_name).unwrap();
    let file = BufReader::new(&f);
    let mut st = St::new();

    println!("Reading input file: {}", infile_name);
    for (num, line) in file.lines().enumerate() {
        let line = line.unwrap();
        let v: Vec<&str> = line.split(" -> ").map(|s|s.trim()).collect();
        assert_eq!(v.len(), 2);
        st.add_edge(Rc::new(v[0].to_string()),
                    Rc::new(v[1].to_string()));
    }
    println!("...Read input file: {}", infile_name);
    st.process_nodes();
    println!("  Found {} edges", st.edges.len());
    println!("  Found {} nodes", st.nodes.len());
    println!("    Found {} root nodes", st.roots.len());
    println!("    Found {} leaf nodes", st.leaves.len());

    println!("\nPerforming DFS on graph...");
    let mut stack = vec![];
    for (node,_) in st.roots.iter() {
        stack.push(node.clone());
        //break;
    }

    let (div, visited) = dfs(&st.graph, stack);
    println!("...Performed DFS on graph.");
    println!("  Visited {} nodes, {:.1}% of total", visited.len(),
             100f32 * (visited.len() as f32) / (st.nodes.len() as f32));

    println!("\nFinding unvisited graph nodes...");
    let mut unvisited : NodeSet = HashMap::new();
    for (node, _) in st.nodes.iter() {
        if visited.get(node) == None {
            unvisited.insert(node.clone(), ());
            //println!("unvisited: {}", node);
        }
    }
    assert_eq!(visited.len() + unvisited.len(),
               st.nodes.len());
    //println!("...Found graph nodes.");
    println!("...Found {} unvisited graph nodes, {:.1}% of total.",
             unvisited.len(),
             100f32 * (unvisited.len() as f32) / (st.nodes.len() as f32));

    println!("Writing HTML output: {}", outfile_name);
    let mut outfile = File::create(outfile_name).unwrap();
    let mut buf_writer = BufWriter::new(outfile);
    buf_writer.write_all(style_string().as_bytes());
    div.write_html(&mut buf_writer);
    buf_writer.flush();
    println!("..Wrote HTML output: {}", outfile_name);
}

fn dfs (graph: &Graph, stack:Vec<Rc<String>>) -> (Div, NodeSet) {
    let mut visited:NodeSet = HashMap::new();
    let mut divs:Vec<Div> = Vec::new();
    for n in stack.iter() {
        divs.push(dfs_rec(graph, &mut visited, n));
    }
    (Div{tag:"dfs".to_string(),
         classes:vec![],
         extent:Box::new(divs),
         text: None}, visited)
}

fn append_classes_of_node(node:&Rc<String>, mut classes:Vec<String>) -> Vec<String> {
    let cons : Vec<&str> = node.trim().split("(").collect();
    assert!(cons.len() > 0 && cons[0] != "");
    classes.push(cons[0].to_string());
    classes
}

fn append_tooltip(node:&Rc<String>, mut extent:Vec<Div>) -> Vec<Div> {
    extent.insert(0, Div{tag:"tooltip".to_string(),
                         classes:vec![],
                         extent:Box::new(vec![]),
                         text:Some((**node).clone())});
    extent
}

fn dfs_rec (graph: &Graph, visited: &mut NodeSet, node:&Rc<String>) -> Div {
    if visited.get(node) == None {
        visited.insert(node.clone(),());
        match graph.get(node) {
            None => {
                /* Has no children */
                Div{tag:if false {(**node).clone()} else { "".to_string() },
                    classes:append_classes_of_node(node, vec![
                        "node".to_string(),
                        "leaf".to_string(),
                        "no-extent".to_string()
                    ]),
                    extent:Box::new(append_tooltip(node, vec![])),
                    text:None}
            }
            Some(out) => {
                /* Has children */
                let mut divs = vec![];
                for n in out {
                    divs.push(dfs_rec(graph, visited, n))
                }
                Div{tag:if false {(**node).clone()} else { "".to_string() },
                    classes:append_classes_of_node(node, vec![
                        "node".to_string(),
                        "has-extent".to_string()
                    ]),
                    extent:Box::new(append_tooltip(node, divs)),
                    text:None}
            }
        }
    }
    else {
        // Already visited
        Div{tag:if false {(**node).clone()} else { "".to_string() },
            classes:vec![
                "node".to_string(),
                "visited".to_string()
            ],
            extent:Box::new(append_tooltip(node, vec![])),
            text:None}
    }
}

pub fn style_string() -> &'static str {
"
<html>
<head>
<script src=\"https://ajax.googleapis.com/ajax/libs/jquery/3.1.1/jquery.min.js\"></script>

<style>
div {
  display: inline
}
body {
  display: inline;
  color: #aa88cc;
  background: #552266;
  font-family: sans-serif;
  text-decoration: none;
  padding: 0px;
  margin: 0px;
}
body:visited {
  color: #aa88cc;
}
a {
  text-decoration: none;
}
a:hover {
  text-decoration: underline;
}
hr {
  display: block;
  float: left;
  clear: both;
  width: 0px;
  border: none;
}

.node {
  color: black;
  display: inline-block;
  border-style: solid;
  border-color: #221133;
  border-width: 1px;
  background: #aa22ff;
  font-size: 0px;
  padding: 0px;
  margin: 1px;
  border-radius: 5px;
}

.visited {
  border-width: 2px;
}

.no-extent {
  padding: 3px;
}
.tooltip {
  visibility: hidden;
}
.tooltip{
  background-color: #324;
  border-style: solid;
  border-color: #eeeeee;
  border-width: 1px;
  color: #eae;
  text-align: left;
  padding: 5px 0;
  border-radius: 2px;
  font-size: 12px;
  position: absolute;
  z-index: 1;
}
/*
.node:hover {
  border-color: white;
}
*/
.node:active > .tooltip {
  visibility: visible;
}
.WorkProduct {
  border-width: 3px;
  border-color: white;
  background: #999;
}

.MetaData {
  border-color: #000055;
  background: #0000ff;
}
.Hir {
  border-color: #005555;
  background: #00aaff;
}

</style>
</head>
<body>
"
}
<commit_msg>faster load time: dont use tooltip for visited nodes<commit_after>extern crate clap;
extern crate adapton_lab;

use std::rc::Rc;
use std::io::BufReader;
use std::io::BufWriter;
use std::io::Write;
use std::io::BufRead;
use std::fs::File;
use std::collections::HashMap;

use adapton_lab::labviz::{Div,WriteHTML};

// Temp: Make this better at some point?
type Graph = HashMap<Rc<String>, Vec<Rc<String>>>;
type NodeSet = HashMap<Rc<String>,()>;

struct St {
    nodes: NodeSet,
    leaves:NodeSet,
    roots: NodeSet,
    graph: Graph,
    edges: Vec<(Rc<String>, Rc<String>)>,
    rev_graph:Graph,
}

impl St {
    fn new() -> Self {
        St {
            nodes: HashMap::new(),
            leaves:HashMap::new(),
            roots: HashMap::new(),
            graph: HashMap::new(),
            edges: Vec::new(),
            rev_graph:HashMap::new()
        }
    }
    fn process_nodes(self:&mut Self) {
        self.leaves=HashMap::new();
        self.roots=HashMap::new();
        for (node,_) in self.nodes.iter() {
            match self.graph.get(node) {
                None => { self.leaves.insert(node.clone(),()); },
                Some(_out) => {}
            };
            match self.rev_graph.get(node) {
                None => { self.roots.insert(node.clone(),()); },
                Some(_out) => {}
            };
        }
    }
    fn add_edge(self:&mut Self, src:Rc<String>, tgt:Rc<String>) {
        self.nodes.insert(src.clone(), ());
        self.nodes.insert(tgt.clone(), ());
        let edge = if false {
            //(Rc::new(v[0].to_string()), Rc::new(v[1].to_string()))
            (src, tgt)
        } else {
            //(Rc::new(v[1].to_string()), Rc::new(v[0].to_string()))
            (tgt, src)
        };
        self.edges.push(edge.clone());

        let inserted : bool = match self.graph.get_mut(&edge.0) {
            None => { false }
            Some(out) => {
                out.push(edge.1.clone());
                true
            },
        };
        if !inserted {
            self.graph.insert(edge.0.clone(), vec![ edge.1.clone() ]);
        };

        let inserted : bool = match self.rev_graph.get_mut(&edge.1) {
            None => { false }
            Some(out) => {
                out.push(edge.0.clone());
                true
            },
        };
        if !inserted {
            self.rev_graph.insert(edge.1, vec![ edge.0 ]);
        };
    }
}

fn main() {
  let args = clap::App::new("dep-viz")
        .version("0.1")
        .author("Matthew Hammer <matthew.hammer@colorado.edu>")
        .about("Consumes Rustc dependency information; Produces visualizations")
        .args_from_usage("\
            -i, --infile=[infile]     'name for input file'
            -o, --outfile=[outfile]   'name for output file'")
    .get_matches();
    let infile_name = args.value_of("infile").unwrap_or("dep_graph.txt");
    let outfile_name = args.value_of("outfile").unwrap_or("dep_graph.html");
    let f = File::open(infile_name).unwrap();
    let file = BufReader::new(&f);
    let mut st = St::new();

    println!("Reading input file: {}", infile_name);
    for (num, line) in file.lines().enumerate() {
        let line = line.unwrap();
        let v: Vec<&str> = line.split(" -> ").map(|s|s.trim()).collect();
        assert_eq!(v.len(), 2);
        st.add_edge(Rc::new(v[0].to_string()),
                    Rc::new(v[1].to_string()));
    }
    println!("...Read input file: {}", infile_name);
    st.process_nodes();
    println!("  Found {} edges", st.edges.len());
    println!("  Found {} nodes", st.nodes.len());
    println!("    Found {} root nodes", st.roots.len());
    println!("    Found {} leaf nodes", st.leaves.len());

    println!("\nPerforming DFS on graph...");
    let mut stack = vec![];
    for (node,_) in st.roots.iter() {
        stack.push(node.clone());
        //break;
    }

    let (div, visited) = dfs(&st.graph, stack);
    println!("...Performed DFS on graph.");
    println!("  Visited {} nodes, {:.1}% of total", visited.len(),
             100f32 * (visited.len() as f32) / (st.nodes.len() as f32));

    println!("\nFinding unvisited graph nodes...");
    let mut unvisited : NodeSet = HashMap::new();
    for (node, _) in st.nodes.iter() {
        if visited.get(node) == None {
            unvisited.insert(node.clone(), ());
            //println!("unvisited: {}", node);
        }
    }
    assert_eq!(visited.len() + unvisited.len(),
               st.nodes.len());
    //println!("...Found graph nodes.");
    println!("...Found {} unvisited graph nodes, {:.1}% of total.",
             unvisited.len(),
             100f32 * (unvisited.len() as f32) / (st.nodes.len() as f32));

    println!("Writing HTML output: {}", outfile_name);
    let mut outfile = File::create(outfile_name).unwrap();
    let mut buf_writer = BufWriter::new(outfile);
    buf_writer.write_all(style_string().as_bytes());
    div.write_html(&mut buf_writer);
    buf_writer.flush();
    println!("..Wrote HTML output: {}", outfile_name);
}

fn dfs (graph: &Graph, stack:Vec<Rc<String>>) -> (Div, NodeSet) {
    let mut visited:NodeSet = HashMap::new();
    let mut divs:Vec<Div> = Vec::new();
    for n in stack.iter() {
        divs.push(dfs_rec(graph, &mut visited, n));
        //if visited.len() > 10000 { break } else { continue }
    }
    (Div{tag:"dfs".to_string(),
         classes:vec![],
         extent:Box::new(divs),
         text: None}, visited)
}

fn cons_of_node_name(node:&Rc<String>) -> String {
    let cons : Vec<&str> = node.trim().split("(").collect();
    assert!(cons.len() > 0 && cons[0] != "");
    cons[0].to_string()
}

fn append_classes_of_node(node:&Rc<String>, mut classes:Vec<String>) -> Vec<String> {
    classes.push(cons_of_node_name(node));
    classes
}

fn append_tooltip(node:&Rc<String>, mut extent:Vec<Div>) -> Vec<Div> {
    extent.insert(0, Div{tag:"tooltip".to_string(),
                         classes:vec![],
                         extent:Box::new(vec![]),
                         //text:Some((**node).clone())
                         text:Some(cons_of_node_name(node)),
    });
    extent
}

fn dfs_rec (graph: &Graph, visited: &mut NodeSet, node:&Rc<String>) -> Div {
    if visited.get(node) == None {
        visited.insert(node.clone(),());
        match graph.get(node) {
            None => {
                /* Has no children */
                Div{tag:if false {(**node).clone()} else { "".to_string() },
                    classes:append_classes_of_node(node, vec![
                        "node".to_string(),
                        "no-extent".to_string()
                    ]),
                    extent:Box::new(append_tooltip(node, vec![])),
                    text:None}
            }
            Some(out) => {
                /* Has children */
                let mut divs = vec![];
                for n in out {
                    divs.push(dfs_rec(graph, visited, n))
                }
                Div{tag:if false {(**node).clone()} else { "".to_string() },
                    classes:append_classes_of_node(node, vec![
                        "node".to_string()
                    ]),
                    extent:Box::new(append_tooltip(node, divs)),
                    text:None}
            }
        }
    }
    else {
        // Already visited
        Div{tag:if false {(**node).clone()} else { "".to_string() },
            classes:vec![
                "node".to_string(),
                "visited".to_string()
            ],
            //extent:Box::new(append_tooltip(node, vec![])),
            extent:Box::new(vec![]),
            text:None}
    }
}

pub fn style_string() -> &'static str {
"
<html>
<head>
<script src=\"https://ajax.googleapis.com/ajax/libs/jquery/3.1.1/jquery.min.js\"></script>

<style>
div {
  display: inline
}
body {
  display: inline;
  color: #aa88cc;
  background: #552266;
  font-family: sans-serif;
  text-decoration: none;
  padding: 0px;
  margin: 0px;
}
body:visited {
  color: #aa88cc;
}
a {
  text-decoration: none;
}
a:hover {
  text-decoration: underline;
}
hr {
  display: block;
  float: left;
  clear: both;
  width: 0px;
  border: none;
}

.node {
  color: black;
  display: inline-block;
  border-style: solid;
  border-color: #221133;
  border-width: 1px;
  background: #aa22ff;
  font-size: 0px;
  padding: 0px;
  margin: 1px;
  border-radius: 5px;
}

.visited {
  border-width: 2px;
}

.no-extent {
  padding: 3px;
}
.tooltip {
  visibility: hidden;
  background-color: #324;
  border-style: solid;
  border-color: #eeeeee;
  border-width: 1px;
  color: #eae;
  text-align: left;
  padding: 5px 0;
  border-radius: 2px;
  font-size: 12px;
  position: absolute;
  z-index: 1;
}
.node:hover {
  border-color: white;
}
.node:hover > .tooltip {
  visibility: visible;
}

.WorkProduct {
  border-width: 3px;
  border-color: white;
  background: #999;
}

.MetaData {
  border-color: #000055;
  background: #0000ff;
}

.Hir {
  border-color: #005555;
  background: #00aaff;
}

</style>
</head>
<body>
"
}
<|endoftext|>


<commit_before>/* This file is part of Grust, GObject introspection bindings for Rust
 *
 * Copyright (C) 2013  Mikhail Zabaluev <mikhail.zabaluev@gmail.com>
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
 * 02110-1301  USA
 */

use ffi;
use plumbing::GMainLoop;

pub struct EventLoop {
    priv raw: *GMainLoop
}

impl EventLoop {
    pub fn new() -> EventLoop {
        unsafe {
            EventLoop { raw: ffi::grustna_main_loop_new_thread_local() }
        }
    }

    pub fn run(&self) {
        unsafe {
            ffi::grustna_main_loop_run_thread_local(self.raw);
        }
    }

    pub fn quit(&self) {
        unsafe {
            ffi::g_main_loop_quit(self.raw);
        }
    }
}

#[unsafe_destructor]
impl Drop for EventLoop {
    fn finalize(&self) {
        unsafe {
            ffi::g_main_loop_unref(self.raw);
        }
    }
}

impl Clone for EventLoop {
    fn clone(&self) -> EventLoop {
        unsafe {
            ffi::g_main_loop_ref(self.raw);
            EventLoop { raw: self.raw }
        }
    }
}
<commit_msg>Declared run method of EventLoop unsafe<commit_after>/* This file is part of Grust, GObject introspection bindings for Rust
 *
 * Copyright (C) 2013  Mikhail Zabaluev <mikhail.zabaluev@gmail.com>
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
 * 02110-1301  USA
 */

use ffi;
use plumbing::GMainLoop;

pub struct EventLoop {
    priv raw: *GMainLoop
}

impl EventLoop {
    pub fn new() -> EventLoop {
        unsafe {
            EventLoop { raw: ffi::grustna_main_loop_new_thread_local() }
        }
    }

    pub unsafe fn run(&self) {
        ffi::grustna_main_loop_run_thread_local(self.raw);
    }

    pub fn quit(&self) {
        unsafe {
            ffi::g_main_loop_quit(self.raw);
        }
    }
}

#[unsafe_destructor]
impl Drop for EventLoop {
    fn finalize(&self) {
        unsafe {
            ffi::g_main_loop_unref(self.raw);
        }
    }
}

impl Clone for EventLoop {
    fn clone(&self) -> EventLoop {
        unsafe {
            ffi::g_main_loop_ref(self.raw);
            EventLoop { raw: self.raw }
        }
    }
}
<|endoftext|>


<commit_before>use syn;
use quote;

use model::{infer_association_name, Model};
use util::{str_value_of_meta_item, wrap_item_in_const};

pub fn derive_associations(input: syn::DeriveInput) -> quote::Tokens {
    let model = t!(Model::from_item(&input, "Associations"));

    let derived_associations = input
        .attrs
        .as_slice()
        .iter()
        .filter_map(|attr| {
            if attr.name() == "belongs_to" {
                Some(
                    build_association_options(attr)
                        .map(|options| expand_belongs_to(&model, options))
                        .unwrap_or_else(|e| e),
                )
            } else {
                None
            }
        })
        .collect::<Vec<_>>();
    if derived_associations.is_empty() {
        quote!(compile_error!("Could not derive `Associations` without any `#[belongs_to(table_name)]` attribute");)
    } else {
        wrap_item_in_const(
            model.dummy_const_name("ASSOCIATIONS"),
            quote!(#(#derived_associations)*),
        )
    }
}

fn expand_belongs_to(model: &Model, options: AssociationOptions) -> quote::Tokens {
    let parent_struct = options.name;
    let struct_name = &model.name;
    let fields = model.attrs.as_slice();

    let foreign_key_name = options
        .foreign_key_name
        .unwrap_or_else(|| to_foreign_key(parent_struct.as_ref()));
    let child_table_name = model.table_name();
    let child_table_name = &child_table_name;
    let foreign_key_attr = fields
        .iter()
        .find(|attr| *attr.column_name() == foreign_key_name);
    let foreign_key_ty = if let Some(foreign_key_attr) = foreign_key_attr {
        &foreign_key_attr.ty
    } else {
        let msg = format!("No field found that corresponds to the column {}", foreign_key_name);
        return quote!{
            compile_error!(#msg);
        };
    };

    // we need to special case foreign keys on with an Option type
    // to allow self referencing joins
    let (foreign_key, foreign_key_ty) = ::util::inner_of_option_ty(foreign_key_ty)
        .map(|foreign_key_ty| (quote!(self.#foreign_key_name.as_ref()), foreign_key_ty))
        .unwrap_or_else(|| (quote!(Some(&self.#foreign_key_name)), foreign_key_ty));

    quote!(
        impl diesel::associations::BelongsTo<#parent_struct> for #struct_name {
            type ForeignKey = #foreign_key_ty;
            type ForeignKeyColumn = #child_table_name::#foreign_key_name;

            fn foreign_key(&self) -> Option<&Self::ForeignKey> {
                #foreign_key
            }

            fn foreign_key_column() -> Self::ForeignKeyColumn {
                #child_table_name::#foreign_key_name
            }
        }
    )
}

struct AssociationOptions {
    name: syn::Ident,
    foreign_key_name: Option<syn::Ident>,
}

fn build_association_options(attr: &syn::Attribute) -> Result<AssociationOptions, quote::Tokens> {
    let usage_error = Err(quote!(
        compile_error!("`#[belongs_to]` must be in the form `#[belongs_to(table_name, foreign_key=\"column_name\")]`")
    ));
    match attr.value {
        syn::MetaItem::List(_, ref options) if options.len() >= 1 => {
            let association_name = match options[0] {
                syn::NestedMetaItem::MetaItem(syn::MetaItem::Word(ref name)) => name.clone(),
                _ => return usage_error,
            };
            let foreign_key_name = options
                .iter()
                .filter_map(|o| match *o {
                    syn::NestedMetaItem::MetaItem(ref mi) => Some(mi),
                    _ => None,
                })
                .find(|a| a.name() == "foreign_key")
                .map(|a| str_value_of_meta_item(a, "foreign_key"))
                .map(syn::Ident::new);
            if options.len() == 1 || (options.len() == 2 && foreign_key_name.is_some()) {
                Ok(AssociationOptions {
                    name: association_name,
                    foreign_key_name: foreign_key_name,
                })
            } else {
                usage_error
            }
        }
        _ => usage_error,
    }
}

fn to_foreign_key(model_name: &str) -> syn::Ident {
    let lower_cased = infer_association_name(model_name);
    syn::Ident::new(format!("{}_id", &lower_cased))
}
<commit_msg>Run rustfmt<commit_after>use syn;
use quote;

use model::{infer_association_name, Model};
use util::{str_value_of_meta_item, wrap_item_in_const};

pub fn derive_associations(input: syn::DeriveInput) -> quote::Tokens {
    let model = t!(Model::from_item(&input, "Associations"));

    let derived_associations = input
        .attrs
        .as_slice()
        .iter()
        .filter_map(|attr| {
            if attr.name() == "belongs_to" {
                Some(
                    build_association_options(attr)
                        .map(|options| expand_belongs_to(&model, options))
                        .unwrap_or_else(|e| e),
                )
            } else {
                None
            }
        })
        .collect::<Vec<_>>();
    if derived_associations.is_empty() {
        quote!(compile_error!("Could not derive `Associations` without any `#[belongs_to(table_name)]` attribute");)
    } else {
        wrap_item_in_const(
            model.dummy_const_name("ASSOCIATIONS"),
            quote!(#(#derived_associations)*),
        )
    }
}

fn expand_belongs_to(model: &Model, options: AssociationOptions) -> quote::Tokens {
    let parent_struct = options.name;
    let struct_name = &model.name;
    let fields = model.attrs.as_slice();

    let foreign_key_name = options
        .foreign_key_name
        .unwrap_or_else(|| to_foreign_key(parent_struct.as_ref()));
    let child_table_name = model.table_name();
    let child_table_name = &child_table_name;
    let foreign_key_attr = fields
        .iter()
        .find(|attr| *attr.column_name() == foreign_key_name);
    let foreign_key_ty = if let Some(foreign_key_attr) = foreign_key_attr {
        &foreign_key_attr.ty
    } else {
        let msg = format!(
            "No field found that corresponds to the column {}",
            foreign_key_name
        );
        return quote!{
            compile_error!(#msg);
        };
    };

    // we need to special case foreign keys on with an Option type
    // to allow self referencing joins
    let (foreign_key, foreign_key_ty) = ::util::inner_of_option_ty(foreign_key_ty)
        .map(|foreign_key_ty| (quote!(self.#foreign_key_name.as_ref()), foreign_key_ty))
        .unwrap_or_else(|| (quote!(Some(&self.#foreign_key_name)), foreign_key_ty));

    quote!(
        impl diesel::associations::BelongsTo<#parent_struct> for #struct_name {
            type ForeignKey = #foreign_key_ty;
            type ForeignKeyColumn = #child_table_name::#foreign_key_name;

            fn foreign_key(&self) -> Option<&Self::ForeignKey> {
                #foreign_key
            }

            fn foreign_key_column() -> Self::ForeignKeyColumn {
                #child_table_name::#foreign_key_name
            }
        }
    )
}

struct AssociationOptions {
    name: syn::Ident,
    foreign_key_name: Option<syn::Ident>,
}

fn build_association_options(attr: &syn::Attribute) -> Result<AssociationOptions, quote::Tokens> {
    let usage_error = Err(quote!(
        compile_error!("`#[belongs_to]` must be in the form `#[belongs_to(table_name, foreign_key=\"column_name\")]`")
    ));
    match attr.value {
        syn::MetaItem::List(_, ref options) if options.len() >= 1 => {
            let association_name = match options[0] {
                syn::NestedMetaItem::MetaItem(syn::MetaItem::Word(ref name)) => name.clone(),
                _ => return usage_error,
            };
            let foreign_key_name = options
                .iter()
                .filter_map(|o| match *o {
                    syn::NestedMetaItem::MetaItem(ref mi) => Some(mi),
                    _ => None,
                })
                .find(|a| a.name() == "foreign_key")
                .map(|a| str_value_of_meta_item(a, "foreign_key"))
                .map(syn::Ident::new);
            if options.len() == 1 || (options.len() == 2 && foreign_key_name.is_some()) {
                Ok(AssociationOptions {
                    name: association_name,
                    foreign_key_name: foreign_key_name,
                })
            } else {
                usage_error
            }
        }
        _ => usage_error,
    }
}

fn to_foreign_key(model_name: &str) -> syn::Ident {
    let lower_cased = infer_association_name(model_name);
    syn::Ident::new(format!("{}_id", &lower_cased))
}
<|endoftext|>


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

use std::fs::File;
use std::path::{Path, PathBuf};

use api::{CaptureBits, ExternalImageData, ImageDescriptor};
#[cfg(feature = "png")]
use api::ImageFormat;
use api::units::TexelRect;
#[cfg(feature = "png")]
use api::units::DeviceIntSize;
#[cfg(feature = "capture")]
use crate::print_tree::{PrintableTree, PrintTree};
use ron;
use serde;

#[derive(Clone)]
pub struct CaptureConfig {
    pub root: PathBuf,
    pub bits: CaptureBits,
    /// Scene sequence ID when capturing multiple frames. Zero for a single frame capture.
    pub scene_id: u32,
    /// Frame sequence ID when capturing multiple frames. Zero for a single frame capture.
    pub frame_id: u32,
    /// Resource sequence ID when capturing multiple frames. Zero for a single frame capture.
    pub resource_id: u32,
    #[cfg(feature = "capture")]
    pretty: ron::ser::PrettyConfig,
}

impl CaptureConfig {
    #[cfg(any(feature = "capture", feature = "replay"))]
    pub fn new(root: PathBuf, bits: CaptureBits) -> Self {
        CaptureConfig {
            root,
            bits,
            scene_id: 0,
            frame_id: 0,
            resource_id: 0,
            #[cfg(feature = "capture")]
            pretty: ron::ser::PrettyConfig {
                enumerate_arrays: true,
                .. ron::ser::PrettyConfig::default()
            },
        }
    }

    #[cfg(feature = "capture")]
    pub fn prepare_scene(&mut self) {
        use std::fs::create_dir_all;
        self.scene_id += 1;
        let _ = create_dir_all(&self.scene_root());
    }

    #[cfg(feature = "capture")]
    pub fn prepare_frame(&mut self) {
        use std::fs::create_dir_all;
        self.frame_id += 1;
        let _ = create_dir_all(&self.frame_root());
    }

    #[cfg(feature = "capture")]
    pub fn prepare_resource(&mut self) {
        use std::fs::create_dir_all;
        self.resource_id += 1;
        let _ = create_dir_all(&self.resource_root());
    }

    #[cfg(any(feature = "capture", feature = "replay"))]
    pub fn scene_root(&self) -> PathBuf {
        if self.scene_id > 0 {
            let path = format!("scenes/{:05}", self.scene_id);
            self.root.join(path)
        } else {
            self.root.clone()
        }
    }

    #[cfg(any(feature = "capture", feature = "replay"))]
    pub fn frame_root(&self) -> PathBuf {
        if self.frame_id > 0 {
            let path = format!("frames/{:05}", self.frame_id);
            self.scene_root().join(path)
        } else {
            self.root.clone()
        }
    }

    #[cfg(any(feature = "capture", feature = "replay"))]
    pub fn resource_root(&self) -> PathBuf {
        if self.resource_id > 0 {
            let path = format!("resources/{:05}", self.resource_id);
            self.root.join(path)
        } else {
            self.root.clone()
        }
    }

    #[cfg(feature = "capture")]
    pub fn serialize_for_scene<T, P>(&self, data: &T, name: P)
    where
        T: serde::Serialize,
        P: AsRef<Path>,
    {
        self.serialize(data, self.scene_root(), name)
    }

    #[cfg(feature = "capture")]
    pub fn serialize_for_frame<T, P>(&self, data: &T, name: P)
    where
        T: serde::Serialize,
        P: AsRef<Path>,
    {
        self.serialize(data, self.frame_root(), name)
    }

    #[cfg(feature = "capture")]
    pub fn serialize_for_resource<T, P>(&self, data: &T, name: P)
    where
        T: serde::Serialize,
        P: AsRef<Path>,
    {
        self.serialize(data, self.resource_root(), name)
    }

    #[cfg(feature = "capture")]
    pub fn file_path_for_frame<P>(&self, name: P, ext: &str) -> PathBuf
    where P: AsRef<Path> {
        self.frame_root().join(name).with_extension(ext)
    }

    #[cfg(feature = "capture")]
    fn serialize<T, P>(&self, data: &T, path: PathBuf, name: P)
    where
        T: serde::Serialize,
        P: AsRef<Path>,
    {
        use std::io::Write;
        let ron = ron::ser::to_string_pretty(data, self.pretty.clone())
            .unwrap();
        let mut file = File::create(path.join(name).with_extension("ron"))
            .unwrap();
        write!(file, "{}\n", ron)
            .unwrap();
    }

    #[cfg(feature = "capture")]
    fn serialize_tree<T, P>(data: &T, root: PathBuf, name: P)
    where
        T: PrintableTree,
        P: AsRef<Path>
    {
        let path = root
            .join(name)
            .with_extension("tree");
        let file = File::create(path)
            .unwrap();
        let mut pt = PrintTree::new_with_sink("", file);
        data.print_with(&mut pt);
    }

    #[cfg(feature = "capture")]
    pub fn serialize_tree_for_frame<T, P>(&self, data: &T, name: P)
    where
        T: PrintableTree,
        P: AsRef<Path>
    {
        Self::serialize_tree(data, self.frame_root(), name)
    }

    #[cfg(feature = "replay")]
    fn deserialize<T, P>(root: &PathBuf, name: P) -> Option<T>
    where
        T: for<'a> serde::Deserialize<'a>,
        P: AsRef<Path>,
    {
        use std::io::Read;

        let mut string = String::new();
        let path = root
            .join(name.as_ref())
            .with_extension("ron");
        File::open(path)
            .ok()?
            .read_to_string(&mut string)
            .unwrap();
        match ron::de::from_str(&string) {
            Ok(out) => Some(out),
            Err(e) => panic!("File {:?} deserialization failed: {:?}", name.as_ref(), e),
        }
    }

    #[cfg(feature = "replay")]
    pub fn deserialize_for_scene<T, P>(&self, name: P) -> Option<T>
    where
        T: for<'a> serde::Deserialize<'a>,
        P: AsRef<Path>,
    {
        Self::deserialize(&self.scene_root(), name)
    }

    #[cfg(feature = "replay")]
    pub fn deserialize_for_frame<T, P>(&self, name: P) -> Option<T>
    where
        T: for<'a> serde::Deserialize<'a>,
        P: AsRef<Path>,
    {
        Self::deserialize(&self.frame_root(), name)
    }

    #[cfg(feature = "replay")]
    pub fn deserialize_for_resource<T, P>(&self, name: P) -> Option<T>
    where
        T: for<'a> serde::Deserialize<'a>,
        P: AsRef<Path>,
    {
        Self::deserialize(&self.resource_root(), name)
    }

    #[cfg(feature = "png")]
    pub fn save_png(
        path: PathBuf, size: DeviceIntSize, format: ImageFormat, stride: Option<i32>, data: &[u8],
    ) {
        use png::{BitDepth, ColorType, Encoder};
        use std::io::BufWriter;
        use std::borrow::Cow;

        // `png` expects
        let data = match stride {
            Some(stride) if stride != format.bytes_per_pixel() * size.width => {
                let mut unstrided = Vec::new();
                for y in 0..size.height {
                    let start = (y * stride) as usize;
                    unstrided.extend_from_slice(&data[start..start+(size.width * format.bytes_per_pixel()) as usize]);
                }
                Cow::from(unstrided)
            }
            _ => Cow::from(data),
        };

        let color_type = match format {
            ImageFormat::RGBA8 => ColorType::RGBA,
            ImageFormat::BGRA8 => {
                warn!("Unable to swizzle PNG of BGRA8 type");
                ColorType::RGBA
            },
            ImageFormat::R8 => ColorType::Grayscale,
            ImageFormat::RG8 => ColorType::GrayscaleAlpha,
            _ => {
                error!("Unable to save PNG of {:?}", format);
                return;
            }
        };
        let w = BufWriter::new(File::create(path).unwrap());
        let mut enc = Encoder::new(w, size.width as u32, size.height as u32);
        enc.set_color(color_type);
        enc.set_depth(BitDepth::Eight);
        enc
            .write_header()
            .unwrap()
            .write_image_data(&*data)
            .unwrap();
    }
}

/// An image that `ResourceCache` is unable to resolve during a capture.
/// The image has to be transferred to `Renderer` and locked with the
/// external image handler to get the actual contents and serialize them.
#[derive(Deserialize, Serialize)]
pub struct ExternalCaptureImage {
    pub short_path: String,
    pub descriptor: ImageDescriptor,
    pub external: ExternalImageData,
}

/// A short description of an external image to be saved separately as
/// "externals/XX.ron", redirecting into a specific texture/blob with
/// the corresponding UV rectangle.
#[derive(Deserialize, Serialize)]
pub struct PlainExternalImage {
    /// Path to the RON file describing the texel data.
    pub data: String,
    /// External image data source.
    pub external: ExternalImageData,
    /// UV sub-rectangle of the image.
    pub uv: TexelRect,
}
<commit_msg>Bug 1662042 - Shrink RON indents in WebRender captures from 4 spaces to 1 space. r=gw<commit_after>/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

use std::fs::File;
use std::path::{Path, PathBuf};

use api::{CaptureBits, ExternalImageData, ImageDescriptor};
#[cfg(feature = "png")]
use api::ImageFormat;
use api::units::TexelRect;
#[cfg(feature = "png")]
use api::units::DeviceIntSize;
#[cfg(feature = "capture")]
use crate::print_tree::{PrintableTree, PrintTree};
use ron;
use serde;

#[derive(Clone)]
pub struct CaptureConfig {
    pub root: PathBuf,
    pub bits: CaptureBits,
    /// Scene sequence ID when capturing multiple frames. Zero for a single frame capture.
    pub scene_id: u32,
    /// Frame sequence ID when capturing multiple frames. Zero for a single frame capture.
    pub frame_id: u32,
    /// Resource sequence ID when capturing multiple frames. Zero for a single frame capture.
    pub resource_id: u32,
    #[cfg(feature = "capture")]
    pretty: ron::ser::PrettyConfig,
}

impl CaptureConfig {
    #[cfg(any(feature = "capture", feature = "replay"))]
    pub fn new(root: PathBuf, bits: CaptureBits) -> Self {
        CaptureConfig {
            root,
            bits,
            scene_id: 0,
            frame_id: 0,
            resource_id: 0,
            #[cfg(feature = "capture")]
            pretty: ron::ser::PrettyConfig {
                enumerate_arrays: true,
                indentor: " ".to_string(),
                .. ron::ser::PrettyConfig::default()
            },
        }
    }

    #[cfg(feature = "capture")]
    pub fn prepare_scene(&mut self) {
        use std::fs::create_dir_all;
        self.scene_id += 1;
        let _ = create_dir_all(&self.scene_root());
    }

    #[cfg(feature = "capture")]
    pub fn prepare_frame(&mut self) {
        use std::fs::create_dir_all;
        self.frame_id += 1;
        let _ = create_dir_all(&self.frame_root());
    }

    #[cfg(feature = "capture")]
    pub fn prepare_resource(&mut self) {
        use std::fs::create_dir_all;
        self.resource_id += 1;
        let _ = create_dir_all(&self.resource_root());
    }

    #[cfg(any(feature = "capture", feature = "replay"))]
    pub fn scene_root(&self) -> PathBuf {
        if self.scene_id > 0 {
            let path = format!("scenes/{:05}", self.scene_id);
            self.root.join(path)
        } else {
            self.root.clone()
        }
    }

    #[cfg(any(feature = "capture", feature = "replay"))]
    pub fn frame_root(&self) -> PathBuf {
        if self.frame_id > 0 {
            let path = format!("frames/{:05}", self.frame_id);
            self.scene_root().join(path)
        } else {
            self.root.clone()
        }
    }

    #[cfg(any(feature = "capture", feature = "replay"))]
    pub fn resource_root(&self) -> PathBuf {
        if self.resource_id > 0 {
            let path = format!("resources/{:05}", self.resource_id);
            self.root.join(path)
        } else {
            self.root.clone()
        }
    }

    #[cfg(feature = "capture")]
    pub fn serialize_for_scene<T, P>(&self, data: &T, name: P)
    where
        T: serde::Serialize,
        P: AsRef<Path>,
    {
        self.serialize(data, self.scene_root(), name)
    }

    #[cfg(feature = "capture")]
    pub fn serialize_for_frame<T, P>(&self, data: &T, name: P)
    where
        T: serde::Serialize,
        P: AsRef<Path>,
    {
        self.serialize(data, self.frame_root(), name)
    }

    #[cfg(feature = "capture")]
    pub fn serialize_for_resource<T, P>(&self, data: &T, name: P)
    where
        T: serde::Serialize,
        P: AsRef<Path>,
    {
        self.serialize(data, self.resource_root(), name)
    }

    #[cfg(feature = "capture")]
    pub fn file_path_for_frame<P>(&self, name: P, ext: &str) -> PathBuf
    where P: AsRef<Path> {
        self.frame_root().join(name).with_extension(ext)
    }

    #[cfg(feature = "capture")]
    fn serialize<T, P>(&self, data: &T, path: PathBuf, name: P)
    where
        T: serde::Serialize,
        P: AsRef<Path>,
    {
        use std::io::Write;
        let ron = ron::ser::to_string_pretty(data, self.pretty.clone())
            .unwrap();
        let mut file = File::create(path.join(name).with_extension("ron"))
            .unwrap();
        write!(file, "{}\n", ron)
            .unwrap();
    }

    #[cfg(feature = "capture")]
    fn serialize_tree<T, P>(data: &T, root: PathBuf, name: P)
    where
        T: PrintableTree,
        P: AsRef<Path>
    {
        let path = root
            .join(name)
            .with_extension("tree");
        let file = File::create(path)
            .unwrap();
        let mut pt = PrintTree::new_with_sink("", file);
        data.print_with(&mut pt);
    }

    #[cfg(feature = "capture")]
    pub fn serialize_tree_for_frame<T, P>(&self, data: &T, name: P)
    where
        T: PrintableTree,
        P: AsRef<Path>
    {
        Self::serialize_tree(data, self.frame_root(), name)
    }

    #[cfg(feature = "replay")]
    fn deserialize<T, P>(root: &PathBuf, name: P) -> Option<T>
    where
        T: for<'a> serde::Deserialize<'a>,
        P: AsRef<Path>,
    {
        use std::io::Read;

        let mut string = String::new();
        let path = root
            .join(name.as_ref())
            .with_extension("ron");
        File::open(path)
            .ok()?
            .read_to_string(&mut string)
            .unwrap();
        match ron::de::from_str(&string) {
            Ok(out) => Some(out),
            Err(e) => panic!("File {:?} deserialization failed: {:?}", name.as_ref(), e),
        }
    }

    #[cfg(feature = "replay")]
    pub fn deserialize_for_scene<T, P>(&self, name: P) -> Option<T>
    where
        T: for<'a> serde::Deserialize<'a>,
        P: AsRef<Path>,
    {
        Self::deserialize(&self.scene_root(), name)
    }

    #[cfg(feature = "replay")]
    pub fn deserialize_for_frame<T, P>(&self, name: P) -> Option<T>
    where
        T: for<'a> serde::Deserialize<'a>,
        P: AsRef<Path>,
    {
        Self::deserialize(&self.frame_root(), name)
    }

    #[cfg(feature = "replay")]
    pub fn deserialize_for_resource<T, P>(&self, name: P) -> Option<T>
    where
        T: for<'a> serde::Deserialize<'a>,
        P: AsRef<Path>,
    {
        Self::deserialize(&self.resource_root(), name)
    }

    #[cfg(feature = "png")]
    pub fn save_png(
        path: PathBuf, size: DeviceIntSize, format: ImageFormat, stride: Option<i32>, data: &[u8],
    ) {
        use png::{BitDepth, ColorType, Encoder};
        use std::io::BufWriter;
        use std::borrow::Cow;

        // `png` expects
        let data = match stride {
            Some(stride) if stride != format.bytes_per_pixel() * size.width => {
                let mut unstrided = Vec::new();
                for y in 0..size.height {
                    let start = (y * stride) as usize;
                    unstrided.extend_from_slice(&data[start..start+(size.width * format.bytes_per_pixel()) as usize]);
                }
                Cow::from(unstrided)
            }
            _ => Cow::from(data),
        };

        let color_type = match format {
            ImageFormat::RGBA8 => ColorType::RGBA,
            ImageFormat::BGRA8 => {
                warn!("Unable to swizzle PNG of BGRA8 type");
                ColorType::RGBA
            },
            ImageFormat::R8 => ColorType::Grayscale,
            ImageFormat::RG8 => ColorType::GrayscaleAlpha,
            _ => {
                error!("Unable to save PNG of {:?}", format);
                return;
            }
        };
        let w = BufWriter::new(File::create(path).unwrap());
        let mut enc = Encoder::new(w, size.width as u32, size.height as u32);
        enc.set_color(color_type);
        enc.set_depth(BitDepth::Eight);
        enc
            .write_header()
            .unwrap()
            .write_image_data(&*data)
            .unwrap();
    }
}

/// An image that `ResourceCache` is unable to resolve during a capture.
/// The image has to be transferred to `Renderer` and locked with the
/// external image handler to get the actual contents and serialize them.
#[derive(Deserialize, Serialize)]
pub struct ExternalCaptureImage {
    pub short_path: String,
    pub descriptor: ImageDescriptor,
    pub external: ExternalImageData,
}

/// A short description of an external image to be saved separately as
/// "externals/XX.ron", redirecting into a specific texture/blob with
/// the corresponding UV rectangle.
#[derive(Deserialize, Serialize)]
pub struct PlainExternalImage {
    /// Path to the RON file describing the texel data.
    pub data: String,
    /// External image data source.
    pub external: ExternalImageData,
    /// UV sub-rectangle of the image.
    pub uv: TexelRect,
}
<|endoftext|>


<commit_before>use crate::utils::is_type_diagnostic_item;
use rustc_hir as hir;
use rustc_lint::LateContext;
use rustc_middle::ty;
use rustc_middle::ty::Ty;
use rustc_span::symbol::sym;

pub fn derefs_to_slice<'tcx>(
    cx: &LateContext<'tcx>,
    expr: &'tcx hir::Expr<'tcx>,
    ty: Ty<'tcx>,
) -> Option<&'tcx hir::Expr<'tcx>> {
    fn may_slice<'a>(cx: &LateContext<'a>, ty: Ty<'a>) -> bool {
        match ty.kind() {
            ty::Slice(_) => true,
            ty::Adt(def, _) if def.is_box() => may_slice(cx, ty.boxed_ty()),
            ty::Adt(..) => is_type_diagnostic_item(cx, ty, sym::vec_type),
            ty::Array(_, size) => size
                .try_eval_usize(cx.tcx, cx.param_env)
                .map_or(false, |size| size < 32),
            ty::Ref(_, inner, _) => may_slice(cx, inner),
            _ => false,
        }
    }

    if let hir::ExprKind::MethodCall(ref path, _, ref args, _) = expr.kind {
        if path.ident.name == sym::iter && may_slice(cx, cx.typeck_results().expr_ty(&args[0])) {
            Some(&args[0])
        } else {
            None
        }
    } else {
        match ty.kind() {
            ty::Slice(_) => Some(expr),
            ty::Adt(def, _) if def.is_box() && may_slice(cx, ty.boxed_ty()) => Some(expr),
            ty::Ref(_, inner, _) => {
                if may_slice(cx, inner) {
                    Some(expr)
                } else {
                    None
                }
            },
            _ => None,
        }
    }
}
<commit_msg>use clippy_utils::ty::is_type_diagnostic_item<commit_after>use clippy_utils::ty::is_type_diagnostic_item;
use rustc_hir as hir;
use rustc_lint::LateContext;
use rustc_middle::ty;
use rustc_middle::ty::Ty;
use rustc_span::symbol::sym;

pub fn derefs_to_slice<'tcx>(
    cx: &LateContext<'tcx>,
    expr: &'tcx hir::Expr<'tcx>,
    ty: Ty<'tcx>,
) -> Option<&'tcx hir::Expr<'tcx>> {
    fn may_slice<'a>(cx: &LateContext<'a>, ty: Ty<'a>) -> bool {
        match ty.kind() {
            ty::Slice(_) => true,
            ty::Adt(def, _) if def.is_box() => may_slice(cx, ty.boxed_ty()),
            ty::Adt(..) => is_type_diagnostic_item(cx, ty, sym::vec_type),
            ty::Array(_, size) => size
                .try_eval_usize(cx.tcx, cx.param_env)
                .map_or(false, |size| size < 32),
            ty::Ref(_, inner, _) => may_slice(cx, inner),
            _ => false,
        }
    }

    if let hir::ExprKind::MethodCall(ref path, _, ref args, _) = expr.kind {
        if path.ident.name == sym::iter && may_slice(cx, cx.typeck_results().expr_ty(&args[0])) {
            Some(&args[0])
        } else {
            None
        }
    } else {
        match ty.kind() {
            ty::Slice(_) => Some(expr),
            ty::Adt(def, _) if def.is_box() && may_slice(cx, ty.boxed_ty()) => Some(expr),
            ty::Ref(_, inner, _) => {
                if may_slice(cx, inner) {
                    Some(expr)
                } else {
                    None
                }
            },
            _ => None,
        }
    }
}
<|endoftext|>


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

#![crate_id = "github.com/mozilla/servo#script:0.1"]
#![crate_type = "lib"]
#![crate_type = "dylib"]
#![crate_type = "rlib"]

#![comment = "The Servo Parallel Browser Project"]
#![license = "MPL"]

#![feature(globs, macro_rules, struct_variant, phase)]

#![feature(phase)]
#[phase(syntax, link)]
extern crate log;

extern crate collections;
extern crate geom;
extern crate hubbub;
extern crate encoding;
extern crate js;
extern crate libc;
extern crate native;
extern crate serialize;
extern crate time;
#[phase(syntax)]
extern crate servo_macros = "macros";
extern crate servo_net = "net";
extern crate servo_util = "util";
extern crate style;
extern crate servo_msg = "msg";
extern crate url;

pub mod dom {
    pub mod bindings {
        pub mod js;
        pub mod element;
        pub mod utils;
        pub mod callback;
        pub mod error;
        pub mod conversions;
        pub mod proxyhandler;
        pub mod trace;
        pub mod codegen {
            pub mod InterfaceTypes;
            pub mod InheritTypes;
            pub mod PrototypeList;
            pub mod RegisterBindings;
            pub mod BindingDeclarations;
            pub mod UnionTypes;
        }
    }

    pub mod types {
        pub use super::bindings::codegen::InterfaceTypes::*;
    }

    pub mod attr;
    pub mod attrlist;
    pub mod blob;
    pub mod browsercontext;
    pub mod characterdata;
    pub mod clientrect;
    pub mod clientrectlist;
    pub mod comment;
    pub mod console;
    pub mod document;
    pub mod documentfragment;
    pub mod documenttype;
    pub mod domexception;
    pub mod domimplementation;
    pub mod domparser;
    pub mod element;
    pub mod event;
    pub mod eventdispatcher;
    pub mod eventtarget;
    pub mod formdata;
    pub mod htmlanchorelement;
    pub mod htmlappletelement;
    pub mod htmlareaelement;
    pub mod htmlaudioelement;
    pub mod htmlbaseelement;
    pub mod htmlbodyelement;
    pub mod htmlbrelement;
    pub mod htmlbuttonelement;
    pub mod htmlcanvaselement;
    pub mod htmlcollection;
    pub mod htmldataelement;
    pub mod htmldatalistelement;
    pub mod htmldirectoryelement;
    pub mod htmldivelement;
    pub mod htmldlistelement;
    pub mod htmlelement;
    pub mod htmlembedelement;
    pub mod htmlfieldsetelement;
    pub mod htmlfontelement;
    pub mod htmlformelement;
    pub mod htmlframeelement;
    pub mod htmlframesetelement;
    pub mod htmlheadelement;
    pub mod htmlheadingelement;
    pub mod htmlhrelement;
    pub mod htmlhtmlelement;
    pub mod htmliframeelement;
    pub mod htmlimageelement;
    pub mod htmlinputelement;
    pub mod htmllabelelement;
    pub mod htmllegendelement;
    pub mod htmllielement;
    pub mod htmllinkelement;
    pub mod htmlmainelement;
    pub mod htmlmapelement;
    pub mod htmlmediaelement;
    pub mod htmlmetaelement;
    pub mod htmlmeterelement;
    pub mod htmlmodelement;
    pub mod htmlobjectelement;
    pub mod htmlolistelement;
    pub mod htmloptgroupelement;
    pub mod htmloptionelement;
    pub mod htmloutputelement;
    pub mod htmlparagraphelement;
    pub mod htmlparamelement;
    pub mod htmlpreelement;
    pub mod htmlprogresselement;
    pub mod htmlquoteelement;
    pub mod htmlscriptelement;
    pub mod htmlselectelement;
    pub mod htmlserializer;
    pub mod htmlspanelement;
    pub mod htmlsourceelement;
    pub mod htmlstyleelement;
    pub mod htmltableelement;
    pub mod htmltablecaptionelement;
    pub mod htmltablecellelement;
    pub mod htmltabledatacellelement;
    pub mod htmltableheadercellelement;
    pub mod htmltablecolelement;
    pub mod htmltablerowelement;
    pub mod htmltablesectionelement;
    pub mod htmltemplateelement;
    pub mod htmltextareaelement;
    pub mod htmltimeelement;
    pub mod htmltitleelement;
    pub mod htmltrackelement;
    pub mod htmlulistelement;
    pub mod htmlvideoelement;
    pub mod htmlunknownelement;
    pub mod location;
    pub mod mouseevent;
    pub mod navigator;
    pub mod node;
    pub mod nodelist;
    pub mod processinginstruction;
    pub mod uievent;
    pub mod text;
    pub mod validitystate;
    pub mod virtualmethods;
    pub mod window;

    pub mod testbinding;
}

pub mod html {
    pub mod cssparse;
    pub mod hubbub_html_parser;
}

pub mod layout_interface;
pub mod script_task;
<commit_msg>Point it to InterfaceTypes.rs directly to export generated types.<commit_after>/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

#![crate_id = "github.com/mozilla/servo#script:0.1"]
#![crate_type = "lib"]
#![crate_type = "dylib"]
#![crate_type = "rlib"]

#![comment = "The Servo Parallel Browser Project"]
#![license = "MPL"]

#![feature(globs, macro_rules, struct_variant, phase)]

#![feature(phase)]
#[phase(syntax, link)]
extern crate log;

extern crate collections;
extern crate geom;
extern crate hubbub;
extern crate encoding;
extern crate js;
extern crate libc;
extern crate native;
extern crate serialize;
extern crate time;
#[phase(syntax)]
extern crate servo_macros = "macros";
extern crate servo_net = "net";
extern crate servo_util = "util";
extern crate style;
extern crate servo_msg = "msg";
extern crate url;

pub mod dom {
    pub mod bindings {
        pub mod js;
        pub mod element;
        pub mod utils;
        pub mod callback;
        pub mod error;
        pub mod conversions;
        pub mod proxyhandler;
        pub mod trace;
        pub mod codegen {
            pub mod InterfaceTypes;
            pub mod InheritTypes;
            pub mod PrototypeList;
            pub mod RegisterBindings;
            pub mod BindingDeclarations;
            pub mod UnionTypes;
        }
    }

    #[path="bindings/codegen/InterfaceTypes.rs"]
    pub mod types;

    pub mod attr;
    pub mod attrlist;
    pub mod blob;
    pub mod browsercontext;
    pub mod characterdata;
    pub mod clientrect;
    pub mod clientrectlist;
    pub mod comment;
    pub mod console;
    pub mod document;
    pub mod documentfragment;
    pub mod documenttype;
    pub mod domexception;
    pub mod domimplementation;
    pub mod domparser;
    pub mod element;
    pub mod event;
    pub mod eventdispatcher;
    pub mod eventtarget;
    pub mod formdata;
    pub mod htmlanchorelement;
    pub mod htmlappletelement;
    pub mod htmlareaelement;
    pub mod htmlaudioelement;
    pub mod htmlbaseelement;
    pub mod htmlbodyelement;
    pub mod htmlbrelement;
    pub mod htmlbuttonelement;
    pub mod htmlcanvaselement;
    pub mod htmlcollection;
    pub mod htmldataelement;
    pub mod htmldatalistelement;
    pub mod htmldirectoryelement;
    pub mod htmldivelement;
    pub mod htmldlistelement;
    pub mod htmlelement;
    pub mod htmlembedelement;
    pub mod htmlfieldsetelement;
    pub mod htmlfontelement;
    pub mod htmlformelement;
    pub mod htmlframeelement;
    pub mod htmlframesetelement;
    pub mod htmlheadelement;
    pub mod htmlheadingelement;
    pub mod htmlhrelement;
    pub mod htmlhtmlelement;
    pub mod htmliframeelement;
    pub mod htmlimageelement;
    pub mod htmlinputelement;
    pub mod htmllabelelement;
    pub mod htmllegendelement;
    pub mod htmllielement;
    pub mod htmllinkelement;
    pub mod htmlmainelement;
    pub mod htmlmapelement;
    pub mod htmlmediaelement;
    pub mod htmlmetaelement;
    pub mod htmlmeterelement;
    pub mod htmlmodelement;
    pub mod htmlobjectelement;
    pub mod htmlolistelement;
    pub mod htmloptgroupelement;
    pub mod htmloptionelement;
    pub mod htmloutputelement;
    pub mod htmlparagraphelement;
    pub mod htmlparamelement;
    pub mod htmlpreelement;
    pub mod htmlprogresselement;
    pub mod htmlquoteelement;
    pub mod htmlscriptelement;
    pub mod htmlselectelement;
    pub mod htmlserializer;
    pub mod htmlspanelement;
    pub mod htmlsourceelement;
    pub mod htmlstyleelement;
    pub mod htmltableelement;
    pub mod htmltablecaptionelement;
    pub mod htmltablecellelement;
    pub mod htmltabledatacellelement;
    pub mod htmltableheadercellelement;
    pub mod htmltablecolelement;
    pub mod htmltablerowelement;
    pub mod htmltablesectionelement;
    pub mod htmltemplateelement;
    pub mod htmltextareaelement;
    pub mod htmltimeelement;
    pub mod htmltitleelement;
    pub mod htmltrackelement;
    pub mod htmlulistelement;
    pub mod htmlvideoelement;
    pub mod htmlunknownelement;
    pub mod location;
    pub mod mouseevent;
    pub mod navigator;
    pub mod node;
    pub mod nodelist;
    pub mod processinginstruction;
    pub mod uievent;
    pub mod text;
    pub mod validitystate;
    pub mod virtualmethods;
    pub mod window;

    pub mod testbinding;
}

pub mod html {
    pub mod cssparse;
    pub mod hubbub_html_parser;
}

pub mod layout_interface;
pub mod script_task;
<|endoftext|>


<commit_before>use compositor::seat::Seat;
use compositor::{self, Action, Server, Shell, View};
use std::time::Duration;
use wlroots::types::Cursor;
use wlroots::{pointer_events::*, CompositorHandle, HandleResult, KeyboardHandle, Origin,
              PointerHandle, PointerHandler, SurfaceHandle, WLR_BUTTON_RELEASED};

#[derive(Debug, Default)]
pub struct Pointer;

impl PointerHandler for Pointer {
    fn on_motion_absolute(&mut self,
                          compositor: CompositorHandle,
                          _: PointerHandle,
                          event: &AbsoluteMotionEvent) {
        with_handles!([(compositor: {compositor})] => {
            let server: &mut Server = compositor.data.downcast_mut().unwrap();
            let Server { ref mut cursor,
                         ref mut seat,
                         ref mut views,
                         .. } = *server;
            with_handles!([(cursor: {&mut *cursor})] => {
                let (x, y) = event.pos();
                cursor.warp_absolute(event.device(), x, y);
                update_view_position(cursor, seat, views, event.time_msec());
            }).expect("Cursor was destroyed");
        }).unwrap();
    }

    fn on_motion(&mut self, compositor: CompositorHandle, _: PointerHandle, event: &MotionEvent) {
        with_handles!([(compositor: {compositor})] => {
            let server: &mut Server = compositor.into();
            let Server { ref mut cursor,
                         ref mut seat,
                         ref mut views,
                         .. } = *server;
            with_handles!([(cursor: {&mut *cursor})] => {
                let (x, y) = event.delta();
                cursor.move_to(event.device(), x, y);
                update_view_position(cursor, seat, views, event.time_msec());
            }).expect("Cursor was destroyed");
        }).unwrap();
    }

    fn on_button(&mut self, compositor: CompositorHandle, _: PointerHandle, event: &ButtonEvent) {
        with_handles!([(compositor: {compositor})] => {
            let server: &mut Server = compositor.into();
            let Server { ref mut cursor,
                         ref mut views,
                         ref mut seat,
                         ref mut keyboards,
                         .. } = *server;
            with_handles!([(cursor: {&mut *cursor})] => {
                if event.state() == WLR_BUTTON_RELEASED {
                    seat.action = None;
                    send_pointer_button(seat, event).expect("Could not send pointer button");
                    return
                }
                let (view, _surface, _sx, _sy) = view_at_pointer(views, cursor);
                match view {
                    Some(view) => {
                        focus_under_pointer(seat, &mut **keyboards, { &mut *view }).expect("Could not focus \
                                                                                view");
                        let meta_held_down = seat.meta;
                        if meta_held_down && event.button() == BTN_LEFT {
                            move_view(seat, cursor, view, None);
                        }
                        send_pointer_button(seat, event).expect("Could not send pointer button");
                    },
                    None => {
                        focus_under_pointer(seat, &mut **keyboards, None).expect("Could not focus view");
                    }
                }
            }).unwrap()
        }).unwrap()
    }
}

/// After the cursor has been warped, send pointer motion events to the view
/// under the pointer or update the position of a view that might have been
/// affected by an ongoing interactive move/resize operation
fn update_view_position(cursor: &mut Cursor, seat: &mut Seat, views: &mut [View], time_msec: u32) {
    match seat.action {
        Some(Action::Moving { start }) => {
            if let Some(focused_shell) = seat.focused.as_ref().map(|f| f.shell.clone()) {
                for v in views {
                    if v.shell == focused_shell {
                        move_view(seat, cursor, v, start);
                    }
                }
            }
        }
        _ => {
            let (_view, surface, sx, sy) = view_at_pointer(views, cursor);
            let ref mut seat = seat.seat;
            match surface {
                Some(surface) => {
                    with_handles!([(surface: {surface}), (seat: {seat})] => {
                        seat.pointer_notify_enter(surface, sx, sy);
                        seat.pointer_notify_motion(Duration::from_millis(time_msec as u64), sx, sy);
                    }).unwrap();
                }
                None => {
                    with_handles!([(seat: {seat})] => {
                        seat.pointer_clear_focus();
                    }).unwrap();
                }
            }
        }
    }
}

fn view_at_pointer<'view>(views: &'view mut [View],
                          cursor: &mut Cursor)
                          -> (Option<&'view mut View>, Option<SurfaceHandle>, f64, f64) {
    for view in views {
        match view.shell.clone() {
            Shell::XdgV6(ref mut shell) => {
                let (mut sx, mut sy) = (0.0, 0.0);
                let surface = with_handles!([(shell: {&mut *shell})] => {
                    let (lx, ly) = cursor.coords();
                    let Origin {x: shell_x, y: shell_y} = view.origin;
                    let (view_sx, view_sy) = (lx - shell_x as f64, ly - shell_y as f64);
                    shell.surface_at(view_sx, view_sy, &mut sx, &mut sy)
                }).unwrap();
                if surface.is_some() {
                    return (Some(view), surface, sx, sy)
                }
            }
        }
    }
    (None, None, 0.0, 0.0)
}

/// Focus the view under the pointer.
fn focus_under_pointer<'view, V>(seat: &mut compositor::Seat,
                                 keyboards: &mut [KeyboardHandle],
                                 view: V)
                                 -> HandleResult<()>
    where V: Into<Option<&'view mut View>>
{
    match view.into() {
        None => {
            if let Some(mut focused_view) = seat.focused.take() {
                focused_view.activate(false);
            }
            with_handles!([(seat: {&mut seat.seat})] => {
                seat.keyboard_clear_focus()
            })
        }
        Some(view) => {
            if let Some(mut focused_view) = seat.focused.take() {
                if focused_view.shell == view.shell {
                    return Ok(());
                }
                focused_view.activate(false);
            }
            seat.focused = Some(view.clone());
            view.activate(true);
            for keyboard in { &mut *keyboards } {
                with_handles!([(seat: {&mut seat.seat}),
                (surface: {view.surface()}),
                (keyboard: {keyboard})] => {
                    seat.keyboard_notify_enter(surface,
                                               &mut keyboard.keycodes(),
                                               &mut keyboard.get_modifier_masks())
                })?;
            }
            Ok(())
        }
    }
}

/// Start moving a view if you haven't already by passing `start: None`.
///
/// Otherwise, update the view position relative to where the move started,
/// which is provided by Action::Moving.
fn move_view<O>(seat: &mut compositor::Seat, cursor: &mut Cursor, view: &mut View, start: O)
    where O: Into<Option<Origin>>
{
    let Origin { x: shell_x,
                 y: shell_y } = view.origin;
    let (lx, ly) = cursor.coords();
    match start.into() {
        None => {
            let (view_sx, view_sy) = (lx - shell_x as f64, ly - shell_y as f64);
            let start = Origin::new(view_sx as _, view_sy as _);
            seat.action = Some(Action::Moving { start });
        }
        Some(start) => {
            let pos = Origin::new(lx as i32 - start.x, ly as i32 - start.y);
            view.origin = pos;
        }
    };
}

fn send_pointer_button(seat: &mut compositor::Seat, event: &ButtonEvent) -> HandleResult<()> {
    with_handles!([(seat: {&mut seat.seat})] => {
        seat.pointer_notify_button(Duration::from_millis(event.time_msec() as _),
                                   event.button(),
                                   event.state() as u32);
    })
}
<commit_msg>put focused view at the top<commit_after>use compositor::seat::Seat;
use compositor::{self, Action, Server, Shell, View};
use std::time::Duration;
use wlroots::types::Cursor;
use wlroots::{pointer_events::*, CompositorHandle, HandleResult, KeyboardHandle, Origin,
              PointerHandle, PointerHandler, SurfaceHandle, WLR_BUTTON_RELEASED};

#[derive(Debug, Default)]
pub struct Pointer;

impl PointerHandler for Pointer {
    fn on_motion_absolute(&mut self,
                          compositor: CompositorHandle,
                          _: PointerHandle,
                          event: &AbsoluteMotionEvent) {
        with_handles!([(compositor: {compositor})] => {
            let server: &mut Server = compositor.data.downcast_mut().unwrap();
            let Server { ref mut cursor,
                         ref mut seat,
                         ref mut views,
                         .. } = *server;
            with_handles!([(cursor: {&mut *cursor})] => {
                let (x, y) = event.pos();
                cursor.warp_absolute(event.device(), x, y);
                update_view_position(cursor, seat, views, event.time_msec());
            }).expect("Cursor was destroyed");
        }).unwrap();
    }

    fn on_motion(&mut self, compositor: CompositorHandle, _: PointerHandle, event: &MotionEvent) {
        with_handles!([(compositor: {compositor})] => {
            let server: &mut Server = compositor.into();
            let Server { ref mut cursor,
                         ref mut seat,
                         ref mut views,
                         .. } = *server;
            with_handles!([(cursor: {&mut *cursor})] => {
                let (x, y) = event.delta();
                cursor.move_to(event.device(), x, y);
                update_view_position(cursor, seat, views, event.time_msec());
            }).expect("Cursor was destroyed");
        }).unwrap();
    }

    fn on_button(&mut self, compositor: CompositorHandle, _: PointerHandle, event: &ButtonEvent) {
        with_handles!([(compositor: {compositor})] => {
            let server: &mut Server = compositor.into();
            let Server { ref mut cursor,
                         ref mut views,
                         ref mut seat,
                         ref mut keyboards,
                         .. } = *server;
            with_handles!([(cursor: {&mut *cursor})] => {
                if event.state() == WLR_BUTTON_RELEASED {
                    seat.action = None;
                    send_pointer_button(seat, event).expect("Could not send pointer button");
                    return
                }
                let view = {
                    let (view, _surface, _sx, _sy) = view_at_pointer(views, cursor);
                    if let Some(view) = view {
                        Some(view.clone())
                    } else{
                        None
                    }
                };

                match view {
                    Some(mut view) => {
                        focus_under_pointer(seat, &mut **keyboards, &mut view, views).expect("Could not focus \
                                                                                view");
                        let meta_held_down = seat.meta;
                        if meta_held_down && event.button() == BTN_LEFT {
                            move_view(seat, cursor, &mut view, None);
                        }
                        send_pointer_button(seat, event).expect("Could not send pointer button");
                    },
                    None => {
                        focus_under_pointer(seat, &mut **keyboards, None, views).expect("Could not focus view");
                    }
                }
            }).unwrap()
        }).unwrap()
    }
}

/// After the cursor has been warped, send pointer motion events to the view
/// under the pointer or update the position of a view that might have been
/// affected by an ongoing interactive move/resize operation
fn update_view_position(cursor: &mut Cursor, seat: &mut Seat, views: &mut [View], time_msec: u32) {
    match seat.action {
        Some(Action::Moving { start }) => {
            if let Some(focused_shell) = seat.focused.as_ref().map(|f| f.shell.clone()) {
                for v in views {
                    if v.shell == focused_shell {
                        move_view(seat, cursor, v, start);
                    }
                }
            }
        }
        _ => {
            let (_view, surface, sx, sy) = view_at_pointer(views, cursor);
            let ref mut seat = seat.seat;
            match surface {
                Some(surface) => {
                    with_handles!([(surface: {surface}), (seat: {seat})] => {
                        seat.pointer_notify_enter(surface, sx, sy);
                        seat.pointer_notify_motion(Duration::from_millis(time_msec as u64), sx, sy);
                    }).unwrap();
                }
                None => {
                    with_handles!([(seat: {seat})] => {
                        seat.pointer_clear_focus();
                    }).unwrap();
                }
            }
        }
    }
}

fn view_at_pointer<'view>(views: &'view mut [View],
                          cursor: &mut Cursor)
                          -> (Option<&'view mut View>, Option<SurfaceHandle>, f64, f64) {
    for view in views {
        match view.shell.clone() {
            Shell::XdgV6(ref mut shell) => {
                let (mut sx, mut sy) = (0.0, 0.0);
                let surface = with_handles!([(shell: {&mut *shell})] => {
                    let (lx, ly) = cursor.coords();
                    let Origin {x: shell_x, y: shell_y} = view.origin;
                    let (view_sx, view_sy) = (lx - shell_x as f64, ly - shell_y as f64);
                    shell.surface_at(view_sx, view_sy, &mut sx, &mut sy)
                }).unwrap();
                if surface.is_some() {
                    return (Some(view), surface, sx, sy)
                }
            }
        }
    }
    (None, None, 0.0, 0.0)
}

/// Focus the view under the pointer.
fn focus_under_pointer<'view, V>(seat: &mut compositor::Seat,
                                 keyboards: &mut [KeyboardHandle],
                                 view: V,
                                 views: &mut Vec<View>)
                                 -> HandleResult<()>
    where V: Into<Option<&'view mut View>>
{
    match view.into() {
        None => {
            if let Some(mut focused_view) = seat.focused.take() {
                focused_view.activate(false);
            }
            with_handles!([(seat: {&mut seat.seat})] => {
                seat.keyboard_clear_focus()
            })
        }
        Some(view) => {
            if let Some(mut focused_view) = seat.focused.as_mut() {
                if focused_view.shell == view.shell {
                    return Ok(());
                }
                focused_view.activate(false);
            }
            seat.focused = Some(view.clone());
            view.activate(true);

            if let Some(idx) = views.iter().position(|ref v| v.shell == view.shell) {
                let v = views.remove(idx);
                views.insert(0, v);
            }

            for keyboard in { &mut *keyboards } {
                with_handles!([(seat: {&mut seat.seat}),
                (surface: {view.surface()}),
                (keyboard: {keyboard})] => {
                    seat.keyboard_notify_enter(surface,
                                               &mut keyboard.keycodes(),
                                               &mut keyboard.get_modifier_masks())
                })?;
            }
            Ok(())
        }
    }
}

/// Start moving a view if you haven't already by passing `start: None`.
///
/// Otherwise, update the view position relative to where the move started,
/// which is provided by Action::Moving.
fn move_view<O>(seat: &mut compositor::Seat, cursor: &mut Cursor, view: &mut View, start: O)
    where O: Into<Option<Origin>>
{
    let Origin { x: shell_x,
                 y: shell_y } = view.origin;
    let (lx, ly) = cursor.coords();
    match start.into() {
        None => {
            let (view_sx, view_sy) = (lx - shell_x as f64, ly - shell_y as f64);
            let start = Origin::new(view_sx as _, view_sy as _);
            seat.action = Some(Action::Moving { start });
        }
        Some(start) => {
            let pos = Origin::new(lx as i32 - start.x, ly as i32 - start.y);
            view.origin = pos;
        }
    };
}

fn send_pointer_button(seat: &mut compositor::Seat, event: &ButtonEvent) -> HandleResult<()> {
    with_handles!([(seat: {&mut seat.seat})] => {
        seat.pointer_notify_button(Duration::from_millis(event.time_msec() as _),
                                   event.button(),
                                   event.state() as u32);
    })
}
<|endoftext|>