<commit_before>//! # Parser Nodes
//!
//! Parser nodes represent the grammar that is defined
//! by the currently permissible set of commands and their
//! parameters.

#![allow(missing_docs)]

use std::rc::Rc;

/// Minimum priority.
pub const PRIORITY_MINIMUM: i32 = -10000;
/// The default priority for a parameter.
pub const PRIORITY_PARAMETER: i32 = -10;
/// The default priority.
pub const PRIORITY_DEFAULT: i32 = 0;

pub trait Node {
    fn node_data(&self) -> &NodeFields;

    fn successors(&self) -> &Vec<Rc<Node>> {
        &self.node_data().successors
    }

    fn help_symbol(&self) -> String {
        self.node_data().name.to_string()
    }

    fn help_text(&self) -> &String {
        unimplemented!();
    }

    fn hidden(&self) -> bool {
        self.node_data().hidden
    }

    fn name(&self) -> &String {
        &self.node_data().name
    }

    fn priority(&self) -> i32 {
        self.node_data().priority
    }
}

/// A parse tree node.
pub struct NodeFields {
    /// Possible successor nodes. Collected while building.
    pub successors: Vec<Rc<Node>>,
    /// The name of this node.
    pub name: String,
    /// Match and complete priority.
    pub priority: i32,
    /// Hidden nodes are not completed. This doesn't modify matching.
    pub hidden: bool,
}

pub struct CommandNode {
    fields: CommandNodeFields,
}

pub struct CommandNodeFields {
    node: NodeFields,
    help: String,
    handler: Option<fn(&node: Node) -> ()>,
    parameters: Vec<Rc<ParameterNode>>,
}

impl Node for CommandNode {
    fn node_data(&self) -> &NodeFields {
        &self.fields.node
    }

    fn help_text(&self) -> &String {
        &self.fields.help
    }
}

impl CommandNode {
    pub fn handler(&self) -> Option<fn(&node: Node) -> ()> {
        self.fields.handler
    }

    /// Get the parameter nodes for this command
    pub fn parameters(&self) -> &Vec<Rc<ParameterNode>> {
        &self.fields.parameters
    }
}

pub struct WrapperNode {
    fields: WrapperNodeFields,
}

pub struct WrapperNodeFields {
    command: CommandNodeFields,
    root: Rc<Node>,
}

impl Node for WrapperNode {
    fn node_data(&self) -> &NodeFields {
        &self.fields.command.node
    }

    fn successors(&self) -> &Vec<Rc<Node>> {
        self.fields.root.successors()
    }
}

pub struct ParameterNameNode {
    fields: ParameterNameNodeFields,
}

pub struct RepeatableNodeFields {
    repeatable: bool,
    repeat_marker: Option<Rc<Node>>,
}

pub struct ParameterNameNodeFields {
    node: NodeFields,
    repeatable: RepeatableNodeFields,
    help: String,
    parameter: Rc<Node>,
}

impl Node for ParameterNameNode {
    fn node_data(&self) -> &NodeFields {
        &self.fields.node
    }

    fn help_symbol(&self) -> String {
        self.fields.node.name.clone() + " " + self.fields.parameter.help_symbol().as_str()
    }

    fn help_text(&self) -> &String {
        &self.fields.help
    }
}

impl ParameterNameNode {
    pub fn repeatable(&self) -> bool {
        self.fields.repeatable.repeatable
    }

    pub fn repeat_marker(&self) -> &Option<Rc<Node>> {
        &self.fields.repeatable.repeat_marker
    }
}

pub trait ParameterNode {
    fn parameter_data(&self) -> &ParameterNodeFields;

    fn repeatable(&self) -> bool {
        self.parameter_data().repeatable.repeatable
    }

    fn repeat_marker(&self) -> &Option<Rc<Node>> {
        &self.parameter_data().repeatable.repeat_marker
    }

    fn required(&self) -> bool {
        self.parameter_data().required
    }
}

pub struct ParameterNodeFields {
    node: NodeFields,
    repeatable: RepeatableNodeFields,
    help: String,
    required: bool,
}

impl Node for ParameterNode {
    fn node_data(&self) -> &NodeFields {
        &self.parameter_data().node
    }

    fn help_symbol(&self) -> String {
        String::from("<") + self.node_data().name.as_str() +
        if self.repeatable() {
            ">..."
        } else {
            ">"
        }
    }

    fn help_text(&self) -> &String {
        &self.parameter_data().help
    }
}

pub struct FlagParameterNode {
    fields: ParameterNodeFields,
}

impl ParameterNode for FlagParameterNode {
    fn parameter_data(&self) -> &ParameterNodeFields {
        &self.fields
    }
}

pub struct NamedParameterNode {
    fields: ParameterNodeFields,
}

impl ParameterNode for NamedParameterNode {
    fn parameter_data(&self) -> &ParameterNodeFields {
        &self.fields
    }
}

pub struct SimpleParameterNode {
    fields: ParameterNodeFields,
}

impl ParameterNode for SimpleParameterNode {
    fn parameter_data(&self) -> &ParameterNodeFields {
        &self.fields
    }
}
<commit_msg>Add RepeatableNode trait.<commit_after>//! # Parser Nodes
//!
//! Parser nodes represent the grammar that is defined
//! by the currently permissible set of commands and their
//! parameters.

#![allow(missing_docs)]

use std::rc::Rc;

/// Minimum priority.
pub const PRIORITY_MINIMUM: i32 = -10000;
/// The default priority for a parameter.
pub const PRIORITY_PARAMETER: i32 = -10;
/// The default priority.
pub const PRIORITY_DEFAULT: i32 = 0;

pub trait Node {
    fn node_data(&self) -> &NodeFields;

    fn successors(&self) -> &Vec<Rc<Node>> {
        &self.node_data().successors
    }

    fn help_symbol(&self) -> String {
        self.node_data().name.to_string()
    }

    fn help_text(&self) -> &String {
        unimplemented!();
    }

    fn hidden(&self) -> bool {
        self.node_data().hidden
    }

    fn name(&self) -> &String {
        &self.node_data().name
    }

    fn priority(&self) -> i32 {
        self.node_data().priority
    }
}

/// A parse tree node.
pub struct NodeFields {
    /// Possible successor nodes. Collected while building.
    pub successors: Vec<Rc<Node>>,
    /// The name of this node.
    pub name: String,
    /// Match and complete priority.
    pub priority: i32,
    /// Hidden nodes are not completed. This doesn't modify matching.
    pub hidden: bool,
}

pub struct CommandNode {
    fields: CommandNodeFields,
}

pub struct CommandNodeFields {
    node: NodeFields,
    help: String,
    handler: Option<fn(&node: Node) -> ()>,
    parameters: Vec<Rc<ParameterNode>>,
}

impl Node for CommandNode {
    fn node_data(&self) -> &NodeFields {
        &self.fields.node
    }

    fn help_text(&self) -> &String {
        &self.fields.help
    }
}

impl CommandNode {
    pub fn handler(&self) -> Option<fn(&node: Node) -> ()> {
        self.fields.handler
    }

    /// Get the parameter nodes for this command
    pub fn parameters(&self) -> &Vec<Rc<ParameterNode>> {
        &self.fields.parameters
    }
}

pub struct WrapperNode {
    fields: WrapperNodeFields,
}

pub struct WrapperNodeFields {
    command: CommandNodeFields,
    root: Rc<Node>,
}

impl Node for WrapperNode {
    fn node_data(&self) -> &NodeFields {
        &self.fields.command.node
    }

    fn successors(&self) -> &Vec<Rc<Node>> {
        self.fields.root.successors()
    }
}

pub trait RepeatableNode: Node {
    fn repeatable_data(&self) -> &RepeatableNodeFields;

    fn repeatable(&self) -> bool {
        self.repeatable_data().repeatable
    }

    fn repeat_marker(&self) -> &Option<Rc<Node>> {
        &self.repeatable_data().repeat_marker
    }
}

pub struct RepeatableNodeFields {
    repeatable: bool,
    repeat_marker: Option<Rc<Node>>,
}

pub struct ParameterNameNode {
    fields: ParameterNameNodeFields,
}

pub struct ParameterNameNodeFields {
    node: NodeFields,
    repeatable: RepeatableNodeFields,
    help: String,
    parameter: Rc<Node>,
}

impl Node for ParameterNameNode {
    fn node_data(&self) -> &NodeFields {
        &self.fields.node
    }

    fn help_symbol(&self) -> String {
        self.fields.node.name.clone() + " " + self.fields.parameter.help_symbol().as_str()
    }

    fn help_text(&self) -> &String {
        &self.fields.help
    }
}

impl RepeatableNode for ParameterNameNode {
    fn repeatable_data(&self) -> &RepeatableNodeFields {
        &self.fields.repeatable
    }
}

pub trait ParameterNode {
    fn parameter_data(&self) -> &ParameterNodeFields;

    fn required(&self) -> bool {
        self.parameter_data().required
    }
}

impl RepeatableNode for ParameterNode {
    fn repeatable_data(&self) -> &RepeatableNodeFields {
        &self.parameter_data().repeatable
    }
}

pub struct ParameterNodeFields {
    node: NodeFields,
    repeatable: RepeatableNodeFields,
    help: String,
    required: bool,
}

impl Node for ParameterNode {
    fn node_data(&self) -> &NodeFields {
        &self.parameter_data().node
    }

    fn help_symbol(&self) -> String {
        String::from("<") + self.node_data().name.as_str() +
        if self.repeatable() {
            ">..."
        } else {
            ">"
        }
    }

    fn help_text(&self) -> &String {
        &self.parameter_data().help
    }
}

pub struct FlagParameterNode {
    fields: ParameterNodeFields,
}

impl ParameterNode for FlagParameterNode {
    fn parameter_data(&self) -> &ParameterNodeFields {
        &self.fields
    }
}

pub struct NamedParameterNode {
    fields: ParameterNodeFields,
}

impl ParameterNode for NamedParameterNode {
    fn parameter_data(&self) -> &ParameterNodeFields {
        &self.fields
    }
}

pub struct SimpleParameterNode {
    fields: ParameterNodeFields,
}

impl ParameterNode for SimpleParameterNode {
    fn parameter_data(&self) -> &ParameterNodeFields {
        &self.fields
    }
}
<|endoftext|>


<commit_before>//! Printer for displaying module structure as a tree.

use std::fmt;

use petgraph::{
    algo::is_cyclic_directed,
    graph::{EdgeIndex, NodeIndex},
    visit::EdgeRef,
    Direction,
};
use yansi::Style;

use crate::{
    graph::{
        edge::{Edge, EdgeKind},
        node::{visibility::NodeVisibility, Node, NodeKind},
        Graph,
    },
    theme::tree::styles,
};

#[derive(Debug)]
struct Twig {
    is_last: bool,
}

#[derive(Clone, Debug)]
pub struct Options {}

pub struct Printer {
    #[allow(dead_code)]
    options: Options,
}

impl Printer {
    pub fn new(options: Options) -> Self {
        Self { options }
    }

    pub fn fmt(
        &self,
        f: &mut dyn fmt::Write,
        graph: &Graph,
        start_node_idx: NodeIndex,
    ) -> Result<(), anyhow::Error> {
        assert!(!is_cyclic_directed(graph));

        let mut twigs: Vec<Twig> = vec![Twig { is_last: true }];
        self.fmt_tree(f, graph, None, start_node_idx, &mut twigs)
    }

