<commit_before>extern crate hmacsha1;

use std::fmt;

/// This implementation of HMAC-Based One Time Passwords proceeds in three stages, as per [RFC
/// 4226](https://www.ietf.org/rfc/rfc4226.txt):
///
/// 1. Generate an HMAC-SHA-1 value given a shared secret `key` and a moving factor `counter` that *should* change on
///    every use
/// 2. Extraction of an indexing offset by reading the 4 low-order bits of the last byte of the SHA-1 digest
/// 3. Extraction of a 4-byte value from the SHA-1 digest, starting at the index offset determined by the previous step
/// 4. Deriving a final HOTP value between 0 and 10^{`desired_code_length`} -1 from the 4-byte value extracted in the
///    previous step.
///
/// Note that it is the responsibility of the caller to increment the counter accordingly per invocation. Consider the
/// use of the [byteorder crate](https://crates.io/crates/byteorder) if you need to convert from a numeric type into the
/// array of 8 bytes that are expected by `hotp()`.
///
/// # Examples
///
/// To generate an HOTP value between 0 and 10^6 - 1, given the shared secret ASCII key `"Hello world!"` and current
/// counter `0`:
///
/// ```
/// let six_digit_result = rusthotp::hotp(6, "Hello world!".as_bytes(), &[0; 8]); assert_eq!(format!("{}",
/// six_digit_result), "124111");
/// ```
///
/// To generate an HOTP value between 0 and 10^8 - 1, given the shared secret ASCII key `"12345678901234567890"` and
/// current counter `1`:
///
/// ```
/// let eight_digit_result = rusthotp::hotp(8, "12345678901234567890".as_bytes(), &[0, 0, 0, 0, 0, 0, 0, 1]);
/// assert_eq!(format!("{}", eight_digit_result), "94287082");
/// ```
///
/// To generate an HOTP value between 0 and 10^6 - 1, given the shared secret ASCII key "Hello world!" and the unix
/// timestamp 1493006116 as the counter:
///
/// ```
/// # extern crate byteorder;
/// # extern crate rusthotp;
/// # fn main() {
/// use byteorder::{BigEndian, ByteOrder};
/// let timestamp : i64 = 1493006116;
/// let mut unpacked_timestamp = [0; 8];
/// BigEndian::write_i64(&mut unpacked_timestamp, timestamp);
/// let result = rusthotp::hotp(6, "Hello world!".as_bytes(), &unpacked_timestamp);
///
/// assert_eq!(format!("{}", result), "106286");
/// # }
/// ```

pub fn hotp(desired_code_length: usize, key: &[u8], counter: &[u8; 8]) -> HotpOutput {
    let hmac_value = hmacsha1::hmac_sha1(key, counter);
    let dbc = sbits(&hmac_value);
    HotpOutput{ code: dbc % 10u32.pow(desired_code_length as u32), length: desired_code_length }
}

fn offset(b: &[u8; hmacsha1::SHA1_DIGEST_BYTES]) -> usize {
    (b.last().unwrap() & 0xf) as usize
}

fn sbits(bits: &[u8; hmacsha1::SHA1_DIGEST_BYTES]) -> u32 {
    let offset = offset(bits);

    let mut val: u32 = 0;
    val += bits[offset + 3] as u32;
    val += (bits[offset + 2] as u32) << 8;
    val += (bits[offset + 1] as u32) << 16;
    val += ((bits[offset] as u32) & 0x7f) << 24;
    val
}

pub struct HotpOutput {
    pub code: u32,
    pub length: usize,
}

impl fmt::Display for HotpOutput {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "{:0length$}", self.code, length = self.length)
    }
}
<commit_msg>Improves the wording of the hotp docs<commit_after>extern crate hmacsha1;

use std::fmt;

/// This implementation of HMAC-Based One Time Passwords proceeds in three stages, as per [RFC
/// 4226](https://www.ietf.org/rfc/rfc4226.txt):
///
/// 1. Generate an HMAC-SHA-1 value given a shared secret `key` and a moving factor `counter` that *should* change on
///    every use
/// 2. Extraction of an indexing offset by reading the 4 low-order bits of the last byte of the SHA-1 digest
/// 3. Extraction of a 4-byte value from the SHA-1 digest, starting at the index offset determined by the previous step
/// 4. Deriving a final HOTP value between 0 and 10^{`desired_code_length`} -1 from the 4-byte value extracted in the
///    previous step.
///
/// Note that it is the responsibility of the caller to increment the counter accordingly per invocation. Consider the
/// use of the [byteorder crate](https://crates.io/crates/byteorder) if you need to convert from a numeric type into the
/// array of 8 bytes that are expected by `hotp()`.
///
/// # Examples
///
/// To generate a six-digit HOTP value (i.e. between 0 and 10^6 - 1), given the shared secret ASCII key `"Hello world!"`
/// and current counter `0`:
///
/// ```
/// let six_digit_result = rusthotp::hotp(6, "Hello world!".as_bytes(), &[0; 8]);
/// assert_eq!(format!("{}", six_digit_result), "124111");
/// ```
///
/// To generate an eight-digit HOTP value (i.e. between 0 and 10^8 - 1), given the shared secret ASCII key
/// `"12345678901234567890"` and current counter `1`:
///
/// ```
/// let eight_digit_result = rusthotp::hotp(8, "12345678901234567890".as_bytes(), &[0, 0, 0, 0, 0, 0, 0, 1]);
/// assert_eq!(format!("{}", eight_digit_result), "94287082");
/// ```
///
/// To generate a six-digit HOTP value given the shared secret ASCII key "Hello world!" and the unix timestamp
/// 1493006116 as the counter:
///
/// ```
/// # extern crate byteorder;
/// # extern crate rusthotp;
/// # fn main() {
/// use byteorder::{BigEndian, ByteOrder};
/// let timestamp : i64 = 1493006116;
/// let mut unpacked_timestamp = [0; 8];
/// BigEndian::write_i64(&mut unpacked_timestamp, timestamp);
/// let result = rusthotp::hotp(6, "Hello world!".as_bytes(), &unpacked_timestamp);
///
/// assert_eq!(format!("{}", result), "106286");
/// # }
/// ```

pub fn hotp(desired_code_length: usize, key: &[u8], counter: &[u8; 8]) -> HotpOutput {
    let hmac_value = hmacsha1::hmac_sha1(key, counter);
    let dbc = sbits(&hmac_value);
    HotpOutput{ code: dbc % 10u32.pow(desired_code_length as u32), length: desired_code_length }
}

fn offset(b: &[u8; hmacsha1::SHA1_DIGEST_BYTES]) -> usize {
    (b.last().unwrap() & 0xf) as usize
}

fn sbits(bits: &[u8; hmacsha1::SHA1_DIGEST_BYTES]) -> u32 {
    let offset = offset(bits);

    let mut val: u32 = 0;
    val += bits[offset + 3] as u32;
    val += (bits[offset + 2] as u32) << 8;
    val += (bits[offset + 1] as u32) << 16;
    val += ((bits[offset] as u32) & 0x7f) << 24;
    val
}

pub struct HotpOutput {
    pub code: u32,
    pub length: usize,
}

impl fmt::Display for HotpOutput {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "{:0length$}", self.code, length = self.length)
    }
}
<|endoftext|>


<commit_before>/*---------------------------------------------------------------------------------------------
 *  Copyright (c) Microsoft Corporation. All rights reserved.
 *  Licensed under the MIT License. See License.txt in the project root for license information.
 *--------------------------------------------------------------------------------------------*/

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

use async_trait::async_trait;
use tokio::sync::mpsc;

use crate::commands::tunnels::ShutdownSignal;
use crate::log;
use crate::state::LauncherPaths;
use crate::util::errors::{wrap, AnyError};
use crate::util::io::{tailf, TailEvent};

pub const SERVICE_LOG_FILE_NAME: &str = "tunnel-service.log";

#[async_trait]
pub trait ServiceContainer: Send {
	async fn run_service(
		&mut self,
		log: log::Logger,
		launcher_paths: LauncherPaths,
		shutdown_rx: mpsc::UnboundedReceiver<ShutdownSignal>,
	) -> Result<(), AnyError>;
}

#[async_trait]
pub trait ServiceManager {
	/// Registers the current executable as a service to run with the given set
	/// of arguments.
	async fn register(&self, exe: PathBuf, args: &[&str]) -> Result<(), AnyError>;

	/// Runs the service using the given handle. The executable *must not* take
	/// any action which may fail prior to calling this to ensure service
	/// states may update.
	async fn run(
		self,
		launcher_paths: LauncherPaths,
		handle: impl 'static + ServiceContainer,
	) -> Result<(), AnyError>;

	/// Show logs from the running service to standard out.
	async fn show_logs(&self) -> Result<(), AnyError>;

	/// Unregisters the current executable as a service.
	async fn unregister(&self) -> Result<(), AnyError>;
}

#[cfg(target_os = "windows")]
pub type ServiceManagerImpl = super::service_windows::WindowsService;

#[cfg(target_os = "linux")]
pub type ServiceManagerImpl = super::service_linux::SystemdService;

#[cfg(target_os = "macos")]
pub type ServiceManagerImpl = super::service_macos::LaunchdService;

#[allow(unreachable_code)]
#[allow(unused_variables)]
pub fn create_service_manager(log: log::Logger, paths: &LauncherPaths) -> ServiceManagerImpl {
	#[cfg(target_os = "macos")]
	{
		super::service_macos::LaunchdService::new(log, paths)
	}
	#[cfg(target_os = "windows")]
	{
		super::service_windows::WindowsService::new(log, paths)
	}
	#[cfg(target_os = "linux")]
	{
		super::service_linux::SystemdService::new(log, paths.clone())
	}
}

pub(crate) async fn tail_log_file(log_file: &Path) -> Result<(), AnyError> {
	if !log_file.exists() {
		println!("The tunnel service has not started yet.");
		return Ok(());
	}

	let file = std::fs::File::open(&log_file).map_err(|e| wrap(e, "error opening log file"))?;
	let mut rx = tailf(file, 20);
	while let Some(line) = rx.recv().await {
		match line {
			TailEvent::Line(l) => print!("{}", l),
			TailEvent::Reset => println!("== Tunnel service restarted =="),
			TailEvent::Err(e) => return Err(wrap(e, "error reading log file").into()),
		}
	}

	Ok(())
}
<commit_msg>clippy fixes<commit_after>/*---------------------------------------------------------------------------------------------
 *  Copyright (c) Microsoft Corporation. All rights reserved.
 *  Licensed under the MIT License. See License.txt in the project root for license information.
 *--------------------------------------------------------------------------------------------*/

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

use async_trait::async_trait;
use tokio::sync::mpsc;

use crate::commands::tunnels::ShutdownSignal;
use crate::log;
use crate::state::LauncherPaths;
use crate::util::errors::{wrap, AnyError};
use crate::util::io::{tailf, TailEvent};

pub const SERVICE_LOG_FILE_NAME: &str = "tunnel-service.log";

#[async_trait]
pub trait ServiceContainer: Send {
	async fn run_service(
		&mut self,
		log: log::Logger,
		launcher_paths: LauncherPaths,
		shutdown_rx: mpsc::UnboundedReceiver<ShutdownSignal>,
	) -> Result<(), AnyError>;
}

#[async_trait]
pub trait ServiceManager {
	/// Registers the current executable as a service to run with the given set
	/// of arguments.
	async fn register(&self, exe: PathBuf, args: &[&str]) -> Result<(), AnyError>;

	/// Runs the service using the given handle. The executable *must not* take
	/// any action which may fail prior to calling this to ensure service
	/// states may update.
	async fn run(
		self,
		launcher_paths: LauncherPaths,
		handle: impl 'static + ServiceContainer,
	) -> Result<(), AnyError>;

	/// Show logs from the running service to standard out.
	async fn show_logs(&self) -> Result<(), AnyError>;

	/// Unregisters the current executable as a service.
	async fn unregister(&self) -> Result<(), AnyError>;
}

