<commit_before>//
//   Copyright 2016 Andrew Hunter
//
//   Licensed under the Apache License, Version 2.0 (the "License");
//   you may not use this file except in compliance with the License.
//   You may obtain a copy of the License at
//
//       http://www.apache.org/licenses/LICENSE-2.0
//
//   Unless required by applicable law or agreed to in writing, software
//   distributed under the License is distributed on an "AS IS" BASIS,
//   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
//   See the License for the specific language governing permissions and
//   limitations under the License.
//

use std::cmp::Ordering;

use super::symbol_range::*;
use super::countable::*;

///
/// A symbol map maps from one set of symbol ranges to another
///
pub struct SymbolMap<Symbol: PartialOrd+Clone+Countable> {
    // Ranges in this symbol map
    ranges: Vec<SymbolRange<Symbol>>,
}

impl<Symbol: PartialOrd+Clone+Countable> SymbolMap<Symbol> {
    ///
    /// Creates a new symbol map
    ///
    pub fn new() -> SymbolMap<Symbol> {
        SymbolMap { ranges: vec![] }
    }

    ///
    /// Orders two symbols (makes unordered symbols equal)
    ///
    #[inline]
    fn order_symbols(a: &Symbol, b: &Symbol) -> Ordering {
        if let Some(order) = a.partial_cmp(b) {
            order
        } else {
            Ordering::Equal
        }
    }

    ///
    /// Orders two symbol ranges
    ///
    #[inline]
    fn order_ranges(a: &SymbolRange<Symbol>, b: &SymbolRange<Symbol>) -> Ordering {
        let ordering = SymbolMap::order_symbols(&a.lowest, &b.lowest);

        if ordering == Ordering::Equal {
            SymbolMap::order_symbols(&a.highest, &b.highest)
        } else {
            ordering
        }
    }

    ///
    /// Adds a range to those that are known about by this object
    ///
    pub fn add_range(&mut self, range: &SymbolRange<Symbol>) {
        let existing = self.ranges.binary_search_by(|test_range| { SymbolMap::order_ranges(test_range, range) });

        // Insert the range if it is not already in the map
        if let Err(insertion_pos) = existing {
            self.ranges.insert(insertion_pos, range.clone());
        }
    }

    ///
    /// Finds the ranges in this map that overlap the target ranges
    ///
    pub fn find_overlapping_ranges(&self, range: &SymbolRange<Symbol>) -> Vec<&SymbolRange<Symbol>> {
        let mut result = vec![];

        // Find the first range that matches (or the insertion position, which should be the first range wit a lowest value higher than the target range)
        let existing = self.ranges.binary_search_by(|test_range| { SymbolMap::order_ranges(test_range, range) });

        // Start returning values from here
        let mut pos = match existing {
            Ok(found_position) => found_position,
            Err(insert_position) => insert_position
        };

        // Move backwards if the previous position overlaps this one
        if pos > 0 && self.ranges[pos-1].highest >= range.lowest {
            pos -= 1;
        }

        // TODO: can we construct a set of ranges such that one is missed here? Think maybe we can
        while pos < self.ranges.len() && self.ranges[pos].lowest <= range.highest {
            result.push(&self.ranges[pos]);
            pos += 1;
        }

        result
    }

    ///
    /// Creates a non-overlapping range from an overlapping one
    ///
    pub fn to_non_overlapping_map(&self) -> SymbolMap<Symbol> {
        // Create a vector of all the range symbols
        let mut range_symbols: Vec<Symbol> = self.ranges.iter()
            .map(|r| r.lowest.clone())
            .chain(self.ranges.iter().map(|r| r.highest.clone()))
            .collect();

        // Sort and dedupe (we'll get pairs of ranges)
        range_symbols.sort_by(SymbolMap::order_symbols);
        range_symbols.dedup();

        // Generate a new symbol map with these ranges
        // They'll overlap with the last value, which should be OK if following the rules for adjacent ranges in symbol_range.rs
        let mut result = vec![];
        for index in 0..range_symbols.len()-2 {
            result.push(SymbolRange::new(range_symbols[index].clone(), range_symbols[index+1].prev()));
        }

        if range_symbols.len() > 1 {
            // Last item is always inclusive
            result.push(SymbolRange::new(range_symbols[range_symbols.len()-2].clone(), range_symbols[range_symbols.len()-1].clone()));
        }

        // We already sorted everything, so bypass the usual 'add' method (which sorts as it goes)
        SymbolMap { ranges: result }
    }
}

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

    #[test]
    fn can_lookup_overlapping_ranges() {
        let mut map = SymbolMap::new();

        map.add_range(&SymbolRange::new(0, 4));
        map.add_range(&SymbolRange::new(2, 5));
        map.add_range(&SymbolRange::new(3, 6));

        let bottom = map.find_overlapping_ranges(&SymbolRange::new(0, 1));
        let all    = map.find_overlapping_ranges(&SymbolRange::new(1, 3));
        let top    = map.find_overlapping_ranges(&SymbolRange::new(6, 6));

        assert!(bottom == vec![&SymbolRange::new(0, 4)]);
        assert!(all == vec![&SymbolRange::new(0, 4), &SymbolRange::new(2, 5), &SymbolRange::new(3, 6)]);
        assert!(top == vec![&SymbolRange::new(3, 6)]);
    }

    #[test]
    fn can_lookup_mid_range() {
        let mut map = SymbolMap::new();

        map.add_range(&SymbolRange::new(0, 4));
        map.add_range(&SymbolRange::new(5, 10));
        map.add_range(&SymbolRange::new(11, 15));

        let mid = map.find_overlapping_ranges(&SymbolRange::new(1, 3));

        assert!(mid == vec![&SymbolRange::new(0, 4)]);
    }

    #[test]
    fn works_with_duplicate_lower_values() {
        let mut map = SymbolMap::new();

        map.add_range(&SymbolRange::new(0, 2));
        map.add_range(&SymbolRange::new(0, 3));

        let all    = map.find_overlapping_ranges(&SymbolRange::new(0, 1));

        assert!(all == vec![&SymbolRange::new(0, 2), &SymbolRange::new(0, 3)]);
    }

    #[test]
    fn can_get_non_overlapping_map() {
        let mut map = SymbolMap::new();

        map.add_range(&SymbolRange::new(0, 4));
        map.add_range(&SymbolRange::new(2, 5));
        map.add_range(&SymbolRange::new(3, 6));

        let non_overlapping = map.to_non_overlapping_map();

        let all = non_overlapping.find_overlapping_ranges(&SymbolRange::new(0, 6));

        assert!(all == vec![&SymbolRange::new(0, 1), &SymbolRange::new(2, 2), &SymbolRange::new(3, 3), &SymbolRange::new(4, 4), &SymbolRange::new(5, 6)]);
    }

    #[test]
    fn can_get_non_overlapping_map_with_single_symbols() {
        let mut map = SymbolMap::new();

        map.add_range(&SymbolRange::new(0, 5));
        map.add_range(&SymbolRange::new(2, 2));
        map.add_range(&SymbolRange::new(3, 6));

        let non_overlapping = map.to_non_overlapping_map();

        let all = non_overlapping.find_overlapping_ranges(&SymbolRange::new(0, 6));

        assert!(all == vec![&SymbolRange::new(0, 1), &SymbolRange::new(2, 2), &SymbolRange::new(3, 4), &SymbolRange::new(5, 6)]);
    }

    #[test]
    fn generate_correctly_for_single_overlap() {
        let mut map = SymbolMap::new();

        // Here the symbol '5' is in both ranges, so we should generate it as a seperate range in the non-overlapping version
        map.add_range(&SymbolRange::new(0, 5));
        map.add_range(&SymbolRange::new(5, 10));

        let non_overlapping = map.to_non_overlapping_map();

        let all = non_overlapping.find_overlapping_ranges(&SymbolRange::new(0, 10));

        assert!(all == vec![&SymbolRange::new(0, 4), &SymbolRange::new(5,5), &SymbolRange::new(6, 10)]);
    }

    #[test]
    fn can_get_non_overlapping_map_with_single_symbols_at_start() {
        let mut map = SymbolMap::new();

        map.add_range(&SymbolRange::new(0, 0));
        map.add_range(&SymbolRange::new(0, 1));

        let non_overlapping = map.to_non_overlapping_map();

        let all = non_overlapping.find_overlapping_ranges(&SymbolRange::new(0, 6));

        assert!(all == vec![&SymbolRange::new(0, 0), &SymbolRange::new(1, 1)]);
    }

    #[test]
    fn can_get_non_overlapping_map_with_single_symbols_at_start_and_gap() {
        let mut map = SymbolMap::new();

        map.add_range(&SymbolRange::new(0, 0));
        map.add_range(&SymbolRange::new(0, 1));
        map.add_range(&SymbolRange::new(3, 6));

        let non_overlapping = map.to_non_overlapping_map();

        let all = non_overlapping.find_overlapping_ranges(&SymbolRange::new(0, 6));

        assert!(all == vec![&SymbolRange::new(0, 0), &SymbolRange::new(1, 1), &SymbolRange::new(2, 2), &SymbolRange::new(3, 6)]);
    }
}
<commit_msg>dedupe lowest and highest values seperately when building the non-overlapping map<commit_after>//
//   Copyright 2016 Andrew Hunter
//
//   Licensed under the Apache License, Version 2.0 (the "License");
//   you may not use this file except in compliance with the License.
//   You may obtain a copy of the License at
//
//       http://www.apache.org/licenses/LICENSE-2.0
//
//   Unless required by applicable law or agreed to in writing, software
//   distributed under the License is distributed on an "AS IS" BASIS,
//   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
//   See the License for the specific language governing permissions and
//   limitations under the License.
//

use std::cmp::Ordering;

use super::symbol_range::*;
use super::countable::*;

///
/// A symbol map maps from one set of symbol ranges to another
///
pub struct SymbolMap<Symbol: PartialOrd+Clone+Countable> {
    // Ranges in this symbol map
    ranges: Vec<SymbolRange<Symbol>>,
}

impl<Symbol: PartialOrd+Clone+Countable> SymbolMap<Symbol> {
    ///
    /// Creates a new symbol map
    ///
    pub fn new() -> SymbolMap<Symbol> {
        SymbolMap { ranges: vec![] }
    }

    ///
    /// Orders two symbols (makes unordered symbols equal)
    ///
    #[inline]
    fn order_symbols(a: &Symbol, b: &Symbol) -> Ordering {
        if let Some(order) = a.partial_cmp(b) {
            order
        } else {
            Ordering::Equal
        }
    }

