<commit_before>use crate::ast::{
    ArrowFunctionBody, Block, BlockStatement, Expression, Ident, ImportStatement, Module,
    ModuleStatement, Operator,
};

pub fn render_module(module: Module) -> String {
    let mut accum = String::new();
    module.render(&mut accum);
    accum
}

#[cfg(windows)]
static NEWLINE: &str = "\r\n";

#[cfg(not(windows))]
static NEWLINE: &str = "\n";

pub(crate) trait Render {
    // REVIEW I doubt pushing to a String like this is the most efficient solution?
    fn render(&self, accum: &mut String);
}

impl Render for Module {
    fn render(&self, accum: &mut String) {
        self.imports.iter().for_each(|import| {
            import.render(accum);
            accum.push_str(NEWLINE);
        });
        self.statements.iter().for_each(|stmt| {
            stmt.render(accum);
            accum.push_str(NEWLINE);
        });

        accum.push_str("export {");
        accum.push_str(
            &self
                .exports
                .iter()
                .map(|ident| ident.0.as_str())
                .collect::<Vec<_>>()
                .join(","),
        );
        accum.push_str("};");
        accum.push_str(NEWLINE);
    }
}

impl Render for ImportStatement {
    fn render(&self, accum: &mut String) {
        accum.push_str("import {");
        for (aliased, ident) in self.idents.iter() {
            accum.push_str(&format!("{} as {}", aliased.0, ident.0));
            accum.push(',');
        }
        accum.push_str(&format!("}} from \"{}\";", self.path));
    }
}

impl Render for ModuleStatement {
    fn render(&self, accum: &mut String) {
        match self {
            Self::LetDeclaration { ident } => {
                accum.push_str(&format!("let {ident};", ident = ident.0));
            }
            Self::ConstAssignment { ident, value } => {
                accum.push_str(&format!("const {ident} = ", ident = ident.0));
                value.render(accum);
                accum.push(';');
            }
            Self::Assignment { ident, value } => {
                accum.push_str(&format!("{ident} = ", ident = ident.0));
                value.render(accum);
                accum.push(';');
            }
            Self::Function {
                ident,
                parameters,
                body,
            } => {
                accum.push_str(&format!(
                    "function {ident}({parameters})",
                    ident = ident.0,
                    parameters = parameters
                        .iter()
                        .map(|ident| ident.0.as_str())
                        .collect::<Vec<&str>>()
                        .join(",")
                ));
                body.render(accum);
            }
        }
    }
}

impl Render for Block {
    fn render(&self, accum: &mut String) {
        accum.push('{');
        self.0.iter().for_each(|stmt| {
            stmt.render(accum);
        });
        accum.push('}');
    }
}

impl Render for BlockStatement {
    fn render(&self, accum: &mut String) {
        match self {
            Self::Return(None) => {
                accum.push_str("return;");
            }
            Self::Return(Some(expression)) => {
                accum.push_str("return ");
                expression.render(accum);
                accum.push(';');
            }
            Self::_Expression(expression) => {
                expression.render(accum);
                accum.push(';');
            }
            Self::Throw(message) => {
                accum.push_str("throw new Error(\"");
                accum.push_str(message);
                accum.push_str("\");");
            }
            Self::ConstAssignment { ident, value } => {
                accum.push_str(&format!("const {ident} = ", ident = ident.0));
                value.render(accum);
                accum.push(';');
            }
        }
    }
}

impl Render for Expression {
    fn render(&self, accum: &mut String) {
        match self {
            Self::Variable(ident) => {
                accum.push_str(&ident.0);
            }
            Self::ArrowFunction { parameters, body } => {
                accum.push_str(&format!(
                    "({parameters}) => ",
                    parameters = parameters
                        .iter()
                        .map(|ident| ident.0.as_str())
                        .collect::<Vec<&str>>()
                        .join(",")
                ));
                body.render(accum)
            }
            Self::Call {
                function,
                arguments,
            } => {
                let function_needs_parens = matches!(**function, Self::ArrowFunction { .. });
                if function_needs_parens {
                    accum.push('(')
                }
                function.render(accum);
                if function_needs_parens {
                    accum.push(')')
                }
                accum.push('(');
                arguments.iter().for_each(|arg| {
                    arg.render(accum);
                    accum.push(',');
                });
                accum.push(')');
            }
            Self::Conditional {
                condition,
                true_clause,
                false_clause,
            } => {
                let condition_needs_parens = matches!(
                    **condition,
                    Self::ArrowFunction { .. } | Self::Conditional { .. }
                );
                if condition_needs_parens {
                    accum.push('(');
                }
                condition.render(accum);
                if condition_needs_parens {
                    accum.push(')');
                }
                accum.push('?');
                true_clause.render(accum);
                accum.push(':');
                false_clause.render(accum);
            }
            Self::Array(expressions) => {
                accum.push('[');
                expressions.iter().for_each(|expr| {
                    expr.render(accum);
                    accum.push(',');
                });
                accum.push(']');
            }
            Self::Number(number_string) => {
                accum.push_str(number_string);
            }
            Self::String(inner_string) => {
                accum.push('"');
                accum.push_str(inner_string);
                accum.push('"');
            }
            Self::True => {
                accum.push_str("true");
            }
            Self::False => {
                accum.push_str("false");
            }
            Self::Undefined => {
                accum.push_str("undefined");
            }
            Self::Block(block) => {
                // IIFE
                accum.push('(');
                let arrow_function = Self::ArrowFunction {
                    parameters: Vec::new(),
                    body: Box::new(ArrowFunctionBody::Block(block.clone())),
                };
                arrow_function.render(accum);
                accum.push_str(")()");
            }
            Self::Operator { op, lhs, rhs } => {
                // Always use parens rather than worry about precedence
                accum.push('(');
                lhs.render(accum);
                accum.push_str(match op {
                    Operator::And => " && ",
                    Operator::Equals => " === ",
                });
                rhs.render(accum);
                accum.push(')');
            }
            Self::IndexAccess { target, index } => {
                target.render(accum);
                accum.push('[');
                index.render(accum);
                accum.push(']');
            }
        }
    }
}

impl Render for ArrowFunctionBody {
    fn render(&self, accum: &mut String) {
        match self {
            Self::Block(block) => block.render(accum),
            Self::Expression(expression) => expression.render(accum),
        }
    }
}

impl Render for Ident {
    fn render(&self, accum: &mut String) {
        accum.push_str(&self.0);
    }
}

#[cfg(test)]
mod tests {
    use super::test_macros::*;
    use crate::ast::*;

    #[test]
    fn it_renders_identifiers() {
        assert_render!(ident!("foo"), "foo");
        assert_render!(ident!("Bar"), "Bar");
    }

    #[test]
    fn it_renders_expressions() {
        assert_render!(Expression::True, "true");
        assert_render!(Expression::False, "false");
        assert_render!(Expression::Undefined, "undefined");

        assert_render!(Expression::Number("42".to_string()), "42");
        assert_render!(Expression::String("five".to_string()), "\"five\"");

        assert_render!(Expression::Variable(ident!("foo")), "foo");

        assert_render!(
            Expression::ArrowFunction {
                parameters: vec![],
                body: Box::new(ArrowFunctionBody::Expression(Expression::String(
                    "test".to_string()
                )))
            },
            "() => \"test\""
        );
        assert_render!(
            Expression::ArrowFunction {
                parameters: vec![ident!("a")],
                body: Box::new(ArrowFunctionBody::Block(Block(vec![
                    BlockStatement::Return(Some(Expression::String("hello".to_string())))
                ]))),
            },
            "(a) => {return \"hello\";}"
        );
        assert_render!(
            Expression::ArrowFunction {
                parameters: vec![ident!("a"), ident!("b"), ident!("c")],
                body: Box::new(ArrowFunctionBody::Expression(Expression::ArrowFunction {
                    parameters: vec![],
                    body: Box::new(ArrowFunctionBody::Expression(Expression::Number(
                        "5".to_string()
                    )))
                }))
            },
            "(a,b,c) => () => 5"
        );

        assert_render!(
            Expression::Call {
                function: Box::new(Expression::Variable(ident!("f"))),
                arguments: vec![Expression::True, Expression::False]
            },
            "f(true,false,)"
        );
        assert_render!(
            Expression::Call {
                function: Box::new(Expression::ArrowFunction {
                    parameters: vec![],
                    body: Box::new(ArrowFunctionBody::Expression(Expression::True))
                },),
                arguments: vec![]
            },
            "(() => true)()"
        );

        assert_render!(
            Expression::Conditional {
                condition: Box::new(Expression::True),
                true_clause: Box::new(Expression::Number("0".to_string())),
                false_clause: Box::new(Expression::Number("1".to_string())),
            },
            "true?0:1"
        );
        assert_render!(
            Expression::Conditional {
                condition: Box::new(Expression::Conditional {
                    condition: Box::new(Expression::True),
                    true_clause: Box::new(Expression::True),
                    false_clause: Box::new(Expression::False),
                }),
                true_clause: Box::new(Expression::Number("0".to_string())),
                false_clause: Box::new(Expression::Number("1".to_string())),
            },
            "(true?true:false)?0:1"
        );
        assert_render!(
            Expression::Conditional {
                condition: Box::new(Expression::Conditional {
                    condition: Box::new(Expression::True),
                    true_clause: Box::new(Expression::True),
                    false_clause: Box::new(Expression::False),
                }),
                true_clause: Box::new(Expression::Conditional {
                    condition: Box::new(Expression::False),
                    true_clause: Box::new(Expression::Number("0".to_string())),
                    false_clause: Box::new(Expression::Number("1".to_string())),
                }),
                false_clause: Box::new(Expression::Conditional {
                    condition: Box::new(Expression::False),
                    true_clause: Box::new(Expression::Number("2".to_string())),
                    false_clause: Box::new(Expression::Number("3".to_string())),
                }),
            },
            "(true?true:false)?false?0:1:false?2:3"
        );
        assert_render!(
            Expression::Operator {
                op: Operator::Equals,
                lhs: Box::new(Expression::Operator {
                    op: Operator::And,
                    lhs: Box::new(Expression::False),
                    rhs: Box::new(Expression::True),
                }),
                rhs: Box::new(Expression::True),
            },
            "((false && true) === true)"
        );

        assert_render!(
            Expression::IndexAccess {
                target: Box::new(Expression::IndexAccess {
                    target: Box::new(Expression::Variable(ident!("foo"))),
                    index: Box::new(Expression::String(String::from("bar")))
                }),
                index: Box::new(Expression::String(String::from("baz")))
            },
            r#"foo["bar"]["baz"]"#
        );
    }

    #[test]
    fn it_renders_block_statements() {
        assert_render!(
            BlockStatement::Return(Some(Expression::True)),
            "return true;"
        );
        assert_render!(BlockStatement::Return(None), "return;");
        assert_render!(
            BlockStatement::Throw(String::from("aaaahhh")),
            "throw new Error(\"aaaahhh\");"
        )
    }

    #[test]
    fn it_renders_blocks() {
        assert_render!(
            Block(vec![BlockStatement::Return(Some(Expression::True)),]),
            "{return true;}"
        );
    }

    #[test]
    fn it_renders_module_statements() {
        assert_render!(
            ModuleStatement::Function {
                ident: ident!("identity"),
                parameters: vec![ident!("a")],
                body: Block(vec![BlockStatement::Return(Some(Expression::Variable(
                    ident!("a")
                ))),]),
            },
            "function identity(a){return a;}"
        );
        assert_render!(
            ModuleStatement::ConstAssignment {
                ident: ident!("yes"),
                value: Expression::True,
            },
            "const yes = true;"
        );
        assert_render!(
            ModuleStatement::LetDeclaration {
                ident: ident!("huh"),
            },
            "let huh;"
        );
        assert_render!(
            ModuleStatement::Assignment {
                ident: ident!("huh"),
                value: Expression::Number("42".to_string()),
            },
            "huh = 42;"
        );
    }
}

#[cfg(test)]
mod test_macros {
    macro_rules! assert_render {
        ($renderable:expr, $want:expr) => {{
            let mut accum = String::new();
            $crate::render::Render::render(&$renderable, &mut accum);
            assert_eq!(accum.as_str(), $want);
        }};
    }