#[cfg(target_os = "windows")]
pub type ServiceManagerImpl = super::service_windows::WindowsService;

#[cfg(target_os = "linux")]
pub type ServiceManagerImpl = super::service_linux::SystemdService;

#[cfg(target_os = "macos")]
pub type ServiceManagerImpl = super::service_macos::LaunchdService;

#[allow(unreachable_code)]
#[allow(unused_variables)]
pub fn create_service_manager(log: log::Logger, paths: &LauncherPaths) -> ServiceManagerImpl {
	#[cfg(target_os = "macos")]
	{
		super::service_macos::LaunchdService::new(log, paths)
	}
	#[cfg(target_os = "windows")]
	{
		super::service_windows::WindowsService::new(log, paths)
	}
	#[cfg(target_os = "linux")]
	{
		super::service_linux::SystemdService::new(log, paths.clone())
	}
}

#[allow(dead_code)] // unused on Linux
pub(crate) async fn tail_log_file(log_file: &Path) -> Result<(), AnyError> {
	if !log_file.exists() {
		println!("The tunnel service has not started yet.");
		return Ok(());
	}

	let file = std::fs::File::open(log_file).map_err(|e| wrap(e, "error opening log file"))?;
	let mut rx = tailf(file, 20);
	while let Some(line) = rx.recv().await {
		match line {
			TailEvent::Line(l) => print!("{}", l),
			TailEvent::Reset => println!("== Tunnel service restarted =="),
			TailEvent::Err(e) => return Err(wrap(e, "error reading log file").into()),
		}
	}

	Ok(())
}
<|endoftext|>


<commit_before>use crate::reexport::*;
use crate::utils::{contains_name, higher, iter_input_pats, snippet, span_lint_and_then};
use rustc::hir::intravisit::FnKind;
use rustc::hir::*;
use rustc::lint::{in_external_macro, LateContext, LateLintPass, LintArray, LintContext, LintPass};
use rustc::ty;
use rustc::{declare_lint_pass, declare_tool_lint};
use syntax::source_map::Span;

declare_clippy_lint! {
    /// **What it does:** Checks for bindings that shadow other bindings already in
    /// scope, while just changing reference level or mutability.
    ///
    /// **Why is this bad?** Not much, in fact it's a very common pattern in Rust
    /// code. Still, some may opt to avoid it in their code base, they can set this
    /// lint to `Warn`.
    ///
    /// **Known problems:** This lint, as the other shadowing related lints,
    /// currently only catches very simple patterns.
    ///
    /// **Example:**
    /// ```rust
    /// let x = &x;
    /// ```
    pub SHADOW_SAME,
    restriction,
    "rebinding a name to itself, e.g., `let mut x = &mut x`"
}

declare_clippy_lint! {
    /// **What it does:** Checks for bindings that shadow other bindings already in
    /// scope, while reusing the original value.
    ///
    /// **Why is this bad?** Not too much, in fact it's a common pattern in Rust
    /// code. Still, some argue that name shadowing like this hurts readability,
    /// because a value may be bound to different things depending on position in
    /// the code.
    ///
    /// **Known problems:** This lint, as the other shadowing related lints,
    /// currently only catches very simple patterns.
    ///
    /// **Example:**
    /// ```rust
    /// let x = x + 1;
    /// ```
    /// use different variable name:
    /// ```rust
    /// let y = x + 1;
    /// ```
    pub SHADOW_REUSE,
    restriction,
    "rebinding a name to an expression that re-uses the original value, e.g., `let x = x + 1`"
}

declare_clippy_lint! {
    /// **What it does:** Checks for bindings that shadow other bindings already in
    /// scope, either without a initialization or with one that does not even use
    /// the original value.
    ///
    /// **Why is this bad?** Name shadowing can hurt readability, especially in
    /// large code bases, because it is easy to lose track of the active binding at
    /// any place in the code. This can be alleviated by either giving more specific
    /// names to bindings or introducing more scopes to contain the bindings.
    ///
    /// **Known problems:** This lint, as the other shadowing related lints,
    /// currently only catches very simple patterns.
    ///
    /// **Example:**
    /// ```rust
    /// let x = y;
    /// let x = z; // shadows the earlier binding
    /// ```
    pub SHADOW_UNRELATED,
    pedantic,
    "rebinding a name without even using the original value"
}

declare_lint_pass!(Shadow => [SHADOW_SAME, SHADOW_REUSE, SHADOW_UNRELATED]);

impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Shadow {
    fn check_fn(
        &mut self,
        cx: &LateContext<'a, 'tcx>,
        _: FnKind<'tcx>,
        decl: &'tcx FnDecl,
        body: &'tcx Body,
        _: Span,
        _: HirId,
    ) {
        if in_external_macro(cx.sess(), body.value.span) {
            return;
        }
        check_fn(cx, decl, body);
    }
}

fn check_fn<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, decl: &'tcx FnDecl, body: &'tcx Body) {
    let mut bindings = Vec::new();
    for arg in iter_input_pats(decl, body) {
        if let PatKind::Binding(.., ident, _) = arg.pat.node {
            bindings.push((ident.name, ident.span))
        }
    }
    check_expr(cx, &body.value, &mut bindings);
}

fn check_block<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, block: &'tcx Block, bindings: &mut Vec<(Name, Span)>) {
    let len = bindings.len();
    for stmt in &block.stmts {
        match stmt.node {
            StmtKind::Local(ref local) => check_local(cx, local, bindings),
            StmtKind::Expr(ref e) | StmtKind::Semi(ref e) => check_expr(cx, e, bindings),
            StmtKind::Item(..) => {},
        }
    }
    if let Some(ref o) = block.expr {
        check_expr(cx, o, bindings);
    }
    bindings.truncate(len);
}

fn check_local<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, local: &'tcx Local, bindings: &mut Vec<(Name, Span)>) {
    if in_external_macro(cx.sess(), local.span) {
        return;
    }
    if higher::is_from_for_desugar(local) {
        return;
    }
    let Local {
        ref pat,
        ref ty,
        ref init,
        span,
        ..
    } = *local;
    if let Some(ref t) = *ty {
        check_ty(cx, t, bindings)
    }
    if let Some(ref o) = *init {
        check_expr(cx, o, bindings);
        check_pat(cx, pat, Some(o), span, bindings);
    } else {
        check_pat(cx, pat, None, span, bindings);
    }
}

fn is_binding(cx: &LateContext<'_, '_>, pat_id: HirId) -> bool {
    let var_ty = cx.tables.node_type(pat_id);
    match var_ty.sty {
        ty::Adt(..) => false,
        _ => true,
    }
}

fn check_pat<'a, 'tcx>(
    cx: &LateContext<'a, 'tcx>,
    pat: &'tcx Pat,
    init: Option<&'tcx Expr>,
    span: Span,
    bindings: &mut Vec<(Name, Span)>,
) {
    // TODO: match more stuff / destructuring
    match pat.node {
        PatKind::Binding(.., ident, ref inner) => {
            let name = ident.name;
            if is_binding(cx, pat.hir_id) {
                let mut new_binding = true;
                for tup in bindings.iter_mut() {
                    if tup.0 == name {
                        lint_shadow(cx, name, span, pat.span, init, tup.1);
                        tup.1 = ident.span;
                        new_binding = false;
                        break;
                    }
                }
                if new_binding {
                    bindings.push((name, ident.span));
                }
            }
            if let Some(ref p) = *inner {
                check_pat(cx, p, init, span, bindings);
            }
        },
        PatKind::Struct(_, ref pfields, _) => {
            if let Some(init_struct) = init {
                if let ExprKind::Struct(_, ref efields, _) = init_struct.node {
                    for field in pfields {
                        let name = field.node.ident.name;
                        let efield = efields
                            .iter()
                            .find_map(|f| if f.ident.name == name { Some(&*f.expr) } else { None });
                        check_pat(cx, &field.node.pat, efield, span, bindings);
                    }
                } else {
                    for field in pfields {
                        check_pat(cx, &field.node.pat, init, span, bindings);
                    }
                }
            } else {
                for field in pfields {
                    check_pat(cx, &field.node.pat, None, span, bindings);
                }
            }
        },
        PatKind::Tuple(ref inner, _) => {
            if let Some(init_tup) = init {
                if let ExprKind::Tup(ref tup) = init_tup.node {
                    for (i, p) in inner.iter().enumerate() {
                        check_pat(cx, p, Some(&tup[i]), p.span, bindings);
                    }
                } else {
                    for p in inner {
                        check_pat(cx, p, init, span, bindings);
                    }
                }
            } else {
                for p in inner {
                    check_pat(cx, p, None, span, bindings);
                }
            }
        },
        PatKind::Box(ref inner) => {
            if let Some(initp) = init {
                if let ExprKind::Box(ref inner_init) = initp.node {
                    check_pat(cx, inner, Some(&**inner_init), span, bindings);
                } else {
                    check_pat(cx, inner, init, span, bindings);
                }
            } else {
                check_pat(cx, inner, init, span, bindings);
            }
        },
        PatKind::Ref(ref inner, _) => check_pat(cx, inner, init, span, bindings),
        // PatVec(Vec<P<Pat>>, Option<P<Pat>>, Vec<P<Pat>>),
        _ => (),
    }
}

fn lint_shadow<'a, 'tcx: 'a>(
    cx: &LateContext<'a, 'tcx>,
    name: Name,
    span: Span,
    pattern_span: Span,
    init: Option<&'tcx Expr>,
    prev_span: Span,
) {
    if let Some(expr) = init {
        if is_self_shadow(name, expr) {
            span_lint_and_then(
                cx,
                SHADOW_SAME,
                span,
                &format!(
                    "`{}` is shadowed by itself in `{}`",
                    snippet(cx, pattern_span, "_"),
                    snippet(cx, expr.span, "..")
                ),
                |db| {
                    db.span_note(prev_span, "previous binding is here");
                },
            );
        } else if contains_name(name, expr) {
            span_lint_and_then(
                cx,
                SHADOW_REUSE,
                pattern_span,
                &format!(
                    "`{}` is shadowed by `{}` which reuses the original value",
                    snippet(cx, pattern_span, "_"),
                    snippet(cx, expr.span, "..")
                ),
                |db| {
                    db.span_note(expr.span, "initialization happens here");
                    db.span_note(prev_span, "previous binding is here");
                },
            );
        } else {
            span_lint_and_then(
                cx,
                SHADOW_UNRELATED,
                pattern_span,
                &format!(
                    "`{}` is shadowed by `{}`",
                    snippet(cx, pattern_span, "_"),
                    snippet(cx, expr.span, "..")
                ),
                |db| {
                    db.span_note(expr.span, "initialization happens here");
                    db.span_note(prev_span, "previous binding is here");
                },
            );
        }
    } else {
        span_lint_and_then(
            cx,
            SHADOW_UNRELATED,
            span,
            &format!("`{}` shadows a previous declaration", snippet(cx, pattern_span, "_")),
            |db| {
                db.span_note(prev_span, "previous binding is here");
            },
        );
    }
}

fn check_expr<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, expr: &'tcx Expr, bindings: &mut Vec<(Name, Span)>) {
    if in_external_macro(cx.sess(), expr.span) {
        return;
    }
    match expr.node {
        ExprKind::Unary(_, ref e) | ExprKind::Field(ref e, _) | ExprKind::AddrOf(_, ref e) | ExprKind::Box(ref e) => {
            check_expr(cx, e, bindings)
        },
        ExprKind::Block(ref block, _) | ExprKind::Loop(ref block, _, _) => check_block(cx, block, bindings),
        // ExprKind::Call
        // ExprKind::MethodCall
        ExprKind::Array(ref v) | ExprKind::Tup(ref v) => {
            for e in v {
                check_expr(cx, e, bindings)
            }
        },
        ExprKind::If(ref cond, ref then, ref otherwise) => {
            check_expr(cx, cond, bindings);
            check_expr(cx, &**then, bindings);
            if let Some(ref o) = *otherwise {
                check_expr(cx, o, bindings);
            }
        },
        ExprKind::While(ref cond, ref block, _) => {
            check_expr(cx, cond, bindings);
            check_block(cx, block, bindings);
        },
        ExprKind::Match(ref init, ref arms, _) => {
            check_expr(cx, init, bindings);
            let len = bindings.len();
            for arm in arms {
                for pat in &arm.pats {
                    check_pat(cx, pat, Some(&**init), pat.span, bindings);
                    // This is ugly, but needed to get the right type
                    if let Some(ref guard) = arm.guard {
                        match guard {
                            Guard::If(if_expr) => check_expr(cx, if_expr, bindings),
                        }
                    }
                    check_expr(cx, &arm.body, bindings);
                    bindings.truncate(len);
                }
            }
        },
        _ => (),
    }
}