    fn fmt_tree(
        &self,
        f: &mut dyn fmt::Write,
        graph: &Graph,
        edge_idx: Option<EdgeIndex>,
        node_idx: NodeIndex,
        twigs: &mut Vec<Twig>,
    ) -> Result<(), anyhow::Error> {
        let edge = edge_idx.map(|idx| &graph[idx]);
        let node = &graph[node_idx];

        self.fmt_branch(f, edge, &twigs[..])?;
        self.fmt_node(f, node)?;
        writeln!(f)?;

        let mut children: Vec<_> = graph
            .edges_directed(node_idx, Direction::Outgoing)
            .filter_map(|edge_ref| {
                let edge_idx = edge_ref.id();
                let edge = &graph[edge_idx];

                // We're only interested in "owns" relationships here:
                let is_owns_edge = edge.kind == EdgeKind::Owns;
                debug_assert!(is_owns_edge);

                if !is_owns_edge {
                    return None;
                }

                let node_idx = edge_ref.target();
                let node = &graph[node_idx];

                let key = node.display_name();
                Some((node_idx, edge_idx, key))
            })
            .collect();

        // Sort the children by name for easier visual scanning of output:
        children.sort_by(|lhs, rhs| {
            let (_lhs_node, _lhs_edge, lhs_key) = lhs;
            let (_rhs_node, _rhs_edge, rhs_key) = rhs;
            lhs_key.cmp(&rhs_key)
        });

        let count = children.len();
        for (pos, (node_idx, edge_idx, _)) in children.into_iter().enumerate() {
            let is_last = pos + 1 == count;
            twigs.push(Twig { is_last });
            self.fmt_tree(f, graph, Some(edge_idx), node_idx, twigs)?;
            twigs.pop();
        }

        Ok(())
    }

    fn fmt_node(&self, f: &mut dyn fmt::Write, node: &Node) -> fmt::Result {
        self.fmt_node_kind(f, node)?;
        write!(f, " ")?;
        self.fmt_node_name(f, node)?;

        if node.kind == NodeKind::Crate {
            return Ok(());
        }

        self.fmt_node_colon(f, node)?;
        write!(f, " ")?;
        self.fmt_node_visibility(f, node)?;

        if !node.attrs.is_empty() {
            write!(f, " ")?;
            self.fmt_node_attrs(f, node)?;
        }

        Ok(())
    }

    fn fmt_node_kind(&self, f: &mut dyn fmt::Write, node: &Node) -> fmt::Result {
        let kind_style = self.kind_style();

        let display_name = node.kind.display_name().unwrap_or("mod");
        let kind = kind_style.paint(display_name);

        write!(f, "{}", kind)?;

        Ok(())
    }

    fn fmt_node_colon(&self, f: &mut dyn fmt::Write, _node: &Node) -> fmt::Result {
        let colon_style = self.colon_style();

        let colon = colon_style.paint(":");
        write!(f, "{}", colon)?;

        Ok(())
    }

    fn fmt_node_visibility(&self, f: &mut dyn fmt::Write, node: &Node) -> fmt::Result {
        let (visibility, visibility_style) = match &node.visibility {
            Some(visibility) => {
                let visibility_style = self.visibility_style(&visibility);
                (format!("{}", visibility), visibility_style)
            }
            None => {
                let orphan_style = self.orphan_style();
                ("orphan".to_owned(), orphan_style)
            }
        };

        let visibility = visibility_style.paint(visibility);
        write!(f, "{}", visibility)?;

        Ok(())
    }

    fn fmt_node_name(&self, f: &mut dyn fmt::Write, node: &Node) -> fmt::Result {
        let name_style = self.name_style();

        let name = name_style.paint(node.display_name());
        write!(f, "{}", name)?;

        Ok(())
    }

    fn fmt_node_attrs(&self, f: &mut dyn fmt::Write, node: &Node) -> fmt::Result {
        let attr_chrome_style = self.attr_chrome_style();
        let attr_style = self.attr_style();

        let mut is_first = true;

        if let Some(test_attr) = &node.attrs.test {
            let prefix = attr_chrome_style.paint("#[");
            let cfg = attr_style.paint(test_attr);
            let suffix = attr_chrome_style.paint("]");

            write!(f, "{}{}{}", prefix, cfg, suffix)?;

            is_first = false;
        }

        let attr_chrome_style = self.attr_chrome_style();
        let attr_style = self.attr_style();

        for cfg in &node.attrs.cfgs[..] {
            if !is_first {
                write!(f, ", ")?;
            }

            let prefix = attr_chrome_style.paint("#[cfg(");
            let cfg = attr_style.paint(cfg);
            let suffix = attr_chrome_style.paint(")]");

            write!(f, "{}{}{}", prefix, cfg, suffix)?;

            is_first = false;
        }

        Ok(())
    }

    fn fmt_branch(
        &self,
        f: &mut dyn fmt::Write,
        _edge: Option<&Edge>,
        twigs: &[Twig],
    ) -> fmt::Result {
        let prefix = self.branch_prefix(&twigs[..]);
        write!(f, "{}", self.branch_style().paint(&prefix))
    }

    /// Print a branch's prefix:
    fn branch_prefix(&self, twigs: &[Twig]) -> String {
        fn trunk_str(_is_last: bool) -> &'static str {
            ""
        }

        fn branch_str(is_last: bool) -> &'static str {
            if is_last {
                "    "
            } else {
                "│   "
            }
        }

        fn leaf_str(is_last: bool) -> &'static str {
            if is_last {
                "└── "
            } else {
                "├── "
            }
        }

        let mut string = String::new();

        // First level is crate level, we need to skip it when
        // printing. But we cannot easily drop the first value.
        match twigs {
            [trunk, branches @ .., leaf] => {
                string.push_str(trunk_str(trunk.is_last));
                for branch in branches {
                    string.push_str(branch_str(branch.is_last));
                }
                string.push_str(leaf_str(leaf.is_last));
            }
            [trunk] => {
                string.push_str(trunk_str(trunk.is_last));
            }
            [] => {}
        }

        string
    }

    fn colon_style(&self) -> Style {
        Style::default().dimmed()
    }

    fn attr_chrome_style(&self) -> Style {
        Style::default().dimmed()
    }

    fn branch_style(&self) -> Style {
        Style::default().dimmed()
    }

    fn name_style(&self) -> Style {
        let styles = styles();
        styles.name
    }

    fn kind_style(&self) -> Style {
        let styles = styles();
        styles.kind
    }

    fn visibility_style(&self, visibility: &NodeVisibility) -> Style {
        let styles = styles().visibility;

        match visibility {
            NodeVisibility::Crate => styles.pub_crate,
            NodeVisibility::Module(_) => styles.pub_module,
            NodeVisibility::Private => styles.pub_private,
            NodeVisibility::Public => styles.pub_global,
            NodeVisibility::Super => styles.pub_super,
        }
    }

    fn orphan_style(&self) -> Style {
        let styles = styles();
        styles.orphan
    }

    fn attr_style(&self) -> Style {
        let styles = styles();
        styles.attr
    }
}
<commit_msg>Fix clippy warnings<commit_after>//! Printer for displaying module structure as a tree.

use std::fmt;

use petgraph::{
    algo::is_cyclic_directed,
    graph::{EdgeIndex, NodeIndex},
    visit::EdgeRef,
    Direction,
};
use yansi::Style;

use crate::{
    graph::{
        edge::{Edge, EdgeKind},
        node::{visibility::NodeVisibility, Node, NodeKind},
        Graph,
    },
    theme::tree::styles,
};

#[derive(Debug)]
struct Twig {
    is_last: bool,
}

#[derive(Clone, Debug)]
pub struct Options {}

pub struct Printer {
    #[allow(dead_code)]
    options: Options,
}

impl Printer {
    pub fn new(options: Options) -> Self {
        Self { options }
    }

    pub fn fmt(
        &self,
        f: &mut dyn fmt::Write,
        graph: &Graph,
        start_node_idx: NodeIndex,
    ) -> Result<(), anyhow::Error> {
        assert!(!is_cyclic_directed(graph));

        let mut twigs: Vec<Twig> = vec![Twig { is_last: true }];
        self.fmt_tree(f, graph, None, start_node_idx, &mut twigs)
    }

    fn fmt_tree(
        &self,
        f: &mut dyn fmt::Write,
        graph: &Graph,
        edge_idx: Option<EdgeIndex>,
        node_idx: NodeIndex,
        twigs: &mut Vec<Twig>,
    ) -> Result<(), anyhow::Error> {
        let edge = edge_idx.map(|idx| &graph[idx]);
        let node = &graph[node_idx];

        self.fmt_branch(f, edge, &twigs[..])?;
        self.fmt_node(f, node)?;
        writeln!(f)?;

        let mut children: Vec<_> = graph
            .edges_directed(node_idx, Direction::Outgoing)
            .filter_map(|edge_ref| {
                let edge_idx = edge_ref.id();
                let edge = &graph[edge_idx];

                // We're only interested in "owns" relationships here:
                let is_owns_edge = edge.kind == EdgeKind::Owns;
                debug_assert!(is_owns_edge);

                if !is_owns_edge {
                    return None;
                }

                let node_idx = edge_ref.target();
                let node = &graph[node_idx];

                let key = node.display_name();
                Some((node_idx, edge_idx, key))
            })
            .collect();

        // Sort the children by name for easier visual scanning of output:
        children.sort_by(|lhs, rhs| {
            let (_lhs_node, _lhs_edge, lhs_key) = lhs;
            let (_rhs_node, _rhs_edge, rhs_key) = rhs;
            lhs_key.cmp(&rhs_key)
        });

        let count = children.len();
        for (pos, (node_idx, edge_idx, _)) in children.into_iter().enumerate() {
            let is_last = pos + 1 == count;
            twigs.push(Twig { is_last });
            self.fmt_tree(f, graph, Some(edge_idx), node_idx, twigs)?;
            twigs.pop();
        }

        Ok(())
    }

    fn fmt_node(&self, f: &mut dyn fmt::Write, node: &Node) -> fmt::Result {
        self.fmt_node_kind(f, node)?;
        write!(f, " ")?;
        self.fmt_node_name(f, node)?;

        if node.kind == NodeKind::Crate {
            return Ok(());
        }

        self.fmt_node_colon(f, node)?;
        write!(f, " ")?;
        self.fmt_node_visibility(f, node)?;

        if !node.attrs.is_empty() {
            write!(f, " ")?;
            self.fmt_node_attrs(f, node)?;
        }

        Ok(())
    }

    fn fmt_node_kind(&self, f: &mut dyn fmt::Write, node: &Node) -> fmt::Result {
        let kind_style = self.kind_style();

        let display_name = node.kind.display_name().unwrap_or("mod");
        let kind = kind_style.paint(display_name);

        write!(f, "{}", kind)?;

        Ok(())
    }

    fn fmt_node_colon(&self, f: &mut dyn fmt::Write, _node: &Node) -> fmt::Result {
        let colon_style = self.colon_style();

        let colon = colon_style.paint(":");
        write!(f, "{}", colon)?;

        Ok(())
    }

    fn fmt_node_visibility(&self, f: &mut dyn fmt::Write, node: &Node) -> fmt::Result {
        let (visibility, visibility_style) = match &node.visibility {
            Some(visibility) => {
                let visibility_style = self.visibility_style(&visibility);
                (format!("{}", visibility), visibility_style)
            }
            None => {
                let orphan_style = self.orphan_style();
                ("orphan".to_owned(), orphan_style)
            }
        };

        let visibility = visibility_style.paint(visibility);
        write!(f, "{}", visibility)?;

        Ok(())
    }

    fn fmt_node_name(&self, f: &mut dyn fmt::Write, node: &Node) -> fmt::Result {
        let name_style = self.name_style();

        let name = name_style.paint(node.display_name());
        write!(f, "{}", name)?;

        Ok(())
    }

    fn fmt_node_attrs(&self, f: &mut dyn fmt::Write, node: &Node) -> fmt::Result {
        let attr_chrome_style = self.attr_chrome_style();
        let attr_style = self.attr_style();

        let mut is_first = true;

        if let Some(test_attr) = &node.attrs.test {
            let prefix = attr_chrome_style.paint("#[");
            let cfg = attr_style.paint(test_attr);
            let suffix = attr_chrome_style.paint("]");

            write!(f, "{}{}{}", prefix, cfg, suffix)?;

            is_first = false;
        }

        let attr_chrome_style = self.attr_chrome_style();
        let attr_style = self.attr_style();

        for cfg in &node.attrs.cfgs[..] {
            if !is_first {
                write!(f, ", ")?;
            }

            let prefix = attr_chrome_style.paint("#[cfg(");
            let cfg = attr_style.paint(cfg);
            let suffix = attr_chrome_style.paint(")]");

            write!(f, "{}{}{}", prefix, cfg, suffix)?;

            is_first = false;
        }

        Ok(())
    }

