<commit_before>//! This module handles fuzzy-searching of functions, structs and other symbols
//! by name across the whole workspace and dependencies.
//!
//! It works by building an incrementally-updated text-search index of all
//! symbols. The backbone of the index is the **awesome** `fst` crate by
//! @BurntSushi.
//!
//! In a nutshell, you give a set of strings to `fst`, and it builds a
//! finite state machine describing this set of strings. The strings which
//! could fuzzy-match a pattern can also be described by a finite state machine.
//! What is freaking cool is that you can now traverse both state machines in
//! lock-step to enumerate the strings which are both in the input set and
//! fuzz-match the query. Or, more formally, given two languages described by
//! FSTs, one can build a product FST which describes the intersection of the
//! languages.
//!
//! `fst` does not support cheap updating of the index, but it supports unioning
//! of state machines. So, to account for changing source code, we build an FST
//! for each library (which is assumed to never change) and an FST for each Rust
//! file in the current workspace, and run a query against the union of all
//! those FSTs.

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

use base_db::{
    salsa::{self, ParallelDatabase},
    SourceDatabaseExt, SourceRootId, Upcast,
};
use fst::{self, Streamer};
use hir::{
    db::HirDatabase,
    symbols::{FileSymbol, SymbolCollector},
    Crate, Module,
};
use rayon::prelude::*;
use rustc_hash::FxHashSet;

use crate::RootDatabase;

#[derive(Debug)]
pub struct Query {
    query: String,
    lowercased: String,
    only_types: bool,
    libs: bool,
    exact: bool,
    case_sensitive: bool,
    limit: usize,
}

impl Query {
    pub fn new(query: String) -> Query {
        let lowercased = query.to_lowercase();
        Query {
            query,
            lowercased,
            only_types: false,
            libs: false,
            exact: false,
            case_sensitive: false,
            limit: usize::max_value(),
        }
    }

    pub fn only_types(&mut self) {
        self.only_types = true;
    }

    pub fn libs(&mut self) {
        self.libs = true;
    }

    pub fn exact(&mut self) {
        self.exact = true;
    }

    pub fn case_sensitive(&mut self) {
        self.case_sensitive = true;
    }

    pub fn limit(&mut self, limit: usize) {
        self.limit = limit
    }
}

#[salsa::query_group(SymbolsDatabaseStorage)]
pub trait SymbolsDatabase: HirDatabase + SourceDatabaseExt + Upcast<dyn HirDatabase> {
    /// The symbol index for a given module. These modules should only be in source roots that
    /// are inside local_roots.
    fn module_symbols(&self, module: Module) -> Arc<SymbolIndex>;

    /// The symbol index for a given source root within library_roots.
    fn library_symbols(&self, source_root_id: SourceRootId) -> Arc<SymbolIndex>;

    /// The set of "local" (that is, from the current workspace) roots.
    /// Files in local roots are assumed to change frequently.
    #[salsa::input]
    fn local_roots(&self) -> Arc<FxHashSet<SourceRootId>>;

    /// The set of roots for crates.io libraries.
    /// Files in libraries are assumed to never change.
    #[salsa::input]
    fn library_roots(&self) -> Arc<FxHashSet<SourceRootId>>;
}

fn library_symbols(db: &dyn SymbolsDatabase, source_root_id: SourceRootId) -> Arc<SymbolIndex> {
    let _p = profile::span("library_symbols");

    // todo: this could be parallelized, once I figure out how to do that...
    let symbols = db
        .source_root_crates(source_root_id)
        .iter()
        .flat_map(|&krate| Crate::from(krate).modules(db.upcast()))
        // we specifically avoid calling SymbolsDatabase::module_symbols here, even they do the same thing,
        // as the index for a library is not going to really ever change, and we do not want to store each
        // module's index in salsa.
        .flat_map(|module| SymbolCollector::collect(db.upcast(), module))
        .collect();

    Arc::new(SymbolIndex::new(symbols))
}

fn module_symbols(db: &dyn SymbolsDatabase, module: Module) -> Arc<SymbolIndex> {
    let _p = profile::span("module_symbols");
    let symbols = SymbolCollector::collect(db.upcast(), module);
    Arc::new(SymbolIndex::new(symbols))
}

/// Need to wrap Snapshot to provide `Clone` impl for `map_with`
struct Snap<DB>(DB);
impl<DB: ParallelDatabase> Snap<salsa::Snapshot<DB>> {
    fn new(db: &DB) -> Self {
        Self(db.snapshot())
    }
}
impl<DB: ParallelDatabase> Clone for Snap<salsa::Snapshot<DB>> {
    fn clone(&self) -> Snap<salsa::Snapshot<DB>> {
        Snap(self.0.snapshot())
    }
}
impl<DB> std::ops::Deref for Snap<DB> {
    type Target = DB;

    fn deref(&self) -> &Self::Target {
        &self.0
    }
}

// Feature: Workspace Symbol
//
// Uses fuzzy-search to find types, modules and functions by name across your
// project and dependencies. This is **the** most useful feature, which improves code
// navigation tremendously. It mostly works on top of the built-in LSP
// functionality, however `#` and `*` symbols can be used to narrow down the
// search. Specifically,
//
// - `Foo` searches for `Foo` type in the current workspace
// - `foo#` searches for `foo` function in the current workspace
// - `Foo*` searches for `Foo` type among dependencies, including `stdlib`
// - `foo#*` searches for `foo` function among dependencies
//
// That is, `#` switches from "types" to all symbols, `*` switches from the current
// workspace to dependencies.
//
// Note that filtering does not currently work in VSCode due to the editor never
// sending the special symbols to the language server. Instead, you can configure
// the filtering via the `rust-analyzer.workspace.symbol.search.scope` and
// `rust-analyzer.workspace.symbol.search.kind` settings.
//
// |===
// | Editor  | Shortcut
//
// | VS Code | kbd:[Ctrl+T]
// |===
pub fn world_symbols(db: &RootDatabase, query: Query) -> Vec<FileSymbol> {
    let _p = profile::span("world_symbols").detail(|| query.query.clone());

    let indices: Vec<_> = if query.libs {
        db.library_roots()
            .par_iter()
            .map_with(Snap::new(db), |snap, &root| snap.library_symbols(root))
            .collect()
    } else {
        let mut modules = Vec::new();

        for &root in db.local_roots().iter() {
            let crates = db.source_root_crates(root);
            for &krate in crates.iter() {
                modules.extend(Crate::from(krate).modules(db));
            }
        }

        modules
            .par_iter()
            .map_with(Snap::new(db), |snap, &module| snap.module_symbols(module))
            .collect()
    };

    query.search(&indices)
}

pub fn crate_symbols(db: &RootDatabase, krate: Crate, query: Query) -> Vec<FileSymbol> {
    let _p = profile::span("crate_symbols").detail(|| format!("{:?}", query));

    let modules = krate.modules(db);
    let indices: Vec<_> = modules
        .par_iter()
        .map_with(Snap::new(db), |snap, &module| snap.module_symbols(module))
        .collect();

    query.search(&indices)
}

pub fn index_resolve(db: &RootDatabase, name: &str) -> Vec<FileSymbol> {
    let mut query = Query::new(name.to_string());
    query.exact();
    query.limit(4);
    world_symbols(db, query)
}

#[derive(Default)]
pub struct SymbolIndex {
    symbols: Vec<FileSymbol>,
    map: fst::Map<Vec<u8>>,
}

impl fmt::Debug for SymbolIndex {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        f.debug_struct("SymbolIndex").field("n_symbols", &self.symbols.len()).finish()
    }
}

impl PartialEq for SymbolIndex {
    fn eq(&self, other: &SymbolIndex) -> bool {
        self.symbols == other.symbols
    }
}

impl Eq for SymbolIndex {}

impl Hash for SymbolIndex {
    fn hash<H: Hasher>(&self, hasher: &mut H) {
        self.symbols.hash(hasher)
    }
}

impl SymbolIndex {
    fn new(mut symbols: Vec<FileSymbol>) -> SymbolIndex {
        fn cmp(lhs: &FileSymbol, rhs: &FileSymbol) -> Ordering {
            let lhs_chars = lhs.name.chars().map(|c| c.to_ascii_lowercase());
            let rhs_chars = rhs.name.chars().map(|c| c.to_ascii_lowercase());
            lhs_chars.cmp(rhs_chars)
        }

        symbols.par_sort_by(cmp);

        let mut builder = fst::MapBuilder::memory();

        let mut last_batch_start = 0;

        for idx in 0..symbols.len() {
            if let Some(next_symbol) = symbols.get(idx + 1) {
                if cmp(&symbols[last_batch_start], next_symbol) == Ordering::Equal {
                    continue;
                }
            }

            let start = last_batch_start;
            let end = idx + 1;
            last_batch_start = end;

            let key = symbols[start].name.as_str().to_ascii_lowercase();
            let value = SymbolIndex::range_to_map_value(start, end);

            builder.insert(key, value).unwrap();
        }

        let map = fst::Map::new(builder.into_inner().unwrap()).unwrap();
        SymbolIndex { symbols, map }
    }

    pub fn len(&self) -> usize {
        self.symbols.len()
    }

    pub fn memory_size(&self) -> usize {
        self.map.as_fst().size() + self.symbols.len() * mem::size_of::<FileSymbol>()
    }

    fn range_to_map_value(start: usize, end: usize) -> u64 {
        debug_assert![start <= (std::u32::MAX as usize)];
        debug_assert![end <= (std::u32::MAX as usize)];

        ((start as u64) << 32) | end as u64
    }

    fn map_value_to_range(value: u64) -> (usize, usize) {
        let end = value as u32 as usize;
        let start = (value >> 32) as usize;
        (start, end)
    }
}

impl Query {
    pub(crate) fn search(self, indices: &[Arc<SymbolIndex>]) -> Vec<FileSymbol> {
        let _p = profile::span("symbol_index::Query::search");
        let mut op = fst::map::OpBuilder::new();
        for file_symbols in indices.iter() {
            let automaton = fst::automaton::Subsequence::new(&self.lowercased);
            op = op.add(file_symbols.map.search(automaton))
        }
        let mut stream = op.union();
        let mut res = Vec::new();
        while let Some((_, indexed_values)) = stream.next() {
            for indexed_value in indexed_values {
                let symbol_index = &indices[indexed_value.index];
                let (start, end) = SymbolIndex::map_value_to_range(indexed_value.value);

                for symbol in &symbol_index.symbols[start..end] {
                    if self.only_types && !symbol.kind.is_type() {
                        continue;
                    }
                    if self.exact {
                        if symbol.name != self.query {
                            continue;
                        }
                    } else if self.case_sensitive {
                        if self.query.chars().any(|c| !symbol.name.contains(c)) {
                            continue;
                        }
                    }

                    res.push(symbol.clone());
                    if res.len() >= self.limit {
                        return res;
                    }
                }
            }
        }
        res
    }
}

#[cfg(test)]
mod tests {

    use base_db::fixture::WithFixture;
    use expect_test::expect_file;
    use hir::symbols::SymbolCollector;

    use super::*;