fn check_ty<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, ty: &'tcx Ty, bindings: &mut Vec<(Name, Span)>) {
    match ty.node {
        TyKind::Slice(ref sty) => check_ty(cx, sty, bindings),
        TyKind::Array(ref fty, ref anon_const) => {
            check_ty(cx, fty, bindings);
            check_expr(cx, &cx.tcx.hir().body(anon_const.body).value, bindings);
        },
        TyKind::Ptr(MutTy { ty: ref mty, .. }) | TyKind::Rptr(_, MutTy { ty: ref mty, .. }) => {
            check_ty(cx, mty, bindings)
        },
        TyKind::Tup(ref tup) => {
            for t in tup {
                check_ty(cx, t, bindings)
            }
        },
        TyKind::Typeof(ref anon_const) => check_expr(cx, &cx.tcx.hir().body(anon_const.body).value, bindings),
        _ => (),
    }
}

fn is_self_shadow(name: Name, expr: &Expr) -> bool {
    match expr.node {
        ExprKind::Box(ref inner) | ExprKind::AddrOf(_, ref inner) => is_self_shadow(name, inner),
        ExprKind::Block(ref block, _) => {
            block.stmts.is_empty() && block.expr.as_ref().map_or(false, |e| is_self_shadow(name, e))
        },
        ExprKind::Unary(op, ref inner) => (UnDeref == op) && is_self_shadow(name, inner),
        ExprKind::Path(QPath::Resolved(_, ref path)) => path_eq_name(name, path),
        _ => false,
    }
}

fn path_eq_name(name: Name, path: &Path) -> bool {
    !path.is_global() && path.segments.len() == 1 && path.segments[0].ident.as_str() == name.as_str()
}
<commit_msg>Fix shadow.rs<commit_after>use crate::reexport::*;
use crate::utils::{contains_name, higher, iter_input_pats, snippet, span_lint_and_then};
use rustc::hir::intravisit::FnKind;
use rustc::hir::*;
use rustc::lint::{in_external_macro, LateContext, LateLintPass, LintArray, LintContext, LintPass};
use rustc::ty;
use rustc::{declare_lint_pass, declare_tool_lint};
use syntax::source_map::Span;

declare_clippy_lint! {
    /// **What it does:** Checks for bindings that shadow other bindings already in
    /// scope, while just changing reference level or mutability.
    ///
    /// **Why is this bad?** Not much, in fact it's a very common pattern in Rust
    /// code. Still, some may opt to avoid it in their code base, they can set this
    /// lint to `Warn`.
    ///
    /// **Known problems:** This lint, as the other shadowing related lints,
    /// currently only catches very simple patterns.
    ///
    /// **Example:**
    /// ```rust
    /// let x = &x;
    /// ```
    pub SHADOW_SAME,
    restriction,
    "rebinding a name to itself, e.g., `let mut x = &mut x`"
}

declare_clippy_lint! {
    /// **What it does:** Checks for bindings that shadow other bindings already in
    /// scope, while reusing the original value.
    ///
    /// **Why is this bad?** Not too much, in fact it's a common pattern in Rust
    /// code. Still, some argue that name shadowing like this hurts readability,
    /// because a value may be bound to different things depending on position in
    /// the code.
    ///
    /// **Known problems:** This lint, as the other shadowing related lints,
    /// currently only catches very simple patterns.
    ///
    /// **Example:**
    /// ```rust
    /// let x = x + 1;
    /// ```
    /// use different variable name:
    /// ```rust
    /// let y = x + 1;
    /// ```
    pub SHADOW_REUSE,
    restriction,
    "rebinding a name to an expression that re-uses the original value, e.g., `let x = x + 1`"
}

declare_clippy_lint! {
    /// **What it does:** Checks for bindings that shadow other bindings already in
    /// scope, either without a initialization or with one that does not even use
    /// the original value.
    ///
    /// **Why is this bad?** Name shadowing can hurt readability, especially in
    /// large code bases, because it is easy to lose track of the active binding at
    /// any place in the code. This can be alleviated by either giving more specific
    /// names to bindings or introducing more scopes to contain the bindings.
    ///
    /// **Known problems:** This lint, as the other shadowing related lints,
    /// currently only catches very simple patterns.
    ///
    /// **Example:**
    /// ```rust
    /// let x = y;
    /// let x = z; // shadows the earlier binding
    /// ```
    pub SHADOW_UNRELATED,
    pedantic,
    "rebinding a name without even using the original value"
}

declare_lint_pass!(Shadow => [SHADOW_SAME, SHADOW_REUSE, SHADOW_UNRELATED]);

impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Shadow {
    fn check_fn(
        &mut self,
        cx: &LateContext<'a, 'tcx>,
        _: FnKind<'tcx>,
        decl: &'tcx FnDecl,
        body: &'tcx Body,
        _: Span,
        _: HirId,
    ) {
        if in_external_macro(cx.sess(), body.value.span) {
            return;
        }
        check_fn(cx, decl, body);
    }
}

fn check_fn<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, decl: &'tcx FnDecl, body: &'tcx Body) {
    let mut bindings = Vec::new();
    for arg in iter_input_pats(decl, body) {
        if let PatKind::Binding(.., ident, _) = arg.pat.node {
            bindings.push((ident.name, ident.span))
        }
    }
    check_expr(cx, &body.value, &mut bindings);
}

fn check_block<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, block: &'tcx Block, bindings: &mut Vec<(Name, Span)>) {
    let len = bindings.len();
    for stmt in &block.stmts {
        match stmt.node {
            StmtKind::Local(ref local) => check_local(cx, local, bindings),
            StmtKind::Expr(ref e) | StmtKind::Semi(ref e) => check_expr(cx, e, bindings),
            StmtKind::Item(..) => {},
        }
    }
    if let Some(ref o) = block.expr {
        check_expr(cx, o, bindings);
    }
    bindings.truncate(len);
}

fn check_local<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, local: &'tcx Local, bindings: &mut Vec<(Name, Span)>) {
    if in_external_macro(cx.sess(), local.span) {
        return;
    }
    if higher::is_from_for_desugar(local) {
        return;
    }
    let Local {
        ref pat,
        ref ty,
        ref init,
        span,
        ..
    } = *local;
    if let Some(ref t) = *ty {
        check_ty(cx, t, bindings)
    }
    if let Some(ref o) = *init {
        check_expr(cx, o, bindings);
        check_pat(cx, pat, Some(o), span, bindings);
    } else {
        check_pat(cx, pat, None, span, bindings);
    }
}

fn is_binding(cx: &LateContext<'_, '_>, pat_id: HirId) -> bool {
    let var_ty = cx.tables.node_type(pat_id);
    match var_ty.sty {
        ty::Adt(..) => false,
        _ => true,
    }
}

fn check_pat<'a, 'tcx>(
    cx: &LateContext<'a, 'tcx>,
    pat: &'tcx Pat,
    init: Option<&'tcx Expr>,
    span: Span,
    bindings: &mut Vec<(Name, Span)>,
) {
    // TODO: match more stuff / destructuring
    match pat.node {
        PatKind::Binding(.., ident, ref inner) => {
            let name = ident.name;
            if is_binding(cx, pat.hir_id) {
                let mut new_binding = true;
                for tup in bindings.iter_mut() {
                    if tup.0 == name {
                        lint_shadow(cx, name, span, pat.span, init, tup.1);
                        tup.1 = ident.span;
                        new_binding = false;
                        break;
                    }
                }
                if new_binding {
                    bindings.push((name, ident.span));
                }
            }
            if let Some(ref p) = *inner {
                check_pat(cx, p, init, span, bindings);
            }
        },
        PatKind::Struct(_, ref pfields, _) => {
            if let Some(init_struct) = init {
                if let ExprKind::Struct(_, ref efields, _) = init_struct.node {
                    for field in pfields {
                        let name = field.node.ident.name;
                        let efield = efields
                            .iter()
                            .find_map(|f| if f.ident.name == name { Some(&*f.expr) } else { None });
                        check_pat(cx, &field.node.pat, efield, span, bindings);
                    }
                } else {
                    for field in pfields {
                        check_pat(cx, &field.node.pat, init, span, bindings);
                    }
                }
            } else {
                for field in pfields {
                    check_pat(cx, &field.node.pat, None, span, bindings);
                }
            }
        },
        PatKind::Tuple(ref inner, _) => {
            if let Some(init_tup) = init {
                if let ExprKind::Tup(ref tup) = init_tup.node {
                    for (i, p) in inner.iter().enumerate() {
                        check_pat(cx, p, Some(&tup[i]), p.span, bindings);
                    }
                } else {
                    for p in inner {
                        check_pat(cx, p, init, span, bindings);
                    }
                }
            } else {
                for p in inner {
                    check_pat(cx, p, None, span, bindings);
                }
            }
        },
        PatKind::Box(ref inner) => {
            if let Some(initp) = init {
                if let ExprKind::Box(ref inner_init) = initp.node {
                    check_pat(cx, inner, Some(&**inner_init), span, bindings);
                } else {
                    check_pat(cx, inner, init, span, bindings);
                }
            } else {
                check_pat(cx, inner, init, span, bindings);
            }
        },
        PatKind::Ref(ref inner, _) => check_pat(cx, inner, init, span, bindings),
        // PatVec(Vec<P<Pat>>, Option<P<Pat>>, Vec<P<Pat>>),
        _ => (),
    }
}

fn lint_shadow<'a, 'tcx: 'a>(
    cx: &LateContext<'a, 'tcx>,
    name: Name,
    span: Span,
    pattern_span: Span,
    init: Option<&'tcx Expr>,
    prev_span: Span,
) {
    if let Some(expr) = init {
        if is_self_shadow(name, expr) {
            span_lint_and_then(
                cx,
                SHADOW_SAME,
                span,
                &format!(
                    "`{}` is shadowed by itself in `{}`",
                    snippet(cx, pattern_span, "_"),
                    snippet(cx, expr.span, "..")
                ),
                |db| {
                    db.span_note(prev_span, "previous binding is here");
                },
            );
        } else if contains_name(name, expr) {
            span_lint_and_then(
                cx,
                SHADOW_REUSE,
                pattern_span,
                &format!(
                    "`{}` is shadowed by `{}` which reuses the original value",
                    snippet(cx, pattern_span, "_"),
                    snippet(cx, expr.span, "..")
                ),
                |db| {
                    db.span_note(expr.span, "initialization happens here");
                    db.span_note(prev_span, "previous binding is here");
                },
            );
        } else {
            span_lint_and_then(
                cx,
                SHADOW_UNRELATED,
                pattern_span,
                &format!(
                    "`{}` is shadowed by `{}`",
                    snippet(cx, pattern_span, "_"),
                    snippet(cx, expr.span, "..")
                ),
                |db| {
                    db.span_note(expr.span, "initialization happens here");
                    db.span_note(prev_span, "previous binding is here");
                },
            );
        }
    } else {
        span_lint_and_then(
            cx,
            SHADOW_UNRELATED,
            span,
            &format!("`{}` shadows a previous declaration", snippet(cx, pattern_span, "_")),
            |db| {
                db.span_note(prev_span, "previous binding is here");
            },
        );
    }
}

