<commit_before>use std::sync::Arc;

use either::Either;

use hir_expand::InFile;
use ra_syntax::ast::{self, VisibilityOwner};

use crate::{
    db::DefDatabase,
    path::{ModPath, PathKind},
    src::{HasChildSource, HasSource},
    AdtId, Lookup, ModuleId, VisibilityDefId,
};

/// Visibility of an item, not yet resolved.
#[derive(Debug, Clone, PartialEq, Eq)]
pub enum Visibility {
    // FIXME: We could avoid the allocation in many cases by special-casing
    // pub(crate), pub(super) and private. Alternatively, `ModPath` could be
    // made to contain an Arc<[Segment]> instead of a Vec?
    /// `pub(in module)`, `pub(crate)` or `pub(super)`. Also private, which is
    /// equivalent to `pub(self)`.
    Module(Arc<ModPath>),
    /// `pub`.
    Public,
}

impl Visibility {
    pub(crate) fn visibility_query(db: &impl DefDatabase, def: VisibilityDefId) -> Visibility {
        match def {
            VisibilityDefId::ModuleId(module) => {
                let def_map = db.crate_def_map(module.krate);
                let src = match def_map[module.local_id].declaration_source(db) {
                    Some(it) => it,
                    None => return Visibility::private(),
                };
                Visibility::from_ast(db, src.map(|it| it.visibility()))
            }
            VisibilityDefId::StructFieldId(it) => {
                let src = it.parent.child_source(db);
                // TODO: enum variant fields should be public by default
                let vis_node = src.map(|m| match &m[it.local_id] {
                    Either::Left(tuple) => tuple.visibility(),
                    Either::Right(record) => record.visibility(),
                });
                Visibility::from_ast(db, vis_node)
            }
            VisibilityDefId::AdtId(it) => match it {
                AdtId::StructId(it) => visibility_from_loc(it.lookup(db), db),
                AdtId::EnumId(it) => visibility_from_loc(it.lookup(db), db),
                AdtId::UnionId(it) => visibility_from_loc(it.lookup(db), db),
            },
            VisibilityDefId::TraitId(it) => visibility_from_loc(it.lookup(db), db),
            VisibilityDefId::ConstId(it) => visibility_from_loc(it.lookup(db), db),
            VisibilityDefId::StaticId(it) => visibility_from_loc(it.lookup(db), db),
            VisibilityDefId::FunctionId(it) => visibility_from_loc(it.lookup(db), db),
            VisibilityDefId::TypeAliasId(it) => visibility_from_loc(it.lookup(db), db),
        }
    }

    fn private() -> Visibility {
        let path = ModPath { kind: PathKind::Super(0), segments: Vec::new() };
        Visibility::Module(Arc::new(path))
    }

    fn from_ast(db: &impl DefDatabase, node: InFile<Option<ast::Visibility>>) -> Visibility {
        let file_id = node.file_id;
        let node = match node.value {
            None => return Visibility::private(),
            Some(node) => node,
        };
        match node.kind() {
            ast::VisibilityKind::In(path) => {
                let path = ModPath::from_src(path, &hir_expand::hygiene::Hygiene::new(db, file_id));
                let path = match path {
                    None => return Visibility::private(),
                    Some(path) => path,
                };
                Visibility::Module(Arc::new(path))
            }
            ast::VisibilityKind::PubCrate => {
                let path = ModPath { kind: PathKind::Crate, segments: Vec::new() };
                Visibility::Module(Arc::new(path))
            }
            ast::VisibilityKind::PubSuper => {
                let path = ModPath { kind: PathKind::Super(1), segments: Vec::new() };
                Visibility::Module(Arc::new(path))
            }
            ast::VisibilityKind::Pub => Visibility::Public,
        }
    }

    pub fn resolve(
        &self,
        db: &impl DefDatabase,
        resolver: &crate::resolver::Resolver,
    ) -> ResolvedVisibility {
        // we fall back to public visibility (i.e. fail open) if the path can't be resolved
        resolver.resolve_visibility(db, self).unwrap_or(ResolvedVisibility::Public)
    }
}

/// Visibility of an item, with the path resolved.
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
pub enum ResolvedVisibility {
    /// Visibility is restricted to a certain module.
    Module(ModuleId),
    /// Visibility is unrestricted.
    Public,
}

impl ResolvedVisibility {
    pub fn visible_from(self, db: &impl DefDatabase, from_module: ModuleId) -> bool {
        let to_module = match self {
            ResolvedVisibility::Module(m) => m,
            ResolvedVisibility::Public => return true,
        };
        // if they're not in the same crate, it can't be visible
        if from_module.krate != to_module.krate {
            return false;
        }
        // from_module needs to be a descendant of to_module
        let def_map = db.crate_def_map(from_module.krate);
        let mut ancestors = std::iter::successors(Some(from_module), |m| {
            let parent_id = def_map[m.local_id].parent?;
            Some(ModuleId { local_id: parent_id, ..*m })
        });
        ancestors.any(|m| m == to_module)
    }
}

fn visibility_from_loc<T>(node: T, db: &impl DefDatabase) -> Visibility
where
    T: HasSource,
    T::Value: ast::VisibilityOwner,
{
    let src = node.source(db);
    Visibility::from_ast(db, src.map(|n| n.visibility()))
}
<commit_msg>Make enum variant fields public<commit_after>use std::sync::Arc;

use either::Either;

use hir_expand::InFile;
use ra_syntax::ast::{self, VisibilityOwner};

use crate::{
    db::DefDatabase,
    path::{ModPath, PathKind},
    src::{HasChildSource, HasSource},
    AdtId, Lookup, ModuleId, VisibilityDefId,
};

/// Visibility of an item, not yet resolved.
#[derive(Debug, Clone, PartialEq, Eq)]
pub enum Visibility {
    // FIXME: We could avoid the allocation in many cases by special-casing
    // pub(crate), pub(super) and private. Alternatively, `ModPath` could be
    // made to contain an Arc<[Segment]> instead of a Vec?
    /// `pub(in module)`, `pub(crate)` or `pub(super)`. Also private, which is
    /// equivalent to `pub(self)`.
    Module(Arc<ModPath>),
    /// `pub`.
    Public,
}

impl Visibility {
    pub(crate) fn visibility_query(db: &impl DefDatabase, def: VisibilityDefId) -> Visibility {
        match def {
            VisibilityDefId::ModuleId(module) => {
                let def_map = db.crate_def_map(module.krate);
                let src = match def_map[module.local_id].declaration_source(db) {
                    Some(it) => it,
                    None => return Visibility::private(),
                };
                Visibility::from_ast(db, src.map(|it| it.visibility()))
            }
            VisibilityDefId::StructFieldId(it) => {
                let src = it.parent.child_source(db);
                let is_enum = match it.parent {
                    crate::VariantId::EnumVariantId(_) => true,
                    _ => false,
                };
                let vis_node = src.map(|m| match &m[it.local_id] {
                    Either::Left(tuple) => tuple.visibility(),
                    Either::Right(record) => record.visibility(),
                });
                if vis_node.value.is_none() && is_enum {
                    Visibility::Public
                } else {
                    Visibility::from_ast(db, vis_node)
                }
            }
            VisibilityDefId::AdtId(it) => match it {
                AdtId::StructId(it) => visibility_from_loc(it.lookup(db), db),
                AdtId::EnumId(it) => visibility_from_loc(it.lookup(db), db),
                AdtId::UnionId(it) => visibility_from_loc(it.lookup(db), db),
            },
            VisibilityDefId::TraitId(it) => visibility_from_loc(it.lookup(db), db),
            VisibilityDefId::ConstId(it) => visibility_from_loc(it.lookup(db), db),
            VisibilityDefId::StaticId(it) => visibility_from_loc(it.lookup(db), db),
            VisibilityDefId::FunctionId(it) => visibility_from_loc(it.lookup(db), db),
            VisibilityDefId::TypeAliasId(it) => visibility_from_loc(it.lookup(db), db),
        }
    }

    fn private() -> Visibility {
        let path = ModPath { kind: PathKind::Super(0), segments: Vec::new() };
        Visibility::Module(Arc::new(path))
    }

    fn from_ast(db: &impl DefDatabase, node: InFile<Option<ast::Visibility>>) -> Visibility {
        let file_id = node.file_id;
        let node = match node.value {
            None => return Visibility::private(),
            Some(node) => node,
        };
        match node.kind() {
            ast::VisibilityKind::In(path) => {
                let path = ModPath::from_src(path, &hir_expand::hygiene::Hygiene::new(db, file_id));
                let path = match path {
                    None => return Visibility::private(),
                    Some(path) => path,
                };
                Visibility::Module(Arc::new(path))
            }
            ast::VisibilityKind::PubCrate => {
                let path = ModPath { kind: PathKind::Crate, segments: Vec::new() };
                Visibility::Module(Arc::new(path))
            }
            ast::VisibilityKind::PubSuper => {
                let path = ModPath { kind: PathKind::Super(1), segments: Vec::new() };
                Visibility::Module(Arc::new(path))
            }
            ast::VisibilityKind::Pub => Visibility::Public,
        }
    }

    pub fn resolve(
        &self,
        db: &impl DefDatabase,
        resolver: &crate::resolver::Resolver,
    ) -> ResolvedVisibility {
        // we fall back to public visibility (i.e. fail open) if the path can't be resolved
        resolver.resolve_visibility(db, self).unwrap_or(ResolvedVisibility::Public)
    }
}

/// Visibility of an item, with the path resolved.
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
pub enum ResolvedVisibility {
    /// Visibility is restricted to a certain module.
    Module(ModuleId),
    /// Visibility is unrestricted.
    Public,
}

impl ResolvedVisibility {
    pub fn visible_from(self, db: &impl DefDatabase, from_module: ModuleId) -> bool {
        let to_module = match self {
            ResolvedVisibility::Module(m) => m,
            ResolvedVisibility::Public => return true,
        };
        // if they're not in the same crate, it can't be visible
        if from_module.krate != to_module.krate {
            return false;
        }
        // from_module needs to be a descendant of to_module
        let def_map = db.crate_def_map(from_module.krate);
        let mut ancestors = std::iter::successors(Some(from_module), |m| {
            let parent_id = def_map[m.local_id].parent?;
            Some(ModuleId { local_id: parent_id, ..*m })
        });
        ancestors.any(|m| m == to_module)
    }
}

fn visibility_from_loc<T>(node: T, db: &impl DefDatabase) -> Visibility
where
    T: HasSource,
    T::Value: ast::VisibilityOwner,
{
    let src = node.source(db);
    Visibility::from_ast(db, src.map(|n| n.visibility()))
}
<|endoftext|>


<commit_before>//! Generate valid parse trees.

use grammar::repr::*;
use rand::{self, Rng};
use std::iter::Iterator;

#[derive(PartialEq, Eq)]
pub enum ParseTree {
    Nonterminal(NonterminalString, Vec<ParseTree>),
    Terminal(TerminalString),
}

pub fn random_parse_tree(grammar: &Grammar, symbol: NonterminalString) -> ParseTree {
    let mut gen = Generator { grammar: grammar, rng: rand::thread_rng(), depth: 0 };
    loop {
        // sometimes, the random walk overflows the stack, so we have a max, and if
        // it is exceeded, we just try again
        if let Some(result) = gen.nonterminal(symbol) {
            return result;
        }
        gen.depth = 0;
    }
}

struct Generator<'grammar> {
    grammar: &'grammar Grammar,
    rng: rand::ThreadRng,
    depth: u32,
}

