<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::ascii::StrAsciiExt;
use extra::sort::tim_sort;

use style::selectors::*;
use style::stylesheets::parse_stylesheet;
use style::media_queries::{Device, Screen};
use style::properties::{ComputedValues, cascade, PropertyDeclaration};
use dom::node::{AbstractNode, ScriptView};
use dom::element::Element;

pub enum StylesheetOrigin {
    UserAgentOrigin,
    AuthorOrigin,
    UserOrigin,
}

pub struct Stylist {
    priv ua_rules: PerOriginRules,
    priv author_rules: PerOriginRules,
    priv user_rules: PerOriginRules,
}

impl Stylist {
    #[inline]
    pub fn new() -> Stylist {
        Stylist {
            ua_rules: PerOriginRules::new(),
            author_rules: PerOriginRules::new(),
            user_rules: PerOriginRules::new(),
        }
    }

    pub fn add_stylesheet(&mut self, css_source: &str, origin: StylesheetOrigin) {
        let stylesheet = parse_stylesheet(css_source);
        let rules = match origin {
            UserAgentOrigin => &mut self.ua_rules,
            AuthorOrigin => &mut self.author_rules,
            UserOrigin => &mut self.user_rules,
        };
        let mut has_normal_declarations = false;
        let mut has_important_declarations = false;

        macro_rules! append(
            ($priority: ident, $flag: ident) => {
                if style_rule.declarations.$priority.len() > 0 {
                    $flag = true;
                    for selector in style_rule.selectors.iter() {
                        rules.$priority.push(Rule {
                            selector: *selector,
                            declarations: style_rule.declarations.$priority,
                        })
                    }
                }
            };
        )

        let device = &Device { media_type: Screen };  // TODO, use Print when printing
        for style_rule in stylesheet.iter_style_rules(device) {
            append!(normal, has_normal_declarations);
            append!(important, has_important_declarations);
        }

        if has_normal_declarations {
            tim_sort(rules.normal)
        }
        if has_important_declarations {
            tim_sort(rules.important)
        }
    }

    pub fn get_computed_style(&self, element: AbstractNode<ScriptView>,
                              parent_style: Option<&ComputedValues>,
                              pseudo_element: Option<PseudoElement>)
                              -> ComputedValues {
        assert!(element.is_element())
        // Only the root does not inherit.
        // The root has no parent or a non-element parent.
        assert_eq!(
            parent_style.is_none(),
            match element.parent_node() {
                None => true,
                Some(ref node) => !node.is_element()
            }
        );
        let mut applicable_declarations = ~[];  // TODO: use an iterator?

        macro_rules! append(
            ($rules: expr) => {
                for rule in $rules.iter() {
                    if matches_selector(rule.selector, element, pseudo_element) {
                        applicable_declarations.push(rule.declarations)
                    }
                }
            };
        );

        // In cascading order
        append!(self.ua_rules.normal);
        append!(self.user_rules.normal);
        append!(self.author_rules.normal);
        // TODO add style attribute
        append!(self.author_rules.important);
        append!(self.user_rules.important);
        append!(self.ua_rules.important);

        cascade(applicable_declarations, parent_style)
    }
}

struct PerOriginRules {
    normal: ~[Rule],
    important: ~[Rule],
}

impl PerOriginRules {
    #[inline]
    fn new() -> PerOriginRules {
        PerOriginRules { normal: ~[], important: ~[] }
    }
}

#[deriving(Clone)]
struct Rule {
    selector: @Selector,
    declarations: @[PropertyDeclaration],
}

impl Ord for Rule {
    #[inline]
    fn lt(&self, other: &Rule) -> bool {
        self.selector.specificity < other.selector.specificity
    }
}

#[inline]
fn matches_selector(selector: &Selector, element: AbstractNode<ScriptView>,
                    pseudo_element: Option<PseudoElement>) -> bool {
    selector.pseudo_element == pseudo_element &&
    matches_compound_selector(&selector.compound_selectors, element)
}

fn matches_compound_selector(selector: &CompoundSelector,
                             element: AbstractNode<ScriptView>) -> bool {
    if do element.with_imm_element |element| {
        !do selector.simple_selectors.iter().all |simple_selector| {
            matches_simple_selector(simple_selector, element)
        }
    } {
        return false
    }
    match selector.next {
        None => true,
        Some((ref next_selector, combinator)) => {
            let (siblings, just_one) = match combinator {
                Child => (false, true),
                Descendant => (false, false),
                NextSibling => (true, true),
                LaterSibling => (true, false),
            };
            let mut node = element;
            loop {
                match if siblings { node.prev_sibling() } else { node.parent_node() } {
                    None => return false,
                    Some(next_node) => node = next_node,
                }
                if node.is_element() {
                    if matches_compound_selector(&**next_selector, node) {
                        return true
                    } else if just_one {
                        return false
                    }
                }
            }
        }
    }
}

#[inline]
fn matches_simple_selector(selector: &SimpleSelector, element: &Element) -> bool {
    static WHITESPACE: &'static [char] = &'static [' ', '\t', '\n', '\r', '\x0C'];

    match *selector {
        // TODO: case-sensitivity depends on the document type
        LocalNameSelector(ref name) => element.tag_name.eq_ignore_ascii_case(name.as_slice()),
        NamespaceSelector(_) => false,  // TODO, when the DOM supports namespaces on elements.
        // TODO: case-sensitivity depends on the document type and quirks mode
        // TODO: cache and intern IDs on elements.
        IDSelector(ref id) => element.get_attr("id") == Some(id.as_slice()),
        // TODO: cache and intern classe names on elements.
        ClassSelector(ref class) => match element.get_attr("class") {
            None => false,
            // TODO: case-sensitivity depends on the document type and quirks mode
            Some(ref class_attr)
            => class_attr.split_iter(WHITESPACE).any(|c| c == class.as_slice()),
        },

        AttrExists(ref attr) => match_attribute(attr, element, |_| true),
        AttrEqual(ref attr, ref value) => match_attribute(attr, element, |v| v == value.as_slice()),
        AttrIncludes(ref attr, ref value) => do match_attribute(attr, element) |attr_value| {
            attr_value.split_iter(WHITESPACE).any(|v| v == value.as_slice())
        },
        AttrDashMatch(ref attr, ref value, ref dashing_value)
        => do match_attribute(attr, element) |attr_value| {
            attr_value == value.as_slice() || attr_value.starts_with(dashing_value.as_slice())
        },
        AttrPrefixMatch(ref attr, ref value) => do match_attribute(attr, element) |attr_value| {
            attr_value.starts_with(value.as_slice())
        },
        AttrSubstringMatch(ref attr, ref value) => do match_attribute(attr, element) |attr_value| {
            attr_value.contains(value.as_slice())
        },
        AttrSuffixMatch(ref attr, ref value) => do match_attribute(attr, element) |attr_value| {
            attr_value.ends_with(value.as_slice())
        },

        Negation(ref negated) => {
            !negated.iter().all(|s| matches_simple_selector(s, element))
        },
    }
}

#[inline]
fn match_attribute(attr: &AttrSelector, element: &Element, f: &fn(&str)-> bool) -> bool {
    match attr.namespace {
        Some(_) => false,  // TODO, when the DOM supports namespaces on attributes
        None => match element.get_attr(attr.name) {
            None => false,
            Some(ref value) => f(value.as_slice())
        }
    }
}
<commit_msg>Sorting on specificity needs to be stable for correctness of the cascade.<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::ascii::StrAsciiExt;
use extra::sort::tim_sort;

use style::selectors::*;
use style::stylesheets::parse_stylesheet;
use style::media_queries::{Device, Screen};
use style::properties::{ComputedValues, cascade, PropertyDeclaration};
use dom::node::{AbstractNode, ScriptView};
use dom::element::Element;

pub enum StylesheetOrigin {
    UserAgentOrigin,
    AuthorOrigin,
    UserOrigin,
}

pub struct Stylist {
    priv ua_rules: PerOriginRules,
    priv author_rules: PerOriginRules,
    priv user_rules: PerOriginRules,
}

impl Stylist {
    #[inline]
    pub fn new() -> Stylist {
        Stylist {
            ua_rules: PerOriginRules::new(),
            author_rules: PerOriginRules::new(),
            user_rules: PerOriginRules::new(),
        }
    }

    pub fn add_stylesheet(&mut self, css_source: &str, origin: StylesheetOrigin) {
        let stylesheet = parse_stylesheet(css_source);
        let rules = match origin {
            UserAgentOrigin => &mut self.ua_rules,
            AuthorOrigin => &mut self.author_rules,
            UserOrigin => &mut self.user_rules,
        };
        let mut has_normal_declarations = false;
        let mut has_important_declarations = false;

        macro_rules! append(
            ($priority: ident, $flag: ident) => {
                if style_rule.declarations.$priority.len() > 0 {
                    $flag = true;
                    for selector in style_rule.selectors.iter() {
                        rules.$priority.push(Rule {
                            selector: *selector,
                            declarations: style_rule.declarations.$priority,
                        })
                    }
                }
            };
        )

        let device = &Device { media_type: Screen };  // TODO, use Print when printing
        for style_rule in stylesheet.iter_style_rules(device) {
            append!(normal, has_normal_declarations);
            append!(important, has_important_declarations);
        }

        // These sorts need to be stable
        if has_normal_declarations {
            tim_sort(rules.normal)
        }
        if has_important_declarations {
            tim_sort(rules.important)
        }
    }

    pub fn get_computed_style(&self, element: AbstractNode<ScriptView>,
                              parent_style: Option<&ComputedValues>,
                              pseudo_element: Option<PseudoElement>)
                              -> ComputedValues {
        assert!(element.is_element())
        // Only the root does not inherit.
        // The root has no parent or a non-element parent.
        assert_eq!(
            parent_style.is_none(),
            match element.parent_node() {
                None => true,
                Some(ref node) => !node.is_element()
            }
        );
        let mut applicable_declarations = ~[];  // TODO: use an iterator?

        macro_rules! append(
            ($rules: expr) => {
                for rule in $rules.iter() {
                    if matches_selector(rule.selector, element, pseudo_element) {
                        applicable_declarations.push(rule.declarations)
                    }
                }
            };
        );

        // In cascading order
        append!(self.ua_rules.normal);
        append!(self.user_rules.normal);
        append!(self.author_rules.normal);
        // TODO add style attribute
        append!(self.author_rules.important);
        append!(self.user_rules.important);
        append!(self.ua_rules.important);

        cascade(applicable_declarations, parent_style)
    }
}