    fn fmt_branch(
        &self,
        f: &mut dyn fmt::Write,
        _edge: Option<&Edge>,
        twigs: &[Twig],
    ) -> fmt::Result {
        let prefix = self.branch_prefix(twigs);
        write!(f, "{}", self.branch_style().paint(&prefix))
    }

    /// Print a branch's prefix:
    fn branch_prefix(&self, twigs: &[Twig]) -> String {
        fn trunk_str(_is_last: bool) -> &'static str {
            ""
        }

        fn branch_str(is_last: bool) -> &'static str {
            if is_last {
                "    "
            } else {
                "│   "
            }
        }

        fn leaf_str(is_last: bool) -> &'static str {
            if is_last {
                "└── "
            } else {
                "├── "
            }
        }

        let mut string = String::new();

        // First level is crate level, we need to skip it when
        // printing. But we cannot easily drop the first value.
        match twigs {
            [trunk, branches @ .., leaf] => {
                string.push_str(trunk_str(trunk.is_last));
                for branch in branches {
                    string.push_str(branch_str(branch.is_last));
                }
                string.push_str(leaf_str(leaf.is_last));
            }
            [trunk] => {
                string.push_str(trunk_str(trunk.is_last));
            }
            [] => {}
        }

        string
    }

    fn colon_style(&self) -> Style {
        Style::default().dimmed()
    }

    fn attr_chrome_style(&self) -> Style {
        Style::default().dimmed()
    }

    fn branch_style(&self) -> Style {
        Style::default().dimmed()
    }

    fn name_style(&self) -> Style {
        let styles = styles();
        styles.name
    }

    fn kind_style(&self) -> Style {
        let styles = styles();
        styles.kind
    }

    fn visibility_style(&self, visibility: &NodeVisibility) -> Style {
        let styles = styles().visibility;

        match visibility {
            NodeVisibility::Crate => styles.pub_crate,
            NodeVisibility::Module(_) => styles.pub_module,
            NodeVisibility::Private => styles.pub_private,
            NodeVisibility::Public => styles.pub_global,
            NodeVisibility::Super => styles.pub_super,
        }
    }

    fn orphan_style(&self) -> Style {
        let styles = styles();
        styles.orphan
    }

    fn attr_style(&self) -> Style {
        let styles = styles();
        styles.attr
    }
}
<|endoftext|>


<commit_before>//! Contains result and error type for FBX reader.

extern crate byteorder;

use std::io;
use std::string;
use std::str;
use std::fmt;

/// A specialized `std::result::Result` type for FBX parsing.
pub type Result<T> = ::std::result::Result<T, Error>;

/// An FBX parsing error.
#[derive(Debug, Clone)]
pub struct Error {
    /// Last position of successfully read data when an error detected.
    pos: u64,
    /// Error type.
    kind: ErrorKind,
}

impl Error {
    /// Constructs `Error` with position and objects which can be converted to
    /// [`ErrorKind`](enum.ErrorKind.html).
    pub fn new<K: Into<ErrorKind>>(pos: u64, kind: K) -> Self {
        Error {
            pos: pos,
            kind: kind.into(),
        }
    }
}

impl fmt::Display for Error {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match self.kind {
            ErrorKind::Utf8Error(ref err) => write!(f, "UTF-8 conversion error at pos={}: {}", self.pos, err),
            ErrorKind::InvalidMagic => write!(f, "Invalid magic header at pos={}: Non-FBX or corrupted data?", self.pos),
            ErrorKind::Io(ref err) => write!(f, "I/O error at pos={}: {}", self.pos, err),
            ErrorKind::DataError(ref err) => write!(f, "Invalid data at pos={}: {}", self.pos, err),
            ErrorKind::UnexpectedValue(ref err) => write!(f, "Got an unexpected value at pos={}: {}", self.pos, err),
            ErrorKind::UnexpectedEof => write!(f, "Unexpected EOF at pos={}", self.pos),
            ErrorKind::Unimplemented(ref err) => write!(f, "Unimplemented feature: {}", err),
        }
    }
}

impl ::std::error::Error for Error {
    fn description(&self) -> &str {
        match self.kind {
            ErrorKind::Utf8Error(ref err) => err.description(),
            ErrorKind::InvalidMagic => "Got an invalid magic header",
            ErrorKind::Io(ref err) => err.description(),
            ErrorKind::DataError(_) => "Got an invalid data",
            ErrorKind::UnexpectedValue(_) => "Invalid value in FBX data",
            ErrorKind::UnexpectedEof => "Unexpected EOF",
            ErrorKind::Unimplemented(_) => "Attempt to use unimplemented feature",
        }
    }

    fn cause(&self) -> Option<&::std::error::Error> {
        match self.kind {
            ErrorKind::Utf8Error(ref err) => Some(err as &::std::error::Error),
            ErrorKind::Io(ref err) => Some(err as &::std::error::Error),
            _ => None,
        }
    }
}

/// Error type.
#[derive(Debug)]
pub enum ErrorKind {
    /// Conversion from array of u8 to String failed.
    Utf8Error(str::Utf8Error),
    /// Invalid magic binary detected.
    InvalidMagic,
    /// I/O operation error.
    Io(io::Error),
    /// Corrupted or inconsistent FBX data detected.
    DataError(String),
    /// Got an unexpected value, and cannot continue parsing.
    ///
    /// This is specialization of [`DataError`](#variant.DataError).
    UnexpectedValue(String),
    /// Reached unexpected EOF.
    UnexpectedEof,
    /// Attempted to use unimplemented feature.
    Unimplemented(String),
}

impl Clone for ErrorKind {
    fn clone(&self) -> Self {
        use self::ErrorKind::*;
        use std::error::Error;
        match *self {
            Utf8Error(ref e) => Utf8Error(e.clone()),
            InvalidMagic => InvalidMagic,
            // `io::Error` (and an error wrapped by `io::Error`) cannot be cloned.
            Io(ref e) => Io(io::Error::new(e.kind(), e.description())),
            DataError(ref e) => DataError(e.clone()),
            UnexpectedValue(ref e) => UnexpectedValue(e.clone()),
            UnexpectedEof => UnexpectedEof,
            Unimplemented(ref e) => Unimplemented(e.clone()),
        }
    }
}

impl From<string::FromUtf8Error> for ErrorKind {
    fn from(err: string::FromUtf8Error) -> ErrorKind {
        ErrorKind::Utf8Error(err.utf8_error())
    }
}

impl From<io::Error> for ErrorKind {
    fn from(err: io::Error) -> ErrorKind {
        // TODO: `io::Error::UnexpectedEof` should be converted to `ErrorKind::UnexpectedEof`.
        ErrorKind::Io(err)
    }
}

impl From<byteorder::Error> for ErrorKind {
    fn from(err: byteorder::Error) -> ErrorKind {
        match err {
            byteorder::Error::UnexpectedEOF => ErrorKind::UnexpectedEof,
            byteorder::Error::Io(err) => ErrorKind::Io(err),
        }
    }
}
<commit_msg>Simplify source code by using `use std::error`<commit_after>//! Contains result and error type for FBX reader.

extern crate byteorder;

use std::io;
use std::string;
use std::str;
use std::fmt;
use std::error;

/// A specialized `std::result::Result` type for FBX parsing.
pub type Result<T> = ::std::result::Result<T, Error>;

/// An FBX parsing error.
#[derive(Debug, Clone)]
pub struct Error {
    /// Last position of successfully read data when an error detected.
    pos: u64,
    /// Error type.
    kind: ErrorKind,
}

impl Error {
    /// Constructs `Error` with position and objects which can be converted to
    /// [`ErrorKind`](enum.ErrorKind.html).
    pub fn new<K: Into<ErrorKind>>(pos: u64, kind: K) -> Self {
        Error {
            pos: pos,
            kind: kind.into(),
        }
    }
}

impl fmt::Display for Error {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match self.kind {
            ErrorKind::Utf8Error(ref err) => write!(f, "UTF-8 conversion error at pos={}: {}", self.pos, err),
            ErrorKind::InvalidMagic => write!(f, "Invalid magic header at pos={}: Non-FBX or corrupted data?", self.pos),
            ErrorKind::Io(ref err) => write!(f, "I/O error at pos={}: {}", self.pos, err),
            ErrorKind::DataError(ref err) => write!(f, "Invalid data at pos={}: {}", self.pos, err),
            ErrorKind::UnexpectedValue(ref err) => write!(f, "Got an unexpected value at pos={}: {}", self.pos, err),
            ErrorKind::UnexpectedEof => write!(f, "Unexpected EOF at pos={}", self.pos),
            ErrorKind::Unimplemented(ref err) => write!(f, "Unimplemented feature: {}", err),
        }
    }
}

impl error::Error for Error {
    fn description(&self) -> &str {
        match self.kind {
            ErrorKind::Utf8Error(ref err) => err.description(),
            ErrorKind::InvalidMagic => "Got an invalid magic header",
            ErrorKind::Io(ref err) => err.description(),
            ErrorKind::DataError(_) => "Got an invalid data",
            ErrorKind::UnexpectedValue(_) => "Invalid value in FBX data",
            ErrorKind::UnexpectedEof => "Unexpected EOF",
            ErrorKind::Unimplemented(_) => "Attempt to use unimplemented feature",
        }
    }

    fn cause(&self) -> Option<&error::Error> {
        match self.kind {
            ErrorKind::Utf8Error(ref err) => Some(err as &error::Error),
            ErrorKind::Io(ref err) => Some(err as &error::Error),
            _ => None,
        }
    }
}

/// Error type.
#[derive(Debug)]
pub enum ErrorKind {
    /// Conversion from array of u8 to String failed.
    Utf8Error(str::Utf8Error),
    /// Invalid magic binary detected.
    InvalidMagic,
    /// I/O operation error.
    Io(io::Error),
    /// Corrupted or inconsistent FBX data detected.
    DataError(String),
    /// Got an unexpected value, and cannot continue parsing.
    ///
    /// This is specialization of [`DataError`](#variant.DataError).
    UnexpectedValue(String),
    /// Reached unexpected EOF.
    UnexpectedEof,
    /// Attempted to use unimplemented feature.
    Unimplemented(String),
}

impl Clone for ErrorKind {
    fn clone(&self) -> Self {
        use self::ErrorKind::*;
        use std::error::Error;
        match *self {
            Utf8Error(ref e) => Utf8Error(e.clone()),
            InvalidMagic => InvalidMagic,
            // `io::Error` (and an error wrapped by `io::Error`) cannot be cloned.
            Io(ref e) => Io(io::Error::new(e.kind(), e.description())),
            DataError(ref e) => DataError(e.clone()),
            UnexpectedValue(ref e) => UnexpectedValue(e.clone()),
            UnexpectedEof => UnexpectedEof,
            Unimplemented(ref e) => Unimplemented(e.clone()),
        }
    }
}

impl From<string::FromUtf8Error> for ErrorKind {
    fn from(err: string::FromUtf8Error) -> ErrorKind {
        ErrorKind::Utf8Error(err.utf8_error())
    }
}

impl From<io::Error> for ErrorKind {
    fn from(err: io::Error) -> ErrorKind {
        // TODO: `io::Error::UnexpectedEof` should be converted to `ErrorKind::UnexpectedEof`.
        ErrorKind::Io(err)
    }
}

impl From<byteorder::Error> for ErrorKind {
    fn from(err: byteorder::Error) -> ErrorKind {
        match err {
            byteorder::Error::UnexpectedEOF => ErrorKind::UnexpectedEof,
            byteorder::Error::Io(err) => ErrorKind::Io(err),
        }
    }
}
<|endoftext|>


<commit_before>#![doc(html_logo_url = "https://raw.githubusercontent.com/clap-rs/clap/master/assets/clap.png")]
#![doc = include_str!("../README.md")]
#![warn(missing_docs, trivial_casts, unused_allocation, trivial_numeric_casts)]
#![forbid(unsafe_code)]
#![deny(missing_docs)]

mod render;

pub use roff;

use render::subcommand_heading;
use roff::{roman, Roff};
use std::io::Write;

/// A manpage writer
pub struct Man<'a> {
    cmd: clap::Command<'a>,
    title: String,
    section: String,
    date: String,
    source: String,
    manual: String,
}