    ///
    /// Orders two symbol ranges
    ///
    #[inline]
    fn order_ranges(a: &SymbolRange<Symbol>, b: &SymbolRange<Symbol>) -> Ordering {
        let ordering = SymbolMap::order_symbols(&a.lowest, &b.lowest);

        if ordering == Ordering::Equal {
            SymbolMap::order_symbols(&a.highest, &b.highest)
        } else {
            ordering
        }
    }

    ///
    /// Adds a range to those that are known about by this object
    ///
    pub fn add_range(&mut self, range: &SymbolRange<Symbol>) {
        let existing = self.ranges.binary_search_by(|test_range| { SymbolMap::order_ranges(test_range, range) });

        // Insert the range if it is not already in the map
        if let Err(insertion_pos) = existing {
            self.ranges.insert(insertion_pos, range.clone());
        }
    }

    ///
    /// Finds the ranges in this map that overlap the target ranges
    ///
    pub fn find_overlapping_ranges(&self, range: &SymbolRange<Symbol>) -> Vec<&SymbolRange<Symbol>> {
        let mut result = vec![];

        // Find the first range that matches (or the insertion position, which should be the first range wit a lowest value higher than the target range)
        let existing = self.ranges.binary_search_by(|test_range| { SymbolMap::order_ranges(test_range, range) });

        // Start returning values from here
        let mut pos = match existing {
            Ok(found_position) => found_position,
            Err(insert_position) => insert_position
        };

        // Move backwards if the previous position overlaps this one
        if pos > 0 && self.ranges[pos-1].highest >= range.lowest {
            pos -= 1;
        }

        // TODO: can we construct a set of ranges such that one is missed here? Think maybe we can
        while pos < self.ranges.len() && self.ranges[pos].lowest <= range.highest {
            result.push(&self.ranges[pos]);
            pos += 1;
        }

        result
    }

    ///
    /// Creates a non-overlapping range from an overlapping one
    ///
    pub fn to_non_overlapping_map(&self) -> SymbolMap<Symbol> {
        // Create a vector of all the range symbols
        let mut lowest:  Vec<Symbol> = self.ranges.iter().map(|r| r.lowest.clone()).collect();
        let mut highest: Vec<Symbol> = self.ranges.iter().map(|r| r.highest.clone()).collect();

        // Dedupe the lowest and highest symbols seperately
        lowest.sort_by(SymbolMap::order_symbols);
        lowest.dedup();

        highest.sort_by(SymbolMap::order_symbols);
        highest.dedup();

        // Combine into the set of ranges (each pair representing a range in the result)
        let mut range_symbols: Vec<Symbol> = lowest.into_iter().chain(highest.into_iter()).collect();
        range_symbols.sort_by(SymbolMap::order_symbols);

        // Generate a new symbol map with these ranges
        let mut result = vec![];
        for index in 0..range_symbols.len()-2 {
            result.push(SymbolRange::new(range_symbols[index].clone(), range_symbols[index+1].prev()));
        }

        if range_symbols.len() > 1 {
            // Last item is always inclusive
            result.push(SymbolRange::new(range_symbols[range_symbols.len()-2].clone(), range_symbols[range_symbols.len()-1].clone()));
        }

        // We already sorted everything, so bypass the usual 'add' method (which sorts as it goes)
        SymbolMap { ranges: result }
    }
}

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

    #[test]
    fn can_lookup_overlapping_ranges() {
        let mut map = SymbolMap::new();

        map.add_range(&SymbolRange::new(0, 4));
        map.add_range(&SymbolRange::new(2, 5));
        map.add_range(&SymbolRange::new(3, 6));

        let bottom = map.find_overlapping_ranges(&SymbolRange::new(0, 1));
        let all    = map.find_overlapping_ranges(&SymbolRange::new(1, 3));
        let top    = map.find_overlapping_ranges(&SymbolRange::new(6, 6));

        assert!(bottom == vec![&SymbolRange::new(0, 4)]);
        assert!(all == vec![&SymbolRange::new(0, 4), &SymbolRange::new(2, 5), &SymbolRange::new(3, 6)]);
        assert!(top == vec![&SymbolRange::new(3, 6)]);
    }

    #[test]
    fn can_lookup_mid_range() {
        let mut map = SymbolMap::new();

        map.add_range(&SymbolRange::new(0, 4));
        map.add_range(&SymbolRange::new(5, 10));
        map.add_range(&SymbolRange::new(11, 15));

        let mid = map.find_overlapping_ranges(&SymbolRange::new(1, 3));

        assert!(mid == vec![&SymbolRange::new(0, 4)]);
    }

    #[test]
    fn works_with_duplicate_lower_values() {
        let mut map = SymbolMap::new();

        map.add_range(&SymbolRange::new(0, 2));
        map.add_range(&SymbolRange::new(0, 3));

        let all    = map.find_overlapping_ranges(&SymbolRange::new(0, 1));

        assert!(all == vec![&SymbolRange::new(0, 2), &SymbolRange::new(0, 3)]);
    }

    #[test]
    fn can_get_non_overlapping_map() {
        let mut map = SymbolMap::new();

        map.add_range(&SymbolRange::new(0, 4));
        map.add_range(&SymbolRange::new(2, 5));
        map.add_range(&SymbolRange::new(3, 6));

        let non_overlapping = map.to_non_overlapping_map();

        let all = non_overlapping.find_overlapping_ranges(&SymbolRange::new(0, 6));

        assert!(all == vec![&SymbolRange::new(0, 1), &SymbolRange::new(2, 2), &SymbolRange::new(3, 3), &SymbolRange::new(4, 4), &SymbolRange::new(5, 6)]);
    }

    #[test]
    fn can_get_non_overlapping_map_with_single_symbols() {
        let mut map = SymbolMap::new();

        map.add_range(&SymbolRange::new(0, 5));
        map.add_range(&SymbolRange::new(2, 2));
        map.add_range(&SymbolRange::new(3, 6));

        let non_overlapping = map.to_non_overlapping_map();

        let all = non_overlapping.find_overlapping_ranges(&SymbolRange::new(0, 6));

        assert!(all == vec![&SymbolRange::new(0, 1), &SymbolRange::new(2, 2), &SymbolRange::new(3, 4), &SymbolRange::new(5, 6)]);
    }

    #[test]
    fn generate_correctly_for_single_overlap() {
        let mut map = SymbolMap::new();

        // Here the symbol '5' is in both ranges, so we should generate it as a seperate range in the non-overlapping version
        map.add_range(&SymbolRange::new(0, 5));
        map.add_range(&SymbolRange::new(5, 10));

        let non_overlapping = map.to_non_overlapping_map();

        let all = non_overlapping.find_overlapping_ranges(&SymbolRange::new(0, 10));
        println!("{:?}", all);

        assert!(all == vec![&SymbolRange::new(0, 4), &SymbolRange::new(5,5), &SymbolRange::new(6, 10)]);
    }

    #[test]
    fn can_get_non_overlapping_map_with_single_symbols_at_start() {
        let mut map = SymbolMap::new();

        map.add_range(&SymbolRange::new(0, 0));
        map.add_range(&SymbolRange::new(0, 1));

        let non_overlapping = map.to_non_overlapping_map();

        let all = non_overlapping.find_overlapping_ranges(&SymbolRange::new(0, 6));

        assert!(all == vec![&SymbolRange::new(0, 0), &SymbolRange::new(1, 1)]);
    }

    #[test]
    fn can_get_non_overlapping_map_with_single_symbols_at_start_and_gap() {
        let mut map = SymbolMap::new();

        map.add_range(&SymbolRange::new(0, 0));
        map.add_range(&SymbolRange::new(0, 1));
        map.add_range(&SymbolRange::new(3, 6));

        let non_overlapping = map.to_non_overlapping_map();

        let all = non_overlapping.find_overlapping_ranges(&SymbolRange::new(0, 6));

        assert!(all == vec![&SymbolRange::new(0, 0), &SymbolRange::new(1, 1), &SymbolRange::new(2, 2), &SymbolRange::new(3, 6)]);
    }
}
<|endoftext|>


<commit_before>#[macro_use]
extern crate clap;
extern crate names;

use names::{Generator, Name};

fn main() {
    let (naming, amount) = {
        let app = clap_app!(names =>
                (version: &crate_version!()[..])
                (author: "\nAuthor: Fletcher Nichol <fnichol@nichol.ca>\n")
                (about: "A random name generator with results like `delirious-pail'.")
                (@setting ColoredHelp)
                (@arg amount: "Number of names to generate (default: 1)")
                (@arg number: -n --number "Adds a random number to the name(s)")
        );
        let matches = app.get_matches();
        let amount = value_t!(matches.value_of("amount"), usize).unwrap_or(1);
        let naming: Name = if matches.is_present("number") {
            Name::Numbered
        } else {
            Default::default()
        };
        (naming, amount)
    };

    let mut generator = Generator::with_naming(naming);
    for _ in 0..amount {
        println!("{}", generator.next().unwrap());
    }
}
<commit_msg>[cli] Update clap code to use `app_from_crate!` macro.<commit_after>#[macro_use]
extern crate clap;
extern crate names;

use clap::{AppSettings, Arg};

use names::{Generator, Name};

fn main() {
    let (naming, amount) = parse_cli_args();
    let mut generator = Generator::with_naming(naming);
    for _ in 0..amount {
        println!("{}", generator.next().unwrap());
    }
}

fn parse_cli_args() -> (Name, usize) {
    const FLAG_NUMBER: &str = "number";
    const ARG_AMOUNT: &str = "amount";

    let app = app_from_crate!()
        .name("names")
        .setting(AppSettings::ColoredHelp)
        .arg(
            Arg::with_name(FLAG_NUMBER)
                .short("n")
                .long(FLAG_NUMBER)
                .help("Adds a random number to the name(s)"),
        ).arg(
            Arg::with_name(ARG_AMOUNT)
                .help("Number of names to generate")
                .default_value("1"),
        );

    let matches = app.get_matches();
    let amount = value_t_or_exit!(matches.value_of(ARG_AMOUNT), usize);
    let naming: Name = if matches.is_present(FLAG_NUMBER) {
        Name::Numbered
    } else {
        Default::default()
    };

    (naming, amount)
}
<|endoftext|>


<commit_before>extern crate hyper;

use hyper::server::{Server, Request, Response};
use hyper::uri::RequestUri;
use hyper::header::ContentType;
use hyper::header;

const HELLO_WORLD: &'static [u8; 13] = b"Hello, World!";