struct PerOriginRules {
    normal: ~[Rule],
    important: ~[Rule],
}

impl PerOriginRules {
    #[inline]
    fn new() -> PerOriginRules {
        PerOriginRules { normal: ~[], important: ~[] }
    }
}

#[deriving(Clone)]
struct Rule {
    selector: @Selector,
    declarations: @[PropertyDeclaration],
}

impl Ord for Rule {
    #[inline]
    fn lt(&self, other: &Rule) -> bool {
        self.selector.specificity < other.selector.specificity
    }
}

#[inline]
fn matches_selector(selector: &Selector, element: AbstractNode<ScriptView>,
                    pseudo_element: Option<PseudoElement>) -> bool {
    selector.pseudo_element == pseudo_element &&
    matches_compound_selector(&selector.compound_selectors, element)
}

fn matches_compound_selector(selector: &CompoundSelector,
                             element: AbstractNode<ScriptView>) -> bool {
    if do element.with_imm_element |element| {
        !do selector.simple_selectors.iter().all |simple_selector| {
            matches_simple_selector(simple_selector, element)
        }
    } {
        return false
    }
    match selector.next {
        None => true,
        Some((ref next_selector, combinator)) => {
            let (siblings, just_one) = match combinator {
                Child => (false, true),
                Descendant => (false, false),
                NextSibling => (true, true),
                LaterSibling => (true, false),
            };
            let mut node = element;
            loop {
                match if siblings { node.prev_sibling() } else { node.parent_node() } {
                    None => return false,
                    Some(next_node) => node = next_node,
                }
                if node.is_element() {
                    if matches_compound_selector(&**next_selector, node) {
                        return true
                    } else if just_one {
                        return false
                    }
                }
            }
        }
    }
}

#[inline]
fn matches_simple_selector(selector: &SimpleSelector, element: &Element) -> bool {
    static WHITESPACE: &'static [char] = &'static [' ', '\t', '\n', '\r', '\x0C'];

    match *selector {
        // TODO: case-sensitivity depends on the document type
        LocalNameSelector(ref name) => element.tag_name.eq_ignore_ascii_case(name.as_slice()),
        NamespaceSelector(_) => false,  // TODO, when the DOM supports namespaces on elements.
        // TODO: case-sensitivity depends on the document type and quirks mode
        // TODO: cache and intern IDs on elements.
        IDSelector(ref id) => element.get_attr("id") == Some(id.as_slice()),
        // TODO: cache and intern classe names on elements.
        ClassSelector(ref class) => match element.get_attr("class") {
            None => false,
            // TODO: case-sensitivity depends on the document type and quirks mode
            Some(ref class_attr)
            => class_attr.split_iter(WHITESPACE).any(|c| c == class.as_slice()),
        },

        AttrExists(ref attr) => match_attribute(attr, element, |_| true),
        AttrEqual(ref attr, ref value) => match_attribute(attr, element, |v| v == value.as_slice()),
        AttrIncludes(ref attr, ref value) => do match_attribute(attr, element) |attr_value| {
            attr_value.split_iter(WHITESPACE).any(|v| v == value.as_slice())
        },
        AttrDashMatch(ref attr, ref value, ref dashing_value)
        => do match_attribute(attr, element) |attr_value| {
            attr_value == value.as_slice() || attr_value.starts_with(dashing_value.as_slice())
        },
        AttrPrefixMatch(ref attr, ref value) => do match_attribute(attr, element) |attr_value| {
            attr_value.starts_with(value.as_slice())
        },
        AttrSubstringMatch(ref attr, ref value) => do match_attribute(attr, element) |attr_value| {
            attr_value.contains(value.as_slice())
        },
        AttrSuffixMatch(ref attr, ref value) => do match_attribute(attr, element) |attr_value| {
            attr_value.ends_with(value.as_slice())
        },

        Negation(ref negated) => {
            !negated.iter().all(|s| matches_simple_selector(s, element))
        },
    }
}

#[inline]
fn match_attribute(attr: &AttrSelector, element: &Element, f: &fn(&str)-> bool) -> bool {
    match attr.namespace {
        Some(_) => false,  // TODO, when the DOM supports namespaces on attributes
        None => match element.get_attr(attr.name) {
            None => false,
            Some(ref value) => f(value.as_slice())
        }
    }
}
<|endoftext|>


<commit_before>use std::path::{Path,PathBuf};
use std::fs::PathExt;
use std::mem::replace;
use std::rc::{Rc, Weak};
use std::cell::RefCell;
use glium::texture::Texture2d;
use glium::backend::Facade;
use image;
use texture_flags::*;
use helpers::*;
use raw_bsp::*;

// TODO: IMPORTANT HOLY SHIT 𝘋𝘖 𝘕𝘖𝘛 𝘍𝘖𝘙𝘎𝘌𝘛!
//       Remove all uses of [] & use try!(_.get(_)) instead

pub struct Bsp {
    node_owner: Vec<NonTerminal>,
    leaf_owner: Vec<Leaf>,
    // For caching/etc. needs keep this separate and store indexes only
    vertices: Vec<Vertex>,
    root: BspTreeNode,
}

impl Bsp {
    pub fn get_visible_set_at(&self, point: Vec3) -> Vec<&Leaf> {
        self.get_terminal_at(point).map_or(
            vec![],
            |t| self.get_visible_set_of(t)
        )
    }

    fn new(
        node_owner: Vec<NonTerminal>,
        leaf_owner: Vec<Leaf>,
        verts: Vec<Vertex>
    ) -> Bsp {
        Bsp {
            node_owner: node_owner,
            leaf_owner: leaf_owner,
            vertices: verts,
            root: BspTreeNode::NonTerminal(0)
        }
    }

    fn get_collision_planes_between(
        &self, bounds: (Vec3, Vec3)
    ) -> Vec<&Plane> {
        unimplemented!()
    }

    fn get_terminal_at(&self, point: Vec3) -> Option<&Leaf> {
        let mut current = &self.root;
        while let &BspTreeNode::NonTerminal(node_index) = current {
            let node = &self.node_owner[node_index];
            let dot = point.iter()
                .zip(node.plane.normal.iter())
                .map(|(a, b)| a * b)
                .sum::<f32>();

            if izip!(
                point.iter(),
                node.bounds.0.iter(),
                node.bounds.1.iter()
            ).any(
                |(&p, &min, &max)| p < min as f32 || p > max as f32
            ) {
                return None;
            }

            current =
                if dot < node.plane.distance {
                    &node.back
                } else {
                    &node.front
                }
        }

        if let &BspTreeNode::Leaf(leaf_index) = current {
            Some(&self.leaf_owner[leaf_index])
        } else {
            unreachable!()
        }
    }

    fn get_visible_set_of<'a>(&'a self, leaf: &'a Leaf) -> Vec<&'a Leaf> {
        let mut out = leaf.visdata.iter()
            .map(|&i| &self.leaf_owner[i])
            .collect::<Vec<_>>();
        out.push(leaf);
        out
    }
}

enum BspTreeNode {
    NonTerminal(usize),
    Leaf(usize),
}

struct NonTerminal {
    plane: Plane,
    bounds: (IVec3, IVec3),
    front: BspTreeNode,
    back: BspTreeNode,
}

#[derive(Debug)]
pub struct Leaf {
    visdata: Vec<usize>,
    pub faces: Vec<Face>,
    pub brushes: Vec<Brush>,
}

#[derive(Debug)]
pub struct Face {
    texture: Rc<Texture>,
    render_type: FaceRenderType,
}

#[derive(Debug)]
struct Surface {
    plane: Plane,
    surface_flags: SurfaceFlags,
}

#[derive(Debug)]
pub struct Texture {
    hash: u64,
    texture: Texture2d,
    surface_flags: SurfaceFlags,
}

// TODO: make this take a root directory
pub struct TextureBuilder<'a, T: Facade + 'a> {
    root: PathBuf,
    facade: &'a T,
    cache: Vec<Weak<Texture>>,
}