const MAX_DEPTH: u32 = 10000;

impl<'grammar> Generator<'grammar> {
    fn nonterminal(&mut self, nt: NonterminalString) -> Option<ParseTree> {
        if self.depth > MAX_DEPTH {
            return None;
        }

        self.depth += 1;
        let productions = self.grammar.productions_for(nt);
        let index: usize = self.rng.gen_range(0, productions.len());
        let production = &productions[index];
        let trees: Option<Vec<_>> = production.symbols.iter()
                                                      .map(|&sym| self.symbol(sym))
                                                      .collect();
        trees.map(|trees| ParseTree::Nonterminal(nt, trees))
    }

    fn symbol(&mut self, symbol: Symbol) -> Option<ParseTree> {
        match symbol {
            Symbol::Nonterminal(nt) => self.nonterminal(nt),
            Symbol::Terminal(t) => Some(ParseTree::Terminal(t)),
        }
    }
}

impl ParseTree {
    pub fn terminals(&self) -> Vec<TerminalString> {
        let mut vec = vec![];
        self.push_terminals(&mut vec);
        vec
    }

    fn push_terminals(&self, vec: &mut Vec<TerminalString>) {
        match *self {
            ParseTree::Terminal(s) => vec.push(s),
            ParseTree::Nonterminal(_, ref trees) => {
                for tree in trees {
                    tree.push_terminals(vec);
                }
            }
        }
    }
}
<commit_msg>Fix compile error when running cargo test on the main crate<commit_after>//! Generate valid parse trees.

use grammar::repr::*;
use rand::{self, Rng};
use std::iter::Iterator;

#[derive(PartialEq, Eq)]
pub enum ParseTree {
    Nonterminal(NonterminalString, Vec<ParseTree>),
    Terminal(TerminalString),
}

pub fn random_parse_tree(grammar: &Grammar, symbol: NonterminalString) -> ParseTree {
    let mut gen = Generator { grammar: grammar, rng: rand::thread_rng(), depth: 0 };
    loop {
        // sometimes, the random walk overflows the stack, so we have a max, and if
        // it is exceeded, we just try again
        if let Some(result) = gen.nonterminal(symbol) {
            return result;
        }
        gen.depth = 0;
    }
}

struct Generator<'grammar> {
    grammar: &'grammar Grammar,
    rng: rand::ThreadRng,
    depth: u32,
}

const MAX_DEPTH: u32 = 10000;

impl<'grammar> Generator<'grammar> {
    fn nonterminal(&mut self, nt: NonterminalString) -> Option<ParseTree> {
        if self.depth > MAX_DEPTH {
            return None;
        }

        self.depth += 1;
        let productions = self.grammar.productions_for(nt);
        let index: usize = self.rng.gen_range(0, productions.len());
        let production = &productions[index];
        let trees: Option<Vec<_>> = production.symbols.iter()
                                                      .map(|&sym| self.symbol(sym))
                                                      .collect();
        trees.map(|trees| ParseTree::Nonterminal(nt, trees))
    }

    fn symbol(&mut self, symbol: Symbol) -> Option<ParseTree> {
        match symbol {
            Symbol::Nonterminal(nt) => self.nonterminal(nt),
            Symbol::Terminal(t) => Some(ParseTree::Terminal(t)),
            Symbol::Error => None,
        }
    }
}

impl ParseTree {
    pub fn terminals(&self) -> Vec<TerminalString> {
        let mut vec = vec![];
        self.push_terminals(&mut vec);
        vec
    }

    fn push_terminals(&self, vec: &mut Vec<TerminalString>) {
        match *self {
            ParseTree::Terminal(s) => vec.push(s),
            ParseTree::Nonterminal(_, ref trees) => {
                for tree in trees {
                    tree.push_terminals(vec);
                }
            }
        }
    }
}
<|endoftext|>


<commit_before>use super::{Open, Sink};
use alsa::device_name::HintIter;
use alsa::pcm::{Access, Format, Frames, HwParams, PCM};
use alsa::{Direction, Error, ValueOr};
use std::cmp::min;
use std::ffi::CString;
use std::io;
use std::process::exit;

const PREFERED_PERIOD_SIZE: Frames = 5512; // Period of roughly 125ms
const BUFFERED_PERIODS: Frames = 4;

pub struct AlsaSink {
    pcm: Option<PCM>,
    device: String,
    buffer: Vec<i16>,
}

fn list_outputs() {
    for t in &["pcm", "ctl", "hwdep"] {
        println!("{} devices:", t);
        let i = HintIter::new(None, &*CString::new(*t).unwrap()).unwrap();
        for a in i {
            if let Some(Direction::Playback) = a.direction {
                // mimic aplay -L
                println!(
                    "{}\n\t{}\n",
                    a.name.unwrap(),
                    a.desc.unwrap().replace("\n", "\n\t")
                );
            }
        }
    }
}

fn open_device(dev_name: &str) -> Result<(PCM, Frames), Box<Error>> {
    let pcm = PCM::new(dev_name, Direction::Playback, false)?;
    let period_size = PREFERED_PERIOD_SIZE;
    // http://www.linuxjournal.com/article/6735?page=0,1#N0x19ab2890.0x19ba78d8
    // latency = period_size * periods / (rate * bytes_per_frame)
    // For 16 Bit stereo data, one frame has a length of four bytes.
    // 500ms  = buffer_size / (44100 * 4)
    // buffer_size_bytes = 0.5 * 44100 / 4
    // buffer_size_frames = 0.5 * 44100 = 22050
    {
        // Set hardware parameters: 44100 Hz / Stereo / 16 bit
        let hwp = HwParams::any(&pcm)?;

        hwp.set_access(Access::RWInterleaved)?;
        hwp.set_format(Format::s16())?;
        hwp.set_rate(44100, ValueOr::Nearest)?;
        hwp.set_channels(2)?;
        let period_size = hwp.set_period_size_near(period_size, ValueOr::Greater)?;
        hwp.set_buffer_size_near(period_size * BUFFERED_PERIODS)?;
        pcm.hw_params(&hwp)?;

        let swp = pcm.sw_params_current()?;
        swp.set_start_threshold(hwp.get_buffer_size()? - hwp.get_period_size()?)?;
        pcm.sw_params(&swp)?;
    }

    Ok((pcm, period_size))
}

impl Open for AlsaSink {
    fn open(device: Option<String>) -> AlsaSink {
        info!("Using alsa sink");

        let name = match device.as_ref().map(AsRef::as_ref) {
            Some("?") => {
                println!("Listing available alsa outputs");
                list_outputs();
                exit(0)
            }
            Some(device) => device,
            None => "default",
        }
        .to_string();

        AlsaSink {
            pcm: None,
            device: name,
            buffer: vec![],
        }
    }
}

impl Sink for AlsaSink {
    fn start(&mut self) -> io::Result<()> {
        if self.pcm.is_none() {
            let pcm = open_device(&self.device);
            match pcm {
                Ok((p, period_size)) => {
                    self.pcm = Some(p);
                    // Create a buffer for all samples for a full period
                    self.buffer = Vec::with_capacity((period_size * 2) as usize);
                }
                Err(e) => {
                    error!("Alsa error PCM open {}", e);
                    return Err(io::Error::new(
                        io::ErrorKind::Other,
                        "Alsa error: PCM open failed",
                    ));
                }
            }
        }

        Ok(())
    }

    fn stop(&mut self) -> io::Result<()> {
        {
            let pcm = self.pcm.as_mut().unwrap();
            // Write any leftover data in the period buffer
            // before draining the actual buffer
            let io = pcm.io_i16().unwrap();
            match io.writei(&self.buffer[..]) {
                Ok(_) => (),
                Err(err) => pcm.try_recover(err, false).unwrap(),
            }
            pcm.drain().unwrap();
        }
        self.pcm = None;
        Ok(())
    }

    fn write(&mut self, data: &[i16]) -> io::Result<()> {
        let mut processed_data = 0;
        while processed_data < data.len() {
            let data_to_buffer = min(
                self.buffer.capacity() - self.buffer.len(),
                data.len() - processed_data,
            );
            self.buffer
                .extend_from_slice(&data[processed_data..processed_data + data_to_buffer]);
            processed_data += data_to_buffer;
            if self.buffer.len() == self.buffer.capacity() {
                let pcm = self.pcm.as_mut().unwrap();
                let io = pcm.io_i16().unwrap();
                match io.writei(&self.buffer) {
                    Ok(_) => (),
                    Err(err) => pcm.try_recover(err, false).unwrap(),
                }
                self.buffer.clear();
            }
        }

        Ok(())
    }
}
<commit_msg>Actually store the period_size<commit_after>use super::{Open, Sink};
use alsa::device_name::HintIter;
use alsa::pcm::{Access, Format, Frames, HwParams, PCM};
use alsa::{Direction, Error, ValueOr};
use std::cmp::min;
use std::ffi::CString;
use std::io;
use std::process::exit;

const PREFERED_PERIOD_SIZE: Frames = 5512; // Period of roughly 125ms
const BUFFERED_PERIODS: Frames = 4;

pub struct AlsaSink {
    pcm: Option<PCM>,
    device: String,
    buffer: Vec<i16>,
}

fn list_outputs() {
    for t in &["pcm", "ctl", "hwdep"] {
        println!("{} devices:", t);
        let i = HintIter::new(None, &*CString::new(*t).unwrap()).unwrap();
        for a in i {
            if let Some(Direction::Playback) = a.direction {
                // mimic aplay -L
                println!(
                    "{}\n\t{}\n",
                    a.name.unwrap(),
                    a.desc.unwrap().replace("\n", "\n\t")
                );
            }
        }
    }
}

fn open_device(dev_name: &str) -> Result<(PCM, Frames), Box<Error>> {
    let pcm = PCM::new(dev_name, Direction::Playback, false)?;
    let mut period_size = PREFERED_PERIOD_SIZE;
    // http://www.linuxjournal.com/article/6735?page=0,1#N0x19ab2890.0x19ba78d8
    // latency = period_size * periods / (rate * bytes_per_frame)
    // For 16 Bit stereo data, one frame has a length of four bytes.
    // 500ms  = buffer_size / (44100 * 4)
    // buffer_size_bytes = 0.5 * 44100 / 4
    // buffer_size_frames = 0.5 * 44100 = 22050
    {
        // Set hardware parameters: 44100 Hz / Stereo / 16 bit
        let hwp = HwParams::any(&pcm)?;

        hwp.set_access(Access::RWInterleaved)?;
        hwp.set_format(Format::s16())?;
        hwp.set_rate(44100, ValueOr::Nearest)?;
        hwp.set_channels(2)?;
        period_size = hwp.set_period_size_near(period_size, ValueOr::Greater)?;
        hwp.set_buffer_size_near(period_size * BUFFERED_PERIODS)?;
        pcm.hw_params(&hwp)?;

        let swp = pcm.sw_params_current()?;
        swp.set_start_threshold(hwp.get_buffer_size()? - hwp.get_period_size()?)?;
        pcm.sw_params(&swp)?;
    }

    Ok((pcm, period_size))
}

impl Open for AlsaSink {
    fn open(device: Option<String>) -> AlsaSink {
        info!("Using alsa sink");

        let name = match device.as_ref().map(AsRef::as_ref) {
            Some("?") => {
                println!("Listing available alsa outputs");
                list_outputs();
                exit(0)
            }
            Some(device) => device,
            None => "default",
        }
        .to_string();

        AlsaSink {
            pcm: None,
            device: name,
            buffer: vec![],
        }
    }
}