fn main() {
    Server::http("0.0.0.0:8080").unwrap().handle(handler).unwrap();
}

fn handler(req: Request, mut res: Response) {
    match (req.method, req.uri) {
        (hyper::Get, RequestUri::AbsolutePath(ref path)) if path == "/plaintext" => {
            res.headers_mut().set(ContentType::plaintext());
            res.headers_mut().set(header::Server("Hyper".to_owned()));

            res.send(HELLO_WORLD).unwrap();
        }
        _ => (),
    }
}
<commit_msg>Fix hyper warning wrt content type<commit_after>extern crate hyper;

use hyper::server::{Server, Request, Response};
use hyper::uri::RequestUri;
use hyper::header::ContentType;
use hyper::header;

const HELLO_WORLD: &'static [u8; 13] = b"Hello, World!";

fn main() {
    Server::http("0.0.0.0:8080").unwrap().handle(handler).unwrap();
}

fn handler(req: Request, mut res: Response) {
    match (req.method, req.uri) {
        (hyper::Get, RequestUri::AbsolutePath(ref path)) if path == "/plaintext" => {
            res.headers_mut().set(ContentType("text/plain".parse().unwrap()));
            res.headers_mut().set(header::Server("Hyper".to_owned()));

            res.send(HELLO_WORLD).unwrap();
        }
        _ => (),
    }
}
<|endoftext|>


<commit_before>extern crate iron;
extern crate router;
extern crate rustc_serialize;
extern crate hyper;
extern crate libc;
extern crate time;

extern crate imageflow_core;
use imageflow_core::boring::*;
use imageflow_core::ffi::*;

use hyper::Client;
use iron::mime::Mime;
use iron::prelude::*;
use iron::status;
use router::Router;
use std::io::Read;
use time::precise_time_ns;

// This Rust server was built one saturday evening to exercise various
// bits of the stack. It's not safe (nor safer than a C equivalent), and
// we're not using Rust idomatically or correctly. Nothing is re-entrant,
// and errors panic the process. It's one build to throw away; a learning experiment.
//
// Run with cargo run --bin imageflow-server
//
// Open in your browser: http://localhost:3000/proto1/scale_unsplash_jpeg/1200/1200/photo-1436891678271-9c672565d8f6
//

fn create_io(c: *mut Context, source_bytes: *const u8, count: usize) -> Vec<IoResource> {
    unsafe {
        let input_io = flow_io_create_from_memory(c,
                                                  IoMode::read_seekable,
                                                  source_bytes,
                                                  count as libc::size_t,
                                                  c as *mut libc::c_void,
                                                  0 as *mut libc::c_void);

        if input_io.is_null() {
            flow_context_print_and_exit_if_err(c);
            // bad, we shouldn't exit the process
        }
        let output_io = flow_io_create_for_output_buffer(c, c as *mut libc::c_void);

        if output_io.is_null() {
            flow_context_print_and_exit_if_err(c);
        }

        vec![IoResource {
                 io: input_io,
                 direction: IoDirection::In,
             },
             IoResource {
                 io: output_io,
                 direction: IoDirection::Out,
             }]
    }
}

fn collect_result(c: *mut Context, job: *mut Job) -> Result<Vec<u8>, String> {
    unsafe {
        let output_io = flow_job_get_io(c, job, 1);
        if output_io.is_null() {
            flow_context_print_and_exit_if_err(c);
        }

        let mut buf: *mut u8 = std::mem::uninitialized(); //This is okay, it's write-only
        let mut buf_length: libc::size_t = 0;
        // Returns false if the flow_io struct is disposed or not an output buffer type (or for any other error)

        if !flow_io_get_output_buffer(c, output_io, &mut buf, &mut buf_length) {
            flow_context_print_and_exit_if_err(c);
        }

        Ok(std::slice::from_raw_parts(buf as *const u8, buf_length as usize).to_vec())
    }
}

fn get_jpeg_bytes(source: &str, w: Option<u32>, h: Option<u32>) -> Vec<u8> {

    let start = precise_time_ns();

    let client = Client::new();
    let mut res = client.get(source).send().unwrap();
    assert_eq!(res.status, hyper::Ok);

    let mut source_bytes = Vec::new();
    let count = res.read_to_end(&mut source_bytes).unwrap(); //bad

    let downloaded = precise_time_ns();

    let commands = BoringCommands {
        fit: ConstraintMode::Max,
        w: w.unwrap_or(0) as i32,
        h: h.unwrap_or(0) as i32,
        jpeg_quality: 90,
        precise_scaling_ratio: 2.1f32,
        luma_correct: true,
        sharpen: 0f32,
        format: ImageFormat::Jpeg,
        down_filter: Filter::Robidoux,
        up_filter: Filter::Ginseng,
    };

    let source_ptr = source_bytes.as_mut_ptr();

    let bytes = imageflow_core::boring::process_image(commands,
                                                        |c| create_io(c, source_ptr, count),
                                                        collect_result);

    std::mem::forget(source_bytes);

    let fetch = downloaded - start;
    let delta = precise_time_ns() - downloaded;
    println!("HTTP fetch took: {} ms, processing took {} ms",
             (fetch as f64) / 1000000.0,
             (delta as f64) / 1000000.0);

    return bytes.unwrap();

}

fn proto1(req: &mut Request) -> IronResult<Response> {
    let content_type = "image/jpeg".parse::<Mime>().unwrap();

    let w = req.extensions.get::<Router>().unwrap().find("w").and_then(|x| x.parse::<u32>().ok());
    let h = req.extensions.get::<Router>().unwrap().find("h").and_then(|x| x.parse::<u32>().ok());
    let url = "http://images.unsplash.com/".to_string() +
              req.extensions.get::<Router>().unwrap().find("url").unwrap();

    let payload = get_jpeg_bytes(&url, w, h);

    Ok(Response::with((content_type, status::Ok, payload)))
}

fn main() {
    let mut router = Router::new();

    router.get("/proto1/scale_unsplash_jpeg/:w/:h/:url",
               move |r: &mut Request| proto1(r));

    Iron::new(router).http("localhost:3000").unwrap();
}
<commit_msg>Update server to work with API changes<commit_after>extern crate iron;
extern crate router;
extern crate rustc_serialize;
extern crate hyper;
extern crate libc;
extern crate time;

extern crate imageflow_core;
use imageflow_core::boring::*;
use imageflow_core::ffi::*;

use hyper::Client;
use iron::mime::Mime;
use iron::prelude::*;
use iron::status;
use router::Router;
use std::io::Read;
use time::precise_time_ns;

// This Rust server was built one saturday evening to exercise various
// bits of the stack. It's not safe (nor safer than a C equivalent), and
// we're not using Rust idomatically or correctly. Nothing is re-entrant,
// and errors panic the process. It's one build to throw away; a learning experiment.
//
// Run with cargo run --bin imageflow-server
//
// Open in your browser: http://localhost:3000/proto1/scale_unsplash_jpeg/1200/1200/photo-1436891678271-9c672565d8f6
//

fn create_io(c: *mut Context, source_bytes: *const u8, count: usize) -> Vec<IoResource> {
    unsafe {
        let input_io = flow_io_create_from_memory(c,
                                                  IoMode::read_seekable,
                                                  source_bytes,
                                                  count as libc::size_t,
                                                  c as *mut libc::c_void,
                                                  0 as *mut libc::c_void);

        if input_io.is_null() {
            flow_context_print_and_exit_if_err(c);
            // bad, we shouldn't exit the process
        }
        let output_io = flow_io_create_for_output_buffer(c, c as *mut libc::c_void);

        if output_io.is_null() {
            flow_context_print_and_exit_if_err(c);
        }

        vec![IoResource {
                 io: input_io,
                 direction: IoDirection::In,
             },
             IoResource {
                 io: output_io,
                 direction: IoDirection::Out,
             }]
    }
}

fn collect_result(c: *mut Context, job: *mut Job) -> Result<Vec<u8>, String> {
    unsafe {
        let output_io = flow_job_get_io(c, job, 1);
        if output_io.is_null() {
            flow_context_print_and_exit_if_err(c);
        }

        let mut buf: *const u8 = std::mem::uninitialized(); //This is okay, it's write-only
        let mut buf_length: libc::size_t = 0;
        // Returns false if the flow_io struct is disposed or not an output buffer type (or for any other error)

        if !flow_io_get_output_buffer(c, output_io, &mut buf, &mut buf_length) {
            flow_context_print_and_exit_if_err(c);
        }

        Ok(std::slice::from_raw_parts(buf as *const u8, buf_length as usize).to_vec())
    }
}

fn get_jpeg_bytes(source: &str, w: Option<u32>, h: Option<u32>) -> Vec<u8> {

    let start = precise_time_ns();

    let client = Client::new();
    let mut res = client.get(source).send().unwrap();
    assert_eq!(res.status, hyper::Ok);

    let mut source_bytes = Vec::new();
    let count = res.read_to_end(&mut source_bytes).unwrap(); //bad

    let downloaded = precise_time_ns();

    let commands = BoringCommands {
        fit: ConstraintMode::Max,
        w: w.unwrap_or(0) as i32,
        h: h.unwrap_or(0) as i32,
        jpeg_quality: 90,
        precise_scaling_ratio: 2.1f32,
        luma_correct: true,
        sharpen: 0f32,
        format: ImageFormat::Jpeg,
        down_filter: Filter::Robidoux,
        up_filter: Filter::Ginseng,
    };

    let source_ptr = source_bytes.as_mut_ptr();

    let bytes = imageflow_core::boring::process_image(commands,
                                                        |c| create_io(c, source_ptr, count),
                                                        collect_result);

    std::mem::forget(source_bytes);

    let fetch = downloaded - start;
    let delta = precise_time_ns() - downloaded;
    println!("HTTP fetch took: {} ms, processing took {} ms",
             (fetch as f64) / 1000000.0,
             (delta as f64) / 1000000.0);

    return bytes.unwrap();

}

fn proto1(req: &mut Request) -> IronResult<Response> {
    let content_type = "image/jpeg".parse::<Mime>().unwrap();

    let w = req.extensions.get::<Router>().unwrap().find("w").and_then(|x| x.parse::<u32>().ok());
    let h = req.extensions.get::<Router>().unwrap().find("h").and_then(|x| x.parse::<u32>().ok());
    let url = "http://images.unsplash.com/".to_string() +
              req.extensions.get::<Router>().unwrap().find("url").unwrap();

    let payload = get_jpeg_bytes(&url, w, h);

    Ok(Response::with((content_type, status::Ok, payload)))
}