    pub(super) use assert_render;
}
<commit_msg>Add parens helper to JavaScript renderer<commit_after>use crate::ast::{
    ArrowFunctionBody, Block, BlockStatement, Expression, Ident, ImportStatement, Module,
    ModuleStatement, Operator,
};

pub fn render_module(module: Module) -> String {
    let mut accum = String::new();
    module.render(&mut accum);
    accum
}

#[cfg(windows)]
static NEWLINE: &str = "\r\n";

#[cfg(not(windows))]
static NEWLINE: &str = "\n";

pub(crate) trait Render {
    // REVIEW I doubt pushing to a String like this is the most efficient solution?
    fn render(&self, accum: &mut String);
}

impl Render for Module {
    fn render(&self, accum: &mut String) {
        self.imports.iter().for_each(|import| {
            import.render(accum);
            accum.push_str(NEWLINE);
        });
        self.statements.iter().for_each(|stmt| {
            stmt.render(accum);
            accum.push_str(NEWLINE);
        });

        accum.push_str("export {");
        accum.push_str(
            &self
                .exports
                .iter()
                .map(|ident| ident.0.as_str())
                .collect::<Vec<_>>()
                .join(","),
        );
        accum.push_str("};");
        accum.push_str(NEWLINE);
    }
}

impl Render for ImportStatement {
    fn render(&self, accum: &mut String) {
        accum.push_str("import {");
        for (aliased, ident) in self.idents.iter() {
            accum.push_str(&format!("{} as {}", aliased.0, ident.0));
            accum.push(',');
        }
        accum.push_str(&format!("}} from \"{}\";", self.path));
    }
}

impl Render for ModuleStatement {
    fn render(&self, accum: &mut String) {
        match self {
            Self::LetDeclaration { ident } => {
                accum.push_str(&format!("let {ident};", ident = ident.0));
            }
            Self::ConstAssignment { ident, value } => {
                accum.push_str(&format!("const {ident} = ", ident = ident.0));
                value.render(accum);
                accum.push(';');
            }
            Self::Assignment { ident, value } => {
                accum.push_str(&format!("{ident} = ", ident = ident.0));
                value.render(accum);
                accum.push(';');
            }
            Self::Function {
                ident,
                parameters,
                body,
            } => {
                accum.push_str(&format!(
                    "function {ident}({parameters})",
                    ident = ident.0,
                    parameters = parameters
                        .iter()
                        .map(|ident| ident.0.as_str())
                        .collect::<Vec<&str>>()
                        .join(",")
                ));
                body.render(accum);
            }
        }
    }
}

impl Render for Block {
    fn render(&self, accum: &mut String) {
        accum.push('{');
        self.0.iter().for_each(|stmt| {
            stmt.render(accum);
        });
        accum.push('}');
    }
}

impl Render for BlockStatement {
    fn render(&self, accum: &mut String) {
        match self {
            Self::Return(None) => {
                accum.push_str("return;");
            }
            Self::Return(Some(expression)) => {
                accum.push_str("return ");
                expression.render(accum);
                accum.push(';');
            }
            Self::_Expression(expression) => {
                expression.render(accum);
                accum.push(';');
            }
            Self::Throw(message) => {
                accum.push_str("throw new Error(\"");
                accum.push_str(message);
                accum.push_str("\");");
            }
            Self::ConstAssignment { ident, value } => {
                accum.push_str(&format!("const {ident} = ", ident = ident.0));
                value.render(accum);
                accum.push(';');
            }
        }
    }
}

impl Render for Expression {
    fn render(&self, accum: &mut String) {
        match self {
            Self::Variable(ident) => {
                accum.push_str(&ident.0);
            }
            Self::ArrowFunction { parameters, body } => {
                accum.push_str(&format!(
                    "({parameters}) => ",
                    parameters = parameters
                        .iter()
                        .map(|ident| ident.0.as_str())
                        .collect::<Vec<&str>>()
                        .join(",")
                ));
                body.render(accum)
            }
            Self::Call {
                box function,
                arguments,
            } => {
                render_in_parens_if(
                    matches!(function, Self::ArrowFunction { .. }),
                    function,
                    accum,
                );
                accum.push('(');
                arguments.iter().for_each(|arg| {
                    arg.render(accum);
                    accum.push(',');
                });
                accum.push(')');
            }
            Self::Conditional {
                box condition,
                true_clause,
                false_clause,
            } => {
                render_in_parens_if(
                    matches!(
                        condition,
                        Self::ArrowFunction { .. } | Self::Conditional { .. }
                    ),
                    condition,
                    accum,
                );
                accum.push('?');
                true_clause.render(accum);
                accum.push(':');
                false_clause.render(accum);
            }
            Self::Array(expressions) => {
                accum.push('[');
                expressions.iter().for_each(|expr| {
                    expr.render(accum);
                    accum.push(',');
                });
                accum.push(']');
            }
            Self::Number(number_string) => {
                accum.push_str(number_string);
            }
            Self::String(inner_string) => {
                accum.push('"');
                accum.push_str(inner_string);
                accum.push('"');
            }
            Self::True => {
                accum.push_str("true");
            }
            Self::False => {
                accum.push_str("false");
            }
            Self::Undefined => {
                accum.push_str("undefined");
            }
            Self::Block(block) => {
                // IIFE
                accum.push('(');
                let arrow_function = Self::ArrowFunction {
                    parameters: Vec::new(),
                    body: Box::new(ArrowFunctionBody::Block(block.clone())),
                };
                arrow_function.render(accum);
                accum.push_str(")()");
            }
            Self::Operator { op, lhs, rhs } => {
                // Always use parens rather than worry about precedence
                accum.push('(');
                lhs.render(accum);
                accum.push_str(match op {
                    Operator::And => " && ",
                    Operator::Equals => " === ",
                });
                rhs.render(accum);
                accum.push(')');
            }
            Self::IndexAccess { target, index } => {
                target.render(accum);
                accum.push('[');
                index.render(accum);
                accum.push(']');
            }
        }
    }
}

fn render_in_parens_if<T: Render>(condition: bool, t: &T, accum: &mut String) {
    if condition {
        accum.push('(');
        t.render(accum);
        accum.push(')');
    } else {
        t.render(accum);
    }
}

impl Render for ArrowFunctionBody {
    fn render(&self, accum: &mut String) {
        match self {
            Self::Block(block) => block.render(accum),
            Self::Expression(expression) => expression.render(accum),
        }
    }
}

impl Render for Ident {
    fn render(&self, accum: &mut String) {
        accum.push_str(&self.0);
    }
}

#[cfg(test)]
mod tests {
    use super::test_macros::*;
    use crate::ast::*;

    #[test]
    fn it_renders_identifiers() {
        assert_render!(ident!("foo"), "foo");
        assert_render!(ident!("Bar"), "Bar");
    }

    #[test]
    fn it_renders_expressions() {
        assert_render!(Expression::True, "true");
        assert_render!(Expression::False, "false");
        assert_render!(Expression::Undefined, "undefined");

        assert_render!(Expression::Number("42".to_string()), "42");
        assert_render!(Expression::String("five".to_string()), "\"five\"");

        assert_render!(Expression::Variable(ident!("foo")), "foo");

        assert_render!(
            Expression::ArrowFunction {
                parameters: vec![],
                body: Box::new(ArrowFunctionBody::Expression(Expression::String(
                    "test".to_string()
                )))
            },
            "() => \"test\""
        );
        assert_render!(
            Expression::ArrowFunction {
                parameters: vec![ident!("a")],
                body: Box::new(ArrowFunctionBody::Block(Block(vec![
                    BlockStatement::Return(Some(Expression::String("hello".to_string())))
                ]))),
            },
            "(a) => {return \"hello\";}"
        );
        assert_render!(
            Expression::ArrowFunction {
                parameters: vec![ident!("a"), ident!("b"), ident!("c")],
                body: Box::new(ArrowFunctionBody::Expression(Expression::ArrowFunction {
                    parameters: vec![],
                    body: Box::new(ArrowFunctionBody::Expression(Expression::Number(
                        "5".to_string()
                    )))
                }))
            },
            "(a,b,c) => () => 5"
        );

        assert_render!(
            Expression::Call {
                function: Box::new(Expression::Variable(ident!("f"))),
                arguments: vec![Expression::True, Expression::False]
            },
            "f(true,false,)"
        );
        assert_render!(
            Expression::Call {
                function: Box::new(Expression::ArrowFunction {
                    parameters: vec![],
                    body: Box::new(ArrowFunctionBody::Expression(Expression::True))
                },),
                arguments: vec![]
            },
            "(() => true)()"
        );

        assert_render!(
            Expression::Conditional {
                condition: Box::new(Expression::True),
                true_clause: Box::new(Expression::Number("0".to_string())),
                false_clause: Box::new(Expression::Number("1".to_string())),
            },
            "true?0:1"
        );
        assert_render!(
            Expression::Conditional {
                condition: Box::new(Expression::Conditional {
                    condition: Box::new(Expression::True),
                    true_clause: Box::new(Expression::True),
                    false_clause: Box::new(Expression::False),
                }),
                true_clause: Box::new(Expression::Number("0".to_string())),
                false_clause: Box::new(Expression::Number("1".to_string())),
            },
            "(true?true:false)?0:1"
        );
        assert_render!(
            Expression::Conditional {
                condition: Box::new(Expression::Conditional {
                    condition: Box::new(Expression::True),
                    true_clause: Box::new(Expression::True),
                    false_clause: Box::new(Expression::False),
                }),
                true_clause: Box::new(Expression::Conditional {
                    condition: Box::new(Expression::False),
                    true_clause: Box::new(Expression::Number("0".to_string())),
                    false_clause: Box::new(Expression::Number("1".to_string())),
                }),
                false_clause: Box::new(Expression::Conditional {
                    condition: Box::new(Expression::False),
                    true_clause: Box::new(Expression::Number("2".to_string())),
                    false_clause: Box::new(Expression::Number("3".to_string())),
                }),
            },
            "(true?true:false)?false?0:1:false?2:3"
        );
        assert_render!(
            Expression::Operator {
                op: Operator::Equals,
                lhs: Box::new(Expression::Operator {
                    op: Operator::And,
                    lhs: Box::new(Expression::False),
                    rhs: Box::new(Expression::True),
                }),
                rhs: Box::new(Expression::True),
            },
            "((false && true) === true)"
        );

        assert_render!(
            Expression::IndexAccess {
                target: Box::new(Expression::IndexAccess {
                    target: Box::new(Expression::Variable(ident!("foo"))),
                    index: Box::new(Expression::String(String::from("bar")))
                }),
                index: Box::new(Expression::String(String::from("baz")))
            },
            r#"foo["bar"]["baz"]"#
        );
    }

    #[test]
    fn it_renders_block_statements() {
        assert_render!(
            BlockStatement::Return(Some(Expression::True)),
            "return true;"
        );
        assert_render!(BlockStatement::Return(None), "return;");
        assert_render!(
            BlockStatement::Throw(String::from("aaaahhh")),
            "throw new Error(\"aaaahhh\");"
        )
    }

    #[test]
    fn it_renders_blocks() {
        assert_render!(
            Block(vec![BlockStatement::Return(Some(Expression::True)),]),
            "{return true;}"
        );
    }

    #[test]
    fn it_renders_module_statements() {
        assert_render!(
            ModuleStatement::Function {
                ident: ident!("identity"),
                parameters: vec![ident!("a")],
                body: Block(vec![BlockStatement::Return(Some(Expression::Variable(
                    ident!("a")
                ))),]),
            },
            "function identity(a){return a;}"
        );
        assert_render!(
            ModuleStatement::ConstAssignment {
                ident: ident!("yes"),
                value: Expression::True,
            },
            "const yes = true;"
        );
        assert_render!(
            ModuleStatement::LetDeclaration {
                ident: ident!("huh"),
            },
            "let huh;"
        );
        assert_render!(
            ModuleStatement::Assignment {
                ident: ident!("huh"),
                value: Expression::Number("42".to_string()),
            },
            "huh = 42;"
        );
    }
}