impl<'a, T: Facade + 'a> TextureBuilder<'a, T> {
    pub fn new<A: Into<PathBuf>>(a: A, facade: &'a T) -> TextureBuilder<'a, T> {
        TextureBuilder { root: a.into(), facade: facade, cache: vec![] }
    }

    fn get_real_path_and_ext(
        &self,
        path: &String
    ) -> Option<(image::ImageFormat, PathBuf)> {
        use image::ImageFormat;
        use image::ImageFormat::*;

        fn get_extensions(i: &ImageFormat) -> &'static [&'static str] {
            static PNG_EXT:  [&'static str; 1] = ["png"];
            static JPEG_EXT: [&'static str; 2] = ["jpeg", "jpg"];
            static GIF_EXT:  [&'static str; 1] = ["gif"];
            static WEBP_EXT: [&'static str; 1] = ["webp"];
            static PPM_EXT:  [&'static str; 1] = ["ppm"];
            static TIFF_EXT: [&'static str; 1] = ["tiff"];
            static TGA_EXT:  [&'static str; 1] = ["tga"];
            static BMP_EXT:  [&'static str; 1] = ["bmp"];
            static ICO_EXT:  [&'static str; 1] = ["ico"];

            match *i {
                PNG  => &PNG_EXT,
                JPEG => &JPEG_EXT,
                GIF  => &GIF_EXT,
                WEBP => &WEBP_EXT,
                PPM  => &PPM_EXT,
                TIFF => &TIFF_EXT,
                TGA  => &TGA_EXT,
                BMP  => &BMP_EXT,
                ICO  => &ICO_EXT,
            }
        }

        let root: PathBuf = self.root.join(path);
        let file_name: String =
            if let Some(Some(f)) = root.file_name().map(|o| o.to_str()) {
                f.into()
            } else {
                return None
            };
        for ex in [PNG, JPEG, GIF, WEBP, PPM, TIFF, TGA, BMP, ICO].into_iter() {
            let extensions = get_extensions(&ex);

            for str_ex in extensions {
                use std::env;

                let out = root.with_file_name(format!("{}.{}", file_name, str_ex));

                if out.is_file() { return Some((*ex, out.to_path_buf())); }
            }
        }

        None
    }

    pub fn load(
        &mut self, path: &String, surface_flags: SurfaceFlags
    ) -> Option<Rc<Texture>> {
        use std::io::BufReader;
        use std::fs::File;
        use glium::texture::RawImage2d;
        use image;

        let str_hash = get_string_hash(path);
        if let Some(t) = self.cache.iter()
            .filter_map(|weak| weak.upgrade())
            .find(
                |t| t.hash == str_hash
            )
        {
            return Some(t);
        }

        let (ext, real_path) =
            if let Some(tup) = self.get_real_path_and_ext(path) {
                tup
            } else {
                println!("{}", path);
                return None
            };

        let mut f = if let Ok(a) = File::open(&real_path) {
                a
            } else {
                println!("Cannot find {:?}", &real_path);
                return None
            };
        let mut reader = BufReader::new(f);

        let raw = if let Ok(a) = image::load(
                reader,
                ext
            ) {
                a.to_rgba()
            } else {
                println!("Cannot interpret {:?}", &real_path);
                return None
            };
        let image_dimensions = raw.dimensions();
        let image = RawImage2d::from_raw_rgba_reversed(
                raw.into_raw(), image_dimensions
            );
        Texture2d::new(self.facade, image).ok()
            .map(|t| {
                let out = Rc::new(
                    Texture {
                        hash: get_string_hash(path),
                        texture: t,
                        surface_flags: surface_flags
                    }
                );
                self.cache.push(Rc::downgrade(&out));
                out
            })
    }
}

impl PartialEq for Texture {
    fn eq(&self, other: &Self) -> bool { self.hash == other.hash }
}

impl Eq for Texture {}

#[derive(Debug)]
pub struct Brush {
    surfaces: Vec<Surface>,
    content_flags: ContentFlags,
}

#[derive(Debug)]
enum FaceRenderType {
    Patch(Vec<Vec3>),
    Mesh(Vec<usize>),
    Billboard(usize),
}

struct BspBuilder {
    bsp: RawBsp,
}

fn get_indices(visdata: &[u8]) -> Vec<usize> {
    (0..visdata.len()*8).into_iter()
        .filter(|i|
            visdata[*i as usize / 8] & (1 << (*i % 8)) != 0
        )
        .collect::<Vec<_>>()
}

fn build_face(
    face: &RawFace,
    mesh_verts: &Vec<RawMeshVertex>,
    textures: &Vec<Rc<Texture>>
) -> Face {
    Face {
        texture: textures[face.texture_index as usize].clone(),
        render_type: match &face.face_type {
            &FaceType::Polygon   =>
                FaceRenderType::Mesh(
                    {
                        let start = face.first_vertex as usize;
                        let end = start + face.num_vertices as usize;
                        start..end
                    }.into_iter()
                    .collect::<Vec<_>>()
                ),
            &FaceType::Mesh      =>
                FaceRenderType::Mesh(
                    {
                        let start = face.first_mesh_vertex as usize;
                        let end = face.num_mesh_vertices as usize;
                        start..end
                    }.into_iter()
                    .map(|i| &mesh_verts[i])
                    .map(|v| v.offset + face.first_vertex)
                    .map(|i| i as usize)
                    .collect::<Vec<_>>()
                ),
            &FaceType::Patch     =>
                FaceRenderType::Patch(
                    vec![] // TODO: make this work
                ),
            &FaceType::Billboard =>
                FaceRenderType::Billboard(
                    0 // TODO: support things proper-like
                ),
        },
    }
}

fn build_brush(
    brush: &RawBrush,
    brush_sides: &Vec<RawBrushSide>,
    planes: &Vec<Plane>,
    raw_textures: &Vec<RawTexture>,
) -> Brush {
    Brush {
        surfaces: brush_sides[{
                let start = brush.first_brush_side as usize;
                let end = start + brush.num_brush_sides as usize;
                start..end
            }].iter()
            .map(|s| (
                planes[s.plane_index as usize].clone(),
                raw_textures[s.texture_index as usize].surface_flags,
            ))
            .map(|(p, f)| Surface {
                plane: p,
                surface_flags: f,
            })
            .collect::<Vec<_>>(),
        content_flags: raw_textures[
            brush.texture_index as usize
        ].content_flags,
    }
}

fn build_leaves<'a>(
    raw: &mut RawBsp,
    textures: &Vec<Rc<Texture>>,
) -> Vec<Leaf> {
    let faces = &raw.faces;
    let leaf_brushes = &raw.leaf_brushes;
    let leaf_faces = &raw.leaf_faces;
    let brushes = &raw.brushes;
    let brush_sides = &raw.brush_sides;
    let planes = &raw.planes;
    let raw_textures = &raw.textures;
    let visibility_data = &raw.visibility_data;
    let mesh_verts = &raw.mesh_vertices;
    raw.leaves.iter()
        .map(|l| {
            let faces = leaf_faces[{
                    let start = l.first_leaf_face as usize;
                    let end = start + l.num_leaf_faces as usize;
                    start..end
                }].iter()
                .map(|i| &faces[i.index as usize])
                .map(|f| build_face(f, mesh_verts, textures))
                .collect::<Vec<_>>();
            let brushes = leaf_brushes[{
                    let start = l.first_leaf_brush as usize;
                    let end = start + l.num_leaf_brushes as usize;
                    start..end
                }].iter()
                .map(|i| &brushes[i.index as usize])
                .map(|b| build_brush(
                        b,
                        brush_sides,
                        planes,
                        raw_textures,
                    )
                )
                .collect::<Vec<_>>();

            Leaf {
                visdata: if l.visdata_cluster < 0 {
                        vec![]
                } else {
                    get_indices(
                        &visibility_data.raw_bytes[{
                            let start = (l.visdata_cluster *
                                         visibility_data.sizeof_vector) as usize;
                            let end = start +
                                visibility_data.sizeof_vector as usize;
                            start..end
                        }]
                        ).into_iter()
                    .flat_map(|i|
                              raw.leaves.iter()
                              .enumerate()
                              .filter(|tup|
                                      tup.1.visdata_cluster as usize == i
                                     )
                              .map(|(index, _)| index)
                              .collect::<Vec<_>>()
                             )
                    .collect::<Vec<_>>()
                },
                faces: faces,
                brushes: brushes,
            }
        })
        .collect::<Vec<_>>()
}

fn get_bsp_tree_node(i: i32) -> BspTreeNode {
    if i < 0 {
        BspTreeNode::Leaf((-i) as usize)
    } else {
        BspTreeNode::NonTerminal(i as usize)
    }
}

fn build_nodes(raw: &mut RawBsp) -> Vec<NonTerminal> {
    let planes = &raw.planes;
    raw.nodes.drain(..)
        .map(|n|
            NonTerminal {
                plane: planes[n.plane_index as usize].clone(),
                bounds: (n.min.clone(), n.max.clone()),
                front: get_bsp_tree_node(n.children_indices.0),
                back: get_bsp_tree_node(n.children_indices.1),
            }
        )
        .collect::<Vec<_>>()
}

fn build_textures<T: Facade>(
    raw: &Vec<RawTexture>,
    builder: &mut TextureBuilder<T>
) -> Result<Vec<Rc<Texture>>, ()> {
    let mut out = Vec::with_capacity(raw.len());
    for res in raw.iter().map(|r| get_texture(r, builder)) {
        try!(res.map(|t| out.push(t)));
    }
    Ok(out)
}

fn get_texture<T: Facade>(
    raw: &RawTexture,
    builder: &mut TextureBuilder<T>
) -> Result<Rc<Texture>, ()> {
    builder.load(
        &raw.path,
        raw.surface_flags.clone()
        )
    .or_else(||
         // TODO: Replace this with 𝘱𝘳𝘰𝘱𝘦𝘳 missingno texture
         builder.load(
             &"textures/phdm5/metb_seam".into(),
             raw.surface_flags.clone()
             )
        )
    .ok_or(())
}

fn get_string_hash(s: &String) -> u64 {
    use std::hash::{SipHasher, Hash, Hasher};

    let mut hasher = SipHasher::new();
    s.hash(&mut hasher);
    hasher.finish()
}

pub fn build_bsp<'a, T: Facade>(
    mut raw: RawBsp,
    texture_builder: &mut TextureBuilder<T>
) -> (Vec<Entity>, Bsp) {
    let tex = build_textures(
            &raw.textures,
            texture_builder
        ).expect("Invalid map");
    let ents = replace(&mut raw.entities, vec![]);
    let vertices = replace(&mut raw.vertices, vec![]);

    (
        ents,
        Bsp::new(
            build_nodes(&mut raw),
            build_leaves(&mut raw, &tex),
            vertices
        )
    )
}
<commit_msg>Style<commit_after>use std::path::{Path,PathBuf};
use std::fs::PathExt;
use std::mem::replace;
use std::rc::{Rc, Weak};
use std::cell::RefCell;
use glium::texture::Texture2d;
use glium::backend::Facade;
use image;
use texture_flags::*;
use helpers::*;
use raw_bsp::*;

// TODO: IMPORTANT HOLY SHIT 𝘋𝘖 𝘕𝘖𝘛 𝘍𝘖𝘙𝘎𝘌𝘛!
//       Remove all uses of [] & use try!(_.get(_)) instead

pub struct Bsp {
    node_owner: Vec<NonTerminal>,
    leaf_owner: Vec<Leaf>,
    // For caching/etc. needs keep this separate and store indexes only
    vertices: Vec<Vertex>,
    root: BspTreeNode,
}

impl Bsp {
    pub fn get_visible_set_at(&self, point: Vec3) -> Vec<&Leaf> {
        self.get_terminal_at(point).map_or(
            vec![],
            |t| self.get_visible_set_of(t)
        )
    }

    fn new(
        node_owner: Vec<NonTerminal>,
        leaf_owner: Vec<Leaf>,
        verts: Vec<Vertex>
    ) -> Bsp {
        Bsp {
            node_owner: node_owner,
            leaf_owner: leaf_owner,
            vertices: verts,
            root: BspTreeNode::NonTerminal(0)
        }
    }

    fn get_collision_planes_between(
        &self, bounds: (Vec3, Vec3)
    ) -> Vec<&Plane> {
        unimplemented!()
    }

    fn get_terminal_at(&self, point: Vec3) -> Option<&Leaf> {
        let mut current = &self.root;
        while let &BspTreeNode::NonTerminal(node_index) = current {
            let node = &self.node_owner[node_index];
            let dot = point.iter()
                .zip(node.plane.normal.iter())
                .map(|(a, b)| a * b)
                .sum::<f32>();

            if izip!(
                point.iter(),
                node.bounds.0.iter(),
                node.bounds.1.iter()
            ).any(
                |(&p, &min, &max)| p < min as f32 || p > max as f32
            ) {
                return None;
            }

            current =
                if dot < node.plane.distance {
                    &node.back
                } else {
                    &node.front
                }
        }

        if let &BspTreeNode::Leaf(leaf_index) = current {
            Some(&self.leaf_owner[leaf_index])
        } else {
            unreachable!()
        }
    }

    fn get_visible_set_of<'a>(&'a self, leaf: &'a Leaf) -> Vec<&'a Leaf> {
        let mut out = leaf.visdata.iter()
            .map(|&i| &self.leaf_owner[i])
            .collect::<Vec<_>>();
        out.push(leaf);
        out
    }
}

enum BspTreeNode {
    NonTerminal(usize),
    Leaf(usize),
}

struct NonTerminal {
    plane: Plane,
    bounds: (IVec3, IVec3),
    front: BspTreeNode,
    back: BspTreeNode,
}

#[derive(Debug)]
pub struct Leaf {
    visdata: Vec<usize>,
    pub faces: Vec<Face>,
    pub brushes: Vec<Brush>,
}

#[derive(Debug)]
pub struct Face {
    texture: Rc<Texture>,
    render_type: FaceRenderType,
}

#[derive(Debug)]
struct Surface {
    plane: Plane,
    surface_flags: SurfaceFlags,
}

#[derive(Debug)]
pub struct Texture {
    hash: u64,
    texture: Texture2d,
    surface_flags: SurfaceFlags,
}

// TODO: make this take a root directory
pub struct TextureBuilder<'a, T: Facade + 'a> {
    root: PathBuf,
    facade: &'a T,
    cache: Vec<Weak<Texture>>,
}

impl<'a, T: Facade + 'a> TextureBuilder<'a, T> {
    pub fn new<A: Into<PathBuf>>(a: A, facade: &'a T) -> TextureBuilder<'a, T> {
        TextureBuilder { root: a.into(), facade: facade, cache: vec![] }
    }

    fn get_real_path_and_ext(
        &self,
        path: &String
    ) -> Option<(image::ImageFormat, PathBuf)> {
        use image::ImageFormat;
        use image::ImageFormat::*;

        fn get_extensions(i: &ImageFormat) -> &'static [&'static str] {
            static PNG_EXT:  [&'static str; 1] = ["png"];
            static JPEG_EXT: [&'static str; 2] = ["jpeg", "jpg"];
            static GIF_EXT:  [&'static str; 1] = ["gif"];
            static WEBP_EXT: [&'static str; 1] = ["webp"];
            static PPM_EXT:  [&'static str; 1] = ["ppm"];
            static TIFF_EXT: [&'static str; 1] = ["tiff"];
            static TGA_EXT:  [&'static str; 1] = ["tga"];
            static BMP_EXT:  [&'static str; 1] = ["bmp"];
            static ICO_EXT:  [&'static str; 1] = ["ico"];

            match *i {
                PNG  => &PNG_EXT,
                JPEG => &JPEG_EXT,
                GIF  => &GIF_EXT,
                WEBP => &WEBP_EXT,
                PPM  => &PPM_EXT,
                TIFF => &TIFF_EXT,
                TGA  => &TGA_EXT,
                BMP  => &BMP_EXT,
                ICO  => &ICO_EXT,
            }
        }

        let root: PathBuf = self.root.join(path);
        let file_name: String =
            if let Some(Some(f)) = root.file_name().map(|o| o.to_str()) {
                f.into()
            } else {
                return None
            };
        for ex in [PNG, JPEG, GIF, WEBP, PPM, TIFF, TGA, BMP, ICO].into_iter() {
            let extensions = get_extensions(&ex);

            for str_ex in extensions {
                use std::env;

                let out = root.with_file_name(format!("{}.{}", file_name, str_ex));

                if out.is_file() { return Some((*ex, out.to_path_buf())); }
            }
        }

        None
    }

    pub fn load(
        &mut self, path: &String, surface_flags: SurfaceFlags
    ) -> Option<Rc<Texture>> {
        use std::io::BufReader;
        use std::fs::File;
        use glium::texture::RawImage2d;
        use image;

        let str_hash = get_string_hash(path);
        if let Some(t) = self.cache.iter()
            .filter_map(|weak| weak.upgrade())
            .find(
                |t| t.hash == str_hash
            )
        {
            return Some(t);
        }

        let (ext, real_path) =
            if let Some(tup) = self.get_real_path_and_ext(path) {
                tup
            } else {
                println!("{}", path);
                return None
            };

        let mut f = if let Ok(a) = File::open(&real_path) {
                a
            } else {
                println!("Cannot find {:?}", &real_path);
                return None
            };
        let mut reader = BufReader::new(f);

        let raw = if let Ok(a) = image::load(
                reader,
                ext
            ) {
                a.to_rgba()
            } else {
                println!("Cannot interpret {:?}", &real_path);
                return None
            };
        let image_dimensions = raw.dimensions();
        let image = RawImage2d::from_raw_rgba_reversed(
                raw.into_raw(), image_dimensions
            );
        Texture2d::new(self.facade, image).ok()
            .map(|t| {
                let out = Rc::new(
                    Texture {
                        hash: get_string_hash(path),
                        texture: t,
                        surface_flags: surface_flags
                    }
                );
                self.cache.push(Rc::downgrade(&out));
                out
            })
    }
}

impl PartialEq for Texture {
    fn eq(&self, other: &Self) -> bool { self.hash == other.hash }
}

impl Eq for Texture {}

#[derive(Debug)]
pub struct Brush {
    surfaces: Vec<Surface>,
    content_flags: ContentFlags,
}

#[derive(Debug)]
enum FaceRenderType {
    Patch(Vec<Vec3>),
    Mesh(Vec<usize>),
    Billboard(usize),
}

struct BspBuilder {
    bsp: RawBsp,
}

fn get_indices(visdata: &[u8]) -> Vec<usize> {
    (0..visdata.len()*8).into_iter()
        .filter(|i|
            visdata[*i as usize / 8] & (1 << (*i % 8)) != 0
        )
        .collect::<Vec<_>>()
}

fn build_face(
    face: &RawFace,
    mesh_verts: &Vec<RawMeshVertex>,
    textures: &Vec<Rc<Texture>>
) -> Face {
    Face {
        texture: textures[face.texture_index as usize].clone(),
        render_type: match &face.face_type {
            &FaceType::Polygon   =>
                FaceRenderType::Mesh(
                    {
                        let start = face.first_vertex as usize;
                        let end = start + face.num_vertices as usize;
                        start..end
                    }.into_iter()
                    .collect::<Vec<_>>()
                ),
            &FaceType::Mesh      =>
                FaceRenderType::Mesh(
                    {
                        let start = face.first_mesh_vertex as usize;
                        let end = face.num_mesh_vertices as usize;
                        start..end
                    }.into_iter()
                    .map(|i| &mesh_verts[i])
                    .map(|v| v.offset + face.first_vertex)
                    .map(|i| i as usize)
                    .collect::<Vec<_>>()
                ),
            &FaceType::Patch     =>
                FaceRenderType::Patch(
                    vec![] // TODO: make this work
                ),
            &FaceType::Billboard =>
                FaceRenderType::Billboard(
                    0 // TODO: support things proper-like
                ),
        },
    }
}

fn build_brush(
    brush: &RawBrush,
    brush_sides: &Vec<RawBrushSide>,
    planes: &Vec<Plane>,
    raw_textures: &Vec<RawTexture>,
) -> Brush {
    Brush {
        surfaces: brush_sides[{
                let start = brush.first_brush_side as usize;
                let end = start + brush.num_brush_sides as usize;
                start..end
            }].iter()
            .map(|s| (
                planes[s.plane_index as usize].clone(),
                raw_textures[s.texture_index as usize].surface_flags,
            ))
            .map(|(p, f)| Surface {
                plane: p,
                surface_flags: f,
            })
            .collect::<Vec<_>>(),
        content_flags: raw_textures[
            brush.texture_index as usize
        ].content_flags,
    }
}

fn build_leaves<'a>(
    raw: &mut RawBsp,
    textures: &Vec<Rc<Texture>>,
) -> Vec<Leaf> {
    let faces = &raw.faces;
    let leaf_brushes = &raw.leaf_brushes;
    let leaf_faces = &raw.leaf_faces;
    let brushes = &raw.brushes;
    let brush_sides = &raw.brush_sides;
    let planes = &raw.planes;
    let raw_textures = &raw.textures;
    let visibility_data = &raw.visibility_data;
    let mesh_verts = &raw.mesh_vertices;
    raw.leaves.iter()
        .map(|l| {
            let faces = leaf_faces[{
                    let start = l.first_leaf_face as usize;
                    let end = start + l.num_leaf_faces as usize;
                    start..end
                }].iter()
                .map(|i| &faces[i.index as usize])
                .map(|f| build_face(f, mesh_verts, textures))
                .collect::<Vec<_>>();
            let brushes = leaf_brushes[{
                    let start = l.first_leaf_brush as usize;
                    let end = start + l.num_leaf_brushes as usize;
                    start..end
                }].iter()
                .map(|i| &brushes[i.index as usize])
                .map(|b| build_brush(
                        b,
                        brush_sides,
                        planes,
                        raw_textures,
                    )
                )
                .collect::<Vec<_>>();

            Leaf {
                visdata: if l.visdata_cluster < 0 {
                        vec![]
                } else {
                    get_indices(
                        &visibility_data.raw_bytes[{
                            let start = (l.visdata_cluster *
                                         visibility_data.sizeof_vector) as usize;
                            let end = start +
                                visibility_data.sizeof_vector as usize;
                            start..end
                        }]
                        ).into_iter()
                    .flat_map(|i|
                              raw.leaves.iter()
                              .enumerate()
                              .filter(|tup|
                                  tup.1.visdata_cluster as usize == i
                              )
                              .map(|(index, _)| index)
                              .collect::<Vec<_>>()
                             )
                    .collect::<Vec<_>>()
                },
                faces: faces,
                brushes: brushes,
            }
        })
        .collect::<Vec<_>>()
}

fn get_bsp_tree_node(i: i32) -> BspTreeNode {
    if i < 0 {
        BspTreeNode::Leaf((-i) as usize)
    } else {
        BspTreeNode::NonTerminal(i as usize)
    }
}

fn build_nodes(raw: &mut RawBsp) -> Vec<NonTerminal> {
    let planes = &raw.planes;
    raw.nodes.drain(..)
        .map(|n|
            NonTerminal {
                plane: planes[n.plane_index as usize].clone(),
                bounds: (n.min.clone(), n.max.clone()),
                front: get_bsp_tree_node(n.children_indices.0),
                back: get_bsp_tree_node(n.children_indices.1),
            }
        )
        .collect::<Vec<_>>()
}

fn build_textures<T: Facade>(
    raw: &Vec<RawTexture>,
    builder: &mut TextureBuilder<T>
) -> Result<Vec<Rc<Texture>>, ()> {
    let mut out = Vec::with_capacity(raw.len());
    for res in raw.iter().map(|r| get_texture(r, builder)) {
        try!(res.map(|t| out.push(t)));
    }
    Ok(out)
}

fn get_texture<T: Facade>(
    raw: &RawTexture,
    builder: &mut TextureBuilder<T>
) -> Result<Rc<Texture>, ()> {
    builder.load(
        &raw.path,
        raw.surface_flags.clone()
        )
    .or_else(||
         // TODO: Replace this with 𝘱𝘳𝘰𝘱𝘦𝘳 missingno texture
         builder.load(
             &"textures/phdm5/metb_seam".into(),
             raw.surface_flags.clone()
             )
        )
    .ok_or(())
}

fn get_string_hash(s: &String) -> u64 {
    use std::hash::{SipHasher, Hash, Hasher};

    let mut hasher = SipHasher::new();
    s.hash(&mut hasher);
    hasher.finish()
}

pub fn build_bsp<'a, T: Facade>(
    mut raw: RawBsp,
    texture_builder: &mut TextureBuilder<T>
) -> (Vec<Entity>, Bsp) {
    let tex = build_textures(
            &raw.textures,
            texture_builder
        ).expect("Invalid map");
    let ents = replace(&mut raw.entities, vec![]);
    let vertices = replace(&mut raw.vertices, vec![]);

    (
        ents,
        Bsp::new(
            build_nodes(&mut raw),
            build_leaves(&mut raw, &tex),
            vertices
        )
    )
}
<|endoftext|>


<commit_before>use std::old_io::{File, Open, Read};
use std::old_io::IoResult;
use super::GapBuffer;
use super::gap_buffer;
use super::Position;
use super::Range;

pub struct Buffer {
    data: GapBuffer,
    path: Option<Path>,
    pub cursor: Position,
}

impl Buffer {
    /// Returns the contents of the buffer as a string.
    ///
    /// # Examples
    ///
    /// ```
    /// let buffer = scribe::buffer::from_file(&Path::new("tests/sample/file")).unwrap();
    /// assert_eq!(buffer.data(), "it works!\n");
    /// ```
    pub fn data(&self) -> String {
        self.data.to_string()
    }

    /// Inserts `data` into the buffer at the cursor position.
    ///
    /// # Examples
    ///
    /// ```
    /// let mut buffer = scribe::buffer::new();
    /// buffer.insert("scribe");
    /// assert_eq!(buffer.data(), "scribe");
    /// ```
    pub fn insert(&mut self, data: &str) {
        self.data.insert(data, &self.cursor);
    }
}

/// Creates a new empty buffer. The buffer's cursor is set to the beginning of the buffer.
///
/// # Examples
///
/// ```
/// let buffer = scribe::buffer::new();
/// # assert_eq!(buffer.cursor.line, 0);
/// # assert_eq!(buffer.cursor.offset, 0);
/// ```
pub fn new() -> Buffer {
    let data = gap_buffer::new(String::new());
    let cursor = Position{ line: 0, offset: 0 };

    Buffer{ data: data, path: None, cursor: cursor }
}

/// Creates a new buffer by reading the UTF-8 interpreted file contents of the specified path.
/// The buffer's cursor is set to the beginning of the buffer.
///
/// # Examples
///
/// ```
/// let buffer = scribe::buffer::from_file(&Path::new("tests/sample/file")).unwrap();
/// assert_eq!(buffer.data(), "it works!\n");
/// # assert_eq!(buffer.cursor.line, 0);
/// # assert_eq!(buffer.cursor.offset, 0);
/// ```
pub fn from_file(path: &Path) -> IoResult<Buffer> {
    // Try to open and read the file, returning any errors encountered.
    let mut file = match File::open_mode(path, Open, Read) {
        Ok(f) => f,
        Err(error) => return Err(error),
    };
    let mut data = match file.read_to_string() {
        Ok(d) => d,
        Err(error) => return Err(error),
    };

    let data = gap_buffer::new(data);
    let cursor = Position{ line: 0, offset: 0 };

    // Create a new buffer using the loaded data, path, and other defaults.
    Ok(Buffer{ data: data, path: Some(path.clone()), cursor: cursor })
}
<commit_msg>Use buffer insert method to clarify data method documentation example.<commit_after>use std::old_io::{File, Open, Read};
use std::old_io::IoResult;
use super::GapBuffer;
use super::gap_buffer;
use super::Position;
use super::Range;

pub struct Buffer {
    data: GapBuffer,
    path: Option<Path>,
    pub cursor: Position,
}

impl Buffer {
    /// Returns the contents of the buffer as a string.
    ///
    /// # Examples
    ///
    /// ```
    /// let mut buffer = scribe::buffer::new();
    /// buffer.insert("scribe");
    /// assert_eq!(buffer.data(), "scribe");
    /// ```
    pub fn data(&self) -> String {
        self.data.to_string()
    }

    /// Inserts `data` into the buffer at the cursor position.
    ///
    /// # Examples
    ///
    /// ```
    /// let mut buffer = scribe::buffer::new();
    /// buffer.insert("scribe");
    /// assert_eq!(buffer.data(), "scribe");
    /// ```
    pub fn insert(&mut self, data: &str) {
        self.data.insert(data, &self.cursor);
    }
}

/// Creates a new empty buffer. The buffer's cursor is set to the beginning of the buffer.
///
/// # Examples
///
/// ```
/// let buffer = scribe::buffer::new();
/// # assert_eq!(buffer.cursor.line, 0);
/// # assert_eq!(buffer.cursor.offset, 0);
/// ```
pub fn new() -> Buffer {
    let data = gap_buffer::new(String::new());
    let cursor = Position{ line: 0, offset: 0 };

    Buffer{ data: data, path: None, cursor: cursor }
}

/// Creates a new buffer by reading the UTF-8 interpreted file contents of the specified path.
/// The buffer's cursor is set to the beginning of the buffer.
///
/// # Examples
///
/// ```
/// let buffer = scribe::buffer::from_file(&Path::new("tests/sample/file")).unwrap();
/// assert_eq!(buffer.data(), "it works!\n");
/// # assert_eq!(buffer.cursor.line, 0);
/// # assert_eq!(buffer.cursor.offset, 0);
/// ```
pub fn from_file(path: &Path) -> IoResult<Buffer> {
    // Try to open and read the file, returning any errors encountered.
    let mut file = match File::open_mode(path, Open, Read) {
        Ok(f) => f,
        Err(error) => return Err(error),
    };
    let mut data = match file.read_to_string() {
        Ok(d) => d,
        Err(error) => return Err(error),
    };

    let data = gap_buffer::new(data);
    let cursor = Position{ line: 0, offset: 0 };

    // Create a new buffer using the loaded data, path, and other defaults.
    Ok(Buffer{ data: data, path: Some(path.clone()), cursor: cursor })
}
<|endoftext|>


<commit_before>// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

//! Library used by tidy and other tools
//!
//! This library contains the tidy lints and exposes it
//! to be used by tools.

extern crate serde;
extern crate serde_json;
#[macro_use]
extern crate serde_derive;

use std::fs;

use std::path::Path;

macro_rules! t {
    ($e:expr, $p:expr) => (match $e {
        Ok(e) => e,
        Err(e) => panic!("{} failed on {} with {}", stringify!($e), ($p).display(), e),
    });

    ($e:expr) => (match $e {
        Ok(e) => e,
        Err(e) => panic!("{} failed with {}", stringify!($e), e),
    })
}

macro_rules! tidy_error {
    ($bad:expr, $fmt:expr, $($arg:tt)*) => ({
        *$bad = true;
        eprint!("tidy error: ");
        eprintln!($fmt, $($arg)*);
    });
}

pub mod bins;
pub mod style;
pub mod errors;
pub mod features;
pub mod cargo;
pub mod pal;
pub mod deps;
pub mod extdeps;
pub mod ui_tests;
pub mod unstable_book;
pub mod libcoretest;

fn filter_dirs(path: &Path) -> bool {
    let skip = [
        "src/dlmalloc",
        "src/jemalloc",
        "src/llvm",
        "src/llvm-emscripten",
        "src/libbacktrace",
        "src/libcompiler_builtins",
        "src/librustc_data_structures/owning_ref",
        "src/compiler-rt",
        "src/liblibc",
        "src/vendor",
        "src/rt/hoedown",
        "src/tools/cargo",
        "src/tools/clang",
        "src/tools/rls",
        "src/tools/clippy",
        "src/tools/rust-installer",
        "src/tools/rustfmt",
        "src/tools/miri",
        "src/tools/lld",
        "src/tools/lldb",
        "src/target",
        "src/stdsimd",
    ];
    skip.iter().any(|p| path.ends_with(p))
}

fn walk_many(paths: &[&Path], skip: &mut dyn FnMut(&Path) -> bool, f: &mut dyn FnMut(&Path)) {
    for path in paths {
        walk(path, skip, f);
    }
}

fn walk(path: &Path, skip: &mut dyn FnMut(&Path) -> bool, f: &mut dyn FnMut(&Path)) {
    if let Ok(dir) = fs::read_dir(path) {
        for entry in dir {
            let entry = t!(entry);
            let kind = t!(entry.file_type());
            let path = entry.path();
            if kind.is_dir() {
                if !skip(&path) {
                    walk(&path, skip, f);
                }
            } else {
                f(&path);
            }
        }
    }
}
<commit_msg>Rollup merge of #55213 - qmx:tidy-fix, r=tmandry<commit_after>// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

//! Library used by tidy and other tools
//!
//! This library contains the tidy lints and exposes it
//! to be used by tools.

extern crate serde;
extern crate serde_json;
#[macro_use]
extern crate serde_derive;

use std::fs;

use std::path::Path;

macro_rules! t {
    ($e:expr, $p:expr) => (match $e {
        Ok(e) => e,
        Err(e) => panic!("{} failed on {} with {}", stringify!($e), ($p).display(), e),
    });

    ($e:expr) => (match $e {
        Ok(e) => e,
        Err(e) => panic!("{} failed with {}", stringify!($e), e),
    })
}

macro_rules! tidy_error {
    ($bad:expr, $fmt:expr, $($arg:tt)*) => ({
        *$bad = true;
        eprint!("tidy error: ");
        eprintln!($fmt, $($arg)*);
    });
}

pub mod bins;
pub mod style;
pub mod errors;
pub mod features;
pub mod cargo;
pub mod pal;
pub mod deps;
pub mod extdeps;
pub mod ui_tests;
pub mod unstable_book;
pub mod libcoretest;

fn filter_dirs(path: &Path) -> bool {
    let skip = [
        "src/dlmalloc",
        "src/jemalloc",
        "src/llvm",
        "src/llvm-emscripten",
        "src/libbacktrace",
        "src/libcompiler_builtins",
        "src/librustc_data_structures/owning_ref",
        "src/compiler-rt",
        "src/liblibc",
        "src/vendor",
        "src/rt/hoedown",
        "src/tools/cargo",
        "src/tools/clang",
        "src/tools/rls",
        "src/tools/clippy",
        "src/tools/rust-installer",
        "src/tools/rustfmt",
        "src/tools/miri",
        "src/tools/lld",
        "src/tools/lldb",
        "src/target",
        "src/stdsimd",
        "target",
    ];
    skip.iter().any(|p| path.ends_with(p))
}

fn walk_many(paths: &[&Path], skip: &mut dyn FnMut(&Path) -> bool, f: &mut dyn FnMut(&Path)) {
    for path in paths {
        walk(path, skip, f);
    }
}

fn walk(path: &Path, skip: &mut dyn FnMut(&Path) -> bool, f: &mut dyn FnMut(&Path)) {
    if let Ok(dir) = fs::read_dir(path) {
        for entry in dir {
            let entry = t!(entry);
            let kind = t!(entry.file_type());
            let path = entry.path();
            if kind.is_dir() {
                if !skip(&path) {
                    walk(&path, skip, f);
                }
            } else {
                f(&path);
            }
        }
    }
}
<|endoftext|>


<commit_before>//! The lexer module.
//!
//! The simpler implementation of a lexer I could think of. It only takes a
//! stream of characters and tansforms it into a tokens one.
//!
//! It doesn't keep track of the current line or column. In a real compiler that
//! information is crucial when you write something wrong and don't know where.

use std::iter::Peekable;
use std::str::Chars;

/// Token types that our language admits.
///
/// All the token types that our little language will need. As it is a very
/// simple language, it doesn't have many. The lexer takes an input and has a
/// token iterator as the output.
///
/// The traits are mostly for tests.
#[derive(Debug, PartialEq)]
pub enum Token {
    /// For anything that we don't recognize.
    Illegal,
    /// Last token, when the input has ended.
    EOF,

    /// Any word: a variable name, a type name...
    Ident(String),

    /// Left parenthesis.
    ParL,
    /// Right parenthesis.
    ParR,
    /// The ':' character.
    Colon,
    /// The ';' character.
    Semicolon,
    /// The ',' character.
    Comma,

    /// The only keyword we have in the language.
    Type,
}

/// The lexer in our language.
///
/// The lexer, also known as tokenizer, transforms the input text into tokens.
pub struct Lexer<'a> {
    input: Peekable<Chars<'a>>,
}

impl Lexer<'_> {
    /// Create a new lexer.
    ///
    /// To build the lexer, you feed it a `str` with the code. Then you can use
    /// the lexer as a normal `Iterator`, which iterates over [`Token`s][1].
    ///
    /// # Examples
    ///
    ///     use simcom::lexer::{Lexer, Token};
    ///
    ///     let mut tokens = Lexer::new(": tipo");
    ///     assert_eq!(tokens.next().unwrap(), Token::Colon);
    ///     assert_eq!(tokens.next().unwrap(), Token::Type);
    ///     assert_eq!(tokens.next(), None);
    ///
    /// [1]: enum.Token.html
    pub fn new(input: &'_ str) -> Lexer {
        Lexer { input: input.chars().peekable() }
    }

    /// The next char in the input, advances the internal iterator.
    fn read_char(&mut self) -> Option<char> {
        self.input.next()
    }

    /// The next char in the input. *doesn't* advance the internal iterator.
    fn peek_char(&mut self) -> Option<&char> {
        self.input.peek()
    }

    /// If an alphabetic char was found, keep reading chars to build a
    /// identifier. Finally, look if it was a keyword.
    fn read_identifier(&mut self, ch: char) -> Token {
        let content = {
            // Since in ::next_token we need to call ::read_char the first
            // char was consumed, so we add it here.
            let mut content = String::new();
            content.push(ch);

            // Keep building the string with allowed characters.
            while let Some(&ch) = self.peek_char() {
                if !(ch.is_alphabetic() || ch.is_digit(10)) {
                    break;
                }

                // We call ::unwrap because we already made sure there is an
                // element with the ::peek above.
                content.push(self.read_char().unwrap());
            }

            content
        };

        // Match the identifier to all the known keywords to see if it is one
        // of them. Otherwise, return a normal identifier.
        match &content[..] {
            "tipo" => Token::Type,
            _ => Token::Ident(content),
        }
    }

    /// Advance the internal iterator when we find whitespace.
    fn consume_whitespace(&mut self) {
        while let Some(&ch) = self.peek_char() {
            if ch.is_whitespace() {
                self.read_char();
            } else {
                break;
            }
        }
    }

    /// The basis for the iterator, matches the characters to Tokens.
    fn next_token(&mut self) -> Token {
        self.consume_whitespace();

        if let Some(ch) = self.read_char() {
            match ch {
                '(' => Token::ParL,
                ')' => Token::ParR,
                ':' => Token::Colon,
                ';' => Token::Semicolon,
                ',' => Token::Comma,
                '\0' => Token::EOF,
                _ => if ch.is_alphabetic() {
                    // Read the remainder part of the identifier, passing its
                    // first character, as we already read it.
                    self.read_identifier(ch)
                } else {
                    Token::Illegal
                }
            }
        // If the internal iterator has given us a None, that means there are no
        // characters left. In other words, EOF was reached.
        } else {
            Token::EOF
        }
    }
}

impl Iterator for Lexer<'_> {
    type Item = Token;

    fn next(&mut self) -> Option<Self::Item> {
        match self.next_token() {
            Token::EOF => None,
            x => Some(x),
        }
    }
}
<commit_msg>Don't call Option::unwrap<commit_after>//! The lexer module.
//!
//! The simpler implementation of a lexer I could think of. It only takes a
//! stream of characters and tansforms it into a tokens one.
//!
//! It doesn't keep track of the current line or column. In a real compiler that
//! information is crucial when you write something wrong and don't know where.

use std::iter::Peekable;
use std::str::Chars;

/// Token types that our language admits.
///
/// All the token types that our little language will need. As it is a very
/// simple language, it doesn't have many. The lexer takes an input and has a
/// token iterator as the output.
///
/// The traits are mostly for tests.
#[derive(Debug, PartialEq)]
pub enum Token {
    /// For anything that we don't recognize.
    Illegal,
    /// Last token, when the input has ended.
    EOF,

    /// Any word: a variable name, a type name...
    Ident(String),

    /// Left parenthesis.
    ParL,
    /// Right parenthesis.
    ParR,
    /// The ':' character.
    Colon,
    /// The ';' character.
    Semicolon,
    /// The ',' character.
    Comma,

    /// The only keyword we have in the language.
    Type,
}

/// The lexer in our language.
///
/// The lexer, also known as tokenizer, transforms the input text into tokens.
pub struct Lexer<'a> {
    input: Peekable<Chars<'a>>,
}

impl Lexer<'_> {
    /// Create a new lexer.
    ///
    /// To build the lexer, you feed it a `str` with the code. Then you can use
    /// the lexer as a normal `Iterator`, which iterates over [`Token`s][1].
    ///
    /// # Examples
    ///
    ///     use simcom::lexer::{Lexer, Token};
    ///
    ///     let mut tokens = Lexer::new(": tipo");
    ///     assert_eq!(tokens.next().unwrap(), Token::Colon);
    ///     assert_eq!(tokens.next().unwrap(), Token::Type);
    ///     assert_eq!(tokens.next(), None);
    ///
    /// [1]: enum.Token.html
    pub fn new(input: &'_ str) -> Lexer {
        Lexer { input: input.chars().peekable() }
    }

    /// The next char in the input, advances the internal iterator.
    fn read_char(&mut self) -> Option<char> {
        self.input.next()
    }

    /// The next char in the input. *doesn't* advance the internal iterator.
    fn peek_char(&mut self) -> Option<&char> {
        self.input.peek()
    }

    /// If an alphabetic char was found, keep reading chars to build a
    /// identifier. Finally, look if it was a keyword.
    fn read_identifier(&mut self, ch: char) -> Token {
        let content = {
            // Since in ::next_token we need to call ::read_char the first
            // char was consumed, so we add it here.
            let mut content = String::new();
            content.push(ch);

            // Keep building the string with allowed characters.
            while let Some(&ch) = self.peek_char() {
                if !(ch.is_alphabetic() || ch.is_digit(10)) {
                    break;
                }

                // We consume the character we previously peeked. Then push it
                // to the string we're building.
                self.read_char();
                content.push(ch);
            }

            content
        };

        // Match the identifier to all the known keywords to see if it is one
        // of them. Otherwise, return a normal identifier.
        match &content[..] {
            "tipo" => Token::Type,
            _ => Token::Ident(content),
        }
    }

    /// Advance the internal iterator when we find whitespace.
    fn consume_whitespace(&mut self) {
        while let Some(&ch) = self.peek_char() {
            if ch.is_whitespace() {
                self.read_char();
            } else {
                break;
            }
        }
    }

    /// The basis for the iterator, matches the characters to Tokens.
    fn next_token(&mut self) -> Token {
        self.consume_whitespace();

        if let Some(ch) = self.read_char() {
            match ch {
                '(' => Token::ParL,
                ')' => Token::ParR,
                ':' => Token::Colon,
                ';' => Token::Semicolon,
                ',' => Token::Comma,
                '\0' => Token::EOF,
                _ => if ch.is_alphabetic() {
                    // Read the remainder part of the identifier, passing its
                    // first character, as we already read it.
                    self.read_identifier(ch)
                } else {
                    Token::Illegal
                }
            }
        // If the internal iterator has given us a None, that means there are no
        // characters left. In other words, EOF was reached.
        } else {
            Token::EOF
        }
    }
}

impl Iterator for Lexer<'_> {
    type Item = Token;

    fn next(&mut self) -> Option<Self::Item> {
        match self.next_token() {
            Token::EOF => None,
            x => Some(x),
        }
    }
}
<|endoftext|>


<commit_before>use super::{function, trait_impls};
use crate::{
    analysis::flags::Info,
    analysis::special_functions::Type,
    codegen::general::{
        self, cfg_deprecated, derives, doc_alias, version_condition, version_condition_string,
    },
    config::gobjects::GObject,
    env::Env,
    file_saver,
    library::*,
    nameutil::{bitfield_member_name, use_glib_type},
    traits::*,
};
use std::{
    io::{prelude::*, Result},
    path::Path,
};

pub fn generate(env: &Env, root_path: &Path, mod_rs: &mut Vec<String>) {
    if !env
        .analysis
        .flags
        .iter()
        .any(|f| env.config.objects[&f.full_name].status.need_generate())
    {
        return;
    }

    let path = root_path.join("flags.rs");
    file_saver::save_to_file(path, env.config.make_backup, |w| {
        general::start_comments(w, &env.config)?;
        general::uses(w, env, &env.analysis.flags_imports, None)?;
        writeln!(w)?;

        mod_rs.push("\nmod flags;".into());
        for flags_analysis in &env.analysis.flags {
            let config = &env.config.objects[&flags_analysis.full_name];
            if !config.status.need_generate() {
                continue;
            }
            let flags = flags_analysis.type_(&env.library);

            if let Some(cfg) = version_condition_string(env, flags.version, false, 0) {
                mod_rs.push(cfg);
            }
            mod_rs.push(format!("pub use self::flags::{};", flags.name));
            generate_flags(env, w, flags, config, flags_analysis)?;
        }

        Ok(())
    });
}

#[allow(clippy::write_literal)]
fn generate_flags(
    env: &Env,
    w: &mut dyn Write,
    flags: &Bitfield,
    config: &GObject,
    analysis: &Info,
) -> Result<()> {
    let sys_crate_name = env.main_sys_crate_name();
    cfg_deprecated(w, env, flags.deprecated_version, false, 0)?;
    version_condition(w, env, flags.version, false, 0)?;
    writeln!(w, "bitflags! {{")?;
    if config.must_use {
        writeln!(w, "    #[must_use]")?;
    }

    if let Some(ref d) = config.derives {
        derives(w, &d, 1)?;
    }

    doc_alias(w, &flags.c_type, "", 1)?;
    writeln!(w, "    pub struct {}: u32 {{", flags.name)?;
    for member in &flags.members {
        let member_config = config.members.matched(&member.name);
        if member.status.ignored() {
            continue;
        }

        let name = bitfield_member_name(&member.name);
        let deprecated_version = member_config.iter().find_map(|m| m.deprecated_version);
        let version = member_config.iter().find_map(|m| m.version);
        cfg_deprecated(w, env, deprecated_version, false, 2)?;
        version_condition(w, env, version, false, 2)?;
        if member.c_identifier != member.name {
            doc_alias(w, &member.c_identifier, "", 2)?;
        }
        writeln!(
            w,
            "\t\tconst {} = ffi::{} as u32;",
            name, member.c_identifier
        )?;
    }

    writeln!(
        w,
        "    }}
}}"
    )?;

    let functions = analysis
        .functions
        .iter()
        .filter(|f| f.status.need_generate())
        .collect::<Vec<_>>();

    if !functions.is_empty() {
        writeln!(w)?;
        version_condition(w, env, flags.version, false, 0)?;
        write!(w, "impl {} {{", analysis.name)?;
        for func_analysis in functions {
            function::generate(
                w,
                env,
                func_analysis,
                Some(&analysis.specials),
                flags.version,
                false,
                false,
                1,
            )?;
        }
        writeln!(w, "}}")?;
    }

    trait_impls::generate(
        w,
        env,
        &analysis.name,
        &analysis.functions,
        &analysis.specials,
        None,
        None,
    )?;

    writeln!(w)?;

    if config.generate_display_trait && !analysis.specials.has_trait(Type::Display) {
        // Generate Display trait implementation.
        version_condition(w, env, flags.version, false, 0)?;
        writeln!(
            w,
            "impl fmt::Display for {0} {{\n\
            \tfn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {{\n\
            \t\t<Self as fmt::Debug>::fmt(self, f)\n\
            \t}}\n\
            }}\n",
            flags.name
        )?;
    }

    version_condition(w, env, flags.version, false, 0)?;
    writeln!(
        w,
        "#[doc(hidden)]
impl IntoGlib for {name} {{
    type GlibType = {sys_crate_name}::{ffi_name};

    fn into_glib(self) -> {sys_crate_name}::{ffi_name} {{
        self.bits()
    }}
}}
",
        sys_crate_name = sys_crate_name,
        name = flags.name,
        ffi_name = flags.c_type
    )?;

    let assert = if env.config.generate_safety_asserts {
        "skip_assert_initialized!();\n\t\t"
    } else {
        ""
    };

    version_condition(w, env, flags.version, false, 0)?;
    writeln!(
        w,
        "#[doc(hidden)]
impl FromGlib<{sys_crate_name}::{ffi_name}> for {name} {{
    unsafe fn from_glib(value: {sys_crate_name}::{ffi_name}) -> Self {{
        {assert}Self::from_bits_truncate(value)
    }}
}}
",
        sys_crate_name = sys_crate_name,
        name = flags.name,
        ffi_name = flags.c_type,
        assert = assert
    )?;

    if let Some(ref get_type) = flags.glib_get_type {
        let configured_functions = config.functions.matched("get_type");
        let version = std::iter::once(flags.version)
            .chain(configured_functions.iter().map(|f| f.version))
            .max()
            .flatten();

        version_condition(w, env, version, false, 0)?;
        writeln!(
            w,
            "impl StaticType for {name} {{
    fn static_type() -> Type {{
        unsafe {{ from_glib({sys_crate_name}::{get_type}()) }}
    }}
}}",
            sys_crate_name = sys_crate_name,
            name = flags.name,
            get_type = get_type
        )?;
        writeln!(w)?;

        version_condition(w, env, version, false, 0)?;
        writeln!(
            w,
            "impl {valuetype} for {name} {{
    type Type = Self;
}}",
            name = flags.name,
            valuetype = use_glib_type(env, "value::ValueType"),
        )?;
        writeln!(w)?;

        version_condition(w, env, version, false, 0)?;
        writeln!(
            w,
            "unsafe impl<'a> FromValue<'a> for {name} {{
    type Checker = {genericwrongvaluetypechecker}<Self>;

    unsafe fn from_value(value: &'a {gvalue}) -> Self {{
        {assert}from_glib({glib}(value.to_glib_none().0))
    }}
}}",
            name = flags.name,
            glib = use_glib_type(env, "gobject_ffi::g_value_get_flags"),
            gvalue = use_glib_type(env, "Value"),
            genericwrongvaluetypechecker = use_glib_type(env, "value::GenericValueTypeChecker"),
            assert = assert,
        )?;
        writeln!(w)?;

        version_condition(w, env, version, false, 0)?;
        writeln!(
            w,
            "impl ToValue for {name} {{
    fn to_value(&self) -> {gvalue} {{
        let mut value = {gvalue}::for_value_type::<Self>();
        unsafe {{
            {glib}(value.to_glib_none_mut().0, self.into_glib());
        }}
        value
    }}

    fn value_type(&self) -> {gtype} {{
        Self::static_type()
    }}
}}",
            name = flags.name,
            glib = use_glib_type(env, "gobject_ffi::g_value_set_flags"),
            gvalue = use_glib_type(env, "Value"),
            gtype = use_glib_type(env, "Type"),
        )?;
        writeln!(w)?;
    }

    Ok(())
}
<commit_msg>Fix sys crate name for bitfields<commit_after>use super::{function, trait_impls};
use crate::{
    analysis::flags::Info,
    analysis::special_functions::Type,
    codegen::general::{
        self, cfg_deprecated, derives, doc_alias, version_condition, version_condition_string,
    },
    config::gobjects::GObject,
    env::Env,
    file_saver,
    library::*,
    nameutil::{bitfield_member_name, use_glib_type},
    traits::*,
};
use std::{
    io::{prelude::*, Result},
    path::Path,
};