impl Sink for AlsaSink {
    fn start(&mut self) -> io::Result<()> {
        if self.pcm.is_none() {
            let pcm = open_device(&self.device);
            match pcm {
                Ok((p, period_size)) => {
                    self.pcm = Some(p);
                    // Create a buffer for all samples for a full period
                    self.buffer = Vec::with_capacity((period_size * 2) as usize);
                }
                Err(e) => {
                    error!("Alsa error PCM open {}", e);
                    return Err(io::Error::new(
                        io::ErrorKind::Other,
                        "Alsa error: PCM open failed",
                    ));
                }
            }
        }

        Ok(())
    }

    fn stop(&mut self) -> io::Result<()> {
        {
            let pcm = self.pcm.as_mut().unwrap();
            // Write any leftover data in the period buffer
            // before draining the actual buffer
            let io = pcm.io_i16().unwrap();
            match io.writei(&self.buffer[..]) {
                Ok(_) => (),
                Err(err) => pcm.try_recover(err, false).unwrap(),
            }
            pcm.drain().unwrap();
        }
        self.pcm = None;
        Ok(())
    }

    fn write(&mut self, data: &[i16]) -> io::Result<()> {
        let mut processed_data = 0;
        while processed_data < data.len() {
            let data_to_buffer = min(
                self.buffer.capacity() - self.buffer.len(),
                data.len() - processed_data,
            );
            self.buffer
                .extend_from_slice(&data[processed_data..processed_data + data_to_buffer]);
            processed_data += data_to_buffer;
            if self.buffer.len() == self.buffer.capacity() {
                let pcm = self.pcm.as_mut().unwrap();
                let io = pcm.io_i16().unwrap();
                match io.writei(&self.buffer) {
                    Ok(_) => (),
                    Err(err) => pcm.try_recover(err, false).unwrap(),
                }
                self.buffer.clear();
            }
        }

        Ok(())
    }
}
<|endoftext|>


<commit_before>// Implements http://rosettacode.org/wiki/24_game
// Uses RPN expression

#[cfg(not(test))]
fn main() {
    use std::rand::{task_rng, Rng};
    use std::io;

    // generating 4 numbers
    let mut rng = task_rng();
    let mut reader = io::stdin();
    let choices = Vec::from_fn(5, |_| rng.gen_range(1u, 10));
    println!("Make 24 with the following numbers");

    // start the game loop
    loop {
        print!("Your numbers: {}, {}, {}, {}\n", choices[0], choices[1], choices[2], choices[3]);
        let expr = reader.read_line().ok().expect("Failed to read line!");
        if check_input(expr, &choices) { break; }
        print!("Try again? (y/n): ");
        let choice = reader.read_line().ok().expect("Failed to read line!");
        if choice.as_slice().trim() != "y" { break; }
    }
}

fn check_input(expr: String, choices: &Vec<uint>) -> bool {
    let mut stack: Vec<uint> = Vec::new();
    for token in expr.as_slice().words() {
        if is_operator(&token) {
            let (a, b) = (stack.pop(), stack.pop());
            match (a, b) {
                (Some(x), Some(y)) => stack.push(evaluate(y, x, token)),
                (_, _) => {
                    println!("Not a valid RPN expression!");
                    return false ;
                }
            }
        } else {
            let v: Option<uint> = from_str(token);
            match v {
                Some(n) => {
                    // check if the number is valid
                    if !choices.contains(&n) {
                        println!("Cannot use {}", n);
                        return false;
                    }
                    stack.push(n)
                },
                None => {
                    println!("Invalid input: {}", token);
                    return false;
                }
            }
        }
    }

    let ans = stack.pop();
    if stack.len() > 0 {
        println!("Not a valid RPN expression!");
        return false;
    }
    match ans {
        Some(x) => {
            if x == 24 {
                println!("Good job!");
                return true;
            }
            println!("Wrong answer. Result: {}", x);
        }
        None => println!("Error encountered!"),
    }
    false
}

// since evaluate is wrapped in is_operator the last
// pattern has to be "/"
fn evaluate(a: uint, b: uint, op: &str) -> uint {
    match op {
        "+" => a + b,
        "-" => a - b,
        "*" => a * b,
        "/" => a / b,
        _   => unreachable!()
    }
}

fn is_operator(op: &&str) -> bool {
    ["*", "-", "+", "/"].contains(op)
}

#[test]
fn test_check_input() {
    let v1: Vec<uint> = vec![4, 3, 6, 2];

    // correct result
    let result1 = check_input("4 3 * 6 2 * +".to_string(), &v1);
    assert!(result1);

    // incorrect result
    let result2 = check_input("4 3 + 2 6 + -".to_string(), &v1);
    assert!(!result2);

    // wrong numbers in input
    let result3 = check_input("4 5 + 6 2 * -".to_string(), &v1);
    assert!(!result3);

    // invalid chars in input
    let result4 = check_input("4 ) + _ 2 * -".to_string(), &v1);
    assert!(!result4);

    // invalid RPN expression
    let result5 = check_input("4 3 + 6 2 *".to_string(), &v1);
    assert!(!result5);
}
<commit_msg>From Bool => Result<commit_after>// Implements http://rosettacode.org/wiki/24_game
// Uses RPN expression

#[cfg(not(test))]
fn main() {
    use std::rand::{task_rng, Rng};
    use std::io;

    let mut rng = task_rng();
    let mut reader = io::stdin();

    // generating 4 numbers
    let choices = Vec::from_fn(5, |_| rng.gen_range(1u, 10));
    println!("Make 24 with the following numbers");

    // start the game loop
    loop {
        print!("Your numbers: {}, {}, {}, {}\n", choices[0], choices[1], choices[2], choices[3]);
        let expr = reader.read_line().ok().expect("Failed to read line!");
        match check_input(expr, &choices) {
            Ok(()) => { println!("Good job!"); break; },
            Err(e) => println!("{}", e)
        }
        print!("Try again? (y/n): ");
        let choice = reader.read_line().ok().expect("Failed to read line!");
        if choice.as_slice().trim() != "y" { break; }
    }
}

fn check_input(expr: String, choices: &Vec<uint>) -> Result<(), String> {
    let mut stack: Vec<uint> = Vec::new();
    for token in expr.as_slice().words() {
        if is_operator(&token) {
            let (a, b) = (stack.pop(), stack.pop());
            match (a, b) {
                (Some(x), Some(y)) => stack.push(evaluate(y, x, token)),
                (_, _) => return Err("Not a valid RPN expression!".to_string())
            }
        } else {
            let v: Option<uint> = from_str(token);
            match v {
                Some(n) => {
                    // check if the number is valid
                    if !choices.contains(&n) {
                        return Err(format!("Cannot use {}", n));
                    }
                    stack.push(n)
                },
                None => return Err(format!("Invalid input: {}", token))
            }
        }
    }

    let ans = stack.pop();
    if stack.len() > 0 {
        return Err("Not a valid RPN expression!".to_string());
    }
    match ans {
        Some(x) => {
            if x == 24 { return Ok(()); }
            return Err(format!("Wrong answer. Result: {}", x));
        }
        None => return Err("Error encountered!".to_string()),
    }
}

// since evaluate is wrapped in is_operator the last
// pattern has to be "/"
fn evaluate(a: uint, b: uint, op: &str) -> uint {
    match op {
        "+" => a + b,
        "-" => a - b,
        "*" => a * b,
        "/" => a / b,
        _   => unreachable!()
    }
}

fn is_operator(op: &&str) -> bool {
    ["*", "-", "+", "/"].contains(op)
}

#[test]
fn test_check_input() {
    let v1: Vec<uint> = vec![4, 3, 6, 2];

    // correct result
    match check_input("4 3 * 6 2 * +".to_string(), &v1) {
        Ok(()) => assert!(true),
        Err(_) => assert!(false)
    }

    // incorrect result
    match check_input("4 3 * 2 6 + -".to_string(), &v1) {
        Ok(()) => assert!(false),
        Err(e) => assert_eq!(e, "Wrong answer. Result: 4".to_string())
    }

    // wrong numbers in input
    match check_input("4 5 + 6 2 * -".to_string(), &v1) {
        Ok(()) => assert!(false),
        Err(e) => assert_eq!(e, "Cannot use 5".to_string())
    }

    // invalid chars in input
    match check_input("4 ) + _ 2 * -".to_string(), &v1) {
        Ok(()) => assert!(false),
        Err(e) => assert_eq!(e, "Invalid input: )".to_string())
    }

    // invalid RPN expression
    match check_input("4 3 + 6 2 *".to_string(), &v1) {
        Ok(()) => assert!(false),
        Err(e) => assert_eq!(e, "Not a valid RPN expression!".to_string())
    }
}
<|endoftext|>


<commit_before>// pest. The Elegant Parser
// Copyright (c) 2018 Dragoș Tiselice
//
// 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. All files in the project carrying such notice may not be copied,
// modified, or distributed except according to those terms.

#[derive(Clone, Debug, Eq, PartialEq)]
pub struct Rule {
    pub name: String,
    pub ty: RuleType,
    pub expr: Expr
}

#[derive(Clone, Copy, Debug, Eq, PartialEq)]
pub enum RuleType {
    Normal,
    Silent,
    Atomic,
    CompoundAtomic,
    NonAtomic
}

#[derive(Clone, Debug, Eq, PartialEq)]
pub enum Expr {
    Str(String),
    Insens(String),
    Range(String, String),
    Ident(String),
    PosPred(Box<Expr>),
    NegPred(Box<Expr>),
    Seq(Box<Expr>, Box<Expr>),
    Choice(Box<Expr>, Box<Expr>),
    Opt(Box<Expr>),
    Rep(Box<Expr>),
    RepOnce(Box<Expr>),
    RepExact(Box<Expr>, u32),
    RepMin(Box<Expr>, u32),
    RepMax(Box<Expr>, u32),
    RepMinMax(Box<Expr>, u32, u32),
    Skip(Vec<String>),
    Push(Box<Expr>)
}

impl Expr {
    pub fn map_top_down<F>(self, mut f: F) -> Expr
    where
        F: FnMut(Expr) -> Expr
    {
        pub fn map_internal<'i, F>(expr: Expr, f: &mut F) -> Expr
        where
            F: FnMut(Expr) -> Expr
        {
            let expr = f(expr);

            match expr {
                // TODO: Use box syntax when it gets stabilized.
                Expr::PosPred(expr) => {
                    let mapped = Box::new(map_internal(*expr, f));
                    Expr::PosPred(mapped)
                }
                Expr::NegPred(expr) => {
                    let mapped = Box::new(map_internal(*expr, f));
                    Expr::NegPred(mapped)
                }
                Expr::Seq(lhs, rhs) => {
                    let mapped_lhs = Box::new(map_internal(*lhs, f));
                    let mapped_rhs = Box::new(map_internal(*rhs, f));
                    Expr::Seq(mapped_lhs, mapped_rhs)
                }
                Expr::Choice(lhs, rhs) => {
                    let mapped_lhs = Box::new(map_internal(*lhs, f));
                    let mapped_rhs = Box::new(map_internal(*rhs, f));
                    Expr::Choice(mapped_lhs, mapped_rhs)
                }
                Expr::Rep(expr) => {
                    let mapped = Box::new(map_internal(*expr, f));
                    Expr::Rep(mapped)
                }
                Expr::RepOnce(expr) => {
                    let mapped = Box::new(map_internal(*expr, f));
                    Expr::RepOnce(mapped)
                }
                Expr::RepExact(expr, max) => {
                    let mapped = Box::new(map_internal(*expr, f));
                    Expr::RepExact(mapped, max)
                }
                Expr::RepMin(expr, num) => {
                    let mapped = Box::new(map_internal(*expr, f));
                    Expr::RepMin(mapped, num)
                }
                Expr::RepMax(expr, num) => {
                    let mapped = Box::new(map_internal(*expr, f));
                    Expr::RepMax(mapped, num)
                }
                Expr::RepMinMax(expr, min, max) => {
                    let mapped = Box::new(map_internal(*expr, f));
                    Expr::RepMinMax(mapped, min, max)
                }
                Expr::Opt(expr) => {
                    let mapped = Box::new(map_internal(*expr, f));
                    Expr::Opt(mapped)
                }
                Expr::Push(expr) => {
                    let mapped = Box::new(map_internal(*expr, f));
                    Expr::Push(mapped)
                }
                expr => expr
            }
        }

        map_internal(self, &mut f)
    }

