<commit_before>use crate::{
    module_map::{ModuleDescriptorQuery, ModuleTreeQuery, ModulesDatabase},
    symbol_index::SymbolIndex,
    FileId, FileResolverImp,
};
use ra_editor::LineIndex;
use ra_syntax::File;
use rustc_hash::FxHashSet;
use salsa;

use std::{
    fmt,
    hash::{Hash, Hasher},
    sync::Arc,
};

#[derive(Default)]
pub(crate) struct RootDatabase {
    runtime: salsa::runtime::Runtime<RootDatabase>,
}

impl fmt::Debug for RootDatabase {
    fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
        fmt.write_str("RootDatabase { ... }")
    }
}

impl salsa::Database for RootDatabase {
    fn salsa_runtime(&self) -> &salsa::runtime::Runtime<RootDatabase> {
        &self.runtime
    }
}

impl salsa::ParallelDatabase for RootDatabase {
    fn fork(&self) -> Self {
        RootDatabase {
            runtime: self.runtime.fork(),
        }
    }
}

impl Clone for RootDatabase {
    fn clone(&self) -> RootDatabase {
        salsa::ParallelDatabase::fork(self)
    }
}

salsa::database_storage! {
    pub(crate) struct RootDatabaseStorage for RootDatabase {
        impl FilesDatabase {
            fn file_text() for FileTextQuery;
            fn file_set() for FileSetQuery;
        }
        impl SyntaxDatabase {
            fn file_syntax() for FileSyntaxQuery;
            fn file_lines() for FileLinesQuery;
            fn file_symbols() for FileSymbolsQuery;
        }
        impl ModulesDatabase {
            fn module_tree() for ModuleTreeQuery;
            fn module_descriptor() for ModuleDescriptorQuery;
        }
    }
}

salsa::query_group! {
    pub(crate) trait FilesDatabase: salsa::Database {
        fn file_text(file_id: FileId) -> Arc<String> {
            type FileTextQuery;
            storage input;
        }
        fn file_set(key: ()) -> Arc<FileSet> {
            type FileSetQuery;
            storage input;
        }
    }
}

#[derive(Default, Debug, PartialEq, Eq)]
pub(crate) struct FileSet {
    pub(crate) files: FxHashSet<FileId>,
    pub(crate) resolver: FileResolverImp,
}

impl Hash for FileSet {
    fn hash<H: Hasher>(&self, hasher: &mut H) {
        let mut files = self.files.iter().cloned().collect::<Vec<_>>();
        files.sort();
        files.hash(hasher);
    }
}

salsa::query_group! {
    pub(crate) trait SyntaxDatabase: FilesDatabase {
        fn file_syntax(file_id: FileId) -> File {
            type FileSyntaxQuery;
        }
        fn file_lines(file_id: FileId) -> Arc<LineIndex> {
            type FileLinesQuery;
        }
        fn file_symbols(file_id: FileId) -> Arc<SymbolIndex> {
            type FileSymbolsQuery;
        }
    }
}

fn file_syntax(db: &impl SyntaxDatabase, file_id: FileId) -> File {
    let text = db.file_text(file_id);
    File::parse(&*text)
}
fn file_lines(db: &impl SyntaxDatabase, file_id: FileId) -> Arc<LineIndex> {
    let text = db.file_text(file_id);
    Arc::new(LineIndex::new(&*text))
}
fn file_symbols(db: &impl SyntaxDatabase, file_id: FileId) -> Arc<SymbolIndex> {
    let syntax = db.file_syntax(file_id);
    Arc::new(SymbolIndex::for_file(file_id, syntax))
}
<commit_msg>Silence clippy::derive_hash_xor_eq<commit_after>use crate::{
    module_map::{ModuleDescriptorQuery, ModuleTreeQuery, ModulesDatabase},
    symbol_index::SymbolIndex,
    FileId, FileResolverImp,
};
use ra_editor::LineIndex;
use ra_syntax::File;
use rustc_hash::FxHashSet;
use salsa;

use std::{
    fmt,
    hash::{Hash, Hasher},
    sync::Arc,
};

#[derive(Default)]
pub(crate) struct RootDatabase {
    runtime: salsa::runtime::Runtime<RootDatabase>,
}

impl fmt::Debug for RootDatabase {
    fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
        fmt.write_str("RootDatabase { ... }")
    }
}

impl salsa::Database for RootDatabase {
    fn salsa_runtime(&self) -> &salsa::runtime::Runtime<RootDatabase> {
        &self.runtime
    }
}

impl salsa::ParallelDatabase for RootDatabase {
    fn fork(&self) -> Self {
        RootDatabase {
            runtime: self.runtime.fork(),
        }
    }
}

impl Clone for RootDatabase {
    fn clone(&self) -> RootDatabase {
        salsa::ParallelDatabase::fork(self)
    }
}

salsa::database_storage! {
    pub(crate) struct RootDatabaseStorage for RootDatabase {
        impl FilesDatabase {
            fn file_text() for FileTextQuery;
            fn file_set() for FileSetQuery;
        }
        impl SyntaxDatabase {
            fn file_syntax() for FileSyntaxQuery;
            fn file_lines() for FileLinesQuery;
            fn file_symbols() for FileSymbolsQuery;
        }
        impl ModulesDatabase {
            fn module_tree() for ModuleTreeQuery;
            fn module_descriptor() for ModuleDescriptorQuery;
        }
    }
}

salsa::query_group! {
    pub(crate) trait FilesDatabase: salsa::Database {
        fn file_text(file_id: FileId) -> Arc<String> {
            type FileTextQuery;
            storage input;
        }
        fn file_set(key: ()) -> Arc<FileSet> {
            type FileSetQuery;
            storage input;
        }
    }
}

#[derive(Default, Debug, Eq)]
pub(crate) struct FileSet {
    pub(crate) files: FxHashSet<FileId>,
    pub(crate) resolver: FileResolverImp,
}

impl PartialEq for FileSet {
    fn eq(&self, other: &FileSet) -> bool {
        self.files == other.files && self.resolver == other.resolver
    }
}

impl Hash for FileSet {
    fn hash<H: Hasher>(&self, hasher: &mut H) {
        let mut files = self.files.iter().cloned().collect::<Vec<_>>();
        files.sort();
        files.hash(hasher);
    }
}

salsa::query_group! {
    pub(crate) trait SyntaxDatabase: FilesDatabase {
        fn file_syntax(file_id: FileId) -> File {
            type FileSyntaxQuery;
        }
        fn file_lines(file_id: FileId) -> Arc<LineIndex> {
            type FileLinesQuery;
        }
        fn file_symbols(file_id: FileId) -> Arc<SymbolIndex> {
            type FileSymbolsQuery;
        }
    }
}

fn file_syntax(db: &impl SyntaxDatabase, file_id: FileId) -> File {
    let text = db.file_text(file_id);
    File::parse(&*text)
}
fn file_lines(db: &impl SyntaxDatabase, file_id: FileId) -> Arc<LineIndex> {
    let text = db.file_text(file_id);
    Arc::new(LineIndex::new(&*text))
}
fn file_symbols(db: &impl SyntaxDatabase, file_id: FileId) -> Arc<SymbolIndex> {
    let syntax = db.file_syntax(file_id);
    Arc::new(SymbolIndex::for_file(file_id, syntax))
}
<|endoftext|>


<commit_before>// Copyright 2019 Benjamin Fry <benjaminfry@me.com>
//
// Licensed under the Apache License, Version 2.0, <LICENSE-APACHE or
// http://apache.org/licenses/LICENSE-2.0> or the MIT license <LICENSE-MIT or
// http://opensource.org/licenses/MIT>, at your option. This file may not be
// copied, modified, or distributed except according to those terms.

//! OPENPGPKEY records for OpenPGP public keys

use error::*;
use rr::rdata::OPENPGPKEY;

/// Parse the RData from a set of tokens.
///
/// [RFC 7929](https://tools.ietf.org/html/rfc7929#section-2.3)
///
/// ```text
/// 2.3.  The OPENPGPKEY RDATA Presentation Format
///
///    The RDATA Presentation Format, as visible in master files [RFC1035],
///    consists of a single OpenPGP Transferable Public Key as defined in
///    Section 11.1 of [RFC4880] encoded in base64 as defined in Section 4
///    of [RFC4648].
/// ```
pub fn parse<'i, I: Iterator<Item = &'i str>>(mut tokens: I) -> ParseResult<OPENPGPKEY> {
    let encoded_public_key = tokens
        .next()
        .ok_or_else(|| ParseErrorKind::Message("OPENPGPKEY public key field is missing"))?;
    let public_key = ::data_encoding::BASE64.decode(encoded_public_key.as_bytes())?;
    Some(OPENPGPKEY::new(public_key))
        .filter(|_| tokens.next().is_none())
        .ok_or_else(|| ParseErrorKind::Message("too many fields for OPENPGPKEY").into())
}

#[test]
fn test_parsing() {
    assert!(parse(::std::iter::empty()).is_err());
    assert!(parse(vec!["äöüäööüä"].into_iter()).is_err());
    assert!(parse(vec!["ZmFpbGVk", "äöüäöüö"].into_iter()).is_err());

    assert!(parse(vec!["dHJ1c3RfZG5zIGlzIGF3ZXNvbWU="].into_iter())
        .map(|rd| rd == OPENPGPKEY::new("trust_dns is awesome".as_bytes().to_vec()))
        .unwrap_or(false));
    assert!(parse(vec!["c2VsZi1wcmFpc2Ugc3Rpbmtz"].into_iter())
        .map(|rd| rd == OPENPGPKEY::new("self-praise stinks".as_bytes().to_vec()))
        .unwrap_or(false));
}
<commit_msg>fix clippy<commit_after>// Copyright 2019 Benjamin Fry <benjaminfry@me.com>
//
// Licensed under the Apache License, Version 2.0, <LICENSE-APACHE or
// http://apache.org/licenses/LICENSE-2.0> or the MIT license <LICENSE-MIT or
// http://opensource.org/licenses/MIT>, at your option. This file may not be
// copied, modified, or distributed except according to those terms.

//! OPENPGPKEY records for OpenPGP public keys

use error::*;
use rr::rdata::OPENPGPKEY;

/// Parse the RData from a set of tokens.
///
/// [RFC 7929](https://tools.ietf.org/html/rfc7929#section-2.3)
///
/// ```text
/// 2.3.  The OPENPGPKEY RDATA Presentation Format
///
///    The RDATA Presentation Format, as visible in master files [RFC1035],
///    consists of a single OpenPGP Transferable Public Key as defined in
///    Section 11.1 of [RFC4880] encoded in base64 as defined in Section 4
///    of [RFC4648].
/// ```
pub fn parse<'i, I: Iterator<Item = &'i str>>(mut tokens: I) -> ParseResult<OPENPGPKEY> {
    let encoded_public_key = tokens
        .next()
        .ok_or_else(|| ParseErrorKind::Message("OPENPGPKEY public key field is missing"))?;
    let public_key = ::data_encoding::BASE64.decode(encoded_public_key.as_bytes())?;
    Some(OPENPGPKEY::new(public_key))
        .filter(|_| tokens.next().is_none())
        .ok_or_else(|| ParseErrorKind::Message("too many fields for OPENPGPKEY").into())
}

#[test]
fn test_parsing() {
    assert!(parse(::std::iter::empty()).is_err());
    assert!(parse(vec!["äöüäööüä"].into_iter()).is_err());
    assert!(parse(vec!["ZmFpbGVk", "äöüäöüö"].into_iter()).is_err());

    assert!(parse(vec!["dHJ1c3RfZG5zIGlzIGF3ZXNvbWU="].into_iter())
        .map(|rd| rd == OPENPGPKEY::new(b"trust_dns is awesome".to_vec()))
        .unwrap_or(false));
    assert!(parse(vec!["c2VsZi1wcmFpc2Ugc3Rpbmtz"].into_iter())
        .map(|rd| rd == OPENPGPKEY::new(b"self-praise stinks".to_vec()))
        .unwrap_or(false));
}
<|endoftext|>


<commit_before>fn main() {
    println!("Day 3");

    first_star(1);
    first_star(9);
    first_star(10);
    first_star(12);
    first_star(23);
    first_star(1024);
    first_star(289326);

    second_star(1);
    second_star(9);
    second_star(10);
    second_star(12);
    second_star(23);
    second_star(1024);
    second_star(289326);
}

fn first_star(input: i32) {
    println!("First star");
    println!("input={}", input);

    let distance = ((input as f64 - 1.).sqrt() as i32 + 1) / 2;
    println!("distance={}", distance);

    let delta = input - (distance * 2 - 1).pow(2);
    println!("delta={}", delta);

    let step = (delta % std::cmp::max(distance * 2, 1) - distance) % std::cmp::max(distance * 2, 1);
    println!("step={}", step);

    let manhattan = distance + step.abs();
    println!("manhattan={}", manhattan);

    println!();
}
<commit_msg>Day 3, Star 2<commit_after>fn main() {
    println!("Day 3");

    first_star(1);
    first_star(9);
    first_star(10);
    first_star(12);
    first_star(23);
    first_star(1024);
    first_star(289326);

    second_star(1);
    second_star(2);
    second_star(9);
    second_star(10);
    second_star(25);
    second_star(1024);
    second_star(289326);
}