    #[test]
    fn test_symbol_index_collection() {
        let (db, _) = RootDatabase::with_many_files(
            r#"
//- /main.rs

macro_rules! macro_rules_macro {
    () => {}
};

macro_rules! define_struct {
    () => {
        struct StructFromMacro;
    }
};

define_struct!();

macro Macro { }

struct Struct;
enum Enum {
    A, B
}
union Union {}

impl Struct {
    fn impl_fn() {}
}

trait Trait {
    fn trait_fn(&self);
}

fn main() {
    struct StructInFn;
}

const CONST: u32 = 1;
static STATIC: &'static str = "2";
type Alias = Struct;

mod a_mod {
    struct StructInModA;
}

const _: () = {
    struct StructInUnnamedConst;

    ()
};

const CONST_WITH_INNER: () = {
    struct StructInNamedConst;

    ()
};

mod b_mod;

//- /b_mod.rs
struct StructInModB;
        "#,
        );

        let symbols: Vec<_> = Crate::from(db.test_crate())
            .modules(&db)
            .into_iter()
            .map(|module_id| {
                let mut symbols = SymbolCollector::collect(&db, module_id);
                symbols.sort_by_key(|it| it.name.clone());
                (module_id, symbols)
            })
            .collect();

        expect_file!["./test_data/test_symbol_index_collection.txt"].assert_debug_eq(&symbols);
    }
}
<commit_msg>Auto merge of #12339 - matklad:dead, r=matklad<commit_after>//! This module handles fuzzy-searching of functions, structs and other symbols
//! by name across the whole workspace and dependencies.
//!
//! It works by building an incrementally-updated text-search index of all
//! symbols. The backbone of the index is the **awesome** `fst` crate by
//! @BurntSushi.
//!
//! In a nutshell, you give a set of strings to `fst`, and it builds a
//! finite state machine describing this set of strings. The strings which
//! could fuzzy-match a pattern can also be described by a finite state machine.
//! What is freaking cool is that you can now traverse both state machines in
//! lock-step to enumerate the strings which are both in the input set and
//! fuzz-match the query. Or, more formally, given two languages described by
//! FSTs, one can build a product FST which describes the intersection of the
//! languages.
//!
//! `fst` does not support cheap updating of the index, but it supports unioning
//! of state machines. So, to account for changing source code, we build an FST
//! for each library (which is assumed to never change) and an FST for each Rust
//! file in the current workspace, and run a query against the union of all
//! those FSTs.

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

use base_db::{
    salsa::{self, ParallelDatabase},
    SourceDatabaseExt, SourceRootId, Upcast,
};
use fst::{self, Streamer};
use hir::{
    db::HirDatabase,
    symbols::{FileSymbol, SymbolCollector},
    Crate, Module,
};
use rayon::prelude::*;
use rustc_hash::FxHashSet;

use crate::RootDatabase;

#[derive(Debug)]
pub struct Query {
    query: String,
    lowercased: String,
    only_types: bool,
    libs: bool,
    exact: bool,
    case_sensitive: bool,
    limit: usize,
}

impl Query {
    pub fn new(query: String) -> Query {
        let lowercased = query.to_lowercase();
        Query {
            query,
            lowercased,
            only_types: false,
            libs: false,
            exact: false,
            case_sensitive: false,
            limit: usize::max_value(),
        }
    }

    pub fn only_types(&mut self) {
        self.only_types = true;
    }

    pub fn libs(&mut self) {
        self.libs = true;
    }

    pub fn exact(&mut self) {
        self.exact = true;
    }

    pub fn case_sensitive(&mut self) {
        self.case_sensitive = true;
    }

    pub fn limit(&mut self, limit: usize) {
        self.limit = limit
    }
}

#[salsa::query_group(SymbolsDatabaseStorage)]
pub trait SymbolsDatabase: HirDatabase + SourceDatabaseExt + Upcast<dyn HirDatabase> {
    /// The symbol index for a given module. These modules should only be in source roots that
    /// are inside local_roots.
    fn module_symbols(&self, module: Module) -> Arc<SymbolIndex>;

    /// The symbol index for a given source root within library_roots.
    fn library_symbols(&self, source_root_id: SourceRootId) -> Arc<SymbolIndex>;

    /// The set of "local" (that is, from the current workspace) roots.
    /// Files in local roots are assumed to change frequently.
    #[salsa::input]
    fn local_roots(&self) -> Arc<FxHashSet<SourceRootId>>;

    /// The set of roots for crates.io libraries.
    /// Files in libraries are assumed to never change.
    #[salsa::input]
    fn library_roots(&self) -> Arc<FxHashSet<SourceRootId>>;
}

fn library_symbols(db: &dyn SymbolsDatabase, source_root_id: SourceRootId) -> Arc<SymbolIndex> {
    let _p = profile::span("library_symbols");

    // todo: this could be parallelized, once I figure out how to do that...
    let symbols = db
        .source_root_crates(source_root_id)
        .iter()
        .flat_map(|&krate| Crate::from(krate).modules(db.upcast()))
        // we specifically avoid calling SymbolsDatabase::module_symbols here, even they do the same thing,
        // as the index for a library is not going to really ever change, and we do not want to store each
        // module's index in salsa.
        .flat_map(|module| SymbolCollector::collect(db.upcast(), module))
        .collect();

    Arc::new(SymbolIndex::new(symbols))
}

fn module_symbols(db: &dyn SymbolsDatabase, module: Module) -> Arc<SymbolIndex> {
    let _p = profile::span("module_symbols");
    let symbols = SymbolCollector::collect(db.upcast(), module);
    Arc::new(SymbolIndex::new(symbols))
}

/// Need to wrap Snapshot to provide `Clone` impl for `map_with`
struct Snap<DB>(DB);
impl<DB: ParallelDatabase> Snap<salsa::Snapshot<DB>> {
    fn new(db: &DB) -> Self {
        Self(db.snapshot())
    }
}
impl<DB: ParallelDatabase> Clone for Snap<salsa::Snapshot<DB>> {
    fn clone(&self) -> Snap<salsa::Snapshot<DB>> {
        Snap(self.0.snapshot())
    }
}
impl<DB> std::ops::Deref for Snap<DB> {
    type Target = DB;

    fn deref(&self) -> &Self::Target {
        &self.0
    }
}

// Feature: Workspace Symbol
//
// Uses fuzzy-search to find types, modules and functions by name across your
// project and dependencies. This is **the** most useful feature, which improves code
// navigation tremendously. It mostly works on top of the built-in LSP
// functionality, however `#` and `*` symbols can be used to narrow down the
// search. Specifically,
//
// - `Foo` searches for `Foo` type in the current workspace
// - `foo#` searches for `foo` function in the current workspace
// - `Foo*` searches for `Foo` type among dependencies, including `stdlib`
// - `foo#*` searches for `foo` function among dependencies
//
// That is, `#` switches from "types" to all symbols, `*` switches from the current
// workspace to dependencies.
//
// Note that filtering does not currently work in VSCode due to the editor never
// sending the special symbols to the language server. Instead, you can configure
// the filtering via the `rust-analyzer.workspace.symbol.search.scope` and
// `rust-analyzer.workspace.symbol.search.kind` settings.
//
// |===
// | Editor  | Shortcut
//
// | VS Code | kbd:[Ctrl+T]
// |===
pub fn world_symbols(db: &RootDatabase, query: Query) -> Vec<FileSymbol> {
    let _p = profile::span("world_symbols").detail(|| query.query.clone());

    let indices: Vec<_> = if query.libs {
        db.library_roots()
            .par_iter()
            .map_with(Snap::new(db), |snap, &root| snap.library_symbols(root))
            .collect()
    } else {
        let mut modules = Vec::new();

        for &root in db.local_roots().iter() {
            let crates = db.source_root_crates(root);
            for &krate in crates.iter() {
                modules.extend(Crate::from(krate).modules(db));
            }
        }

        modules
            .par_iter()
            .map_with(Snap::new(db), |snap, &module| snap.module_symbols(module))
            .collect()
    };

    query.search(&indices)
}

pub fn crate_symbols(db: &RootDatabase, krate: Crate, query: Query) -> Vec<FileSymbol> {
    let _p = profile::span("crate_symbols").detail(|| format!("{:?}", query));

    let modules = krate.modules(db);
    let indices: Vec<_> = modules
        .par_iter()
        .map_with(Snap::new(db), |snap, &module| snap.module_symbols(module))
        .collect();

    query.search(&indices)
}

#[derive(Default)]
pub struct SymbolIndex {
    symbols: Vec<FileSymbol>,
    map: fst::Map<Vec<u8>>,
}

impl fmt::Debug for SymbolIndex {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        f.debug_struct("SymbolIndex").field("n_symbols", &self.symbols.len()).finish()
    }
}

impl PartialEq for SymbolIndex {
    fn eq(&self, other: &SymbolIndex) -> bool {
        self.symbols == other.symbols
    }
}

impl Eq for SymbolIndex {}

impl Hash for SymbolIndex {
    fn hash<H: Hasher>(&self, hasher: &mut H) {
        self.symbols.hash(hasher)
    }
}

impl SymbolIndex {
    fn new(mut symbols: Vec<FileSymbol>) -> SymbolIndex {
        fn cmp(lhs: &FileSymbol, rhs: &FileSymbol) -> Ordering {
            let lhs_chars = lhs.name.chars().map(|c| c.to_ascii_lowercase());
            let rhs_chars = rhs.name.chars().map(|c| c.to_ascii_lowercase());
            lhs_chars.cmp(rhs_chars)
        }

        symbols.par_sort_by(cmp);

        let mut builder = fst::MapBuilder::memory();

        let mut last_batch_start = 0;

        for idx in 0..symbols.len() {
            if let Some(next_symbol) = symbols.get(idx + 1) {
                if cmp(&symbols[last_batch_start], next_symbol) == Ordering::Equal {
                    continue;
                }
            }

            let start = last_batch_start;
            let end = idx + 1;
            last_batch_start = end;

            let key = symbols[start].name.as_str().to_ascii_lowercase();
            let value = SymbolIndex::range_to_map_value(start, end);

            builder.insert(key, value).unwrap();
        }

        let map = fst::Map::new(builder.into_inner().unwrap()).unwrap();
        SymbolIndex { symbols, map }
    }

    pub fn len(&self) -> usize {
        self.symbols.len()
    }

    pub fn memory_size(&self) -> usize {
        self.map.as_fst().size() + self.symbols.len() * mem::size_of::<FileSymbol>()
    }

    fn range_to_map_value(start: usize, end: usize) -> u64 {
        debug_assert![start <= (std::u32::MAX as usize)];
        debug_assert![end <= (std::u32::MAX as usize)];

        ((start as u64) << 32) | end as u64
    }

    fn map_value_to_range(value: u64) -> (usize, usize) {
        let end = value as u32 as usize;
        let start = (value >> 32) as usize;
        (start, end)
    }
}

impl Query {
    pub(crate) fn search(self, indices: &[Arc<SymbolIndex>]) -> Vec<FileSymbol> {
        let _p = profile::span("symbol_index::Query::search");
        let mut op = fst::map::OpBuilder::new();
        for file_symbols in indices.iter() {
            let automaton = fst::automaton::Subsequence::new(&self.lowercased);
            op = op.add(file_symbols.map.search(automaton))
        }
        let mut stream = op.union();
        let mut res = Vec::new();
        while let Some((_, indexed_values)) = stream.next() {
            for indexed_value in indexed_values {
                let symbol_index = &indices[indexed_value.index];
                let (start, end) = SymbolIndex::map_value_to_range(indexed_value.value);

                for symbol in &symbol_index.symbols[start..end] {
                    if self.only_types && !symbol.kind.is_type() {
                        continue;
                    }
                    if self.exact {
                        if symbol.name != self.query {
                            continue;
                        }
                    } else if self.case_sensitive {
                        if self.query.chars().any(|c| !symbol.name.contains(c)) {
                            continue;
                        }
                    }

                    res.push(symbol.clone());
                    if res.len() >= self.limit {
                        return res;
                    }
                }
            }
        }
        res
    }
}

#[cfg(test)]
mod tests {

    use base_db::fixture::WithFixture;
    use expect_test::expect_file;
    use hir::symbols::SymbolCollector;

    use super::*;