    pub fn map_bottom_up<F>(self, mut f: F) -> Expr
    where
        F: FnMut(Expr) -> Expr
    {
        pub fn map_internal<'i, F>(expr: Expr, f: &mut F) -> Expr
        where
            F: FnMut(Expr) -> Expr
        {
            let mapped = match expr {
                Expr::PosPred(expr) => {
                    // TODO: Use box syntax when it gets stabilized.
                    let mapped = Box::new(map_internal(*expr, f));
                    Expr::PosPred(mapped)
                }
                Expr::NegPred(expr) => {
                    let mapped = Box::new(map_internal(*expr, f));
                    Expr::NegPred(mapped)
                }
                Expr::Seq(lhs, rhs) => {
                    let mapped_lhs = Box::new(map_internal(*lhs, f));
                    let mapped_rhs = Box::new(map_internal(*rhs, f));
                    Expr::Seq(mapped_lhs, mapped_rhs)
                }
                Expr::Choice(lhs, rhs) => {
                    let mapped_lhs = Box::new(map_internal(*lhs, f));
                    let mapped_rhs = Box::new(map_internal(*rhs, f));
                    Expr::Choice(mapped_lhs, mapped_rhs)
                }
                Expr::Rep(expr) => {
                    let mapped = Box::new(map_internal(*expr, f));
                    Expr::Rep(mapped)
                }
                Expr::RepOnce(expr) => {
                    let mapped = Box::new(map_internal(*expr, f));
                    Expr::RepOnce(mapped)
                }
                Expr::RepExact(expr, num) => {
                    let mapped = Box::new(map_internal(*expr, f));
                    Expr::RepExact(mapped, num)
                }
                Expr::RepMin(expr, max) => {
                    let mapped = Box::new(map_internal(*expr, f));
                    Expr::RepMin(mapped, max)
                }
                Expr::RepMax(expr, max) => {
                    let mapped = Box::new(map_internal(*expr, f));
                    Expr::RepMax(mapped, max)
                }
                Expr::RepMinMax(expr, min, max) => {
                    let mapped = Box::new(map_internal(*expr, f));
                    Expr::RepMinMax(mapped, min, max)
                }
                Expr::Opt(expr) => {
                    let mapped = Box::new(map_internal(*expr, f));
                    Expr::Opt(mapped)
                }
                Expr::Push(expr) => {
                    let mapped = Box::new(map_internal(*expr, f));
                    Expr::Push(mapped)
                }
                expr => expr
            };

            f(mapped)
        }

        map_internal(self, &mut f)
    }
}

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

    #[test]
    fn identity() {
        let expr = Expr::Choice(
            Box::new(Expr::Seq(
                Box::new(Expr::Ident("a".to_owned())),
                Box::new(Expr::Str("b".to_owned()))
            )),
            Box::new(Expr::PosPred(Box::new(Expr::NegPred(Box::new(
                Expr::Rep(Box::new(Expr::RepOnce(Box::new(Expr::Opt(Box::new(
                    Expr::Choice(
                        Box::new(Expr::Insens("c".to_owned())),
                        Box::new(Expr::Push(Box::new(Expr::Range(
                            "'d'".to_owned(),
                            "'e'".to_owned()
                        ))))
                    )
                ))))))
            )))))
        );

        assert_eq!(
            expr.clone()
                .map_bottom_up(|expr| expr)
                .map_top_down(|expr| expr),
            expr
        );
    }
}
<commit_msg>Removed pointless lifetimes.<commit_after>// pest. The Elegant Parser
// Copyright (c) 2018 Dragoș Tiselice
//
// 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. All files in the project carrying such notice may not be copied,
// modified, or distributed except according to those terms.

#[derive(Clone, Debug, Eq, PartialEq)]
pub struct Rule {
    pub name: String,
    pub ty: RuleType,
    pub expr: Expr
}

#[derive(Clone, Copy, Debug, Eq, PartialEq)]
pub enum RuleType {
    Normal,
    Silent,
    Atomic,
    CompoundAtomic,
    NonAtomic
}

#[derive(Clone, Debug, Eq, PartialEq)]
pub enum Expr {
    Str(String),
    Insens(String),
    Range(String, String),
    Ident(String),
    PosPred(Box<Expr>),
    NegPred(Box<Expr>),
    Seq(Box<Expr>, Box<Expr>),
    Choice(Box<Expr>, Box<Expr>),
    Opt(Box<Expr>),
    Rep(Box<Expr>),
    RepOnce(Box<Expr>),
    RepExact(Box<Expr>, u32),
    RepMin(Box<Expr>, u32),
    RepMax(Box<Expr>, u32),
    RepMinMax(Box<Expr>, u32, u32),
    Skip(Vec<String>),
    Push(Box<Expr>)
}

impl Expr {
    pub fn map_top_down<F>(self, mut f: F) -> Expr
    where
        F: FnMut(Expr) -> Expr
    {
        pub fn map_internal<F>(expr: Expr, f: &mut F) -> Expr
        where
            F: FnMut(Expr) -> Expr
        {
            let expr = f(expr);

            match expr {
                // TODO: Use box syntax when it gets stabilized.
                Expr::PosPred(expr) => {
                    let mapped = Box::new(map_internal(*expr, f));
                    Expr::PosPred(mapped)
                }
                Expr::NegPred(expr) => {
                    let mapped = Box::new(map_internal(*expr, f));
                    Expr::NegPred(mapped)
                }
                Expr::Seq(lhs, rhs) => {
                    let mapped_lhs = Box::new(map_internal(*lhs, f));
                    let mapped_rhs = Box::new(map_internal(*rhs, f));
                    Expr::Seq(mapped_lhs, mapped_rhs)
                }
                Expr::Choice(lhs, rhs) => {
                    let mapped_lhs = Box::new(map_internal(*lhs, f));
                    let mapped_rhs = Box::new(map_internal(*rhs, f));
                    Expr::Choice(mapped_lhs, mapped_rhs)
                }
                Expr::Rep(expr) => {
                    let mapped = Box::new(map_internal(*expr, f));
                    Expr::Rep(mapped)
                }
                Expr::RepOnce(expr) => {
                    let mapped = Box::new(map_internal(*expr, f));
                    Expr::RepOnce(mapped)
                }
                Expr::RepExact(expr, max) => {
                    let mapped = Box::new(map_internal(*expr, f));
                    Expr::RepExact(mapped, max)
                }
                Expr::RepMin(expr, num) => {
                    let mapped = Box::new(map_internal(*expr, f));
                    Expr::RepMin(mapped, num)
                }
                Expr::RepMax(expr, num) => {
                    let mapped = Box::new(map_internal(*expr, f));
                    Expr::RepMax(mapped, num)
                }
                Expr::RepMinMax(expr, min, max) => {
                    let mapped = Box::new(map_internal(*expr, f));
                    Expr::RepMinMax(mapped, min, max)
                }
                Expr::Opt(expr) => {
                    let mapped = Box::new(map_internal(*expr, f));
                    Expr::Opt(mapped)
                }
                Expr::Push(expr) => {
                    let mapped = Box::new(map_internal(*expr, f));
                    Expr::Push(mapped)
                }
                expr => expr
            }
        }

        map_internal(self, &mut f)
    }

    pub fn map_bottom_up<F>(self, mut f: F) -> Expr
    where
        F: FnMut(Expr) -> Expr
    {
        pub fn map_internal<F>(expr: Expr, f: &mut F) -> Expr
        where
            F: FnMut(Expr) -> Expr
        {
            let mapped = match expr {
                Expr::PosPred(expr) => {
                    // TODO: Use box syntax when it gets stabilized.
                    let mapped = Box::new(map_internal(*expr, f));
                    Expr::PosPred(mapped)
                }
                Expr::NegPred(expr) => {
                    let mapped = Box::new(map_internal(*expr, f));
                    Expr::NegPred(mapped)
                }
                Expr::Seq(lhs, rhs) => {
                    let mapped_lhs = Box::new(map_internal(*lhs, f));
                    let mapped_rhs = Box::new(map_internal(*rhs, f));
                    Expr::Seq(mapped_lhs, mapped_rhs)
                }
                Expr::Choice(lhs, rhs) => {
                    let mapped_lhs = Box::new(map_internal(*lhs, f));
                    let mapped_rhs = Box::new(map_internal(*rhs, f));
                    Expr::Choice(mapped_lhs, mapped_rhs)
                }
                Expr::Rep(expr) => {
                    let mapped = Box::new(map_internal(*expr, f));
                    Expr::Rep(mapped)
                }
                Expr::RepOnce(expr) => {
                    let mapped = Box::new(map_internal(*expr, f));
                    Expr::RepOnce(mapped)
                }
                Expr::RepExact(expr, num) => {
                    let mapped = Box::new(map_internal(*expr, f));
                    Expr::RepExact(mapped, num)
                }
                Expr::RepMin(expr, max) => {
                    let mapped = Box::new(map_internal(*expr, f));
                    Expr::RepMin(mapped, max)
                }
                Expr::RepMax(expr, max) => {
                    let mapped = Box::new(map_internal(*expr, f));
                    Expr::RepMax(mapped, max)
                }
                Expr::RepMinMax(expr, min, max) => {
                    let mapped = Box::new(map_internal(*expr, f));
                    Expr::RepMinMax(mapped, min, max)
                }
                Expr::Opt(expr) => {
                    let mapped = Box::new(map_internal(*expr, f));
                    Expr::Opt(mapped)
                }
                Expr::Push(expr) => {
                    let mapped = Box::new(map_internal(*expr, f));
                    Expr::Push(mapped)
                }
                expr => expr
            };

            f(mapped)
        }

        map_internal(self, &mut f)
    }
}

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

    #[test]
    fn identity() {
        let expr = Expr::Choice(
            Box::new(Expr::Seq(
                Box::new(Expr::Ident("a".to_owned())),
                Box::new(Expr::Str("b".to_owned()))
            )),
            Box::new(Expr::PosPred(Box::new(Expr::NegPred(Box::new(
                Expr::Rep(Box::new(Expr::RepOnce(Box::new(Expr::Opt(Box::new(
                    Expr::Choice(
                        Box::new(Expr::Insens("c".to_owned())),
                        Box::new(Expr::Push(Box::new(Expr::Range(
                            "'d'".to_owned(),
                            "'e'".to_owned()
                        ))))
                    )
                ))))))
            )))))
        );

        assert_eq!(
            expr.clone()
                .map_bottom_up(|expr| expr)
                .map_top_down(|expr| expr),
            expr
        );
    }
}
<|endoftext|>