fn first_star(input: i32) {
    println!("First star");
    println!("input={}", input);

    let distance = ((input as f32 - 1.).sqrt() as i32 + 1) / 2;
    println!("distance={}", distance);

    let delta = input - (distance * 2 - 1).pow(2);
    println!("delta={}", delta);

    let step = (delta % std::cmp::max(distance * 2, 1) - distance) % std::cmp::max(distance * 2, 1);
    println!("step={}", step);

    let manhattan = distance + step.abs();
    println!("manhattan={}", manhattan);

    println!();
}

fn second_star(input: i32) {
    println!("Second star");
    println!("input={}", input);

    let size = ((input as f32).sqrt() as i32 / 2 * 2 + 5) as usize;
    let mut sq = vec![vec![0; size]; size];

    let mut i = size / 2;
    let mut j = i;
    let mut step = 2;
    let mut w = 1;
    sq[i][j] = w;

    'search:
    loop {
        i += 1;
        j += 1;
        for _ in 0..step {
            j -= 1;
            w = fill(&mut sq, i, j);
            if w > input {
                break 'search;
            }
        }

        for _ in 0..step {
            i -= 1;
            w = fill(&mut sq, i, j);
            if w > input {
                break 'search;
            }
        }

        for _ in 0..step {
            j += 1;
            w = fill(&mut sq, i, j);
            if w > input {
                break 'search;
            }
        }

        for _ in 0..step {
            i += 1;
            w = fill(&mut sq, i, j);
            if w > input {
                break 'search;
            }
        }

        step += 2;
    }

    println!("written={}", w);

    println!();
}

fn fill(sq: &mut Vec<Vec<i32>>, i: usize, j: usize) -> i32 {
    sq[i][j] = sq[i-1][j-1] + sq[i][j-1] + sq[i+1][j-1]
             + sq[i-1][j]                + sq[i+1][j]
             + sq[i-1][j+1] + sq[i][j+1] + sq[i+1][j+1];
    return sq[i][j];
}
<|endoftext|>


<commit_before>use crate::msg::diagnostic_msgs::{DiagnosticStatus, KeyValue};
use crate::Level;

#[derive(Clone)]
pub struct Status {
    pub level: Level,
    pub name: String,
    pub message: String,
    pub hardware_id: String,
    pub values: Vec<KeyValue>,
}

impl Default for Status {
    fn default() -> Self {
        Self {
            level: Level::Error,
            name: "".to_string(),
            message: "".to_string(),
            hardware_id: "".to_string(),
            values: vec![],
        }
    }
}

impl Status {
    pub fn set_summary(&mut self, level: Level, message: &str) {
        self.level = level;
        self.message = message.into();
    }

    #[inline]
    pub fn copy_summary(&mut self, other: &Status) {
        self.set_summary(other.level, &other.message)
    }

    #[inline]
    pub fn clear_summary(&mut self) {
        self.set_summary(Level::Ok, "")
    }

    fn merge_messages(&mut self, message: &str) {
        if message.is_empty() {
            return;
        }

        self.message = if self.message.is_empty() {
            message.into()
        } else {
            format!("{}; {}", self.message, message)
        };
    }

    pub fn merge_summary(&mut self, level: Level, message: &str) {
        if level as i8 > self.level as i8 {
            self.level = level;
        }
        match (self.level, level) {
            (Level::Ok, Level::Ok) => self.merge_messages(message),
            (Level::Ok, _) => self.message = message.into(),
            (_, Level::Ok) => {}
            _ => self.merge_messages(message),
        }
    }

    #[inline]
    pub fn merge_summary_with(&mut self, other: &Status) {
        self.merge_summary(other.level, &other.message)
    }

    pub fn clear_values(&mut self) {
        self.values.clear();
    }

    pub fn add(&mut self, key: String, value: impl std::string::ToString) {
        let value = value.to_string();
        self.values.push(KeyValue { key, value });
    }
}

impl Into<DiagnosticStatus> for Status {
    fn into(self) -> DiagnosticStatus {
        DiagnosticStatus {
            level: self.level as i8,
            name: self.name,
            message: self.message,
            hardware_id: self.hardware_id,
            values: self.values,
        }
    }
}
<commit_msg>Fix task composition<commit_after>use crate::msg::diagnostic_msgs::{DiagnosticStatus, KeyValue};
use crate::Level;

#[derive(Clone)]
pub struct Status {
    pub level: Level,
    pub name: String,
    pub message: String,
    pub hardware_id: String,
    pub values: Vec<KeyValue>,
}

impl Default for Status {
    fn default() -> Self {
        Self {
            level: Level::Ok,
            name: "".to_string(),
            message: "".to_string(),
            hardware_id: "".to_string(),
            values: vec![],
        }
    }
}

impl Status {
    pub fn set_summary(&mut self, level: Level, message: &str) {
        self.level = level;
        self.message = message.into();
    }

    #[inline]
    pub fn copy_summary(&mut self, other: &Status) {
        self.set_summary(other.level, &other.message)
    }

    #[inline]
    pub fn clear_summary(&mut self) {
        self.set_summary(Level::Ok, "")
    }

    fn merge_messages(&mut self, message: &str) {
        if message.is_empty() {
            return;
        }

        self.message = if self.message.is_empty() {
            message.into()
        } else {
            format!("{}; {}", self.message, message)
        };
    }

    pub fn merge_summary(&mut self, level: Level, message: &str) {
        match (self.level, level) {
            (Level::Ok, Level::Ok) => self.merge_messages(message),
            (Level::Ok, _) => self.message = message.into(),
            (_, Level::Ok) => {}
            _ => self.merge_messages(message),
        }
        if level as i8 > self.level as i8 {
            self.level = level;
        }
    }

    #[inline]
    pub fn merge_summary_with(&mut self, other: &Status) {
        self.merge_summary(other.level, &other.message)
    }

    pub fn clear_values(&mut self) {
        self.values.clear();
    }

    pub fn add(&mut self, key: String, value: impl std::string::ToString) {
        let value = value.to_string();
        self.values.push(KeyValue { key, value });
    }
}

impl Into<DiagnosticStatus> for Status {
    fn into(self) -> DiagnosticStatus {
        DiagnosticStatus {
            level: self.level as i8,
            name: self.name,
            message: self.message,
            hardware_id: self.hardware_id,
            values: self.values,
        }
    }
}
<|endoftext|>


<commit_before>use crate::utils::{snippet_with_applicability, span_lint, span_lint_and_then};
use if_chain::if_chain;
use rustc_ast::ast;
use rustc_ast::visit as ast_visit;
use rustc_ast::visit::Visitor as AstVisitor;
use rustc_errors::Applicability;
use rustc_hir as hir;
use rustc_hir::intravisit as hir_visit;
use rustc_hir::intravisit::Visitor as HirVisitor;
use rustc_lint::{EarlyContext, EarlyLintPass, LateContext, LateLintPass, LintContext};
use rustc_middle::hir::map::Map;
use rustc_middle::lint::in_external_macro;
use rustc_session::{declare_lint_pass, declare_tool_lint};

declare_clippy_lint! {
    /// **What it does:** Detects closures called in the same expression where they
    /// are defined.
    ///
    /// **Why is this bad?** It is unnecessarily adding to the expression's
    /// complexity.
    ///
    /// **Known problems:** None.
    ///
    /// **Example:**
    /// ```rust,ignore
    /// // Bad
    /// let a = (|| 42)()
    ///
    /// // Good
    /// let a = 42
    /// ```
    pub REDUNDANT_CLOSURE_CALL,
    complexity,
    "throwaway closures called in the expression they are defined"
}

declare_lint_pass!(RedundantClosureCall => [REDUNDANT_CLOSURE_CALL]);

// Used to find `return` statements or equivalents e.g., `?`
struct ReturnVisitor {
    found_return: bool,
}

impl ReturnVisitor {
    #[must_use]
    fn new() -> Self {
        Self { found_return: false }
    }
}

impl<'ast> ast_visit::Visitor<'ast> for ReturnVisitor {
    fn visit_expr(&mut self, ex: &'ast ast::Expr) {
        if let ast::ExprKind::Ret(_) = ex.kind {
            self.found_return = true;
        } else if let ast::ExprKind::Try(_) = ex.kind {
            self.found_return = true;
        }

        ast_visit::walk_expr(self, ex)
    }
}

impl EarlyLintPass for RedundantClosureCall {
    fn check_expr(&mut self, cx: &EarlyContext<'_>, expr: &ast::Expr) {
        if in_external_macro(cx.sess(), expr.span) {
            return;
        }
        if_chain! {
            if let ast::ExprKind::Call(ref paren, _) = expr.kind;
            if let ast::ExprKind::Paren(ref closure) = paren.kind;
            if let ast::ExprKind::Closure(_, _, _, ref decl, ref block, _) = closure.kind;
            then {
                let mut visitor = ReturnVisitor::new();
                visitor.visit_expr(block);
                if !visitor.found_return {
                    span_lint_and_then(
                        cx,
                        REDUNDANT_CLOSURE_CALL,
                        expr.span,
                        "try not to call a closure in the expression where it is declared",
                        |diag| {
                            if decl.inputs.is_empty() {
                                let mut app = Applicability::MachineApplicable;
                                let hint =
                                    snippet_with_applicability(cx, block.span, "..", &mut app).into_owned();
                                diag.span_suggestion(expr.span, "try doing something like", hint, app);
                            }
                        },
                    );
                }
            }
        }
    }
}

impl<'tcx> LateLintPass<'tcx> for RedundantClosureCall {
    fn check_block(&mut self, cx: &LateContext<'tcx>, block: &'tcx hir::Block<'_>) {
        fn count_closure_usage<'a, 'tcx>(
            cx: &'a LateContext<'tcx>,
            block: &'tcx hir::Block<'_>,
            path: &'tcx hir::Path<'tcx>,
        ) -> usize {
            struct ClosureUsageCount<'a, 'tcx> {
                cx: &'a LateContext<'tcx>,
                path: &'tcx hir::Path<'tcx>,
                count: usize,
            };
            impl<'a, 'tcx> hir_visit::Visitor<'tcx> for ClosureUsageCount<'a, 'tcx> {
                type Map = Map<'tcx>;

                fn visit_expr(&mut self, expr: &'tcx hir::Expr<'tcx>) {
                    if_chain! {
                        if let hir::ExprKind::Call(ref closure, _) = expr.kind;
                        if let hir::ExprKind::Path(hir::QPath::Resolved(_, ref path)) = closure.kind;
                        if self.path.segments[0].ident == path.segments[0].ident
                            && self.path.res == path.res;
                        then {
                            self.count += 1;
                        }
                    }
                    hir_visit::walk_expr(self, expr);
                }

                fn nested_visit_map(&mut self) -> hir_visit::NestedVisitorMap<Self::Map> {
                    hir_visit::NestedVisitorMap::OnlyBodies(self.cx.tcx.hir())
                }
            };
            let mut closure_usage_count = ClosureUsageCount { cx, path, count: 0 };
            closure_usage_count.visit_block(block);
            closure_usage_count.count
        }

        for w in block.stmts.windows(2) {
            if_chain! {
                if let hir::StmtKind::Local(ref local) = w[0].kind;
                if let Option::Some(ref t) = local.init;
                if let hir::ExprKind::Closure(..) = t.kind;
                if let hir::PatKind::Binding(_, _, ident, _) = local.pat.kind;
                if let hir::StmtKind::Semi(ref second) = w[1].kind;
                if let hir::ExprKind::Assign(_, ref call, _) = second.kind;
                if let hir::ExprKind::Call(ref closure, _) = call.kind;
                if let hir::ExprKind::Path(hir::QPath::Resolved(_, ref path)) = closure.kind;
                if ident == path.segments[0].ident;
                if count_closure_usage(cx, block, path) == 1;
                then {
                    span_lint(
                        cx,
                        REDUNDANT_CLOSURE_CALL,
                        second.span,
                        "closure called just once immediately after it was declared",
                    );
                }
            }
        }
    }
}
<commit_msg>Fix weird dogfood error<commit_after>use crate::utils::{snippet_with_applicability, span_lint, span_lint_and_then};
use if_chain::if_chain;
use rustc_ast::ast;
use rustc_ast::visit as ast_visit;
use rustc_ast::visit::Visitor as AstVisitor;
use rustc_errors::Applicability;
use rustc_hir as hir;
use rustc_hir::intravisit as hir_visit;
use rustc_hir::intravisit::Visitor as HirVisitor;
use rustc_lint::{EarlyContext, EarlyLintPass, LateContext, LateLintPass, LintContext};
use rustc_middle::hir::map::Map;
use rustc_middle::lint::in_external_macro;
use rustc_session::{declare_lint_pass, declare_tool_lint};