fn main() {
    let mut router = Router::new();

    router.get("/proto1/scale_unsplash_jpeg/:w/:h/:url",
               move |r: &mut Request| proto1(r), "proto1-unsplash");

    Iron::new(router).http("localhost:3000").unwrap();
}
<|endoftext|>


<commit_before>use std::ops::{Add, Div, Mul, Rem, Sub};
use typedef::*;

#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, PartialOrd)]
pub enum Value {
    Boolean(bool), // true | false
    Float(Float), // -1.33 | 0.23114 | 3.141 | ...
    Integer(Integer), // 12 | 42 | 1 | 0 | 24 | ...
    Symbol(Address), // :hello | :test | :symbol | ...
    String(String), // "hello world" | "hello!" | "yellow \"blue\" or red" | ...
    Color(u8, u8, u8), // #FF00FF | #bd37b3 | ...
    Char(char), // 'a' | 'b' | 'c' | 'd' | ...
    Undefined, // The Undefined value symbolizes an internal error or a wrong use of the bytecode
}

impl Default for Value {
    fn default() -> Self {
        Value::Undefined
    }
}

impl Value {
    pub fn is_undefined(&self) -> bool {
        match self {
            &Value::Undefined => true,
            _ => false,
        }
    }
}

impl Add for Value {
    type Output = Value;

    fn add(self, rhs: Self) -> Self::Output {
        match self {
            Value::Float(lhs_float) => {
                match rhs {
                    Value::Float(rhs_float) => Value::Float(lhs_float + rhs_float),
                    Value::String(rhs_string) => Value::String(format!("{}{}", lhs_float, rhs_string),),
                    _ => Value::Undefined,
                }
            }

            Value::Integer(lhs_integer) => {
                match rhs {
                    Value::Integer(rhs_integer) => Value::Integer(lhs_integer + rhs_integer),
                    Value::String(rhs_string) => Value::String(format!("{}{}", lhs_integer, rhs_string),),
                    _ => Value::Undefined,
                }
            }

            Value::String(lhs_string) => {
                match rhs {
                    Value::Float(rhs_float) => Value::String(format!("{}{}", lhs_string, rhs_float),),
                    Value::Integer(rhs_integer) => Value::String(format!("{}{}", lhs_string, rhs_integer),),
                    Value::String(rhs_string) => Value::String(format!("{}{}", lhs_string, rhs_string),),
                    _ => Value::Undefined,
                }
            }
            _ => Value::Undefined,
        }
    }
}

impl Sub for Value {
    type Output = Value;

    fn sub(self, rhs: Self) -> Self::Output {
        match (self, rhs) {
            (Value::Float(lhs_float), Value::Float(rhs_float)) => Value::Float(lhs_float - rhs_float,),
            (Value::Integer(lhs_integer), Value::Integer(rhs_integer)) => {
                Value::Integer(lhs_integer - rhs_integer)
            }
            _ => Value::Undefined,
        }
    }
}

impl Mul for Value {
    type Output = Value;

    fn mul(self, rhs: Self) -> Self::Output {
        match self {
            Value::Float(lhs_float) => {
                match rhs {
                    Value::Float(rhs_float) => Value::Float(lhs_float * rhs_float),
                    _ => Value::Undefined,
                }
            }

            Value::Integer(lhs_integer) => {
                match rhs {
                    Value::Integer(rhs_integer) => Value::Integer(lhs_integer * rhs_integer),
                    _ => Value::Undefined,
                }
            }
            _ => Value::Undefined,
        }
    }
}

impl Div for Value {
    type Output = Value;

    fn div(self, rhs: Self) -> Self::Output {
        match (self, rhs) {
            (Value::Float(lhs_float), Value::Float(rhs_float)) => Value::Float(lhs_float / rhs_float,),
            _ => Value::Undefined,
        }
    }
}

impl Rem for Value {
    type Output = Value;

    fn rem(self, rhs: Self) -> Self::Output {
        match (self, rhs) {
            (Value::Float(lhs_float), Value::Float(rhs_float)) => Value::Float(lhs_float % rhs_float,),
            (Value::Integer(lhs_integer), Value::Integer(rhs_integer)) => {
                Value::Integer(lhs_integer % rhs_integer)
            }
            _ => Value::Undefined,
        }
    }
}

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

    #[test]
    fn comparison() {
        assert!(Value::Float(1.3) < Value::Float(1.4));
        assert!(Value::Float(3.1) > Value::Float(2.4));
        assert!(Value::Float(9.6) == Value::Float(9.6));

        assert!(Value::Integer(124) < Value::Integer(234));
        assert!(Value::Integer(4) > Value::Integer(1));
        assert!(Value::Integer(839) == Value::Integer(839));
    }
}
<commit_msg>Removed string and symbol values<commit_after>use std::ops::{Add, Div, Mul, Rem, Sub};
use typedef::*;

#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, PartialOrd)]
pub enum Value {
    Boolean(bool), // true | false
    Float(Float), // -1.33 | 0.23114 | 3.141 | ...
    Integer(Integer), // 12 | 42 | 1 | 0 | 24 | ...
    Color(u8, u8, u8), // #FF00FF | #bd37b3 | ...
    Char(char), // 'a' | 'b' | 'c' | 'd' | ...
    Undefined, // The Undefined value symbolizes an internal error or a wrong use of the bytecode
}

impl Default for Value {
    fn default() -> Self {
        Value::Undefined
    }
}

impl Value {
    pub fn is_undefined(&self) -> bool {
        match self {
            &Value::Undefined => true,
            _ => false,
        }
    }
}

impl Add for Value {
    type Output = Value;

    fn add(self, rhs: Self) -> Self::Output {
        match self {
            Value::Float(lhs_float) => {
                match rhs {
                    Value::Float(rhs_float) => Value::Float(lhs_float + rhs_float),
                    _ => Value::Undefined,
                }
            }
            Value::Integer(lhs_integer) => {
                match rhs {
                    Value::Integer(rhs_integer) => Value::Integer(lhs_integer + rhs_integer),
                    _ => Value::Undefined,
                }
            }
            _ => Value::Undefined,
        }
    }
}

impl Sub for Value {
    type Output = Value;

    fn sub(self, rhs: Self) -> Self::Output {
        match (self, rhs) {
            (Value::Float(lhs_float), Value::Float(rhs_float)) => Value::Float(lhs_float - rhs_float,),
            (Value::Integer(lhs_integer), Value::Integer(rhs_integer)) => {
                Value::Integer(lhs_integer - rhs_integer)
            }
            _ => Value::Undefined,
        }
    }
}

impl Mul for Value {
    type Output = Value;

    fn mul(self, rhs: Self) -> Self::Output {
        match self {
            Value::Float(lhs_float) => {
                match rhs {
                    Value::Float(rhs_float) => Value::Float(lhs_float * rhs_float),
                    _ => Value::Undefined,
                }
            }

            Value::Integer(lhs_integer) => {
                match rhs {
                    Value::Integer(rhs_integer) => Value::Integer(lhs_integer * rhs_integer),
                    _ => Value::Undefined,
                }
            }
            _ => Value::Undefined,
        }
    }
}

impl Div for Value {
    type Output = Value;

    fn div(self, rhs: Self) -> Self::Output {
        match (self, rhs) {
            (Value::Float(lhs_float), Value::Float(rhs_float)) => Value::Float(lhs_float / rhs_float,),
            _ => Value::Undefined,
        }
    }
}

impl Rem for Value {
    type Output = Value;

    fn rem(self, rhs: Self) -> Self::Output {
        match (self, rhs) {
            (Value::Float(lhs_float), Value::Float(rhs_float)) => Value::Float(lhs_float % rhs_float,),
            (Value::Integer(lhs_integer), Value::Integer(rhs_integer)) => {
                Value::Integer(lhs_integer % rhs_integer)
            }
            _ => Value::Undefined,
        }
    }
}

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

    #[test]
    fn comparison() {
        assert!(Value::Float(1.3) < Value::Float(1.4));
        assert!(Value::Float(3.1) > Value::Float(2.4));
        assert!(Value::Float(9.6) == Value::Float(9.6));

        assert!(Value::Integer(124) < Value::Integer(234));
        assert!(Value::Integer(4) > Value::Integer(1));
        assert!(Value::Integer(839) == Value::Integer(839));
    }
}
<|endoftext|>


<commit_before>use combine::*;
use combine::char::char;
use combine::primitives::RangeStream;
use parser::errors::CustomError;
use parser::trivia::ws;
use parser::key::key;
use parser::value::value;
use value::{InlineTable, KeyValue};
use decor::{InternalString, Repr};
use formatted::decorated;

// ;; Inline Table

// inline-table = inline-table-open inline-table-keyvals inline-table-close
parse!(inline_table() -> InlineTable, {
    between(char(INLINE_TABLE_OPEN), char(INLINE_TABLE_CLOSE),
            inline_table_keyvals().and_then(|(p, v)| table_from_pairs(p, v)))
});

fn table_from_pairs(
    preamble: &str,
    v: Vec<(InternalString, KeyValue)>,
) -> Result<InlineTable, CustomError> {
    let mut table = InlineTable::default();
    table.preamble = InternalString::from(preamble);

    for (k, kv) in v {
        if table.contains_key(&k) {
            return Err(CustomError::DuplicateKey {
                key: k.into(),
                table: "inline".into(),
            });
        }
        table.key_value_pairs.insert(k, kv);
    }
    Ok(table)
}

// inline-table-open  = %x7B ws     ; {
const INLINE_TABLE_OPEN: char = '{';
// inline-table-close = ws %x7D     ; }
const INLINE_TABLE_CLOSE: char = '}';
// inline-table-sep   = ws %x2C ws  ; , Comma
const INLINE_TABLE_SEP: char = ',';
// keyval-sep = ws %x3D ws ; =
pub(crate) const KEYVAL_SEP: char = '=';