#[cfg(test)]
mod test_macros {
    macro_rules! assert_render {
        ($renderable:expr, $want:expr) => {{
            let mut accum = String::new();
            $crate::render::Render::render(&$renderable, &mut accum);
            assert_eq!(accum.as_str(), $want);
        }};
    }

    pub(super) use assert_render;
}
<|endoftext|>


<commit_before>//! Grammar for the command-line arguments.
#![allow(unreachable_pub)]
use std::{path::PathBuf, str::FromStr};

use ide_ssr::{SsrPattern, SsrRule};

use crate::cli::Verbosity;

xflags::xflags! {
    src "./src/cli/flags.rs"

    /// LSP server for the Rust programming language.
    cmd rust-analyzer {
        /// Verbosity level, can be repeated multiple times.
        repeated -v, --verbose
        /// Verbosity level.
        optional -q, --quiet

        /// Log to the specified file instead of stderr.
        optional --log-file path: PathBuf
        /// Flush log records to the file immediately.
        optional --no-log-buffering

        /// Wait until a debugger is attached to (requires debug build).
        optional --wait-dbg

        default cmd lsp-server {
            /// Print version.
            optional --version
            /// Print help.
            optional -h, --help

            /// Dump a LSP config JSON schema.
            optional --print-config-schema
        }

        /// Parse stdin.
        cmd parse {
            /// Suppress printing.
            optional --no-dump
        }

        /// Parse stdin and print the list of symbols.
        cmd symbols {}

        /// Highlight stdin as html.
        cmd highlight {
            /// Enable rainbow highlighting of identifiers.
            optional --rainbow
        }

        /// Batch typecheck project and print summary statistics
        cmd analysis-stats
            /// Directory with Cargo.toml.
            required path: PathBuf
        {
            optional --output format: OutputFormat

            /// Randomize order in which crates, modules, and items are processed.
            optional --randomize
            /// Run type inference in parallel.
            optional --parallel
            /// Collect memory usage statistics.
            optional --memory-usage
            /// Print the total length of all source and macro files (whitespace is not counted).
            optional --source-stats

            /// Only analyze items matching this path.
            optional -o, --only path: String
            /// Also analyze all dependencies.
            optional --with-deps
            /// Don't load sysroot crates (`std`, `core` & friends).
            optional --no-sysroot

            /// Don't run build scripts or load `OUT_DIR` values by running `cargo check` before analysis.
            optional --disable-build-scripts
            /// Don't use expand proc macros.
            optional --disable-proc-macros
            /// Only resolve names, don't run type inference.
            optional --skip-inference
        }

        cmd diagnostics
            /// Directory with Cargo.toml.
            required path: PathBuf
        {
            /// Don't run build scripts or load `OUT_DIR` values by running `cargo check` before analysis.
            optional --disable-build-scripts
            /// Don't use expand proc macros.
            optional --disable-proc-macros
        }

        cmd ssr
            /// A structured search replace rule (`$a.foo($b) ==> bar($a, $b)`)
            repeated rule: SsrRule
        {}

        cmd search
            /// A structured search replace pattern (`$a.foo($b)`)
            repeated pattern: SsrPattern
        {
            /// Prints debug information for any nodes with source exactly equal to snippet.
            optional --debug snippet: String
        }

        cmd proc-macro {}

        cmd lsif
            required path: PathBuf
        {}
    }
}

// generated start
// The following code is generated by `xflags` macro.
// Run `env UPDATE_XFLAGS=1 cargo build` to regenerate.
#[derive(Debug)]
pub struct RustAnalyzer {
    pub verbose: u32,
    pub quiet: bool,
    pub log_file: Option<PathBuf>,
    pub no_log_buffering: bool,
    pub wait_dbg: bool,
    pub subcommand: RustAnalyzerCmd,
}

#[derive(Debug)]
pub enum RustAnalyzerCmd {
    LspServer(LspServer),
    Parse(Parse),
    Symbols(Symbols),
    Highlight(Highlight),
    AnalysisStats(AnalysisStats),
    Diagnostics(Diagnostics),
    Ssr(Ssr),
    Search(Search),
    ProcMacro(ProcMacro),
    Lsif(Lsif),
}

#[derive(Debug)]
pub struct LspServer {
    pub version: bool,
    pub help: bool,
    pub print_config_schema: bool,
}

#[derive(Debug)]
pub struct Parse {
    pub no_dump: bool,
}

#[derive(Debug)]
pub struct Symbols;

#[derive(Debug)]
pub struct Highlight {
    pub rainbow: bool,
}

#[derive(Debug)]
pub struct AnalysisStats {
    pub path: PathBuf,

    pub output: Option<OutputFormat>,
    pub randomize: bool,
    pub parallel: bool,
    pub memory_usage: bool,
    pub source_stats: bool,
    pub only: Option<String>,
    pub with_deps: bool,
    pub no_sysroot: bool,
    pub disable_build_scripts: bool,
    pub disable_proc_macros: bool,
    pub skip_inference: bool,
}

#[derive(Debug)]
pub struct Diagnostics {
    pub path: PathBuf,

    pub disable_build_scripts: bool,
    pub disable_proc_macros: bool,
}

#[derive(Debug)]
pub struct Ssr {
    pub rule: Vec<SsrRule>,
}

#[derive(Debug)]
pub struct Search {
    pub pattern: Vec<SsrPattern>,

    pub debug: Option<String>,
}

#[derive(Debug)]
pub struct ProcMacro;

#[derive(Debug)]
pub struct Lsif {
    pub path: PathBuf,
}

impl RustAnalyzer {
    pub const HELP: &'static str = Self::HELP_;

    #[allow(dead_code)]
    pub fn from_env() -> xflags::Result<Self> {
        Self::from_env_()
    }

    #[allow(dead_code)]
    pub fn from_vec(args: Vec<std::ffi::OsString>) -> xflags::Result<Self> {
        Self::from_vec_(args)
    }
}
// generated end

#[derive(Debug, PartialEq, Eq)]
pub enum OutputFormat {
    Csv,
}

impl RustAnalyzer {
    pub fn verbosity(&self) -> Verbosity {
        if self.quiet {
            return Verbosity::Quiet;
        }
        match self.verbose {
            0 => Verbosity::Normal,
            1 => Verbosity::Verbose,
            _ => Verbosity::Spammy,
        }
    }
}

impl FromStr for OutputFormat {
    type Err = String;

    fn from_str(s: &str) -> Result<Self, Self::Err> {
        match s {
            "csv" => Ok(Self::Csv),
            _ => Err(format!("unknown output format `{}`", s)),
        }
    }
}
<commit_msg>Document CLI flag stability<commit_after>//! Grammar for the command-line arguments.
#![allow(unreachable_pub)]
use std::{path::PathBuf, str::FromStr};

use ide_ssr::{SsrPattern, SsrRule};

use crate::cli::Verbosity;

xflags::xflags! {
    src "./src/cli/flags.rs"

    /// LSP server for the Rust programming language.
    ///
    /// Subcommands and their flags do not provide any stability guarantees and may be removed or
    /// changed without notice. Top-level flags that are not are marked as [Unstable] provide
    /// backwards-compatibility and may be relied on.
    cmd rust-analyzer {
        /// Verbosity level, can be repeated multiple times.
        repeated -v, --verbose
        /// Verbosity level.
        optional -q, --quiet

        /// Log to the specified file instead of stderr.
        optional --log-file path: PathBuf
        /// Flush log records to the file immediately.
        optional --no-log-buffering

        /// [Unstable] Wait until a debugger is attached to (requires debug build).
        optional --wait-dbg

        default cmd lsp-server {
            /// Print version.
            optional --version
            /// Print help.
            optional -h, --help

            /// Dump a LSP config JSON schema.
            optional --print-config-schema
        }

        /// Parse stdin.
        cmd parse {
            /// Suppress printing.
            optional --no-dump
        }

        /// Parse stdin and print the list of symbols.
        cmd symbols {}

        /// Highlight stdin as html.
        cmd highlight {
            /// Enable rainbow highlighting of identifiers.
            optional --rainbow
        }

        /// Batch typecheck project and print summary statistics
        cmd analysis-stats
            /// Directory with Cargo.toml.
            required path: PathBuf
        {
            optional --output format: OutputFormat

            /// Randomize order in which crates, modules, and items are processed.
            optional --randomize
            /// Run type inference in parallel.
            optional --parallel
            /// Collect memory usage statistics.
            optional --memory-usage
            /// Print the total length of all source and macro files (whitespace is not counted).
            optional --source-stats

            /// Only analyze items matching this path.
            optional -o, --only path: String
            /// Also analyze all dependencies.
            optional --with-deps
            /// Don't load sysroot crates (`std`, `core` & friends).
            optional --no-sysroot

            /// Don't run build scripts or load `OUT_DIR` values by running `cargo check` before analysis.
            optional --disable-build-scripts
            /// Don't use expand proc macros.
            optional --disable-proc-macros
            /// Only resolve names, don't run type inference.
            optional --skip-inference
        }

        cmd diagnostics
            /// Directory with Cargo.toml.
            required path: PathBuf
        {
            /// Don't run build scripts or load `OUT_DIR` values by running `cargo check` before analysis.
            optional --disable-build-scripts
            /// Don't use expand proc macros.
            optional --disable-proc-macros
        }

        cmd ssr
            /// A structured search replace rule (`$a.foo($b) ==> bar($a, $b)`)
            repeated rule: SsrRule
        {}

        cmd search
            /// A structured search replace pattern (`$a.foo($b)`)
            repeated pattern: SsrPattern
        {
            /// Prints debug information for any nodes with source exactly equal to snippet.
            optional --debug snippet: String
        }

        cmd proc-macro {}

        cmd lsif
            required path: PathBuf
        {}
    }
}

// generated start
// The following code is generated by `xflags` macro.
// Run `env UPDATE_XFLAGS=1 cargo build` to regenerate.
#[derive(Debug)]
pub struct RustAnalyzer {
    pub verbose: u32,
    pub quiet: bool,
    pub log_file: Option<PathBuf>,
    pub no_log_buffering: bool,
    pub wait_dbg: bool,
    pub subcommand: RustAnalyzerCmd,
}

#[derive(Debug)]
pub enum RustAnalyzerCmd {
    LspServer(LspServer),
    Parse(Parse),
    Symbols(Symbols),
    Highlight(Highlight),
    AnalysisStats(AnalysisStats),
    Diagnostics(Diagnostics),
    Ssr(Ssr),
    Search(Search),
    ProcMacro(ProcMacro),
    Lsif(Lsif),
}

#[derive(Debug)]
pub struct LspServer {
    pub version: bool,
    pub help: bool,
    pub print_config_schema: bool,
}

#[derive(Debug)]
pub struct Parse {
    pub no_dump: bool,
}

#[derive(Debug)]
pub struct Symbols;

#[derive(Debug)]
pub struct Highlight {
    pub rainbow: bool,
}

#[derive(Debug)]
pub struct AnalysisStats {
    pub path: PathBuf,

    pub output: Option<OutputFormat>,
    pub randomize: bool,
    pub parallel: bool,
    pub memory_usage: bool,
    pub source_stats: bool,
    pub only: Option<String>,
    pub with_deps: bool,
    pub no_sysroot: bool,
    pub disable_build_scripts: bool,
    pub disable_proc_macros: bool,
    pub skip_inference: bool,
}

#[derive(Debug)]
pub struct Diagnostics {
    pub path: PathBuf,

    pub disable_build_scripts: bool,
    pub disable_proc_macros: bool,
}

#[derive(Debug)]
pub struct Ssr {
    pub rule: Vec<SsrRule>,
}

#[derive(Debug)]
pub struct Search {
    pub pattern: Vec<SsrPattern>,

    pub debug: Option<String>,
}

#[derive(Debug)]
pub struct ProcMacro;

#[derive(Debug)]
pub struct Lsif {
    pub path: PathBuf,
}

impl RustAnalyzer {
    pub const HELP: &'static str = Self::HELP_;

    #[allow(dead_code)]
    pub fn from_env() -> xflags::Result<Self> {
        Self::from_env_()
    }

    #[allow(dead_code)]
    pub fn from_vec(args: Vec<std::ffi::OsString>) -> xflags::Result<Self> {
        Self::from_vec_(args)
    }
}
// generated end