/// Build a [`Man`]
impl<'a> Man<'a> {
    /// Create a new manual page.
    pub fn new(mut cmd: clap::Command<'a>) -> Self {
        cmd._build_all();
        let title = cmd.get_name().to_owned();
        let section = "1".to_owned();
        let date = "".to_owned();
        let source = format!(
            "{} {}",
            cmd.get_name(),
            cmd.get_version().unwrap_or_default()
        );
        let manual = "".to_owned();
        Self {
            cmd,
            title,
            section,
            date,
            source,
            manual,
        }
    }

    /// Override the default man page title, written in all caps
    pub fn title(mut self, title: impl Into<String>) -> Self {
        self.title = title.into();
        self
    }

    /// Override the default section this man page is placed in
    ///
    /// Common values:
    ///
    // - `"1"`: User Commands
    // - `"2"`: System Calls
    // - `"3"`: C Library Functions
    // - `"4"`: Devices and Special Files
    // - `"5"`: File Formats and Conventions
    // - `"6"`: Games et. al.
    // - `"7"`: Miscellanea
    // - `"8"`: System Administration tools and Daemons
    pub fn section(mut self, section: impl Into<String>) -> Self {
        self.section = section.into();
        self
    }

    /// Override the default date for the last non-trivial change to this man page
    ///
    /// Dates should be written in the form `YYYY-MM-DD`.
    pub fn date(mut self, date: impl Into<String>) -> Self {
        self.date = date.into();
        self
    }

    /// Override the default source your command
    ///
    /// For those few man-pages pages in Sections 1 and 8, probably you just want to write GNU.
    pub fn source(mut self, source: impl Into<String>) -> Self {
        self.source = source.into();
        self
    }

    /// Override the default manual this page is a member of
    pub fn manual(mut self, manual: impl Into<String>) -> Self {
        self.manual = manual.into();
        self
    }
}

/// Generate ROFF output
impl<'a> Man<'a> {
    /// Render a full manual page into the writer.
    ///
    /// If customization is needed, you can call the individual sections you want and mix them into
    /// your own ROFF content.
    pub fn render(&self, w: &mut dyn Write) -> Result<(), std::io::Error> {
        let mut roff = Roff::default();
        self._render_title(&mut roff);
        self._render_name_section(&mut roff);
        self._render_synopsis_section(&mut roff);
        self._render_description_section(&mut roff);

        if app_has_arguments(&self.cmd) {
            self._render_options_section(&mut roff);
        }

        if app_has_subcommands(&self.cmd) {
            self._render_subcommands_section(&mut roff);
        }

        if self.cmd.get_after_long_help().is_some() || self.cmd.get_after_help().is_some() {
            self._render_extra_section(&mut roff);
        }

        if app_has_version(&self.cmd) {
            self._render_version_section(&mut roff);
        }

        if self.cmd.get_author().is_some() {
            self._render_authors_section(&mut roff);
        }

        roff.to_writer(w)
    }

    /// Render the title into the writer.
    pub fn render_title(&self, w: &mut dyn Write) -> Result<(), std::io::Error> {
        let mut roff = Roff::default();
        self._render_title(&mut roff);
        roff.to_writer(w)
    }

    fn _render_title(&self, roff: &mut Roff) {
        roff.control("TH", self.title_args());
    }

    // Turn metadata into arguments for a .TH macro.
    fn title_args(&self) -> Vec<&str> {
        vec![
            &self.title,
            &self.section,
            &self.date,
            &self.source,
            &self.manual,
        ]
    }

    /// Render the NAME section into the writer.
    pub fn render_name_section(&self, w: &mut dyn Write) -> Result<(), std::io::Error> {
        let mut roff = Roff::default();
        self._render_name_section(&mut roff);
        roff.to_writer(w)
    }

    fn _render_name_section(&self, roff: &mut Roff) {
        roff.control("SH", ["NAME"]);
        render::about(roff, &self.cmd);
    }

    /// Render the SYNOPSIS section into the writer.
    pub fn render_synopsis_section(&self, w: &mut dyn Write) -> Result<(), std::io::Error> {
        let mut roff = Roff::default();
        self._render_synopsis_section(&mut roff);
        roff.to_writer(w)
    }

    fn _render_synopsis_section(&self, roff: &mut Roff) {
        roff.control("SH", ["SYNOPSIS"]);
        render::synopsis(roff, &self.cmd);
    }

    /// Render the DESCRIPTION section into the writer.
    pub fn render_description_section(&self, w: &mut dyn Write) -> Result<(), std::io::Error> {
        let mut roff = Roff::default();
        self._render_description_section(&mut roff);
        roff.to_writer(w)
    }

    fn _render_description_section(&self, roff: &mut Roff) {
        roff.control("SH", ["DESCRIPTION"]);
        render::description(roff, &self.cmd);
    }

    /// Render the OPTIONS section into the writer.
    pub fn render_options_section(&self, w: &mut dyn Write) -> Result<(), std::io::Error> {
        let mut roff = Roff::default();
        self._render_options_section(&mut roff);
        roff.to_writer(w)
    }

    fn _render_options_section(&self, roff: &mut Roff) {
        roff.control("SH", ["OPTIONS"]);
        render::options(roff, &self.cmd);
    }

    /// Render the SUBCOMMANDS section into the writer.
    pub fn render_subcommands_section(&self, w: &mut dyn Write) -> Result<(), std::io::Error> {
        let mut roff = Roff::default();
        self._render_subcommands_section(&mut roff);
        roff.to_writer(w)
    }

    fn _render_subcommands_section(&self, roff: &mut Roff) {
        let heading = subcommand_heading(&self.cmd);
        roff.control("SH", [heading.as_str()]);
        render::subcommands(roff, &self.cmd, &self.section);
    }

    /// Render the EXTRA section into the writer.
    pub fn render_extra_section(&self, w: &mut dyn Write) -> Result<(), std::io::Error> {
        let mut roff = Roff::default();
        self._render_extra_section(&mut roff);
        roff.to_writer(w)
    }

    fn _render_extra_section(&self, roff: &mut Roff) {
        roff.control("SH", ["EXTRA"]);
        render::after_help(roff, &self.cmd);
    }

    /// Render the VERSION section into the writer.
    pub fn render_version_section(&self, w: &mut dyn Write) -> Result<(), std::io::Error> {
        let mut roff = Roff::default();
        self._render_version_section(&mut roff);
        roff.to_writer(w)
    }

    fn _render_version_section(&self, roff: &mut Roff) {
        let version = roman(&render::version(&self.cmd));
        roff.control("SH", ["VERSION"]);
        roff.text([version]);
    }

    /// Render the AUTHORS section into the writer.
    pub fn render_authors_section(&self, w: &mut dyn Write) -> Result<(), std::io::Error> {
        let mut roff = Roff::default();
        self._render_authors_section(&mut roff);
        roff.to_writer(w)
    }

    fn _render_authors_section(&self, roff: &mut Roff) {
        let author = roman(self.cmd.get_author().unwrap_or_default());
        roff.control("SH", ["AUTHORS"]);
        roff.text([author]);
    }
}

// Does the application have a version?
fn app_has_version(cmd: &clap::Command) -> bool {
    cmd.get_version()
        .or_else(|| cmd.get_long_version())
        .is_some()
}

// Does the application have any command line arguments?
fn app_has_arguments(cmd: &clap::Command) -> bool {
    cmd.get_arguments().any(|i| !i.is_hide_set())
}

// Does the application have any subcommands?
fn app_has_subcommands(cmd: &clap::Command) -> bool {
    cmd.get_subcommands().any(|i| !i.is_hide_set())
}
<commit_msg>docs(mangen): Fix docs for Man::section()<commit_after>#![doc(html_logo_url = "https://raw.githubusercontent.com/clap-rs/clap/master/assets/clap.png")]
#![doc = include_str!("../README.md")]
#![warn(missing_docs, trivial_casts, unused_allocation, trivial_numeric_casts)]
#![forbid(unsafe_code)]
#![deny(missing_docs)]

mod render;

pub use roff;

use render::subcommand_heading;
use roff::{roman, Roff};
use std::io::Write;

/// A manpage writer
pub struct Man<'a> {
    cmd: clap::Command<'a>,
    title: String,
    section: String,
    date: String,
    source: String,
    manual: String,
}

/// Build a [`Man`]
impl<'a> Man<'a> {
    /// Create a new manual page.
    pub fn new(mut cmd: clap::Command<'a>) -> Self {
        cmd._build_all();
        let title = cmd.get_name().to_owned();
        let section = "1".to_owned();
        let date = "".to_owned();
        let source = format!(
            "{} {}",
            cmd.get_name(),
            cmd.get_version().unwrap_or_default()
        );
        let manual = "".to_owned();
        Self {
            cmd,
            title,
            section,
            date,
            source,
            manual,
        }
    }

    /// Override the default man page title, written in all caps
    pub fn title(mut self, title: impl Into<String>) -> Self {
        self.title = title.into();
        self
    }

    /// Override the default section this man page is placed in
    ///
    /// Common values:
    ///
    /// - `"1"`: User Commands
    /// - `"2"`: System Calls
    /// - `"3"`: C Library Functions
    /// - `"4"`: Devices and Special Files
    /// - `"5"`: File Formats and Conventions
    /// - `"6"`: Games et. al.
    /// - `"7"`: Miscellanea
    /// - `"8"`: System Administration tools and Daemons
    pub fn section(mut self, section: impl Into<String>) -> Self {
        self.section = section.into();
        self
    }

    /// Override the default date for the last non-trivial change to this man page
    ///
    /// Dates should be written in the form `YYYY-MM-DD`.
    pub fn date(mut self, date: impl Into<String>) -> Self {
        self.date = date.into();
        self
    }

    /// Override the default source your command
    ///
    /// For those few man-pages pages in Sections 1 and 8, probably you just want to write GNU.
    pub fn source(mut self, source: impl Into<String>) -> Self {
        self.source = source.into();
        self
    }

    /// Override the default manual this page is a member of
    pub fn manual(mut self, manual: impl Into<String>) -> Self {
        self.manual = manual.into();
        self
    }
}

/// Generate ROFF output
impl<'a> Man<'a> {
    /// Render a full manual page into the writer.
    ///
    /// If customization is needed, you can call the individual sections you want and mix them into
    /// your own ROFF content.
    pub fn render(&self, w: &mut dyn Write) -> Result<(), std::io::Error> {
        let mut roff = Roff::default();
        self._render_title(&mut roff);
        self._render_name_section(&mut roff);
        self._render_synopsis_section(&mut roff);
        self._render_description_section(&mut roff);

        if app_has_arguments(&self.cmd) {
            self._render_options_section(&mut roff);
        }

        if app_has_subcommands(&self.cmd) {
            self._render_subcommands_section(&mut roff);
        }

        if self.cmd.get_after_long_help().is_some() || self.cmd.get_after_help().is_some() {
            self._render_extra_section(&mut roff);
        }

        if app_has_version(&self.cmd) {
            self._render_version_section(&mut roff);
        }

        if self.cmd.get_author().is_some() {
            self._render_authors_section(&mut roff);
        }

        roff.to_writer(w)
    }

    /// Render the title into the writer.
    pub fn render_title(&self, w: &mut dyn Write) -> Result<(), std::io::Error> {
        let mut roff = Roff::default();
        self._render_title(&mut roff);
        roff.to_writer(w)
    }

    fn _render_title(&self, roff: &mut Roff) {
        roff.control("TH", self.title_args());
    }

    // Turn metadata into arguments for a .TH macro.
    fn title_args(&self) -> Vec<&str> {
        vec![
            &self.title,
            &self.section,
            &self.date,
            &self.source,
            &self.manual,
        ]
    }

    /// Render the NAME section into the writer.
    pub fn render_name_section(&self, w: &mut dyn Write) -> Result<(), std::io::Error> {
        let mut roff = Roff::default();
        self._render_name_section(&mut roff);
        roff.to_writer(w)
    }

    fn _render_name_section(&self, roff: &mut Roff) {
        roff.control("SH", ["NAME"]);
        render::about(roff, &self.cmd);
    }