// inline-table-keyvals = [ inline-table-keyvals-non-empty ]
// inline-table-keyvals-non-empty =
// ( key keyval-sep val inline-table-sep inline-table-keyvals-non-empty ) /
// ( key keyval-sep val )
parser!{
    fn inline_table_keyvals['a, I]()(I) -> (&'a str, Vec<(InternalString, KeyValue)>)
        where
        [I: RangeStream<Range = &'a str, Item = char>,]
    {
        (
            sep_by(keyval(), char(INLINE_TABLE_SEP)),
            ws(),
        ).map(|(v, w)| {
            (w, v)
        })
    }
}

parser!{
    fn keyval['a, I]()(I) -> (InternalString, KeyValue)
        where
        [I: RangeStream<Range = &'a str, Item = char>,]
    {
        (
            try((ws(), key(), ws())),
            char(KEYVAL_SEP),
            (ws(), value(), ws()),
        ).map(|(k, _, v)| {
            let (pre, v, suf) = v;
            let v = decorated(v, pre, suf);
            let (pre, (raw, key), suf) = k;
            (
                key,
                KeyValue {
                    key: Repr::new(pre, raw, suf),
                    value: v,
                }
            )
        })
    }
}
<commit_msg>refactor(parser): use parse macro for inline_table<commit_after>use combine::*;
use combine::char::char;
use combine::primitives::RangeStream;
use parser::errors::CustomError;
use parser::trivia::ws;
use parser::key::key;
use parser::value::value;
use value::{InlineTable, KeyValue};
use decor::{InternalString, Repr};
use formatted::decorated;

// ;; Inline Table

// inline-table = inline-table-open inline-table-keyvals inline-table-close
parse!(inline_table() -> InlineTable, {
    between(char(INLINE_TABLE_OPEN), char(INLINE_TABLE_CLOSE),
            inline_table_keyvals().and_then(|(p, v)| table_from_pairs(p, v)))
});

fn table_from_pairs(
    preamble: &str,
    v: Vec<(InternalString, KeyValue)>,
) -> Result<InlineTable, CustomError> {
    let mut table = InlineTable::default();
    table.preamble = InternalString::from(preamble);

    for (k, kv) in v {
        if table.contains_key(&k) {
            return Err(CustomError::DuplicateKey {
                key: k.into(),
                table: "inline".into(),
            });
        }
        table.key_value_pairs.insert(k, kv);
    }
    Ok(table)
}

// inline-table-open  = %x7B ws     ; {
const INLINE_TABLE_OPEN: char = '{';
// inline-table-close = ws %x7D     ; }
const INLINE_TABLE_CLOSE: char = '}';
// inline-table-sep   = ws %x2C ws  ; , Comma
const INLINE_TABLE_SEP: char = ',';
// keyval-sep = ws %x3D ws ; =
pub(crate) const KEYVAL_SEP: char = '=';

// inline-table-keyvals = [ inline-table-keyvals-non-empty ]
// inline-table-keyvals-non-empty =
// ( key keyval-sep val inline-table-sep inline-table-keyvals-non-empty ) /
// ( key keyval-sep val )
parse!(inline_table_keyvals() -> (&'a str, Vec<(InternalString, KeyValue)>), {
    (
        sep_by(keyval(), char(INLINE_TABLE_SEP)),
        ws(),
    ).map(|(v, w)| {
        (w, v)
    })
});

parse!(keyval() -> (InternalString, KeyValue), {
    (
        try((ws(), key(), ws())),
        char(KEYVAL_SEP),
        (ws(), value(), ws()),
    ).map(|(k, _, v)| {
        let (pre, v, suf) = v;
        let v = decorated(v, pre, suf);
        let (pre, (raw, key), suf) = k;
        (
            key,
            KeyValue {
                key: Repr::new(pre, raw, suf),
                value: v,
            }
        )
    })
});
<|endoftext|>


<commit_before>use async_trait::async_trait;
use cucumber::{then, when};
use geo::algorithm::haversine_distance::HaversineDistance;
use itertools::{EitherOrBoth::*, Itertools};
use mimir::adapters::secondary::elasticsearch::remote::connection_test_pool;
use mimir::domain::model::configuration;
use mimir::domain::ports::secondary::remote::Remote;
use std::cmp::Ordering;

use crate::error::Error;
use crate::state::{GlobalState, State, Step, StepStatus};
use mimir::adapters::primary::bragi::api::DEFAULT_LIMIT_RESULT_ES;
use mimir::adapters::primary::common::dsl::QueryType;
use mimir::adapters::primary::{
    common::coord::Coord, common::dsl::build_query, common::filters::Filters,
    common::settings::QuerySettings,
};
use mimir::adapters::secondary::elasticsearch::ElasticsearchStorageConfig;
use mimir::domain::{model::query::Query, ports::primary::search_documents::SearchDocuments};
use places::{addr::Addr, admin::Admin, poi::Poi};

// Search place

#[when(regex = r#"the user searches (.+) datatype for "(.*)" at (.+), (.+)$"#)]
async fn search(state: &mut GlobalState, places: String, query: String, lat: f32, lon: f32) {
    perform_search(state, places, query, Coord::new(lat, lon).into(), None).await;
}

#[when(regex = r#"the user searches (.+) datatype for "(.+)" with "(.+)" filters$"#)]
async fn search_with_zone_filters(
    state: &mut GlobalState,
    places: String,
    query: String,
    zone_types: String,
) {
    perform_search(state, places, query, None, Some(zone_types)).await;
}

#[when(regex = r#"the user searches (.+) datatype for "(.*)"$"#)]
async fn search_no_coord(state: &mut GlobalState, places: String, query: String) {
    perform_search(state, places, query, None, None).await;
}

async fn perform_search(
    state: &mut GlobalState,
    places: String,
    query: String,
    coord: Option<Coord>,
    zone_types: Option<String>,
) {
    let places = {
        if places == "all" {
            vec![configuration::root()]
        } else {
            places
                .split(',')
                .map(str::trim)
                .map(str::to_string)
                .map(|s| configuration::root_doctype(&s))
                .collect()
        }
    };

    let zone_types = zone_types.map(|f| {
        f.split(',')
            .map(str::trim)
            .map(str::to_string)
            .collect::<Vec<String>>()
    });

    let filters = Filters {
        coord,
        zone_types,
        ..Default::default()
    };

    state
        .execute(Search {
            places,
            query,
            filters,
            results: Vec::new(),
        })
        .await
        .expect("failed to search");
}

/// Perform a search in current Elasticsearch DB.
#[derive(Debug)]
pub struct Search {
    places: Vec<String>, // What kind of places we're searching
    query: String,       // The search string
    filters: Filters,    // Search filters
    results: Vec<serde_json::Value>,
}

#[async_trait(?Send)]
impl Step for Search {
    async fn execute(&mut self, _state: &State) -> Result<StepStatus, Error> {
        let client = connection_test_pool()
            .conn(ElasticsearchStorageConfig::default_testing())
            .await
            .expect("Could not establish connection to Elasticsearch");

        // Build ES query
        let dsl = build_query(
            &self.query,
            self.filters.clone(),
            "fr",
            &QuerySettings::default(),
            QueryType::PREFIX,
        );

        // Fetch documents
        self.results = {
            client
                .search_documents(
                    self.places.clone(),
                    Query::QueryDSL(dsl),
                    DEFAULT_LIMIT_RESULT_ES,
                    None,
                )
                .await
                .unwrap()
        };

        Ok(StepStatus::Done)
    }
}

// Find document

#[then(regex = r#"he finds "(.+)" as the first result$"#)]
async fn find_id(state: &mut GlobalState, id: String) {
    state
        .execute(HasDocument { id, max_rank: 1 })
        .await
        .expect("failed to find document");
}

/// Check if given document is in the output.
///
/// It assumes that a Search has already been performed before.
pub struct HasDocument {
    id: String,
    max_rank: usize,
}

#[async_trait(?Send)]
impl Step for HasDocument {
    async fn execute(&mut self, state: &State) -> Result<StepStatus, Error> {
        let (search, _) = state
            .steps_for::<Search>()
            .next_back()
            .expect("the user must perform a search before checking results");

        let (rank, _) = (search.results.iter().enumerate())
            .find(|(_, doc)| {
                println!("{} vs {}", self.id, doc["id"].as_str().unwrap());
                self.id == doc["id"].as_str().unwrap()
            })
            .expect("document was not found in search results");

        assert!(rank < self.max_rank);
        Ok(StepStatus::Done)
    }
}

// Find Admin

#[then(regex = r#"he finds admin "(.*)", a "(.*)", in the first (.*) results$"#)]
async fn find_admin(state: &mut GlobalState, name: String, zone_type: String, limit: usize) {
    state
        .execute(HasAdmin {
            name: Some(name),
            zone_type: Some(zone_type),
            limit,
        })
        .await
        .expect("failed to find document");
}

/// Check if given admin is in the output.
///
/// It assumes that a Search has already been performed before.
pub struct HasAdmin {
    name: Option<String>,
    zone_type: Option<String>,
    limit: usize,
}

#[async_trait(?Send)]
impl Step for HasAdmin {
    async fn execute(&mut self, state: &State) -> Result<StepStatus, Error> {
        let (search, _) = state
            .steps_for::<Search>()
            .next_back()
            .expect("the user must perform a search before checking results");
        let rank = search
            .results
            .clone()
            .into_iter()
            .enumerate()
            .find_map(|(num, doc)| {
                let admin: Admin = serde_json::from_value(doc).expect("admin");
                if let Some(name) = &self.name {
                    if !equal_ignore_case_utf8(name, admin.name.as_str()) {
                        return None;
                    }
                }
                if let Some(zone_type) = &self.zone_type {
                    if !equal_ignore_case_utf8(
                        zone_type,
                        admin.zone_type.expect("zone type").as_str(),
                    ) {
                        // is it justified to expect a zone type?
                        return None;
                    }
                }
                Some(num)
            })
            .expect("document was not found in search results");

        assert!(rank < self.limit);
        Ok(StepStatus::Done)
    }
}

// Find address

#[then(
    regex = r#"he finds address "(.*)", "(.*)", "(.*)", and "(.*)" in the first "(.*)" results$"#
)]
async fn find_address(
    state: &mut GlobalState,
    house: String,
    street: String,
    city: String,
    postcode: String,
    limit: usize,
) {
    state
        .execute(HasAddress {
            house: none_if_empty(house),
            street: none_if_empty(street),
            city: none_if_empty(city),
            postcode: none_if_empty(postcode),
            limit,
        })
        .await
        .expect("failed to find document");
}

/// Check if given address is in the output.
///
/// It assumes that a Search has already been performed before.
pub struct HasAddress {
    house: Option<String>,
    street: Option<String>,
    city: Option<String>,
    postcode: Option<String>,
    limit: usize,
}

#[async_trait(?Send)]
impl Step for HasAddress {
    async fn execute(&mut self, state: &State) -> Result<StepStatus, Error> {
        let (search, _) = state
            .steps_for::<Search>()
            .next_back()
            .expect("the user must perform a search before checking results");

        let rank = search
            .results
            .clone()
            .into_iter()
            .enumerate()
            .find_map(|(num, doc)| {
                let addr: Addr = serde_json::from_value(doc).expect("address");
                if let Some(house) = &self.house {
                    if !equal_ignore_case_utf8(house, addr.house_number.as_str()) {
                        return None;
                    }
                }
                if let Some(street) = &self.street {
                    if !equal_ignore_case_utf8(street, addr.street.name.as_str()) {
                        return None;
                    }
                }
                if let Some(postcode) = &self.postcode {
                    if !equal_ignore_case_utf8(postcode, addr.zip_codes[0].as_str()) {
                        return None;
                    }
                }
                if let Some(city) = &self.city {
                    if !equal_ignore_case_utf8(city, addr.city().expect("city").as_str()) {
                        return None;
                    }
                }
                Some(num)
            })
            .expect("document was not found in search results");

        assert!(rank < self.limit);
        Ok(StepStatus::Done)
    }
}

// Find POI

#[then(
    regex = r#"he finds poi "(.*)", a "(.*)" located near ([0-9\.]+), ([0-9\.]+) in the first (\d+) results$"#
)]
async fn find_poi(
    state: &mut GlobalState,
    label: String,
    poi_type: String,
    lat: f64,
    lon: f64,
    limit: usize,
) {
    state
        .execute(HasPoi {
            label: none_if_empty(label),
            poi_type: none_if_empty(poi_type),
            coord: Some(geo_types::Point::new(lon, lat)),
            limit,
        })
        .await
        .expect("failed to find document");
}