declare_clippy_lint! {
    /// **What it does:** Detects closures called in the same expression where they
    /// are defined.
    ///
    /// **Why is this bad?** It is unnecessarily adding to the expression's
    /// complexity.
    ///
    /// **Known problems:** None.
    ///
    /// **Example:**
    /// ```rust,ignore
    /// // Bad
    /// let a = (|| 42)()
    ///
    /// // Good
    /// let a = 42
    /// ```
    pub REDUNDANT_CLOSURE_CALL,
    complexity,
    "throwaway closures called in the expression they are defined"
}

declare_lint_pass!(RedundantClosureCall => [REDUNDANT_CLOSURE_CALL]);

// Used to find `return` statements or equivalents e.g., `?`
struct ReturnVisitor {
    found_return: bool,
}

impl ReturnVisitor {
    #[must_use]
    fn new() -> Self {
        Self { found_return: false }
    }
}

impl<'ast> ast_visit::Visitor<'ast> for ReturnVisitor {
    fn visit_expr(&mut self, ex: &'ast ast::Expr) {
        if let ast::ExprKind::Ret(_) = ex.kind {
            self.found_return = true;
        } else if let ast::ExprKind::Try(_) = ex.kind {
            self.found_return = true;
        }

        ast_visit::walk_expr(self, ex)
    }
}

impl EarlyLintPass for RedundantClosureCall {
    fn check_expr(&mut self, cx: &EarlyContext<'_>, expr: &ast::Expr) {
        if in_external_macro(cx.sess(), expr.span) {
            return;
        }
        if_chain! {
            if let ast::ExprKind::Call(ref paren, _) = expr.kind;
            if let ast::ExprKind::Paren(ref closure) = paren.kind;
            if let ast::ExprKind::Closure(_, _, _, ref decl, ref block, _) = closure.kind;
            then {
                let mut visitor = ReturnVisitor::new();
                visitor.visit_expr(block);
                if !visitor.found_return {
                    span_lint_and_then(
                        cx,
                        REDUNDANT_CLOSURE_CALL,
                        expr.span,
                        "try not to call a closure in the expression where it is declared",
                        |diag| {
                            if decl.inputs.is_empty() {
                                let mut app = Applicability::MachineApplicable;
                                let hint =
                                    snippet_with_applicability(cx, block.span, "..", &mut app).into_owned();
                                diag.span_suggestion(expr.span, "try doing something like", hint, app);
                            }
                        },
                    );
                }
            }
        }
    }
}

impl<'tcx> LateLintPass<'tcx> for RedundantClosureCall {
    fn check_block(&mut self, cx: &LateContext<'tcx>, block: &'tcx hir::Block<'_>) {
        fn count_closure_usage<'a, 'tcx>(
            cx: &'a LateContext<'tcx>,
            block: &'tcx hir::Block<'_>,
            path: &'tcx hir::Path<'tcx>,
        ) -> usize {
            struct ClosureUsageCount<'a, 'tcx> {
                cx: &'a LateContext<'tcx>,
                path: &'tcx hir::Path<'tcx>,
                count: usize,
            }
            impl<'a, 'tcx> hir_visit::Visitor<'tcx> for ClosureUsageCount<'a, 'tcx> {
                type Map = Map<'tcx>;

                fn visit_expr(&mut self, expr: &'tcx hir::Expr<'tcx>) {
                    if_chain! {
                        if let hir::ExprKind::Call(ref closure, _) = expr.kind;
                        if let hir::ExprKind::Path(hir::QPath::Resolved(_, ref path)) = closure.kind;
                        if self.path.segments[0].ident == path.segments[0].ident
                            && self.path.res == path.res;
                        then {
                            self.count += 1;
                        }
                    }
                    hir_visit::walk_expr(self, expr);
                }

                fn nested_visit_map(&mut self) -> hir_visit::NestedVisitorMap<Self::Map> {
                    hir_visit::NestedVisitorMap::OnlyBodies(self.cx.tcx.hir())
                }
            }
            let mut closure_usage_count = ClosureUsageCount { cx, path, count: 0 };
            closure_usage_count.visit_block(block);
            closure_usage_count.count
        }

        for w in block.stmts.windows(2) {
            if_chain! {
                if let hir::StmtKind::Local(ref local) = w[0].kind;
                if let Option::Some(ref t) = local.init;
                if let hir::ExprKind::Closure(..) = t.kind;
                if let hir::PatKind::Binding(_, _, ident, _) = local.pat.kind;
                if let hir::StmtKind::Semi(ref second) = w[1].kind;
                if let hir::ExprKind::Assign(_, ref call, _) = second.kind;
                if let hir::ExprKind::Call(ref closure, _) = call.kind;
                if let hir::ExprKind::Path(hir::QPath::Resolved(_, ref path)) = closure.kind;
                if ident == path.segments[0].ident;
                if count_closure_usage(cx, block, path) == 1;
                then {
                    span_lint(
                        cx,
                        REDUNDANT_CLOSURE_CALL,
                        second.span,
                        "closure called just once immediately after it was declared",
                    );
                }
            }
        }
    }
}
<|endoftext|>


<commit_before>use std::ops::RangeFrom;

use nom::{
    branch::alt,
    bytes::complete::{tag, take},
    character::complete::space1,
    combinator::{all_consuming, map, map_res, value},
    error::{Error, ErrorKind},
    multi::{many0, many1},
    sequence::{delimited, pair, tuple},
    Finish, IResult,
};

use super::lexer::{Token, Tokens};
use crate::api::{Api, Array, ParamListEntry, ParamType};
use crate::paramset::ParamSet;

pub fn parse<'input, 'api, A: Api>(
    input: Tokens<'input>,
    api: &'api A,
) -> IResult<Tokens<'input>, ()> {
    let accelerator = map_res(
        tuple((token(Token::ACCELERATOR), string_, param_list)),
        |(_, typ, params)| api.accelerator(typ, &params),
    );
    let attribute_begin = map_res(token(Token::ATTRIBUTEBEGIN), |_| api.attribute_begin());
    let attribute_end = map_res(token(Token::ATTRIBUTEEND), |_| api.attribute_end());
    let transform_begin = map_res(token(Token::TRANSFORMBEGIN), |_| api.transform_begin());
    let transform_end = map_res(token(Token::TRANSFORMEND), |_| api.transform_end());
    let object_begin = map_res(pair(token(Token::OBJECTBEGIN), string_), |(_, name)| {
        api.object_begin(name)
    });
    let object_end = map_res(token(Token::OBJECTEND), |_| api.object_end());
    let object_instance = map_res(pair(token(Token::OBJECTINSTANCE), string_), |(_, name)| {
        api.object_instance(name)
    });
    let world_begin = map_res(token(Token::WORLDBEGIN), |_| api.world_begin());
    let world_end = map_res(token(Token::WORLDEND), |_| api.world_end());
    let look_at = map_res(
        tuple((
            token(Token::LOOKAT),
            num,
            num,
            num,
            num,
            num,
            num,
            num,
            num,
            num,
        )),
        |(_, ex, ey, ez, lx, ly, lz, ux, uy, uz)| api.look_at(ex, ey, ez, lx, ly, lz, ux, uy, uz),
    );
    let coordinate_system = map_res(
        pair(token(Token::COORDINATESYSTEM), string_),
        |(_, name)| api.coordinate_system(name),
    );
    let coord_sys_transform = map_res(
        pair(token(Token::COORDSYSTRANSFORM), string_),
        |(_, name)| api.coord_sys_transform(name),
    );
    let camera = map_res(
        tuple((token(Token::CAMERA), string_, param_list)),
        |(_, typ, params)| api.camera(typ, &params),
    );
    let film = map_res(
        tuple((token(Token::FILM), string_, param_list)),
        |(_, typ, params)| api.film(typ, &params),
    );
    // TODO include
    /* let include = (token(Tokens::INCLUDE), string_()).and_then(|(_, name)| {
        info!("Parsing included file: {}", name);
        super::tokenize_file(&name)
            .and_then(|tokens| {
                parse(&tokens[..], api)
                    .map(|_| ())
                    .map_err(|e| format_err!("Failed to parse included file: {:?}", e))
            })
            .map_err(|e| Error::Other(e.into()))
    }); */
    let integrator = map_res(
        tuple((token(Token::INTEGRATOR), string_, param_list)),
        |(_, typ, params)| api.integrator(typ, &params),
    );
    let arealightsource = map_res(
        tuple((token(Token::AREALIGHTSOURCE), string_, param_list)),
        |(_, typ, params)| api.arealightsource(typ, &params),
    );
    let lightsource = map_res(
        tuple((token(Token::LIGHTSOURCE), string_, param_list)),
        |(_, typ, params)| api.lightsource(typ, &params),
    );
    let material = map_res(
        tuple((token(Token::MATERIAL), string_, param_list)),
        |(_, typ, params)| api.material(typ, &params),
    );
    let make_named_material = map_res(
        tuple((token(Token::MAKENAMEDMATERIAL), string_, param_list)),
        |(_, typ, params)| api.make_named_material(typ, &params),
    );
    let named_material = map_res(pair(token(Token::NAMEDMATERIAL), string_), |(_, name)| {
        api.named_material(name)
    });
    let sampler = map_res(
        tuple((token(Token::SAMPLER), string_, param_list)),
        |(_, typ, params)| api.sampler(typ, &params),
    );
    let shape = map_res(
        tuple((token(Token::SHAPE), string_, param_list)),
        |(_, typ, params)| api.shape(typ, &params),
    );
    let reverse_orientation = map_res(token(Token::REVERSEORIENTATION), |_| {
        api.reverse_orientation()
    });
    let filter = map_res(
        tuple((token(Token::PIXELFILTER), string_, param_list)),
        |(_, typ, params)| api.pixel_filter(typ, &params),
    );
    let scale = map_res(
        tuple((token(Token::SCALE), num, num, num)),
        |(_, sx, sy, sz)| api.scale(sx, sy, sz),
    );
    let rotate = map_res(
        tuple((token(Token::ROTATE), num, num, num, num)),
        |(_, angle, dx, dy, dz)| api.rotate(angle, dx, dy, dz),
    );
    let texture = map_res(
        tuple((token(Token::TEXTURE), string_, string_, string_, param_list)),
        |(_, name, typ, texname, params)| api.texture(name, typ, texname, &params),
    );
    let concat_transform = map_res(
        pair(token(Token::CONCATTRANSFORM), num_array),
        |(_, nums)| {
            api.concat_transform(
                nums[0], nums[1], nums[2], nums[3], nums[4], nums[5], nums[6], nums[7], nums[8],
                nums[9], nums[10], nums[11], nums[12], nums[13], nums[14], nums[15],
            )
        },
    );
    let transform = map_res(pair(token(Token::TRANSFORM), num_array), |(_, nums)| {
        api.transform(
            nums[0], nums[1], nums[2], nums[3], nums[4], nums[5], nums[6], nums[7], nums[8],
            nums[9], nums[10], nums[11], nums[12], nums[13], nums[14], nums[15],
        )
    });
    let translate = map_res(
        tuple((token(Token::TRANSLATE), num, num, num)),
        |(_, dx, dy, dz)| api.translate(dx, dy, dz),
    );

    let (rest, _) = all_consuming(many1(alt((
        accelerator,
        attribute_begin,
        attribute_end,
        transform_begin,
        transform_end,
        object_begin,
        object_end,
        object_instance,
        world_begin,
        world_end,
        look_at,
        coordinate_system,
        coord_sys_transform,
        camera,
        film,
        integrator,
        arealightsource,
        lightsource,
        material,
        make_named_material,
        alt((
            named_material,
            sampler,
            shape,
            reverse_orientation,
            filter,
            scale,
            rotate,
            texture,
            concat_transform,
            transform,
            translate,
        )),
    ))))(input)?;

    Ok((rest, ()))
}