fn check_expr<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, expr: &'tcx Expr, bindings: &mut Vec<(Name, Span)>) {
    if in_external_macro(cx.sess(), expr.span) {
        return;
    }
    match expr.node {
        ExprKind::Unary(_, ref e) | ExprKind::Field(ref e, _) | ExprKind::AddrOf(_, ref e) | ExprKind::Box(ref e) => {
            check_expr(cx, e, bindings)
        },
        ExprKind::Block(ref block, _) | ExprKind::Loop(ref block, _, _) => check_block(cx, block, bindings),
        // ExprKind::Call
        // ExprKind::MethodCall
        ExprKind::Array(ref v) | ExprKind::Tup(ref v) => {
            for e in v {
                check_expr(cx, e, bindings)
            }
        },
        ExprKind::While(ref cond, ref block, _) => {
            check_expr(cx, cond, bindings);
            check_block(cx, block, bindings);
        },
        ExprKind::Match(ref init, ref arms, _) => {
            check_expr(cx, init, bindings);
            let len = bindings.len();
            for arm in arms {
                for pat in &arm.pats {
                    check_pat(cx, pat, Some(&**init), pat.span, bindings);
                    // This is ugly, but needed to get the right type
                    if let Some(ref guard) = arm.guard {
                        match guard {
                            Guard::If(if_expr) => check_expr(cx, if_expr, bindings),
                        }
                    }
                    check_expr(cx, &arm.body, bindings);
                    bindings.truncate(len);
                }
            }
        },
        _ => (),
    }
}

fn check_ty<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, ty: &'tcx Ty, bindings: &mut Vec<(Name, Span)>) {
    match ty.node {
        TyKind::Slice(ref sty) => check_ty(cx, sty, bindings),
        TyKind::Array(ref fty, ref anon_const) => {
            check_ty(cx, fty, bindings);
            check_expr(cx, &cx.tcx.hir().body(anon_const.body).value, bindings);
        },
        TyKind::Ptr(MutTy { ty: ref mty, .. }) | TyKind::Rptr(_, MutTy { ty: ref mty, .. }) => {
            check_ty(cx, mty, bindings)
        },
        TyKind::Tup(ref tup) => {
            for t in tup {
                check_ty(cx, t, bindings)
            }
        },
        TyKind::Typeof(ref anon_const) => check_expr(cx, &cx.tcx.hir().body(anon_const.body).value, bindings),
        _ => (),
    }
}

fn is_self_shadow(name: Name, expr: &Expr) -> bool {
    match expr.node {
        ExprKind::Box(ref inner) | ExprKind::AddrOf(_, ref inner) => is_self_shadow(name, inner),
        ExprKind::Block(ref block, _) => {
            block.stmts.is_empty() && block.expr.as_ref().map_or(false, |e| is_self_shadow(name, e))
        },
        ExprKind::Unary(op, ref inner) => (UnDeref == op) && is_self_shadow(name, inner),
        ExprKind::Path(QPath::Resolved(_, ref path)) => path_eq_name(name, path),
        _ => false,
    }
}

fn path_eq_name(name: Name, path: &Path) -> bool {
    !path.is_global() && path.segments.len() == 1 && path.segments[0].ident.as_str() == name.as_str()
}
<|endoftext|>


<commit_before>use wtftw_core::core::*;

extern crate wtftw_core;

#[test]
fn stack_add() {
    let s1 = Stack::from_element(42);
    let s2 = s1.add(23);

    assert!(s2.focus == 23);
    assert!(s1.up == s2.up);
    assert!(s1.focus == s2.down[0]);
}

#[test]
fn stack_integrate() {
    let s1 = Stack::new(1, vec!(2, 3), vec!(4, 5, 6));
    assert!(s1.integrate() == vec!(3, 2, 1, 4, 5, 6));
}

#[test]
fn stack_filter() {
    let s1 = Stack::new(1, vec!(2, 3), vec!(4, 5, 6));
    let s2 = s1.filter(|&x| x != 3);

    assert!(s2.is_some());
    assert!(s2.unwrap() == Stack::new(1, vec!(2), vec!(4, 5, 6)));
}

#[test]
fn stack_focus_up() {
    let s1 = Stack::new(1, vec!(2, 3), vec!(4, 5, 6));
    let s2 = s1.focus_up();

    assert!(s2 == Stack::new(2, vec!(3), vec!(1, 4, 5, 6)));
}

#[test]
fn stack_focus_down() {
    let s1 = Stack::new(1, vec!(2, 3), vec!(4, 5, 6));
    let s2 = s1.focus_down();

    assert!(s2 == Stack::new(4, vec!(1, 2, 3), vec!(5, 6)));
}

#[test]
fn stack_reverse() {
    let v1 = vec!(2, 3);
    let v2 = vec!(4, 5, 6);

    let s1 = Stack::new(1, v1.clone(), v2.clone());
    let s2 = Stack::new(1, v2.clone(), v1.clone());

    assert!(s1.reverse() == s2);
    assert!(s2.reverse() == s1);
    assert!(s1.reverse().reverse() == s1);
}

#[test]
fn stack_len() {
    let s1 = Stack::new(1, vec!(2, 3), vec!(4, 5, 6));

    assert!(s1.len() == 6);
}

#[test]
fn stack_contains() {
    let s1 = Stack::new(42, vec!(2, 3), vec!(4, 5, 6));
    let s2 = Stack::new(23, Vec::new(), Vec::new());

    assert!(s1.contains(42));
    assert!(!s1.contains(23));
    assert!(!s2.contains(42));
    assert!(s2.contains(23));
}
<commit_msg>updated testcases<commit_after>use wtftw_core::core::*;
use wtftw_core::layout::FullLayout;

extern crate wtftw_core;

#[test]
fn stack_add() {
    let s1 = Stack::from_element(42);
    let s2 = s1.add(23);

    assert!(s2.focus == 23);
    assert!(s1.up == s2.up);
    assert!(s1.focus == s2.down[0]);
}

#[test]
fn stack_integrate() {
    let s1 = Stack::new(1, vec!(2, 3), vec!(4, 5, 6));
    assert!(s1.integrate() == vec!(3, 2, 1, 4, 5, 6));
}

#[test]
fn stack_filter() {
    let s1 = Stack::new(1, vec!(2, 3), vec!(4, 5, 6));
    let s2 = s1.filter(|&x| x != 3);

    assert!(s2.is_some());
    assert!(s2.unwrap() == Stack::new(1, vec!(2), vec!(4, 5, 6)));
}

#[test]
fn stack_focus_up() {
    let s1 = Stack::new(1, vec!(2, 3), vec!(4, 5, 6));
    let s2 = s1.focus_up();

    assert!(s2 == Stack::new(2, vec!(3), vec!(1, 4, 5, 6)));
}

#[test]
fn stack_focus_down() {
    let s1 = Stack::new(1, vec!(2, 3), vec!(4, 5, 6));
    let s2 = s1.focus_down();

    assert!(s2 == Stack::new(4, vec!(1, 2, 3), vec!(5, 6)));
}

#[test]
fn stack_reverse() {
    let v1 = vec!(2, 3);
    let v2 = vec!(4, 5, 6);

    let s1 = Stack::new(1, v1.clone(), v2.clone());
    let s2 = Stack::new(1, v2.clone(), v1.clone());

    assert!(s1.reverse() == s2);
    assert!(s2.reverse() == s1);
    assert!(s1.reverse().reverse() == s1);
}

#[test]
fn stack_len() {
    let s1 = Stack::new(1, vec!(2, 3), vec!(4, 5, 6));

    assert!(s1.len() == 6);
}

#[test]
fn stack_contains() {
    let s1 = Stack::new(42, vec!(2, 3), vec!(4, 5, 6));
    let s2 = Stack::new(23, Vec::new(), Vec::new());

    assert!(s1.contains(42));
    assert!(!s1.contains(23));
    assert!(!s2.contains(42));
    assert!(s2.contains(23));
}

#[test]
fn workspace_contains() {
    let s1 = Stack::new(42, vec!(2, 3), vec!(4, 5, 6));
    let w1 = Workspace::new(1, String::from_str("Foo"), Box::new(FullLayout), Some(s1));
    let w2 = Workspace::new(1, String::from_str("Foo"), Box::new(FullLayout), None);

    assert!(w1.contains(42));
    assert!(!w1.contains(23));
    assert!(!w2.contains(2));
}
<|endoftext|>


<commit_before>use docset::DocSet;
use query::Scorer;
use DocId;
use Score;
use SkipResult;

/// Creates a `DocSet` that iterate through the intersection of two `DocSet`s.
pub struct IntersectionTwoTerms<TDocSet> {
    left: TDocSet,
    right: TDocSet
}

impl<TDocSet: DocSet> IntersectionTwoTerms<TDocSet> {
    pub fn new(left: TDocSet, right: TDocSet) -> IntersectionTwoTerms<TDocSet> {
        IntersectionTwoTerms {
            left,
            right
        }
    }
}

impl<TDocSet: DocSet> DocSet for IntersectionTwoTerms<TDocSet> {

    fn advance(&mut self) -> bool {
        let (left, right) = (&mut self.left, &mut self.right);
        if !left.advance() {
            return false;
        }
        let mut candidate = left.doc();
        loop {
            match right.skip_next(candidate) {
                SkipResult::Reached => {
                    return true;
                }
                SkipResult::End => {
                    return false;
                }
                SkipResult::OverStep => {
                    candidate = right.doc();
                }
            }
            match left.skip_next(candidate) {
                SkipResult::Reached => {
                    return true;
                }
                SkipResult::End => {
                    return false;
                }
                SkipResult::OverStep => {
                    candidate = left.doc();
                }
            }
        }
    }

    fn doc(&self) -> DocId {
        self.left.doc()
    }

    fn size_hint(&self) -> u32 {
        self.left.size_hint().min(self.right.size_hint())
    }
}