#[derive(Debug, PartialEq, Eq)]
pub enum OutputFormat {
    Csv,
}

impl RustAnalyzer {
    pub fn verbosity(&self) -> Verbosity {
        if self.quiet {
            return Verbosity::Quiet;
        }
        match self.verbose {
            0 => Verbosity::Normal,
            1 => Verbosity::Verbose,
            _ => Verbosity::Spammy,
        }
    }
}

impl FromStr for OutputFormat {
    type Err = String;

    fn from_str(s: &str) -> Result<Self, Self::Err> {
        match s {
            "csv" => Ok(Self::Csv),
            _ => Err(format!("unknown output format `{}`", s)),
        }
    }
}
<|endoftext|>


<commit_before>//! Provides various functions and structs for MessagePack encoding.

mod sint;
mod uint;
mod dec;
mod str;
mod bin;
mod vec;
mod map;
mod ext;

pub use self::sint::{write_nfix, write_i8, write_i16, write_i32, write_i64, write_sint};
pub use self::uint::{write_pfix, write_u8, write_u16, write_u32, write_u64, write_uint};
pub use self::dec::{write_f32, write_f64};
pub use self::str::{write_str_len, write_str};
pub use self::bin::{write_bin_len, write_bin};

use std::error;
use std::fmt::{self, Display, Formatter};
use std::io::Write;

use byteorder::{self, WriteBytesExt};

use Marker;

/// The error type for I/O operations of the `Write` and associated traits.
pub type Error = ::std::io::Error;

// An error returned from the `write_marker` and `write_fixval` functions.
struct MarkerWriteError(Error);

impl From<Error> for MarkerWriteError {
    fn from(err: Error) -> MarkerWriteError {
        MarkerWriteError(err)
    }
}

impl From<MarkerWriteError> for Error {
    fn from(err: MarkerWriteError) -> Error {
        match err {
            MarkerWriteError(err) => err
        }
    }
}

/// Attempts to write the given marker into the writer.
fn write_marker<W: Write>(wr: &mut W, marker: Marker) -> Result<(), MarkerWriteError> {
    wr.write_u8(marker.to_u8()).map_err(MarkerWriteError)
}

/// An error returned from primitive values write functions.
struct DataWriteError(Error);

impl From<Error> for DataWriteError {
    fn from(err: Error) -> DataWriteError {
        DataWriteError(err)
    }
}

impl From<DataWriteError> for Error {
    fn from(err: DataWriteError) -> Error {
        err.0
    }
}

/// Encodes and attempts to write a nil value into the given write.
///
/// According to the MessagePack specification, a nil value is represented as a single `0xc0` byte.
///
/// # Errors
///
/// This function will return `Error` on any I/O error occurred while writing the nil marker.
///
/// # Examples
///
/// ```
/// let mut buf = Vec::new();
///
/// rmp::encode::write_nil(&mut buf).unwrap();
///
/// assert_eq!(vec![0xc0], buf);
/// ```
pub fn write_nil<W: Write>(wr: &mut W) -> Result<(), Error> {
    write_marker(wr, Marker::Null).map_err(From::from)
}

/// Encodes and attempts to write a bool value into the given write.
///
/// According to the MessagePack specification, an encoded boolean value is represented as a single
/// byte.
///
/// # Errors
///
/// Each call to this function may generate an I/O error indicating that the operation could not be
/// completed.
pub fn write_bool<W: Write>(wr: &mut W, val: bool) -> Result<(), Error> {
    let marker = if val {
        Marker::True
    } else {
        Marker::False
    };

    write_marker(wr, marker).map_err(From::from)
}

fn write_data_u8<W: Write>(wr: &mut W, val: u8) -> Result<(), DataWriteError> {
    wr.write_u8(val).map_err(DataWriteError)
}

fn write_data_u16<W: Write>(wr: &mut W, val: u16) -> Result<(), DataWriteError> {
    wr.write_u16::<byteorder::BigEndian>(val).map_err(DataWriteError)
}

fn write_data_u32<W: Write>(wr: &mut W, val: u32) -> Result<(), DataWriteError> {
    wr.write_u32::<byteorder::BigEndian>(val).map_err(DataWriteError)
}

fn write_data_u64<W: Write>(wr: &mut W, val: u64) -> Result<(), DataWriteError> {
    wr.write_u64::<byteorder::BigEndian>(val).map_err(DataWriteError)
}

fn write_data_i8<W: Write>(wr: &mut W, val: i8) -> Result<(), DataWriteError> {
    wr.write_i8(val).map_err(DataWriteError)
}

fn write_data_i16<W: Write>(wr: &mut W, val: i16) -> Result<(), DataWriteError> {
    wr.write_i16::<byteorder::BigEndian>(val).map_err(DataWriteError)
}

fn write_data_i32<W: Write>(wr: &mut W, val: i32) -> Result<(), DataWriteError> {
    wr.write_i32::<byteorder::BigEndian>(val).map_err(DataWriteError)
}

fn write_data_i64<W: Write>(wr: &mut W, val: i64) -> Result<(), DataWriteError> {
    wr.write_i64::<byteorder::BigEndian>(val).map_err(DataWriteError)
}

fn write_data_f32<W: Write>(wr: &mut W, val: f32) -> Result<(), DataWriteError> {
    wr.write_f32::<byteorder::BigEndian>(val).map_err(DataWriteError)
}

fn write_data_f64<W: Write>(wr: &mut W, val: f64) -> Result<(), DataWriteError> {
    wr.write_f64::<byteorder::BigEndian>(val).map_err(DataWriteError)
}

/// An error that can occur when attempring to write multibyte MessagePack value.
#[derive(Debug)]
pub enum ValueWriteError {
    /// I/O error while writing marker.
    InvalidMarkerWrite(Error),
    /// I/O error while writing data.
    InvalidDataWrite(Error),
}

impl From<MarkerWriteError> for ValueWriteError {
    fn from(err: MarkerWriteError) -> ValueWriteError {
        match err {
            MarkerWriteError(err) => ValueWriteError::InvalidMarkerWrite(err),
        }
    }
}

impl From<DataWriteError> for ValueWriteError {
    fn from(err: DataWriteError) -> ValueWriteError {
        match err {
            DataWriteError(err) => ValueWriteError::InvalidDataWrite(err),
        }
    }
}

impl From<ValueWriteError> for Error {
    fn from(err: ValueWriteError) -> Error {
        match err {
            ValueWriteError::InvalidMarkerWrite(err) |
            ValueWriteError::InvalidDataWrite(err) => err,
        }
    }
}

impl error::Error for ValueWriteError {
    fn description(&self) -> &str {
        "error while writing multibyte MessagePack value"
    }

    fn cause(&self) -> Option<&error::Error> {
        match *self {
            ValueWriteError::InvalidMarkerWrite(ref err) |
            ValueWriteError::InvalidDataWrite(ref err) => Some(err),
        }
    }
}

impl Display for ValueWriteError {
    fn fmt(&self, f: &mut Formatter) -> Result<(), fmt::Error> {
        error::Error::description(self).fmt(f)
    }
}

/// Encodes and attempts to write the most efficient array length implementation to the given write,
/// returning the marker used.
///
/// # Errors
///
/// This function will return `ValueWriteError` on any I/O error occurred while writing either the
/// marker or the data, except the EINTR, which is handled internally.
pub fn write_array_len<W: Write>(wr: &mut W, len: u32) -> Result<Marker, ValueWriteError> {
    let marker = if len < 16 {
        try!(write_marker(wr, Marker::FixArray(len as u8)));
        Marker::FixArray(len as u8)
    } else if len < 65536 {
        try!(write_marker(wr, Marker::Array16));
        try!(write_data_u16(wr, len as u16));
        Marker::Array16
    } else {
        try!(write_marker(wr, Marker::Array32));
        try!(write_data_u32(wr, len));
        Marker::Array32
    };

    Ok(marker)
}

/// Encodes and attempts to write the most efficient map length implementation to the given write,
/// returning the marker used.
///
/// # Errors
///
/// This function will return `ValueWriteError` on any I/O error occurred while writing either the
/// marker or the data, except the EINTR, which is handled internally.
pub fn write_map_len<W: Write>(wr: &mut W, len: u32) -> Result<Marker, ValueWriteError> {
    let marker = if len < 16 {
        try!(write_marker(wr, Marker::FixMap(len as u8)));
        Marker::FixMap(len as u8)
    } else if len < 65536 {
        try!(write_marker(wr, Marker::Map16));
        try!(write_data_u16(wr, len as u16));
        Marker::Map16
    } else {
        try!(write_marker(wr, Marker::Map32));
        try!(write_data_u32(wr, len));
        Marker::Map32
    };

    Ok(marker)
}

/// Encodes and attempts to write the most efficient ext metadata implementation to the given
/// write, returning the marker used.
///
/// # Errors
///
/// This function will return `ValueWriteError` on any I/O error occurred while writing either the
/// marker or the data, except the EINTR, which is handled internally.
///
/// # Panics
///
/// Panics if `ty` is negative, because it is reserved for future MessagePack extension including
/// 2-byte type information.
pub fn write_ext_meta<W: Write>(wr: &mut W, len: u32, ty: i8) -> Result<Marker, ValueWriteError> {
    assert!(ty >= 0);

    let marker = match len {
        1 => {
            try!(write_marker(wr, Marker::FixExt1));
            Marker::FixExt1
        }
        2 => {
            try!(write_marker(wr, Marker::FixExt2));
            Marker::FixExt2
        }
        4 => {
            try!(write_marker(wr, Marker::FixExt4));
            Marker::FixExt4
        }
        8 => {
            try!(write_marker(wr, Marker::FixExt8));
            Marker::FixExt8
        }
        16 => {
            try!(write_marker(wr, Marker::FixExt16));
            Marker::FixExt16
        }
        len if len < 256 => {
            try!(write_marker(wr, Marker::Ext8));
            try!(write_data_u8(wr, len as u8));
            Marker::Ext8
        }
        len if len < 65536 => {
            try!(write_marker(wr, Marker::Ext16));
            try!(write_data_u16(wr, len as u16));
            Marker::Ext16
        }
        len => {
            try!(write_marker(wr, Marker::Ext32));
            try!(write_data_u32(wr, len));
            Marker::Ext32
        }
    };

    try!(write_data_i8(wr, ty));

    Ok(marker)
}
<commit_msg>docs: typos<commit_after>//! Provides various functions and structs for MessagePack encoding.

mod sint;
mod uint;
mod dec;
mod str;
mod bin;
mod vec;
mod map;
mod ext;

pub use self::sint::{write_nfix, write_i8, write_i16, write_i32, write_i64, write_sint};
pub use self::uint::{write_pfix, write_u8, write_u16, write_u32, write_u64, write_uint};
pub use self::dec::{write_f32, write_f64};
pub use self::str::{write_str_len, write_str};
pub use self::bin::{write_bin_len, write_bin};

use std::error;
use std::fmt::{self, Display, Formatter};
use std::io::Write;

use byteorder::{self, WriteBytesExt};

use Marker;

/// The error type for I/O operations of the `Write` and associated traits.
pub type Error = ::std::io::Error;

// An error returned from the `write_marker` and `write_fixval` functions.
struct MarkerWriteError(Error);

impl From<Error> for MarkerWriteError {
    fn from(err: Error) -> MarkerWriteError {
        MarkerWriteError(err)
    }
}

impl From<MarkerWriteError> for Error {
    fn from(err: MarkerWriteError) -> Error {
        match err {
            MarkerWriteError(err) => err
        }
    }
}

/// Attempts to write the given marker into the writer.
fn write_marker<W: Write>(wr: &mut W, marker: Marker) -> Result<(), MarkerWriteError> {
    wr.write_u8(marker.to_u8()).map_err(MarkerWriteError)
}

/// An error returned from primitive values write functions.
struct DataWriteError(Error);

impl From<Error> for DataWriteError {
    fn from(err: Error) -> DataWriteError {
        DataWriteError(err)
    }
}

impl From<DataWriteError> for Error {
    fn from(err: DataWriteError) -> Error {
        err.0
    }
}