fn param_list(input: Tokens<'_>) -> IResult<Tokens<'_>, ParamSet> {
    map(many0(param_list_entry), |x| {
        let mut ps = ParamSet::default();
        ps.init(x);
        ps
    })(input)
}

fn param_type(input: &str) -> IResult<&str, ParamType> {
    alt((
        value(ParamType::Int, tag("integer")),
        value(ParamType::Bool, tag("bool")),
        value(ParamType::Float, tag("float")),
        value(ParamType::Point2, tag("point2")),
        value(ParamType::Vector2, tag("vector2")),
        value(ParamType::Point3, tag("point3")),
        value(ParamType::Vector3, tag("vector3")),
        value(ParamType::Point3, tag("point")),
        value(ParamType::Vector3, tag("vector")),
        value(ParamType::Normal, tag("normal")),
        value(ParamType::Rgb, tag("color")),
        value(ParamType::Rgb, tag("rgb")),
        value(ParamType::Xyz, tag("xyz")),
        value(ParamType::Blackbody, tag("blackbody")),
        value(ParamType::Spectrum, tag("spectrum")),
        value(ParamType::String, tag("string")),
        value(ParamType::Texture, tag("texture")),
    ))(input)
}

fn param_list_entry_header(input: Tokens<'_>) -> IResult<Tokens<'_>, (ParamType, String)> {
    let (rest, s) = string_(input)?;

    let (name, (param_type, _)) = match tuple((param_type, space1))(&s).finish() {
        Ok(res) => res,
        Err(e) => return Err(nom::Err::Error(Error::new(rest, e.code))),
    };

    Ok((rest, (param_type, name.to_string())))
}

fn param_list_entry(input: Tokens<'_>) -> IResult<Tokens<'_>, ParamListEntry> {
    map(
        tuple((param_list_entry_header, array)),
        |(header, array)| ParamListEntry::new(header.0, header.1, array),
    )(input)
}

fn array(input: Tokens<'_>) -> IResult<Tokens<'_>, Array> {
    alt((
        map(string_array, Array::StrArray),
        map(num_array, Array::NumArray),
    ))(input)
}

fn string_array(input: Tokens<'_>) -> IResult<Tokens<'_>, Vec<String>> {
    alt((
        delimited(token(Token::LBRACK), many1(string_), token(Token::RBRACK)),
        map(string_, |x| vec![x]),
    ))(input)
}

fn num_array(input: Tokens<'_>) -> IResult<Tokens<'_>, Vec<f32>> {
    alt((
        delimited(token(Token::LBRACK), many1(num), token(Token::RBRACK)),
        map(num, |x| vec![x]),
    ))(input)
}

fn num(input: Tokens<'_>) -> IResult<Tokens<'_>, f32> {
    let (i, ret) = take(1usize)(input)?;

    match ret[0] {
        Token::NUMBER(n) => Ok((i, n)),
        _ => Err(nom::Err::Error(Error::new(i, ErrorKind::Digit))),
    }
}

fn string_(input: Tokens<'_>) -> IResult<Tokens<'_>, String> {
    let (i, ret) = take(1usize)(input)?;
    match ret[0] {
        Token::STR(ref s) => Ok((i, s.clone())),
        _ => Err(nom::Err::Error(Error::new(i, ErrorKind::Tag))),
    }
}

fn token<'a, I>(t: Token) -> impl Fn(I) -> IResult<I, Token>
where
    I: nom::Slice<RangeFrom<usize>> + nom::InputIter<Item = &'a Token>,
{
    move |i: I| match (i).iter_elements().next().map(|tt| {
        let b = *tt == t;
        (&t, b)
    }) {
        Some((t, true)) => Ok((i.slice(1..), t.clone())),
        _ => Err(nom::Err::Error(Error::new(i, nom::error::ErrorKind::Char))),
    }
}

// #[test]
// fn test_parse() {
//     let tokens = vec![Tokens::ATTRIBUTEBEGIN, Tokens::ATTRIBUTEEND];
//     let api = ::api::RealApi::default();
//     api.init().unwrap();
//     parse(&tokens[..], &api).unwrap();
// }

#[cfg(test)]
mod tests {
    use nom::{error::ParseError, Parser};

    use super::*;

    fn test_parse<'a, O, E>(input: &'a [Token], mut p: impl Parser<Tokens<'a>, O, E>, v: O)
    where
        O: std::fmt::Debug + PartialEq,
        E: ParseError<Tokens<'a>> + std::fmt::Debug,
    {
        assert_eq!(p.parse(Tokens::new(input)).unwrap().1, v);
    }

    #[test]
    fn test_array() {
        let p = vec![
            Token::LBRACK,
            Token::NUMBER(50.0),
            Token::NUMBER(12.0),
            Token::RBRACK,
        ];

        test_parse(&p, array, Array::NumArray(vec![50.0, 12.0]))
    }

    #[test]
    fn test_num_array() {
        let p = vec![Token::LBRACK, Token::NUMBER(50.0), Token::RBRACK];

        test_parse(&p, num_array, vec![50.0])
    }

    #[test]
    fn test_param_list_entry() {
        let p = vec![
            Token::STR("float fov".to_owned()),
            Token::LBRACK,
            Token::NUMBER(50.0),
            Token::RBRACK,
        ];

        param_list_entry(Tokens::new(&p[..])).unwrap();
    }

    #[test]
    fn test_param_type() {
        let p = "float";

        let res = param_type(&p).unwrap();
        assert_eq!(res, ("", ParamType::Float));

        let q = "floatxxx";
        let res = param_type(&q).unwrap();
        assert_eq!(res, ("xxx", ParamType::Float));
    }

    #[test]
    fn test_param_list_entry_header() {
        let p = vec![Token::STR("float fov".to_owned())];

        test_parse(
            &p,
            param_list_entry_header,
            (ParamType::Float, "fov".to_string()),
        );
    }
}
<commit_msg>Re-add INCLUDE statements<commit_after>use std::ops::RangeFrom;

use anyhow::format_err;
use log::info;
use nom::{
    branch::alt,
    bytes::complete::{tag, take},
    character::complete::space1,
    combinator::{all_consuming, map, map_res, value},
    error::{Error, ErrorKind},
    multi::{many0, many1},
    sequence::{delimited, pair, tuple},
    Finish, IResult,
};

use super::lexer::{Token, Tokens};
use crate::api::{Api, Array, ParamListEntry, ParamType};
use crate::paramset::ParamSet;

pub fn parse<'input, 'api, A: Api>(
    input: Tokens<'input>,
    api: &'api A,
) -> IResult<Tokens<'input>, ()> {
    let accelerator = map_res(
        tuple((token(Token::ACCELERATOR), string_, param_list)),
        |(_, typ, params)| api.accelerator(typ, &params),
    );
    let attribute_begin = map_res(token(Token::ATTRIBUTEBEGIN), |_| api.attribute_begin());
    let attribute_end = map_res(token(Token::ATTRIBUTEEND), |_| api.attribute_end());
    let transform_begin = map_res(token(Token::TRANSFORMBEGIN), |_| api.transform_begin());
    let transform_end = map_res(token(Token::TRANSFORMEND), |_| api.transform_end());
    let object_begin = map_res(pair(token(Token::OBJECTBEGIN), string_), |(_, name)| {
        api.object_begin(name)
    });
    let object_end = map_res(token(Token::OBJECTEND), |_| api.object_end());
    let object_instance = map_res(pair(token(Token::OBJECTINSTANCE), string_), |(_, name)| {
        api.object_instance(name)
    });
    let world_begin = map_res(token(Token::WORLDBEGIN), |_| api.world_begin());
    let world_end = map_res(token(Token::WORLDEND), |_| api.world_end());
    let look_at = map_res(
        tuple((
            token(Token::LOOKAT),
            num,
            num,
            num,
            num,
            num,
            num,
            num,
            num,
            num,
        )),
        |(_, ex, ey, ez, lx, ly, lz, ux, uy, uz)| api.look_at(ex, ey, ez, lx, ly, lz, ux, uy, uz),
    );
    let coordinate_system = map_res(
        pair(token(Token::COORDINATESYSTEM), string_),
        |(_, name)| api.coordinate_system(name),
    );
    let coord_sys_transform = map_res(
        pair(token(Token::COORDSYSTRANSFORM), string_),
        |(_, name)| api.coord_sys_transform(name),
    );
    let camera = map_res(
        tuple((token(Token::CAMERA), string_, param_list)),
        |(_, typ, params)| api.camera(typ, &params),
    );
    let film = map_res(
        tuple((token(Token::FILM), string_, param_list)),
        |(_, typ, params)| api.film(typ, &params),
    );
    let include = map_res(pair(token(Token::INCLUDE), string_), |(_, name)| {
        info!("Parsing included file: {}", name);
        super::tokenize_file(&name)
            .and_then(|tokens| {
                parse(Tokens::new(&tokens[..]), api)
                    .map(|_| ())
                    .map_err(|e| format_err!("Failed to parse included file: {:?}", e))
            })
    });
    let integrator = map_res(
        tuple((token(Token::INTEGRATOR), string_, param_list)),
        |(_, typ, params)| api.integrator(typ, &params),
    );
    let arealightsource = map_res(
        tuple((token(Token::AREALIGHTSOURCE), string_, param_list)),
        |(_, typ, params)| api.arealightsource(typ, &params),
    );
    let lightsource = map_res(
        tuple((token(Token::LIGHTSOURCE), string_, param_list)),
        |(_, typ, params)| api.lightsource(typ, &params),
    );
    let material = map_res(
        tuple((token(Token::MATERIAL), string_, param_list)),
        |(_, typ, params)| api.material(typ, &params),
    );
    let make_named_material = map_res(
        tuple((token(Token::MAKENAMEDMATERIAL), string_, param_list)),
        |(_, typ, params)| api.make_named_material(typ, &params),
    );
    let named_material = map_res(pair(token(Token::NAMEDMATERIAL), string_), |(_, name)| {
        api.named_material(name)
    });
    let sampler = map_res(
        tuple((token(Token::SAMPLER), string_, param_list)),
        |(_, typ, params)| api.sampler(typ, &params),
    );
    let shape = map_res(
        tuple((token(Token::SHAPE), string_, param_list)),
        |(_, typ, params)| api.shape(typ, &params),
    );
    let reverse_orientation = map_res(token(Token::REVERSEORIENTATION), |_| {
        api.reverse_orientation()
    });
    let filter = map_res(
        tuple((token(Token::PIXELFILTER), string_, param_list)),
        |(_, typ, params)| api.pixel_filter(typ, &params),
    );
    let scale = map_res(
        tuple((token(Token::SCALE), num, num, num)),
        |(_, sx, sy, sz)| api.scale(sx, sy, sz),
    );
    let rotate = map_res(
        tuple((token(Token::ROTATE), num, num, num, num)),
        |(_, angle, dx, dy, dz)| api.rotate(angle, dx, dy, dz),
    );
    let texture = map_res(
        tuple((token(Token::TEXTURE), string_, string_, string_, param_list)),
        |(_, name, typ, texname, params)| api.texture(name, typ, texname, &params),
    );
    let concat_transform = map_res(
        pair(token(Token::CONCATTRANSFORM), num_array),
        |(_, nums)| {
            api.concat_transform(
                nums[0], nums[1], nums[2], nums[3], nums[4], nums[5], nums[6], nums[7], nums[8],
                nums[9], nums[10], nums[11], nums[12], nums[13], nums[14], nums[15],
            )
        },
    );
    let transform = map_res(pair(token(Token::TRANSFORM), num_array), |(_, nums)| {
        api.transform(
            nums[0], nums[1], nums[2], nums[3], nums[4], nums[5], nums[6], nums[7], nums[8],
            nums[9], nums[10], nums[11], nums[12], nums[13], nums[14], nums[15],
        )
    });
    let translate = map_res(
        tuple((token(Token::TRANSLATE), num, num, num)),
        |(_, dx, dy, dz)| api.translate(dx, dy, dz),
    );

    let (rest, _) = all_consuming(many1(alt((
        accelerator,
        attribute_begin,
        attribute_end,
        transform_begin,
        transform_end,
        object_begin,
        object_end,
        object_instance,
        world_begin,
        world_end,
        look_at,
        coordinate_system,
        coord_sys_transform,
        camera,
        film,
        include,
        integrator,
        arealightsource,
        lightsource,
        material,
        alt((
            make_named_material,
            named_material,
            sampler,
            shape,
            reverse_orientation,
            filter,
            scale,
            rotate,
            texture,
            concat_transform,
            transform,
            translate,
        )),
    ))))(input)?;

    Ok((rest, ()))
}

fn param_list(input: Tokens<'_>) -> IResult<Tokens<'_>, ParamSet> {
    map(many0(param_list_entry), |x| {
        let mut ps = ParamSet::default();
        ps.init(x);
        ps
    })(input)
}

fn param_type(input: &str) -> IResult<&str, ParamType> {
    alt((
        value(ParamType::Int, tag("integer")),
        value(ParamType::Bool, tag("bool")),
        value(ParamType::Float, tag("float")),
        value(ParamType::Point2, tag("point2")),
        value(ParamType::Vector2, tag("vector2")),
        value(ParamType::Point3, tag("point3")),
        value(ParamType::Vector3, tag("vector3")),
        value(ParamType::Point3, tag("point")),
        value(ParamType::Vector3, tag("vector")),
        value(ParamType::Normal, tag("normal")),
        value(ParamType::Rgb, tag("color")),
        value(ParamType::Rgb, tag("rgb")),
        value(ParamType::Xyz, tag("xyz")),
        value(ParamType::Blackbody, tag("blackbody")),
        value(ParamType::Spectrum, tag("spectrum")),
        value(ParamType::String, tag("string")),
        value(ParamType::Texture, tag("texture")),
    ))(input)
}

fn param_list_entry_header(input: Tokens<'_>) -> IResult<Tokens<'_>, (ParamType, String)> {
    let (rest, s) = string_(input)?;

    let (name, (param_type, _)) = match tuple((param_type, space1))(&s).finish() {
        Ok(res) => res,
        Err(e) => return Err(nom::Err::Error(Error::new(rest, e.code))),
    };

    Ok((rest, (param_type, name.to_string())))
}

fn param_list_entry(input: Tokens<'_>) -> IResult<Tokens<'_>, ParamListEntry> {
    map(
        tuple((param_list_entry_header, array)),
        |(header, array)| ParamListEntry::new(header.0, header.1, array),
    )(input)
}

fn array(input: Tokens<'_>) -> IResult<Tokens<'_>, Array> {
    alt((
        map(string_array, Array::StrArray),
        map(num_array, Array::NumArray),
    ))(input)
}

fn string_array(input: Tokens<'_>) -> IResult<Tokens<'_>, Vec<String>> {
    alt((
        delimited(token(Token::LBRACK), many1(string_), token(Token::RBRACK)),
        map(string_, |x| vec![x]),
    ))(input)
}

fn num_array(input: Tokens<'_>) -> IResult<Tokens<'_>, Vec<f32>> {
    alt((
        delimited(token(Token::LBRACK), many1(num), token(Token::RBRACK)),
        map(num, |x| vec![x]),
    ))(input)
}

fn num(input: Tokens<'_>) -> IResult<Tokens<'_>, f32> {
    let (i, ret) = take(1usize)(input)?;

    match ret[0] {
        Token::NUMBER(n) => Ok((i, n)),
        _ => Err(nom::Err::Error(Error::new(i, ErrorKind::Digit))),
    }
}

fn string_(input: Tokens<'_>) -> IResult<Tokens<'_>, String> {
    let (i, ret) = take(1usize)(input)?;
    match ret[0] {
        Token::STR(ref s) => Ok((i, s.clone())),
        _ => Err(nom::Err::Error(Error::new(i, ErrorKind::Tag))),
    }
}

fn token<'a, I>(t: Token) -> impl Fn(I) -> IResult<I, Token>
where
    I: nom::Slice<RangeFrom<usize>> + nom::InputIter<Item = &'a Token>,
{
    move |i: I| match (i).iter_elements().next().map(|tt| {
        let b = *tt == t;
        (&t, b)
    }) {
        Some((t, true)) => Ok((i.slice(1..), t.clone())),
        _ => Err(nom::Err::Error(Error::new(i, nom::error::ErrorKind::Char))),
    }
}

// #[test]
// fn test_parse() {
//     let tokens = vec![Tokens::ATTRIBUTEBEGIN, Tokens::ATTRIBUTEEND];
//     let api = ::api::RealApi::default();
//     api.init().unwrap();
//     parse(&tokens[..], &api).unwrap();
// }

#[cfg(test)]
mod tests {
    use nom::{error::ParseError, Parser};

    use super::*;

    fn test_parse<'a, O, E>(input: &'a [Token], mut p: impl Parser<Tokens<'a>, O, E>, v: O)
    where
        O: std::fmt::Debug + PartialEq,
        E: ParseError<Tokens<'a>> + std::fmt::Debug,
    {
        assert_eq!(p.parse(Tokens::new(input)).unwrap().1, v);
    }

    #[test]
    fn test_array() {
        let p = vec![
            Token::LBRACK,
            Token::NUMBER(50.0),
            Token::NUMBER(12.0),
            Token::RBRACK,
        ];

        test_parse(&p, array, Array::NumArray(vec![50.0, 12.0]))
    }

    #[test]
    fn test_num_array() {
        let p = vec![Token::LBRACK, Token::NUMBER(50.0), Token::RBRACK];

        test_parse(&p, num_array, vec![50.0])
    }

    #[test]
    fn test_param_list_entry() {
        let p = vec![
            Token::STR("float fov".to_owned()),
            Token::LBRACK,
            Token::NUMBER(50.0),
            Token::RBRACK,
        ];

        param_list_entry(Tokens::new(&p[..])).unwrap();
    }

    #[test]
    fn test_param_type() {
        let p = "float";

        let res = param_type(&p).unwrap();
        assert_eq!(res, ("", ParamType::Float));

        let q = "floatxxx";
        let res = param_type(&q).unwrap();
        assert_eq!(res, ("xxx", ParamType::Float));
    }

    #[test]
    fn test_param_list_entry_header() {
        let p = vec![Token::STR("float fov".to_owned())];

        test_parse(
            &p,
            param_list_entry_header,
            (ParamType::Float, "fov".to_string()),
        );
    }
}
<|endoftext|>


<commit_before>use byteorder::{BigEndian, ByteOrder};
use bytes::Bytes;
use futures::sync::{mpsc, BiLock};
use futures::{Async, Poll, Stream};
use std::collections::HashMap;
use std::time::Instant;

use util::SeqGenerator;

component! {
    ChannelManager : ChannelManagerInner {
        sequence: SeqGenerator<u16> = SeqGenerator::new(0),
        channels: HashMap<u16, mpsc::UnboundedSender<(u8, Bytes)>> = HashMap::new(),
        download_rate_estimate: usize = 0,
        download_measurement_start: Option<Instant> = None,
        download_measurement_bytes: usize = 0,
    }
}

#[derive(Debug, Hash, PartialEq, Eq, Copy, Clone)]
pub struct ChannelError;

pub struct Channel {
    receiver: mpsc::UnboundedReceiver<(u8, Bytes)>,
    state: ChannelState,
}

pub struct ChannelHeaders(BiLock<Channel>);
pub struct ChannelData(BiLock<Channel>);

pub enum ChannelEvent {
    Header(u8, Vec<u8>),
    Data(Bytes),
}

#[derive(Clone)]
enum ChannelState {
    Header(Bytes),
    Data,
    Closed,
}

impl ChannelManager {
    pub fn allocate(&self) -> (u16, Channel) {
        let (tx, rx) = mpsc::unbounded();

        let seq = self.lock(|inner| {
            let seq = inner.sequence.get();
            inner.channels.insert(seq, tx);
            seq
        });

        let channel = Channel {
            receiver: rx,
            state: ChannelState::Header(Bytes::new()),
        };

        (seq, channel)
    }

    pub(crate) fn dispatch(&self, cmd: u8, mut data: Bytes) {
        use std::collections::hash_map::Entry;

        let id: u16 = BigEndian::read_u16(data.split_to(2).as_ref());

        self.lock(|inner| {
            let current_time = Instant::now();
            if let Some(download_measurement_start) = inner.download_measurement_start {
                if (current_time - download_measurement_start).as_millis() > 1000 {
                    inner.download_rate_estimate = 1000 * inner.download_measurement_bytes
                        / (current_time - download_measurement_start).as_millis() as usize;
                    inner.download_measurement_start = Some(current_time);
                    inner.download_measurement_bytes = 0;
                }
            } else {
                inner.download_measurement_start = Some(current_time);
            }

            inner.download_measurement_bytes += data.len();

            if let Entry::Occupied(entry) = inner.channels.entry(id) {
                let _ = entry.get().unbounded_send((cmd, data));
            }
        });
    }

    pub fn get_download_rate_estimate(&self) -> usize {
        return self.lock(|inner| inner.download_rate_estimate);
    }
}

impl Channel {
    fn recv_packet(&mut self) -> Poll<Bytes, ChannelError> {
        let (cmd, packet) = match self.receiver.poll() {
            Ok(Async::Ready(t)) => t.expect("channel closed"),
            Ok(Async::NotReady) => return Ok(Async::NotReady),
            Err(()) => unreachable!(),
        };

        if cmd == 0xa {
            let code = BigEndian::read_u16(&packet.as_ref()[..2]);
            error!("channel error: {} {}", packet.len(), code);

            self.state = ChannelState::Closed;

            Err(ChannelError)
        } else {
            Ok(Async::Ready(packet))
        }
    }

    pub fn split(self) -> (ChannelHeaders, ChannelData) {
        let (headers, data) = BiLock::new(self);

        (ChannelHeaders(headers), ChannelData(data))
    }
}

impl Stream for Channel {
    type Item = ChannelEvent;
    type Error = ChannelError;

    fn poll(&mut self) -> Poll<Option<Self::Item>, Self::Error> {
        loop {
            match self.state.clone() {
                ChannelState::Closed => panic!("Polling already terminated channel"),
                ChannelState::Header(mut data) => {
                    if data.len() == 0 {
                        data = try_ready!(self.recv_packet());
                    }

                    let length = BigEndian::read_u16(data.split_to(2).as_ref()) as usize;
                    if length == 0 {
                        assert_eq!(data.len(), 0);
                        self.state = ChannelState::Data;
                    } else {
                        let header_id = data.split_to(1).as_ref()[0];
                        let header_data = data.split_to(length - 1).as_ref().to_owned();

                        self.state = ChannelState::Header(data);

                        let event = ChannelEvent::Header(header_id, header_data);
                        return Ok(Async::Ready(Some(event)));
                    }
                }

                ChannelState::Data => {
                    let data = try_ready!(self.recv_packet());
                    if data.len() == 0 {
                        self.receiver.close();
                        self.state = ChannelState::Closed;
                        return Ok(Async::Ready(None));
                    } else {
                        let event = ChannelEvent::Data(data);
                        return Ok(Async::Ready(Some(event)));
                    }
                }
            }
        }
    }
}

impl Stream for ChannelData {
    type Item = Bytes;
    type Error = ChannelError;

    fn poll(&mut self) -> Poll<Option<Self::Item>, Self::Error> {
        let mut channel = match self.0.poll_lock() {
            Async::Ready(c) => c,
            Async::NotReady => return Ok(Async::NotReady),
        };

        loop {
            match try_ready!(channel.poll()) {
                Some(ChannelEvent::Header(..)) => (),
                Some(ChannelEvent::Data(data)) => return Ok(Async::Ready(Some(data))),
                None => return Ok(Async::Ready(None)),
            }
        }
    }
}

impl Stream for ChannelHeaders {
    type Item = (u8, Vec<u8>);
    type Error = ChannelError;

    fn poll(&mut self) -> Poll<Option<Self::Item>, Self::Error> {
        let mut channel = match self.0.poll_lock() {
            Async::Ready(c) => c,
            Async::NotReady => return Ok(Async::NotReady),
        };

        match try_ready!(channel.poll()) {
            Some(ChannelEvent::Header(id, data)) => Ok(Async::Ready(Some((id, data)))),
            Some(ChannelEvent::Data(..)) | None => Ok(Async::Ready(None)),
        }
    }
}
<commit_msg>Fix error handling for closed channel.<commit_after>use byteorder::{BigEndian, ByteOrder};
use bytes::Bytes;
use futures::sync::{mpsc, BiLock};
use futures::{Async, Poll, Stream};
use std::collections::HashMap;
use std::time::Instant;

use util::SeqGenerator;

component! {
    ChannelManager : ChannelManagerInner {
        sequence: SeqGenerator<u16> = SeqGenerator::new(0),
        channels: HashMap<u16, mpsc::UnboundedSender<(u8, Bytes)>> = HashMap::new(),
        download_rate_estimate: usize = 0,
        download_measurement_start: Option<Instant> = None,
        download_measurement_bytes: usize = 0,
    }
}

#[derive(Debug, Hash, PartialEq, Eq, Copy, Clone)]
pub struct ChannelError;

pub struct Channel {
    receiver: mpsc::UnboundedReceiver<(u8, Bytes)>,
    state: ChannelState,
}

pub struct ChannelHeaders(BiLock<Channel>);
pub struct ChannelData(BiLock<Channel>);

pub enum ChannelEvent {
    Header(u8, Vec<u8>),
    Data(Bytes),
}

#[derive(Clone)]
enum ChannelState {
    Header(Bytes),
    Data,
    Closed,
}

impl ChannelManager {
    pub fn allocate(&self) -> (u16, Channel) {
        let (tx, rx) = mpsc::unbounded();

        let seq = self.lock(|inner| {
            let seq = inner.sequence.get();
            inner.channels.insert(seq, tx);
            seq
        });

        let channel = Channel {
            receiver: rx,
            state: ChannelState::Header(Bytes::new()),
        };

        (seq, channel)
    }

    pub(crate) fn dispatch(&self, cmd: u8, mut data: Bytes) {
        use std::collections::hash_map::Entry;

        let id: u16 = BigEndian::read_u16(data.split_to(2).as_ref());

        self.lock(|inner| {
            let current_time = Instant::now();
            if let Some(download_measurement_start) = inner.download_measurement_start {
                if (current_time - download_measurement_start).as_millis() > 1000 {
                    inner.download_rate_estimate = 1000 * inner.download_measurement_bytes
                        / (current_time - download_measurement_start).as_millis() as usize;
                    inner.download_measurement_start = Some(current_time);
                    inner.download_measurement_bytes = 0;
                }
            } else {
                inner.download_measurement_start = Some(current_time);
            }

            inner.download_measurement_bytes += data.len();

            if let Entry::Occupied(entry) = inner.channels.entry(id) {
                let _ = entry.get().unbounded_send((cmd, data));
            }
        });
    }

    pub fn get_download_rate_estimate(&self) -> usize {
        return self.lock(|inner| inner.download_rate_estimate);
    }
}

impl Channel {
    fn recv_packet(&mut self) -> Poll<Bytes, ChannelError> {
        let (cmd, packet) = match self.receiver.poll() {
            Ok(Async::Ready(Some(t))) => t,
            Ok(Async::Ready(None)) => return Err(ChannelError), // The channel has been closed.
            Ok(Async::NotReady) => return Ok(Async::NotReady),
            Err(()) => unreachable!(),
        };

        if cmd == 0xa {
            let code = BigEndian::read_u16(&packet.as_ref()[..2]);
            error!("channel error: {} {}", packet.len(), code);

            self.state = ChannelState::Closed;

            Err(ChannelError)
        } else {
            Ok(Async::Ready(packet))
        }
    }

    pub fn split(self) -> (ChannelHeaders, ChannelData) {
        let (headers, data) = BiLock::new(self);

        (ChannelHeaders(headers), ChannelData(data))
    }
}

impl Stream for Channel {
    type Item = ChannelEvent;
    type Error = ChannelError;

    fn poll(&mut self) -> Poll<Option<Self::Item>, Self::Error> {
        loop {
            match self.state.clone() {
                ChannelState::Closed => panic!("Polling already terminated channel"),
                ChannelState::Header(mut data) => {
                    if data.len() == 0 {
                        data = try_ready!(self.recv_packet());
                    }

                    let length = BigEndian::read_u16(data.split_to(2).as_ref()) as usize;
                    if length == 0 {
                        assert_eq!(data.len(), 0);
                        self.state = ChannelState::Data;
                    } else {
                        let header_id = data.split_to(1).as_ref()[0];
                        let header_data = data.split_to(length - 1).as_ref().to_owned();

                        self.state = ChannelState::Header(data);

                        let event = ChannelEvent::Header(header_id, header_data);
                        return Ok(Async::Ready(Some(event)));
                    }
                }

                ChannelState::Data => {
                    let data = try_ready!(self.recv_packet());
                    if data.len() == 0 {
                        self.receiver.close();
                        self.state = ChannelState::Closed;
                        return Ok(Async::Ready(None));
                    } else {
                        let event = ChannelEvent::Data(data);
                        return Ok(Async::Ready(Some(event)));
                    }
                }
            }
        }
    }
}

impl Stream for ChannelData {
    type Item = Bytes;
    type Error = ChannelError;

    fn poll(&mut self) -> Poll<Option<Self::Item>, Self::Error> {
        let mut channel = match self.0.poll_lock() {
            Async::Ready(c) => c,
            Async::NotReady => return Ok(Async::NotReady),
        };

        loop {
            match try_ready!(channel.poll()) {
                Some(ChannelEvent::Header(..)) => (),
                Some(ChannelEvent::Data(data)) => return Ok(Async::Ready(Some(data))),
                None => return Ok(Async::Ready(None)),
            }
        }
    }
}

impl Stream for ChannelHeaders {
    type Item = (u8, Vec<u8>);
    type Error = ChannelError;

    fn poll(&mut self) -> Poll<Option<Self::Item>, Self::Error> {
        let mut channel = match self.0.poll_lock() {
            Async::Ready(c) => c,
            Async::NotReady => return Ok(Async::NotReady),
        };

        match try_ready!(channel.poll()) {
            Some(ChannelEvent::Header(id, data)) => Ok(Async::Ready(Some((id, data)))),
            Some(ChannelEvent::Data(..)) | None => Ok(Async::Ready(None)),
        }
    }
}
<|endoftext|>


<commit_before>// Copyright © 2017 Mozilla Foundation
//
// This program is made available under an ISC-style license.  See the
// accompanying file LICENSE for details.

use cubeb_core::{Context, DeviceCollectionRef, DeviceId, DeviceRef, DeviceType, Result, Stream,
                 StreamParams, StreamParamsRef};
use ffi;
use std::ffi::CStr;
use std::os::raw::c_void;

pub trait ContextOps {
    fn init(context_name: Option<&CStr>) -> Result<Context>;
    fn backend_id(&mut self) -> &'static CStr;
    fn max_channel_count(&mut self) -> Result<u32>;
    fn min_latency(&mut self, params: StreamParams) -> Result<u32>;
    fn preferred_sample_rate(&mut self) -> Result<u32>;
    fn enumerate_devices(
        &mut self,
        devtype: DeviceType,
        collection: &DeviceCollectionRef,
    ) -> Result<()>;
    fn device_collection_destroy(&mut self, collection: &mut DeviceCollectionRef) -> Result<()>;
    #[cfg_attr(feature = "cargo-clippy", allow(too_many_arguments))]
    fn stream_init(
        &mut self,
        stream_name: Option<&CStr>,
        input_device: DeviceId,
        input_stream_params: Option<&StreamParamsRef>,
        output_device: DeviceId,
        output_stream_params: Option<&StreamParamsRef>,
        latency_frames: u32,
        data_callback: ffi::cubeb_data_callback,
        state_callback: ffi::cubeb_state_callback,
        user_ptr: *mut c_void,
    ) -> Result<Stream>;
    fn register_device_collection_changed(
        &mut self,
        devtype: DeviceType,
        cb: ffi::cubeb_device_collection_changed_callback,
        user_ptr: *mut c_void,
    ) -> Result<()>;
}

pub trait StreamOps {
    fn start(&mut self) -> Result<()>;
    fn stop(&mut self) -> Result<()>;
    fn reset_default_device(&mut self) -> Result<()>;
    fn position(&mut self) -> Result<u64>;
    fn latency(&mut self) -> Result<u32>;
    fn set_volume(&mut self, volume: f32) -> Result<()>;
    fn set_panning(&mut self, panning: f32) -> Result<()>;
    fn current_device(&mut self) -> Result<&DeviceRef>;
    fn device_destroy(&mut self, device: &DeviceRef) -> Result<()>;
    fn register_device_changed_callback(
        &mut self,
        device_changed_callback: ffi::cubeb_device_changed_callback,
    ) -> Result<()>;
}
<commit_msg>Drop 'static lifetime from ContextOps::backend_id return value.<commit_after>// Copyright © 2017 Mozilla Foundation
//
// This program is made available under an ISC-style license.  See the
// accompanying file LICENSE for details.

use cubeb_core::{Context, DeviceCollectionRef, DeviceId, DeviceRef, DeviceType, Result, Stream,
                 StreamParams, StreamParamsRef};
use ffi;
use std::ffi::CStr;
use std::os::raw::c_void;

pub trait ContextOps {
    fn init(context_name: Option<&CStr>) -> Result<Context>;
    fn backend_id(&mut self) -> &CStr;
    fn max_channel_count(&mut self) -> Result<u32>;
    fn min_latency(&mut self, params: StreamParams) -> Result<u32>;
    fn preferred_sample_rate(&mut self) -> Result<u32>;
    fn enumerate_devices(
        &mut self,
        devtype: DeviceType,
        collection: &DeviceCollectionRef,
    ) -> Result<()>;
    fn device_collection_destroy(&mut self, collection: &mut DeviceCollectionRef) -> Result<()>;
    #[cfg_attr(feature = "cargo-clippy", allow(too_many_arguments))]
    fn stream_init(
        &mut self,
        stream_name: Option<&CStr>,
        input_device: DeviceId,
        input_stream_params: Option<&StreamParamsRef>,
        output_device: DeviceId,
        output_stream_params: Option<&StreamParamsRef>,
        latency_frames: u32,
        data_callback: ffi::cubeb_data_callback,
        state_callback: ffi::cubeb_state_callback,
        user_ptr: *mut c_void,
    ) -> Result<Stream>;
    fn register_device_collection_changed(
        &mut self,
        devtype: DeviceType,
        cb: ffi::cubeb_device_collection_changed_callback,
        user_ptr: *mut c_void,
    ) -> Result<()>;
}

pub trait StreamOps {
    fn start(&mut self) -> Result<()>;
    fn stop(&mut self) -> Result<()>;
    fn reset_default_device(&mut self) -> Result<()>;
    fn position(&mut self) -> Result<u64>;
    fn latency(&mut self) -> Result<u32>;
    fn set_volume(&mut self, volume: f32) -> Result<()>;
    fn set_panning(&mut self, panning: f32) -> Result<()>;
    fn current_device(&mut self) -> Result<&DeviceRef>;
    fn device_destroy(&mut self, device: &DeviceRef) -> Result<()>;
    fn register_device_changed_callback(
        &mut self,
        device_changed_callback: ffi::cubeb_device_changed_callback,
    ) -> Result<()>;
}
<|endoftext|>


<commit_before>mod api;
mod key;
mod metrics;

use beacon_chain::{BeaconChain, BeaconChainTypes};
use futures::Future;
use iron::prelude::*;
use network::NetworkMessage;
use router::Router;
use slog::{info, o, warn};
use std::sync::Arc;
use tokio::runtime::TaskExecutor;

#[derive(PartialEq, Clone, Debug)]
pub struct HttpServerConfig {
    pub enabled: bool,
    pub listen_address: String,
}

impl Default for HttpServerConfig {
    fn default() -> Self {
        Self {
            enabled: false,
            listen_address: "127.0.0.1:5051".to_string(),
        }
    }
}

/// Build the `iron` HTTP server, defining the core routes.
pub fn create_iron_http_server<T: BeaconChainTypes + 'static>(
    beacon_chain: Arc<BeaconChain<T>>,
) -> Iron<Router> {
    let mut router = Router::new();

    // A `GET` request to `/metrics` is handled by the `metrics` module.
    router.get(
        "/metrics",
        metrics::build_handler(beacon_chain.clone()),
        "metrics",
    );

    // Any request to all other endpoints is handled by the `api` module.
    router.any("/*", api::build_handler(beacon_chain.clone()), "api");

    Iron::new(router)
}

/// Start the HTTP service on the tokio `TaskExecutor`.
pub fn start_service<T: BeaconChainTypes + 'static>(
    config: &HttpServerConfig,
    executor: &TaskExecutor,
    _network_chan: crossbeam_channel::Sender<NetworkMessage>,
    beacon_chain: Arc<BeaconChain<T>>,
    log: &slog::Logger,
) -> exit_future::Signal {
    let log = log.new(o!("Service"=>"HTTP"));

    // Create:
    //  - `shutdown_trigger` a one-shot to shut down this service.
    //  - `wait_for_shutdown` a future that will wait until someone calls shutdown.
    let (shutdown_trigger, wait_for_shutdown) = exit_future::signal();

    // Create an `iron` http, without starting it yet.
    let iron = create_iron_http_server(beacon_chain);

    // Create a HTTP server future.
    //
    // 1. Start the HTTP server
    // 2. Build an exit future that will shutdown the server when requested.
    // 3. Return the exit future, so the caller may shutdown the service when desired.
    let http_service = {
        // Start the HTTP server
        let server_start_result = iron.http(config.listen_address.clone());

        if server_start_result.is_ok() {
            info!(log, "HTTP server running on {}", config.listen_address);
        } else {
            warn!(
                log,
                "HTTP server failed to start on {}", config.listen_address
            );
        }

        // Build a future that will shutdown the HTTP server when the `shutdown_trigger` is
        // triggered.
        wait_for_shutdown.and_then(move |_| {
            info!(log, "HTTP server shutting down");

            if let Ok(mut server) = server_start_result {
                // According to the documentation, `server.close()` "doesn't work" and the server
                // keeps listening.
                //
                // It is being called anyway, because it seems like the right thing to do. If you
                // know this has negative side-effects, please create an issue to discuss.
                //
                // See: https://docs.rs/iron/0.6.0/iron/struct.Listening.html#impl
                match server.close() {
                    _ => (),
                };
            }
            info!(log, "HTTP server shutdown complete.");
            Ok(())
        })
    };

    // Attach the HTTP server to the executor.
    executor.spawn(http_service);

    shutdown_trigger
}

/// Helper function for mapping a failure to read state to a 500 server error.
fn map_persistent_err_to_500(e: persistent::PersistentError) -> iron::error::IronError {
    iron::error::IronError {
        error: Box::new(e),
        response: iron::Response::with(iron::status::Status::InternalServerError),
    }
}
<commit_msg>Switch HTTP listen port to 5052<commit_after>mod api;
mod key;
mod metrics;

use beacon_chain::{BeaconChain, BeaconChainTypes};
use futures::Future;
use iron::prelude::*;
use network::NetworkMessage;
use router::Router;
use slog::{info, o, warn};
use std::sync::Arc;
use tokio::runtime::TaskExecutor;

#[derive(PartialEq, Clone, Debug)]
pub struct HttpServerConfig {
    pub enabled: bool,
    pub listen_address: String,
}

impl Default for HttpServerConfig {
    fn default() -> Self {
        Self {
            enabled: false,
            listen_address: "127.0.0.1:5052".to_string(),
        }
    }
}

/// Build the `iron` HTTP server, defining the core routes.
pub fn create_iron_http_server<T: BeaconChainTypes + 'static>(
    beacon_chain: Arc<BeaconChain<T>>,
) -> Iron<Router> {
    let mut router = Router::new();

    // A `GET` request to `/metrics` is handled by the `metrics` module.
    router.get(
        "/metrics",
        metrics::build_handler(beacon_chain.clone()),
        "metrics",
    );

    // Any request to all other endpoints is handled by the `api` module.
    router.any("/*", api::build_handler(beacon_chain.clone()), "api");

    Iron::new(router)
}

/// Start the HTTP service on the tokio `TaskExecutor`.
pub fn start_service<T: BeaconChainTypes + 'static>(
    config: &HttpServerConfig,
    executor: &TaskExecutor,
    _network_chan: crossbeam_channel::Sender<NetworkMessage>,
    beacon_chain: Arc<BeaconChain<T>>,
    log: &slog::Logger,
) -> exit_future::Signal {
    let log = log.new(o!("Service"=>"HTTP"));

    // Create:
    //  - `shutdown_trigger` a one-shot to shut down this service.
    //  - `wait_for_shutdown` a future that will wait until someone calls shutdown.
    let (shutdown_trigger, wait_for_shutdown) = exit_future::signal();

    // Create an `iron` http, without starting it yet.
    let iron = create_iron_http_server(beacon_chain);

    // Create a HTTP server future.
    //
    // 1. Start the HTTP server
    // 2. Build an exit future that will shutdown the server when requested.
    // 3. Return the exit future, so the caller may shutdown the service when desired.
    let http_service = {
        // Start the HTTP server
        let server_start_result = iron.http(config.listen_address.clone());

        if server_start_result.is_ok() {
            info!(log, "HTTP server running on {}", config.listen_address);
        } else {
            warn!(
                log,
                "HTTP server failed to start on {}", config.listen_address
            );
        }

        // Build a future that will shutdown the HTTP server when the `shutdown_trigger` is
        // triggered.
        wait_for_shutdown.and_then(move |_| {
            info!(log, "HTTP server shutting down");

            if let Ok(mut server) = server_start_result {
                // According to the documentation, `server.close()` "doesn't work" and the server
                // keeps listening.
                //
                // It is being called anyway, because it seems like the right thing to do. If you
                // know this has negative side-effects, please create an issue to discuss.
                //
                // See: https://docs.rs/iron/0.6.0/iron/struct.Listening.html#impl
                match server.close() {
                    _ => (),
                };
            }
            info!(log, "HTTP server shutdown complete.");
            Ok(())
        })
    };

    // Attach the HTTP server to the executor.
    executor.spawn(http_service);

    shutdown_trigger
}

/// Helper function for mapping a failure to read state to a 500 server error.
fn map_persistent_err_to_500(e: persistent::PersistentError) -> iron::error::IronError {
    iron::error::IronError {
        error: Box::new(e),
        response: iron::Response::with(iron::status::Status::InternalServerError),
    }
}
<|endoftext|>


<commit_before>//! Owned and borrowed file descriptors.

#![unstable(feature = "io_safety", issue = "87074")]

use super::raw::{AsRawFd, FromRawFd, IntoRawFd, RawFd};
use crate::fmt;
use crate::fs;
use crate::marker::PhantomData;
use crate::mem::forget;
use crate::os::raw;
use crate::sys_common::{AsInner, FromInner, IntoInner};

/// A borrowed file descriptor.
///
/// This has a lifetime parameter to tie it to the lifetime of something that
/// owns the file descriptor.
///
/// This uses `repr(transparent)` and has the representation of a host file
/// descriptor, so it can be used in FFI in places where a file descriptor is
/// passed as an argument, it is not captured or consumed, and it never has the
/// value `-1`.
#[derive(Copy, Clone)]
#[repr(transparent)]
#[rustc_layout_scalar_valid_range_start(0)]
// libstd/os/raw/mod.rs assures me that every libstd-supported platform has a
// 32-bit c_int. Below is -2, in two's complement, but that only works out
// because c_int is 32 bits.
#[rustc_layout_scalar_valid_range_end(0xFF_FF_FF_FE)]
#[unstable(feature = "io_safety", issue = "87074")]
pub struct BorrowedFd<'fd> {
    raw: RawFd,
    _phantom: PhantomData<&'fd OwnedFd>,
}

/// An owned file descriptor.
///
/// This closes the file descriptor on drop.
///
/// This uses `repr(transparent)` and has the representation of a host file
/// descriptor, so it can be used in FFI in places where a file descriptor is
/// passed as a consumed argument or returned as an owned value, and it never
/// has the value `-1`.
#[repr(transparent)]
#[rustc_layout_scalar_valid_range_start(0)]
// libstd/os/raw/mod.rs assures me that every libstd-supported platform has a
// 32-bit c_int. Below is -2, in two's complement, but that only works out
// because c_int is 32 bits.
#[rustc_layout_scalar_valid_range_end(0xFF_FF_FF_FE)]
#[unstable(feature = "io_safety", issue = "87074")]
pub struct OwnedFd {
    raw: RawFd,
}

impl BorrowedFd<'_> {
    /// Return a `BorrowedFd` holding the given raw file descriptor.
    ///
    /// # Safety
    ///
    /// The resource pointed to by `raw` must remain open for the duration of
    /// the returned `BorrowedFd`, and it must not have the value `-1`.
    #[inline]
    #[unstable(feature = "io_safety", issue = "87074")]
    pub unsafe fn borrow_raw_fd(raw: RawFd) -> Self {
        assert_ne!(raw, -1_i32 as RawFd);
        Self { raw, _phantom: PhantomData }
    }
}

#[unstable(feature = "io_safety", issue = "87074")]
impl AsRawFd for BorrowedFd<'_> {
    #[inline]
    fn as_raw_fd(&self) -> RawFd {
        self.raw
    }
}

#[unstable(feature = "io_safety", issue = "87074")]
impl AsRawFd for OwnedFd {
    #[inline]
    fn as_raw_fd(&self) -> RawFd {
        self.raw
    }
}

#[unstable(feature = "io_safety", issue = "87074")]
impl IntoRawFd for OwnedFd {
    #[inline]
    fn into_raw_fd(self) -> RawFd {
        let raw = self.raw;
        forget(self);
        raw
    }
}

#[unstable(feature = "io_safety", issue = "87074")]
impl FromRawFd for OwnedFd {
    /// Constructs a new instance of `Self` from the given raw file descriptor.
    ///
    /// # Safety
    ///
    /// The resource pointed to by `raw` must be open and suitable for assuming
    /// ownership.
    #[inline]
    unsafe fn from_raw_fd(raw: RawFd) -> Self {
        assert_ne!(raw, -1i32);
        // SAFETY: we just asserted that the value is in the valid range and isn't `-1` (the only value bigger than `0xFF_FF_FF_FE` unsigned)
        Self { raw }
    }
}

#[unstable(feature = "io_safety", issue = "87074")]
impl Drop for OwnedFd {
    #[inline]
    fn drop(&mut self) {
        unsafe {
            // Note that errors are ignored when closing a file descriptor. The
            // reason for this is that if an error occurs we don't actually know if
            // the file descriptor was closed or not, and if we retried (for
            // something like EINTR), we might close another valid file descriptor
            // opened after we closed ours.
            let _ = libc::close(self.raw as raw::c_int);
        }
    }
}

#[unstable(feature = "io_safety", issue = "87074")]
impl fmt::Debug for BorrowedFd<'_> {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        f.debug_struct("BorrowedFd").field("fd", &self.raw).finish()
    }
}

#[unstable(feature = "io_safety", issue = "87074")]
impl fmt::Debug for OwnedFd {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        f.debug_struct("OwnedFd").field("fd", &self.raw).finish()
    }
}

/// A trait to borrow the file descriptor from an underlying object.
///
/// This is only available on unix platforms and must be imported in order to
/// call the method. Windows platforms have a corresponding `AsHandle` and
/// `AsSocket` set of traits.
#[unstable(feature = "io_safety", issue = "87074")]
pub trait AsFd {
    /// Borrows the file descriptor.
    ///
    /// # Example
    ///
    /// ```rust,no_run
    /// #![feature(io_safety)]
    /// use std::fs::File;
    /// # use std::io;
    /// use std::os::unix::io::{AsFd, BorrowedFd};
    ///
    /// let mut f = File::open("foo.txt")?;
    /// let borrowed_fd: BorrowedFd<'_> = f.as_fd();
    /// # Ok::<(), io::Error>(())
    /// ```
    #[unstable(feature = "io_safety", issue = "87074")]
    fn as_fd(&self) -> BorrowedFd<'_>;
}

#[unstable(feature = "io_safety", issue = "87074")]
impl AsFd for BorrowedFd<'_> {
    #[inline]
    fn as_fd(&self) -> BorrowedFd<'_> {
        *self
    }
}

#[unstable(feature = "io_safety", issue = "87074")]
impl AsFd for OwnedFd {
    #[inline]
    fn as_fd(&self) -> BorrowedFd<'_> {
        unsafe { BorrowedFd::borrow_raw_fd(self.as_raw_fd()) }
    }
}

#[unstable(feature = "io_safety", issue = "87074")]
impl AsFd for fs::File {
    #[inline]
    fn as_fd(&self) -> BorrowedFd<'_> {
        self.as_inner().as_fd()
    }
}

#[unstable(feature = "io_safety", issue = "87074")]
impl From<fs::File> for OwnedFd {
    #[inline]
    fn from(file: fs::File) -> OwnedFd {
        file.into_inner().into_inner().into_inner()
    }
}

#[unstable(feature = "io_safety", issue = "87074")]
impl From<OwnedFd> for fs::File {
    #[inline]
    fn from(owned_fd: OwnedFd) -> Self {
        Self::from_inner(FromInner::from_inner(FromInner::from_inner(owned_fd)))
    }
}

#[unstable(feature = "io_safety", issue = "87074")]
impl AsFd for crate::net::TcpStream {
    #[inline]
    fn as_fd(&self) -> BorrowedFd<'_> {
        self.as_inner().socket().as_fd()
    }
}