/// Check if given poi is in the output.
///
/// It assumes that a Search has already been performed before.
pub struct HasPoi {
    label: Option<String>,
    poi_type: Option<String>,
    coord: Option<geo_types::Point<f64>>,
    limit: usize,
}

#[async_trait(?Send)]
impl Step for HasPoi {
    async fn execute(&mut self, state: &State) -> Result<StepStatus, Error> {
        let (search, _) = state
            .steps_for::<Search>()
            .next_back()
            .expect("the user must perform a search before checking results");

        let rank = search
            .results
            .clone()
            .into_iter()
            .enumerate()
            .find_map(|(num, doc)| {
                let poi: Poi = serde_json::from_value(doc).expect("poi");
                if let Some(label) = &self.label {
                    if !equal_ignore_case_utf8(label, poi.label.as_str()) {
                        return None;
                    }
                }
                if let Some(poi_type) = &self.poi_type {
                    if !equal_ignore_case_utf8(poi_type, poi.poi_type.name.as_str()) {
                        return None;
                    }
                }
                if let Some(coord) = &self.coord {
                    let distance = coord.haversine_distance(&poi.coord.into());
                    // if we are at more than 100m
                    if distance > 100.0 {
                        return None;
                    }
                }
                Some(num)
            })
            .expect("document was not found in search results");

        assert!(rank < self.limit);
        Ok(StepStatus::Done)
    }
}

// Utils

fn none_if_empty(val: String) -> Option<String> {
    if val.is_empty() {
        None
    } else {
        Some(val)
    }
}

// Based on https://stackoverflow.com/questions/63871601/what-is-an-efficient-way-to-compare-strings-while-ignoring-case
// Its a case insensitive comparison, returning true if equal, false otherwise
fn equal_ignore_case_utf8(a: &str, b: &str) -> bool {
    let abs = a
        .chars()
        .flat_map(char::to_lowercase)
        .zip_longest(b.chars().flat_map(char::to_lowercase));

    for ab in abs {
        match ab {
            Left(_) => return false,
            Right(_) => return false,
            Both(a, b) => {
                if a.cmp(&b) != Ordering::Equal {
                    return false;
                }
            }
        }
    }
    true
}
<commit_msg>correction<commit_after>use async_trait::async_trait;
use cucumber::{then, when};
use geo::algorithm::haversine_distance::HaversineDistance;
use itertools::{EitherOrBoth::*, Itertools};
use mimir::adapters::secondary::elasticsearch::remote::connection_test_pool;
use mimir::domain::model::configuration;
use mimir::domain::ports::secondary::remote::Remote;
use std::cmp::Ordering;

use crate::error::Error;
use crate::state::{GlobalState, State, Step, StepStatus};
use mimir::adapters::primary::bragi::api::DEFAULT_LIMIT_RESULT_ES;
use mimir::adapters::primary::common::dsl::QueryType;
use mimir::adapters::primary::{
    common::coord::Coord, common::dsl::build_query, common::filters::Filters,
    common::settings::QuerySettings,
};
use mimir::adapters::secondary::elasticsearch::ElasticsearchStorageConfig;
use mimir::domain::{model::query::Query, ports::primary::search_documents::SearchDocuments};
use places::{addr::Addr, admin::Admin, poi::Poi};

// Search place

#[when(regex = r#"the user searches (.+) datatype for "(.*)" at (.+), (.+)$"#)]
async fn search(state: &mut GlobalState, places: String, query: String, lat: f32, lon: f32) {
    perform_search(state, places, query, Coord::new(lat, lon).into(), None).await;
}

#[when(regex = r#"the user searches (.+) datatype for "(.+)" with "(.+)" filters$"#)]
async fn search_with_zone_filters(
    state: &mut GlobalState,
    places: String,
    query: String,
    zone_types: String,
) {
    perform_search(state, places, query, None, Some(zone_types)).await;
}

#[when(regex = r#"the user searches (.+) datatype for "(.*)"$"#)]
async fn search_no_coord(state: &mut GlobalState, places: String, query: String) {
    perform_search(state, places, query, None, None).await;
}

async fn perform_search(
    state: &mut GlobalState,
    places: String,
    query: String,
    coord: Option<Coord>,
    zone_types: Option<String>,
) {
    let places = {
        if places == "all" {
            vec![configuration::root()]
        } else {
            places
                .split(',')
                .map(str::trim)
                .map(str::to_string)
                .map(|s| configuration::root_doctype(&s))
                .collect()
        }
    };

    let zone_types = zone_types.map(|f| {
        f.split(',')
            .map(str::trim)
            .map(str::to_string)
            .collect::<Vec<String>>()
    });

    let filters = Filters {
        coord,
        zone_types,
        ..Default::default()
    };

    state
        .execute(Search {
            places,
            query,
            filters,
            results: Vec::new(),
        })
        .await
        .expect("failed to search");
}

/// Perform a search in current Elasticsearch DB.
#[derive(Debug)]
pub struct Search {
    places: Vec<String>, // What kind of places we're searching
    query: String,       // The search string
    filters: Filters,    // Search filters
    results: Vec<serde_json::Value>,
}

#[async_trait(?Send)]
impl Step for Search {
    async fn execute(&mut self, _state: &State) -> Result<StepStatus, Error> {
        let client = connection_test_pool()
            .conn(ElasticsearchStorageConfig::default_testing())
            .await
            .expect("Could not establish connection to Elasticsearch");

        // Build ES query
        let dsl = build_query(
            &self.query,
            self.filters.clone(),
            "fr",
            &QuerySettings::default(),
            QueryType::PREFIX,
            &Option::None,
        );

        // Fetch documents
        self.results = {
            client
                .search_documents(
                    self.places.clone(),
                    Query::QueryDSL(dsl),
                    DEFAULT_LIMIT_RESULT_ES,
                    None,
                )
                .await
                .unwrap()
        };

        Ok(StepStatus::Done)
    }
}

// Find document

#[then(regex = r#"he finds "(.+)" as the first result$"#)]
async fn find_id(state: &mut GlobalState, id: String) {
    state
        .execute(HasDocument { id, max_rank: 1 })
        .await
        .expect("failed to find document");
}

/// Check if given document is in the output.
///
/// It assumes that a Search has already been performed before.
pub struct HasDocument {
    id: String,
    max_rank: usize,
}

#[async_trait(?Send)]
impl Step for HasDocument {
    async fn execute(&mut self, state: &State) -> Result<StepStatus, Error> {
        let (search, _) = state
            .steps_for::<Search>()
            .next_back()
            .expect("the user must perform a search before checking results");

        let (rank, _) = (search.results.iter().enumerate())
            .find(|(_, doc)| {
                println!("{} vs {}", self.id, doc["id"].as_str().unwrap());
                self.id == doc["id"].as_str().unwrap()
            })
            .expect("document was not found in search results");

        assert!(rank < self.max_rank);
        Ok(StepStatus::Done)
    }
}

// Find Admin

#[then(regex = r#"he finds admin "(.*)", a "(.*)", in the first (.*) results$"#)]
async fn find_admin(state: &mut GlobalState, name: String, zone_type: String, limit: usize) {
    state
        .execute(HasAdmin {
            name: Some(name),
            zone_type: Some(zone_type),
            limit,
        })
        .await
        .expect("failed to find document");
}

/// Check if given admin is in the output.
///
/// It assumes that a Search has already been performed before.
pub struct HasAdmin {
    name: Option<String>,
    zone_type: Option<String>,
    limit: usize,
}

#[async_trait(?Send)]
impl Step for HasAdmin {
    async fn execute(&mut self, state: &State) -> Result<StepStatus, Error> {
        let (search, _) = state
            .steps_for::<Search>()
            .next_back()
            .expect("the user must perform a search before checking results");
        let rank = search
            .results
            .clone()
            .into_iter()
            .enumerate()
            .find_map(|(num, doc)| {
                let admin: Admin = serde_json::from_value(doc).expect("admin");
                if let Some(name) = &self.name {
                    if !equal_ignore_case_utf8(name, admin.name.as_str()) {
                        return None;
                    }
                }
                if let Some(zone_type) = &self.zone_type {
                    if !equal_ignore_case_utf8(
                        zone_type,
                        admin.zone_type.expect("zone type").as_str(),
                    ) {
                        // is it justified to expect a zone type?
                        return None;
                    }
                }
                Some(num)
            })
            .expect("document was not found in search results");

        assert!(rank < self.limit);
        Ok(StepStatus::Done)
    }
}

// Find address

#[then(
    regex = r#"he finds address "(.*)", "(.*)", "(.*)", and "(.*)" in the first "(.*)" results$"#
)]
async fn find_address(
    state: &mut GlobalState,
    house: String,
    street: String,
    city: String,
    postcode: String,
    limit: usize,
) {
    state
        .execute(HasAddress {
            house: none_if_empty(house),
            street: none_if_empty(street),
            city: none_if_empty(city),
            postcode: none_if_empty(postcode),
            limit,
        })
        .await
        .expect("failed to find document");
}