/// Encodes and attempts to write a nil value into the given write.
///
/// According to the MessagePack specification, a nil value is represented as a single `0xc0` byte.
///
/// # Errors
///
/// This function will return `Error` on any I/O error occurred while writing the nil marker.
///
/// # Examples
///
/// ```
/// let mut buf = Vec::new();
///
/// rmp::encode::write_nil(&mut buf).unwrap();
///
/// assert_eq!(vec![0xc0], buf);
/// ```
pub fn write_nil<W: Write>(wr: &mut W) -> Result<(), Error> {
    write_marker(wr, Marker::Null).map_err(From::from)
}

/// Encodes and attempts to write a bool value into the given write.
///
/// According to the MessagePack specification, an encoded boolean value is represented as a single
/// byte.
///
/// # Errors
///
/// Each call to this function may generate an I/O error indicating that the operation could not be
/// completed.
pub fn write_bool<W: Write>(wr: &mut W, val: bool) -> Result<(), Error> {
    let marker = if val {
        Marker::True
    } else {
        Marker::False
    };

    write_marker(wr, marker).map_err(From::from)
}

fn write_data_u8<W: Write>(wr: &mut W, val: u8) -> Result<(), DataWriteError> {
    wr.write_u8(val).map_err(DataWriteError)
}

fn write_data_u16<W: Write>(wr: &mut W, val: u16) -> Result<(), DataWriteError> {
    wr.write_u16::<byteorder::BigEndian>(val).map_err(DataWriteError)
}

fn write_data_u32<W: Write>(wr: &mut W, val: u32) -> Result<(), DataWriteError> {
    wr.write_u32::<byteorder::BigEndian>(val).map_err(DataWriteError)
}

fn write_data_u64<W: Write>(wr: &mut W, val: u64) -> Result<(), DataWriteError> {
    wr.write_u64::<byteorder::BigEndian>(val).map_err(DataWriteError)
}

fn write_data_i8<W: Write>(wr: &mut W, val: i8) -> Result<(), DataWriteError> {
    wr.write_i8(val).map_err(DataWriteError)
}

fn write_data_i16<W: Write>(wr: &mut W, val: i16) -> Result<(), DataWriteError> {
    wr.write_i16::<byteorder::BigEndian>(val).map_err(DataWriteError)
}

fn write_data_i32<W: Write>(wr: &mut W, val: i32) -> Result<(), DataWriteError> {
    wr.write_i32::<byteorder::BigEndian>(val).map_err(DataWriteError)
}

fn write_data_i64<W: Write>(wr: &mut W, val: i64) -> Result<(), DataWriteError> {
    wr.write_i64::<byteorder::BigEndian>(val).map_err(DataWriteError)
}

fn write_data_f32<W: Write>(wr: &mut W, val: f32) -> Result<(), DataWriteError> {
    wr.write_f32::<byteorder::BigEndian>(val).map_err(DataWriteError)
}

fn write_data_f64<W: Write>(wr: &mut W, val: f64) -> Result<(), DataWriteError> {
    wr.write_f64::<byteorder::BigEndian>(val).map_err(DataWriteError)
}

/// An error that can occur when attempting to write multi-byte MessagePack value.
#[derive(Debug)]
pub enum ValueWriteError {
    /// I/O error while writing marker.
    InvalidMarkerWrite(Error),
    /// I/O error while writing data.
    InvalidDataWrite(Error),
}

impl From<MarkerWriteError> for ValueWriteError {
    fn from(err: MarkerWriteError) -> ValueWriteError {
        match err {
            MarkerWriteError(err) => ValueWriteError::InvalidMarkerWrite(err),
        }
    }
}

impl From<DataWriteError> for ValueWriteError {
    fn from(err: DataWriteError) -> ValueWriteError {
        match err {
            DataWriteError(err) => ValueWriteError::InvalidDataWrite(err),
        }
    }
}

impl From<ValueWriteError> for Error {
    fn from(err: ValueWriteError) -> Error {
        match err {
            ValueWriteError::InvalidMarkerWrite(err) |
            ValueWriteError::InvalidDataWrite(err) => err,
        }
    }
}

impl error::Error for ValueWriteError {
    fn description(&self) -> &str {
        "error while writing multibyte MessagePack value"
    }

    fn cause(&self) -> Option<&error::Error> {
        match *self {
            ValueWriteError::InvalidMarkerWrite(ref err) |
            ValueWriteError::InvalidDataWrite(ref err) => Some(err),
        }
    }
}

impl Display for ValueWriteError {
    fn fmt(&self, f: &mut Formatter) -> Result<(), fmt::Error> {
        error::Error::description(self).fmt(f)
    }
}

/// Encodes and attempts to write the most efficient array length implementation to the given write,
/// returning the marker used.
///
/// # Errors
///
/// This function will return `ValueWriteError` on any I/O error occurred while writing either the
/// marker or the data, except the EINTR, which is handled internally.
pub fn write_array_len<W: Write>(wr: &mut W, len: u32) -> Result<Marker, ValueWriteError> {
    let marker = if len < 16 {
        try!(write_marker(wr, Marker::FixArray(len as u8)));
        Marker::FixArray(len as u8)
    } else if len < 65536 {
        try!(write_marker(wr, Marker::Array16));
        try!(write_data_u16(wr, len as u16));
        Marker::Array16
    } else {
        try!(write_marker(wr, Marker::Array32));
        try!(write_data_u32(wr, len));
        Marker::Array32
    };

    Ok(marker)
}

/// Encodes and attempts to write the most efficient map length implementation to the given write,
/// returning the marker used.
///
/// # Errors
///
/// This function will return `ValueWriteError` on any I/O error occurred while writing either the
/// marker or the data, except the EINTR, which is handled internally.
pub fn write_map_len<W: Write>(wr: &mut W, len: u32) -> Result<Marker, ValueWriteError> {
    let marker = if len < 16 {
        try!(write_marker(wr, Marker::FixMap(len as u8)));
        Marker::FixMap(len as u8)
    } else if len < 65536 {
        try!(write_marker(wr, Marker::Map16));
        try!(write_data_u16(wr, len as u16));
        Marker::Map16
    } else {
        try!(write_marker(wr, Marker::Map32));
        try!(write_data_u32(wr, len));
        Marker::Map32
    };

    Ok(marker)
}

/// Encodes and attempts to write the most efficient ext metadata implementation to the given
/// write, returning the marker used.
///
/// # Errors
///
/// This function will return `ValueWriteError` on any I/O error occurred while writing either the
/// marker or the data, except the EINTR, which is handled internally.
///
/// # Panics
///
/// Panics if `ty` is negative, because it is reserved for future MessagePack extension including
/// 2-byte type information.
pub fn write_ext_meta<W: Write>(wr: &mut W, len: u32, ty: i8) -> Result<Marker, ValueWriteError> {
    assert!(ty >= 0);

    let marker = match len {
        1 => {
            try!(write_marker(wr, Marker::FixExt1));
            Marker::FixExt1
        }
        2 => {
            try!(write_marker(wr, Marker::FixExt2));
            Marker::FixExt2
        }
        4 => {
            try!(write_marker(wr, Marker::FixExt4));
            Marker::FixExt4
        }
        8 => {
            try!(write_marker(wr, Marker::FixExt8));
            Marker::FixExt8
        }
        16 => {
            try!(write_marker(wr, Marker::FixExt16));
            Marker::FixExt16
        }
        len if len < 256 => {
            try!(write_marker(wr, Marker::Ext8));
            try!(write_data_u8(wr, len as u8));
            Marker::Ext8
        }
        len if len < 65536 => {
            try!(write_marker(wr, Marker::Ext16));
            try!(write_data_u16(wr, len as u16));
            Marker::Ext16
        }
        len => {
            try!(write_marker(wr, Marker::Ext32));
            try!(write_data_u32(wr, len));
            Marker::Ext32
        }
    };

    try!(write_data_i8(wr, ty));

    Ok(marker)
}
<|endoftext|>


<commit_before>// Lumol, an extensible molecular simulation engine
// Copyright (C) 2015-2016 G. Fraux — BSD license

//! Testing physical properties of a Lennard-Jones Argon
//! Monte-Carlo simulation
extern crate lumol;
extern crate lumol_input as input;

use lumol::Logger;
use lumol::sys::{System, Trajectory, UnitCell};
use lumol::energy::{LennardJones, PairInteraction};
use lumol::sim::Simulation;
use lumol::sim::mc::{MonteCarlo, Translate, Resize};
use lumol::units;
use lumol::out::{EnergyOutput, PropertiesOutput};

use std::sync::{Once, ONCE_INIT};
static START: Once = ONCE_INIT;

use std::path::Path;

fn get_system() -> System {
    let data_dir = Path::new(file!()).parent().unwrap();
    let configuration = data_dir.join("data").join("argon.xyz");
    let mut system = Trajectory::open(configuration)
                               .and_then(|mut traj| traj.read())
                               .unwrap();

    system.set_cell(UnitCell::cubic(31.0));

    // add LJ cut + tail corrections
    let lj = Box::new(LennardJones{
        sigma: units::from(3.405, "A").unwrap(),
        epsilon: units::from(1.0, "kJ/mol").unwrap()
    });

    let mut pairs = PairInteraction::new(lj, 10.215);
    pairs.enable_tail_corrections();
    system.interactions_mut().add_pair("Ar", "Ar", pairs);
    return system;
}

fn main() {
    START.call_once(|| {Logger::stdout();});
    let mut system = get_system();

    // rng: set this here in case we want to change the seed
    //let mut rng = Box::new(rand::XorShiftRng::new_unseeded());
    //rng.reseed([2015u32, 42u32, 3u32, 12u32]);

    // set thermodynamic state (T,p)
    // rc = 10.215 A
    // T  = 108.24463287 K
    // V  = 21932.030625 A^3
    // p  = 1087.26359088 bar
    // L  = 27.9915070437 A
    // We use this state to compare to NIST NVT data

    let temperature = units::from(108.0, "K").unwrap();
    let pressure = units::from(1087.0, "bar").unwrap();
    //let mut mc = MonteCarlo::from_rng(temperature, rng); // This is not working, why?
    let mut mc = MonteCarlo::new(temperature);

    // Build move set for NPT
    let delta_trans = units::from(3.0, "A").unwrap();
    let delta_vol = units::from(0.05 * system.volume(), "A^3").unwrap();

    mc.add_move_with_acceptance(
        Box::new(Translate::new(delta_trans)), 500.0, 0.3);
    mc.add_move_with_acceptance(
        Box::new(Resize::new(pressure, delta_vol)), 2.0, 0.3);
    mc.set_amplitude_update_frequency(200);

    let mut simulation = Simulation::new(Box::new(mc));
    simulation.add_output_with_frequency(
        Box::new(PropertiesOutput::new("npt_prp.dat").unwrap()), 500);
    simulation.add_output_with_frequency(
        Box::new(EnergyOutput::new("npt_ener.dat").unwrap()), 500);

    println!("initial U/N = {:8.2} kJ/mol", units::to(system.total_energy(),"kJ/mol").unwrap() / system.size() as f64);

    // run simulation
    simulation.run(&mut system, 2_000_000);

    println!("final   U/N = {:8.2} kJ/mol", units::to(system.total_energy(),"kJ/mol").unwrap() / system.size() as f64);
}
<commit_msg>Some changes to example<commit_after>// Lumol, an extensible molecular simulation engine
// Copyright (C) 2015-2016 G. Fraux — BSD license

//! Testing physical properties of a Lennard-Jones Argon
//! Monte-Carlo simulation
extern crate lumol;
extern crate lumol_input as input;

use lumol::Logger;
use lumol::sys::{System, Trajectory, UnitCell};
use lumol::energy::{LennardJones, PairInteraction};
use lumol::sim::Simulation;
use lumol::sim::mc::{MonteCarlo, Translate, Resize};
use lumol::units;
use lumol::out::{EnergyOutput, PropertiesOutput};

use std::sync::{Once, ONCE_INIT};
static START: Once = ONCE_INIT;

use std::path::Path;