#[unstable(feature = "io_safety", issue = "87074")]
impl From<crate::net::TcpStream> for OwnedFd {
    #[inline]
    fn from(tcp_stream: crate::net::TcpStream) -> OwnedFd {
        tcp_stream.into_inner().into_socket().into_inner().into_inner().into()
    }
}

#[unstable(feature = "io_safety", issue = "87074")]
impl From<OwnedFd> for crate::net::TcpStream {
    #[inline]
    fn from(owned_fd: OwnedFd) -> Self {
        Self::from_inner(FromInner::from_inner(FromInner::from_inner(FromInner::from_inner(
            owned_fd,
        ))))
    }
}

#[unstable(feature = "io_safety", issue = "87074")]
impl AsFd for crate::net::TcpListener {
    #[inline]
    fn as_fd(&self) -> BorrowedFd<'_> {
        self.as_inner().socket().as_fd()
    }
}

#[unstable(feature = "io_safety", issue = "87074")]
impl From<crate::net::TcpListener> for OwnedFd {
    #[inline]
    fn from(tcp_listener: crate::net::TcpListener) -> OwnedFd {
        tcp_listener.into_inner().into_socket().into_inner().into_inner().into()
    }
}

#[unstable(feature = "io_safety", issue = "87074")]
impl From<OwnedFd> for crate::net::TcpListener {
    #[inline]
    fn from(owned_fd: OwnedFd) -> Self {
        Self::from_inner(FromInner::from_inner(FromInner::from_inner(FromInner::from_inner(
            owned_fd,
        ))))
    }
}