/// Check if given address is in the output.
///
/// It assumes that a Search has already been performed before.
pub struct HasAddress {
    house: Option<String>,
    street: Option<String>,
    city: Option<String>,
    postcode: Option<String>,
    limit: usize,
}

#[async_trait(?Send)]
impl Step for HasAddress {
    async fn execute(&mut self, state: &State) -> Result<StepStatus, Error> {
        let (search, _) = state
            .steps_for::<Search>()
            .next_back()
            .expect("the user must perform a search before checking results");

        let rank = search
            .results
            .clone()
            .into_iter()
            .enumerate()
            .find_map(|(num, doc)| {
                let addr: Addr = serde_json::from_value(doc).expect("address");
                if let Some(house) = &self.house {
                    if !equal_ignore_case_utf8(house, addr.house_number.as_str()) {
                        return None;
                    }
                }
                if let Some(street) = &self.street {
                    if !equal_ignore_case_utf8(street, addr.street.name.as_str()) {
                        return None;
                    }
                }
                if let Some(postcode) = &self.postcode {
                    if !equal_ignore_case_utf8(postcode, addr.zip_codes[0].as_str()) {
                        return None;
                    }
                }
                if let Some(city) = &self.city {
                    if !equal_ignore_case_utf8(city, addr.city().expect("city").as_str()) {
                        return None;
                    }
                }
                Some(num)
            })
            .expect("document was not found in search results");

        assert!(rank < self.limit);
        Ok(StepStatus::Done)
    }
}

// Find POI

#[then(
    regex = r#"he finds poi "(.*)", a "(.*)" located near ([0-9\.]+), ([0-9\.]+) in the first (\d+) results$"#
)]
async fn find_poi(
    state: &mut GlobalState,
    label: String,
    poi_type: String,
    lat: f64,
    lon: f64,
    limit: usize,
) {
    state
        .execute(HasPoi {
            label: none_if_empty(label),
            poi_type: none_if_empty(poi_type),
            coord: Some(geo_types::Point::new(lon, lat)),
            limit,
        })
        .await
        .expect("failed to find document");
}

/// Check if given poi is in the output.
///
/// It assumes that a Search has already been performed before.
pub struct HasPoi {
    label: Option<String>,
    poi_type: Option<String>,
    coord: Option<geo_types::Point<f64>>,
    limit: usize,
}

#[async_trait(?Send)]
impl Step for HasPoi {
    async fn execute(&mut self, state: &State) -> Result<StepStatus, Error> {
        let (search, _) = state
            .steps_for::<Search>()
            .next_back()
            .expect("the user must perform a search before checking results");

        let rank = search
            .results
            .clone()
            .into_iter()
            .enumerate()
            .find_map(|(num, doc)| {
                let poi: Poi = serde_json::from_value(doc).expect("poi");
                if let Some(label) = &self.label {
                    if !equal_ignore_case_utf8(label, poi.label.as_str()) {
                        return None;
                    }
                }
                if let Some(poi_type) = &self.poi_type {
                    if !equal_ignore_case_utf8(poi_type, poi.poi_type.name.as_str()) {
                        return None;
                    }
                }
                if let Some(coord) = &self.coord {
                    let distance = coord.haversine_distance(&poi.coord.into());
                    // if we are at more than 100m
                    if distance > 100.0 {
                        return None;
                    }
                }
                Some(num)
            })
            .expect("document was not found in search results");

        assert!(rank < self.limit);
        Ok(StepStatus::Done)
    }
}

// Utils

fn none_if_empty(val: String) -> Option<String> {
    if val.is_empty() {
        None
    } else {
        Some(val)
    }
}

// Based on https://stackoverflow.com/questions/63871601/what-is-an-efficient-way-to-compare-strings-while-ignoring-case
// Its a case insensitive comparison, returning true if equal, false otherwise
fn equal_ignore_case_utf8(a: &str, b: &str) -> bool {
    let abs = a
        .chars()
        .flat_map(char::to_lowercase)
        .zip_longest(b.chars().flat_map(char::to_lowercase));

    for ab in abs {
        match ab {
            Left(_) => return false,
            Right(_) => return false,
            Both(a, b) => {
                if a.cmp(&b) != Ordering::Equal {
                    return false;
                }
            }
        }
    }
    true
}
<|endoftext|>


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

use memory::paging::entry::*;
use memory::paging::ENTRY_COUNT;
use memory::FrameAllocator;
use core::ops::{Index, IndexMut};
use core::marker::PhantomData;

pub const P4: *mut Table<Level4> = 0xffffffff_fffff000 as *mut _;

pub struct Table<L: TableLevel> {
    entries: [Entry; ENTRY_COUNT],
    level: PhantomData<L>,
}

impl<L> Table<L> where L: TableLevel
{
    pub fn zero(&mut self) {
        for entry in self.entries.iter_mut() {
            entry.set_unused();
        }
    }
}

impl<L> Table<L> where L: HierarchicalLevel
{
    fn next_table_address(&self, index: usize) -> Option<usize> {
        let entry_flags = self[index].flags();
        if entry_flags.contains(PRESENT) && !entry_flags.contains(HUGE_PAGE) {
            let table_address = self as *const _ as usize;
            Some((table_address << 9) | (index << 12))
        } else {
            None
        }
    }

    pub fn next_table(&self, index: usize) -> Option<&Table<L::NextLevel>> {
        self.next_table_address(index)
            .map(|address| unsafe { &*(address as *const _) })
    }

    pub fn next_table_mut(&mut self, index: usize) -> Option<&mut Table<L::NextLevel>> {
        self.next_table_address(index)
            .map(|address| unsafe { &mut *(address as *mut _) })
    }

    pub fn next_table_create<A>(&mut self,
                                index: usize,
                                allocator: &mut A)
                                -> &mut Table<L::NextLevel>
        where A: FrameAllocator
    {
        if self.next_table(index).is_none() {
            assert!(!self.entries[index].flags().contains(HUGE_PAGE),
                    "mapping code does not support huge pages");
            let frame = allocator.allocate_frame().expect("no frames available");
            self.entries[index].set(frame, PRESENT | WRITABLE);
            self.next_table_mut(index).unwrap().zero();
        }
        self.next_table_mut(index).unwrap()
    }
}

impl<L> Index<usize> for Table<L> where L: TableLevel
{
    type Output = Entry;

    fn index(&self, index: usize) -> &Entry {
        &self.entries[index]
    }
}

impl<L> IndexMut<usize> for Table<L> where L: TableLevel
{
    fn index_mut(&mut self, index: usize) -> &mut Entry {
        &mut self.entries[index]
    }
}

pub trait TableLevel {}

pub enum Level4 {}
enum Level3 {}
enum Level2 {}
pub enum Level1 {}

impl TableLevel for Level4 {}
impl TableLevel for Level3 {}
impl TableLevel for Level2 {}
impl TableLevel for Level1 {}

trait HierarchicalLevel: TableLevel {
    type NextLevel: TableLevel;
}

impl HierarchicalLevel for Level4 {
    type NextLevel = Level3;
}

impl HierarchicalLevel for Level3 {
    type NextLevel = Level2;
}

impl HierarchicalLevel for Level2 {
    type NextLevel = Level1;
}
<commit_msg>Make some more types public since they are part of the public interface<commit_after>// Copyright 2015 Philipp Oppermann. See the README.md
// file at the top-level directory of this distribution.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

use memory::paging::entry::*;
use memory::paging::ENTRY_COUNT;
use memory::FrameAllocator;
use core::ops::{Index, IndexMut};
use core::marker::PhantomData;

pub const P4: *mut Table<Level4> = 0xffffffff_fffff000 as *mut _;

pub struct Table<L: TableLevel> {
    entries: [Entry; ENTRY_COUNT],
    level: PhantomData<L>,
}

impl<L> Table<L> where L: TableLevel
{
    pub fn zero(&mut self) {
        for entry in self.entries.iter_mut() {
            entry.set_unused();
        }
    }
}

impl<L> Table<L> where L: HierarchicalLevel
{
    fn next_table_address(&self, index: usize) -> Option<usize> {
        let entry_flags = self[index].flags();
        if entry_flags.contains(PRESENT) && !entry_flags.contains(HUGE_PAGE) {
            let table_address = self as *const _ as usize;
            Some((table_address << 9) | (index << 12))
        } else {
            None
        }
    }

    pub fn next_table(&self, index: usize) -> Option<&Table<L::NextLevel>> {
        self.next_table_address(index)
            .map(|address| unsafe { &*(address as *const _) })
    }

    pub fn next_table_mut(&mut self, index: usize) -> Option<&mut Table<L::NextLevel>> {
        self.next_table_address(index)
            .map(|address| unsafe { &mut *(address as *mut _) })
    }

    pub fn next_table_create<A>(&mut self,
                                index: usize,
                                allocator: &mut A)
                                -> &mut Table<L::NextLevel>
        where A: FrameAllocator
    {
        if self.next_table(index).is_none() {
            assert!(!self.entries[index].flags().contains(HUGE_PAGE),
                    "mapping code does not support huge pages");
            let frame = allocator.allocate_frame().expect("no frames available");
            self.entries[index].set(frame, PRESENT | WRITABLE);
            self.next_table_mut(index).unwrap().zero();
        }
        self.next_table_mut(index).unwrap()
    }
}

impl<L> Index<usize> for Table<L> where L: TableLevel
{
    type Output = Entry;

    fn index(&self, index: usize) -> &Entry {
        &self.entries[index]
    }
}

impl<L> IndexMut<usize> for Table<L> where L: TableLevel
{
    fn index_mut(&mut self, index: usize) -> &mut Entry {
        &mut self.entries[index]
    }
}

pub trait TableLevel {}

pub enum Level4 {}
#[allow(dead_code)]
pub enum Level3 {}
#[allow(dead_code)]
pub enum Level2 {}
pub enum Level1 {}

impl TableLevel for Level4 {}
impl TableLevel for Level3 {}
impl TableLevel for Level2 {}
impl TableLevel for Level1 {}

pub trait HierarchicalLevel: TableLevel {
    type NextLevel: TableLevel;
}

impl HierarchicalLevel for Level4 {
    type NextLevel = Level3;
}

impl HierarchicalLevel for Level3 {
    type NextLevel = Level2;
}

impl HierarchicalLevel for Level2 {
    type NextLevel = Level1;
}
<|endoftext|>


<commit_before>use pandora::Track;
use super::audio::Audio;

use std::collections::VecDeque;
use std::sync::{Arc, Barrier, Mutex};
use std::thread;