<commit_before>use std::rand::StdRng;
use std::rand::SeedableRng;
use serialize::{Decodable, Decoder, Encodable, Encoder};
use std::collections::hashmap::HashMap;
use terrain::TerrainType;
use terrain;
use location::Location;
use mapgen;
use egg::Egg;
use mob::{Player};
use {AreaSpec};

/// Immutable procedurally generated terrain initialized on random seed.
pub struct Area {
    seed: u32,
    terrain: HashMap<Location, TerrainType>,
}

impl<E, D:Decoder<E>> Decodable<D, E> for Area {
    fn decode(d: &mut D) -> Result<Area, E> {
        Ok(Area::new(try!(d.read_u32())))
    }
}

impl<E, S:Encoder<E>> Encodable<S, E> for Area {
    fn encode(&self, s: &mut S) -> Result<(), E> {
        s.emit_u32(self.seed)
    }
}

impl Area {
    pub fn new(seed: u32) -> Area {
        let mut terrain = HashMap::new();
        let mut rng: StdRng = SeedableRng::from_seed([seed as uint].as_slice());
        // TODO: Underground areas.
        mapgen::gen_herringbone(
            &mut rng,
            &AreaSpec::new(::Overland, 1),
            |p, t| {terrain.insert(Location::new(0, 0) + p, t);});

        Area {
            seed: seed,
            terrain: terrain,
        }
    }

    /// Return terrain at given location.
    pub fn terrain(&self, loc: Location) -> TerrainType {
        match self.terrain.find(&loc) {
            Some(&t) => t,
            None => self.default_terrain(loc)
        }
    }

    /// List the objects that should be hatched in the world during init. This
    /// is tied to map generation, so it goes in the area module.
   pub fn get_eggs(&self) -> Vec<(Egg, Location)> {
        // TODO: Properly.
        vec![
            (Egg::new(::MobKind(Player)), Location::new(0, 0)),
        ]
    }

    fn default_terrain(&self, _loc: Location) -> TerrainType {
        // TODO: Different default terrains in different biomes.
        terrain::Rock
    }
}
<commit_msg>Area invariant comment<commit_after>use std::rand::StdRng;
use std::rand::SeedableRng;
use serialize::{Decodable, Decoder, Encodable, Encoder};
use std::collections::hashmap::HashMap;
use terrain::TerrainType;
use terrain;
use location::Location;
use mapgen;
use egg::Egg;
use mob::{Player};
use {AreaSpec};

// Note to maintainer: Due to the way serialization works, Area *must* be
// generated to have exactly the same contents every time given the same seed
// value. That means absolutely no outside sources of randomness. Only use an
// internal generator initialized with the given seed value. And watch out for
// surprise randomness. A map generator in a previous project used memory
// addresses of temporary structures as indexing keys, and ended up with a
// nondeterminism bug that depended on the numerical order of the arbitrary
// address values.

/// Immutable procedurally generated terrain initialized on random seed.
pub struct Area {
    seed: u32,
    terrain: HashMap<Location, TerrainType>,
}

impl<E, D:Decoder<E>> Decodable<D, E> for Area {
    fn decode(d: &mut D) -> Result<Area, E> {
        Ok(Area::new(try!(d.read_u32())))
    }
}

impl<E, S:Encoder<E>> Encodable<S, E> for Area {
    fn encode(&self, s: &mut S) -> Result<(), E> {
        s.emit_u32(self.seed)
    }
}

impl Area {
    pub fn new(seed: u32) -> Area {
        let mut terrain = HashMap::new();
        let mut rng: StdRng = SeedableRng::from_seed([seed as uint].as_slice());
        // TODO: Underground areas.
        mapgen::gen_herringbone(
            &mut rng,
            &AreaSpec::new(::Overland, 1),
            |p, t| {terrain.insert(Location::new(0, 0) + p, t);});

        Area {
            seed: seed,
            terrain: terrain,
        }
    }

    /// Return terrain at given location.
    pub fn terrain(&self, loc: Location) -> TerrainType {
        match self.terrain.find(&loc) {
            Some(&t) => t,
            None => self.default_terrain(loc)
        }
    }

    /// List the objects that should be hatched in the world during init. This
    /// is tied to map generation, so it goes in the area module.
   pub fn get_eggs(&self) -> Vec<(Egg, Location)> {
        // TODO: Properly.
        vec![
            (Egg::new(::MobKind(Player)), Location::new(0, 0)),
        ]
    }

    fn default_terrain(&self, _loc: Location) -> TerrainType {
        // TODO: Different default terrains in different biomes.
        terrain::Rock
    }
}
<|endoftext|>


<commit_before>use pulldown_cmark::{html, Options, Parser};
use std::fs;

mod paths;
mod printing;

fn main() {
    printing::heading("Creating the build directory for my website.");

    printing::subheading("Cleaning the build directory.");
    paths::remove_dir(&paths::build());

    printing::subheading("Generating the build directory.");
    paths::create_dir(&paths::build());
    generate_pages();

    printing::subheading("Configuring the build directory.");
    // Adds a CNAME file for the host (GitHub Pages) and registrar (Hover) to use my custom domain name (trevordmiller.com)
    paths::create_file(&paths::build().join("CNAME"), "trevordmiller.com");
}

fn generate_pages() {
    match fs::read_dir(&paths::pages()) {
        Ok(markdown_files) => {
            for markdown_file in markdown_files {
                let markdown_file = match &markdown_file {
                    Ok(markdown_file) => markdown_file.path(),
                    Err(error) => panic!("There was a problem: {:?}", error),
                };

                let markdown_file_contents = match fs::read_to_string(&markdown_file) {
                    Ok(contents) => contents,
                    Err(error) => panic!("There was a problem: {:?}", error),
                };

                let route = &paths::file_stem(markdown_file);

                if route == "index" {
                    paths::create_file(
                        &paths::build()
                            .join("index.html"),
                        &markdown_to_html(&markdown_file_contents),
                    );
                } else {
                    paths::create_dir(&paths::build().join(route));
                    paths::create_file(
                        &paths::build()
                            .join(route)
                            .join("index.html"),
                        &markdown_to_html(&markdown_file_contents),
                    );
                }
            }
        }
        Err(error) => panic!("There was a problem: {:?}", error),
    };
}

fn markdown_to_html(markdown: &str) -> std::string::String {
    let css = r#"
        body {
            font-family: -apple-system, BlinkMacSystemFont, "Helvetica Neue", Helvetica, Arial, Verdana, sans-serif;
            color: #333333;
            max-width: 80ch;
            margin: 0 auto;
            padding: 1rem;
        }
        header a {
            font-size: 1rem;
            font-family: "Courier New", Courier, monospace;
            font-weight: normal;
            text-decoration: none;
            color: #333333;
            display: flex;
            align-items: center;
        }
        header a::before {
            content: ">";
            margin: 0 1ch 0 0;
        }
        header a::after {
            content: "";
            margin: 0 0 0 1ch;
            display: inline-block;
            background: #333333;
            width: 1ch;
            height: 1em;
            animation: cursor 800ms infinite;
        }
        @keyframes cursor {
            0% {
                opacity: 0;
            }
            50% {
                opacity: 1;
            }
            to {
                opacity: 0;
            }
        }
        li {
            margin-bottom: 0.5rem;
        }
        code {
            overflow: auto;
            display: block;
            background: #f5f5f5;
            padding: 1rem;
        }
        label, input {
            font-size: 1rem;
            display: block;
            margin-bottom: 1rem;
        }
        input[type=submit] {
            font-size: 1rem;
            cursor: pointer;
            border: 0 none;
            -moz-appearance: none;
            -webkit-appearance: none;
            background: #333333;
            color: #ffffff;
            padding: 0.5rem;
        }
    "#;

    let parser = Parser::new_ext(markdown, Options::empty());
    let mut html = String::new();
    html::push_html(&mut html, parser);

    format!("
        <!DOCTYPE html>

                <title>trevordmiller.com</title>
                <meta name='author' content='Trevor D. Miller'>
                <meta name='description' content='Personal website.'>
                <meta charset='utf-8'>
                <meta name='viewport' content='width=device-width, initial-scale=1'>

trevordmiller

                    {}

Join my newsletter

                    <form action='https://trevordmiller.us10.list-manage.com/subscribe/post?u=91fe993c2d93cde48679d6826&id=f7f097d693' method='post' id='mc-embedded-subscribe-form' name='mc-embedded-subscribe-form'>
                        Email address:
                        <input type='email' required placeholder='Your email' value='' name='EMAIL' id='mce-EMAIL'>

<input type='text' name='b_91fe993c2d93cde48679d6826_f7f097d693' tabindex='-1' value=''>

                        <input type='submit' value='Subscribe' placeholder='you@somewhere.com' name='subscribe' id='mc-embedded-subscribe'>
                    </form>

    ",
        css,
        &html
    )
}
<commit_msg>Format<commit_after>use pulldown_cmark::{html, Options, Parser};
use std::fs;

mod paths;
mod printing;

fn main() {
    printing::heading("Creating the build directory for my website.");

    printing::subheading("Cleaning the build directory.");
    paths::remove_dir(&paths::build());

    printing::subheading("Generating the build directory.");
    paths::create_dir(&paths::build());
    generate_pages();

    printing::subheading("Configuring the build directory.");
    // Adds a CNAME file for the host (GitHub Pages) and registrar (Hover) to use my custom domain name (trevordmiller.com)
    paths::create_file(&paths::build().join("CNAME"), "trevordmiller.com");
}

fn generate_pages() {
    match fs::read_dir(&paths::pages()) {
        Ok(markdown_files) => {
            for markdown_file in markdown_files {
                let markdown_file = match &markdown_file {
                    Ok(markdown_file) => markdown_file.path(),
                    Err(error) => panic!("There was a problem: {:?}", error),
                };

                let markdown_file_contents = match fs::read_to_string(&markdown_file) {
                    Ok(contents) => contents,
                    Err(error) => panic!("There was a problem: {:?}", error),
                };

                let route = &paths::file_stem(markdown_file);

                if route == "index" {
                    paths::create_file(
                        &paths::build().join("index.html"),
                        &markdown_to_html(&markdown_file_contents),
                    );
                } else {
                    paths::create_dir(&paths::build().join(route));
                    paths::create_file(
                        &paths::build().join(route).join("index.html"),
                        &markdown_to_html(&markdown_file_contents),
                    );
                }
            }
        }
        Err(error) => panic!("There was a problem: {:?}", error),
    };
}