#[unstable(feature = "io_safety", issue = "87074")]
impl AsFd for crate::net::UdpSocket {
    #[inline]
    fn as_fd(&self) -> BorrowedFd<'_> {
        self.as_inner().socket().as_fd()
    }
}

#[unstable(feature = "io_safety", issue = "87074")]
impl From<crate::net::UdpSocket> for OwnedFd {
    #[inline]
    fn from(udp_socket: crate::net::UdpSocket) -> OwnedFd {
        udp_socket.into_inner().into_socket().into_inner().into_inner().into()
    }
}

#[unstable(feature = "io_safety", issue = "87074")]
impl From<OwnedFd> for crate::net::UdpSocket {
    #[inline]
    fn from(owned_fd: OwnedFd) -> Self {
        Self::from_inner(FromInner::from_inner(FromInner::from_inner(FromInner::from_inner(
            owned_fd,
        ))))
    }
}

#[unstable(feature = "io_safety", issue = "87074")]
impl AsFd for crate::process::ChildStdin {
    #[inline]
    fn as_fd(&self) -> BorrowedFd<'_> {
        self.as_inner().as_fd()
    }
}

#[unstable(feature = "io_safety", issue = "87074")]
impl From<crate::process::ChildStdin> for OwnedFd {
    #[inline]
    fn from(child_stdin: crate::process::ChildStdin) -> OwnedFd {
        child_stdin.into_inner().into_inner().into_inner()
    }
}