impl<TScorer: Scorer> Scorer for IntersectionTwoTerms<TScorer> {
    fn score(&mut self) -> Score {
        self.left.score() + self.right.score()
    }
}
<commit_msg>Removing dead file (#1170)<commit_after><|endoftext|>


<commit_before>use std::{cmp, usize};
use slsr_core::puzzle::Side;
use slsr_core::geom::{CellId, Geom};

use {State, SolverResult};
use model::connect_map::ConnectMap;
use model::side_map::SideMap;

fn create_conn_graph(conn_map: &mut ConnectMap,
                     exclude_side: Side)
                     -> (Vec<CellId>, Vec<State<Side>>, Vec<Vec<usize>>) {
    let mut pts = vec![];
    let mut sides = vec![];
    for i in 0..conn_map.cell_len() {
        let p = CellId::new(i);
        let a = conn_map.get(p);
        if a.coord() != p || a.side() == State::Fixed(exclude_side) {
            continue;
        }
        pts.push(p);
        sides.push(a.side());
    }

    let mut verts = vec![None; conn_map.cell_len()];
    for (i, &p) in pts.iter().enumerate() {
        verts[p.id()] = Some(i);
    }

    let graph = pts.iter()
                   .map(|&p| {
                       conn_map.get(p)
                               .unknown_edge()
                               .iter()
                               .filter_map(|p2| verts[p2.id()])
                               .collect::<Vec<_>>()
                   })
                   .collect();

    (pts, sides, graph)
}

fn get_articulation(graph: &[Vec<usize>],
                    v: usize,
                    arts: &mut Vec<usize>,
                    gvisited: &mut [bool])
                    -> Vec<bool> {
    let mut visited = vec![false; graph.len()];
    let mut ord = vec![0; graph.len()];
    let mut low = vec![0; graph.len()];
    let mut ord_cnt = 0;
    unsafe {
        dfs(graph,
            v,
            usize::MAX,
            arts,
            gvisited,
            &mut visited,
            &mut ord,
            &mut low,
            &mut ord_cnt);
    }

    return visited;

    unsafe fn dfs(graph: &[Vec<usize>],
                  v: usize,
                  prev: usize,
                  arts: &mut Vec<usize>,
                  gvisited: &mut [bool],
                  visited: &mut [bool],
                  ord: &mut [usize],
                  low: &mut [usize],
                  ord_cnt: &mut usize) {
        debug_assert!(!visited[v]);

        *visited.get_unchecked_mut(v) = true;
        *gvisited.get_unchecked_mut(v) = true;

        let ord_v = *ord_cnt;
        *ord.get_unchecked_mut(v) = ord_v;
        *low.get_unchecked_mut(v) = ord_v;
        *ord_cnt += 1;

        let mut is_articulation = false;
        let mut num_child = 0;

        for &u in graph.get_unchecked(v) {
            if u == v {
                continue;
            }

            if !*visited.get_unchecked(u) {
                dfs(graph, u, v, arts, gvisited, visited, ord, low, ord_cnt);

                let low_u = *low.get_unchecked(u);
                num_child += 1;
                *low.get_unchecked_mut(v) = cmp::min(*low.get_unchecked(v), low_u);
                if ord_v <= low_u {
                    is_articulation = true;
                }
            } else if u != prev {
                *low.get_unchecked_mut(v) = cmp::min(*low.get_unchecked(v), *ord.get_unchecked(u));
            } else {
            }
        }

        if ord_v == 0 {
            is_articulation = num_child > 1;
        }
        if is_articulation {
            arts.push(v);
        }
    }
}

fn find_disconn_area(conn_map: &mut ConnectMap,
                     pts: &[CellId],
                     visited: &[bool])
                     -> SolverResult<Vec<usize>> {
    let mut disconn = vec![];
    let mut disconn_sum = 0;
    for (u, &vis) in visited.iter().enumerate() {
        if !vis {
            disconn.push(u);
            disconn_sum += conn_map.get(pts[u]).sum_of_hint();
        }
    }
    if disconn.is_empty() {
        // All area is connected
        return Ok(vec![]);
    }
    if disconn_sum == 0 {
        // Disconnected components does not contain any edges. It is a hole in
        // the exclude_side area.
        return Ok(disconn);
    }

    let mut conn = vec![];
    let mut conn_sum = 0;
    for (u, &vis) in visited.iter().enumerate() {
        if vis {
            conn.push(u);
            conn_sum += conn_map.get(pts[u]).sum_of_hint();
        }
    }
    if conn_sum == 0 {
        // Conencted area does not contain any edges. It is a hole in the
        // exclude_side area.
        return Ok(conn);
    }

    // Graph is splitted into more than two parts, but both parts contain edges.
    // This may be valid in some situation, so, return empty.
    Ok(vec![])
}

fn splits(graph: &[Vec<usize>], v: usize, sides: &[State<Side>], set_side: Side) -> bool {
    if graph.is_empty() {
        return false;
    }

    let mut contain_cnt = 0;
    let mut visited = vec![false; graph.len()];

    unsafe {
        *visited.get_unchecked_mut(v) = true;

        for &u in graph.get_unchecked(v) {
            if *visited.get_unchecked(u) {
                continue;
            }

            let mut contains = false;
            dfs(graph, u, &mut contains, &mut visited, sides, set_side);

            if contains {
                contain_cnt += 1;
                if contain_cnt > 1 {
                    return true;
                }
            }
        }
    }

    return false;

    unsafe fn dfs(graph: &[Vec<usize>],
                  v: usize,
                  contains: &mut bool,
                  visited: &mut [bool],
                  sides: &[State<Side>],
                  set_side: Side) {
        if *sides.get_unchecked(v) == State::Fixed(set_side) {
            *contains = true;
        }
        *visited.get_unchecked_mut(v) = true;

        for &u in graph.get_unchecked(v) {
            if *visited.get_unchecked_mut(u) {
                continue;
            }
            dfs(graph, u, contains, visited, sides, set_side);
        }
    }
}

pub fn run(side_map: &mut SideMap, conn_map: &mut ConnectMap) -> SolverResult<()> {
    try!(conn_map.sync(side_map));

    let sides = &[(Side::In, Side::Out), (Side::Out, Side::In)];

    for &(set_side, exclude_side) in sides {
        let (pts, sides, graph) = create_conn_graph(conn_map, exclude_side);

        let mut arts = vec![];
        let mut gvisited = vec![false; graph.len()];
        for v in 0..graph.len() {
            if gvisited[v] {
                continue;
            }

            let visited = get_articulation(&graph, v, &mut arts, &mut gvisited);

            if set_side == Side::Out || conn_map.sum_of_hint() != 0 {
                // If there is no edge in puzzle (sum_of_hint == 0) and set_side ==
                // Side::In, any disconnected area can be loop.
                let disconn = try!(find_disconn_area(conn_map, &pts, &visited));
                for v in disconn {
                    side_map.set_side(pts[v], exclude_side);
                }
            }
        }

        for v in arts {
            if sides[v] == State::Fixed(set_side) {
                continue;
            }

            if splits(&graph, v, &sides, set_side) {
                side_map.set_side(pts[v], set_side);
            }
        }
    }

    Ok(())
}
<commit_msg>solver: make busy loop body small<commit_after>use std::{cmp, usize};
use slsr_core::puzzle::Side;
use slsr_core::geom::{CellId, Geom};

use {State, SolverResult};
use model::connect_map::ConnectMap;
use model::side_map::SideMap;

fn create_conn_graph(conn_map: &mut ConnectMap,
                     exclude_side: Side)
                     -> (Vec<CellId>, Vec<State<Side>>, Vec<Vec<usize>>) {
    let mut pts = vec![];
    let mut sides = vec![];
    for i in 0..conn_map.cell_len() {
        let p = CellId::new(i);
        let a = conn_map.get(p);
        if a.coord() != p || a.side() == State::Fixed(exclude_side) {
            continue;
        }
        pts.push(p);
        sides.push(a.side());
    }

    let mut verts = vec![None; conn_map.cell_len()];
    for (i, &p) in pts.iter().enumerate() {
        verts[p.id()] = Some(i);
    }

    let graph = pts.iter()
                   .map(|&p| {
                       conn_map.get(p)
                               .unknown_edge()
                               .iter()
                               .filter_map(|p2| verts[p2.id()])
                               .collect::<Vec<_>>()
                   })
                   .collect();

    (pts, sides, graph)
}

fn get_articulation(graph: &[Vec<usize>],
                    v: usize,
                    arts: &mut Vec<usize>,
                    gvisited: &mut [bool])
                    -> Vec<bool> {
    let mut visited = vec![false; graph.len()];
    let mut ord = vec![0; graph.len()];
    let mut low = vec![0; graph.len()];
    let mut ord_cnt = 0;
    unsafe {
        dfs(graph,
            v,
            usize::MAX,
            arts,
            gvisited,
            &mut visited,
            &mut ord,
            &mut low,
            &mut ord_cnt);
    }

    return visited;

    unsafe fn dfs(graph: &[Vec<usize>],
                  v: usize,
                  prev: usize,
                  arts: &mut Vec<usize>,
                  gvisited: &mut [bool],
                  visited: &mut [bool],
                  ord: &mut [usize],
                  low: &mut [usize],
                  ord_cnt: &mut usize) {
        debug_assert!(!visited[v]);

        *visited.get_unchecked_mut(v) = true;
        *gvisited.get_unchecked_mut(v) = true;

        let ord_v = *ord_cnt;
        *ord.get_unchecked_mut(v) = ord_v;
        *low.get_unchecked_mut(v) = ord_v;
        *ord_cnt += 1;

        let mut is_articulation = false;
        let mut num_child = 0;

        for &u in graph.get_unchecked(v) {
            if u == v {
                continue;
            }

            if !*visited.get_unchecked(u) {
                dfs(graph, u, v, arts, gvisited, visited, ord, low, ord_cnt);

                let low_u = *low.get_unchecked(u);
                num_child += 1;
                *low.get_unchecked_mut(v) = cmp::min(*low.get_unchecked(v), low_u);
                if ord_v <= low_u {
                    is_articulation = true;
                }
            } else if u != prev {
                *low.get_unchecked_mut(v) = cmp::min(*low.get_unchecked(v), *ord.get_unchecked(u));
            } else {
            }
        }

        if ord_v == 0 {
            is_articulation = num_child > 1;
        }
        if is_articulation {
            arts.push(v);
        }
    }
}

fn find_disconn_area(conn_map: &mut ConnectMap,
                     pts: &[CellId],
                     visited: &[bool])
                     -> SolverResult<Vec<usize>> {
    let mut disconn = vec![];
    let mut disconn_sum = 0;
    for (u, &vis) in visited.iter().enumerate() {
        if !vis {
            disconn.push(u);
            disconn_sum += conn_map.get(pts[u]).sum_of_hint();
        }
    }
    if disconn.is_empty() {
        // All area is connected
        return Ok(vec![]);
    }
    if disconn_sum == 0 {
        // Disconnected components does not contain any edges. It is a hole in
        // the exclude_side area.
        return Ok(disconn);
    }

    let mut conn = vec![];
    let mut conn_sum = 0;
    for (u, &vis) in visited.iter().enumerate() {
        if vis {
            conn.push(u);
            conn_sum += conn_map.get(pts[u]).sum_of_hint();
        }
    }
    if conn_sum == 0 {
        // Conencted area does not contain any edges. It is a hole in the
        // exclude_side area.
        return Ok(conn);
    }

    // Graph is splitted into more than two parts, but both parts contain edges.
    // This may be valid in some situation, so, return empty.
    Ok(vec![])
}

fn splits(graph: &[Vec<usize>], v: usize, sides: &[State<Side>], set_side: Side) -> bool {
    if graph.is_empty() {
        return false;
    }

    let mut contain_cnt = 0;
    let mut visited = vec![false; graph.len()];

    unsafe {
        *visited.get_unchecked_mut(v) = true;

        for &u in graph.get_unchecked(v) {
            if *visited.get_unchecked(u) {
                continue;
            }

            let mut contains = false;
            dfs(graph, u, &mut contains, &mut visited, sides, set_side);

            if contains {
                contain_cnt += 1;
                if contain_cnt > 1 {
                    return true;
                }
            }
        }
    }

    return false;

    unsafe fn dfs(graph: &[Vec<usize>],
                  v: usize,
                  contains: &mut bool,
                  visited: &mut [bool],
                  sides: &[State<Side>],
                  set_side: Side) {
        if *sides.get_unchecked(v) == State::Fixed(set_side) {
            *contains = true;

            *visited.get_unchecked_mut(v) = true;

            for &u in graph.get_unchecked(v) {
                if *visited.get_unchecked_mut(u) {
                    continue;
                }
                dfs_mark(graph, u, visited);
            }
            return;
        }

        *visited.get_unchecked_mut(v) = true;

        for &u in graph.get_unchecked(v) {
            if *visited.get_unchecked_mut(u) {
                continue;
            }
            dfs(graph, u, contains, visited, sides, set_side);
        }
    }

    unsafe fn dfs_mark(graph: &[Vec<usize>], v: usize, visited: &mut [bool]) {
        *visited.get_unchecked_mut(v) = true;

        for &u in graph.get_unchecked(v) {
            if *visited.get_unchecked_mut(u) {
                continue;
            }
            dfs_mark(graph, u, visited);
        }
    }
}

pub fn run(side_map: &mut SideMap, conn_map: &mut ConnectMap) -> SolverResult<()> {
    try!(conn_map.sync(side_map));

    let sides = &[(Side::In, Side::Out), (Side::Out, Side::In)];

    for &(set_side, exclude_side) in sides {
        let (pts, sides, graph) = create_conn_graph(conn_map, exclude_side);

        let mut arts = vec![];
        let mut gvisited = vec![false; graph.len()];
        for v in 0..graph.len() {
            if gvisited[v] {
                continue;
            }

            let visited = get_articulation(&graph, v, &mut arts, &mut gvisited);

            if set_side == Side::Out || conn_map.sum_of_hint() != 0 {
                // If there is no edge in puzzle (sum_of_hint == 0) and set_side ==
                // Side::In, any disconnected area can be loop.
                let disconn = try!(find_disconn_area(conn_map, &pts, &visited));
                for v in disconn {
                    side_map.set_side(pts[v], exclude_side);
                }
            }
        }

        for v in arts {
            if sides[v] == State::Fixed(set_side) {
                continue;
            }

            if splits(&graph, v, &sides, set_side) {
                side_map.set_side(pts[v], set_side);
            }
        }
    }

    Ok(())
}
<|endoftext|>


<commit_before>mod session;
pub use self::session::*;

mod handler;
pub use self::handler::*;

mod worker;
use self::worker::Worker;

use std::fmt;
use std::io;
use std::mem;
use std::net::SocketAddr;
use std::sync::Arc;
use std::sync::atomic::AtomicUsize;
use std::thread::{self, JoinHandle};

use futures::{Future, Stream};

use channel::err::SendError;
use channel::spsc::{self, SyncSender};
use net::{TcpListener, TcpListenerBuilder};
use reactor::{self, IntoStream, IntoTask};

struct Inner {
    name: String,
    listener: Option<TcpListener>,
    workers: Vec<Worker>,
    mask: usize,
    idx: usize,
    worker_conns: usize,
}

impl Inner {
    #[inline]
    fn init<H>(&mut self, to_handler: Arc<H>)
    where
        H: ToHandler + Send + Sync + 'static,
    {
        for _ in 0..self.mask + 1 {
            let (tx, rx) = spsc::sync_channel(self.worker_conns).unwrap();
            let conn_count = Arc::new(AtomicUsize::new(0));
            let join_handle = {
                let conn_count = conn_count.clone();
                let to_handler = to_handler.clone();
                thread::spawn(move || {
                    let mut handler = to_handler.to_handler();
                    let handle = rx.into_stream().for_each(|(conn, peer_addr)| {
                        let session = Session::new(
                            conn,
                            Some(peer_addr),
                            unsafe { mem::transmute(&conn_count) },
                        );
                        Ok(reactor::spawn(handler.handle(session)))
                    });
                    reactor::run(handle).map_err(|e| error!("{}", e)).ok();
                })
            };
            let worker = Worker::new(tx, join_handle, conn_count);
            self.workers.push(worker);
        }
    }

    #[inline]
    fn run(mut self) {
        info!("{} started", self);
        let accept = self.listener
            .take()
            .unwrap()
            .incoming()
            .for_each(move |(s, a)| {
                let mut idx = self.idx;
                loop {
                    let worker: &Worker = unsafe { self.workers.get_unchecked(idx) };
                    idx = (idx + 1) & self.mask;
                    if worker.conn_count() < self.worker_conns {
                        self.idx = idx;
                        worker
                            .send(s, a)
                            .map_err(|e| error!("Error dispatch connection from {}: {:?}", a, e))
                            .ok();
                        worker.inc_conn_count();
                        break;
                    }
                    if idx == self.idx {
                        warn!("{} drops {} not to exceed worker_conns", self, s);
                        break;
                    }
                }
                Ok(())
            })
            .map_err(|e| error!("{}", e))
            .into_task();
        reactor::spawn(accept);
    }
}

impl fmt::Display for Inner {
    #[inline]
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "TcpServer({})", self.name)
    }
}