pub fn generate(env: &Env, root_path: &Path, mod_rs: &mut Vec<String>) {
    if !env
        .analysis
        .flags
        .iter()
        .any(|f| env.config.objects[&f.full_name].status.need_generate())
    {
        return;
    }

    let path = root_path.join("flags.rs");
    file_saver::save_to_file(path, env.config.make_backup, |w| {
        general::start_comments(w, &env.config)?;
        general::uses(w, env, &env.analysis.flags_imports, None)?;
        writeln!(w)?;

        mod_rs.push("\nmod flags;".into());
        for flags_analysis in &env.analysis.flags {
            let config = &env.config.objects[&flags_analysis.full_name];
            if !config.status.need_generate() {
                continue;
            }
            let flags = flags_analysis.type_(&env.library);

            if let Some(cfg) = version_condition_string(env, flags.version, false, 0) {
                mod_rs.push(cfg);
            }
            mod_rs.push(format!("pub use self::flags::{};", flags.name));
            generate_flags(env, w, flags, config, flags_analysis)?;
        }

        Ok(())
    });
}

#[allow(clippy::write_literal)]
fn generate_flags(
    env: &Env,
    w: &mut dyn Write,
    flags: &Bitfield,
    config: &GObject,
    analysis: &Info,
) -> Result<()> {
    let sys_crate_name = env.main_sys_crate_name();
    cfg_deprecated(w, env, flags.deprecated_version, false, 0)?;
    version_condition(w, env, flags.version, false, 0)?;
    writeln!(w, "bitflags! {{")?;
    if config.must_use {
        writeln!(w, "    #[must_use]")?;
    }

    if let Some(ref d) = config.derives {
        derives(w, &d, 1)?;
    }

    doc_alias(w, &flags.c_type, "", 1)?;
    writeln!(w, "    pub struct {}: u32 {{", flags.name)?;
    for member in &flags.members {
        let member_config = config.members.matched(&member.name);
        if member.status.ignored() {
            continue;
        }

        let name = bitfield_member_name(&member.name);
        let deprecated_version = member_config.iter().find_map(|m| m.deprecated_version);
        let version = member_config.iter().find_map(|m| m.version);
        cfg_deprecated(w, env, deprecated_version, false, 2)?;
        version_condition(w, env, version, false, 2)?;
        if member.c_identifier != member.name {
            doc_alias(w, &member.c_identifier, "", 2)?;
        }
        writeln!(
            w,
            "\t\tconst {} = {}::{} as u32;",
            name, sys_crate_name, member.c_identifier,
        )?;
    }

    writeln!(
        w,
        "    }}
}}"
    )?;

    let functions = analysis
        .functions
        .iter()
        .filter(|f| f.status.need_generate())
        .collect::<Vec<_>>();

    if !functions.is_empty() {
        writeln!(w)?;
        version_condition(w, env, flags.version, false, 0)?;
        write!(w, "impl {} {{", analysis.name)?;
        for func_analysis in functions {
            function::generate(
                w,
                env,
                func_analysis,
                Some(&analysis.specials),
                flags.version,
                false,
                false,
                1,
            )?;
        }
        writeln!(w, "}}")?;
    }

    trait_impls::generate(
        w,
        env,
        &analysis.name,
        &analysis.functions,
        &analysis.specials,
        None,
        None,
    )?;

    writeln!(w)?;

    if config.generate_display_trait && !analysis.specials.has_trait(Type::Display) {
        // Generate Display trait implementation.
        version_condition(w, env, flags.version, false, 0)?;
        writeln!(
            w,
            "impl fmt::Display for {0} {{\n\
            \tfn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {{\n\
            \t\t<Self as fmt::Debug>::fmt(self, f)\n\
            \t}}\n\
            }}\n",
            flags.name
        )?;
    }

    version_condition(w, env, flags.version, false, 0)?;
    writeln!(
        w,
        "#[doc(hidden)]
impl IntoGlib for {name} {{
    type GlibType = {sys_crate_name}::{ffi_name};

    fn into_glib(self) -> {sys_crate_name}::{ffi_name} {{
        self.bits()
    }}
}}
",
        sys_crate_name = sys_crate_name,
        name = flags.name,
        ffi_name = flags.c_type
    )?;

    let assert = if env.config.generate_safety_asserts {
        "skip_assert_initialized!();\n\t\t"
    } else {
        ""
    };

    version_condition(w, env, flags.version, false, 0)?;
    writeln!(
        w,
        "#[doc(hidden)]
impl FromGlib<{sys_crate_name}::{ffi_name}> for {name} {{
    unsafe fn from_glib(value: {sys_crate_name}::{ffi_name}) -> Self {{
        {assert}Self::from_bits_truncate(value)
    }}
}}
",
        sys_crate_name = sys_crate_name,
        name = flags.name,
        ffi_name = flags.c_type,
        assert = assert
    )?;

    if let Some(ref get_type) = flags.glib_get_type {
        let configured_functions = config.functions.matched("get_type");
        let version = std::iter::once(flags.version)
            .chain(configured_functions.iter().map(|f| f.version))
            .max()
            .flatten();

        version_condition(w, env, version, false, 0)?;
        writeln!(
            w,
            "impl StaticType for {name} {{
    fn static_type() -> Type {{
        unsafe {{ from_glib({sys_crate_name}::{get_type}()) }}
    }}
}}",
            sys_crate_name = sys_crate_name,
            name = flags.name,
            get_type = get_type
        )?;
        writeln!(w)?;

        version_condition(w, env, version, false, 0)?;
        writeln!(
            w,
            "impl {valuetype} for {name} {{
    type Type = Self;
}}",
            name = flags.name,
            valuetype = use_glib_type(env, "value::ValueType"),
        )?;
        writeln!(w)?;

        version_condition(w, env, version, false, 0)?;
        writeln!(
            w,
            "unsafe impl<'a> FromValue<'a> for {name} {{
    type Checker = {genericwrongvaluetypechecker}<Self>;

    unsafe fn from_value(value: &'a {gvalue}) -> Self {{
        {assert}from_glib({glib}(value.to_glib_none().0))
    }}
}}",
            name = flags.name,
            glib = use_glib_type(env, "gobject_ffi::g_value_get_flags"),
            gvalue = use_glib_type(env, "Value"),
            genericwrongvaluetypechecker = use_glib_type(env, "value::GenericValueTypeChecker"),
            assert = assert,
        )?;
        writeln!(w)?;

        version_condition(w, env, version, false, 0)?;
        writeln!(
            w,
            "impl ToValue for {name} {{
    fn to_value(&self) -> {gvalue} {{
        let mut value = {gvalue}::for_value_type::<Self>();
        unsafe {{
            {glib}(value.to_glib_none_mut().0, self.into_glib());
        }}
        value
    }}

    fn value_type(&self) -> {gtype} {{
        Self::static_type()
    }}
}}",
            name = flags.name,
            glib = use_glib_type(env, "gobject_ffi::g_value_set_flags"),
            gvalue = use_glib_type(env, "Value"),
            gtype = use_glib_type(env, "Type"),
        )?;
        writeln!(w)?;
    }

    Ok(())
}
<|endoftext|>