#[unstable(feature = "io_safety", issue = "87074")]
impl AsFd for crate::process::ChildStdout {
    #[inline]
    fn as_fd(&self) -> BorrowedFd<'_> {
        self.as_inner().as_fd()
    }
}

#[unstable(feature = "io_safety", issue = "87074")]
impl From<crate::process::ChildStdout> for OwnedFd {
    #[inline]
    fn from(child_stdout: crate::process::ChildStdout) -> OwnedFd {
        child_stdout.into_inner().into_inner().into_inner()
    }
}

#[unstable(feature = "io_safety", issue = "87074")]
impl AsFd for crate::process::ChildStderr {
    #[inline]
    fn as_fd(&self) -> BorrowedFd<'_> {
        self.as_inner().as_fd()
    }
}

#[unstable(feature = "io_safety", issue = "87074")]
impl From<crate::process::ChildStderr> for OwnedFd {
    #[inline]
    fn from(child_stderr: crate::process::ChildStderr) -> OwnedFd {
        child_stderr.into_inner().into_inner().into_inner()
    }
}
<commit_msg>Update library/std/src/os/unix/io/fd.rs<commit_after>//! Owned and borrowed file descriptors.

#![unstable(feature = "io_safety", issue = "87074")]

use super::raw::{AsRawFd, FromRawFd, IntoRawFd, RawFd};
use crate::fmt;
use crate::fs;
use crate::marker::PhantomData;
use crate::mem::forget;
use crate::os::raw;
use crate::sys_common::{AsInner, FromInner, IntoInner};