    /// Render the SYNOPSIS section into the writer.
    pub fn render_synopsis_section(&self, w: &mut dyn Write) -> Result<(), std::io::Error> {
        let mut roff = Roff::default();
        self._render_synopsis_section(&mut roff);
        roff.to_writer(w)
    }

    fn _render_synopsis_section(&self, roff: &mut Roff) {
        roff.control("SH", ["SYNOPSIS"]);
        render::synopsis(roff, &self.cmd);
    }

    /// Render the DESCRIPTION section into the writer.
    pub fn render_description_section(&self, w: &mut dyn Write) -> Result<(), std::io::Error> {
        let mut roff = Roff::default();
        self._render_description_section(&mut roff);
        roff.to_writer(w)
    }

    fn _render_description_section(&self, roff: &mut Roff) {
        roff.control("SH", ["DESCRIPTION"]);
        render::description(roff, &self.cmd);
    }

    /// Render the OPTIONS section into the writer.
    pub fn render_options_section(&self, w: &mut dyn Write) -> Result<(), std::io::Error> {
        let mut roff = Roff::default();
        self._render_options_section(&mut roff);
        roff.to_writer(w)
    }

    fn _render_options_section(&self, roff: &mut Roff) {
        roff.control("SH", ["OPTIONS"]);
        render::options(roff, &self.cmd);
    }

    /// Render the SUBCOMMANDS section into the writer.
    pub fn render_subcommands_section(&self, w: &mut dyn Write) -> Result<(), std::io::Error> {
        let mut roff = Roff::default();
        self._render_subcommands_section(&mut roff);
        roff.to_writer(w)
    }

    fn _render_subcommands_section(&self, roff: &mut Roff) {
        let heading = subcommand_heading(&self.cmd);
        roff.control("SH", [heading.as_str()]);
        render::subcommands(roff, &self.cmd, &self.section);
    }

    /// Render the EXTRA section into the writer.
    pub fn render_extra_section(&self, w: &mut dyn Write) -> Result<(), std::io::Error> {
        let mut roff = Roff::default();
        self._render_extra_section(&mut roff);
        roff.to_writer(w)
    }

    fn _render_extra_section(&self, roff: &mut Roff) {
        roff.control("SH", ["EXTRA"]);
        render::after_help(roff, &self.cmd);
    }

    /// Render the VERSION section into the writer.
    pub fn render_version_section(&self, w: &mut dyn Write) -> Result<(), std::io::Error> {
        let mut roff = Roff::default();
        self._render_version_section(&mut roff);
        roff.to_writer(w)
    }

    fn _render_version_section(&self, roff: &mut Roff) {
        let version = roman(&render::version(&self.cmd));
        roff.control("SH", ["VERSION"]);
        roff.text([version]);
    }

    /// Render the AUTHORS section into the writer.
    pub fn render_authors_section(&self, w: &mut dyn Write) -> Result<(), std::io::Error> {
        let mut roff = Roff::default();
        self._render_authors_section(&mut roff);
        roff.to_writer(w)
    }

    fn _render_authors_section(&self, roff: &mut Roff) {
        let author = roman(self.cmd.get_author().unwrap_or_default());
        roff.control("SH", ["AUTHORS"]);
        roff.text([author]);
    }
}

// Does the application have a version?
fn app_has_version(cmd: &clap::Command) -> bool {
    cmd.get_version()
        .or_else(|| cmd.get_long_version())
        .is_some()
}

// Does the application have any command line arguments?
fn app_has_arguments(cmd: &clap::Command) -> bool {
    cmd.get_arguments().any(|i| !i.is_hide_set())
}

// Does the application have any subcommands?
fn app_has_subcommands(cmd: &clap::Command) -> bool {
    cmd.get_subcommands().any(|i| !i.is_hide_set())
}
<|endoftext|>


<commit_before>extern crate num;
extern crate test;
extern crate time;

use num::bigint::BigInt;
use std::io::fs::File;
use std::iter::AdditiveIterator;
use std::os::args;
use test::black_box;
use time::precise_time_ns;

#[inline]
fn f() -> String {
    let content = match File::open(&Path::new("013.txt")) {
        Err(_) => fail!("couldn't open input file"),
        Ok(mut file) => match file.read_to_str() {
            Err(_) => fail!("couldn't read input file"),
            Ok(string) => string,
        }
    };

    let sum = content.as_slice().lines()
                     .filter_map(|line| from_str::<BigInt>(line.trim()))
                     .sum()
                     .to_str();

    sum.as_slice().slice(0, 10).to_owned()
}

fn main() {
    match args().as_slice() {
        [_] => {
            println!("{}", f());
        },
        [_, ref iters] => {
            let iters: u64 = from_str(iters.as_slice()).unwrap();

            let start = precise_time_ns();
            for _ in range(0, iters) {
                black_box(f());
            }
            let end = precise_time_ns();

            println!("{}", end - start);
        },
        _ => unreachable!(),
    }
}
<commit_msg>013.rs: to owned is deprecated, use to_string<commit_after>extern crate num;
extern crate test;
extern crate time;

use num::bigint::BigInt;
use std::io::fs::File;
use std::iter::AdditiveIterator;
use std::os::args;
use test::black_box;
use time::precise_time_ns;

#[inline]
fn f() -> String {
    let content = match File::open(&Path::new("013.txt")) {
        Err(_) => fail!("couldn't open input file"),
        Ok(mut file) => match file.read_to_str() {
            Err(_) => fail!("couldn't read input file"),
            Ok(string) => string,
        }
    };

    let sum = content.as_slice().lines()
                     .filter_map(|line| from_str::<BigInt>(line.trim()))
                     .sum()
                     .to_str();

    sum.as_slice().slice(0, 10).to_string()
}

fn main() {
    match args().as_slice() {
        [_] => {
            println!("{}", f());
        },
        [_, ref iters] => {
            let iters: u64 = from_str(iters.as_slice()).unwrap();

            let start = precise_time_ns();
            for _ in range(0, iters) {
                black_box(f());
            }
            let end = precise_time_ns();

            println!("{}", end - start);
        },
        _ => unreachable!(),
    }
}
<|endoftext|>


<commit_before>use crate::back::write::create_informational_target_machine;
use crate::llvm;
use syntax_pos::symbol::Symbol;
use rustc::session::Session;
use rustc::session::config::PrintRequest;
use rustc_target::spec::{MergeFunctions, PanicStrategy};
use libc::c_int;
use std::ffi::CString;
use rustc_feature::UnstableFeatures;
use syntax::symbol::sym;
use rustc::bug;

use std::str;
use std::slice;
use std::sync::atomic::{AtomicBool, Ordering};
use std::sync::Once;

static POISONED: AtomicBool = AtomicBool::new(false);
static INIT: Once = Once::new();

pub(crate) fn init(sess: &Session) {
    unsafe {
        // Before we touch LLVM, make sure that multithreading is enabled.
        INIT.call_once(|| {
            if llvm::LLVMStartMultithreaded() != 1 {
                // use an extra bool to make sure that all future usage of LLVM
                // cannot proceed despite the Once not running more than once.
                POISONED.store(true, Ordering::SeqCst);
            }

            configure_llvm(sess);
        });

        if POISONED.load(Ordering::SeqCst) {
            bug!("couldn't enable multi-threaded LLVM");
        }
    }
}

fn require_inited() {
    INIT.call_once(|| bug!("llvm is not initialized"));
    if POISONED.load(Ordering::SeqCst) {
        bug!("couldn't enable multi-threaded LLVM");
    }
}

unsafe fn configure_llvm(sess: &Session) {
    let n_args = sess.opts.cg.llvm_args.len();
    let mut llvm_c_strs = Vec::with_capacity(n_args + 1);
    let mut llvm_args = Vec::with_capacity(n_args + 1);

    llvm::LLVMRustInstallFatalErrorHandler();

    {
        let mut add = |arg: &str| {
            let s = CString::new(arg).unwrap();
            llvm_args.push(s.as_ptr());
            llvm_c_strs.push(s);
        };
        add("rustc"); // fake program name
        if sess.time_llvm_passes() { add("-time-passes"); }
        if sess.print_llvm_passes() { add("-debug-pass=Structure"); }
        if sess.opts.debugging_opts.disable_instrumentation_preinliner {
            add("-disable-preinline");
        }
        if sess.opts.debugging_opts.generate_arange_section {
            add("-generate-arange-section");
        }
        if get_major_version() >= 8 {
            match sess.opts.debugging_opts.merge_functions
                  .unwrap_or(sess.target.target.options.merge_functions) {
                MergeFunctions::Disabled |
                MergeFunctions::Trampolines => {}
                MergeFunctions::Aliases => {
                    add("-mergefunc-use-aliases");
                }
            }
        }

        if sess.target.target.target_os == "emscripten" &&
            sess.panic_strategy() == PanicStrategy::Unwind {
            add("-enable-emscripten-cxx-exceptions");
        }

        // HACK(eddyb) LLVM inserts `llvm.assume` calls to preserve align attributes
        // during inlining. Unfortunately these may block other optimizations.
        add("-preserve-alignment-assumptions-during-inlining=false");

        for arg in &sess.opts.cg.llvm_args {
            add(&(*arg));
        }
    }

    llvm::LLVMInitializePasses();

    ::rustc_llvm::initialize_available_targets();

    llvm::LLVMRustSetLLVMOptions(llvm_args.len() as c_int,
                                 llvm_args.as_ptr());
}

// WARNING: the features after applying `to_llvm_feature` must be known
// to LLVM or the feature detection code will walk past the end of the feature
// array, leading to crashes.

const ARM_WHITELIST: &[(&str, Option<Symbol>)] = &[
    ("aclass", Some(sym::arm_target_feature)),
    ("mclass", Some(sym::arm_target_feature)),
    ("rclass", Some(sym::arm_target_feature)),
    ("dsp", Some(sym::arm_target_feature)),
    ("neon", Some(sym::arm_target_feature)),
    ("crc", Some(sym::arm_target_feature)),
    ("crypto", Some(sym::arm_target_feature)),
    ("v5te", Some(sym::arm_target_feature)),
    ("v6", Some(sym::arm_target_feature)),
    ("v6k", Some(sym::arm_target_feature)),
    ("v6t2", Some(sym::arm_target_feature)),
    ("v7", Some(sym::arm_target_feature)),
    ("v8", Some(sym::arm_target_feature)),
    ("vfp2", Some(sym::arm_target_feature)),
    ("vfp3", Some(sym::arm_target_feature)),
    ("vfp4", Some(sym::arm_target_feature)),
];

const AARCH64_WHITELIST: &[(&str, Option<Symbol>)] = &[
    ("fp", Some(sym::aarch64_target_feature)),
    ("neon", Some(sym::aarch64_target_feature)),
    ("sve", Some(sym::aarch64_target_feature)),
    ("crc", Some(sym::aarch64_target_feature)),
    ("crypto", Some(sym::aarch64_target_feature)),
    ("ras", Some(sym::aarch64_target_feature)),
    ("lse", Some(sym::aarch64_target_feature)),
    ("rdm", Some(sym::aarch64_target_feature)),
    ("fp16", Some(sym::aarch64_target_feature)),
    ("rcpc", Some(sym::aarch64_target_feature)),
    ("dotprod", Some(sym::aarch64_target_feature)),
    ("v8.1a", Some(sym::aarch64_target_feature)),
    ("v8.2a", Some(sym::aarch64_target_feature)),
    ("v8.3a", Some(sym::aarch64_target_feature)),
];