fn get_system() -> System {
    let data_dir = Path::new(file!()).parent().unwrap();
    let configuration = data_dir.join("data").join("argon.xyz");
    let mut system = Trajectory::open(configuration)
                               .and_then(|mut traj| traj.read())
                               .unwrap();

    system.set_cell(UnitCell::cubic(31.0));

    // add LJ cut + tail corrections
    let lj = Box::new(LennardJones{
        sigma: units::from(3.405, "A").unwrap(),
        epsilon: units::from(1.0, "kJ/mol").unwrap()
    });

    let mut pairs = PairInteraction::new(lj, 10.215);
    pairs.enable_tail_corrections();
    system.interactions_mut().add_pair("Ar", "Ar", pairs);
    return system;
}

fn main() {
    START.call_once(|| {Logger::stdout();});
    let mut system = get_system();

    // rng: set this here in case we want to change the seed
    //let mut rng = Box::new(rand::XorShiftRng::new_unseeded());
    //rng.reseed([2015u32, 42u32, 3u32, 12u32]);

    // set thermodynamic state (T,p)
    // rc = 10.215 A
    // T  = 108.24463287 K
    // V  = 21932.030625 A^3
    // p  = 1087.26359088 bar
    // L  = 27.9915070437 A
    // We use this state to compare to NIST NVT data

    let temperature = units::from(108.0, "K").unwrap();
    let pressure = units::from(1087.0, "bar").unwrap();
    //let mut mc = MonteCarlo::from_rng(temperature, rng); // This is not working, why?
    let mut mc = MonteCarlo::new(temperature);

    // Build move set for NPT
    let delta_trans = units::from(3.0, "A").unwrap();
    let delta_vol = units::from(0.05 * system.volume(), "A^3").unwrap();

    mc.add_move_with_acceptance(
        Box::new(Translate::new(delta_trans)), 500.0, 0.5);
    mc.add_move_with_acceptance(
        Box::new(Resize::new(pressure, delta_vol)), 2.0, 0.5);
    mc.set_amplitude_update_frequency(200);

    let mut simulation = Simulation::new(Box::new(mc));
    simulation.add_output_with_frequency(
        Box::new(PropertiesOutput::new("npt_prp.dat").unwrap()), 500);
    simulation.add_output_with_frequency(
        Box::new(EnergyOutput::new("npt_ener.dat").unwrap()), 500);

    println!("initial U/N = {:8.2} kJ/mol", units::to(system.total_energy(),"kJ/mol").unwrap() / system.size() as f64);

    // run simulation
    simulation.run(&mut system, 2_000_000);

    println!("final U/N = {:8.2} kJ/mol", units::to(system.total_energy(),"kJ/mol").unwrap() / system.size() as f64);
}
<|endoftext|>


<commit_before>/*
Module: option

Represents the presence or absence of a value.

Every option<T> value can either be some(T) or none. Where in other languages
you might use a nullable type, in Rust you would use an option type.
*/

/*
Tag: t

The option type
*/
enum t<T> {
    /* Variant: none */
    none,
    /* Variant: some */
    some(T),
}

/* Section: Operations */

/*
Function: get

Gets the value out of an option

Failure:

Fails if the value equals `none`.
*/
pure fn get<T: copy>(opt: t<T>) -> T {
    alt opt { some(x) { ret x; } none { fail "option none"; } }
}

/*
*/
fn map<T, U: copy>(opt: t<T>, f: fn(T) -> U) -> t<U> {
    alt opt { some(x) { some(f(x)) } none { none } }
}

/*
Function: is_none

Returns true if the option equals none
*/
pure fn is_none<T>(opt: t<T>) -> bool {
    alt opt { none { true } some(_) { false } }
}

/*
Function: is_some

Returns true if the option contains some value
*/
pure fn is_some<T>(opt: t<T>) -> bool { !is_none(opt) }

/*
Function: from_maybe

Returns the contained value or a default
*/
pure fn from_maybe<T: copy>(def: T, opt: t<T>) -> T {
    alt opt { some(x) { x } none { def } }
}

/*
Function: maybe

Applies a function to the contained value or returns a default
*/
fn maybe<T, U: copy>(def: U, opt: t<T>, f: fn(T) -> U) -> U {
    alt opt { none { def } some(t) { f(t) } }
}

// FIXME: Can be defined in terms of the above when/if we have const bind.
/*
Function: may

Performs an operation on the contained value or does nothing
*/
fn may<T>(opt: t<T>, f: fn(T)) {
    alt opt { none {/* nothing */ } some(t) { f(t); } }
}

// Local Variables:
// mode: rust;
// fill-column: 78;
// indent-tabs-mode: nil
// c-basic-offset: 4
// buffer-file-coding-system: utf-8-unix
// End:
<commit_msg>core: Add option::unwrap<commit_after>/*
Module: option

Represents the presence or absence of a value.

Every option<T> value can either be some(T) or none. Where in other languages
you might use a nullable type, in Rust you would use an option type.
*/

/*
Tag: t

The option type
*/
enum t<T> {
    /* Variant: none */
    none,
    /* Variant: some */
    some(T),
}

/* Section: Operations */

/*
Function: get

Gets the value out of an option

Failure:

Fails if the value equals `none`.
*/
pure fn get<T: copy>(opt: t<T>) -> T {
    alt opt { some(x) { ret x; } none { fail "option none"; } }
}

/*
*/
fn map<T, U: copy>(opt: t<T>, f: fn(T) -> U) -> t<U> {
    alt opt { some(x) { some(f(x)) } none { none } }
}

/*
Function: is_none

Returns true if the option equals none
*/
pure fn is_none<T>(opt: t<T>) -> bool {
    alt opt { none { true } some(_) { false } }
}

/*
Function: is_some

Returns true if the option contains some value
*/
pure fn is_some<T>(opt: t<T>) -> bool { !is_none(opt) }

/*
Function: from_maybe

Returns the contained value or a default
*/
pure fn from_maybe<T: copy>(def: T, opt: t<T>) -> T {
    alt opt { some(x) { x } none { def } }
}

/*
Function: maybe

Applies a function to the contained value or returns a default
*/
fn maybe<T, U: copy>(def: U, opt: t<T>, f: fn(T) -> U) -> U {
    alt opt { none { def } some(t) { f(t) } }
}

// FIXME: Can be defined in terms of the above when/if we have const bind.
/*
Function: may

Performs an operation on the contained value or does nothing
*/
fn may<T>(opt: t<T>, f: fn(T)) {
    alt opt { none {/* nothing */ } some(t) { f(t); } }
}

/*
Function: unwrap

Moves a value out of an option type and returns it. Useful primarily
for getting strings, vectors and unique pointers out of option types
without copying them.
*/
fn unwrap<T>(-opt: t<T>) -> T unsafe {
    let addr = alt opt {
      some(x) { ptr::addr_of(x) }
      none { fail "option none" }
    };
    let liberated_value = unsafe::reinterpret_cast(*addr);
    unsafe::leak(opt);
    ret liberated_value;
}

#[test]
fn test_unwrap_ptr() {
    let x = ~0;
    let addr_x = ptr::addr_of(*x);
    let opt = some(x);
    let y = unwrap(opt);
    let addr_y = ptr::addr_of(*y);
    assert addr_x == addr_y;
}

#[test]
fn test_unwrap_str() {
    let x = "test";
    let addr_x = str::as_buf(x) {|buf| ptr::addr_of(buf) };
    let opt = some(x);
    let y = unwrap(opt);
    let addr_y = str::as_buf(y) {|buf| ptr::addr_of(buf) };
    assert addr_x == addr_y;
}

#[test]
fn test_unwrap_resource() {
    resource r(i: @mutable int) {
        *i += 1;
    }
    let i = @mutable 0;
    {
        let x = r(i);
        let opt = some(x);
        let y = unwrap(opt);
    }
    assert *i == 1;
}

// Local Variables:
// mode: rust;
// fill-column: 78;
// indent-tabs-mode: nil
// c-basic-offset: 4
// buffer-file-coding-system: utf-8-unix
// End:
<|endoftext|>


<commit_before>#![allow(missing_copy_implementations)]

use crate::fmt;
use crate::io::{self, Read, Initializer, Write, ErrorKind, BufRead, IoSlice, IoSliceMut};
use crate::mem;

/// Copies the entire contents of a reader into a writer.
///
/// This function will continuously read data from `reader` and then
/// write it into `writer` in a streaming fashion until `reader`
/// returns EOF.
///
/// On success, the total number of bytes that were copied from
/// `reader` to `writer` is returned.
///
/// If you’re wanting to copy the contents of one file to another and you’re
/// working with filesystem paths, see the [`fs::copy`] function.
///
/// [`fs::copy`]: ../fs/fn.copy.html
///
/// # Errors
///
/// This function will return an error immediately if any call to `read` or
/// `write` returns an error. All instances of `ErrorKind::Interrupted` are
/// handled by this function and the underlying operation is retried.
///
/// # Examples
///
/// ```
/// use std::io;
///
/// fn main() -> io::Result<()> {
///     let mut reader: &[u8] = b"hello";
///     let mut writer: Vec<u8> = vec![];
///
///     io::copy(&mut reader, &mut writer)?;
///
///     assert_eq!(&b"hello"[..], &writer[..]);
///     Ok(())
/// }
/// ```
#[stable(feature = "rust1", since = "1.0.0")]
pub fn copy<R: ?Sized, W: ?Sized>(reader: &mut R, writer: &mut W) -> io::Result<u64>
    where R: Read, W: Write
{
    let mut buf = unsafe {
        #[allow(deprecated)]
        let mut buf: [u8; super::DEFAULT_BUF_SIZE] = mem::uninitialized();
        reader.initializer().initialize(&mut buf);
        buf
    };

    let mut written = 0;
    loop {
        let len = match reader.read(&mut buf) {
            Ok(0) => return Ok(written),
            Ok(len) => len,
            Err(ref e) if e.kind() == ErrorKind::Interrupted => continue,
            Err(e) => return Err(e),
        };
        writer.write_all(&buf[..len])?;
        written += len as u64;
    }
}

/// A reader which is always at EOF.
///
/// This struct is generally created by calling [`empty`]. Please see
/// the documentation of [`empty()`][`empty`] for more details.
///
/// [`empty`]: fn.empty.html
#[stable(feature = "rust1", since = "1.0.0")]
pub struct Empty { _priv: () }

/// Constructs a new handle to an empty reader.
///
/// All reads from the returned reader will return [`Ok`]`(0)`.
///
/// [`Ok`]: ../result/enum.Result.html#variant.Ok
///
/// # Examples
///
/// A slightly sad example of not reading anything into a buffer:
///
/// ```
/// use std::io::{self, Read};
///
/// let mut buffer = String::new();
/// io::empty().read_to_string(&mut buffer).unwrap();
/// assert!(buffer.is_empty());
/// ```
#[stable(feature = "rust1", since = "1.0.0")]
pub fn empty() -> Empty { Empty { _priv: () } }

#[stable(feature = "rust1", since = "1.0.0")]
impl Read for Empty {
    #[inline]
    fn read(&mut self, _buf: &mut [u8]) -> io::Result<usize> { Ok(0) }

    #[inline]
    unsafe fn initializer(&self) -> Initializer {
        Initializer::nop()
    }
}
#[stable(feature = "rust1", since = "1.0.0")]
impl BufRead for Empty {
    #[inline]
    fn fill_buf(&mut self) -> io::Result<&[u8]> { Ok(&[]) }
    #[inline]
    fn consume(&mut self, _n: usize) {}
}

#[stable(feature = "std_debug", since = "1.16.0")]
impl fmt::Debug for Empty {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        f.pad("Empty { .. }")
    }
}

/// A reader which yields one byte over and over and over and over and over and...
///
/// This struct is generally created by calling [`repeat`][repeat]. Please
/// see the documentation of `repeat()` for more details.
///
/// [repeat]: fn.repeat.html
#[stable(feature = "rust1", since = "1.0.0")]
pub struct Repeat { byte: u8 }

/// Creates an instance of a reader that infinitely repeats one byte.
///
/// All reads from this reader will succeed by filling the specified buffer with
/// the given byte.
///
/// # Examples
///
/// ```
/// use std::io::{self, Read};
///
/// let mut buffer = [0; 3];
/// io::repeat(0b101).read_exact(&mut buffer).unwrap();
/// assert_eq!(buffer, [0b101, 0b101, 0b101]);
/// ```
#[stable(feature = "rust1", since = "1.0.0")]
pub fn repeat(byte: u8) -> Repeat { Repeat { byte } }