/// A borrowed file descriptor.
///
/// This has a lifetime parameter to tie it to the lifetime of something that
/// owns the file descriptor.
///
/// This uses `repr(transparent)` and has the representation of a host file
/// descriptor, so it can be used in FFI in places where a file descriptor is
/// passed as an argument, it is not captured or consumed, and it never has the
/// value `-1`.
#[derive(Copy, Clone)]
#[repr(transparent)]
#[rustc_layout_scalar_valid_range_start(0)]
// libstd/os/raw/mod.rs assures me that every libstd-supported platform has a
// 32-bit c_int. Below is -2, in two's complement, but that only works out
// because c_int is 32 bits.
#[rustc_layout_scalar_valid_range_end(0xFF_FF_FF_FE)]
#[unstable(feature = "io_safety", issue = "87074")]
pub struct BorrowedFd<'fd> {
    raw: RawFd,
    _phantom: PhantomData<&'fd OwnedFd>,
}

/// An owned file descriptor.
///
/// This closes the file descriptor on drop.
///
/// This uses `repr(transparent)` and has the representation of a host file
/// descriptor, so it can be used in FFI in places where a file descriptor is
/// passed as a consumed argument or returned as an owned value, and it never
/// has the value `-1`.
#[repr(transparent)]
#[rustc_layout_scalar_valid_range_start(0)]
// libstd/os/raw/mod.rs assures me that every libstd-supported platform has a
// 32-bit c_int. Below is -2, in two's complement, but that only works out
// because c_int is 32 bits.
#[rustc_layout_scalar_valid_range_end(0xFF_FF_FF_FE)]
#[unstable(feature = "io_safety", issue = "87074")]
pub struct OwnedFd {
    raw: RawFd,
}

impl BorrowedFd<'_> {
    /// Return a `BorrowedFd` holding the given raw file descriptor.
    ///
    /// # Safety
    ///
    /// The resource pointed to by `raw` must remain open for the duration of
    /// the returned `BorrowedFd`, and it must not have the value `-1`.
    #[inline]
    #[unstable(feature = "io_safety", issue = "87074")]
    pub unsafe fn borrow_raw_fd(raw: RawFd) -> Self {
        assert_ne!(raw, -1_i32 as RawFd);
        Self { raw, _phantom: PhantomData }
    }
}

#[unstable(feature = "io_safety", issue = "87074")]
impl AsRawFd for BorrowedFd<'_> {
    #[inline]
    fn as_raw_fd(&self) -> RawFd {
        self.raw
    }
}

#[unstable(feature = "io_safety", issue = "87074")]
impl AsRawFd for OwnedFd {
    #[inline]
    fn as_raw_fd(&self) -> RawFd {
        self.raw
    }
}

#[unstable(feature = "io_safety", issue = "87074")]
impl IntoRawFd for OwnedFd {
    #[inline]
    fn into_raw_fd(self) -> RawFd {
        let raw = self.raw;
        forget(self);
        raw
    }
}

#[unstable(feature = "io_safety", issue = "87074")]
impl FromRawFd for OwnedFd {
    /// Constructs a new instance of `Self` from the given raw file descriptor.
    ///
    /// # Safety
    ///
    /// The resource pointed to by `raw` must be open and suitable for assuming
    /// ownership. The resource must not require any cleanup other than `close`.
    #[inline]
    unsafe fn from_raw_fd(raw: RawFd) -> Self {
        assert_ne!(raw, -1i32);
        // SAFETY: we just asserted that the value is in the valid range and isn't `-1` (the only value bigger than `0xFF_FF_FF_FE` unsigned)
        Self { raw }
    }
}

#[unstable(feature = "io_safety", issue = "87074")]
impl Drop for OwnedFd {
    #[inline]
    fn drop(&mut self) {
        unsafe {
            // Note that errors are ignored when closing a file descriptor. The
            // reason for this is that if an error occurs we don't actually know if
            // the file descriptor was closed or not, and if we retried (for
            // something like EINTR), we might close another valid file descriptor
            // opened after we closed ours.
            let _ = libc::close(self.raw as raw::c_int);
        }
    }
}

#[unstable(feature = "io_safety", issue = "87074")]
impl fmt::Debug for BorrowedFd<'_> {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        f.debug_struct("BorrowedFd").field("fd", &self.raw).finish()
    }
}

#[unstable(feature = "io_safety", issue = "87074")]
impl fmt::Debug for OwnedFd {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        f.debug_struct("OwnedFd").field("fd", &self.raw).finish()
    }
}

/// A trait to borrow the file descriptor from an underlying object.
///
/// This is only available on unix platforms and must be imported in order to
/// call the method. Windows platforms have a corresponding `AsHandle` and
/// `AsSocket` set of traits.
#[unstable(feature = "io_safety", issue = "87074")]
pub trait AsFd {
    /// Borrows the file descriptor.
    ///
    /// # Example
    ///
    /// ```rust,no_run
    /// #![feature(io_safety)]
    /// use std::fs::File;
    /// # use std::io;
    /// use std::os::unix::io::{AsFd, BorrowedFd};
    ///
    /// let mut f = File::open("foo.txt")?;
    /// let borrowed_fd: BorrowedFd<'_> = f.as_fd();
    /// # Ok::<(), io::Error>(())
    /// ```
    #[unstable(feature = "io_safety", issue = "87074")]
    fn as_fd(&self) -> BorrowedFd<'_>;
}

#[unstable(feature = "io_safety", issue = "87074")]
impl AsFd for BorrowedFd<'_> {
    #[inline]
    fn as_fd(&self) -> BorrowedFd<'_> {
        *self
    }
}

#[unstable(feature = "io_safety", issue = "87074")]
impl AsFd for OwnedFd {
    #[inline]
    fn as_fd(&self) -> BorrowedFd<'_> {
        unsafe { BorrowedFd::borrow_raw_fd(self.as_raw_fd()) }
    }
}

#[unstable(feature = "io_safety", issue = "87074")]
impl AsFd for fs::File {
    #[inline]
    fn as_fd(&self) -> BorrowedFd<'_> {
        self.as_inner().as_fd()
    }
}

#[unstable(feature = "io_safety", issue = "87074")]
impl From<fs::File> for OwnedFd {
    #[inline]
    fn from(file: fs::File) -> OwnedFd {
        file.into_inner().into_inner().into_inner()
    }
}

#[unstable(feature = "io_safety", issue = "87074")]
impl From<OwnedFd> for fs::File {
    #[inline]
    fn from(owned_fd: OwnedFd) -> Self {
        Self::from_inner(FromInner::from_inner(FromInner::from_inner(owned_fd)))
    }
}

#[unstable(feature = "io_safety", issue = "87074")]
impl AsFd for crate::net::TcpStream {
    #[inline]
    fn as_fd(&self) -> BorrowedFd<'_> {
        self.as_inner().socket().as_fd()
    }
}

#[unstable(feature = "io_safety", issue = "87074")]
impl From<crate::net::TcpStream> for OwnedFd {
    #[inline]
    fn from(tcp_stream: crate::net::TcpStream) -> OwnedFd {
        tcp_stream.into_inner().into_socket().into_inner().into_inner().into()
    }
}

#[unstable(feature = "io_safety", issue = "87074")]
impl From<OwnedFd> for crate::net::TcpStream {
    #[inline]
    fn from(owned_fd: OwnedFd) -> Self {
        Self::from_inner(FromInner::from_inner(FromInner::from_inner(FromInner::from_inner(
            owned_fd,
        ))))
    }
}

#[unstable(feature = "io_safety", issue = "87074")]
impl AsFd for crate::net::TcpListener {
    #[inline]
    fn as_fd(&self) -> BorrowedFd<'_> {
        self.as_inner().socket().as_fd()
    }
}

#[unstable(feature = "io_safety", issue = "87074")]
impl From<crate::net::TcpListener> for OwnedFd {
    #[inline]
    fn from(tcp_listener: crate::net::TcpListener) -> OwnedFd {
        tcp_listener.into_inner().into_socket().into_inner().into_inner().into()
    }
}

#[unstable(feature = "io_safety", issue = "87074")]
impl From<OwnedFd> for crate::net::TcpListener {
    #[inline]
    fn from(owned_fd: OwnedFd) -> Self {
        Self::from_inner(FromInner::from_inner(FromInner::from_inner(FromInner::from_inner(
            owned_fd,
        ))))
    }
}

#[unstable(feature = "io_safety", issue = "87074")]
impl AsFd for crate::net::UdpSocket {
    #[inline]
    fn as_fd(&self) -> BorrowedFd<'_> {
        self.as_inner().socket().as_fd()
    }
}

#[unstable(feature = "io_safety", issue = "87074")]
impl From<crate::net::UdpSocket> for OwnedFd {
    #[inline]
    fn from(udp_socket: crate::net::UdpSocket) -> OwnedFd {
        udp_socket.into_inner().into_socket().into_inner().into_inner().into()
    }
}

#[unstable(feature = "io_safety", issue = "87074")]
impl From<OwnedFd> for crate::net::UdpSocket {
    #[inline]
    fn from(owned_fd: OwnedFd) -> Self {
        Self::from_inner(FromInner::from_inner(FromInner::from_inner(FromInner::from_inner(
            owned_fd,
        ))))
    }
}

#[unstable(feature = "io_safety", issue = "87074")]
impl AsFd for crate::process::ChildStdin {
    #[inline]
    fn as_fd(&self) -> BorrowedFd<'_> {
        self.as_inner().as_fd()
    }
}

#[unstable(feature = "io_safety", issue = "87074")]
impl From<crate::process::ChildStdin> for OwnedFd {
    #[inline]
    fn from(child_stdin: crate::process::ChildStdin) -> OwnedFd {
        child_stdin.into_inner().into_inner().into_inner()
    }
}

#[unstable(feature = "io_safety", issue = "87074")]
impl AsFd for crate::process::ChildStdout {
    #[inline]
    fn as_fd(&self) -> BorrowedFd<'_> {
        self.as_inner().as_fd()
    }
}

#[unstable(feature = "io_safety", issue = "87074")]
impl From<crate::process::ChildStdout> for OwnedFd {
    #[inline]
    fn from(child_stdout: crate::process::ChildStdout) -> OwnedFd {
        child_stdout.into_inner().into_inner().into_inner()
    }
}

#[unstable(feature = "io_safety", issue = "87074")]
impl AsFd for crate::process::ChildStderr {
    #[inline]
    fn as_fd(&self) -> BorrowedFd<'_> {
        self.as_inner().as_fd()
    }
}

#[unstable(feature = "io_safety", issue = "87074")]
impl From<crate::process::ChildStderr> for OwnedFd {
    #[inline]
    fn from(child_stderr: crate::process::ChildStderr) -> OwnedFd {
        child_stderr.into_inner().into_inner().into_inner()
    }
}
<|endoftext|>


<commit_before>use handlebars::Template;
use std::collections::BTreeMap;

use super::ActionType;
use super::ExecCondition;

mod deser;
mod builder;

pub use self::builder::MessageActionBuilder;
pub const ON_CLOSED_DEFAULT: Option<bool> = Some(true);

#[derive(Clone, Debug, PartialEq)]
pub struct MessageAction {
    pub uuid: String,
    pub name: Option<String>,
    pub message: Template,
    pub values: BTreeMap<String, Template>,
    pub when: ExecCondition
}

impl MessageAction {
    pub fn uuid(&self) -> &String {
        &self.uuid
    }
    pub fn name(&self) -> Option<&String> {
        self.name.as_ref()
    }
    pub fn message(&self) -> &Template {
        &self.message
    }
    pub fn values(&self) -> &BTreeMap<String, Template> {
        &self.values
    }
}

impl From<MessageAction> for super::ActionType {
    fn from(action: MessageAction) -> super::ActionType {
        super::ActionType::Message(action)
    }
}
<commit_msg>MessageAction: remove unused constant<commit_after>use handlebars::Template;
use std::collections::BTreeMap;

use super::ActionType;
use super::ExecCondition;

mod deser;
mod builder;

pub use self::builder::MessageActionBuilder;

#[derive(Clone, Debug, PartialEq)]
pub struct MessageAction {
    pub uuid: String,
    pub name: Option<String>,
    pub message: Template,
    pub values: BTreeMap<String, Template>,
    pub when: ExecCondition
}

impl MessageAction {
    pub fn uuid(&self) -> &String {
        &self.uuid
    }
    pub fn name(&self) -> Option<&String> {
        self.name.as_ref()
    }
    pub fn message(&self) -> &Template {
        &self.message
    }
    pub fn values(&self) -> &BTreeMap<String, Template> {
        &self.values
    }
}

impl From<MessageAction> for super::ActionType {
    fn from(action: MessageAction) -> super::ActionType {
        super::ActionType::Message(action)
    }
}
<|endoftext|>