    #[test]
    fn test_symbol_index_collection() {
        let (db, _) = RootDatabase::with_many_files(
            r#"
//- /main.rs

macro_rules! macro_rules_macro {
    () => {}
};

macro_rules! define_struct {
    () => {
        struct StructFromMacro;
    }
};

define_struct!();

macro Macro { }

struct Struct;
enum Enum {
    A, B
}
union Union {}

impl Struct {
    fn impl_fn() {}
}

trait Trait {
    fn trait_fn(&self);
}

fn main() {
    struct StructInFn;
}

const CONST: u32 = 1;
static STATIC: &'static str = "2";
type Alias = Struct;

mod a_mod {
    struct StructInModA;
}

const _: () = {
    struct StructInUnnamedConst;

    ()
};

const CONST_WITH_INNER: () = {
    struct StructInNamedConst;

    ()
};

mod b_mod;

//- /b_mod.rs
struct StructInModB;
        "#,
        );

        let symbols: Vec<_> = Crate::from(db.test_crate())
            .modules(&db)
            .into_iter()
            .map(|module_id| {
                let mut symbols = SymbolCollector::collect(&db, module_id);
                symbols.sort_by_key(|it| it.name.clone());
                (module_id, symbols)
            })
            .collect();

        expect_file!["./test_data/test_symbol_index_collection.txt"].assert_debug_eq(&symbols);
    }
}
<|endoftext|>


<commit_before>use std::ops::{Add, Neg};
use num::bigint::BigInt;
use num::{Integer, Zero, ToPrimitive};

use euclid::*;

use gameplay_constants::*;
use types::*;

// A "vector" in the world, possibly going up or down levels

// TODO: If memory use becomes a problem, it may be worth converting this to
// using a persistent data structure and sharing the coords deque as
// much as possible

#[derive(Clone)]
pub struct Delta {
    pub zdelta: i16, // How far DOWN the target is

    // TODO: maybe find a faster bigint
    pub coords: TypedVector2D<BigInt, UniverseSpace>,
}

impl Delta {
    // TODO: from
    // pub fn new(top: UVec) -> Delta {
    //     Delta {
    //         zdelta: 0,
    //         coords: TypedVector2D::new(BigInt::from(top.x), BigInt::from(top.y)),
    //     }
    // }

    pub fn zero() -> Delta {
        Delta {
            zdelta: 0,
            coords: TypedVector2D::new(BigInt::zero(), BigInt::zero())
        }
    }

    fn div_vec<T : Integer + From<u32>, U>(mut v: TypedVector2D<T, U>) -> TypedVector2D<T, U> {
        v.x = v.x.div_floor(&T::from(ZOOM_SCALE));
        v.y = v.y.div_floor(&T::from(ZOOM_SCALE));
        v
    }

    fn mult_vec<T : Integer + From<u32>, U>(mut v: TypedVector2D<T, U>) -> TypedVector2D<T, U> {
        v.x = v.x * (T::from(ZOOM_SCALE));
        v.y = v.y * (T::from(ZOOM_SCALE));
        v
    }

    pub fn shift_target_down(mut self) -> Delta {
        self.coords.x = self.coords.x * (BigInt::from(ZOOM_SCALE));
        self.coords.y = self.coords.y * (BigInt::from(ZOOM_SCALE));

        self.zdelta += 1;
        self
    }

    pub fn shift_target_down_ref(&self) -> Delta {
        self.clone().shift_target_down()
    }

    pub fn truncate_target_up(&mut self) -> () {
        self.coords.x = self.coords.x.div_floor(&BigInt::from(ZOOM_SCALE));
        self.coords.y = self.coords.y.div_floor(&BigInt::from(ZOOM_SCALE));

        self.zdelta -= 1;
    }

    pub fn to_uvec(&self) -> UVec {
        UVec::new(self.coords.x.to_i32().unwrap(), self.coords.y.to_i32().unwrap())
    }

}

impl PartialEq for Delta {
    fn eq(&self, other: &Delta) -> bool {
        self.zdelta == other.zdelta && self.coords == other.coords
    }
}

impl Eq for Delta {}

impl<'a> Add<&'a Delta> for &'a Delta {
    type Output = Delta;

    fn add(self, other: &Delta) -> Delta {
        assert!(self.zdelta == other.zdelta);

        Delta {
            zdelta: self.zdelta,
            coords: TypedVector2D::new(self.coords.x.clone() + other.coords.x.clone(), self.coords.y.clone() + other.coords.y.clone()),
        }
    }
}

impl Neg for Delta {
    type Output = Delta;

    fn neg(mut self) -> Delta {
        self.coords.x = -self.coords.x;
        self.coords.y = -self.coords.y;
        self
    }
}
<commit_msg>Fill out Delta more<commit_after>use std::ops::{Add, Neg, Sub};
use num::bigint::BigInt;
use num::{Integer, ToPrimitive, Zero};

use euclid::*;

use gameplay_constants::*;
use types::*;

// A "vector" in the world, possibly going up or down levels

// TODO: If memory use becomes a problem, it may be worth converting this to
// using a persistent data structure and sharing the coords deque as
// much as possible

#[derive(Clone)]
pub struct Delta {
    pub zdelta: i16, // How far DOWN the target is

    // TODO: maybe find a faster bigint
    pub coords: TypedVector2D<BigInt, UniverseSpace>,
}

impl Delta {
    // TODO: from
    // pub fn new(top: UVec) -> Delta {
    //     Delta {
    //         zdelta: 0,
    //         coords: TypedVector2D::new(BigInt::from(top.x), BigInt::from(top.y)),
    //     }
    // }

    pub fn zero() -> Delta {
        Delta {
            zdelta: 0,
            coords: TypedVector2D::new(BigInt::zero(), BigInt::zero()),
        }
    }

    fn div_vec<T: Integer + From<u32>, U>(mut v: TypedVector2D<T, U>) -> TypedVector2D<T, U> {
        v.x = v.x.div_floor(&T::from(ZOOM_SCALE));
        v.y = v.y.div_floor(&T::from(ZOOM_SCALE));
        v
    }

    fn mult_vec<T: Integer + From<u32>, U>(mut v: TypedVector2D<T, U>) -> TypedVector2D<T, U> {
        v.x = v.x * (T::from(ZOOM_SCALE));
        v.y = v.y * (T::from(ZOOM_SCALE));
        v
    }

    pub fn shift_target_down(mut self) -> Delta {
        self.coords.x = self.coords.x * (BigInt::from(ZOOM_SCALE));
        self.coords.y = self.coords.y * (BigInt::from(ZOOM_SCALE));

        self.zdelta += 1;
        self
    }

    pub fn shift_target_down_ref(&self) -> Delta {
        self.clone().shift_target_down()
    }

    pub fn truncate_target_up(&mut self) -> () {
        self.coords.x = self.coords.x.div_floor(&BigInt::from(ZOOM_SCALE));
        self.coords.y = self.coords.y.div_floor(&BigInt::from(ZOOM_SCALE));

        self.zdelta -= 1;
    }

    pub fn to_uvec(&self) -> UVec {
        UVec::new(self.coords.x.to_i32().unwrap(), self.coords.y.to_i32().unwrap())
    }

}

impl PartialEq for Delta {
    fn eq(&self, other: &Delta) -> bool {
        self.zdelta == other.zdelta && self.coords == other.coords
    }
}

impl Eq for Delta {}

impl Add<Delta> for Delta {
    type Output = Delta;

    fn add(self, other: Delta) -> Delta {
        assert!(self.zdelta == other.zdelta);

        Delta {
            zdelta: self.zdelta,
            coords: TypedVector2D::new(
                self.coords.x + other.coords.x,
                self.coords.y + other.coords.y,
            ),
        }
    }
}

impl<'a> Add<&'a Delta> for &'a Delta {
    type Output = Delta;

    fn add(self, other: &Delta) -> Delta {
        assert!(self.zdelta == other.zdelta);

        Delta {
            zdelta: self.zdelta,
            coords: TypedVector2D::new(
                self.coords.x.clone() + other.coords.x.clone(),
                self.coords.y.clone() + other.coords.y.clone(),
            ),
        }
    }
}

impl Sub<Delta> for Delta {
    type Output = Delta;

    fn sub(self, other: Delta) -> Delta {
        assert!(self.zdelta == other.zdelta);

        Delta {
            zdelta: self.zdelta,
            coords: TypedVector2D::new(
                self.coords.x - other.coords.x,
                self.coords.y - other.coords.y,
            ),
        }
    }
}

impl<'a> Sub<&'a Delta> for &'a Delta {
    type Output = Delta;

    fn sub(self, other: &Delta) -> Delta {
        assert!(self.zdelta == other.zdelta);

        Delta {
            zdelta: self.zdelta,
            coords: TypedVector2D::new(
                self.coords.x.clone() - other.coords.x.clone(),
                self.coords.y.clone() - other.coords.y.clone(),
            ),
        }
    }
}

impl Neg for Delta {
    type Output = Delta;

    fn neg(mut self) -> Delta {
        self.coords.x = -self.coords.x;
        self.coords.y = -self.coords.y;
        self
    }
}

impl From<ChildVec> for Delta {
    fn from(c: ChildVec) -> Delta {
        Delta {
            zdelta: 0,
            coords: TypedVector2D::new(BigInt::from(c.x), BigInt::from(c.y)),
        }
    }
}
<|endoftext|>


<commit_before>use serde::de::{Deserialize, Deserializer, Error};

use types::*;

#[derive(Debug, Clone, PartialEq, PartialOrd, Deserialize)]
pub struct User {
    pub id: Integer,
    pub first_name: String,
    pub last_name: Option<String>,
    pub username: Option<String>,
}

#[derive(Debug, Clone, PartialEq, PartialOrd)]
pub struct Group {
    pub id: Integer,
    pub title: String,
    pub all_members_are_administrators: bool,
}

#[derive(Debug, Clone, PartialEq, PartialOrd)]
pub struct Supergroup {
    pub id: Integer,
    pub title: String,
    pub username: Option<String>,
}

#[derive(Debug, Clone, PartialEq, PartialOrd)]
pub struct Channel {
    pub id: Integer,
    pub title: String,
    pub username: Option<String>,
}

#[derive(Debug, Clone, PartialEq, PartialOrd)]
pub enum Chat {
    Private(User),
    Group(Group),
    Supergroup(Supergroup),
    Channel(Channel),
    #[doc(hidden)]
    Unknown(RawChat),
}

impl Chat {
    pub fn id(&self) -> Integer {
        match *self {
            Chat::Private(ref x) => x.id,
            Chat::Group(ref x) => x.id,
            Chat::Supergroup(ref x) => x.id,
            Chat::Channel(ref x) => x.id,
            Chat::Unknown(ref x) => x.id,
        }
    }
}

impl Deserialize for Chat {
    fn deserialize<D>(deserializer: D) -> Result<Chat, D::Error> where D: Deserializer {
        let raw: RawChat = Deserialize::deserialize(deserializer)?;

        macro_rules! required_field {
            ($name:ident) => {{
                match raw.$name {
                    Some(val) => val,
                    None => return Err(D::Error::missing_field(stringify!($name)))
                }
            }}
        }

        Ok(match raw.type_.as_ref() {
            "private" => {
                Chat::Private(User {
                    id: raw.id,
                    username: raw.username,
                    first_name: required_field!(first_name),
                    last_name: raw.last_name,
                })
            },
            "group" => {
                Chat::Group(Group {
                    id: raw.id,
                    title: required_field!(title),
                    all_members_are_administrators: required_field!(all_members_are_administrators),
                })
            },
            "supergroup" => Chat::Supergroup(Supergroup {
                id: raw.id,
                title: required_field!(title),
                username: raw.username,
            }),
            "channel" => Chat::Channel(Channel {
                id: raw.id,
                title: required_field!(title),
                username: raw.username,
            }),
            _ => Chat::Unknown(raw)
        })
    }
}

#[derive(Debug, Clone, PartialEq, PartialOrd, Deserialize)]
pub struct RawChat {
    pub id: Integer,
    #[serde(rename="type")]
    pub type_: String,
    pub title: Option<String>,
    pub username: Option<String>,
    pub first_name: Option<String>,
    pub last_name: Option<String>,
    pub all_members_are_administrators: Option<bool>,
}
<commit_msg>docs: document chat types<commit_after>use serde::de::{Deserialize, Deserializer, Error};