fn markdown_to_html(markdown: &str) -> std::string::String {
    let css = r#"
        body {
            font-family: -apple-system, BlinkMacSystemFont, "Helvetica Neue", Helvetica, Arial, Verdana, sans-serif;
            color: #333333;
            max-width: 80ch;
            margin: 0 auto;
            padding: 1rem;
        }
        header a {
            font-size: 1rem;
            font-family: "Courier New", Courier, monospace;
            font-weight: normal;
            text-decoration: none;
            color: #333333;
            display: flex;
            align-items: center;
        }
        header a::before {
            content: ">";
            margin: 0 1ch 0 0;
        }
        header a::after {
            content: "";
            margin: 0 0 0 1ch;
            display: inline-block;
            background: #333333;
            width: 1ch;
            height: 1em;
            animation: cursor 800ms infinite;
        }
        @keyframes cursor {
            0% {
                opacity: 0;
            }
            50% {
                opacity: 1;
            }
            to {
                opacity: 0;
            }
        }
        li {
            margin-bottom: 0.5rem;
        }
        code {
            overflow: auto;
            display: block;
            background: #f5f5f5;
            padding: 1rem;
        }
        label, input {
            font-size: 1rem;
            display: block;
            margin-bottom: 1rem;
        }
        input[type=submit] {
            font-size: 1rem;
            cursor: pointer;
            border: 0 none;
            -moz-appearance: none;
            -webkit-appearance: none;
            background: #333333;
            color: #ffffff;
            padding: 0.5rem;
        }
    "#;

    let parser = Parser::new_ext(markdown, Options::empty());
    let mut html = String::new();
    html::push_html(&mut html, parser);

    format!("
        <!DOCTYPE html>

                <title>trevordmiller.com</title>
                <meta name='author' content='Trevor D. Miller'>
                <meta name='description' content='Personal website.'>
                <meta charset='utf-8'>
                <meta name='viewport' content='width=device-width, initial-scale=1'>

trevordmiller

                    {}

Join my newsletter

                    <form action='https://trevordmiller.us10.list-manage.com/subscribe/post?u=91fe993c2d93cde48679d6826&id=f7f097d693' method='post' id='mc-embedded-subscribe-form' name='mc-embedded-subscribe-form'>
                        Email address:
                        <input type='email' required placeholder='Your email' value='' name='EMAIL' id='mce-EMAIL'>

<input type='text' name='b_91fe993c2d93cde48679d6826_f7f097d693' tabindex='-1' value=''>

                        <input type='submit' value='Subscribe' placeholder='you@somewhere.com' name='subscribe' id='mc-embedded-subscribe'>
                    </form>

    ",
        css,
        &html
    )
}
<|endoftext|>


<commit_before>/*
 * Copyright (c) 2013, David Renshaw (dwrenshaw@gmail.com)
 *
 * See the LICENSE file in the capnproto-rust root directory.
 */

use std;

use common::*;
use catrank_capnp::*;

pub type RequestBuilder<'a> = SearchResultList::Builder<'a>;
pub type ResponseBuilder<'a> = SearchResultList::Builder<'a>;
pub type Expectation = int;
pub type RequestReader<'a> = SearchResultList::Reader<'a>;
pub type ResponseReader<'a> = SearchResultList::Reader<'a>;

pub struct ScoredResult<'a> {
    score : f64,
    result : SearchResult::Reader<'a>
}

static URL_PREFIX : &'static str = "http://example.com";

pub fn setup_request(rng : &mut FastRand, request : SearchResultList::Builder) -> int {
    let count = rng.next_less_than(1000) as uint;
    let mut goodCount : int = 0;

    let list = request.init_results(count);

    for i in range(0, count) {
        let result = list[i];
        result.set_score(1000.0 - i as f64);
        let url_size = rng.next_less_than(100) as uint;

        let url_prefix_length = URL_PREFIX.as_bytes().len();
        let url = result.init_url(url_size + url_prefix_length);

        let bytes = url.as_mut_bytes();
        std::io::BufWriter::new(bytes).write(URL_PREFIX.as_bytes()).unwrap();

        for j in range(0, url_size) {
            bytes[j + url_prefix_length] = (97 + rng.next_less_than(26)) as u8;
        }

        let isCat = rng.next_less_than(8) == 0;
        let isDog = rng.next_less_than(8) == 0;
        if isCat && !isDog {
            goodCount += 1;
        }

        let mut snippet = String::from_str(" ");

        let prefix = rng.next_less_than(20) as uint;
        for _ in range(0, prefix) {
            snippet.push_str(WORDS[rng.next_less_than(WORDS.len() as u32) as uint]);
        }
        if isCat { snippet.push_str("cat ") }
        if isDog { snippet.push_str("dog ") }

        let suffix = rng.next_less_than(20) as uint;
        for _ in range(0, suffix) {
            snippet.push_str(WORDS[rng.next_less_than(WORDS.len() as u32) as uint]);
        }

        result.set_snippet(snippet.as_slice());
    }

    goodCount
}

pub fn handle_request(request : SearchResultList::Reader,
                     response : SearchResultList::Builder) {
    let mut scoredResults : Vec<ScoredResult> = Vec::new();

    let results = request.get_results();
    for i in range(0, results.size()) {
        let result = results[i];
        let mut score = result.get_score();
        if result.get_snippet().contains(" cat ") {
            score *= 10000.0;
        }
        if result.get_snippet().contains(" dog ") {
            score /= 10000.0;
        }
        scoredResults.push(ScoredResult {score : score, result : result});
    }

    scoredResults.sort_by(|v1, v2| { if v1.score < v2.score { std::cmp::Less } else { std::cmp::Greater } });

    let list = response.init_results(scoredResults.len());
    for i in range(0, list.size()) {
        let item = list[i];
        let result = scoredResults.get(i);
        item.set_score(result.score);
        item.set_url(result.result.get_url());
        item.set_snippet(result.result.get_snippet());
    }
}

pub fn check_response(response : SearchResultList::Reader, expectedGoodCount : int) -> bool {
    let mut goodCount : int = 0;
    let results = response.get_results();
    for i in range(0, results.size()) {
        let result = results[i];
        if result.get_score() > 1001.0 {
            goodCount += 1;
        } else {
            break;
        }
    }
    return goodCount == expectedGoodCount;
}
<commit_msg>oops, was sorting in wrong order<commit_after>/*
 * Copyright (c) 2013, David Renshaw (dwrenshaw@gmail.com)
 *
 * See the LICENSE file in the capnproto-rust root directory.
 */

use std;

use common::*;
use catrank_capnp::*;

pub type RequestBuilder<'a> = SearchResultList::Builder<'a>;
pub type ResponseBuilder<'a> = SearchResultList::Builder<'a>;
pub type Expectation = int;
pub type RequestReader<'a> = SearchResultList::Reader<'a>;
pub type ResponseReader<'a> = SearchResultList::Reader<'a>;

pub struct ScoredResult<'a> {
    score : f64,
    result : SearchResult::Reader<'a>
}

static URL_PREFIX : &'static str = "http://example.com";

pub fn setup_request(rng : &mut FastRand, request : SearchResultList::Builder) -> int {
    let count = rng.next_less_than(1000) as uint;
    let mut goodCount : int = 0;

    let list = request.init_results(count);

    for i in range(0, count) {
        let result = list[i];
        result.set_score(1000.0 - i as f64);
        let url_size = rng.next_less_than(100) as uint;

        let url_prefix_length = URL_PREFIX.as_bytes().len();
        let url = result.init_url(url_size + url_prefix_length);

        let bytes = url.as_mut_bytes();
        std::io::BufWriter::new(bytes).write(URL_PREFIX.as_bytes()).unwrap();

        for j in range(0, url_size) {
            bytes[j + url_prefix_length] = (97 + rng.next_less_than(26)) as u8;
        }

        let isCat = rng.next_less_than(8) == 0;
        let isDog = rng.next_less_than(8) == 0;
        if isCat && !isDog {
            goodCount += 1;
        }

        let mut snippet = String::from_str(" ");

        let prefix = rng.next_less_than(20) as uint;
        for _ in range(0, prefix) {
            snippet.push_str(WORDS[rng.next_less_than(WORDS.len() as u32) as uint]);
        }
        if isCat { snippet.push_str("cat ") }
        if isDog { snippet.push_str("dog ") }

        let suffix = rng.next_less_than(20) as uint;
        for _ in range(0, suffix) {
            snippet.push_str(WORDS[rng.next_less_than(WORDS.len() as u32) as uint]);
        }

        result.set_snippet(snippet.as_slice());
    }

    goodCount
}

pub fn handle_request(request : SearchResultList::Reader,
                     response : SearchResultList::Builder) {
    let mut scoredResults : Vec<ScoredResult> = Vec::new();

    let results = request.get_results();
    for i in range(0, results.size()) {
        let result = results[i];
        let mut score = result.get_score();
        if result.get_snippet().contains(" cat ") {
            score *= 10000.0;
        }
        if result.get_snippet().contains(" dog ") {
            score /= 10000.0;
        }
        scoredResults.push(ScoredResult {score : score, result : result});
    }

    // sort in decreasing order
    scoredResults.sort_by(|v1, v2| { if v1.score < v2.score { std::cmp::Greater } else { std::cmp::Less } });

    let list = response.init_results(scoredResults.len());
    for i in range(0, list.size()) {
        let item = list[i];
        let result = scoredResults.get(i);
        item.set_score(result.score);
        item.set_url(result.result.get_url());
        item.set_snippet(result.result.get_snippet());
    }
}

pub fn check_response(response : SearchResultList::Reader, expectedGoodCount : int) -> bool {
    let mut goodCount : int = 0;
    let results = response.get_results();
    for i in range(0, results.size()) {
        let result = results[i];
        if result.get_score() > 1001.0 {
            goodCount += 1;
        } else {
            break;
        }
    }
    return goodCount == expectedGoodCount;
}
<|endoftext|>


<commit_before>// # Custom collector example
//
// This example shows how you can implement your own
// collector. As an example, we will compute a collector
// that computes the standard deviation of a given fast field.
//
// Of course, you can have a look at the tantivy's built-in collectors
// such as the `CountCollector` for more examples.

// ---
// Importing tantivy...
use std::marker::PhantomData;

use crate::collector::{Collector, SegmentCollector};
use crate::fastfield::FastFieldReader;
use crate::schema::Field;
use crate::{Score, SegmentReader, TantivyError};

/// The `FilterCollector` collector filters docs using a u64 fast field value and a predicate.
/// Only the documents for which the predicate returned "true" will be passed on to the next collector.
///
/// ```rust
/// use tantivy::collector::{TopDocs, FilterCollector};
/// use tantivy::query::QueryParser;
/// use tantivy::schema::{Schema, TEXT, INDEXED, FAST};
/// use tantivy::{doc, DocAddress, Index};
///
/// let mut schema_builder = Schema::builder();
/// let title = schema_builder.add_text_field("title", TEXT);
/// let price = schema_builder.add_u64_field("price", INDEXED | FAST);
/// let schema = schema_builder.build();
/// let index = Index::create_in_ram(schema);
///
/// let mut index_writer = index.writer_with_num_threads(1, 10_000_000).unwrap();
/// index_writer.add_document(doc!(title => "The Name of the Wind", price => 30_200u64));
/// index_writer.add_document(doc!(title => "The Diary of Muadib", price => 29_240u64));
/// index_writer.add_document(doc!(title => "A Dairy Cow", price => 21_240u64));
/// index_writer.add_document(doc!(title => "The Diary of a Young Girl", price => 20_120u64));
/// assert!(index_writer.commit().is_ok());
///
/// let reader = index.reader().unwrap();
/// let searcher = reader.searcher();
///
/// let query_parser = QueryParser::for_index(&index, vec![title]);
/// let query = query_parser.parse_query("diary").unwrap();
/// let no_filter_collector = FilterCollector::new(price, &|value| true, TopDocs::with_limit(2));
/// let top_docs = searcher.search(&query, &no_filter_collector).unwrap();
///
/// assert_eq!(top_docs.len(), 2);
/// assert_eq!(top_docs[0].1, DocAddress(0, 1));
/// assert_eq!(top_docs[1].1, DocAddress(0, 3));
///
/// let filter_all_collector = FilterCollector::new(price, &|value| false, TopDocs::with_limit(2));
/// let filtered_top_docs = searcher.search(&query, &filter_all_collector).unwrap();
///
/// assert_eq!(filtered_top_docs.len(), 0);
/// ```
pub struct FilterCollector<TCollector, TSegmentCollector> {
    field: Field,
    collector: TCollector,
    predicate: &'static (dyn Fn(u64) -> bool + Send + Sync),
    phantom: PhantomData<TSegmentCollector>,
}