#[stable(feature = "rust1", since = "1.0.0")]
impl Read for Repeat {
    #[inline]
    fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
        for slot in &mut *buf {
            *slot = self.byte;
        }
        Ok(buf.len())
    }

    #[inline]
    fn read_vectored(&mut self, bufs: &mut [IoSliceMut<'_>]) -> io::Result<usize> {
        let mut nwritten = 0;
        for buf in bufs {
            nwritten += self.read(buf)?;
        }
        Ok(nwritten)
    }

    #[inline]
    unsafe fn initializer(&self) -> Initializer {
        Initializer::nop()
    }
}

#[stable(feature = "std_debug", since = "1.16.0")]
impl fmt::Debug for Repeat {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        f.pad("Repeat { .. }")
    }
}

/// A writer which will move data into the void.
///
/// This struct is generally created by calling [`sink`][sink]. Please
/// see the documentation of `sink()` for more details.
///
/// [sink]: fn.sink.html
#[stable(feature = "rust1", since = "1.0.0")]
pub struct Sink { _priv: () }

/// Creates an instance of a writer which will successfully consume all data.
///
/// All calls to `write` on the returned instance will return `Ok(buf.len())`
/// and the contents of the buffer will not be inspected.
///
/// # Examples
///
/// ```rust
/// use std::io::{self, Write};
///
/// let buffer = vec![1, 2, 3, 5, 8];
/// let num_bytes = io::sink().write(&buffer).unwrap();
/// assert_eq!(num_bytes, 5);
/// ```
#[stable(feature = "rust1", since = "1.0.0")]
pub fn sink() -> Sink { Sink { _priv: () } }

#[stable(feature = "rust1", since = "1.0.0")]
impl Write for Sink {
    #[inline]
    fn write(&mut self, buf: &[u8]) -> io::Result<usize> { Ok(buf.len()) }

    #[inline]
    fn write_vectored(&mut self, bufs: &[IoSlice<'_>]) -> io::Result<usize> {
        let total_len = bufs.iter().map(|b| b.len()).sum();
        Ok(total_len)
    }

    #[inline]
    fn flush(&mut self) -> io::Result<()> { Ok(()) }
}

#[stable(feature = "std_debug", since = "1.16.0")]
impl fmt::Debug for Sink {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        f.pad("Sink { .. }")
    }
}

#[cfg(test)]
mod tests {
    use crate::io::prelude::*;
    use crate::io::{copy, sink, empty, repeat};

    #[test]
    fn copy_copies() {
        let mut r = repeat(0).take(4);
        let mut w = sink();
        assert_eq!(copy(&mut r, &mut w).unwrap(), 4);

        let mut r = repeat(0).take(1 << 17);
        assert_eq!(copy(&mut r as &mut dyn Read, &mut w as &mut dyn Write).unwrap(), 1 << 17);
    }

    #[test]
    fn sink_sinks() {
        let mut s = sink();
        assert_eq!(s.write(&[]).unwrap(), 0);
        assert_eq!(s.write(&[0]).unwrap(), 1);
        assert_eq!(s.write(&[0; 1024]).unwrap(), 1024);
        assert_eq!(s.by_ref().write(&[0; 1024]).unwrap(), 1024);
    }

    #[test]
    fn empty_reads() {
        let mut e = empty();
        assert_eq!(e.read(&mut []).unwrap(), 0);
        assert_eq!(e.read(&mut [0]).unwrap(), 0);
        assert_eq!(e.read(&mut [0; 1024]).unwrap(), 0);
        assert_eq!(e.by_ref().read(&mut [0; 1024]).unwrap(), 0);
    }

    #[test]
    fn repeat_repeats() {
        let mut r = repeat(4);
        let mut b = [0; 1024];
        assert_eq!(r.read(&mut b).unwrap(), 1024);
        assert!(b.iter().all(|b| *b == 4));
    }

    #[test]
    fn take_some_bytes() {
        assert_eq!(repeat(4).take(100).bytes().count(), 100);
        assert_eq!(repeat(4).take(100).bytes().next().unwrap().unwrap(), 4);
        assert_eq!(repeat(1).take(10).chain(repeat(2).take(10)).bytes().count(), 20);
    }
}
<commit_msg>Remove last use of mem::uninitialized from std::io::util<commit_after>#![allow(missing_copy_implementations)]

use crate::fmt;
use crate::io::{self, Read, Initializer, Write, ErrorKind, BufRead, IoSlice, IoSliceMut};
use crate::mem;

/// Copies the entire contents of a reader into a writer.
///
/// This function will continuously read data from `reader` and then
/// write it into `writer` in a streaming fashion until `reader`
/// returns EOF.
///
/// On success, the total number of bytes that were copied from
/// `reader` to `writer` is returned.
///
/// If you’re wanting to copy the contents of one file to another and you’re
/// working with filesystem paths, see the [`fs::copy`] function.
///
/// [`fs::copy`]: ../fs/fn.copy.html
///
/// # Errors
///
/// This function will return an error immediately if any call to `read` or
/// `write` returns an error. All instances of `ErrorKind::Interrupted` are
/// handled by this function and the underlying operation is retried.
///
/// # Examples
///
/// ```
/// use std::io;
///
/// fn main() -> io::Result<()> {
///     let mut reader: &[u8] = b"hello";
///     let mut writer: Vec<u8> = vec![];
///
///     io::copy(&mut reader, &mut writer)?;
///
///     assert_eq!(&b"hello"[..], &writer[..]);
///     Ok(())
/// }
/// ```
#[stable(feature = "rust1", since = "1.0.0")]
pub fn copy<R: ?Sized, W: ?Sized>(reader: &mut R, writer: &mut W) -> io::Result<u64>
    where R: Read, W: Write
{
    let mut buf = unsafe {
        // This is still technically undefined behavior due to creating a reference
        // to uninitialized data, but within libstd we can rely on more guarantees
        // than if this code were in an external lib

        // FIXME: This should probably be changed to an array of `MaybeUninit<u8>`
        // once the `mem::MaybeUninit` slice APIs stabilize
        let mut buf: mem::MaybeUninit<[u8; super::DEFAULT_BUF_SIZE]> = mem::MaybeUninit::uninit();
        reader.initializer().initialize(&mut *buf.as_mut_ptr());
        buf.assume_init()
    };

    let mut written = 0;
    loop {
        let len = match reader.read(&mut buf) {
            Ok(0) => return Ok(written),
            Ok(len) => len,
            Err(ref e) if e.kind() == ErrorKind::Interrupted => continue,
            Err(e) => return Err(e),
        };
        writer.write_all(&buf[..len])?;
        written += len as u64;
    }
}

/// A reader which is always at EOF.
///
/// This struct is generally created by calling [`empty`]. Please see
/// the documentation of [`empty()`][`empty`] for more details.
///
/// [`empty`]: fn.empty.html
#[stable(feature = "rust1", since = "1.0.0")]
pub struct Empty { _priv: () }

/// Constructs a new handle to an empty reader.
///
/// All reads from the returned reader will return [`Ok`]`(0)`.
///
/// [`Ok`]: ../result/enum.Result.html#variant.Ok
///
/// # Examples
///
/// A slightly sad example of not reading anything into a buffer:
///
/// ```
/// use std::io::{self, Read};
///
/// let mut buffer = String::new();
/// io::empty().read_to_string(&mut buffer).unwrap();
/// assert!(buffer.is_empty());
/// ```
#[stable(feature = "rust1", since = "1.0.0")]
pub fn empty() -> Empty { Empty { _priv: () } }

#[stable(feature = "rust1", since = "1.0.0")]
impl Read for Empty {
    #[inline]
    fn read(&mut self, _buf: &mut [u8]) -> io::Result<usize> { Ok(0) }

    #[inline]
    unsafe fn initializer(&self) -> Initializer {
        Initializer::nop()
    }
}
#[stable(feature = "rust1", since = "1.0.0")]
impl BufRead for Empty {
    #[inline]
    fn fill_buf(&mut self) -> io::Result<&[u8]> { Ok(&[]) }
    #[inline]
    fn consume(&mut self, _n: usize) {}
}

#[stable(feature = "std_debug", since = "1.16.0")]
impl fmt::Debug for Empty {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        f.pad("Empty { .. }")
    }
}

/// A reader which yields one byte over and over and over and over and over and...
///
/// This struct is generally created by calling [`repeat`][repeat]. Please
/// see the documentation of `repeat()` for more details.
///
/// [repeat]: fn.repeat.html
#[stable(feature = "rust1", since = "1.0.0")]
pub struct Repeat { byte: u8 }

/// Creates an instance of a reader that infinitely repeats one byte.
///
/// All reads from this reader will succeed by filling the specified buffer with
/// the given byte.
///
/// # Examples
///
/// ```
/// use std::io::{self, Read};
///
/// let mut buffer = [0; 3];
/// io::repeat(0b101).read_exact(&mut buffer).unwrap();
/// assert_eq!(buffer, [0b101, 0b101, 0b101]);
/// ```
#[stable(feature = "rust1", since = "1.0.0")]
pub fn repeat(byte: u8) -> Repeat { Repeat { byte } }

#[stable(feature = "rust1", since = "1.0.0")]
impl Read for Repeat {
    #[inline]
    fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
        for slot in &mut *buf {
            *slot = self.byte;
        }
        Ok(buf.len())
    }

    #[inline]
    fn read_vectored(&mut self, bufs: &mut [IoSliceMut<'_>]) -> io::Result<usize> {
        let mut nwritten = 0;
        for buf in bufs {
            nwritten += self.read(buf)?;
        }
        Ok(nwritten)
    }

    #[inline]
    unsafe fn initializer(&self) -> Initializer {
        Initializer::nop()
    }
}

#[stable(feature = "std_debug", since = "1.16.0")]
impl fmt::Debug for Repeat {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        f.pad("Repeat { .. }")
    }
}

/// A writer which will move data into the void.
///
/// This struct is generally created by calling [`sink`][sink]. Please
/// see the documentation of `sink()` for more details.
///
/// [sink]: fn.sink.html
#[stable(feature = "rust1", since = "1.0.0")]
pub struct Sink { _priv: () }

/// Creates an instance of a writer which will successfully consume all data.
///
/// All calls to `write` on the returned instance will return `Ok(buf.len())`
/// and the contents of the buffer will not be inspected.
///
/// # Examples
///
/// ```rust
/// use std::io::{self, Write};
///
/// let buffer = vec![1, 2, 3, 5, 8];
/// let num_bytes = io::sink().write(&buffer).unwrap();
/// assert_eq!(num_bytes, 5);
/// ```
#[stable(feature = "rust1", since = "1.0.0")]
pub fn sink() -> Sink { Sink { _priv: () } }

#[stable(feature = "rust1", since = "1.0.0")]
impl Write for Sink {
    #[inline]
    fn write(&mut self, buf: &[u8]) -> io::Result<usize> { Ok(buf.len()) }

    #[inline]
    fn write_vectored(&mut self, bufs: &[IoSlice<'_>]) -> io::Result<usize> {
        let total_len = bufs.iter().map(|b| b.len()).sum();
        Ok(total_len)
    }

    #[inline]
    fn flush(&mut self) -> io::Result<()> { Ok(()) }
}

#[stable(feature = "std_debug", since = "1.16.0")]
impl fmt::Debug for Sink {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        f.pad("Sink { .. }")
    }
}

#[cfg(test)]
mod tests {
    use crate::io::prelude::*;
    use crate::io::{copy, sink, empty, repeat};

    #[test]
    fn copy_copies() {
        let mut r = repeat(0).take(4);
        let mut w = sink();
        assert_eq!(copy(&mut r, &mut w).unwrap(), 4);

        let mut r = repeat(0).take(1 << 17);
        assert_eq!(copy(&mut r as &mut dyn Read, &mut w as &mut dyn Write).unwrap(), 1 << 17);
    }