use types::*;

/// This object represents a Telegram user or bot.
#[derive(Debug, Clone, PartialEq, PartialOrd, Deserialize)]
pub struct User {
    /// Unique identifier for this user or bot.
    pub id: Integer,
    /// User‘s or bot’s first name.
    pub first_name: String,
    /// User‘s or bot’s last name.
    pub last_name: Option<String>,
    /// User‘s or bot’s username.
    pub username: Option<String>,
}

/// This object represents a group.
#[derive(Debug, Clone, PartialEq, PartialOrd)]
pub struct Group {
    /// Unique identifier for this chat.
    pub id: Integer,
    /// Title, for supergroups, channels and group chats.
    pub title: String,
    /// True if a group has ‘All Members Are Admins’ enabled.
    pub all_members_are_administrators: bool,
}

/// This object represents a supergroup.
#[derive(Debug, Clone, PartialEq, PartialOrd)]
pub struct Supergroup {
    /// Unique identifier for this chat.
    pub id: Integer,
    /// Title, for supergroups, channels and group chats.
    pub title: String,
    /// Username for supergroup.
    pub username: Option<String>,
}

/// This object represents a channel.
#[derive(Debug, Clone, PartialEq, PartialOrd)]
pub struct Channel {
    /// Unique identifier for this chat.
    pub id: Integer,
    /// Title, for supergroups, channels and group chats.
    pub title: String,
    /// Username for channel.
    pub username: Option<String>,
}

/// This object represents a chat.
#[derive(Debug, Clone, PartialEq, PartialOrd)]
pub enum Chat {
    Private(User),
    Group(Group),
    Supergroup(Supergroup),
    Channel(Channel),
    #[doc(hidden)]
    Unknown(RawChat),
}

impl Chat {
    pub fn id(&self) -> Integer {
        match *self {
            Chat::Private(ref x) => x.id,
            Chat::Group(ref x) => x.id,
            Chat::Supergroup(ref x) => x.id,
            Chat::Channel(ref x) => x.id,
            Chat::Unknown(ref x) => x.id,
        }
    }
}

impl Deserialize for Chat {
    fn deserialize<D>(deserializer: D) -> Result<Chat, D::Error> where D: Deserializer {
        let raw: RawChat = Deserialize::deserialize(deserializer)?;

        macro_rules! required_field {
            ($name:ident) => {{
                match raw.$name {
                    Some(val) => val,
                    None => return Err(D::Error::missing_field(stringify!($name)))
                }
            }}
        }

        Ok(match raw.type_.as_ref() {
            "private" => {
                Chat::Private(User {
                    id: raw.id,
                    username: raw.username,
                    first_name: required_field!(first_name),
                    last_name: raw.last_name,
                })
            },
            "group" => {
                Chat::Group(Group {
                    id: raw.id,
                    title: required_field!(title),
                    all_members_are_administrators: required_field!(all_members_are_administrators),
                })
            },
            "supergroup" => Chat::Supergroup(Supergroup {
                id: raw.id,
                title: required_field!(title),
                username: raw.username,
            }),
            "channel" => Chat::Channel(Channel {
                id: raw.id,
                title: required_field!(title),
                username: raw.username,
            }),
            _ => Chat::Unknown(raw)
        })
    }
}

/// This object represents a chat, directly mapped.
#[derive(Debug, Clone, PartialEq, PartialOrd, Deserialize)]
pub struct RawChat {
    /// Unique identifier for this chat.
    pub id: Integer,
    /// Type of chat, can be either “private”, “group”, “supergroup” or “channel”
    #[serde(rename="type")]
    pub type_: String,
    /// Title, for supergroups, channels and group chats
    pub title: Option<String>,
    /// Username, for private chats, supergroups and channels if available
    pub username: Option<String>,
    /// First name of the other party in a private chat
    pub first_name: Option<String>,
    /// Last name of the other party in a private chat
    pub last_name: Option<String>,
    /// True if a group has ‘All Members Are Admins’ enabled.
    pub all_members_are_administrators: Option<bool>,
}
<|endoftext|>


<commit_before>// Copyright 2016 Pavel Kiselev

// My implementation of Eller's Algorithm, following instructions at http://www.neocomputer.org/projects/eller.html
// Comments detailing algorithm steps are mostly copypasted from there

#![allow(dead_code)]

use rand::{Rng,thread_rng,ThreadRng};
use std::collections::HashMap;
use std::fmt;

#[derive(Debug,Clone,Copy)]
struct Cell {
    set: usize,
    rw: bool,
    bw: bool,
}

pub struct EllerMaze {
    maze: Vec<Vec<Cell>>,
}

// Somewhat changes look of generated mazes
pub enum MazeOrient {
    Normal,
    Vertical,
    Horizontal,
}

impl EllerMaze {
    pub fn generate(width: usize, height: usize, orient: MazeOrient) -> EllerMaze {

        let mut rng = thread_rng();

        //Closure for changing the maze generated (as proposed on neocomputer.org in "Example
        //mazes" section
        let verticality = |orient: &MazeOrient, rng: &mut ThreadRng, is_right: bool| -> bool {
            if is_right {
                match *orient {
                    MazeOrient::Normal => rng.gen(),
                    MazeOrient::Vertical => rng.gen() || rng.gen(),
                    MazeOrient::Horizontal => rng.gen() && rng.gen(),
                }
            } else {
                match *orient {
                    MazeOrient::Normal => rng.gen(),
                    MazeOrient::Vertical => rng.gen() && rng.gen(),
                    MazeOrient::Horizontal => rng.gen() || rng.gen(),
                }
            }
        };

        let mut maze: Vec<Vec<Cell>> = Vec::with_capacity(height);

        // 1. Create the first row. No cells will be members of any set
        let mut row = vec![Cell { set: 0, rw: false, bw: false }; width];

        row[width-1].rw = true; // The last one always has a wall.

        let mut sets: HashMap<usize, Vec<usize>> = HashMap::with_capacity(width);

        for count_iterations in 0..height {

            sets.drain(); // Empty the db

            // Create a database of indexes for all set members
            for (i,cell) in row.iter().enumerate() {
                if sets.contains_key(&cell.set) {
                    let mut vec = sets.get_mut(&cell.set).expect("Cannot get sets to compete the HashMap");
                    (*vec).push(i);
                } else {
                    sets.insert(cell.set, vec![i]);
                }
            }

            // 2. Join any cells not members of a set to their own unique set
            let no_set = sets.remove(&0).unwrap_or(vec![]); //Get indexes of cells without set, or init with empty vec
            for i in no_set {
                let mut j = 1;
                while row[i].set == 0 {
                    if sets.contains_key(&j) {
                        j += 1;
                    } else {
                        row[i].set = j;
                        sets.insert(j, vec![i]);
                    }
                }
            }

            // 3. Create right-walls, moving from left to right:
            for i in 0..row.len()-1 {
                // - If the current cell and the cell to the right are members of the same set, always create a wall between them. (This prevents loops)
                if row[i].set == row[i+1].set {
                    row[i].rw = true;
                    continue;
                }
                // - Randomly decide to add a wall or not:
                if verticality(&orient, &mut rng, true) {
                    row[i].rw = true;
                } else {
                    // - If you decide not to add a wall, union the sets to which the current cell and the cell to the right are members.
                    let mut set2 = sets.remove(&row[i+1].set).expect("Can't get set for union");
                    let mut set1 = sets.get_mut(&row[i].set).expect("Can't get set to union with");
                    for j in set2.iter() {
                        row[*j].set = row[i].set;
                    }
                    set1.append(&mut set2);
                }
            }

            // 4. Create bottom-walls, moving from left to right:
            // 4.1. Randomly decide to add a wall or not. Make sure that each set has at least one cell without a bottom-wall (This prevents isolations)
            // - If a cell is the only member of its set, do not create a bottom-wall
            // - If a cell is the only member of its set without a bottom-wall, do not create a bottom-wall
            let mut wall_sets = sets.clone();
            for (i, cell) in row.iter_mut().enumerate() {
                if verticality(&orient, &mut rng, false) {
                    let mut set = wall_sets.get_mut(&cell.set).expect("Cannot get set to ensure correct bottom walls creation");
                    if set.len() > 1 {
                        cell.bw = true;
                        set.retain(|&x| x != i); // Maybe not optimal. Remove the element
                    }
                }
            }

            // 5. Decide to keep adding rows, or stop and complete the maze
            // 5.1. If you decide to add another row:
            if !(count_iterations == height-1) {
                // 5.1.1. Output the current row
                maze.push(row.clone());
                for cell in row.iter_mut() {
                    // 5.1.2. Remove all right walls
                    if cell.rw {
                        cell.rw = false;
                    }
                    if cell.bw {
                        // 5.1.3. Remove cells with a bottom-wall from their set
                        cell.set = 0;
                        // 5.1.4. Remove all bottom walls
                        cell.bw = false;
                    }
                }
                row[width-1].rw = true; // return the right-most wall

            // 5.1.5. Continue from Step 2
            }
        }

        // 5.2. If you decide to complete the maze
        // 5.2.2. Moving from left to right:
        for i in 0..row.len()-1 {
            // 5.2.1. Add a bottom wall to every cell
            row[i].bw = true;
            // If the current cell and the cell to the right are members of a different set:
            if row[i].set != row[i+1].set {
                // - Remove the right wall
                row[i].rw = false;
                // - Union the sets to which the current cell and cell to the right are members.
                let mut set2 = sets.remove(&row[i+1].set).expect("Can't get set for union");
                let mut set1 = sets.get_mut(&row[i].set).expect("Can't get set to union with");
                for j in set2.iter() {
                    row[*j].set = row[i].set;
                }
                set1.append(&mut set2);
            }
        }
        row[width-1].bw = true;

        // - Output the final row
        maze.push(row);

        EllerMaze {
            maze: maze,
        }
    }
}

// Using the style of http://www.neocomputer.org/projects/eller.html
// Doubled the line count, I think it look better in terminal that way
impl fmt::Display for EllerMaze {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {

        let mut result = String::new();

        for _ in 0..self.maze[0].len() {
            result.push_str(" ___");
        }
        result.push('\n');

        for row in &self.maze {
            let mut string1 = String::new();
            let mut string2 = String::new();
            string1.push('|');
            string2.push('|');
            for cell in row {
                if cell.bw {
                    string1.push_str("   ");
                    string2.push_str("___");
                } else {
                    string1.push_str("   ");
                    string2.push_str("   ");
                }
                if cell.rw {
                    string1.push_str("|");
                    string2.push_str("|");
                } else {
                    string1.push_str(" ");
                    string2.push_str(" ");
                }
            }
            result.push_str(&*string1);
            result.push('\n');
            result.push_str(&*string2);
            result.push('\n');
        }

        write!(f, "{}", result)
    }
}

<commit_msg>Rustfmt\'ed eller.rs<commit_after>// Copyright 2016 Pavel Kiselev

// My implementation of Eller's Algorithm,
// following instructions at http://www.neocomputer.org/projects/eller.html
// Comments detailing algorithm steps are mostly copypasted from there

#![allow(dead_code)]

use rand::{Rng, thread_rng, ThreadRng};
use std::collections::HashMap;
use std::fmt;

#[derive(Debug,Clone,Copy)]
struct Cell {
    set: usize,
    rw: bool,
    bw: bool,
}

pub struct EllerMaze {
    maze: Vec<Vec<Cell>>,
}

// Somewhat changes look of generated mazes
pub enum MazeOrient {
    Normal,
    Vertical,
    Horizontal,
}