impl Drop for Inner {
    #[inline]
    fn drop(&mut self) {
        info!("{} stopped", self);
    }
}

pub struct Server<H> {
    listener_builder: TcpListenerBuilder,
    num_of_workers: usize,
    worker_conns: usize, // Max number of simultaneous connections per worker
    tx: Option<SyncSender<(Inner, Arc<H>)>>,
    join_handle: Option<JoinHandle<()>>,
    to_handler: Arc<H>,
}

impl<H> Server<H>
where
    H: ToHandler + Send + Sync + 'static,
{
    #[inline]
    pub fn with_handler(to_handler: H) -> Self {
        Server {
            listener_builder: TcpListenerBuilder::default(),
            num_of_workers: 1,
            worker_conns: 512,
            tx: None,
            join_handle: None,
            to_handler: Arc::new(to_handler),
        }
    }

    #[inline]
    pub fn addr(&mut self, addr: SocketAddr) -> &mut Self {
        self.listener_builder.addr(addr);
        self
    }

    #[inline]
    pub fn port(&mut self, port: u16) -> &mut Self {
        self.listener_builder.port(port);
        self
    }

    #[inline]
    pub fn backlog(&mut self, blacklog: i32) -> &mut Self {
        self.listener_builder.backlog(blacklog);
        self
    }

    #[inline]
    pub fn ttl(&mut self, ttl: Option<u32>) -> &mut Self {
        self.listener_builder.ttl(ttl);
        self
    }

    #[inline]
    pub fn only_v6(&mut self, only_v6: Option<bool>) -> &mut Self {
        self.listener_builder.only_v6(only_v6);
        self
    }

    #[inline]
    pub fn num_of_workers(&mut self, num_of_workers: usize) -> &mut Self {
        if let Some(n) = num_of_workers.checked_next_power_of_two() {
            self.num_of_workers = n;
        }
        self
    }

    #[inline]
    pub fn worker_conns(&mut self, worker_conns: usize) -> &mut Self {
        if worker_conns > 0 {
            self.worker_conns = worker_conns;
        }
        self
    }

    pub fn start(&mut self) -> io::Result<()> {
        let listener = self.listener_builder.build()?;
        let name = format!("{}", listener.local_addr()?);
        let inner = Inner {
            name,
            listener: Some(listener),
            workers: Vec::with_capacity(self.num_of_workers),
            mask: self.num_of_workers - 1,
            idx: 0,
            worker_conns: self.worker_conns,
        };
        let (tx, rx) = spsc::sync_channel(1)?;
        match tx.send((inner, self.to_handler.clone())) {
            Ok(..) => {}
            Err(SendError::Io(e)) => return Err(e),
            Err(SendError::Disconnected(..)) => ::unreachable(),
        }
        let join_handle = thread::spawn(move || {
            let server = rx.into_stream().for_each(|(mut inner, h)| {
                inner.init(h);
                inner.run();
                Ok(())
            });
            reactor::run(server).map_err(|e| error!("{}", e)).ok();
        });
        self.tx = Some(tx);
        self.join_handle = Some(join_handle);
        Ok(())
    }
}

impl<H> Drop for Server<H> {
    fn drop(&mut self) {
        self.tx = None;
        if let Some(join_handle) = self.join_handle.take() {
            join_handle.join().ok();
        }
    }
}
<commit_msg>Accepter and worker share the same thread and loop when num_of_workers  = 1<commit_after>mod session;
pub use self::session::*;

mod handler;
pub use self::handler::*;

mod worker;
use self::worker::Worker;

use std::fmt;
use std::io;
use std::mem;
use std::net::SocketAddr;
use std::sync::Arc;
use std::sync::atomic::{AtomicUsize, Ordering};
use std::thread::{self, JoinHandle};

use futures::{Future, Stream};

use channel::err::SendError;
use channel::spsc::{self, SyncSender};
use net::{TcpListener, TcpListenerBuilder};
use reactor::{self, IntoStream, IntoTask};

struct Inner {
    name: String,
    listener: Option<TcpListener>,
    workers: Vec<Worker>,
    mask: usize,
    idx: usize,
    worker_conns: usize,
}

impl Inner {
    #[inline]
    fn init<H>(&mut self, to_handler: Arc<H>)
    where
        H: ToHandler + Send + Sync + 'static,
    {
        for _ in 0..self.mask + 1 {
            let (tx, rx) = spsc::sync_channel(self.worker_conns).unwrap();
            let conn_count = Arc::new(AtomicUsize::new(0));
            let join_handle = {
                let conn_count = conn_count.clone();
                let to_handler = to_handler.clone();
                thread::spawn(move || {
                    let mut handler = to_handler.to_handler();
                    let handle = rx.into_stream().for_each(|(conn, peer_addr)| {
                        let session = Session::new(conn, Some(peer_addr), unsafe {
                            mem::transmute(conn_count.as_ref())
                        });
                        Ok(reactor::spawn(handler.handle(session)))
                    });
                    reactor::run(handle).map_err(|e| error!("{}", e)).ok();
                })
            };
            let worker = Worker::new(tx, join_handle, conn_count);
            self.workers.push(worker);
        }
    }

    #[inline]
    fn run(mut self) {
        info!("{} started", self);
        let run = self.listener
            .take()
            .unwrap()
            .incoming()
            .for_each(move |(s, a)| {
                let mut idx = self.idx;
                loop {
                    let worker: &Worker = unsafe { self.workers.get_unchecked(idx) };
                    idx = (idx + 1) & self.mask;
                    if worker.conn_count() < self.worker_conns {
                        self.idx = idx;
                        worker
                            .send(s, a)
                            .map_err(|e| error!("Error dispatch connection from {}: {:?}", a, e))
                            .ok();
                        worker.inc_conn_count();
                        break;
                    }
                    if idx == self.idx {
                        warn!("{} drops {} not to exceed worker_conns", self, s);
                        break;
                    }
                }
                Ok(())
            })
            .map_err(|e| error!("{}", e))
            .into_task();
        reactor::spawn(run);
    }

    #[inline]
    fn run_single<H>(mut self, to_handler: Arc<H>)
    where
        H: ToHandler + Send + Sync + 'static,
    {
        info!("{} started", self);
        let mut handler = to_handler.to_handler();
        let conn_count = Box::new(AtomicUsize::new(0));
        let run = self.listener
            .take()
            .unwrap()
            .incoming()
            .for_each(move |(conn, peer_addr)| {
                let n = conn_count.fetch_add(1, Ordering::Relaxed);
                if self.worker_conns > n {
                    let session = Session::new(conn, Some(peer_addr), unsafe {
                        mem::transmute(conn_count.as_ref())
                    });
                    reactor::spawn(handler.handle(session));
                } else {
                    warn!("{} drops {} not to exceed worker_conns", self, conn);
                }
                Ok(())
            })
            .map_err(|e| error!("{}", e))
            .into_task();
        reactor::spawn(run);
    }
}

impl fmt::Display for Inner {
    #[inline]
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "TcpServer({})", self.name)
    }
}

impl Drop for Inner {
    #[inline]
    fn drop(&mut self) {
        info!("{} stopped", self);
    }
}

pub struct Server<H> {
    listener_builder: TcpListenerBuilder,
    num_of_workers: usize,
    worker_conns: usize, // Max number of simultaneous connections per worker
    tx: Option<SyncSender<(Inner, Arc<H>)>>,
    join_handle: Option<JoinHandle<()>>,
    to_handler: Arc<H>,
}