    #[test]
    fn sink_sinks() {
        let mut s = sink();
        assert_eq!(s.write(&[]).unwrap(), 0);
        assert_eq!(s.write(&[0]).unwrap(), 1);
        assert_eq!(s.write(&[0; 1024]).unwrap(), 1024);
        assert_eq!(s.by_ref().write(&[0; 1024]).unwrap(), 1024);
    }

    #[test]
    fn empty_reads() {
        let mut e = empty();
        assert_eq!(e.read(&mut []).unwrap(), 0);
        assert_eq!(e.read(&mut [0]).unwrap(), 0);
        assert_eq!(e.read(&mut [0; 1024]).unwrap(), 0);
        assert_eq!(e.by_ref().read(&mut [0; 1024]).unwrap(), 0);
    }

    #[test]
    fn repeat_repeats() {
        let mut r = repeat(4);
        let mut b = [0; 1024];
        assert_eq!(r.read(&mut b).unwrap(), 1024);
        assert!(b.iter().all(|b| *b == 4));
    }

    #[test]
    fn take_some_bytes() {
        assert_eq!(repeat(4).take(100).bytes().count(), 100);
        assert_eq!(repeat(4).take(100).bytes().next().unwrap().unwrap(), 4);
        assert_eq!(repeat(1).take(10).chain(repeat(2).take(10)).bytes().count(), 20);
    }
}
<|endoftext|>


<commit_before>extern crate toml;

use std::{env, process};
use std::io::prelude::*;
use std::io::{BufReader, ErrorKind};
use std::collections::HashMap;
use std::path::PathBuf;
use std::fs::File;

static OVERRIDES_PATH : &'static str = ".multirust/overrides";
static SETTINGS_PATH : &'static str = ".multirust/settings.toml";

fn with_date<'a>(short: &'a str, toolchain: &'a str) -> Option<&'a str> {
    let date_start = short.len() + 1;
    let date_end   = short.len() + 3 + 4 + 2 + 2;
    let char_range = toolchain.chars()
        .skip(date_start)
        .take(4)
        .all(char::is_numeric);

    if toolchain.len() > date_start && char_range {
        Some(&toolchain[0..date_end])
    } else {
        None
    }
}

fn clean_toolchain_name(toolchain: &str) -> &str {
    static SHORTNAMES : &'static [&'static str] = &["stable", "nightly", "beta"];

    for short in SHORTNAMES {
        if toolchain.starts_with(short) {
            return match with_date(short, toolchain) {
                Some(s) => s,
                None => short
            }
        }
    }

    toolchain
}

fn plain_overrides_file(f: File) {
    let overrides = BufReader::new(f);

    let mut overrides_map = HashMap::<PathBuf, String>::new();

    for line in overrides.lines() {
        let line = line.expect("No valid line found");
        let mut s = line.split(';');
        let path = s.next().expect("No path in line");
        let toolchain = s.next().expect("No toolchain in line");

        let path = PathBuf::from(path);

        overrides_map.insert(path, toolchain.into());
    }

    let cwd = env::current_dir().expect("No valid working directory");

    match overrides_map.get(&cwd) {
        Some(toolchain) => println!("{}", clean_toolchain_name(toolchain)),
        None => println!("default"),
    }
}

fn settings_toml(mut settings: File) {
    let mut content = String::new();
    settings.read_to_string(&mut content).expect("Can't read settings file");

    let toml = match toml::Parser::new(&content).parse() {
        Some(table) => table,
        None => {
            println!("default");
            process::exit(0);
        }
    };

    let overrides = match toml.get("overrides") {
        Some(overrides) => overrides,
        None => {
            println!("default");
            process::exit(0);
        }
    };

    let overrides = match overrides.as_table() {
        Some(overrides) => overrides,
        None => {
            println!("default");
            process::exit(0);
        }
    };

    let cwd = env::current_dir().expect("No valid working directory");
    let cwd = format!("{}", cwd.display());

    match overrides.get(&cwd) {
        Some(toolchain) => {
            let toolchain = toolchain.as_str().expect("Toolchain should be a string, it wasn't.");
            println!("{}", clean_toolchain_name(toolchain))
        },
        None => println!("default"),
    }
}

fn main() {
    let home = env::home_dir().expect("Impossible to get your home dir!");

    let mut overrides_path = home.clone();
    overrides_path.push(OVERRIDES_PATH);

    let mut settings_path = home.clone();
    settings_path.push(SETTINGS_PATH);

    match File::open(&overrides_path) {
        Ok(f) => {
            plain_overrides_file(f);
            process::exit(0);
        },
        Err(ref e) if e.kind() == ErrorKind::NotFound => { /* ignored */ },
        Err(_) => {
            println!("default");
            process::exit(0);
        }
    }

    if let Ok(f) = File::open(&settings_path) {
        settings_toml(f);
        process::exit(0);
    }

    println!("default");
}

#[cfg(test)]
mod test {
    use super::clean_toolchain_name;

    #[test]
    fn simple_name() {
        assert_eq!("nightly", clean_toolchain_name("nightly-x86_64-unknown-linux-gnu"));
        assert_eq!("nightly", clean_toolchain_name("nightly"));
    }

    #[test]
    fn name_with_date() {
        assert_eq!("nightly-2016-06-05", clean_toolchain_name("nightly-2016-06-05-x86_64-unknown-linux-gnu"));
    }
}
<commit_msg>feat: Handle searching path upwards<commit_after>extern crate toml;

use std::{env, process};
use std::io::prelude::*;
use std::io::{BufReader, ErrorKind};
use std::collections::BTreeMap;
use std::fs::File;

static OVERRIDES_PATH : &'static str = ".multirust/overrides";
static SETTINGS_PATH : &'static str = ".multirust/settings.toml";

enum OverridesDatabase {
    Plain(BTreeMap<String, String>),
    Toml(BTreeMap<String, toml::Value>),
}

impl OverridesDatabase {
    pub fn get(&self, key: &str) -> Option<&str> {
        use OverridesDatabase::*;

        match *self {
            Plain(ref db) => db.get(key).map(|s| &s[..]),
            Toml(ref db) => {
                db.get(key).map(|v| v.as_str().expect("Expected value is not a string."))
            }
        }
    }
}

fn with_date<'a>(short: &'a str, toolchain: &'a str) -> Option<&'a str> {
    let date_start = short.len() + 1;
    let date_end   = short.len() + 3 + 4 + 2 + 2;
    let char_range = toolchain.chars()
        .skip(date_start)
        .take(4)
        .all(char::is_numeric);

    if toolchain.len() > date_start && char_range {
        Some(&toolchain[0..date_end])
    } else {
        None
    }
}

fn clean_toolchain_name(toolchain: &str) -> &str {
    static SHORTNAMES : &'static [&'static str] = &["stable", "nightly", "beta"];

    for short in SHORTNAMES {
        if toolchain.starts_with(short) {
            return match with_date(short, toolchain) {
                Some(s) => s,
                None => short
            }
        }
    }

    toolchain
}

fn plain_overrides_file(f: File) {
    let overrides = BufReader::new(f);

    let mut overrides_map = BTreeMap::new();

    for line in overrides.lines() {
        let line = line.expect("No valid line found");
        let mut s = line.split(';');
        let path = s.next().expect("No path in line");
        let toolchain = s.next().expect("No toolchain in line");

        overrides_map.insert(path.into(), toolchain.into());
    }

    let database = OverridesDatabase::Plain(overrides_map);
    toolchain(database);
}

fn settings_toml(mut settings: File) {
    let mut content = String::new();
    settings.read_to_string(&mut content).expect("Can't read settings file");

    let toml = match toml::Parser::new(&content).parse() {
        Some(table) => table,
        None => {
            println!("default");
            process::exit(0);
        }
    };

    let overrides = match toml.get("overrides") {
        Some(overrides) => overrides,
        None => {
            println!("default");
            process::exit(0);
        }
    };

    let overrides = match overrides.as_table() {
        Some(overrides) => overrides,
        None => {
            println!("default");
            process::exit(0);
        }
    };

    let database = OverridesDatabase::Toml(overrides.clone());
    toolchain(database);
}

fn toolchain(database: OverridesDatabase) {
    let mut cwd = env::current_dir().expect("No valid working directory");

    loop {
        let path = format!("{}", cwd.display());

        if let Some(toolchain) =  database.get(&path) {
            println!("{}", clean_toolchain_name(toolchain));
            return;
        }

        if !cwd.pop() {
            break;
        }
    }
    println!("default");
}

fn main() {
    let home = env::home_dir().expect("Impossible to get your home dir!");

    let mut overrides_path = home.clone();
    overrides_path.push(OVERRIDES_PATH);

    let mut settings_path = home.clone();
    settings_path.push(SETTINGS_PATH);

    match File::open(&overrides_path) {
        Ok(f) => {
            plain_overrides_file(f);
            process::exit(0);
        },
        Err(ref e) if e.kind() == ErrorKind::NotFound => { /* ignored */ },
        Err(_) => {
            println!("default");
            process::exit(0);
        }
    }

    if let Ok(f) = File::open(&settings_path) {
        settings_toml(f);
        process::exit(0);
    }

    println!("default");
}

#[cfg(test)]
mod test {
    use super::clean_toolchain_name;

    #[test]
    fn simple_name() {
        assert_eq!("nightly", clean_toolchain_name("nightly-x86_64-unknown-linux-gnu"));
        assert_eq!("nightly", clean_toolchain_name("nightly"));
    }

    #[test]
    fn name_with_date() {
        assert_eq!("nightly-2016-06-05", clean_toolchain_name("nightly-2016-06-05-x86_64-unknown-linux-gnu"));
    }
}
<|endoftext|>


<commit_before>#![feature(plugin)]
#![plugin(rocket_codegen)]

extern crate rocket_contrib;
extern crate rocket;
#[macro_use] extern crate serde_derive;

#[cfg(test)] mod tests;

use rocket::Request;
use rocket::response::Redirect;
use rocket_contrib::Template;

#[derive(Serialize)]
struct TemplateContext {
    name: String,
    items: Vec<String>
}

#[get("/")]
fn index() -> Redirect {
    Redirect::to("/hello/Unknown")
}

#[get("/hello/<name>")]
fn get(name: String) -> Template {
    let context = TemplateContext {
        name: name,
        items: vec!["One", "Two", "Three"].iter().map(|s| s.to_string()).collect()
    };

    Template::render("index", &context)
}

#[error(404)]
fn not_found(req: &Request) -> Template {
    let mut map = std::collections::HashMap::new();
    map.insert("path", req.uri().as_str());
    Template::render("error/404", &map)
}

fn rocket() -> rocket::Rocket {
    rocket::ignite()
        .mount("/", routes![index, get])
        .attach(Template::fairing())
        .catch(errors![not_found])
}

fn main() {
    rocket().launch();
}<commit_msg>Fix routing issues<commit_after>#![feature(plugin)]
#![plugin(rocket_codegen)]

extern crate rocket_contrib;
extern crate rocket;
#[macro_use] extern crate serde_derive;

#[cfg(test)] mod tests;

use rocket::Request;
use rocket::response::Redirect;
use rocket_contrib::Template;

#[derive(Serialize)]
struct TemplateContext {
    name: String,
    items: Vec<String>
}

#[get("/")]
fn index() -> Redirect {
    Redirect::to("/hello/Unknown")
}

#[get("/hello/<name>")]
fn hello(name: String) -> Template {
    let context = TemplateContext {
        name: name,
        items: vec!["One", "Two", "Three"].iter().map(|s| s.to_string()).collect()
    };

    Template::render("index", &context)
}

#[get("/map")]
fn map() -> Template {
    let context = TemplateContext {
        name: String::from("Test"),
        items: vec!["One", "Two", "Three"].iter().map(|s| s.to_string()).collect()
    };

    Template::render("map", &context)
}

#[error(404)]
fn not_found(req: &Request) -> Template {
    let mut map = std::collections::HashMap::new();
    map.insert("path", req.uri().as_str());
    Template::render("error/404", &map)
}

fn rocket() -> rocket::Rocket {
    rocket::ignite()
        .mount("/", routes![index, hello, map])
        .attach(Template::fairing())
        .catch(errors![not_found])
}

fn main() {
    rocket().launch();
}<|endoftext|>