impl EllerMaze {
    pub fn generate(width: usize, height: usize, orient: MazeOrient) -> EllerMaze {

        let mut rng = thread_rng();

        // Closure for changing the maze generated (as proposed on neocomputer.org in "Example
        // mazes" section
        let verticality = |orient: &MazeOrient, rng: &mut ThreadRng, is_right: bool| -> bool {
            if is_right {
                match *orient {
                    MazeOrient::Normal => rng.gen(),
                    MazeOrient::Vertical => rng.gen() || rng.gen(),
                    MazeOrient::Horizontal => rng.gen() && rng.gen(),
                }
            } else {
                match *orient {
                    MazeOrient::Normal => rng.gen(),
                    MazeOrient::Vertical => rng.gen() && rng.gen(),
                    MazeOrient::Horizontal => rng.gen() || rng.gen(),
                }
            }
        };

        let mut maze: Vec<Vec<Cell>> = Vec::with_capacity(height);

        // 1. Create the first row. No cells will be members of any set
        let mut row = vec![Cell { set: 0, rw: false, bw: false }; width];

        row[width - 1].rw = true; // The last one always has a wall.

        let mut sets: HashMap<usize, Vec<usize>> = HashMap::with_capacity(width);

        for count_iterations in 0..height {

            sets.drain(); // Empty the db

            // Create a database of indexes for all set members
            for (i, cell) in row.iter().enumerate() {
                if sets.contains_key(&cell.set) {
                    let mut vec = sets.get_mut(&cell.set)
                                      .expect("Cannot get sets to compete the HashMap");
                    (*vec).push(i);
                } else {
                    sets.insert(cell.set, vec![i]);
                }
            }

            // 2. Join any cells not members of a set to their own unique set
            // Get indexes of cells without set, or init with empty vec
            let no_set = sets.remove(&0).unwrap_or(vec![]);
            for i in no_set {
                let mut j = 1;
                while row[i].set == 0 {
                    if sets.contains_key(&j) {
                        j += 1;
                    } else {
                        row[i].set = j;
                        sets.insert(j, vec![i]);
                    }
                }
            }

            // 3. Create right-walls, moving from left to right:
            for i in 0..row.len() - 1 {
                // - If the current cell and the cell to the right are members of the same set,
                // always create a wall between them. (This prevents loops)
                if row[i].set == row[i + 1].set {
                    row[i].rw = true;
                    continue;
                }
                // - Randomly decide to add a wall or not:
                if verticality(&orient, &mut rng, true) {
                    row[i].rw = true;
                } else {
                    // - If you decide not to add a wall,  union the sets
                    let mut set2 = sets.remove(&row[i + 1].set).expect("Can't get set for union");
                    let mut set1 = sets.get_mut(&row[i].set).expect("Can't get set to union with");
                    for j in set2.iter() {
                        row[*j].set = row[i].set;
                    }
                    set1.append(&mut set2);
                }
            }

            // 4. Create bottom-walls, moving from left to right:
            // 4.1. Randomly decide to add a wall or not.
            // Make sure that each set has at least one cell without a bottom-wall
            // - If a cell is the only member of its set, do not create a bottom-wall
            // - If a cell is the only member of its set without a bottom-wall,
            // do not create a bottom-wall
            let mut wall_sets = sets.clone();
            for (i, cell) in row.iter_mut().enumerate() {
                if verticality(&orient, &mut rng, false) {
                    let mut set = wall_sets.get_mut(&cell.set)
                                           .expect("Cannot get set to ensure correct bottom \
                                                    walls creation");
                    if set.len() > 1 {
                        cell.bw = true;
                        set.retain(|&x| x != i); // Maybe not optimal. Remove the element
                    }
                }
            }

            // 5. Decide to keep adding rows, or stop and complete the maze
            // 5.1. If you decide to add another row:
            if !(count_iterations == height - 1) {
                // 5.1.1. Output the current row
                maze.push(row.clone());
                for cell in row.iter_mut() {
                    // 5.1.2. Remove all right walls
                    if cell.rw {
                        cell.rw = false;
                    }
                    if cell.bw {
                        // 5.1.3. Remove cells with a bottom-wall from their set
                        cell.set = 0;
                        // 5.1.4. Remove all bottom walls
                        cell.bw = false;
                    }
                }
                row[width - 1].rw = true; // return the right-most wall

                // 5.1.5. Continue from Step 2
            }
        }

        // 5.2. If you decide to complete the maze
        // 5.2.2. Moving from left to right:
        for i in 0..row.len() - 1 {
            // 5.2.1. Add a bottom wall to every cell
            row[i].bw = true;
            // If the current cell and the cell to the right are members of a different set:
            if row[i].set != row[i + 1].set {
                // - Remove the right wall
                row[i].rw = false;
                // - Union the sets to which the current cell and cell to the right are members.
                let mut set2 = sets.remove(&row[i + 1].set).expect("Can't get set for union");
                let mut set1 = sets.get_mut(&row[i].set).expect("Can't get set to union with");
                for j in set2.iter() {
                    row[*j].set = row[i].set;
                }
                set1.append(&mut set2);
            }
        }
        row[width - 1].bw = true;

        // - Output the final row
        maze.push(row);

        EllerMaze { maze: maze }
    }
}

// Using the style of http://www.neocomputer.org/projects/eller.html
// Doubled the line count, I think it look better in terminal that way
impl fmt::Display for EllerMaze {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {

        let mut result = String::new();

        for _ in 0..self.maze[0].len() {
            result.push_str(" ___");
        }
        result.push('\n');

        for row in &self.maze {
            let mut string1 = String::new();
            let mut string2 = String::new();
            string1.push('|');
            string2.push('|');
            for cell in row {
                if cell.bw {
                    string1.push_str("   ");
                    string2.push_str("___");
                } else {
                    string1.push_str("   ");
                    string2.push_str("   ");
                }
                if cell.rw {
                    string1.push_str("|");
                    string2.push_str("|");
                } else {
                    string1.push_str(" ");
                    string2.push_str(" ");
                }
            }
            result.push_str(&*string1);
            result.push('\n');
            result.push_str(&*string2);
            result.push('\n');
        }

        write!(f, "{}", result)
    }
}
<|endoftext|>


<commit_before>use hyper;
use hyper::server::Response;
use hyper::StatusCode;
use s3;
use serde_json;
use tera;

error_chain! {
    types {
        Error, ErrorKind, ResultExt, Result;
    }

    links {
    }

    foreign_links {
        Hyper(hyper::Error);
        Io(::std::io::Error);
        Tera(tera::Error);
        S3Get(s3::GetObjectError);
        S3Put(s3::PutObjectError);
        Json(serde_json::Error);
        UriError(hyper::error::UriError);
        FromUtf8Error(::std::string::FromUtf8Error);
    }

    errors {
        Forbidden {
            description("Forbidden")
            display("Forbidden.")
        }
        InternalServerError {
            description("Internal server error")
            display("Internal server error.")
        }
        LatexFailed(output: String) {
            description("The latex command failed")
            display("The latex command failed with the following output:\n{}", output)
        }
        MergeFailed(output: String) {
            description("A document merge failed")
            display("The provided documents could not be merged, output:\n{}", output)
        }
        UnprocessableEntity(reason: String) {
            description("Unprocessable entity")
            display("Unprocessable entity:\n{}", reason)
        }
    }
}

impl Error {
    pub fn into_response(self) -> Response {
        match self {
            Error(ErrorKind::UnprocessableEntity(_), _) => {
                Response::new().with_status(StatusCode::UnprocessableEntity)
            }
            Error(ErrorKind::Forbidden, _) => Response::new().with_status(StatusCode::Forbidden),
            Error(ErrorKind::InternalServerError, _)
            | Error(ErrorKind::Tera(_), _)
            | Error(ErrorKind::UriError(_), _)
            | Error(ErrorKind::Hyper(_), _) => {
                Response::new().with_status(StatusCode::InternalServerError)
            }
            _ => unreachable!(),
        }
    }
}
<commit_msg>🔥 Delete dead code<commit_after><|endoftext|>


<commit_before>// Copyright 2016, The Gtk-rs Project Developers.
// See the COPYRIGHT file at the top-level directory of this distribution.
// Licensed under the MIT license, see the LICENSE file or <http://opensource.org/licenses/MIT>

//! `Error` binding and helper trait.

use std::ffi::CStr;
use Quark;
use std::error;
use std::fmt;
use std::str;
use std::ptr;
use std::mem;
use translate::*;
use ffi as glib_ffi;
use gobject_ffi;

glib_wrapper! {
    /// A generic error capable of representing various error domains (types).
    pub struct Error(Boxed<glib_ffi::GError>);

    match fn {
        copy => |ptr| glib_ffi::g_error_copy(ptr),
        free => |ptr| glib_ffi::g_error_free(ptr),
        get_type => || glib_ffi::g_error_get_type(),
    }
}

unsafe impl Send for Error {}
unsafe impl Sync for Error {}

impl Error {
    /// Creates an error with supplied error enum variant and message.
    pub fn new<T: ErrorDomain>(error: T, message: &str) -> Error {
        unsafe {
            from_glib_full(
                glib_ffi::g_error_new_literal(T::domain().to_glib(), error.code(), message.to_glib_none().0))
        }
    }

    /// Checks if the error domain matches `T`.
    pub fn is<T: ErrorDomain>(&self) -> bool {
        self.0.domain == T::domain().to_glib()
    }

    /// Tries to convert to a specific error enum.
    ///
    /// Returns `Some` if the error belongs to the enum's error domain and
    /// `None` otherwise.
    ///
    /// # Examples
    ///
    /// ```ignore
    /// if let Some(file_error) = error.kind::<FileError>() {
    ///     match file_error {
    ///         FileError::Exist => ...
    ///         FileError::Isdir => ...
    ///         ...
    ///     }
    /// }
    /// ```
    ///
    /// ```ignore
    /// match error {
    ///     Some(FileError::Exist) => ...
    ///     Some(FileError::Isdir) => ...
    ///     ...
    /// }
    /// ```
    pub fn kind<T: ErrorDomain>(&self) -> Option<T> {
        if self.0.domain == T::domain().to_glib() {
            T::from(self.0.code)
        }
        else {
            None
        }
    }

    fn message(&self) -> &str {
        unsafe {
            let bytes = CStr::from_ptr(self.0.message).to_bytes();
            str::from_utf8(bytes).unwrap_or_else(|err| {
                str::from_utf8(&bytes[..err.valid_up_to()]).unwrap()
            })
        }
    }

    // backcompat shim
    #[cfg_attr(feature = "cargo-clippy", allow(not_unsafe_ptr_arg_deref))]
    pub fn wrap(ptr: *mut glib_ffi::GError) -> Error {
        unsafe { from_glib_full(ptr) }
    }
}

impl fmt::Display for Error {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "{}", self.message())
    }
}

impl error::Error for Error {
    fn description(&self) -> &str {
        self.message()
    }
}

/// `GLib` error domain.
///
/// This trait is implemented by error enums that represent error domains (types).
pub trait ErrorDomain: Copy {
    /// Returns the quark identifying the error domain.
    ///
    /// As returned from `g_some_error_quark`.
    fn domain() -> Quark;

    /// Gets the integer representation of the variant.
    fn code(self) -> i32;

    /// Tries to convert an integer code to an enum variant.
    ///
    /// By convention, the `Failed` variant, if present, is a catch-all,
    /// i.e. any unrecognized codes map to it.
    fn from(code: i32) -> Option<Self> where Self: Sized;
}

/// Generic error used for functions that fail without any further information
#[derive(Debug)]
pub struct BoolError(pub &'static str);

impl BoolError {
    pub fn from_glib(b: glib_ffi::gboolean, s: &'static str) -> Result<(), Self> {
        match b {
            glib_ffi::GFALSE => Err(BoolError(s)),
            _ => Ok(()),
        }
    }
}

impl fmt::Display for BoolError {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "{}", self.0)
    }
}