impl<TCollector, TSegmentCollector> FilterCollector<TCollector, TSegmentCollector>
where
    TCollector: Collector<Child = TSegmentCollector> + Send + Sync,
    TSegmentCollector: SegmentCollector + Send + Sync,
{
    pub fn new(
        field: Field,
        predicate: &'static (dyn Fn(u64) -> bool + Send + Sync),
        collector: TCollector,
    ) -> FilterCollector<TCollector, TSegmentCollector> {
        FilterCollector {
            field,
            predicate,
            collector,
            phantom: PhantomData,
        }
    }
}

impl<TCollector, TSegmentCollector> Collector for FilterCollector<TCollector, TSegmentCollector>
where
    TSegmentCollector: SegmentCollector + Send + Sync,
    TCollector: Collector<Child = TSegmentCollector> + Send + Sync,
{
    // That's the type of our result.
    // Our standard deviation will be a float.
    type Fruit = TCollector::Fruit;

    type Child = FilterSegmentCollector<TSegmentCollector>;

    fn for_segment(
        &self,
        segment_local_id: u32,
        segment_reader: &SegmentReader,
    ) -> crate::Result<FilterSegmentCollector<TSegmentCollector>> {
        let fast_field_reader = segment_reader
            .fast_fields()
            .u64(self.field)
            .ok_or_else(|| {
                let field_name = segment_reader.schema().get_field_name(self.field);
                TantivyError::SchemaError(format!(
                    "Field {:?} is not a u64 fast field.",
                    field_name
                ))
            })?;
        let child_segment_collector = self.collector.for_segment(segment_local_id, segment_reader);
        match child_segment_collector {
            Ok(segment_collector) => Ok(FilterSegmentCollector::<TSegmentCollector> {
                fast_field_reader,
                segment_collector: segment_collector,
                predicate: self.predicate,
            }),
            Err(_) => Err(TantivyError::SystemError(
                "Could not open segment: ".to_owned(),
            )),
        }
    }

    fn requires_scoring(&self) -> bool {
        self.collector.requires_scoring()
    }

    fn merge_fruits(
        &self,
        segment_fruits: Vec<<TCollector::Child as SegmentCollector>::Fruit>,
    ) -> crate::Result<TCollector::Fruit> {
        self.collector.merge_fruits(segment_fruits)
    }
}

pub struct FilterSegmentCollector<TSegmentCollector> {
    fast_field_reader: FastFieldReader<u64>,
    segment_collector: TSegmentCollector,
    predicate: &'static (dyn Fn(u64) -> bool + Send + Sync),
}

impl<TSegmentCollector> SegmentCollector for FilterSegmentCollector<TSegmentCollector>
where
    TSegmentCollector: SegmentCollector + Send + Sync,
{
    type Fruit = TSegmentCollector::Fruit;

    fn collect(&mut self, doc: u32, score: Score) {
        let value = self.fast_field_reader.get(doc);
        if (self.predicate)(value) {
            self.segment_collector.collect(doc, score)
        }
    }

    fn harvest(self) -> <TSegmentCollector as SegmentCollector>::Fruit {
        self.segment_collector.harvest()
    }
}
<commit_msg>simplified FilterCollector#for_segment<commit_after>// # Custom collector example
//
// This example shows how you can implement your own
// collector. As an example, we will compute a collector
// that computes the standard deviation of a given fast field.
//
// Of course, you can have a look at the tantivy's built-in collectors
// such as the `CountCollector` for more examples.

// ---
// Importing tantivy...
use std::marker::PhantomData;

use crate::collector::{Collector, SegmentCollector};
use crate::fastfield::FastFieldReader;
use crate::schema::Field;
use crate::{Score, SegmentReader, TantivyError};

/// The `FilterCollector` collector filters docs using a u64 fast field value and a predicate.
/// Only the documents for which the predicate returned "true" will be passed on to the next collector.
///
/// ```rust
/// use tantivy::collector::{TopDocs, FilterCollector};
/// use tantivy::query::QueryParser;
/// use tantivy::schema::{Schema, TEXT, INDEXED, FAST};
/// use tantivy::{doc, DocAddress, Index};
///
/// let mut schema_builder = Schema::builder();
/// let title = schema_builder.add_text_field("title", TEXT);
/// let price = schema_builder.add_u64_field("price", INDEXED | FAST);
/// let schema = schema_builder.build();
/// let index = Index::create_in_ram(schema);
///
/// let mut index_writer = index.writer_with_num_threads(1, 10_000_000).unwrap();
/// index_writer.add_document(doc!(title => "The Name of the Wind", price => 30_200u64));
/// index_writer.add_document(doc!(title => "The Diary of Muadib", price => 29_240u64));
/// index_writer.add_document(doc!(title => "A Dairy Cow", price => 21_240u64));
/// index_writer.add_document(doc!(title => "The Diary of a Young Girl", price => 20_120u64));
/// assert!(index_writer.commit().is_ok());
///
/// let reader = index.reader().unwrap();
/// let searcher = reader.searcher();
///
/// let query_parser = QueryParser::for_index(&index, vec![title]);
/// let query = query_parser.parse_query("diary").unwrap();
/// let no_filter_collector = FilterCollector::new(price, &|value| true, TopDocs::with_limit(2));
/// let top_docs = searcher.search(&query, &no_filter_collector).unwrap();
///
/// assert_eq!(top_docs.len(), 2);
/// assert_eq!(top_docs[0].1, DocAddress(0, 1));
/// assert_eq!(top_docs[1].1, DocAddress(0, 3));
///
/// let filter_all_collector = FilterCollector::new(price, &|value| false, TopDocs::with_limit(2));
/// let filtered_top_docs = searcher.search(&query, &filter_all_collector).unwrap();
///
/// assert_eq!(filtered_top_docs.len(), 0);
/// ```
pub struct FilterCollector<TCollector, TSegmentCollector> {
    field: Field,
    collector: TCollector,
    predicate: &'static (dyn Fn(u64) -> bool + Send + Sync),
    phantom: PhantomData<TSegmentCollector>,
}

impl<TCollector, TSegmentCollector> FilterCollector<TCollector, TSegmentCollector>
where
    TCollector: Collector<Child = TSegmentCollector> + Send + Sync,
    TSegmentCollector: SegmentCollector + Send + Sync,
{
    pub fn new(
        field: Field,
        predicate: &'static (dyn Fn(u64) -> bool + Send + Sync),
        collector: TCollector,
    ) -> FilterCollector<TCollector, TSegmentCollector> {
        FilterCollector {
            field,
            predicate,
            collector,
            phantom: PhantomData,
        }
    }
}

impl<TCollector, TSegmentCollector> Collector for FilterCollector<TCollector, TSegmentCollector>
where
    TSegmentCollector: SegmentCollector + Send + Sync,
    TCollector: Collector<Child = TSegmentCollector> + Send + Sync,
{
    // That's the type of our result.
    // Our standard deviation will be a float.
    type Fruit = TCollector::Fruit;

    type Child = FilterSegmentCollector<TSegmentCollector>;

    fn for_segment(
        &self,
        segment_local_id: u32,
        segment_reader: &SegmentReader,
    ) -> crate::Result<FilterSegmentCollector<TSegmentCollector>> {
        let fast_field_reader = segment_reader
            .fast_fields()
            .u64(self.field)
            .ok_or_else(|| {
                let field_name = segment_reader.schema().get_field_name(self.field);
                TantivyError::SchemaError(format!(
                    "Field {:?} is not a u64 fast field.",
                    field_name
                ))
            })?;
        let segment_collector = self
            .collector
            .for_segment(segment_local_id, segment_reader)?;
        Ok(FilterSegmentCollector::<TSegmentCollector> {
            fast_field_reader,
            segment_collector: segment_collector,
            predicate: self.predicate,
        })
    }

    fn requires_scoring(&self) -> bool {
        self.collector.requires_scoring()
    }

    fn merge_fruits(
        &self,
        segment_fruits: Vec<<TCollector::Child as SegmentCollector>::Fruit>,
    ) -> crate::Result<TCollector::Fruit> {
        self.collector.merge_fruits(segment_fruits)
    }
}

pub struct FilterSegmentCollector<TSegmentCollector> {
    fast_field_reader: FastFieldReader<u64>,
    segment_collector: TSegmentCollector,
    predicate: &'static (dyn Fn(u64) -> bool + Send + Sync),
}

impl<TSegmentCollector> SegmentCollector for FilterSegmentCollector<TSegmentCollector>
where
    TSegmentCollector: SegmentCollector + Send + Sync,
{
    type Fruit = TSegmentCollector::Fruit;

    fn collect(&mut self, doc: u32, score: Score) {
        let value = self.fast_field_reader.get(doc);
        if (self.predicate)(value) {
            self.segment_collector.collect(doc, score)
        }
    }

    fn harvest(self) -> <TSegmentCollector as SegmentCollector>::Fruit {
        self.segment_collector.harvest()
    }
}
<|endoftext|>


<commit_before>//! Implements a pass that goes over the ssa and checks if the ssa is still valid.
//!
//! This is only for verification and to catch potential mistakes.
#![allow(unused_imports, unused_variables)]
use petgraph::EdgeDirection;
use petgraph::graph::{Graph, NodeIndex, EdgeIndex};

use std::collections::HashSet;

use super::cfg_traits::{CFG, CFGMod};
use super::ssa_traits::{SSA, SSAMod, ValueType};
use super::ssastorage::{EdgeData};
use super::ssastorage::NodeData;
use super::ssa_traits::NodeData as TNodeData;

use super::ssastorage::SSAStorage;
use middle::ir::{MArity, MOpcode};

pub trait Verify: SSA {
	fn verify_block(&self, i: &Self::ActionRef);
	fn verify_expr(&self, i: &Self::ValueRef);
}

pub trait VerifiedAdd: SSAMod {
	fn verified_add_op(&mut self, block: Self::ActionRef, opc: MOpcode, vt: ValueType, args: &[Self::ValueRef]) -> Self::ValueRef;
}

impl<T: Verify + SSAMod> VerifiedAdd for T {
	fn verified_add_op(&mut self, block: Self::ActionRef, opc: MOpcode, vt: ValueType, args: &[Self::ValueRef]) -> Self::ValueRef {
		assert!(opc.allowed_in_ssa());
		let op = self.add_op(block, opc, vt);
		for (i, arg) in args.iter().enumerate() {
			self.op_use(op, i as u8, *arg);
		}
		self.verify_expr(&op);
		op
	}
}