<commit_before>use error::{CliError, Usage, UsageKind};
use super::Command;

use lib::setting::{Config, ConfigKey};
use lib::setting::Cron;

#[derive(Debug)]
pub struct Start;

impl Command for Start {
    fn validation(&self) -> bool { true }

    fn usage(&self) -> Usage {
        return Usage::new(UsageKind::Start);
    }

    fn main(&self) -> Result<(), CliError> {
        let cron = try!(Cron::read());

        let pair_for_burn = ("0 0 * * *", "burn");

        let config        = try!(Config::read());
        let day_and_month = match try!(config.get(ConfigKey::SweepPeriod)).as_ref() {
            "daily"  => "* * *",
            "weekly" => "* * 0",
            _        => unreachable!("Mistake SweepPeriod's validation!!"),
        };
        let (hour, minute) = Config::to_hour_and_minute(try!(config.get(ConfigKey::SweepTime)));
        let when = format!("{} {} {}", minute, hour, day_and_month);
        let pair_for_sweep = (&when as &str, "sweep");

        cron
            .update(&[pair_for_burn, pair_for_sweep])
            .and_then(|new_cron| new_cron.set())
    }
}
<commit_msg>[Refactoring] Summarize "import"s<commit_after>use error::{CliError, Usage, UsageKind};
use super::Command;

use lib::setting::{Config, ConfigKey, Cron};

#[derive(Debug)]
pub struct Start;

impl Command for Start {
    fn validation(&self) -> bool { true }

    fn usage(&self) -> Usage {
        return Usage::new(UsageKind::Start);
    }

    fn main(&self) -> Result<(), CliError> {
        let cron = try!(Cron::read());

        let pair_for_burn = ("0 0 * * *", "burn");

        let config        = try!(Config::read());
        let day_and_month = match try!(config.get(ConfigKey::SweepPeriod)).as_ref() {
            "daily"  => "* * *",
            "weekly" => "* * 0",
            _        => unreachable!("Mistake SweepPeriod's validation!!"),
        };
        let (hour, minute) = Config::to_hour_and_minute(try!(config.get(ConfigKey::SweepTime)));
        let when = format!("{} {} {}", minute, hour, day_and_month);
        let pair_for_sweep = (&when as &str, "sweep");

        cron
            .update(&[pair_for_burn, pair_for_sweep])
            .and_then(|new_cron| new_cron.set())
    }
}
<|endoftext|>