impl error::Error for BoolError {
    fn description(&self) -> &str {
        self.0
    }
}
<commit_msg>Implement Debug in a meaningful way for Error<commit_after>// Copyright 2016, The Gtk-rs Project Developers.
// See the COPYRIGHT file at the top-level directory of this distribution.
// Licensed under the MIT license, see the LICENSE file or <http://opensource.org/licenses/MIT>

//! `Error` binding and helper trait.

use std::ffi::CStr;
use Quark;
use std::error;
use std::fmt;
use std::str;
use std::ptr;
use std::mem;
use translate::*;
use ffi as glib_ffi;
use gobject_ffi;

glib_wrapper! {
    /// A generic error capable of representing various error domains (types).
    pub struct Error(Boxed<glib_ffi::GError>);

    match fn {
        copy => |ptr| glib_ffi::g_error_copy(ptr),
        free => |ptr| glib_ffi::g_error_free(ptr),
        get_type => || glib_ffi::g_error_get_type(),
    }
}

unsafe impl Send for Error {}
unsafe impl Sync for Error {}

impl Error {
    /// Creates an error with supplied error enum variant and message.
    pub fn new<T: ErrorDomain>(error: T, message: &str) -> Error {
        unsafe {
            from_glib_full(
                glib_ffi::g_error_new_literal(T::domain().to_glib(), error.code(), message.to_glib_none().0))
        }
    }

    /// Checks if the error domain matches `T`.
    pub fn is<T: ErrorDomain>(&self) -> bool {
        self.0.domain == T::domain().to_glib()
    }

    /// Tries to convert to a specific error enum.
    ///
    /// Returns `Some` if the error belongs to the enum's error domain and
    /// `None` otherwise.
    ///
    /// # Examples
    ///
    /// ```ignore
    /// if let Some(file_error) = error.kind::<FileError>() {
    ///     match file_error {
    ///         FileError::Exist => ...
    ///         FileError::Isdir => ...
    ///         ...
    ///     }
    /// }
    /// ```
    ///
    /// ```ignore
    /// match error {
    ///     Some(FileError::Exist) => ...
    ///     Some(FileError::Isdir) => ...
    ///     ...
    /// }
    /// ```
    pub fn kind<T: ErrorDomain>(&self) -> Option<T> {
        if self.0.domain == T::domain().to_glib() {
            T::from(self.0.code)
        }
        else {
            None
        }
    }

    fn message(&self) -> &str {
        unsafe {
            let bytes = CStr::from_ptr(self.0.message).to_bytes();
            str::from_utf8(bytes).unwrap_or_else(|err| {
                str::from_utf8(&bytes[..err.valid_up_to()]).unwrap()
            })
        }
    }

    // backcompat shim
    #[cfg_attr(feature = "cargo-clippy", allow(not_unsafe_ptr_arg_deref))]
    pub fn wrap(ptr: *mut glib_ffi::GError) -> Error {
        unsafe { from_glib_full(ptr) }
    }
}

impl fmt::Display for Error {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "{}", self.message())
    }
}

impl error::Error for Error {
    fn description(&self) -> &str {
        self.message()
    }
}

impl fmt::Debug for Error {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        f.debug_struct("Error")
            .field("domain", &self.0.domain)
            .field("code", &self.0.code)
            .field("message", &self.message())
            .finish()
    }
}

/// `GLib` error domain.
///
/// This trait is implemented by error enums that represent error domains (types).
pub trait ErrorDomain: Copy {
    /// Returns the quark identifying the error domain.
    ///
    /// As returned from `g_some_error_quark`.
    fn domain() -> Quark;

    /// Gets the integer representation of the variant.
    fn code(self) -> i32;

    /// Tries to convert an integer code to an enum variant.
    ///
    /// By convention, the `Failed` variant, if present, is a catch-all,
    /// i.e. any unrecognized codes map to it.
    fn from(code: i32) -> Option<Self> where Self: Sized;
}

/// Generic error used for functions that fail without any further information
#[derive(Debug)]
pub struct BoolError(pub &'static str);

impl BoolError {
    pub fn from_glib(b: glib_ffi::gboolean, s: &'static str) -> Result<(), Self> {
        match b {
            glib_ffi::GFALSE => Err(BoolError(s)),
            _ => Ok(()),
        }
    }
}

impl fmt::Display for BoolError {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "{}", self.0)
    }
}

impl error::Error for BoolError {
    fn description(&self) -> &str {
        self.0
    }
}
<|endoftext|>


<commit_before>use std::error;
use std::io;
use std::fmt;
use byteorder;

#[derive(Debug)]
pub enum Error {
    UnexpectedSize(usize, usize),
    Io(io::Error),
    Byteorder(byteorder::Error)
}

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

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

impl fmt::Display for Error {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match *self {
            Error::UnexpectedSize(expected_size, size) =>
                write!(f, "Unexpected number of bytes in NTP datagram (expected:{}; actual:{})", expected_size, size),
            Error::Io(ref err) => err.fmt(f),
            Error::Byteorder(ref err) => err.fmt(f),
        }
    }
}

impl error::Error for Error {
    fn description(&self) -> &str {
        match *self {
            Error::UnexpectedSize(_, _) => "Unexpected number of bytes in NTP datagram",
            Error::Io(ref err) => error::Error::description(err),
            Error::Byteorder(ref err) => error::Error::description(err),
        }
    }

    fn cause(&self) -> Option<&error::Error> {
        match *self {
            Error::UnexpectedSize(_, _) => None,
            Error::Io(ref err) => err.cause(),
            Error::Byteorder(ref err) => err.cause(),
        }
    }
}
<commit_msg>Removed Byteorder::Error dependency<commit_after>use std::error;
use std::io;
use std::fmt;

#[derive(Debug)]
pub enum Error {
    UnexpectedSize(usize, usize),
    Io(io::Error),
}

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

impl fmt::Display for Error {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match *self {
            Error::UnexpectedSize(expected_size, size) =>
                write!(f, "Unexpected number of bytes in NTP datagram (expected:{}; actual:{})", expected_size, size),
            Error::Io(ref err) => err.fmt(f),
        }
    }
}

impl error::Error for Error {
    fn description(&self) -> &str {
        match *self {
            Error::UnexpectedSize(_, _) => "Unexpected number of bytes in NTP datagram",
            Error::Io(ref err) => error::Error::description(err),
        }
    }

    fn cause(&self) -> Option<&error::Error> {
        match *self {
            Error::UnexpectedSize(_, _) => None,
            Error::Io(ref err) => err.cause(),
        }
    }
}
<|endoftext|>


<commit_before>//! Provides a simple Rect struct.

use std::default::Default;
use std::ops::Add;

/// A simple rect struct.
#[derive(Debug)]
pub struct Rect<T> {
    pub top: T,
    pub left: T,
    pub height: T,
    pub width: T
}

impl<T> Rect<T> {
    /// Returns the value of the bottom of the struct.
    ///
    /// # Examples
    ///
    /// ```
    /// use std::default::Default;
    /// use rex_utils::rect::Rect;
    ///
    /// let rect = Rect { top: 2, height: 5, ..Default::default()};
    /// assert_eq!(rect.bottom(), 7);
    /// ```
    pub fn bottom(&self) -> <T as Add>::Output
            where T: Add+Copy {
        self.top + self.height
    }

    /// Returns the value of the right of the struct.
    ///
    /// # Examples
    ///
    /// ```
    /// use std::default::Default;
    /// use rex_utils::rect::Rect;
    ///
    /// let rect = Rect { left: 2, width: 5, ..Default::default()};
    /// assert_eq!(rect.right(), 7);
    /// ```
    pub fn right(&self) -> <T as Add>::Output
            where T: Add+Copy {
        self.left + self.width
    }
}

impl<T> Default for Rect<T>
        where T: Default {
    fn default() -> Rect<T> {
        Rect {
            top: Default::default(),
            left: Default::default(),
            height: Default::default(),
            width: Default::default(),
        }
    }
}
<commit_msg>Make Rect clone-able and copy-able<commit_after>//! Provides a simple Rect struct.

use std::default::Default;
use std::ops::Add;

/// A simple rect struct.
#[derive(Debug, Clone, Copy)]
pub struct Rect<T> {
    pub top: T,
    pub left: T,
    pub height: T,
    pub width: T
}

impl<T> Rect<T> {
    /// Returns the value of the bottom of the struct.
    ///
    /// # Examples
    ///
    /// ```
    /// use std::default::Default;
    /// use rex_utils::rect::Rect;
    ///
    /// let rect = Rect { top: 2, height: 5, ..Default::default()};
    /// assert_eq!(rect.bottom(), 7);
    /// ```
    pub fn bottom(&self) -> <T as Add>::Output
            where T: Add+Copy {
        self.top + self.height
    }

    /// Returns the value of the right of the struct.
    ///
    /// # Examples
    ///
    /// ```
    /// use std::default::Default;
    /// use rex_utils::rect::Rect;
    ///
    /// let rect = Rect { left: 2, width: 5, ..Default::default()};
    /// assert_eq!(rect.right(), 7);
    /// ```
    pub fn right(&self) -> <T as Add>::Output
            where T: Add+Copy {
        self.left + self.width
    }
}

impl<T> Default for Rect<T>
        where T: Default {
    fn default() -> Rect<T> {
        Rect {
            top: Default::default(),
            left: Default::default(),
            height: Default::default(),
            width: Default::default(),
        }
    }
}
<|endoftext|>


<commit_before>extern crate libc;

extern crate emu;
extern crate spc;
extern crate snes_apu;

use std::sync::{Arc, Mutex};

use std::ffi::CStr;
use libc::{c_void, c_char};

use emu::audio_driver::AudioDriver;
use emu::core_audio_driver::CoreAudioDriver;

use spc::spc::{Spc, RAM_LEN};
use snes_apu::apu::{Apu, BUFFER_LEN};

struct ContextState {
    apu: Box<Apu>,
    spc: Option<Spc>
}

struct Context {
    state: Arc<Mutex<ContextState>>,
    _driver: CoreAudioDriver
}

impl Context {
    fn new() -> Context {
        let state = Arc::new(Mutex::new(ContextState {
            apu: Apu::new(),
            spc: None
        }));

        let mut driver = CoreAudioDriver::new();
        driver.set_sample_rate(32000);
        let render_callback_state = state.clone();
        let mut left = [0; BUFFER_LEN];
        let mut right = [0; BUFFER_LEN];
        driver.set_render_callback(Some(Box::new(move |buffer, num_frames| {
            render_callback_state.lock().unwrap().apu.render(&mut left, &mut right, num_frames as i32);
            for i in 0..num_frames {
                let j = i * 2;
                buffer[j + 0] = left[i] as f32 / 32768.0;
                buffer[j + 1] = right[i] as f32 / 32768.0;
            }
        })));

        Context {
            state: state,
            _driver: driver
        }
    }

    fn set_song(&mut self, spc: Option<Spc>) {
        let state = &mut self.state.lock().unwrap();
        state.apu.reset();
        if let Some(ref spc) = spc {
            state.apu.set_state(&spc);
            state.apu.clear_echo_buffer();
        }
        state.spc = spc;
    }

    fn get_ram_snapshot(&mut self) -> Box<[u8; RAM_LEN]> {
        self.state.lock().unwrap().apu.get_ram_snapshot()
    }
}

#[no_mangle]
pub extern fn create_context() -> *mut c_void {
    Box::into_raw(Box::new(Context::new())) as *mut c_void
}

#[no_mangle]
pub extern fn free_context(context: *mut c_void) {
    unsafe { Box::from_raw(context as *mut Context) };
}

#[no_mangle]
pub extern fn set_song(context: *mut c_void, filename: *const c_char) {
    let context = unsafe { &mut *(context as *mut Context) };
    let spc = if filename.is_null() {
        None
    } else {
        let filename = unsafe { CStr::from_ptr(filename) }.to_str().unwrap();
        Some(Spc::load(filename).unwrap())
    };
    context.set_song(spc);
}