const X86_WHITELIST: &[(&str, Option<Symbol>)] = &[
    ("adx", Some(sym::adx_target_feature)),
    ("aes", None),
    ("avx", None),
    ("avx2", None),
    ("avx512bw", Some(sym::avx512_target_feature)),
    ("avx512cd", Some(sym::avx512_target_feature)),
    ("avx512dq", Some(sym::avx512_target_feature)),
    ("avx512er", Some(sym::avx512_target_feature)),
    ("avx512f", Some(sym::avx512_target_feature)),
    ("avx512ifma", Some(sym::avx512_target_feature)),
    ("avx512pf", Some(sym::avx512_target_feature)),
    ("avx512vbmi", Some(sym::avx512_target_feature)),
    ("avx512vl", Some(sym::avx512_target_feature)),
    ("avx512vpopcntdq", Some(sym::avx512_target_feature)),
    ("bmi1", None),
    ("bmi2", None),
    ("cmpxchg16b", Some(sym::cmpxchg16b_target_feature)),
    ("f16c", Some(sym::f16c_target_feature)),
    ("fma", None),
    ("fxsr", None),
    ("lzcnt", None),
    ("mmx", Some(sym::mmx_target_feature)),
    ("movbe", Some(sym::movbe_target_feature)),
    ("pclmulqdq", None),
    ("popcnt", None),
    ("rdrand", None),
    ("rdseed", None),
    ("rtm", Some(sym::rtm_target_feature)),
    ("sha", None),
    ("sse", None),
    ("sse2", None),
    ("sse3", None),
    ("sse4.1", None),
    ("sse4.2", None),
    ("sse4a", Some(sym::sse4a_target_feature)),
    ("ssse3", None),
    ("tbm", Some(sym::tbm_target_feature)),
    ("xsave", None),
    ("xsavec", None),
    ("xsaveopt", None),
    ("xsaves", None),
];

const HEXAGON_WHITELIST: &[(&str, Option<Symbol>)] = &[
    ("hvx", Some(sym::hexagon_target_feature)),
    ("hvx-length128b", Some(sym::hexagon_target_feature)),
];

const POWERPC_WHITELIST: &[(&str, Option<Symbol>)] = &[
    ("altivec", Some(sym::powerpc_target_feature)),
    ("power8-altivec", Some(sym::powerpc_target_feature)),
    ("power9-altivec", Some(sym::powerpc_target_feature)),
    ("power8-vector", Some(sym::powerpc_target_feature)),
    ("power9-vector", Some(sym::powerpc_target_feature)),
    ("vsx", Some(sym::powerpc_target_feature)),
];

const MIPS_WHITELIST: &[(&str, Option<Symbol>)] = &[
    ("fp64", Some(sym::mips_target_feature)),
    ("msa", Some(sym::mips_target_feature)),
];

const WASM_WHITELIST: &[(&str, Option<Symbol>)] = &[
    ("simd128", Some(sym::wasm_target_feature)),
    ("atomics", Some(sym::wasm_target_feature)),
];

/// When rustdoc is running, provide a list of all known features so that all their respective
/// primitives may be documented.
///
/// IMPORTANT: If you're adding another whitelist to the above lists, make sure to add it to this
/// iterator!
pub fn all_known_features() -> impl Iterator<Item=(&'static str, Option<Symbol>)> {
    ARM_WHITELIST.iter().cloned()
        .chain(AARCH64_WHITELIST.iter().cloned())
        .chain(X86_WHITELIST.iter().cloned())
        .chain(HEXAGON_WHITELIST.iter().cloned())
        .chain(POWERPC_WHITELIST.iter().cloned())
        .chain(MIPS_WHITELIST.iter().cloned())
        .chain(WASM_WHITELIST.iter().cloned())
}

pub fn to_llvm_feature<'a>(sess: &Session, s: &'a str) -> &'a str {
    let arch = if sess.target.target.arch == "x86_64" {
        "x86"
    } else {
        &*sess.target.target.arch
    };
    match (arch, s) {
        ("x86", "pclmulqdq") => "pclmul",
        ("x86", "rdrand") => "rdrnd",
        ("x86", "bmi1") => "bmi",
        ("x86", "cmpxchg16b") => "cx16",
        ("aarch64", "fp") => "fp-armv8",
        ("aarch64", "fp16") => "fullfp16",
        (_, s) => s,
    }
}

pub fn target_features(sess: &Session) -> Vec<Symbol> {
    let target_machine = create_informational_target_machine(sess, true);
    target_feature_whitelist(sess)
        .iter()
        .filter_map(|&(feature, gate)| {
            if UnstableFeatures::from_environment().is_nightly_build() || gate.is_none() {
                Some(feature)
            } else {
                None
            }
        })
        .filter(|feature| {
            let llvm_feature = to_llvm_feature(sess, feature);
            let cstr = CString::new(llvm_feature).unwrap();
            unsafe { llvm::LLVMRustHasFeature(target_machine, cstr.as_ptr()) }
        })
        .map(|feature| Symbol::intern(feature)).collect()
}

pub fn target_feature_whitelist(sess: &Session)
    -> &'static [(&'static str, Option<Symbol>)]
{
    match &*sess.target.target.arch {
        "arm" => ARM_WHITELIST,
        "aarch64" => AARCH64_WHITELIST,
        "x86" | "x86_64" => X86_WHITELIST,
        "hexagon" => HEXAGON_WHITELIST,
        "mips" | "mips64" => MIPS_WHITELIST,
        "powerpc" | "powerpc64" => POWERPC_WHITELIST,
        "wasm32" => WASM_WHITELIST,
        _ => &[],
    }
}

pub fn print_version() {
    // Can be called without initializing LLVM
    unsafe {
        println!("LLVM version: {}.{}",
                 llvm::LLVMRustVersionMajor(), llvm::LLVMRustVersionMinor());
    }
}

pub fn get_major_version() -> u32 {
    unsafe { llvm::LLVMRustVersionMajor() }
}

pub fn print_passes() {
    // Can be called without initializing LLVM
    unsafe { llvm::LLVMRustPrintPasses(); }
}

pub(crate) fn print(req: PrintRequest, sess: &Session) {
    require_inited();
    let tm = create_informational_target_machine(sess, true);
    unsafe {
        match req {
            PrintRequest::TargetCPUs => llvm::LLVMRustPrintTargetCPUs(tm),
            PrintRequest::TargetFeatures => llvm::LLVMRustPrintTargetFeatures(tm),
            _ => bug!("rustc_codegen_llvm can't handle print request: {:?}", req),
        }
    }
}

pub fn target_cpu(sess: &Session) -> &str {
    let name = match sess.opts.cg.target_cpu {
        Some(ref s) => &**s,
        None => &*sess.target.target.options.cpu
    };
    if name != "native" {
        return name
    }

    unsafe {
        let mut len = 0;
        let ptr = llvm::LLVMRustGetHostCPUName(&mut len);
        str::from_utf8(slice::from_raw_parts(ptr as *const u8, len)).unwrap()
    }
}
<commit_msg>Allow -Cllvm-args to override rustc's default LLVM args.<commit_after>use crate::back::write::create_informational_target_machine;
use crate::llvm;
use syntax_pos::symbol::Symbol;
use rustc::session::Session;
use rustc::session::config::PrintRequest;
use rustc_data_structures::fx::FxHashSet;
use rustc_target::spec::{MergeFunctions, PanicStrategy};
use libc::c_int;
use std::ffi::CString;
use rustc_feature::UnstableFeatures;
use syntax::symbol::sym;
use rustc::bug;

use std::str;
use std::slice;
use std::sync::atomic::{AtomicBool, Ordering};
use std::sync::Once;

static POISONED: AtomicBool = AtomicBool::new(false);
static INIT: Once = Once::new();

pub(crate) fn init(sess: &Session) {
    unsafe {
        // Before we touch LLVM, make sure that multithreading is enabled.
        INIT.call_once(|| {
            if llvm::LLVMStartMultithreaded() != 1 {
                // use an extra bool to make sure that all future usage of LLVM
                // cannot proceed despite the Once not running more than once.
                POISONED.store(true, Ordering::SeqCst);
            }

            configure_llvm(sess);
        });

        if POISONED.load(Ordering::SeqCst) {
            bug!("couldn't enable multi-threaded LLVM");
        }
    }
}

fn require_inited() {
    INIT.call_once(|| bug!("llvm is not initialized"));
    if POISONED.load(Ordering::SeqCst) {
        bug!("couldn't enable multi-threaded LLVM");
    }
}

unsafe fn configure_llvm(sess: &Session) {
    let n_args = sess.opts.cg.llvm_args.len();
    let mut llvm_c_strs = Vec::with_capacity(n_args + 1);
    let mut llvm_args = Vec::with_capacity(n_args + 1);

    llvm::LLVMRustInstallFatalErrorHandler();

    fn llvm_arg_to_arg_name(full_arg: &str) -> &str {
        full_arg.trim().split(|c: char| {
            c == '=' || c.is_whitespace()
        }).next().unwrap_or("")
    }

    let user_specified_args: FxHashSet<_> = sess
        .opts
        .cg
        .llvm_args
        .iter()
        .map(|s| llvm_arg_to_arg_name(s))
        .filter(|s| s.len() > 0)
        .collect();

    {
        // This adds the given argument to LLVM. Unless `force` is true
        // user specified arguments are *not* overridden.
        let mut add = |arg: &str, force: bool| {
            if force || !user_specified_args.contains(llvm_arg_to_arg_name(arg)) {
                let s = CString::new(arg).unwrap();
                llvm_args.push(s.as_ptr());
                llvm_c_strs.push(s);
            }
        };
        add("rustc", true); // fake program name
        if sess.time_llvm_passes() { add("-time-passes", false); }
        if sess.print_llvm_passes() { add("-debug-pass=Structure", false); }
        if sess.opts.debugging_opts.disable_instrumentation_preinliner {
            add("-disable-preinline", false);
        }
        if sess.opts.debugging_opts.generate_arange_section {
            add("-generate-arange-section", false);
        }
        if get_major_version() >= 8 {
            match sess.opts.debugging_opts.merge_functions
                  .unwrap_or(sess.target.target.options.merge_functions) {
                MergeFunctions::Disabled |
                MergeFunctions::Trampolines => {}
                MergeFunctions::Aliases => {
                    add("-mergefunc-use-aliases", false);
                }
            }
        }

        if sess.target.target.target_os == "emscripten" &&
            sess.panic_strategy() == PanicStrategy::Unwind {
            add("-enable-emscripten-cxx-exceptions", false);
        }

        // HACK(eddyb) LLVM inserts `llvm.assume` calls to preserve align attributes
        // during inlining. Unfortunately these may block other optimizations.
        add("-preserve-alignment-assumptions-during-inlining=false", false);

        for arg in &sess.opts.cg.llvm_args {
            add(&(*arg), true);
        }
    }

    llvm::LLVMInitializePasses();

    ::rustc_llvm::initialize_available_targets();

    llvm::LLVMRustSetLLVMOptions(llvm_args.len() as c_int,
                                 llvm_args.as_ptr());
}

// WARNING: the features after applying `to_llvm_feature` must be known
// to LLVM or the feature detection code will walk past the end of the feature
// array, leading to crashes.

const ARM_WHITELIST: &[(&str, Option<Symbol>)] = &[
    ("aclass", Some(sym::arm_target_feature)),
    ("mclass", Some(sym::arm_target_feature)),
    ("rclass", Some(sym::arm_target_feature)),
    ("dsp", Some(sym::arm_target_feature)),
    ("neon", Some(sym::arm_target_feature)),
    ("crc", Some(sym::arm_target_feature)),
    ("crypto", Some(sym::arm_target_feature)),
    ("v5te", Some(sym::arm_target_feature)),
    ("v6", Some(sym::arm_target_feature)),
    ("v6k", Some(sym::arm_target_feature)),
    ("v6t2", Some(sym::arm_target_feature)),
    ("v7", Some(sym::arm_target_feature)),
    ("v8", Some(sym::arm_target_feature)),
    ("vfp2", Some(sym::arm_target_feature)),
    ("vfp3", Some(sym::arm_target_feature)),
    ("vfp4", Some(sym::arm_target_feature)),
];

const AARCH64_WHITELIST: &[(&str, Option<Symbol>)] = &[
    ("fp", Some(sym::aarch64_target_feature)),
    ("neon", Some(sym::aarch64_target_feature)),
    ("sve", Some(sym::aarch64_target_feature)),
    ("crc", Some(sym::aarch64_target_feature)),
    ("crypto", Some(sym::aarch64_target_feature)),
    ("ras", Some(sym::aarch64_target_feature)),
    ("lse", Some(sym::aarch64_target_feature)),
    ("rdm", Some(sym::aarch64_target_feature)),
    ("fp16", Some(sym::aarch64_target_feature)),
    ("rcpc", Some(sym::aarch64_target_feature)),
    ("dotprod", Some(sym::aarch64_target_feature)),
    ("v8.1a", Some(sym::aarch64_target_feature)),
    ("v8.2a", Some(sym::aarch64_target_feature)),
    ("v8.3a", Some(sym::aarch64_target_feature)),
];