/// TrackLoader type for loading tracks in the background.
pub struct TrackLoader {
    tracklist: Arc<Mutex<VecDeque<Track>>>,
    next: Arc<Mutex<Option<(Track, Audio)>>>,
    fetching: Arc<Mutex<bool>>,
    fetching_barrier: Arc<Barrier>,
}

impl TrackLoader {
    /// Creates a new TrackLoader form the given tracklist.
    pub fn new(tracklist: VecDeque<Track>) -> Self {
        let mut track_loader = TrackLoader {
            tracklist: Arc::new(Mutex::new(tracklist)),
            next: Arc::new(Mutex::new(None)),
            fetching: Arc::new(Mutex::new(false)),
            fetching_barrier: Arc::new(Barrier::new(2)),
        };
        track_loader.fetch();
        track_loader
    }

    /// Returns the next track and audio, `None` is no more
    /// items available.
    pub fn next(&mut self) -> Option<(Track, Audio)> {
        // Wait until we are done fetching.
        if *self.fetching.lock().unwrap() {
            self.fetching_barrier.wait();
        }
        else if self.next.lock().unwrap().is_none() {
            *self.next.lock().unwrap() = pop_tracklist(self.tracklist.clone());
        }

        let next = self.next.lock().unwrap().take();
        self.fetch();
        return next;
    }

    /// Fetches the next track in the background.
    fn fetch(&mut self) {
        let tracklist = self.tracklist.clone();
        let next = self.next.clone();
        let fetching = self.fetching.clone();
        let barrier = self.fetching_barrier.clone();

        if tracklist.lock().unwrap().len() > 0 {
            *fetching.lock().unwrap() = true;
            thread::spawn(move || {
                if next.lock().unwrap().is_none() {
                    *next.lock().unwrap() = pop_tracklist(tracklist)
                }
                barrier.wait();
                *fetching.lock().unwrap() = false;
            });
        }
    }

}

/// Pops the next track from the tracklist and returns it along
/// with the audio.
fn pop_tracklist(tracklist: Arc<Mutex<VecDeque<Track>>>) -> Option<(Track, Audio)> {
    if let Some((track, audio)) = tracklist.lock().unwrap().pop_front().and_then(|track| {
        track.track_audio.clone().map(|audio| (track, audio))
    }) {
        let audio = match Audio::new(&audio.high_quality.audio_url) {
            Ok(audio) => audio,
            Err(e) => {
                return None;
            }
        };
        return Some((track, audio));
    }

    None
}
<commit_msg>Changed barrier to condvar for better behaviour<commit_after>use pandora::Track;
use super::audio::Audio;

use std::collections::VecDeque;
use std::sync::{Arc, Mutex, Condvar};
use std::thread;

/// TrackLoader type for loading tracks in the background.
pub struct TrackLoader {
    tracklist: Arc<Mutex<VecDeque<Track>>>,
    next: Arc<Mutex<Option<(Track, Audio)>>>,
    fetching: Arc<(Mutex<bool>, Condvar)>,
}

impl TrackLoader {
    /// Creates a new TrackLoader form the given tracklist.
    pub fn new(tracklist: VecDeque<Track>) -> Self {
        let mut track_loader = TrackLoader {
            tracklist: Arc::new(Mutex::new(tracklist)),
            next: Arc::new(Mutex::new(None)),
            fetching: Arc::new((Mutex::new(false), Condvar::new())),
        };
        track_loader.fetch();
        track_loader
    }

    /// Returns the next track and audio, `None` is no more
    /// items available.
    pub fn next(&mut self) -> Option<(Track, Audio)> {
        // Wait until we are done fetching.
        {
            let &(ref lock, ref cvar) = &*self.fetching;
            let mut fetching = lock.lock().unwrap();
            while *fetching {
                fetching = cvar.wait(fetching).unwrap();
            }
        }

        let next = self.next.lock().unwrap().take();
        self.fetch();
        return next;
    }

    /// Fetches the next track in the background.
    fn fetch(&mut self) {
        let tracklist = self.tracklist.clone();
        let next = self.next.clone();
        let pair = self.fetching.clone();

        if tracklist.lock().unwrap().len() > 0 {
            let &(ref lock, ref cvar) = &*self.fetching;
            let mut fetching = lock.lock().unwrap();
            *fetching = true;

            thread::spawn(move || {
                if next.lock().unwrap().is_none() {
                    *next.lock().unwrap() = pop_tracklist(tracklist);
                }
                let &(ref lock, ref cvar) = &*pair;
                let mut fetching = lock.lock().unwrap();
                *fetching = false;
                cvar.notify_one();
            });
        }
    }

}

/// Pops the next track from the tracklist and returns it along
/// with the audio.
fn pop_tracklist(tracklist: Arc<Mutex<VecDeque<Track>>>) -> Option<(Track, Audio)> {
    if let Some((track, audio)) = tracklist.lock().unwrap().pop_front().and_then(|track| {
        track.track_audio.clone().map(|audio| (track, audio))
    }) {
        let audio = match Audio::new(&audio.high_quality.audio_url) {
            Ok(audio) => audio,
            Err(e) => {
                return None;
            }
        };
        return Some((track, audio));
    }
    None
}
<|endoftext|>


<commit_before>use ::Key;
use super::innerptr::{InnerPtr, IntoPtr};
use super::traits::JpmNode;
use ::rudymap::results::InsertResult;
use super::branch_uncompressed::BranchUncompressed;

struct Subexpanse<K: Key, V> {
    pub bitmap: u8,
    // boxes contain 16 words
    pub ptr: Option<Box<[InnerPtr<K, V>; 8]>>
}

impl<K: Key, V> Default for Subexpanse<K, V> {
    fn default() -> Subexpanse<K, V> {
        Subexpanse {
            bitmap: 0,
            ptr: None
        }
    }
}

pub struct BranchBitmap<K: Key, V> {
    subexpanses: [Subexpanse<K, V>; 8]
}

impl<K: Key, V> BranchBitmap<K, V> {
    pub fn new() -> BranchBitmap<K, V> {
        BranchBitmap {
            subexpanses: Default::default()
        }
    }
}

impl<K: Key, V> JpmNode<K, V> for BranchBitmap<K, V> {
    fn get(&self, key: &[u8]) -> Option<&V> {
        unimplemented!()
    }
    fn get_mut(&mut self, key: &[u8]) -> Option<&mut V> {
        unimplemented!()
    }
    fn insert(&mut self, key: &[u8], value: V) -> InsertResult<V> {
        unimplemented!()
    }
    fn expand(self: Box<Self>, pop: usize, key: &[u8], value: V) -> InnerPtr<K, V> {
        unimplemented!()
    }
}
<commit_msg>Implement BranchBitmap<commit_after>use ::Key;
use super::innerptr::{InnerPtr, IntoPtr};
use super::traits::JpmNode;
use ::rudymap::results::InsertResult;
use super::branch_uncompressed::BranchUncompressed;
use std::iter::FromIterator;

struct Subexpanse<K: Key, V> {
    pub bitmap: u32,
    pub ptr: Option<Box<[InnerPtr<K, V>; 32]>>
}

impl<K: Key, V> Default for Subexpanse<K, V> {
    fn default() -> Subexpanse<K, V> {
        Subexpanse {
            bitmap: 0,
            ptr: None
        }
    }
}

impl<K: Key, V> Subexpanse<K, V> {
    fn is_set(&self, sub_byte: u8) -> bool {
        self.bitmap & (1 << sub_byte as u32) != 0
    }

    pub fn get(&self, sub_byte: u8, subkey: &[u8]) -> Option<&V> {
        if self.is_set(sub_byte) {
            self.ptr.as_ref()
                .unwrap()[sub_byte as usize]
                .get(subkey)
        } else {
            None
        }
    }

    pub fn get_mut(&mut self, sub_byte: u8, subkey: &[u8]) -> Option<&mut V> {
        if self.is_set(sub_byte) {
            self.ptr.as_mut()
                .unwrap()[sub_byte as usize]
                .get_mut(subkey)
        } else {
            None
        }
    }

    pub fn insert(&mut self, sub_byte: u8, subkey: &[u8], value: V) -> InsertResult<V> {
        if self.ptr.is_none() {
            self.ptr = Some(Default::default());
        }
        let evicted = self.ptr.as_mut()
            .unwrap()[sub_byte as usize]
            .insert(subkey, value);
        self.bitmap |= 1 << sub_byte as u32;
        InsertResult::Success(evicted)
    }

    pub fn insert_ptr(&mut self, sub_byte: u8, ptr: InnerPtr<K, V>) {
        if self.ptr.is_none() {
            self.ptr = Some(Default::default());
        }
        self.ptr.as_mut().unwrap()[sub_byte as usize] = ptr;
        self.bitmap |= 1 << sub_byte as u32;
    }
}

pub struct BranchBitmap<K: Key, V> {
    subexpanses: [Subexpanse<K, V>; 8]
}

impl<K: Key, V> BranchBitmap<K, V> {
    pub fn new() -> BranchBitmap<K, V> {
        BranchBitmap {
            subexpanses: Default::default()
        }
    }
}

impl<K: Key, V> JpmNode<K, V> for BranchBitmap<K, V> {
    fn get(&self, key: &[u8]) -> Option<&V> {
        let (&byte, subkey) = key.split_first().unwrap();
        self.subexpanses[byte as usize / 32].get(byte % 32, subkey)
    }
    fn get_mut(&mut self, key: &[u8]) -> Option<&mut V> {
        let (&byte, subkey) = key.split_first().unwrap();
        self.subexpanses[byte as usize / 32].get_mut(byte % 32, subkey)
    }
    fn insert(&mut self, key: &[u8], value: V) -> InsertResult<V> {
        let (&byte, subkey) = key.split_first().unwrap();
        self.subexpanses[byte as usize / 32].insert(byte % 32, subkey, value)
    }
    fn expand(self: Box<Self>, pop: usize, key: &[u8], value: V) -> InnerPtr<K, V> {
        unreachable!()
    }
}

impl<K: Key, V> FromIterator<(u8, InnerPtr<K, V>)> for BranchBitmap<K, V> {
    fn from_iter<I>(iter: I) -> BranchBitmap<K, V>
        where I: IntoIterator<Item=(u8, InnerPtr<K, V>)> {
        let mut node = BranchBitmap::new();
        for (k, v) in iter {
            node.subexpanses[k as usize / 32].insert_ptr(k % 32, v);
        }
        node
    }
}
<|endoftext|>