impl Verify for SSAStorage {
	fn verify_block(&self, block: &NodeIndex) {
		let edge_count = self.edge_count();
		let node_count = self.node_count();
		// Make sure that we have a valid node first.
		assert!(block.index() < node_count);
		let edges = self.edges_of(block);
		// Every BB can have a maximum of 2 Outgoing CFG Edges.
		assert!(edges.len() < 3);

		let mut edgecases = [false; 256];

		for edge in edges.iter() {
			match self.g[*edge] {
				EdgeData::Control(i) => {
					let target = self.target_of(edge);
					assert!(self.is_action(target));
					assert!(!edgecases[i as usize]);
					edgecases[i as usize] = true;
				},
				_ => ()
			}
		}

		for edge in edges.iter() {
			assert!(edge.index() < edge_count);
			match self.g[*edge] {
				EdgeData::Control(i) if i < 2 => {
					// Things to lookout for:
					//  * There must be a minimum of two edges.
					//  * There _must_ be a selector.
					//  * The jump targets must not be the same block.
					assert!(edges.len() == 2);
					let other_edge = match i {
						0 => self.true_edge_of(block),
						1 => self.false_edge_of(block),
						_ => unreachable!(),
					};
					let target_1 = self.target_of(edge);
					let target_2 = self.target_of(&other_edge);
					assert!(target_1 != target_2);
					// No need to test the next edge.
					break;
				},
				EdgeData::Control(2) => {
					// Things to lookout for:
					//  * There can be only one Unconditional Edge.
					//  * There can be no selector.
					//  * Make sure we have not introduced an unconditional jump
					//    which self-loops.
					let target_block = self.target_of(edge);
					assert!(edges.len() == 1);
					assert!(self.selector_of(block).is_none());
					assert!(target_block.index() < node_count);
					let valid_block = if let NodeData::BasicBlock(_) = self.g[target_block] {
						true
					} else {
						false
					};
					//assert!(valid_block);
					assert!(*block != target_block);
				},
				_ => panic!("Found something other than a control edge!"),
			}
		}

		if edges.len() > 2 {
			assert!(self.selector_of(block).is_none());
		} else if edges.len() > 1{
			assert!(self.selector_of(block).is_some());
		}

		// Make sure that this block is reachable.
		let incoming = self.incoming_edges(block);
		assert!((incoming.len() > 0) || *block == self.start_node());
	}

	fn verify_expr(&self, i: &NodeIndex) {
		let node_count = self.node_count();
		// Make sure we have a valid node first.
		assert!(i.index() < node_count);
		let node_data = &self.g[*i];

		match *node_data {
			NodeData::Op(opcode, ValueType::Integer { width: w }) => {
				let operands = self.get_operands(i);
				let op_len = operands.len();
				let extract = |x: TNodeData| -> u16 {
					match x.vt {
						ValueType::Integer { width: w } => w,
						/*_ => {
							let panic_str = format!("Found {:?}, expected ValueType::Integer", x);
							panic!(panic_str);
						}*/
					}
				};

				let n = match opcode.arity() {
					MArity::Zero => 0,
					MArity::Unary => 1,
					MArity::Binary => 2,
					_ => unimplemented!(),
				};

				{
					let panic_str = format!("Expression {:?} has {} operands", opcode, op_len);
					assert!(op_len == n, panic_str);
				}

				if n == 0 { return; }
				match opcode {
					MOpcode::OpNarrow(w0) => {
						let w0 = self.get_node_data(&operands[0])
						             .map(&extract)
						             .unwrap();
						assert!(w0 > w);
					},
				    MOpcode::OpWiden(w0) =>  {
						let w0 = self.get_node_data(&operands[0])
						             .map(&extract)
						             .unwrap();
						assert!(w0 < w);
					},
					MOpcode::OpCmp | MOpcode::OpGt | MOpcode::OpLt | MOpcode::OpLteq | MOpcode::OpGteq => {
						let panic_str = format!("Expected width to be 1, found: {}", w);
						assert!(w == 1, panic_str);
					},
					_ => {
						let w0 = self.get_node_data(&operands[0])
						             .map(&extract)
						             .unwrap();
						assert!(w0 == w, format!("{:?} == {:?}; {:?}", w0, w, opcode));
						for op in operands.iter() {
							let w1 = self.get_node_data(op)
							             .map(&extract)
						                 .unwrap();
							let panic_str = format!("{:?}: Expected size to be: {}, found: {}", opcode, w, w1);
							assert!(w1 == w, panic_str);
						}
					},
				}
			},
			_ => panic!("Found something other than an expression!"),
		}
	}
}

pub fn verify<T>(ssa: &T) where T: Verify {
	let blocks = ssa.blocks();
	for block in blocks.iter() {
		// assert the qualities of the block first.
		ssa.verify_block(block);
		// Iterate through each node in the block and assert their properties.
		let exprs = ssa.exprs_in(block);
		for expr in exprs.iter() {
			ssa.verify_expr(expr);
		}
	}
}
<commit_msg>verifier.rs: Replace panic!() by return Err()<commit_after>//! Implements a pass that goes over the ssa and checks if the ssa is still valid.
//!
//! This is only for verification and to catch potential mistakes.
#![allow(unused_imports, unused_variables)]
use petgraph::EdgeDirection;
use petgraph::graph::{Graph, NodeIndex, EdgeIndex};

use std::collections::HashSet;

use super::cfg_traits::{CFG, CFGMod};
use super::ssa_traits::{SSA, SSAMod, ValueType};
use super::ssastorage::{EdgeData};
use super::ssastorage::NodeData;
use super::ssa_traits::NodeData as TNodeData;

use super::ssastorage::SSAStorage;
use middle::ir::{MArity, MOpcode};

pub trait Verify: SSA {
	fn verify_block(&self, i: &Self::ActionRef) -> Result<(), SSAFault<Self>>;
	fn verify_expr(&self, i: &Self::ValueRef) -> Result<(), SSAFault<Self>>;
}

pub trait VerifiedAdd: SSAMod {
	fn verified_add_op(&mut self, block: Self::ActionRef, opc: MOpcode, vt: ValueType, args: &[Self::ValueRef]) -> Self::ValueRef;
}

impl<T: Verify + SSAMod> VerifiedAdd for T {
	fn verified_add_op(&mut self, block: Self::ActionRef, opc: MOpcode, vt: ValueType, args: &[Self::ValueRef]) -> Self::ValueRef {
		assert!(opc.allowed_in_ssa());
		let op = self.add_op(block, opc, vt);
		for (i, arg) in args.iter().enumerate() {
			self.op_use(op, i as u8, *arg);
		}
		self.verify_expr(&op);
		op
	}
}

#[derive(Debug)]
pub enum AnyRef<T: SSA> {
	Value(T::ValueRef),
	Action(T::ActionRef),
	None
}

#[derive(Debug)]
pub struct SSAFault<T: SSA> {
	pub node: AnyRef<T>,
	pub message: Option<String>,
}

macro_rules! check {
	($ri: expr, $cond:expr, $message:expr) => (
		if !$cond { return Err(SSAFault{node: $ri, message: Some($message.to_owned())}) }
	);
	($ri: expr, $cond:expr) => (
		if !$cond { return Err(SSAFault{node: $ri, message: None}) }
	)
}

impl Verify for SSAStorage {
	fn verify_block(&self, block: &NodeIndex) -> Result<(), SSAFault<Self>> {
		let ri = AnyRef::Action(*block);

		let edge_count = self.edge_count();
		let node_count = self.node_count();
		// Make sure that we have a valid node first.
		assert!(block.index() < node_count);
		let edges = self.edges_of(block);
		// Every BB can have a maximum of 2 Outgoing CFG Edges.
		check!(ri, edges.len() < 3);

		let mut edgecases = [false; 256];

		for edge in edges.iter() {
			match self.g[*edge] {
				EdgeData::Control(i) => {
					let target = self.target_of(edge);
					check!(ri, self.is_action(target));
					check!(ri, !edgecases[i as usize]);
					edgecases[i as usize] = true;
				},
				_ => ()
			}
		}

		for edge in edges.iter() {
			assert!(edge.index() < edge_count);
			match self.g[*edge] {
				EdgeData::Control(i) if i < 2 => {
					// Things to lookout for:
					//  * There must be a minimum of two edges.
					//  * There _must_ be a selector.
					//  * The jump targets must not be the same block.
					check!(ri, edges.len() == 2);
					let other_edge = match i {
						0 => self.true_edge_of(block),
						1 => self.false_edge_of(block),
						_ => unreachable!(),
					};
					let target_1 = self.target_of(edge);
					let target_2 = self.target_of(&other_edge);
					check!(ri, target_1 != target_2);
					// No need to test the next edge.
					break;
				},
				EdgeData::Control(2) => {
					// Things to lookout for:
					//  * There can be only one Unconditional Edge.
					//  * There can be no selector.
					//  * Make sure we have not introduced an unconditional jump
					//    which self-loops.
					let target_block = self.target_of(edge);
					check!(ri, edges.len() == 1);
					check!(ri, self.selector_of(block).is_none());
					check!(ri, target_block.index() < node_count);
					let valid_block = if let NodeData::BasicBlock(_) = self.g[target_block] {
						true
					} else {
						false
					};
					//check!(ri, valid_block);
					check!(ri, *block != target_block);
				},
				_ => panic!("Found something other than a control edge!"),
			}
		}

		if edges.len() > 2 {
			check!(ri, self.selector_of(block).is_none());
		} else if edges.len() > 1{
			check!(ri, self.selector_of(block).is_some());
		}

		// Make sure that this block is reachable.
		let incoming = self.incoming_edges(block);
		check!(ri, (incoming.len() > 0) || *block == self.start_node());
		Ok(())
	}

	fn verify_expr(&self, i: &NodeIndex) -> Result<(), SSAFault<Self>> {
		let ri = AnyRef::Value(*i);

		let node_count = self.node_count();
		// Make sure we have a valid node first.
		assert!(i.index() < node_count);
		let node_data = &self.g[*i];

		match *node_data {
			NodeData::Op(opcode, ValueType::Integer { width: w }) => {
				let operands = self.get_operands(i);
				let op_len = operands.len();
				let extract = |x: TNodeData| -> u16 {
					match x.vt {
						ValueType::Integer { width: w } => w,
						/*_ => {
							let panic_str = format!("Found {:?}, expected ValueType::Integer", x);
							panic!(panic_str);
						}*/
					}
				};

				let n = match opcode.arity() {
					MArity::Zero => 0,
					MArity::Unary => 1,
					MArity::Binary => 2,
					_ => unimplemented!(),
				};

				{
					let panic_str = format!("Expression {:?} has {} operands", opcode, op_len);
					check!(ri, op_len == n, panic_str);
				}

				if n == 0 { return Ok(()) }
				match opcode {
					MOpcode::OpNarrow(w0) => {
						let w0 = self.get_node_data(&operands[0])
						             .map(&extract)
						             .unwrap();
						check!(ri, w0 > w);
					},
				    MOpcode::OpWiden(w0) =>  {
						let w0 = self.get_node_data(&operands[0])
						             .map(&extract)
						             .unwrap();
						check!(ri, w0 < w);
					},
					MOpcode::OpCmp | MOpcode::OpGt | MOpcode::OpLt | MOpcode::OpLteq | MOpcode::OpGteq => {
						let panic_str = format!("Expected width to be 1, found: {}", w);
						check!(ri, w == 1, panic_str);
					},
					_ => {
						let w0 = self.get_node_data(&operands[0])
						             .map(&extract)
						             .unwrap();
						check!(ri, w0 == w, format!("{:?} == {:?}; {:?}", w0, w, opcode));
						for op in operands.iter() {
							let w1 = self.get_node_data(op)
							             .map(&extract)
						                 .unwrap();
							let panic_str = format!("{:?}: Expected size to be: {}, found: {}", opcode, w, w1);
							check!(ri, w1 == w, panic_str);
						}
					},
				}
			},
			_ => check!(ri, false, "Found something other than an expression!"),
		}
		Ok(())
	}
}

pub fn verify<T>(ssa: &T) -> Result<(), SSAFault<T>> where T: Verify {
	let blocks = ssa.blocks();
	for block in blocks.iter() {
		// assert the qualities of the block first.
		ssa.verify_block(block).ok().unwrap();
		// Iterate through each node in the block and assert their properties.
		let exprs = ssa.exprs_in(block);
		for expr in exprs.iter() {
			try!(ssa.verify_expr(expr));
		}
	}
	Ok(())
}
<|endoftext|>