const X86_WHITELIST: &[(&str, Option<Symbol>)] = &[
    ("adx", Some(sym::adx_target_feature)),
    ("aes", None),
    ("avx", None),
    ("avx2", None),
    ("avx512bw", Some(sym::avx512_target_feature)),
    ("avx512cd", Some(sym::avx512_target_feature)),
    ("avx512dq", Some(sym::avx512_target_feature)),
    ("avx512er", Some(sym::avx512_target_feature)),
    ("avx512f", Some(sym::avx512_target_feature)),
    ("avx512ifma", Some(sym::avx512_target_feature)),
    ("avx512pf", Some(sym::avx512_target_feature)),
    ("avx512vbmi", Some(sym::avx512_target_feature)),
    ("avx512vl", Some(sym::avx512_target_feature)),
    ("avx512vpopcntdq", Some(sym::avx512_target_feature)),
    ("bmi1", None),
    ("bmi2", None),
    ("cmpxchg16b", Some(sym::cmpxchg16b_target_feature)),
    ("f16c", Some(sym::f16c_target_feature)),
    ("fma", None),
    ("fxsr", None),
    ("lzcnt", None),
    ("mmx", Some(sym::mmx_target_feature)),
    ("movbe", Some(sym::movbe_target_feature)),
    ("pclmulqdq", None),
    ("popcnt", None),
    ("rdrand", None),
    ("rdseed", None),
    ("rtm", Some(sym::rtm_target_feature)),
    ("sha", None),
    ("sse", None),
    ("sse2", None),
    ("sse3", None),
    ("sse4.1", None),
    ("sse4.2", None),
    ("sse4a", Some(sym::sse4a_target_feature)),
    ("ssse3", None),
    ("tbm", Some(sym::tbm_target_feature)),
    ("xsave", None),
    ("xsavec", None),
    ("xsaveopt", None),
    ("xsaves", None),
];

const HEXAGON_WHITELIST: &[(&str, Option<Symbol>)] = &[
    ("hvx", Some(sym::hexagon_target_feature)),
    ("hvx-length128b", Some(sym::hexagon_target_feature)),
];

const POWERPC_WHITELIST: &[(&str, Option<Symbol>)] = &[
    ("altivec", Some(sym::powerpc_target_feature)),
    ("power8-altivec", Some(sym::powerpc_target_feature)),
    ("power9-altivec", Some(sym::powerpc_target_feature)),
    ("power8-vector", Some(sym::powerpc_target_feature)),
    ("power9-vector", Some(sym::powerpc_target_feature)),
    ("vsx", Some(sym::powerpc_target_feature)),
];

const MIPS_WHITELIST: &[(&str, Option<Symbol>)] = &[
    ("fp64", Some(sym::mips_target_feature)),
    ("msa", Some(sym::mips_target_feature)),
];

const WASM_WHITELIST: &[(&str, Option<Symbol>)] = &[
    ("simd128", Some(sym::wasm_target_feature)),
    ("atomics", Some(sym::wasm_target_feature)),
];

/// When rustdoc is running, provide a list of all known features so that all their respective
/// primitives may be documented.
///
/// IMPORTANT: If you're adding another whitelist to the above lists, make sure to add it to this
/// iterator!
pub fn all_known_features() -> impl Iterator<Item=(&'static str, Option<Symbol>)> {
    ARM_WHITELIST.iter().cloned()
        .chain(AARCH64_WHITELIST.iter().cloned())
        .chain(X86_WHITELIST.iter().cloned())
        .chain(HEXAGON_WHITELIST.iter().cloned())
        .chain(POWERPC_WHITELIST.iter().cloned())
        .chain(MIPS_WHITELIST.iter().cloned())
        .chain(WASM_WHITELIST.iter().cloned())
}

pub fn to_llvm_feature<'a>(sess: &Session, s: &'a str) -> &'a str {
    let arch = if sess.target.target.arch == "x86_64" {
        "x86"
    } else {
        &*sess.target.target.arch
    };
    match (arch, s) {
        ("x86", "pclmulqdq") => "pclmul",
        ("x86", "rdrand") => "rdrnd",
        ("x86", "bmi1") => "bmi",
        ("x86", "cmpxchg16b") => "cx16",
        ("aarch64", "fp") => "fp-armv8",
        ("aarch64", "fp16") => "fullfp16",
        (_, s) => s,
    }
}

pub fn target_features(sess: &Session) -> Vec<Symbol> {
    let target_machine = create_informational_target_machine(sess, true);
    target_feature_whitelist(sess)
        .iter()
        .filter_map(|&(feature, gate)| {
            if UnstableFeatures::from_environment().is_nightly_build() || gate.is_none() {
                Some(feature)
            } else {
                None
            }
        })
        .filter(|feature| {
            let llvm_feature = to_llvm_feature(sess, feature);
            let cstr = CString::new(llvm_feature).unwrap();
            unsafe { llvm::LLVMRustHasFeature(target_machine, cstr.as_ptr()) }
        })
        .map(|feature| Symbol::intern(feature)).collect()
}

pub fn target_feature_whitelist(sess: &Session)
    -> &'static [(&'static str, Option<Symbol>)]
{
    match &*sess.target.target.arch {
        "arm" => ARM_WHITELIST,
        "aarch64" => AARCH64_WHITELIST,
        "x86" | "x86_64" => X86_WHITELIST,
        "hexagon" => HEXAGON_WHITELIST,
        "mips" | "mips64" => MIPS_WHITELIST,
        "powerpc" | "powerpc64" => POWERPC_WHITELIST,
        "wasm32" => WASM_WHITELIST,
        _ => &[],
    }
}

pub fn print_version() {
    // Can be called without initializing LLVM
    unsafe {
        println!("LLVM version: {}.{}",
                 llvm::LLVMRustVersionMajor(), llvm::LLVMRustVersionMinor());
    }
}

pub fn get_major_version() -> u32 {
    unsafe { llvm::LLVMRustVersionMajor() }
}

pub fn print_passes() {
    // Can be called without initializing LLVM
    unsafe { llvm::LLVMRustPrintPasses(); }
}

pub(crate) fn print(req: PrintRequest, sess: &Session) {
    require_inited();
    let tm = create_informational_target_machine(sess, true);
    unsafe {
        match req {
            PrintRequest::TargetCPUs => llvm::LLVMRustPrintTargetCPUs(tm),
            PrintRequest::TargetFeatures => llvm::LLVMRustPrintTargetFeatures(tm),
            _ => bug!("rustc_codegen_llvm can't handle print request: {:?}", req),
        }
    }
}

pub fn target_cpu(sess: &Session) -> &str {
    let name = match sess.opts.cg.target_cpu {
        Some(ref s) => &**s,
        None => &*sess.target.target.options.cpu
    };
    if name != "native" {
        return name
    }

    unsafe {
        let mut len = 0;
        let ptr = llvm::LLVMRustGetHostCPUName(&mut len);
        str::from_utf8(slice::from_raw_parts(ptr as *const u8, len)).unwrap()
    }
}
<|endoftext|>


<commit_before>extern crate libc;

use libc::size_t;
use libc::strncpy;
use std::ffi::CStr;
use std::ffi::CString;
use std::os::raw::c_char;

mod add;
pub use add::add;

mod cmp;
pub use cmp::cmp;

mod denormalize;
pub use denormalize::denormalize;

mod normalize;
pub use normalize::normalize;

#[no_mangle]
pub extern fn rnc_add(dst: *mut c_char, dstlen: size_t, num_l: *const c_char, num_r: *const c_char) {
    unsafe {
        let sum = add(CStr::from_ptr(num_l).to_str().unwrap(), CStr::from_ptr(num_r).to_str().unwrap());
        let csum = CString::new(sum).unwrap();
        strncpy(dst, csum.as_ptr() as *const i8, dstlen);
    }
}
<commit_msg>Rust returns failure when the incoming buffer is too small<commit_after>extern crate libc;

use libc::{c_int, size_t, strncpy};
use std::ffi::CStr;
use std::ffi::CString;
use std::os::raw::c_char;

mod add;
pub use add::add;

mod cmp;
pub use cmp::cmp;

mod denormalize;
pub use denormalize::denormalize;

mod normalize;
pub use normalize::normalize;

#[no_mangle]
pub extern fn rnc_add(dst: *mut c_char, dstlen: size_t, num_l: *const c_char, num_r: *const c_char) -> c_int {
    unsafe {
        let sum = add(CStr::from_ptr(num_l).to_str().unwrap(), CStr::from_ptr(num_r).to_str().unwrap());
        if sum.len() > (dstlen - 1) {
            1
        } else {
            let csum = CString::new(sum).unwrap();
            strncpy(dst, csum.as_ptr() as *const i8, dstlen);
            0
        }
    }
}
<|endoftext|>


<commit_before>// Copyright 2012-2013 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.

use trans::cabi::FnType;
use trans::cabi_arm;
use trans::context::CrateContext;
use trans::type_::Type;

pub fn compute_abi_info(ccx: &CrateContext,
                        atys: &[Type],
                        rty: Type,
                        ret_def: bool) -> FnType {
    cabi_arm::compute_abi_info(ccx, atys, rty, ret_def,
                               cabi_arm::Flavor::General)
}
<commit_msg>Auto merge of #31653 - tomaka:emscripten-abi, r=eddyb<commit_after>// Copyright 2012-2013 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.

#![allow(non_upper_case_globals)]

use llvm::{Struct, Array, Attribute};
use trans::cabi::{FnType, ArgType};
use trans::context::CrateContext;
use trans::type_::Type;

// Data layout: e-p:32:32-i64:64-v128:32:128-n32-S128

// See the https://github.com/kripken/emscripten-fastcomp-clang repository.
// The class `EmscriptenABIInfo` in `/lib/CodeGen/TargetInfo.cpp` contains the ABI definitions.

fn classify_ret_ty(ccx: &CrateContext, ty: Type) -> ArgType {
    match ty.kind() {
        Struct => {
            let field_types = ty.field_types();
            if field_types.len() == 1 {
                ArgType::direct(ty, Some(field_types[0]), None, None)
            } else {
                ArgType::indirect(ty, Some(Attribute::StructRet))
            }
        },
        Array => {
            ArgType::indirect(ty, Some(Attribute::StructRet))
        },
        _ => {
            let attr = if ty == Type::i1(ccx) { Some(Attribute::ZExt) } else { None };
            ArgType::direct(ty, None, None, attr)
        }
    }
}

fn classify_arg_ty(ccx: &CrateContext, ty: Type) -> ArgType {
    if ty.is_aggregate() {
        ArgType::indirect(ty, Some(Attribute::ByVal))
    } else {
        let attr = if ty == Type::i1(ccx) { Some(Attribute::ZExt) } else { None };
        ArgType::direct(ty, None, None, attr)
    }
}

pub fn compute_abi_info(ccx: &CrateContext,
                        atys: &[Type],
                        rty: Type,
                        ret_def: bool) -> FnType {
    let mut arg_tys = Vec::new();
    for &aty in atys {
        let ty = classify_arg_ty(ccx, aty);
        arg_tys.push(ty);
    }

    let ret_ty = if ret_def {
        classify_ret_ty(ccx, rty)
    } else {
        ArgType::direct(Type::void(ccx), None, None, None)
    };

    return FnType {
        arg_tys: arg_tys,
        ret_ty: ret_ty,
    };
}
<|endoftext|>


<commit_before>#![feature(macro_rules)]
#![feature(phase)]

#![unstable]

#[phase(plugin)]
extern crate compile_msg;

extern crate libc;
extern crate native;

use std::sync::Mutex;

#[doc(hidden)]
pub mod ffi;

/// This static variable  will store the android_app* on creation, and set it back to 0 at
///  destruction.
/// Apart from this, the static is never written, so there is no risk of race condition.
static mut ANDROID_APP: *mut ffi::android_app = 0 as *mut ffi::android_app;

/// This is the structure that serves as user data in the android_app*
#[doc(hidden)]
struct Context {
    senders: Mutex<Vec<Sender<Event>>>,
}