#[no_mangle]
pub extern fn get_ram_snapshot(context: *mut c_void) -> *mut u8 {
    let context = unsafe { &mut *(context as *mut Context) };
    let snapshot = context.get_ram_snapshot();
    Box::into_raw(snapshot) as *mut u8
}

#[no_mangle]
pub extern fn free_ram_snapshot(snapshot: *mut c_void) {
    unsafe { Box::from_raw(snapshot as *mut [u8; RAM_LEN]) };
}
<commit_msg>Updated snes-apu-c after changes in snes-apu<commit_after>extern crate libc;

extern crate emu;
extern crate spc;
extern crate snes_apu;

use std::sync::{Arc, Mutex};

use std::ffi::CStr;
use libc::{c_void, c_char};

use emu::audio_driver::AudioDriver;
use emu::core_audio_driver::CoreAudioDriver;

use spc::spc::{Spc, RAM_LEN};
use snes_apu::apu::Apu;
use snes_apu::dsp::dsp::{SAMPLE_RATE, BUFFER_LEN};

struct ContextState {
    apu: Box<Apu>,
    spc: Option<Spc>
}

struct Context {
    state: Arc<Mutex<ContextState>>,
    _driver: CoreAudioDriver
}

impl Context {
    fn new() -> Context {
        let state = Arc::new(Mutex::new(ContextState {
            apu: Apu::new(),
            spc: None
        }));

        let mut driver = CoreAudioDriver::new();
        driver.set_sample_rate(SAMPLE_RATE as i32);
        let render_callback_state = state.clone();
        let mut left = [0; BUFFER_LEN];
        let mut right = [0; BUFFER_LEN];
        driver.set_render_callback(Some(Box::new(move |buffer, num_frames| {
            render_callback_state.lock().unwrap().apu.render(&mut left, &mut right, num_frames as i32);
            for i in 0..num_frames {
                let j = i * 2;
                buffer[j + 0] = left[i] as f32 / 32768.0;
                buffer[j + 1] = right[i] as f32 / 32768.0;
            }
        })));

        Context {
            state: state,
            _driver: driver
        }
    }

    fn set_song(&mut self, spc: Option<Spc>) {
        let state = &mut self.state.lock().unwrap();
        state.apu.reset();
        if let Some(ref spc) = spc {
            state.apu.set_state(&spc);
            state.apu.clear_echo_buffer();
        }
        state.spc = spc;
    }

    fn get_ram_snapshot(&mut self) -> Box<[u8; RAM_LEN]> {
        self.state.lock().unwrap().apu.get_ram_snapshot()
    }
}

#[no_mangle]
pub extern fn create_context() -> *mut c_void {
    Box::into_raw(Box::new(Context::new())) as *mut c_void
}

#[no_mangle]
pub extern fn free_context(context: *mut c_void) {
    unsafe { Box::from_raw(context as *mut Context) };
}

#[no_mangle]
pub extern fn set_song(context: *mut c_void, filename: *const c_char) {
    let context = unsafe { &mut *(context as *mut Context) };
    let spc = if filename.is_null() {
        None
    } else {
        let filename = unsafe { CStr::from_ptr(filename) }.to_str().unwrap();
        Some(Spc::load(filename).unwrap())
    };
    context.set_song(spc);
}

#[no_mangle]
pub extern fn get_ram_snapshot(context: *mut c_void) -> *mut u8 {
    let context = unsafe { &mut *(context as *mut Context) };
    let snapshot = context.get_ram_snapshot();
    Box::into_raw(snapshot) as *mut u8
}

#[no_mangle]
pub extern fn free_ram_snapshot(snapshot: *mut c_void) {
    unsafe { Box::from_raw(snapshot as *mut [u8; RAM_LEN]) };
}
<|endoftext|>


<commit_before>// Crypto challenge Set1 / Challenge 3
// Decrypt single XOR chiffre

extern crate codec;
extern crate challenge3;

#[cfg(not(test))]
fn main() {
    let args = std::os::args();

    if args.len() != 2 {
        println!("USAGE: challenge3 HEX_ENCODED_STRING");
    } else {
        let input = args[1].as_slice();
        match codec::from_hex(input) {
            Err(msg) => println!("Invalid hex string: {}", msg),
            Ok(binary) => {
                let result = challenge3::decode_xor(binary.as_slice());
                println!("Text {}", std::str::from_utf8(result.as_slice()));
                println!("Raw {}", result);
            }
        }
    }
}
<commit_msg>Improve output of Challenge 3<commit_after>// Crypto challenge Set1 / Challenge 3
// Decrypt single XOR chiffre

extern crate codec;
extern crate challenge3;

#[cfg(not(test))]
fn main() {
    let args = std::os::args();

    if args.len() != 2 {
        println!("USAGE: challenge3 HEX_ENCODED_STRING");
    } else {
        let input = args[1].as_slice();
        match codec::from_hex(input) {
            Err(msg) => println!("Invalid hex string: {}", msg),
            Ok(binary) => {
                let decoded = challenge3::decode_xor(binary.as_slice());
                match std::str::from_utf8(decoded.as_slice()) {
                    Some(result) => println!("Decoded: {}", result),
                    None => println!("Failed to decode to UTF-8 string!")
                }
            }
        }
    }
}
<|endoftext|>


<commit_before>use std::fmt;

#[derive(PartialEq)]
pub struct Clock {
    hours: i32,
    minutes: i32,
}

impl Clock {
    pub fn new(hours: i32, minutes: i32) -> Self {
        return Clock { hours, minutes };
    }

    pub fn add_minutes(&self, minutes: i32) -> Self {
        return Clock::new(self.hours, self.minutes + minutes);
    }
}

impl fmt::Display for Clock {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        let minutes = self.minutes % 60;
        let additional_hours = self.minutes / 60;
        let mut hours = self.hours + additional_hours;
        while hours < 0 {
            hours += 24
        }
        let hours = hours % 24;
        write!(f, "{:02}:{:02}", hours, minutes)
    }
}

impl fmt::Debug for Clock {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        write!(f, "{:02}:{:02}", self.hours, self.minutes)
    }
}
<commit_msg>Remove hours from internal state<commit_after>use std::fmt;

#[derive(PartialEq)]
pub struct Clock {
    minutes: i32,
}

impl Clock {
    pub fn new(hours: i32, minutes: i32) -> Self {
        return Clock {
            minutes: (hours * 60) + minutes,
        };
    }

    pub fn add_minutes(&self, minutes: i32) -> Self {
        return Clock::new(0, self.minutes + minutes);
    }
}

impl fmt::Display for Clock {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        let mut minutes = self.minutes;
        let mut hours = 0;

        while minutes < 0 {
            hours -= 1;
            minutes += 60
        }
        while minutes >= 60 {
            hours += 1;
            minutes -= 60
        }
        while hours < 0 {
            hours += 24;
        }
        while hours >= 24 {
            hours -= 24;
        }

        write!(f, "{:02}:{:02}", hours, minutes)
    }
}

impl fmt::Debug for Clock {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        write!(f, "{}", self.minutes)
    }
}
<|endoftext|>


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

use crate::rustc::hir::{intravisit::FnKind, Body, ExprKind, FnDecl};
use crate::rustc::lint::{LateContext, LateLintPass, LintArray, LintPass};
use crate::rustc::{declare_tool_lint, lint_array};
use crate::rustc_errors::Applicability;
use crate::syntax::{ast::NodeId, source_map::Span};
use crate::utils::{snippet_opt, span_lint_and_then, in_macro};

/// **What it does:** Checks for missing return statements at the end of a block.
///
/// **Why is this bad?** Actually omitting the return keyword is idiomatic Rust code. Programmers
/// coming from other languages might prefer the expressiveness of `return`. It's possible to miss
/// the last returning statement because the only difference is a missing `;`. Especially in bigger
/// code with multiple return paths having a `return` keyword makes it easier to find the
/// corresponding statements.
///
/// **Known problems:** None.
///
/// **Example:**
/// ```rust
/// fn foo(x: usize) {
///     x
/// }
/// ```
/// add return
/// ```rust
/// fn foo(x: usize) {
///     return x;
/// }
/// ```
declare_clippy_lint! {
    pub IMPLICIT_RETURN,
    restriction,
    "use a return statement like `return expr` instead of an expression"
}

pub struct Pass;

impl Pass {
    fn lint(cx: &LateContext<'_, '_>, outer_span: syntax_pos::Span, inner_span: syntax_pos::Span, msg: &str) {
        span_lint_and_then(cx, IMPLICIT_RETURN, outer_span, "missing return statement", |db| {
            if let Some(snippet) = snippet_opt(cx, inner_span) {
                db.span_suggestion_with_applicability(
                    outer_span,
                    msg,
                    format!("return {}", snippet),
                    Applicability::MachineApplicable,
                );
            }
        });
    }

    fn expr_match(cx: &LateContext<'_, '_>, expr: &rustc::hir::Expr) {
        match &expr.node {
            // loops could be using `break` instead of `return`
            ExprKind::Block(block, ..) | ExprKind::Loop(block, ..) => {
                if let Some(expr) = &block.expr {
                    Self::expr_match(cx, expr);
                }
                // only needed in the case of `break` with `;` at the end
                else if let Some(stmt) = block.stmts.last() {
                    if let rustc::hir::StmtKind::Semi(expr, ..) = &stmt.node {
                        // make sure it's a break, otherwise we want to skip
                        if let ExprKind::Break(.., break_expr) = &expr.node {
                            if let Some(break_expr) = break_expr {
                                Self::lint(cx, expr.span, break_expr.span, "change `break` to `return` as shown");
                            }
                        }
                    }
                }
            },
            // use `return` instead of `break`
            ExprKind::Break(.., break_expr) => {
                if let Some(break_expr) = break_expr {
                    Self::lint(cx, expr.span, break_expr.span, "change `break` to `return` as shown");
                }
            },
            ExprKind::If(.., if_expr, else_expr) => {
                Self::expr_match(cx, if_expr);

                if let Some(else_expr) = else_expr {
                    Self::expr_match(cx, else_expr);
                }
            },
            ExprKind::Match(_, arms, ..) => {
                for arm in arms {
                    Self::expr_match(cx, &arm.body);
                }
            },
            // skip if it already has a return statement
            ExprKind::Ret(..) => (),
            // everything else is missing `return`
            _ => Self::lint(cx, expr.span, expr.span, "add `return` as shown"),
        }
    }
}

impl LintPass for Pass {
    fn get_lints(&self) -> LintArray {
        lint_array!(IMPLICIT_RETURN)
    }
}

impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass {
    fn check_fn(
        &mut self,
        cx: &LateContext<'a, 'tcx>,
        _: FnKind<'tcx>,
        _: &'tcx FnDecl,
        body: &'tcx Body,
        span: Span,
        _: NodeId,
    ) {
        let def_id = cx.tcx.hir().body_owner_def_id(body.id());
        let mir = cx.tcx.optimized_mir(def_id);

        // checking return type through MIR, HIR is not able to determine inferred closure return types
        // make sure it's not a macro
        if !mir.return_ty().is_unit() && !in_macro(span) {
            Self::expr_match(cx, &body.value);
        }
    }
}
<commit_msg>Rustfmt.<commit_after>// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

use crate::rustc::hir::{intravisit::FnKind, Body, ExprKind, FnDecl};
use crate::rustc::lint::{LateContext, LateLintPass, LintArray, LintPass};
use crate::rustc::{declare_tool_lint, lint_array};
use crate::rustc_errors::Applicability;
use crate::syntax::{ast::NodeId, source_map::Span};
use crate::utils::{in_macro, snippet_opt, span_lint_and_then};