impl<H> Server<H>
where
    H: ToHandler + Send + Sync + 'static,
{
    #[inline]
    pub fn with_handler(to_handler: H) -> Self {
        Server {
            listener_builder: TcpListenerBuilder::default(),
            num_of_workers: 1,
            worker_conns: 512,
            tx: None,
            join_handle: None,
            to_handler: Arc::new(to_handler),
        }
    }

    #[inline]
    pub fn addr(&mut self, addr: SocketAddr) -> &mut Self {
        self.listener_builder.addr(addr);
        self
    }

    #[inline]
    pub fn port(&mut self, port: u16) -> &mut Self {
        self.listener_builder.port(port);
        self
    }

    #[inline]
    pub fn backlog(&mut self, blacklog: i32) -> &mut Self {
        self.listener_builder.backlog(blacklog);
        self
    }

    #[inline]
    pub fn ttl(&mut self, ttl: Option<u32>) -> &mut Self {
        self.listener_builder.ttl(ttl);
        self
    }

    #[inline]
    pub fn only_v6(&mut self, only_v6: Option<bool>) -> &mut Self {
        self.listener_builder.only_v6(only_v6);
        self
    }

    #[inline]
    pub fn num_of_workers(&mut self, num_of_workers: usize) -> &mut Self {
        if let Some(n) = num_of_workers.checked_next_power_of_two() {
            self.num_of_workers = n;
        }
        self
    }

    #[inline]
    pub fn worker_conns(&mut self, worker_conns: usize) -> &mut Self {
        if worker_conns > 0 {
            self.worker_conns = worker_conns;
        }
        self
    }

    pub fn start(&mut self) -> io::Result<()> {
        let listener = self.listener_builder.build()?;
        let name = format!("{}", listener.local_addr()?);
        let inner = Inner {
            name,
            listener: Some(listener),
            workers: Vec::with_capacity(self.num_of_workers),
            mask: self.num_of_workers - 1,
            idx: 0,
            worker_conns: self.worker_conns,
        };
        let (tx, rx) = spsc::sync_channel(1)?;
        match tx.send((inner, self.to_handler.clone())) {
            Ok(..) => {}
            Err(SendError::Io(e)) => return Err(e),
            Err(SendError::Disconnected(..)) => ::unreachable(),
        }
        let join_handle = thread::spawn(move || {
            let server = rx.into_stream().for_each(|(mut inner, h)| {
                if inner.mask == 0 {
                    inner.run_single(h);
                } else {
                    inner.init(h);
                    inner.run();
                }
                Ok(())
            });
            reactor::run(server).map_err(|e| error!("{}", e)).ok();
        });
        self.tx = Some(tx);
        self.join_handle = Some(join_handle);
        Ok(())
    }
}

impl<H> Drop for Server<H> {
    fn drop(&mut self) {
        self.tx = None;
        if let Some(join_handle) = self.join_handle.take() {
            join_handle.join().ok();
        }
    }
}
<|endoftext|>


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

static FOO: i32 = [][0];
//~^ ERROR E0080

fn main() {
    let array = [std::env::args().len()];
    array[1]; //~ ERROR index out of bounds
}<commit_msg>Fix tidy<commit_after>// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

static FOO: i32 = [][0];
//~^ ERROR E0080

fn main() {
    let array = [std::env::args().len()];
    array[1]; //~ ERROR index out of bounds
}
<|endoftext|>


<commit_before>extern crate criterion;
extern crate snapshot;
extern crate versionize;
extern crate versionize_derive;

use criterion::{black_box, criterion_group, criterion_main, Criterion};
use snapshot::Snapshot;
use versionize::{Error, VersionMap, Versionize, VersionizeResult};
use versionize_derive::Versionize;

#[derive(Clone, Debug, Default, Versionize)]
struct Test {
    dummy: Vec<Dummy>,
    field_x: u64,
    field0: u64,
    field1: u32,
    #[version(start = 2, default_fn = "field2_default")]
    field2: u64,
    #[version(
        start = 3,
        default_fn = "field3_default",
        ser_fn = "field3_serialize",
        de_fn = "field3_deserialize"
    )]
    field3: String,
    #[version(
        start = 4,
        default_fn = "field4_default",
        ser_fn = "field4_serialize",
        de_fn = "field4_deserialize"
    )]
    field4: Vec<u64>,
}

#[derive(Clone, Debug, Default, Versionize)]
struct Dummy {
    dummy: u64,
    string: String,
}

impl Test {
    fn field2_default(_: u16) -> u64 {
        20
    }
    fn field3_default(_: u16) -> String {
        "default".to_owned()
    }
    fn field4_default(_: u16) -> Vec<u64> {
        vec![1, 2, 3, 4]
    }

    fn field4_serialize(&mut self, target_version: u16) -> VersionizeResult<()> {
        // Fail if semantic serialization is called for the latest version.
        assert_ne!(target_version, Test::version());
        self.field0 = self.field4.iter().sum();

        if self.field0 == 6666 {
            return Err(Error::Semantic("field4 element sum is 6666".to_owned()));
        }
        Ok(())
    }

    fn field4_deserialize(&mut self, source_version: u16) -> VersionizeResult<()> {
        // Fail if semantic deserialization is called for the latest version.
        assert_ne!(source_version, Test::version());
        self.field4 = vec![self.field0; 4];
        Ok(())
    }

    fn field3_serialize(&mut self, target_version: u16) -> VersionizeResult<()> {
        // Fail if semantic serialization is called for the previous versions only.
        assert!(target_version < 3);
        self.field_x += 1;
        Ok(())
    }

    fn field3_deserialize(&mut self, source_version: u16) -> VersionizeResult<()> {
        // Fail if semantic deserialization is called for the latest version.
        assert!(source_version < 3);
        self.field_x += 1;
        if self.field0 == 7777 {
            return Err(Error::Semantic("field0 is 7777".to_owned()));
        }
        Ok(())
    }
}

#[inline]
pub fn bench_restore_v1(mut snapshot_mem: &[u8], vm: VersionMap) {
    let mut loaded_snapshot = Snapshot::load(&mut snapshot_mem, vm).unwrap();

    loaded_snapshot.read_section::<Test>("test").unwrap();
}

#[inline]
pub fn bench_snapshot_v1(mut snapshot_mem: &mut [u8], vm: VersionMap) -> usize {
    let state = Test {
        dummy: vec![
            Dummy {
                dummy: 123,
                string: "xxx".to_owned()
            };
            100
        ],
        field0: 0,
        field1: 1,
        field2: 2,
        field3: "test".to_owned(),
        field4: vec![4; 1024 * 10],
        field_x: 0,
    };

    // Serialize as v4.
    let mut snapshot = Snapshot::new(vm.clone(), 4);
    let size = snapshot.write_section("test", &state).unwrap();
    snapshot.save(&mut snapshot_mem).unwrap();
    size
}

#[inline]
pub fn bench_restore_crc_v1(mut snapshot_mem: &[u8], vm: VersionMap) {
    let mut loaded_snapshot = Snapshot::load_with_crc64(&mut snapshot_mem, vm).unwrap();
    loaded_snapshot.read_section::<Test>("test").unwrap();
}

#[inline]
pub fn bench_snapshot_crc_v1(mut snapshot_mem: &mut [u8], vm: VersionMap) -> usize {
    let state = Test {
        dummy: vec![
            Dummy {
                dummy: 123,
                string: "xxx".to_owned()
            };
            100
        ],
        field0: 0,
        field1: 1,
        field2: 2,
        field3: "test".to_owned(),
        field4: vec![4; 1024 * 10],
        field_x: 0,
    };

    // Serialize as v4.
    let mut snapshot = Snapshot::new(vm.clone(), 4);
    let size = snapshot.write_section("test", &state).unwrap();
    snapshot.save_with_crc64(&mut snapshot_mem).unwrap();
    size
}

pub fn criterion_benchmark(c: &mut Criterion) {
    let mut snapshot_mem = vec![0u8; 1024 * 1024 * 128];
    let mut vm = VersionMap::new();

    vm.new_version()
        .set_type_version(Test::type_id(), 2)
        .new_version()
        .set_type_version(Test::type_id(), 3)
        .new_version()
        .set_type_version(Test::type_id(), 4);

    let mut snapshot_len = bench_snapshot_v1(&mut snapshot_mem.as_mut_slice(), vm.clone());
    println!("Snapshot len {}", snapshot_len);

    c.bench_function("Serialize to v4", |b| {
        b.iter(|| {
            bench_snapshot_v1(
                black_box(&mut snapshot_mem.as_mut_slice()),
                black_box(vm.clone()),
            )
        })
    });
    c.bench_function("Deserialize to v4", |b| {
        b.iter(|| {
            bench_restore_v1(
                black_box(&mut snapshot_mem.as_slice()),
                black_box(vm.clone()),
            )
        })
    });

    snapshot_len = bench_snapshot_crc_v1(&mut snapshot_mem.as_mut_slice(), vm.clone());
    println!("Snapshot with crc64 len {}", snapshot_len);

    c.bench_function("Serialize with crc64 to v4", |b| {
        b.iter(|| {
            bench_snapshot_crc_v1(
                black_box(&mut snapshot_mem.as_mut_slice()),
                black_box(vm.clone()),
            )
        })
    });
    c.bench_function("Deserialize with crc64 from v4", |b| {
        b.iter(|| {
            bench_restore_crc_v1(
                black_box(&mut snapshot_mem.as_slice()),
                black_box(vm.clone()),
            )
        })
    });
}

criterion_group! {
    name = benches;
    config = Criterion::default().sample_size(50);
    targets = criterion_benchmark
}

criterion_main!(benches);
<commit_msg>[snapshot] fix build issue<commit_after>extern crate criterion;
extern crate snapshot;
extern crate versionize;
extern crate versionize_derive;

use criterion::{black_box, criterion_group, criterion_main, Criterion};
use snapshot::Snapshot;
use versionize::{VersionMap, Versionize, VersionizeError, VersionizeResult};
use versionize_derive::Versionize;

#[derive(Clone, Debug, Default, Versionize)]
struct Test {
    dummy: Vec<Dummy>,
    field_x: u64,
    field0: u64,
    field1: u32,
    #[version(start = 2, default_fn = "field2_default")]
    field2: u64,
    #[version(
        start = 3,
        default_fn = "field3_default",
        ser_fn = "field3_serialize",
        de_fn = "field3_deserialize"
    )]
    field3: String,
    #[version(
        start = 4,
        default_fn = "field4_default",
        ser_fn = "field4_serialize",
        de_fn = "field4_deserialize"
    )]
    field4: Vec<u64>,
}

#[derive(Clone, Debug, Default, Versionize)]
struct Dummy {
    dummy: u64,
    string: String,
}

impl Test {
    fn field2_default(_: u16) -> u64 {
        20
    }
    fn field3_default(_: u16) -> String {
        "default".to_owned()
    }
    fn field4_default(_: u16) -> Vec<u64> {
        vec![1, 2, 3, 4]
    }

    fn field4_serialize(&mut self, target_version: u16) -> VersionizeResult<()> {
        // Fail if semantic serialization is called for the latest version.
        assert_ne!(target_version, Test::version());
        self.field0 = self.field4.iter().sum();

        if self.field0 == 6666 {
            return Err(VersionizeError::Semantic(
                "field4 element sum is 6666".to_owned(),
            ));
        }
        Ok(())
    }

    fn field4_deserialize(&mut self, source_version: u16) -> VersionizeResult<()> {
        // Fail if semantic deserialization is called for the latest version.
        assert_ne!(source_version, Test::version());
        self.field4 = vec![self.field0; 4];
        Ok(())
    }

    fn field3_serialize(&mut self, target_version: u16) -> VersionizeResult<()> {
        // Fail if semantic serialization is called for the previous versions only.
        assert!(target_version < 3);
        self.field_x += 1;
        Ok(())
    }

    fn field3_deserialize(&mut self, source_version: u16) -> VersionizeResult<()> {
        // Fail if semantic deserialization is called for the latest version.
        assert!(source_version < 3);
        self.field_x += 1;
        if self.field0 == 7777 {
            return Err(VersionizeError::Semantic("field0 is 7777".to_owned()));
        }
        Ok(())
    }
}

#[inline]
pub fn bench_restore_v1(mut snapshot_mem: &[u8], vm: VersionMap) {
    let mut loaded_snapshot = Snapshot::load(&mut snapshot_mem, vm).unwrap();

    loaded_snapshot.read_section::<Test>("test").unwrap();
}

#[inline]
pub fn bench_snapshot_v1(mut snapshot_mem: &mut [u8], vm: VersionMap) -> usize {
    let state = Test {
        dummy: vec![
            Dummy {
                dummy: 123,
                string: "xxx".to_owned()
            };
            100
        ],
        field0: 0,
        field1: 1,
        field2: 2,
        field3: "test".to_owned(),
        field4: vec![4; 1024 * 10],
        field_x: 0,
    };

    // Serialize as v4.
    let mut snapshot = Snapshot::new(vm.clone(), 4);
    let size = snapshot.write_section("test", &state).unwrap();
    snapshot.save(&mut snapshot_mem).unwrap();
    size
}