/// An event triggered by the Android environment.
pub enum Event {
    EventUp,
    EventDown,
    EventMove(i32, i32),
}

#[cfg(not(target_os = "android"))]
compile_note!("You are not compiling for Android")

#[macro_export]
macro_rules! android_start(
    ($main: ident) => (
        pub mod __android_start {
            extern crate android_glue;

            // this function is here because we are sure that it will be included by the linker
            // so we call app_dummy in it, in order to be sure that the native glue will be included
            #[start]
            pub fn start(_: int, _: *const *const u8) -> int {
                unsafe { android_glue::ffi::app_dummy() };
                1
            }

            #[no_mangle]
            #[inline(never)]
            #[allow(non_snake_case)]
            pub extern "C" fn android_main(app: *mut ()) {
                android_glue::android_main2(app, proc() super::$main());
            }
        }
    )
)

/// This is the function that must be called by `android_main`
#[doc(hidden)]
pub fn android_main2(app: *mut (), main_function: proc(): Send) {
    use native::NativeTaskBuilder;
    use std::task::TaskBuilder;
    use std::{mem, ptr};

    write_log("Entering android_main");

    unsafe { ANDROID_APP = std::mem::transmute(app) };
    let app: &mut ffi::android_app = unsafe { std::mem::transmute(app) };

    // starting the runtime
    native::start(1, &b"".as_ptr(), proc() {
        // creating the context that will be passed to the callback
        let context = Context { senders: Mutex::new(Vec::new()) };
        app.onAppCmd = commands_callback;
        app.onInputEvent = inputs_callback;
        app.userData = unsafe { std::mem::transmute(&context) };

        // executing the main function in parallel
        TaskBuilder::new().native().spawn(proc() {
            std::io::stdio::set_stdout(box std::io::LineBufferedWriter::new(ToLogWriter));
            std::io::stdio::set_stderr(box std::io::LineBufferedWriter::new(ToLogWriter));
            main_function()
        });

        // polling for events forever
        // note that this must be done in the same thread as android_main because ALooper are
        //  thread-local
        unsafe {
            loop {
                let mut events = mem::uninitialized();
                let mut source = mem::uninitialized();

                // passing -1 means that we are blocking
                let ident = ffi::ALooper_pollAll(-1, ptr::null_mut(), &mut events,
                    &mut source);

                // processing the event
                if !source.is_null() {
                    let source: *mut ffi::android_poll_source = mem::transmute(source);
                    ((*source).process)(ANDROID_APP, source);
                }
            }
        }
    });

    // terminating the application
    unsafe { ANDROID_APP = 0 as *mut ffi::android_app };
}

/// Writer that will redirect what is written to it to the logs.
struct ToLogWriter;

impl Writer for ToLogWriter {
    fn write(&mut self, buf: &[u8]) -> std::io::IoResult<()> {
        buf.with_c_str(|message| {
            b"RustAndroidGlueStdouterr".with_c_str(|tag| {
                unsafe { ffi::__android_log_write(3, tag, message) };
            });
        });
        Ok(())
    }
}

/// The callback for inputs.
pub extern fn inputs_callback(_: *mut ffi::android_app, event: *const ffi::AInputEvent)
    -> libc::int32_t
{
    fn send_event(event: Event) {
        for sender in get_context().senders.lock().iter() {
            sender.send(event);
        }
    }
    let action = unsafe { ffi::AMotionEvent_getAction(event) };
    let action_code = action & ffi::AMOTION_EVENT_ACTION_MASK;
    match action_code {
        ffi::AMOTION_EVENT_ACTION_UP
            | ffi::AMOTION_EVENT_ACTION_OUTSIDE
            | ffi::AMOTION_EVENT_ACTION_CANCEL
            | ffi::AMOTION_EVENT_ACTION_POINTER_UP =>
        {
            send_event(Event::EventUp);
        },
        ffi::AMOTION_EVENT_ACTION_DOWN
            | ffi::AMOTION_EVENT_ACTION_POINTER_DOWN =>
        {
            send_event(Event::EventDown);
        },
        _ => {
            let x = unsafe { ffi::AMotionEvent_getX(event, 0) };
            let y = unsafe { ffi::AMotionEvent_getY(event, 0) };
            send_event(Event::EventMove(x as i32, y as i32));
        },
    }
    0
}

/// The callback for commands.
#[doc(hidden)]
pub extern fn commands_callback(_: *mut ffi::android_app, command: libc::int32_t) {
    let context = get_context();

    match command {
        ffi::APP_CMD_INIT_WINDOW => {

        },

        ffi::APP_CMD_SAVE_STATE => {

        },

        ffi::APP_CMD_TERM_WINDOW => {

        },

        ffi::APP_CMD_GAINED_FOCUS => {

        },

        ffi::APP_CMD_LOST_FOCUS => {

        },

        _ => ()
    }
}

/// Returns the current Context.
fn get_context() -> &'static Context {
    let context = unsafe { (*ANDROID_APP).userData };
    unsafe { std::mem::transmute(context) }
}

/// Adds a sender where events will be sent to.
pub fn add_sender(sender: Sender<Event>) {
    get_context().senders.lock().push(sender);
}

/// Returns a handle to the native window.
pub unsafe fn get_native_window() -> ffi::NativeWindowType {
    if ANDROID_APP.is_null() {
        panic!("The application was not initialized from android_main");
    }

    loop {
        let value = (*ANDROID_APP).window;
        if !value.is_null() {
            return value;
        }

        // spin-locking
        std::io::timer::sleep(std::time::Duration::milliseconds(10));
    }
}

///
pub fn write_log(message: &str) {
    message.with_c_str(|message| {
        b"RustAndroidGlue".with_c_str(|tag| {
            unsafe { ffi::__android_log_write(3, tag, message) };
        });
    });
}
<commit_msg>android: Updated for rust e583c4d24 2014-11-21 09:01:50 +0000<commit_after>#![feature(macro_rules)]
#![feature(phase)]

#![unstable]

#[phase(plugin)]
extern crate compile_msg;

extern crate libc;

use std::sync::Mutex;

#[doc(hidden)]
pub mod ffi;

/// This static variable  will store the android_app* on creation, and set it back to 0 at
///  destruction.
/// Apart from this, the static is never written, so there is no risk of race condition.
static mut ANDROID_APP: *mut ffi::android_app = 0 as *mut ffi::android_app;

/// This is the structure that serves as user data in the android_app*
#[doc(hidden)]
struct Context {
    senders: Mutex<Vec<Sender<Event>>>,
}

/// An event triggered by the Android environment.
pub enum Event {
    EventUp,
    EventDown,
    EventMove(i32, i32),
}

#[cfg(not(target_os = "android"))]
compile_note!("You are not compiling for Android")

#[macro_export]
macro_rules! android_start(
    ($main: ident) => (
        pub mod __android_start {
            extern crate android_glue;

            // this function is here because we are sure that it will be included by the linker
            // so we call app_dummy in it, in order to be sure that the native glue will be included
            #[start]
            pub fn start(_: int, _: *const *const u8) -> int {
                unsafe { android_glue::ffi::app_dummy() };
                1
            }

            #[no_mangle]
            #[inline(never)]
            #[allow(non_snake_case)]
            pub extern "C" fn android_main(app: *mut ()) {
                android_glue::android_main2(app, proc() super::$main());
            }
        }
    )
)

/// This is the function that must be called by `android_main`
#[doc(hidden)]
pub fn android_main2(app: *mut (), main_function: proc(): Send) {
    use std::task::TaskBuilder;
    use std::{mem, ptr};

    write_log("Entering android_main");

    unsafe { ANDROID_APP = std::mem::transmute(app) };
    let app: &mut ffi::android_app = unsafe { std::mem::transmute(app) };

    // starting the runtime
    std::rt::start(1, &b"".as_ptr(), proc() {
        // creating the context that will be passed to the callback
        let context = Context { senders: Mutex::new(Vec::new()) };
        app.onAppCmd = commands_callback;
        app.onInputEvent = inputs_callback;
        app.userData = unsafe { std::mem::transmute(&context) };

        // executing the main function in parallel
        spawn(proc() {
            std::io::stdio::set_stdout(box std::io::LineBufferedWriter::new(ToLogWriter));
            std::io::stdio::set_stderr(box std::io::LineBufferedWriter::new(ToLogWriter));
            main_function()
        });

        // polling for events forever
        // note that this must be done in the same thread as android_main because ALooper are
        //  thread-local
        unsafe {
            loop {
                let mut events = mem::uninitialized();
                let mut source = mem::uninitialized();

                // passing -1 means that we are blocking
                let ident = ffi::ALooper_pollAll(-1, ptr::null_mut(), &mut events,
                    &mut source);

                // processing the event
                if !source.is_null() {
                    let source: *mut ffi::android_poll_source = mem::transmute(source);
                    ((*source).process)(ANDROID_APP, source);
                }
            }
        }
    });

    // terminating the application
    unsafe { ANDROID_APP = 0 as *mut ffi::android_app };
}

/// Writer that will redirect what is written to it to the logs.
struct ToLogWriter;

impl Writer for ToLogWriter {
    fn write(&mut self, buf: &[u8]) -> std::io::IoResult<()> {
        buf.with_c_str(|message| {
            b"RustAndroidGlueStdouterr".with_c_str(|tag| {
                unsafe { ffi::__android_log_write(3, tag, message) };
            });
        });
        Ok(())
    }
}

/// The callback for inputs.
pub extern fn inputs_callback(_: *mut ffi::android_app, event: *const ffi::AInputEvent)
    -> libc::int32_t
{
    fn send_event(event: Event) {
        for sender in get_context().senders.lock().iter() {
            sender.send(event);
        }
    }
    let action = unsafe { ffi::AMotionEvent_getAction(event) };
    let action_code = action & ffi::AMOTION_EVENT_ACTION_MASK;
    match action_code {
        ffi::AMOTION_EVENT_ACTION_UP
            | ffi::AMOTION_EVENT_ACTION_OUTSIDE
            | ffi::AMOTION_EVENT_ACTION_CANCEL
            | ffi::AMOTION_EVENT_ACTION_POINTER_UP =>
        {
            send_event(Event::EventUp);
        },
        ffi::AMOTION_EVENT_ACTION_DOWN
            | ffi::AMOTION_EVENT_ACTION_POINTER_DOWN =>
        {
            send_event(Event::EventDown);
        },
        _ => {
            let x = unsafe { ffi::AMotionEvent_getX(event, 0) };
            let y = unsafe { ffi::AMotionEvent_getY(event, 0) };
            send_event(Event::EventMove(x as i32, y as i32));
        },
    }
    0
}

/// The callback for commands.
#[doc(hidden)]
pub extern fn commands_callback(_: *mut ffi::android_app, command: libc::int32_t) {
    let context = get_context();

    match command {
        ffi::APP_CMD_INIT_WINDOW => {

        },

        ffi::APP_CMD_SAVE_STATE => {

        },

        ffi::APP_CMD_TERM_WINDOW => {

        },

        ffi::APP_CMD_GAINED_FOCUS => {

        },

        ffi::APP_CMD_LOST_FOCUS => {

        },

        _ => ()
    }
}

/// Returns the current Context.
fn get_context() -> &'static Context {
    let context = unsafe { (*ANDROID_APP).userData };
    unsafe { std::mem::transmute(context) }
}

/// Adds a sender where events will be sent to.
pub fn add_sender(sender: Sender<Event>) {
    get_context().senders.lock().push(sender);
}

/// Returns a handle to the native window.
pub unsafe fn get_native_window() -> ffi::NativeWindowType {
    if ANDROID_APP.is_null() {
        panic!("The application was not initialized from android_main");
    }

    loop {
        let value = (*ANDROID_APP).window;
        if !value.is_null() {
            return value;
        }

        // spin-locking
        std::io::timer::sleep(std::time::Duration::milliseconds(10));
    }
}

///
pub fn write_log(message: &str) {
    message.with_c_str(|message| {
        b"RustAndroidGlue".with_c_str(|tag| {
            unsafe { ffi::__android_log_write(3, tag, message) };
        });
    });
}
<|endoftext|>