/// **What it does:** Checks for missing return statements at the end of a block.
///
/// **Why is this bad?** Actually omitting the return keyword is idiomatic Rust code. Programmers
/// coming from other languages might prefer the expressiveness of `return`. It's possible to miss
/// the last returning statement because the only difference is a missing `;`. Especially in bigger
/// code with multiple return paths having a `return` keyword makes it easier to find the
/// corresponding statements.
///
/// **Known problems:** None.
///
/// **Example:**
/// ```rust
/// fn foo(x: usize) {
///     x
/// }
/// ```
/// add return
/// ```rust
/// fn foo(x: usize) {
///     return x;
/// }
/// ```
declare_clippy_lint! {
    pub IMPLICIT_RETURN,
    restriction,
    "use a return statement like `return expr` instead of an expression"
}

pub struct Pass;

impl Pass {
    fn lint(cx: &LateContext<'_, '_>, outer_span: syntax_pos::Span, inner_span: syntax_pos::Span, msg: &str) {
        span_lint_and_then(cx, IMPLICIT_RETURN, outer_span, "missing return statement", |db| {
            if let Some(snippet) = snippet_opt(cx, inner_span) {
                db.span_suggestion_with_applicability(
                    outer_span,
                    msg,
                    format!("return {}", snippet),
                    Applicability::MachineApplicable,
                );
            }
        });
    }

    fn expr_match(cx: &LateContext<'_, '_>, expr: &rustc::hir::Expr) {
        match &expr.node {
            // loops could be using `break` instead of `return`
            ExprKind::Block(block, ..) | ExprKind::Loop(block, ..) => {
                if let Some(expr) = &block.expr {
                    Self::expr_match(cx, expr);
                }
                // only needed in the case of `break` with `;` at the end
                else if let Some(stmt) = block.stmts.last() {
                    if let rustc::hir::StmtKind::Semi(expr, ..) = &stmt.node {
                        // make sure it's a break, otherwise we want to skip
                        if let ExprKind::Break(.., break_expr) = &expr.node {
                            if let Some(break_expr) = break_expr {
                                Self::lint(cx, expr.span, break_expr.span, "change `break` to `return` as shown");
                            }
                        }
                    }
                }
            },
            // use `return` instead of `break`
            ExprKind::Break(.., break_expr) => {
                if let Some(break_expr) = break_expr {
                    Self::lint(cx, expr.span, break_expr.span, "change `break` to `return` as shown");
                }
            },
            ExprKind::If(.., if_expr, else_expr) => {
                Self::expr_match(cx, if_expr);

                if let Some(else_expr) = else_expr {
                    Self::expr_match(cx, else_expr);
                }
            },
            ExprKind::Match(_, arms, ..) => {
                for arm in arms {
                    Self::expr_match(cx, &arm.body);
                }
            },
            // skip if it already has a return statement
            ExprKind::Ret(..) => (),
            // everything else is missing `return`
            _ => Self::lint(cx, expr.span, expr.span, "add `return` as shown"),
        }
    }
}

impl LintPass for Pass {
    fn get_lints(&self) -> LintArray {
        lint_array!(IMPLICIT_RETURN)
    }
}

impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass {
    fn check_fn(
        &mut self,
        cx: &LateContext<'a, 'tcx>,
        _: FnKind<'tcx>,
        _: &'tcx FnDecl,
        body: &'tcx Body,
        span: Span,
        _: NodeId,
    ) {
        let def_id = cx.tcx.hir().body_owner_def_id(body.id());
        let mir = cx.tcx.optimized_mir(def_id);

        // checking return type through MIR, HIR is not able to determine inferred closure return types
        // make sure it's not a macro
        if !mir.return_ty().is_unit() && !in_macro(span) {
            Self::expr_match(cx, &body.value);
        }
    }
}
<|endoftext|>


<commit_before>extern crate s3;

use std::str;

use s3::bucket::Bucket;
use s3::creds::Credentials;
use s3::region::Region;
use s3::S3Error;

struct Storage {
    name: String,
    region: Region,
    credentials: Credentials,
    bucket: String,
    location_supported: bool,
}

const MESSAGE: &str = "I want to go to S3";

pub fn main() -> Result<(), S3Error> {
    let aws = Storage {
        name: "aws".into(),
        region: "eu-central-1".parse()?,
        // credentials: Credentials::from_profile(Some("rust-s3"))?,
        credentials: Credentials::from_env_specific(
            Some("EU_AWS_ACCESS_KEY_ID"),
            Some("EU_AWS_SECRET_ACCESS_KEY"),
            None,
            None,
        )?,
        bucket: "rust-s3-test".to_string(),
        location_supported: true,
    };

    // let aws_public = Storage {
    //     name: "aws-public".into(),
    //     region: "eu-central-1".parse()?,
    //     credentials: Credentials::anonymous()?,
    //     bucket: "rust-s3-public".to_string(),
    //     location_supported: true,
    // };

    // let minio = Storage {
    //     name: "minio".into(),
    //     region: Region::Custom {
    //         region: "us-east-1".into(),
    //         endpoint: "https://minio.adder.black".into(),
    //     },
    //     credentials: Credentials::from_profile(Some("minio"))?,
    //     bucket: "rust-s3".to_string(),
    //     location_supported: false,
    // };

    // let yandex = Storage {
    //     name: "yandex".into(),
    //     region: "ru-central1".parse()?,
    //     credentials: Credentials::from_profile(Some("yandex"))?,
    //     bucket: "soundcloud".to_string(),
    //     location_supported: false,
    // };

    for backend in vec![aws] {
        println!("Running {}", backend.name);
        // Create Bucket in REGION for BUCKET
        let bucket = Bucket::new(&backend.bucket, backend.region, backend.credentials)?;

        // List out contents of directory
        let results = bucket.list_blocking("".to_string(), None)?;
        for (list, code) in results {
            assert_eq!(200, code);
            println!("{:?}", list.contents.len());
        }

        // Make sure that our "test_file" doesn't exist, delete it if it does. Note
        // that the s3 library returns the HTTP code even if it indicates a failure
        // (i.e. 404) since we can't predict desired usage. For example, you may
        // expect a 404 to make sure a fi le doesn't exist.
        //    let (_, code) = bucket.delete("test_file")?;
        //    assert_eq!(204, code);

        // Put a "test_file" with the contents of MESSAGE at the root of the
        // bucket.
        let (_, code) = bucket.put_object_blocking("test_file", MESSAGE.as_bytes())?;
        // println!("{}", bucket.presign_get("test_file", 604801)?);
        assert_eq!(200, code);

        // Get the "test_file" contents and make sure that the returned message
        // matches what we sent.
        let (data, code) = bucket.get_object_blocking("test_file")?;
        let string = str::from_utf8(&data)?;
        // println!("{}", string);
        assert_eq!(200, code);
        assert_eq!(MESSAGE, string);

        if backend.location_supported {
            // Get bucket location
            println!("{:?}", bucket.location_blocking()?);
        }

        bucket.put_object_tagging_blocking("test_file", &[("test", "tag")])?;
        println!("Tags set");
        let (tags, _status) = bucket.get_object_tagging_blocking("test_file")?;
        println!("{:?}", tags);

        // Test with random byte array

        let random_bytes: Vec<u8> = (0..3072).map(|_| 33).collect();
        let (_, code) = bucket.put_object_blocking("random.bin", random_bytes.as_slice())?;
        assert_eq!(200, code);
        let (data, code) = bucket.get_object_blocking("random.bin")?;
        assert_eq!(code, 200);
        assert_eq!(data.len(), 3072);
        assert_eq!(data, random_bytes);
    }

    Ok(())
}
<commit_msg>Add some commented example for Minio (#217)<commit_after>extern crate s3;

use std::str;

use s3::bucket::Bucket;
use s3::creds::Credentials;
use s3::region::Region;
use s3::S3Error;

struct Storage {
    name: String,
    region: Region,
    credentials: Credentials,
    bucket: String,
    location_supported: bool,
}

const MESSAGE: &str = "I want to go to S3";

pub fn main() -> Result<(), S3Error> {
    let aws = Storage {
        name: "aws".into(),
        region: "eu-central-1".parse()?,
        // credentials: Credentials::from_profile(Some("rust-s3"))?,
        credentials: Credentials::from_env_specific(
            Some("EU_AWS_ACCESS_KEY_ID"),
            Some("EU_AWS_SECRET_ACCESS_KEY"),
            None,
            None,
        )?,
        bucket: "rust-s3-test".to_string(),
        location_supported: true,
    };

    // let aws_public = Storage {
    //     name: "aws-public".into(),
    //     region: "eu-central-1".parse()?,
    //     credentials: Credentials::anonymous()?,
    //     bucket: "rust-s3-public".to_string(),
    //     location_supported: true,
    // };

    // let minio = Storage {
    //     name: "minio".into(),
    //     region: Region::Custom {
    //         region: "".into(),
    //         endpoint: "http://127.0.0.1:9001".into(),
    //     },
    //     credentials: Credentials {
    //          access_key: Some("ACCESS_KEY".to_owned()),
    //          secret_key: Some("SECRET_KEY".to_owned()),
    //          security_token: None,
    //          session_token: None,
    //     },
    //     bucket: "rust-s3".to_string(),
    //     location_supported: false,
    // };

    // let yandex = Storage {
    //     name: "yandex".into(),
    //     region: "ru-central1".parse()?,
    //     credentials: Credentials::from_profile(Some("yandex"))?,
    //     bucket: "soundcloud".to_string(),
    //     location_supported: false,
    // };

    for backend in vec![aws] {
        println!("Running {}", backend.name);
        // Create Bucket in REGION for BUCKET
        let bucket = Bucket::new(&backend.bucket, backend.region, backend.credentials)?;

        // With Minio, the bucket name is part of the path of the requests.
        // You will need to instantiante bucket using the `new_with_path_style` method.
        // let bucket = Bucket::new_with_path_style(&backend.bucket, backend.region, backend.credentials)?;

        // List out contents of directory
        let results = bucket.list_blocking("".to_string(), None)?;
        for (list, code) in results {
            assert_eq!(200, code);
            println!("{:?}", list.contents.len());
        }

        // Make sure that our "test_file" doesn't exist, delete it if it does. Note
        // that the s3 library returns the HTTP code even if it indicates a failure
        // (i.e. 404) since we can't predict desired usage. For example, you may
        // expect a 404 to make sure a fi le doesn't exist.
        //    let (_, code) = bucket.delete("test_file")?;
        //    assert_eq!(204, code);

        // Put a "test_file" with the contents of MESSAGE at the root of the
        // bucket.
        let (_, code) = bucket.put_object_blocking("test_file", MESSAGE.as_bytes())?;
        // println!("{}", bucket.presign_get("test_file", 604801)?);
        assert_eq!(200, code);

        // Get the "test_file" contents and make sure that the returned message
        // matches what we sent.
        let (data, code) = bucket.get_object_blocking("test_file")?;
        let string = str::from_utf8(&data)?;
        // println!("{}", string);
        assert_eq!(200, code);
        assert_eq!(MESSAGE, string);

        if backend.location_supported {
            // Get bucket location
            println!("{:?}", bucket.location_blocking()?);
        }

        bucket.put_object_tagging_blocking("test_file", &[("test", "tag")])?;
        println!("Tags set");
        let (tags, _status) = bucket.get_object_tagging_blocking("test_file")?;
        println!("{:?}", tags);

        // Test with random byte array

        let random_bytes: Vec<u8> = (0..3072).map(|_| 33).collect();
        let (_, code) = bucket.put_object_blocking("random.bin", random_bytes.as_slice())?;
        assert_eq!(200, code);
        let (data, code) = bucket.get_object_blocking("random.bin")?;
        assert_eq!(code, 200);
        assert_eq!(data.len(), 3072);
        assert_eq!(data, random_bytes);
    }

    Ok(())
}
<|endoftext|>