#[inline]
pub fn bench_restore_crc_v1(mut snapshot_mem: &[u8], vm: VersionMap) {
    let mut loaded_snapshot = Snapshot::load_with_crc64(&mut snapshot_mem, vm).unwrap();
    loaded_snapshot.read_section::<Test>("test").unwrap();
}

#[inline]
pub fn bench_snapshot_crc_v1(mut snapshot_mem: &mut [u8], vm: VersionMap) -> usize {
    let state = Test {
        dummy: vec![
            Dummy {
                dummy: 123,
                string: "xxx".to_owned()
            };
            100
        ],
        field0: 0,
        field1: 1,
        field2: 2,
        field3: "test".to_owned(),
        field4: vec![4; 1024 * 10],
        field_x: 0,
    };

    // Serialize as v4.
    let mut snapshot = Snapshot::new(vm.clone(), 4);
    let size = snapshot.write_section("test", &state).unwrap();
    snapshot.save_with_crc64(&mut snapshot_mem).unwrap();
    size
}

pub fn criterion_benchmark(c: &mut Criterion) {
    let mut snapshot_mem = vec![0u8; 1024 * 1024 * 128];
    let mut vm = VersionMap::new();

    vm.new_version()
        .set_type_version(Test::type_id(), 2)
        .new_version()
        .set_type_version(Test::type_id(), 3)
        .new_version()
        .set_type_version(Test::type_id(), 4);

    let mut snapshot_len = bench_snapshot_v1(&mut snapshot_mem.as_mut_slice(), vm.clone());
    println!("Snapshot len {}", snapshot_len);

    c.bench_function("Serialize to v4", |b| {
        b.iter(|| {
            bench_snapshot_v1(
                black_box(&mut snapshot_mem.as_mut_slice()),
                black_box(vm.clone()),
            )
        })
    });
    c.bench_function("Deserialize to v4", |b| {
        b.iter(|| {
            bench_restore_v1(
                black_box(&mut snapshot_mem.as_slice()),
                black_box(vm.clone()),
            )
        })
    });

    snapshot_len = bench_snapshot_crc_v1(&mut snapshot_mem.as_mut_slice(), vm.clone());
    println!("Snapshot with crc64 len {}", snapshot_len);

    c.bench_function("Serialize with crc64 to v4", |b| {
        b.iter(|| {
            bench_snapshot_crc_v1(
                black_box(&mut snapshot_mem.as_mut_slice()),
                black_box(vm.clone()),
            )
        })
    });
    c.bench_function("Deserialize with crc64 from v4", |b| {
        b.iter(|| {
            bench_restore_crc_v1(
                black_box(&mut snapshot_mem.as_slice()),
                black_box(vm.clone()),
            )
        })
    });
}

criterion_group! {
    name = benches;
    config = Criterion::default().sample_size(50);
    targets = criterion_benchmark
}

criterion_main!(benches);
<|endoftext|>


<commit_before>use std::path::PathBuf;

use anyhow::Context;
use anyhow::{bail, Result};

use pueue_lib::network::message::*;
use pueue_lib::network::protocol::*;
use pueue_lib::task::{Task, TaskResult, TaskStatus};

use crate::commands::edit::edit_line_wrapper;
use crate::commands::get_state;

/// When restarting tasks, the remote state is queried and a [AddMessage]
/// is create from the existing task in the state.
///
/// This is done on the client-side, so we can easily edit the task before restarting it.
/// It's also necessary to get all failed tasks, in case the user specified the `--all-failed` flag.
#[allow(clippy::too_many_arguments)]
pub async fn restart(
    stream: &mut GenericStream,
    task_ids: Vec<usize>,
    all_failed: bool,
    failed_in_group: Option<String>,
    start_immediately: bool,
    stashed: bool,
    in_place: bool,
    edit_command: bool,
    edit_path: bool,
) -> Result<()> {
    let new_status = if stashed {
        TaskStatus::Stashed { enqueue_at: None }
    } else {
        TaskStatus::Queued
    };

    let state = get_state(stream).await?;

    // Filter to get done tasks
    let done_filter = |task: &Task| task.is_done();

    let (matching, mismatching) = if all_failed || failed_in_group.is_some() {
        // Either all failed tasks or all failed tasks of a specific group need to be restarted.

        // First we have to get all finished tasks (Done)
        let (matching, _) = if let Some(group) = failed_in_group {
            state.filter_tasks_of_group(done_filter, &group)
        } else {
            state.filter_tasks(done_filter, None)
        };

        // now pick the failed tasks
        let failed = matching
            .into_iter()
            .filter(|task_id| {
                let task = state.tasks.get(task_id).unwrap();
                !matches!(task.status, TaskStatus::Done(TaskResult::Success))
            })
            .collect();

        // We return an empty vec for the mismatching tasks, since there shouldn't be any.
        // Any User provided ids are ignored in this mode.
        (failed, Vec::new())
    } else if task_ids.is_empty() {
        bail!("Please provide the ids of the tasks you want to restart.");
    } else {
        state.filter_tasks(done_filter, Some(task_ids))
    };

    // Build a RestartMessage, if the tasks should be replaced instead of creating a copy of the
    // original task. This is only important, if replace is `True`.
    let mut restart_message = RestartMessage {
        tasks: Vec::new(),
        stashed,
        start_immediately,
    };

    // Go through all Done commands we found and restart them
    for task_id in &matching {
        let task = state.tasks.get(task_id).unwrap();
        let mut new_task = Task::from_task(task);
        new_task.status = new_status.clone();

        // Path and command can be edited, if the use specified the -e or -p flag.
        let mut command = None;
        let mut path = None;

        // Update the command if requested.
        if edit_command {
            command = Some(edit_line_wrapper(stream, *task_id, &task.command).await?);
        };

        // Update the path if requested.
        if edit_path {
            let str_path = task
                .path
                .to_str()
                .context("Failed to convert task path to string")?;
            let changed_path = edit_line_wrapper(stream, *task_id, str_path).await?;
            path = Some(PathBuf::from(changed_path));
        }

        // Add the tasks to the singular message, if we want to restart the tasks in-place.
        // And continue with the next task. The message will then be sent after the for loop.
        if in_place {
            restart_message.tasks.push(TaskToRestart {
                task_id: *task_id,
                command,
                path,
            });

            continue;
        }

        // In case we don't do in-place restarts, we have to add a new task.
        // Create a AddMessage to send the task to the daemon from the updated info and the old task.
        let add_task_message = Message::Add(AddMessage {
            command: command.unwrap_or_else(|| task.command.clone()),
            path: path.unwrap_or_else(|| task.path.clone()),
            envs: task.envs.clone(),
            start_immediately,
            stashed,
            group: task.group.clone(),
            enqueue_at: None,
            dependencies: Vec::new(),
            label: task.label.clone(),
            print_task_id: false,
        });

        // Send the cloned task to the daemon and abort on any failure messages.
        send_message(add_task_message, stream).await?;
        if let Message::Failure(message) = receive_message(stream).await? {
            bail!(message);
        };
    }

    // Send the singular in-place restart message to the daemon.
    if in_place {
        send_message(Message::Restart(restart_message), stream).await?;
        if let Message::Failure(message) = receive_message(stream).await? {
            bail!(message);
        };
    }

    if !matching.is_empty() {
        println!("Restarted tasks: {matching:?}");
    }
    if !mismatching.is_empty() {
        println!("Couldn't restart tasks: {mismatching:?}");
    }

    Ok(())
}
<commit_msg>fix: Don't use edit_line_wrapper in restart<commit_after>use std::path::PathBuf;

use anyhow::Context;
use anyhow::{bail, Result};

use pueue_lib::network::message::*;
use pueue_lib::network::protocol::*;
use pueue_lib::task::{Task, TaskResult, TaskStatus};

use crate::commands::edit::edit_line;
use crate::commands::get_state;

/// When restarting tasks, the remote state is queried and a [AddMessage]
/// is create from the existing task in the state.
///
/// This is done on the client-side, so we can easily edit the task before restarting it.
/// It's also necessary to get all failed tasks, in case the user specified the `--all-failed` flag.
#[allow(clippy::too_many_arguments)]
pub async fn restart(
    stream: &mut GenericStream,
    task_ids: Vec<usize>,
    all_failed: bool,
    failed_in_group: Option<String>,
    start_immediately: bool,
    stashed: bool,
    in_place: bool,
    edit_command: bool,
    edit_path: bool,
) -> Result<()> {
    let new_status = if stashed {
        TaskStatus::Stashed { enqueue_at: None }
    } else {
        TaskStatus::Queued
    };

    let state = get_state(stream).await?;

    // Filter to get done tasks
    let done_filter = |task: &Task| task.is_done();

    let (matching, mismatching) = if all_failed || failed_in_group.is_some() {
        // Either all failed tasks or all failed tasks of a specific group need to be restarted.

        // First we have to get all finished tasks (Done)
        let (matching, _) = if let Some(group) = failed_in_group {
            state.filter_tasks_of_group(done_filter, &group)
        } else {
            state.filter_tasks(done_filter, None)
        };

        // now pick the failed tasks
        let failed = matching
            .into_iter()
            .filter(|task_id| {
                let task = state.tasks.get(task_id).unwrap();
                !matches!(task.status, TaskStatus::Done(TaskResult::Success))
            })
            .collect();

        // We return an empty vec for the mismatching tasks, since there shouldn't be any.
        // Any User provided ids are ignored in this mode.
        (failed, Vec::new())
    } else if task_ids.is_empty() {
        bail!("Please provide the ids of the tasks you want to restart.");
    } else {
        state.filter_tasks(done_filter, Some(task_ids))
    };

    // Build a RestartMessage, if the tasks should be replaced instead of creating a copy of the
    // original task. This is only important, if replace is `True`.
    let mut restart_message = RestartMessage {
        tasks: Vec::new(),
        stashed,
        start_immediately,
    };

    // Go through all Done commands we found and restart them
    for task_id in &matching {
        let task = state.tasks.get(task_id).unwrap();
        let mut new_task = Task::from_task(task);
        new_task.status = new_status.clone();

        // Path and command can be edited, if the use specified the -e or -p flag.
        let mut command = None;
        let mut path = None;

        // Update the command if requested.
        if edit_command {
            command = Some(edit_line(&task.command)?);
        };

        // Update the path if requested.
        if edit_path {
            let str_path = task
                .path
                .to_str()
                .context("Failed to convert task path to string")?;
            let changed_path = edit_line(str_path)?;
            path = Some(PathBuf::from(changed_path));
        }

        // Add the tasks to the singular message, if we want to restart the tasks in-place.
        // And continue with the next task. The message will then be sent after the for loop.
        if in_place {
            restart_message.tasks.push(TaskToRestart {
                task_id: *task_id,
                command,
                path,
            });

            continue;
        }

        // In case we don't do in-place restarts, we have to add a new task.
        // Create a AddMessage to send the task to the daemon from the updated info and the old task.
        let add_task_message = Message::Add(AddMessage {
            command: command.unwrap_or_else(|| task.command.clone()),
            path: path.unwrap_or_else(|| task.path.clone()),
            envs: task.envs.clone(),
            start_immediately,
            stashed,
            group: task.group.clone(),
            enqueue_at: None,
            dependencies: Vec::new(),
            label: task.label.clone(),
            print_task_id: false,
        });

        // Send the cloned task to the daemon and abort on any failure messages.
        send_message(add_task_message, stream).await?;
        if let Message::Failure(message) = receive_message(stream).await? {
            bail!(message);
        };
    }

    // Send the singular in-place restart message to the daemon.
    if in_place {
        send_message(Message::Restart(restart_message), stream).await?;
        if let Message::Failure(message) = receive_message(stream).await? {
            bail!(message);
        };
    }

    if !matching.is_empty() {
        println!("Restarted tasks: {matching:?}");
    }
    if !mismatching.is_empty() {
        println!("Couldn't restart tasks: {mismatching:?}");
    }

    Ok(())
}
<|endoftext|>