<commit_before>extern crate clap;
extern crate rand;

pub const DEFAULT_ENGLISH_DICTIONARY_PATH: &'static str = "/usr/share/dict/words";

#[derive(Debug)]
pub struct EnglishPasswordOptions {
    pub num_words: u8,
    pub dictionary_path: String,
}

#[derive(Debug)]
pub struct KanaPasswordOptions {
    pub syllable_counts: Vec<u8>,
}

pub enum PasswordOptions {
    English(EnglishPasswordOptions),
    Japanese(KanaPasswordOptions),
}

mod args {
    use super::{
        EnglishPasswordOptions, KanaPasswordOptions, PasswordOptions,
        DEFAULT_ENGLISH_DICTIONARY_PATH,
    };

    // Aborts this process on error.
    pub fn parse_args() -> PasswordOptions {
        let matches = clap::App::new("xkpw")
            .version("0.1.1")
            .author("j39m")
            .about("Generates passwords")
            .subcommand(
                clap::App::new("en")
                    .about("generates dictionary passwords in English")
                    .arg(clap::Arg::new("num-words").required(true)),
            )
            .subcommand(
                clap::App::new("jp")
                    .about("generates random strings of Japanese syllables")
                    .arg(
                        clap::Arg::new("syllable-counts")
                            .required(true)
                            .multiple_values(true),
                    ),
            )
            .get_matches();

        match matches.subcommand() {
            Some(("en", en_matches)) => {
                return PasswordOptions::English(EnglishPasswordOptions {
                    num_words: en_matches
                        .value_of_t::<u8>("num-words")
                        .unwrap_or_else(|e| e.exit()),
                    dictionary_path: DEFAULT_ENGLISH_DICTIONARY_PATH.to_owned(),
                })
            }
            Some(("jp", jp_matches)) => {
                return PasswordOptions::Japanese(KanaPasswordOptions {
                    syllable_counts: jp_matches
                        .values_of_t("syllable-counts")
                        .unwrap_or_else(|e| e.exit()),
                })
            }
            _ => (),
        }
        PasswordOptions::Japanese(KanaPasswordOptions {
            syllable_counts: vec![4, 3, 3, 3],
        })
    }
} // mod args

mod kana {
    #[rustfmt::skip]
    const BASE: &'static [&str] = &[
        "a",    "i",    "u",    "e",    "o",
        "ka",   "ki",   "ku",   "ke",   "ko",
        "sa",   "shi",  "su",   "se",   "so",
        "ta",   "chi",  "tsu",  "te",   "to",
        "na",   "ni",   "nu",   "ne",   "no",
        "ha",   "hi",   "hu",   "he",   "ho",
        "ma",   "mi",   "mu",   "me",   "mo",
        "ya",           "yu",           "yo",
        "ra",   "ri",   "ru",   "re",   "ro",
        "wa",                           "wo",
    ];

    #[rustfmt::skip]
    const DIGRAPHS: &'static [&str] = &[
        "kya", "kyu", "kyo",
        "sha", "shu", "sho",
        "cha", "chu", "cho",
        "nya", "nyu", "nyo",
        "hya", "hyu", "hyo",
        "mya", "myu", "myo",
        "rya", "ryu", "ryo",
    ];

    #[rustfmt::skip]
    const DIACRITICS: &'static [&str] = &[
        "ga", "gi", "gu", "ge", "go",
        "za", "ji", "zu", "ze", "zo",
        "da",             "de", "do",
        "ba", "bi", "bu", "be", "bo",
        "pa", "pi", "pu", "pe", "po",
    ];

    #[rustfmt::skip]
    const DIGRAPHS_WITH_DIACRITICS: &'static [&str] = &[
        "gya",  "gyu",  "gyo",
        "ja",   "ju",   "jo",
        "bya",  "byu",  "byo",
        "pya",  "pyu",  "pyo",
    ];

    fn all() -> Vec<&'static str> {
        let mut all_kana: Vec<&'static str> = Vec::new();
        all_kana.extend(BASE);
        all_kana.extend(DIGRAPHS);
        all_kana.extend(DIACRITICS);
        all_kana.extend(DIGRAPHS_WITH_DIACRITICS);
        all_kana
    }

    fn simple() -> Vec<&'static str> {
        let mut simple_kana: Vec<&'static str> = Vec::new();
        simple_kana.extend(BASE);
        simple_kana.extend(DIACRITICS);
        simple_kana
    }

    pub fn get(use_simple: bool) -> Vec<&'static str> {
        match use_simple {
            true => simple(),
            false => all(),
        }
    }
} // mod kana

mod helpers {
    use super::{EnglishPasswordOptions, KanaPasswordOptions, PasswordOptions};
    use rand::seq::SliceRandom;
    use std::convert::TryInto;
    use std::io::Read;

    // Reads the dictionary at |path| and returns a linewise vector of
    // its contents.
    fn ingest_english_dictionary(path: &std::path::Path) -> std::io::Result<Vec<String>> {
        let mut file = std::fs::File::open(path)?;
        let mut contents = String::new();
        file.read_to_string(&mut contents)?;
        Ok(contents
            .lines()
            .map(|word| word.trim().to_lowercase())
            .collect())
    }

    // Assumes ownership of a Vector of owned |words| and prints them
    // separated by spaces.
    fn print_words(words: Vec<String>) {
        let mut iter = words.into_iter();
        if let Some(word) = iter.next() {
            print!("{}", word);
            for word in iter {
                print!(" {}", word);
            }
            print!("\n");
        }
    }

    // Returns 1 if we fail to read the word dictionary.
    fn print_english_password(options: EnglishPasswordOptions) -> i32 {
        let all_words =
            match ingest_english_dictionary(std::path::Path::new(&options.dictionary_path)) {
                Ok(result) => result,
                Err(error) => {
                    eprintln!("Error reading dictionary: {}", error);
                    return 1;
                }
            };
        let mut rng = &mut rand::thread_rng();
        let selection: Vec<String> = all_words
            .choose_multiple(&mut rng, options.num_words.try_into().unwrap())
            .map(|borrowed| borrowed.to_owned())
            .collect();

        print_words(selection);
        0
    }

    // Builds a single random pseudo-Japanese word from |kana_set|.
    fn build_kana_word(kana_set: &Vec<&'static str>, syllable_count: &u8) -> String {
        let mut collected_kana: Vec<&'static str> = Vec::new();
        let mut rng = &mut rand::thread_rng();
        for _ in 0..*syllable_count {
            collected_kana.push(kana_set.choose(&mut rng).unwrap());
        }
        collected_kana.join("")
    }

    // Builds random pseudo-Japanese words from |kana_set|, observing
    // the word lengths specified by |options|.
    fn build_kana_words(kana_set: Vec<&'static str>, options: KanaPasswordOptions) -> Vec<String> {
        options
            .syllable_counts
            .iter()
            .map(|count| build_kana_word(&kana_set, count))
            .collect()
    }

    // Builds a vector of owned kana words, maps these to a vector of
    // borrowed kana words, and then prints the same.
    fn print_kana_password(options: KanaPasswordOptions) {
        print_words(build_kana_words(crate::kana::get(true), options));
    }

    pub fn main() -> i32 {
        let options = crate::args::parse_args();
        match options {
            PasswordOptions::English(options) => return print_english_password(options),
            PasswordOptions::Japanese(options) => print_kana_password(options),
        }
        0
    }
} // mod helpers

fn main() {
    std::process::exit(crate::helpers::main());
}
<commit_msg>xkpw: Enable "harder" hiragana<commit_after>extern crate clap;
extern crate rand;

pub const DEFAULT_ENGLISH_DICTIONARY_PATH: &'static str = "/usr/share/dict/words";

#[derive(Debug)]
pub struct EnglishPasswordOptions {
    pub num_words: u8,
    pub dictionary_path: String,
}

#[derive(Debug)]
pub struct KanaPasswordOptions {
    pub syllable_counts: Vec<u8>,
    pub use_all_hiragana: bool,
}

pub enum PasswordOptions {
    English(EnglishPasswordOptions),
    Japanese(KanaPasswordOptions),
}

mod args {
    use super::{
        EnglishPasswordOptions, KanaPasswordOptions, PasswordOptions,
        DEFAULT_ENGLISH_DICTIONARY_PATH,
    };

    // Aborts this process on error.
    pub fn parse_args() -> PasswordOptions {
        let matches = clap::App::new("xkpw")
            .version("0.2.1")
            .author("j39m")
            .about("Generates passwords")
            .subcommand(
                clap::App::new("en")
                    .about("generates dictionary passwords in English")
                    .arg(clap::Arg::new("num-words").required(true)),
            )
            .subcommand(
                clap::App::new("jp")
                    .about("generates random strings of Japanese syllables")
                    .arg(clap::Arg::new("use-all-hiragana").short('a').long("harder"))
                    .arg(
                        clap::Arg::new("syllable-counts")
                            .required(true)
                            .short('c')
                            .long("syllable-counts")
                            .takes_value(true)
                            .multiple_values(true),
                    ),
            )
            .get_matches();

        match matches.subcommand() {
            Some(("en", en_matches)) => {
                return PasswordOptions::English(EnglishPasswordOptions {
                    num_words: en_matches
                        .value_of_t::<u8>("num-words")
                        .unwrap_or_else(|e| e.exit()),
                    dictionary_path: DEFAULT_ENGLISH_DICTIONARY_PATH.to_owned(),
                })
            }
            Some(("jp", jp_matches)) => {
                return PasswordOptions::Japanese(KanaPasswordOptions {
                    syllable_counts: jp_matches
                        .values_of_t("syllable-counts")
                        .unwrap_or_else(|e| e.exit()),
                    use_all_hiragana: jp_matches.is_present("use-all-hiragana"),
                })
            }
            _ => (),
        }
        PasswordOptions::Japanese(KanaPasswordOptions {
            syllable_counts: vec![4, 3, 3, 3],
            use_all_hiragana: true,
        })
    }
} // mod args

mod kana {
    #[rustfmt::skip]
    const BASE: &'static [&str] = &[
        "a",    "i",    "u",    "e",    "o",
        "ka",   "ki",   "ku",   "ke",   "ko",
        "sa",   "shi",  "su",   "se",   "so",
        "ta",   "chi",  "tsu",  "te",   "to",
        "na",   "ni",   "nu",   "ne",   "no",
        "ha",   "hi",   "hu",   "he",   "ho",
        "ma",   "mi",   "mu",   "me",   "mo",
        "ya",           "yu",           "yo",
        "ra",   "ri",   "ru",   "re",   "ro",
        "wa",                           "wo",
    ];

    #[rustfmt::skip]
    const DIGRAPHS: &'static [&str] = &[
        "kya", "kyu", "kyo",
        "sha", "shu", "sho",
        "cha", "chu", "cho",
        "nya", "nyu", "nyo",
        "hya", "hyu", "hyo",
        "mya", "myu", "myo",
        "rya", "ryu", "ryo",
    ];

    #[rustfmt::skip]
    const DIACRITICS: &'static [&str] = &[
        "ga", "gi", "gu", "ge", "go",
        "za", "ji", "zu", "ze", "zo",
        "da",             "de", "do",
        "ba", "bi", "bu", "be", "bo",
        "pa", "pi", "pu", "pe", "po",
    ];

    #[rustfmt::skip]
    const DIGRAPHS_WITH_DIACRITICS: &'static [&str] = &[
        "gya",  "gyu",  "gyo",
        "ja",   "ju",   "jo",
        "bya",  "byu",  "byo",
        "pya",  "pyu",  "pyo",
    ];

    fn all() -> Vec<&'static str> {
        let mut all_kana: Vec<&'static str> = Vec::new();
        all_kana.extend(BASE);
        all_kana.extend(DIGRAPHS);
        all_kana.extend(DIACRITICS);
        all_kana.extend(DIGRAPHS_WITH_DIACRITICS);
        all_kana
    }

    fn simple() -> Vec<&'static str> {
        let mut simple_kana: Vec<&'static str> = Vec::new();
        simple_kana.extend(BASE);
        simple_kana.extend(DIACRITICS);
        simple_kana
    }

    pub fn get(use_all_hiragana: bool) -> Vec<&'static str> {
        match use_all_hiragana {
            true => all(),
            false => simple(),
        }
    }
} // mod kana

mod helpers {
    use super::{EnglishPasswordOptions, KanaPasswordOptions, PasswordOptions};
    use rand::seq::SliceRandom;
    use std::convert::TryInto;
    use std::io::Read;

    // Reads the dictionary at |path| and returns a linewise vector of
    // its contents.
    fn ingest_english_dictionary(path: &std::path::Path) -> std::io::Result<Vec<String>> {
        let mut file = std::fs::File::open(path)?;
        let mut contents = String::new();
        file.read_to_string(&mut contents)?;
        Ok(contents
            .lines()
            .map(|word| word.trim().to_lowercase())
            .collect())
    }

    // Assumes ownership of a Vector of owned |words| and prints them
    // separated by spaces.
    fn print_words(words: Vec<String>) {
        let mut iter = words.into_iter();
        if let Some(word) = iter.next() {
            print!("{}", word);
            for word in iter {
                print!(" {}", word);
            }
            print!("\n");
        }
    }

    // Returns 1 if we fail to read the word dictionary.
    fn print_english_password(options: EnglishPasswordOptions) -> i32 {
        let all_words =
            match ingest_english_dictionary(std::path::Path::new(&options.dictionary_path)) {
                Ok(result) => result,
                Err(error) => {
                    eprintln!("Error reading dictionary: {}", error);
                    return 1;
                }
            };
        let mut rng = &mut rand::thread_rng();
        let selection: Vec<String> = all_words
            .choose_multiple(&mut rng, options.num_words.try_into().unwrap())
            .map(|borrowed| borrowed.to_owned())
            .collect();

        print_words(selection);
        0
    }

    // Builds a single random pseudo-Japanese word from |kana_set|.
    fn build_kana_word(kana_set: &Vec<&'static str>, syllable_count: &u8) -> String {
        let mut collected_kana: Vec<&'static str> = Vec::new();
        let mut rng = &mut rand::thread_rng();
        for _ in 0..*syllable_count {
            collected_kana.push(kana_set.choose(&mut rng).unwrap());
        }
        collected_kana.join("")
    }

    // Builds random pseudo-Japanese words from |kana_set|, observing
    // the word lengths specified by |options|.
    fn build_kana_words(kana_set: Vec<&'static str>, options: KanaPasswordOptions) -> Vec<String> {
        options
            .syllable_counts
            .iter()
            .map(|count| build_kana_word(&kana_set, count))
            .collect()
    }

    // Builds a vector of owned kana words, maps these to a vector of
    // borrowed kana words, and then prints the same.
    fn print_kana_password(options: KanaPasswordOptions) {
        print_words(build_kana_words(
            crate::kana::get(options.use_all_hiragana),
            options,
        ));
    }

    pub fn main() -> i32 {
        let options = crate::args::parse_args();
        match options {
            PasswordOptions::English(options) => return print_english_password(options),
            PasswordOptions::Japanese(options) => print_kana_password(options),
        }
        0
    }
} // mod helpers

fn main() {
    std::process::exit(crate::helpers::main());
}
<|endoftext|>


<commit_before>use communication::Data;
use communication::pact::Pipeline;
use construction::{Stream, GraphBuilder};
use construction::operators::unary::UnaryStreamExt;

pub trait InspectExt<D: Data> {
    fn inspect<F: FnMut(&D)+'static>(&self, func: F) -> Self;
    fn inspect_batch<F: FnMut(&G::Timestamp, &[D])+'static>(&self, mut func: F) -> Self;
}

impl<G: GraphBuilder, D: Data> InspectExt<D> for Stream<G, D> {
    fn inspect<F: FnMut(&D)+'static>(&self, mut func: F) -> Stream<G, D> {
        self.unary_stream(Pipeline, "Inspect", move |input, output| {
            while let Some((time, data)) = input.pull() {
                for datum in data.iter() { func(datum); }
                output.session(time).give_message(data);
            }
        })
    }

    fn inspect_batch<F: FnMut(&G::Timestamp, &[D])+'static>(&self, mut func: F) -> Stream<G, D> {
        self.unary_stream(Pipeline, "Inspect", move |input, output| {
            while let Some((time, data)) = input.pull() {
                func(&time, &data[..]);
                output.session(time).give_message(data);
            }
        })
    }
}
<commit_msg>correct generic params for unified trait<commit_after>use communication::Data;
use communication::pact::Pipeline;
use construction::{Stream, GraphBuilder};
use construction::operators::unary::UnaryStreamExt;

pub trait InspectExt<G: GraphBuilder, D: Data> {
    fn inspect<F: FnMut(&D)+'static>(&self, func: F) -> Self;
    fn inspect_batch<F: FnMut(&G::Timestamp, &[D])+'static>(&self, mut func: F) -> Self;
}

impl<G: GraphBuilder, D: Data> InspectExt<G, D> for Stream<G, D> {
    fn inspect<F: FnMut(&D)+'static>(&self, mut func: F) -> Stream<G, D> {
        self.unary_stream(Pipeline, "Inspect", move |input, output| {
            while let Some((time, data)) = input.pull() {
                for datum in data.iter() { func(datum); }
                output.session(time).give_message(data);
            }
        })
    }

    fn inspect_batch<F: FnMut(&G::Timestamp, &[D])+'static>(&self, mut func: F) -> Stream<G, D> {
        self.unary_stream(Pipeline, "InspectBatch", move |input, output| {
            while let Some((time, data)) = input.pull() {
                func(&time, &data[..]);
                output.session(time).give_message(data);
            }
        })
    }
}
<|endoftext|>


<commit_before>use std::io::Read;
use std::env;
use hyper::Client;
use hyper::header::Connection;
use rustc_serialize::json;
use rustc_serialize::json::{DecodeResult};
use std::fs::File;

static BASE_URL: &'static str = "https://api.soundcloud.com";
lazy_static! {
    static ref API_KEY: String = {
        let opt_key = env::var("SOUNDCLOUD_API_KEY");
        match opt_key {
            Ok(key) => key,
            Err(_) => {
                let mut f = File::open("soundcloud.txt").unwrap();
                let mut s = String::new();
                let _ = f.read_to_string(&mut s);
                s
            }
        }
    };
}

#[derive(Debug, RustcDecodable, RustcEncodable)]
pub struct Playlist {
    pub id:            i32,
    pub created_at:    String,
    pub user_id:       i32,
    pub title:         String,
    pub permalink:     String,
    pub permalink_url: String,
    pub artwork_url:   Option<String>,
    pub tracks:        Vec<Track>,
}

#[derive(Debug, RustcDecodable, RustcEncodable)]
pub struct Track {
    pub id:            i32,
    pub created_at:    String,
    pub user_id:       i32,
    pub title:         String,
    pub description:   String,
    pub artist:        Option<String>,
    pub permalink:     String,
    pub permalink_url: String,
    pub uri:           String,
    pub artwork_url:   Option<String>,
    pub duration:      i32,
    pub stream_url:    String,
}

pub fn fetch_track(id: &str) -> DecodeResult<Track> {
    let params = format!("client_id={}", *API_KEY);
    let url    = format!("{}/tracks/{}?{}", BASE_URL, id, params);
    let client = Client::new();
    let mut res = client.get(&url)
                        .header(Connection::close())
                        .send().unwrap();
    let mut body = String::new();
    res.read_to_string(&mut body).unwrap();
    return json::decode::<Track>(&body)
}

pub fn fetch_playlist(id: &str) -> DecodeResult<Playlist> {
    let params = format!("client_id={}", *API_KEY);
    let url    = format!("{}/playlists/{}?{}", BASE_URL, id, params);
    let client = Client::new();
    let mut res = client.get(&url)
                        .header(Connection::close())
                        .send().unwrap();
    let mut body = String::new();
    res.read_to_string(&mut body).unwrap();
    return  json::decode::<Playlist>(&body)
}

pub fn fetch_user_tracks(id: &str) -> DecodeResult<Vec<Track>> {
    let params = format!("client_id={}", *API_KEY);
    let url    = format!("{}/users/{}/tracks?{}", BASE_URL, id, params);
    println!("{}", url);
    let client = Client::new();
    let mut res = client.get(&url)
                        .header(Connection::close())
                        .send().unwrap();
    let mut body = String::new();
    res.read_to_string(&mut body).unwrap();
    return  json::decode::<Vec<Track>>(&body)
}

<commit_msg>Parse soundcloud user object in soundcloud track api response<commit_after>use std::io::Read;
use std::env;
use hyper::Client;
use hyper::header::Connection;
use rustc_serialize::json;
use rustc_serialize::json::{DecodeResult};
use std::fs::File;

static BASE_URL: &'static str = "https://api.soundcloud.com";
lazy_static! {
    static ref API_KEY: String = {
        let opt_key = env::var("SOUNDCLOUD_API_KEY");
        match opt_key {
            Ok(key) => key,
            Err(_) => {
                let mut f = File::open("soundcloud.txt").unwrap();
                let mut s = String::new();
                let _ = f.read_to_string(&mut s);
                s
            }
        }
    };
}

#[derive(Debug, RustcDecodable, RustcEncodable)]
pub struct Playlist {
    pub id:            i32,
    pub created_at:    String,
    pub user_id:       i32,
    pub title:         String,
    pub permalink:     String,
    pub permalink_url: String,
    pub artwork_url:   Option<String>,
    pub tracks:        Vec<Track>,
}

#[derive(Debug, RustcDecodable, RustcEncodable)]
pub struct Track {
    pub id:            i32,
    pub created_at:    String,
    pub title:         String,
    pub description:   String,
    pub user_id:       i32,
    pub user:          User,
    pub permalink:     String,
    pub permalink_url: String,
    pub uri:           String,
    pub artwork_url:   Option<String>,
    pub duration:      i32,
    pub stream_url:    String,
}

#[derive(Debug, RustcDecodable, RustcEncodable)]
pub struct User {
    pub id:            i32,
    pub username:      String,
    pub permalink:     String,
    pub uri:           String,
    pub permalink_url: String,
    pub avatar_url:    String,
}

pub fn fetch_track(id: &str) -> DecodeResult<Track> {
    let params = format!("client_id={}", *API_KEY);
    let url    = format!("{}/tracks/{}?{}", BASE_URL, id, params);
    let client = Client::new();
    let mut res = client.get(&url)
                        .header(Connection::close())
                        .send().unwrap();
    let mut body = String::new();
    res.read_to_string(&mut body).unwrap();
    return json::decode::<Track>(&body)
}

pub fn fetch_playlist(id: &str) -> DecodeResult<Playlist> {
    let params = format!("client_id={}", *API_KEY);
    let url    = format!("{}/playlists/{}?{}", BASE_URL, id, params);
    let client = Client::new();
    let mut res = client.get(&url)
                        .header(Connection::close())
                        .send().unwrap();
    let mut body = String::new();
    res.read_to_string(&mut body).unwrap();
    return  json::decode::<Playlist>(&body)
}

pub fn fetch_user_tracks(id: &str) -> DecodeResult<Vec<Track>> {
    let params = format!("client_id={}", *API_KEY);
    let url    = format!("{}/users/{}/tracks?{}", BASE_URL, id, params);
    let client = Client::new();
    let mut res = client.get(&url)
                        .header(Connection::close())
                        .send().unwrap();
    let mut body = String::new();
    res.read_to_string(&mut body).unwrap();
    return  json::decode::<Vec<Track>>(&body)
}

<|endoftext|>


<commit_before>#[macro_use]
extern crate log;

extern crate abstract_ns;
extern crate futures;
extern crate getopts;
extern crate ns_dns_tokio;
extern crate rand;
extern crate tokio_core;
extern crate tokio_io;

// the device under test
extern crate net_interceptor;

use abstract_ns::Resolver;
use futures::{Future, Map, Stream, Async, Poll};
use futures::future;
use futures::sync::oneshot;
use futures::sync::oneshot::{Sender};
use ns_dns_tokio::DnsResolver;
use tokio_core::net::{TcpStream, TcpListener};
use tokio_core::reactor::{Core, Handle};
use tokio_io::{AsyncRead, io};

use std::net::{IpAddr, Ipv4Addr, SocketAddr};
use std::fmt::{Debug, Display};
use std::time::{Duration};

use std::io::Error;

use net_interceptor::logging::unittestlogger;

fn add_ten<F>(future: F) -> Map<F, fn(i32) -> i32>
    where F: Future<Item=i32>,
{
    error!("shutdown");
    fn add(a: i32) -> i32 { a + 10 }
    future.map(add)
}

pub struct AbortCondition {
    condition: bool,
    reactor_handle: futures::task::Task,
}

#[derive(Copy, Clone)]
pub struct Releaser {
    block: *const AbortCondition
}

impl AbortCondition {

    fn set(&mut self) {
        debug!("abort condition met");
        self.condition = true;
        self.reactor_handle.unpark();
    }

}

impl Future for AbortCondition {

    type Item = ();
    type Error = Error;

    fn poll(&mut self) -> Poll<(), Error> {
        if  self.condition {
            Ok(Async::Ready(()))
        } else {
            self.reactor_handle = futures::task::park();
            Ok(Async::NotReady)
        }
    }

}
/*
#[derive(Clone)]
pub struct Stopper {
    signal: futures::sync::oneshot::Sender<i64>,
}

impl Stopper {

    pub fn stop(&mut self) {
        self.signal = 1;
    }

}
*/

/*impl Copy for Abort {
    fn clone(&self) -> Abort {
        *self
    }
}
*/
// Here we'll express the handling of `client` and return it as a future
// to be spawned onto the event loop.
/*fn process(client: TcpStream) -> Box<Future<Item = (i64), Error = error>> {
    warn!("received");
    Box::new(futures::future::ok(0));
}
*/
#[test]
fn test_infra_connect() {
    unittestlogger();

    // this is the main event loop, powered by tokio core
    let mut core = Core::new().unwrap();
    let handle = core.handle();

    let bind_socket_addr = SocketAddr::new(IpAddr::V4(Ipv4Addr::new(127, 0, 0, 1)), 12000);
    let listener = TcpListener::bind(&bind_socket_addr, &handle)
        .expect(&format!("Unable to bind to {}", &bind_socket_addr));
    warn!("Listening on {}", listener.local_addr().unwrap());

    let addr = listener.local_addr().unwrap();
    assert!(addr.port() == 12000, "should accept {}");

    let mut abort = AbortCondition { condition: false, reactor_handle: futures::task::park() };

    let connections = listener.incoming();
    let (tx, stop) = oneshot::channel();

//    let mut stopper = Stopper { signal: tx };
    let server = connections.for_each(move |(socket, _peer_addr)| {
        warn!("connection received");
        /*let (writer, reader) = socket.framed(LineCodec).split();
        let service = s.new_service()?;

        let responses = reader.and_then(move |req| service.call(req));
        let server = writer.send_all(responses)
            .then(|_| Ok(()));
        handle.spawn(server);
        */
//        tx.send(1);
        tx.send(1).unwrap();
        abort.set();
        Ok(())
    });

    core.handle().spawn(server.map_err(|_|()));

    fn abortCondition() -> futures::Poll<(), std::io::Error> {
        warn!("poll");
        if true {
            Ok(Async::Ready(()))
        }
        else {
            futures::task::park().unpark();
            Ok(Async::NotReady)
        }
    }

    //let abort = futures::future::poll_fn(abortCondition);

    //let timeout = tokio_core::reactor::Timeout::new_at(std::time::Duration::seconds(1));
    // run server, stop on panic
//    core.run(server.select2(timeout)).unwrap();
//    core.run(abort).unwrap();
    // core.spawn(server);
//    core.run(server.select(abort)).unwrap();
    core.run(stop).unwrap();
}
<commit_msg>broken!<commit_after>#[macro_use]
extern crate log;

extern crate abstract_ns;
extern crate futures;
extern crate getopts;
extern crate ns_dns_tokio;
extern crate rand;
extern crate tokio_core;
extern crate tokio_io;

// the device under test
extern crate net_interceptor;

use abstract_ns::Resolver;
use futures::{Future, Map, Stream, Async, Poll};
use futures::future;
use futures::sync::oneshot;
use futures::sync::oneshot::{Sender};
use ns_dns_tokio::DnsResolver;
use tokio_core::net::{TcpStream, TcpListener};
use tokio_core::reactor::{Core, Handle};
use tokio_io::{AsyncRead, io};

use std::net::{IpAddr, Ipv4Addr, SocketAddr};
use std::fmt::{Debug, Display};
use std::time::{Duration};

use std::io::Error;

use net_interceptor::logging::unittestlogger;

fn add_ten<F>(future: F) -> Map<F, fn(i32) -> i32>
    where F: Future<Item=i32>,
{
    error!("shutdown");
    fn add(a: i32) -> i32 { a + 10 }
    future.map(add)
}

pub struct AbortCondition {
    condition: bool,
    reactor_handle: futures::task::Task,
}

#[derive(Copy, Clone)]
pub struct Releaser {
    block: *const AbortCondition
}

impl AbortCondition {

    fn set(&mut self) {
        debug!("abort condition met");
        self.condition = true;
        self.reactor_handle.unpark();
    }

}

impl Future for AbortCondition {

    type Item = ();
    type Error = Error;

    fn poll(&mut self) -> Poll<(), Error> {
        if  self.condition {
            Ok(Async::Ready(()))
        } else {
            self.reactor_handle = futures::task::park();
            Ok(Async::NotReady)
        }
    }

}
/*
#[derive(Clone)]
pub struct Stopper {
    signal: futures::sync::oneshot::Sender<i64>,
}

impl Stopper {

    pub fn stop(&mut self) {
        self.signal = 1;
    }

}
*/

/*impl Copy for Abort {
    fn clone(&self) -> Abort {
        *self
    }
}
*/
// Here we'll express the handling of `client` and return it as a future
// to be spawned onto the event loop.
/*fn process(client: TcpStream) -> Box<Future<Item = (i64), Error = error>> {
    warn!("received");
    Box::new(futures::future::ok(0));
}
*/
#[test]
fn test_infra_connect() {
    unittestlogger();

    // this is the main event loop, powered by tokio core
    let mut core = Core::new().unwrap();
    let handle = core.handle();

    let bind_socket_addr = SocketAddr::new(IpAddr::V4(Ipv4Addr::new(127, 0, 0, 1)), 12000);
    let listener = TcpListener::bind(&bind_socket_addr, &handle)
        .expect(&format!("Unable to bind to {}", &bind_socket_addr));
    warn!("Listening on {}", listener.local_addr().unwrap());

    let addr = listener.local_addr().unwrap();
    assert!(addr.port() == 12000, "should accept {}");

//    let mut abort = AbortCondition { condition: false, reactor_handle: futures::task::park() };

    let connections = listener.incoming();
    let (tx, stop) = oneshot::channel();
//    let mut stopper = Stopper { signal: tx };
    let server = connections.for_each(move |(socket, _peer_addr)| {
        warn!("connection received");
        /*let (writer, reader) = socket.framed(LineCodec).split();
        let service = s.new_service()?;

        let responses = reader.and_then(move |req| service.call(req));
        let server = writer.send_all(responses)
            .then(|_| Ok(()));
        handle.spawn(server);
        */
//        tx.send(1);
//        tx.send(1).unwrap();
//        abort.set();
        Ok(())
    });

    core.handle().spawn(server.map_err(|_|()));

    fn abortCondition() -> futures::Poll<(), std::io::Error> {
        warn!("poll");
        if true {
            Ok(Async::Ready(()))
        }
        else {
            futures::task::park().unpark();
            Ok(Async::NotReady)
        }
    }

    //let abort = futures::future::poll_fn(abortCondition);

    //let timeout = tokio_core::reactor::Timeout::new_at(std::time::Duration::seconds(1));
    // run server, stop on panic
//    core.run(server.select2(timeout)).unwrap();
//    core.run(abort).unwrap();
    // core.spawn(server);
//    core.run(server.select(abort)).unwrap();
    core.run(stop).unwrap();

    // dummy
    tx.send(1);
}
<|endoftext|>


<commit_before>use std::collections::HashMap;
use std::slice::Iter;

use stopwatch::Stopwatch;

#[derive(Copy, Clone, Debug, Eq, Hash, PartialEq)]
pub enum SWType {
    Empty,
    Total,
    Loading,
    Generating,
}

impl SWType {
    pub fn iterator() -> Iter<'static, SWType> {
        use self::SWType::*;
        static ITEMS: [SWType;  3] = [
            Total,
            Loading,
            Generating,
        ];
        ITEMS.into_iter()
    }
}

impl Default for SWType {
    fn default() -> SWType {
        SWType::Empty
    }
}

#[derive(Default)]
pub struct Statistics {
    stopwatches:  HashMap<SWType, Stopwatch>,
}

impl Statistics {
    pub fn new() -> Statistics {
        Default::default()
    }

    pub fn start(&mut self, typ: SWType) {
        let mut sw = self.stopwatches.entry(typ).or_insert(Default::default());
        sw.start();
    }

    pub fn stop(&mut self, typ: SWType) {
        let mut sw = self.stopwatches.entry(typ).or_insert(Default::default());
        sw.stop();
    }

    pub fn print(&mut self) {
        for typ in SWType::iterator() {
            let sw = self.stopwatches.entry(*typ).or_insert(Default::default());
            let elapsed = sw.elapsed();
            let elapsed_ms = sw.elapsed_ms();
            let typ_str = format!("{:?}", typ);
            let elapsed_str = format!("{}", elapsed);
            let elapsed_ms_str = format!("{}", elapsed_ms);
            println!("{:20} {:>20} {:>20}", typ_str, elapsed_str, elapsed_ms_str);
        }
    }
}
<commit_msg>Fixed enum iterator<commit_after>use std::collections::HashMap;
use std::slice::Iter;

use stopwatch::Stopwatch;

macro_rules! iterated_enum {
    ($name: ident ; $num: expr => [ $($thing: ident),* ] ) => {
        #[derive(Copy, Clone, Debug, Eq, Hash, PartialEq)]
        pub enum $name {
            $($thing),*
        }

        impl $name {
            fn iter() -> Iter<'static, $name> {
                use self::$name::*;
                static THINGS: [$name; $num] = [ $($thing),* ];
                THINGS.into_iter()
            }
        }
    }
}

iterated_enum! {
    SWType ; 3 => [
        Total,
        Loading,
        Generating
    ]
}

#[derive(Default)]
pub struct Statistics {
    stopwatches:  HashMap<SWType, Stopwatch>,
}

impl Statistics {
    pub fn new() -> Statistics {
        Default::default()
    }

    pub fn start(&mut self, typ: SWType) {
        let mut sw = self.stopwatches.entry(typ).or_insert(Default::default());
        sw.start();
    }

    pub fn stop(&mut self, typ: SWType) {
        let mut sw = self.stopwatches.entry(typ).or_insert(Default::default());
        sw.stop();
    }

    pub fn print(&mut self) {
        for typ in SWType::iter() {
            let sw = self.stopwatches.entry(*typ).or_insert(Default::default());
            let elapsed = sw.elapsed();
            let elapsed_ms = sw.elapsed_ms();
            let typ_str = format!("{:?}", typ);
            let elapsed_str = format!("{}", elapsed);
            let elapsed_ms_str = format!("{}", elapsed_ms);
            println!("{:20} {:>20} {:>20}", typ_str, elapsed_str, elapsed_ms_str);
        }
    }
}
<|endoftext|>


<commit_before>use cgmath::{Point3, Vector3, EuclideanVector};

mod voxel {
  pub use super::super::super::*;
}

#[derive(Debug, Clone, Copy)]
pub struct T {
  pub low: Point3<f32>,
  pub high: Point3<f32>,
}

unsafe impl Send for T {}

impl ::voxel::field::T for T {
  fn density_at(this: &Self, p: &Point3<f32>) -> f32 {
    (p.x - this.low.x) * (this.high.x - p.x) *
    (p.y - this.low.y) * (this.high.y - p.y) *
    (p.z - this.low.z) * (this.high.z - p.z) *
    1.0
  }

  fn contains(this: &Self, p: &Point3<f32>) -> bool {
    this.low.x <= p.x && p.x <= this.high.x &&
    this.low.y <= p.y && p.y <= this.high.y &&
    this.low.z <= p.z && p.z <= this.high.z &&
    true
  }

  fn normal_at(_: &Self, _: f32, _: &Point3<f32>) -> Vector3<f32> {
    unimplemented!();
  }
}

/// Whether a line segment contains another segment.
enum SegmentOverlap {
  FirstContainsSecond,
  SecondContainsFirst,
  /// The segments each contain one of the other's ends.
  Partial(f32, f32),
  /// The segments do not overlap.
  None,
}

impl SegmentOverlap {
  pub fn of(x00: f32, x01: f32, x10: f32, x11: f32) -> SegmentOverlap {
    assert!(x00 < x01);
    assert!(x10 < x11);

    if x00 <= x10 {
      if x01 < x11 {
        if x01 <= x10 {
          SegmentOverlap::None
        } else {
          SegmentOverlap::Partial(x01, x10)
        }
      } else {
        SegmentOverlap::FirstContainsSecond
      }
    } else {
      if x01 < x11 {
        SegmentOverlap::SecondContainsFirst
      } else {
        if x11 <= x00 {
          SegmentOverlap::None
        } else {
          SegmentOverlap::Partial(x00, x11)
        }
      }
    }
  }
}

impl voxel::brush::T for T {
  fn intersect(this: &Self, voxel: &::voxel::Bounds) -> voxel::brush::Intersection {
    let (low, high) = voxel.corners();

    let mut touches_surface = false;

    macro_rules! in1D(($d:ident) => {{
      match SegmentOverlap::of(low.$d, high.$d, this.low.$d, this.high.$d) {
        SegmentOverlap::None => {
          return voxel::brush::Intersection::Outside
        },
        SegmentOverlap::FirstContainsSecond => {
          panic!("FirstContainsSecond");
        },
        SegmentOverlap::SecondContainsFirst => {
          // Put a point in the middle of the voxel.
          ((low.$d + high.$d) / 2.0, 0.0)
        },
        SegmentOverlap::Partial(_, surface_point) => {
          touches_surface = true;
          if surface_point == this.low.$d {
            (surface_point, 1.0)
          } else {
            (surface_point, -1.0)
          }
        },
      }
    }});

    let (x, nx) = in1D!(x);
    let (y, ny) = in1D!(y);
    let (z, nz) = in1D!(z);

    if !touches_surface {
      return super::Intersection::Inside;
    }

    let vtx = voxel::Vertex::of_world_vertex_in(&Point3::new(x, y, z), voxel);
    let normal = voxel::Normal::of_float_normal(&Vector3::new(nx, ny, nz).normalize());

    super::Intersection::Crosses(vtx, normal)
  }
}
<commit_msg>Fix brush normals<commit_after>use cgmath::{Point3, Vector3, EuclideanVector};

mod voxel {
  pub use super::super::super::*;
}

#[derive(Debug, Clone, Copy)]
pub struct T {
  pub low: Point3<f32>,
  pub high: Point3<f32>,
}

unsafe impl Send for T {}

impl ::voxel::field::T for T {
  fn density_at(this: &Self, p: &Point3<f32>) -> f32 {
    (p.x - this.low.x) * (this.high.x - p.x) *
    (p.y - this.low.y) * (this.high.y - p.y) *
    (p.z - this.low.z) * (this.high.z - p.z) *
    1.0
  }

  fn contains(this: &Self, p: &Point3<f32>) -> bool {
    this.low.x <= p.x && p.x <= this.high.x &&
    this.low.y <= p.y && p.y <= this.high.y &&
    this.low.z <= p.z && p.z <= this.high.z &&
    true
  }

  fn normal_at(_: &Self, _: f32, _: &Point3<f32>) -> Vector3<f32> {
    unimplemented!();
  }
}

/// Whether a line segment contains another segment.
enum SegmentOverlap {
  FirstContainsSecond,
  SecondContainsFirst,
  /// The segments each contain one of the other's ends.
  Partial(f32, f32),
  /// The segments do not overlap.
  None,
}

impl SegmentOverlap {
  pub fn of(x00: f32, x01: f32, x10: f32, x11: f32) -> SegmentOverlap {
    assert!(x00 < x01);
    assert!(x10 < x11);

    if x00 <= x10 {
      if x01 < x11 {
        if x01 <= x10 {
          SegmentOverlap::None
        } else {
          SegmentOverlap::Partial(x01, x10)
        }
      } else {
        SegmentOverlap::FirstContainsSecond
      }
    } else {
      if x01 < x11 {
        SegmentOverlap::SecondContainsFirst
      } else {
        if x11 <= x00 {
          SegmentOverlap::None
        } else {
          SegmentOverlap::Partial(x00, x11)
        }
      }
    }
  }
}

impl voxel::brush::T for T {
  fn intersect(this: &Self, voxel: &::voxel::Bounds) -> voxel::brush::Intersection {
    let (low, high) = voxel.corners();

    let mut touches_surface = false;

    macro_rules! in1D(($d:ident) => {{
      match SegmentOverlap::of(low.$d, high.$d, this.low.$d, this.high.$d) {
        SegmentOverlap::None => {
          return voxel::brush::Intersection::Outside
        },
        SegmentOverlap::FirstContainsSecond => {
          panic!("FirstContainsSecond");
        },
        SegmentOverlap::SecondContainsFirst => {
          // Put a point in the middle of the voxel.
          ((low.$d + high.$d) / 2.0, 0.0)
        },
        SegmentOverlap::Partial(_, surface_point) => {
          touches_surface = true;
          if surface_point == this.low.$d {
            (surface_point, -1.0)
          } else if surface_point == this.high.$d {
            (surface_point, 1.0)
          } else {
            panic!("SegmentOverlap::Partial matches no inputs");
          }
        },
      }
    }});

    let (x, nx) = in1D!(x);
    let (y, ny) = in1D!(y);
    let (z, nz) = in1D!(z);

    if !touches_surface {
      return super::Intersection::Inside;
    }

    let vtx = Point3::new(x, y, z);
    let normal = Vector3::new(nx, ny, nz);

    let vtx = voxel::Vertex::of_world_vertex_in(&vtx, voxel);
    let normal = voxel::Normal::of_float_normal(&normal.normalize());

    super::Intersection::Crosses(vtx, normal)
  }
}
<|endoftext|>


<commit_before>use im::HashMap;
use itertools::Itertools;

use crate::{
    builtin_functions::BuiltinFunction,
    compiler::hir::{self, Expression},
    discover::run::run_call,
    input::Input,
};

use super::{
    result::DiscoverResult,
    run::Discover,
    value::{Environment, Value},
};

pub fn run_builtin_function(
    db: &dyn Discover,
    builtin_function: BuiltinFunction,
    arguments: Vec<hir::Id>,
    environment: Environment,
) -> DiscoverResult {
    log::trace!(
        "run_builtin_function: builtin{:?} {}",
        builtin_function,
        arguments.iter().join(" ")
    );
    // Handle builtin functions that don't need to resolve the arguments.
    match builtin_function {
        BuiltinFunction::IfElse => return if_else(db, arguments, environment),
        _ => {}
    }

    let arguments = arguments
        .iter()
        .map(|it| environment.get(it).transitive())
        .collect::<DiscoverResult<_>>()?;
    match builtin_function {
        BuiltinFunction::Add => add(arguments),
        BuiltinFunction::Equals => equals(arguments),
        BuiltinFunction::GetArgumentCount => get_argument_count(db, arguments),
        BuiltinFunction::Panic => panic(arguments),
        BuiltinFunction::Print => print(arguments),
        BuiltinFunction::StructGet => struct_get(arguments),
        BuiltinFunction::StructGetKeys => struct_get_keys(arguments),
        BuiltinFunction::StructHasKey => struct_has_key(arguments),
        BuiltinFunction::TypeOf => type_of(arguments),
        BuiltinFunction::Use => use_(db, arguments),
        _ => panic!("Unhandled builtin function: {:?}", builtin_function),
    }
}

macro_rules! destructure {
    ($arguments:expr, $enum:pat, $body:block) => {{
        if let $enum = &$arguments[..] {
            $body
        } else {
            DiscoverResult::panic(format!("Invalid arguments").to_owned())
        }
    }};
}

fn add(arguments: Vec<Value>) -> DiscoverResult {
    destructure!(arguments, [Value::Int(a), Value::Int(b)], {
        Value::Int(a + b).into()
    })
}

fn equals(arguments: Vec<Value>) -> DiscoverResult {
    destructure!(arguments, [a, b], { Value::bool(a == b).into() })
}

fn get_argument_count(db: &dyn Discover, arguments: Vec<Value>) -> DiscoverResult {
    destructure!(arguments, [Value::Lambda(function)], {
        // TODO: support parameter counts > 2^64 on 128-bit systems and better
        let expression = match db.find_expression(function.id.to_owned()).unwrap() {
            Expression::Lambda(lambda) => lambda,
            _ => panic!("Lambda's function"),
        };
        Value::Int(expression.parameters.len() as u64).into()
    })
}

fn if_else(db: &dyn Discover, arguments: Vec<hir::Id>, environment: Environment) -> DiscoverResult {
    if let [condition, then, else_] = &arguments[..] {
        let body_id = match environment.get(condition)? {
            value if value == Value::bool(true) => then,
            value if value == Value::bool(false) => else_,
            value => {
                return DiscoverResult::panic(format!(
                    "Condition must be a boolean, but was {:?}.",
                    value
                ));
            }
        };

        run_call(db, body_id.to_owned(), vec![], environment)
    } else {
        DiscoverResult::panic(format!(
            "Builtin if/else called with wrong number of arguments: {}, expected: {}",
            arguments.len(),
            3
        ))
    }
}

fn panic(arguments: Vec<Value>) -> DiscoverResult {
    destructure!(arguments, [value], { DiscoverResult::Panic(value.clone()) })
}

fn print(arguments: Vec<Value>) -> DiscoverResult {
    destructure!(arguments, [value], {
        println!("{:?}", value);
        Value::nothing().into()
    })
}

fn struct_get(arguments: Vec<Value>) -> DiscoverResult {
    destructure!(arguments, [struct_, key], {
        let struct_ = expect_struct("builtinStructGet".to_owned(), struct_)?;
        struct_
            .get(key)
            .map(|value| value.clone().into())
            .unwrap_or_else(|| {
                DiscoverResult::panic(format!("Struct does not contain key {:?}", key))
            })
    })
}
fn struct_get_keys(arguments: Vec<Value>) -> DiscoverResult {
    destructure!(arguments, [struct_], {
        let struct_ = expect_struct("builtinStructGetKeys".to_owned(), struct_)?;
        Value::list(struct_.keys().cloned().collect()).into()
    })
}
fn struct_has_key(arguments: Vec<Value>) -> DiscoverResult {
    destructure!(arguments, [struct_, key], {
        let struct_ = expect_struct("builtinStructHasKey".to_owned(), struct_)?;
        Value::bool(struct_.contains_key(key)).into()
    })
}
fn expect_struct(function_name: String, value: &Value) -> DiscoverResult<&HashMap<Value, Value>> {
    match value {
        Value::Struct(struct_) => struct_.into(),
        _ => {
            return DiscoverResult::panic(format!(
                "`{}` expected a struct as its first parameter, but received: {:?}",
                function_name, value
            ))
        }
    }
}

fn type_of(arguments: Vec<Value>) -> DiscoverResult {
    destructure!(arguments, [value], {
        match value {
            Value::Int(_) => Value::Symbol("Int".to_owned()).into(),
            Value::Text(_) => Value::Symbol("Text".to_owned()).into(),
            Value::Symbol(_) => Value::Symbol("Symbol".to_owned()).into(),
            Value::Struct(_) => Value::Symbol("Struct".to_owned()).into(),
            Value::Lambda(_) => Value::Symbol("Function".to_owned()).into(),
        }
    })
}

fn use_(db: &dyn Discover, arguments: Vec<Value>) -> DiscoverResult {
    destructure!(arguments, [current_path, target], {
        // `current_path` is set by us and not users, hence we don't have to validate it that strictly.
        let current_path_struct = match current_path {
            Value::Struct(value) => value,
            _ => unreachable!(),
        };
        let mut current_path = vec![];
        let mut index = 0;
        loop {
            if let Some(component) = current_path_struct.get(&Value::Int(index)) {
                match component {
                    Value::Text(component) => current_path.push(component.clone()),
                    _ => unreachable!(),
                }
            } else {
                break;
            }
            index += 1;
        }

        let target = match target {
            Value::Text(value) => value,
            it => {
                return DiscoverResult::panic(format!(
                    "`use` expected a text as its second parameter, but received: {:?}",
                    it
                ))
            }
        };
        let target = match UseTarget::parse(target) {
            Ok(target) => target,
            Err(error) => return DiscoverResult::panic(error),
        };

        if target.parent_navigations > current_path.len() {
            return DiscoverResult::panic("Too many parent navigations.".to_owned());
        }

        let inputs = target.resolve(&current_path[..]);
        let input = match inputs
            .iter()
            .filter(|&it| db.get_input(it.to_owned()).is_some())
            .next()
        {
            Some(target) => target,
            None => {
                return DiscoverResult::panic(format!(
                    "Target doesn't exist. Checked the following path(s): {}",
                    inputs.iter().map(|it| format!("{}", it)).join(", ")
                ));
            }
        };

        let (hir, _) = db.hir(input.clone()).unwrap();
        let discover_result = db.run_all(input.to_owned());

        hir.identifiers
            .iter()
            .map(|(id, key)| {
                let mut key = key.to_owned();
                key.get_mut(0..1).unwrap().make_ascii_uppercase();
                let key = Value::Symbol(key.to_owned());

                let value = match discover_result.get(id) {
                    Some(value) => value.to_owned()?,
                    None => return DiscoverResult::ErrorInHir,
                };

                DiscoverResult::Value((key, value))
            })
            .collect::<DiscoverResult<HashMap<Value, Value>>>()
            .map(|it| Value::Struct(it))
    })
}
struct UseTarget {
    parent_navigations: usize,
    path: Vec<String>,
}
impl UseTarget {
    const PARENT_NAVIGATION_CHAR: char = '.';

    fn parse(target: &str) -> Result<Self, String> {
        let mut parent_navigations = 0;
        let mut target = target;
        while target.chars().next() == Some(UseTarget::PARENT_NAVIGATION_CHAR) {
            parent_navigations += 1;
            target = &target[UseTarget::PARENT_NAVIGATION_CHAR.len_utf8()..];
        }

        let mut path = vec![];
        loop {
            let mut chars = vec![];
            while let Some(c) = target.chars().next() {
                if c == UseTarget::PARENT_NAVIGATION_CHAR {
                    break;
                }
                chars.push(c);
                target = &target[c.len_utf8()..];
            }

            if target.is_empty() {
                path.push(chars.into_iter().join(""));
                break;
            }

            if chars.is_empty() {
                return Err("Target contains consecutive dots (`.`) in the path.".to_owned());
            }

            path.push(chars.into_iter().join(""));
        }
        Ok(UseTarget {
            parent_navigations,
            path,
        })
    }

    fn resolve(&self, current_path: &[String]) -> Vec<Input> {
        let mut path = current_path.to_owned();
        if self.parent_navigations == 0 {
            assert!(!path.is_empty());
            let last = path.last_mut().unwrap();
            if last == ".candy" {
                path.pop();
            } else {
                *last = last
                    .strip_suffix(".candy")
                    .expect("File name must end with `.candy`.")
                    .to_owned();
            }
        } else {
            for _ in 0..self.parent_navigations {
                if path.is_empty() {
                    return vec![];
                }
                path.pop();
            }
        }

        for part in &self.path {
            path.push(part.to_owned());
        }

        let mut result = vec![];

        let mut subdirectory = path.clone();
        subdirectory.push(".candy".to_owned());
        result.push(Input::File(subdirectory));

        if path.len() >= 1 {
            let last = path.last_mut().unwrap();
            *last = format!("{}.candy", last);
            result.push(Input::File(path));
        }
        result
    }
}
<commit_msg>feat(compiler): add compile-time flag for tracing built-in function calls<commit_after>use im::HashMap;
use itertools::Itertools;

use crate::{
    builtin_functions::BuiltinFunction,
    compiler::hir::{self, Expression},
    discover::run::run_call,
    input::Input,
};

use super::{
    result::DiscoverResult,
    run::Discover,
    value::{Environment, Value},
};

const TRACE_BUILTIN_FUNCTION_CALLS: bool = false;

pub fn run_builtin_function(
    db: &dyn Discover,
    builtin_function: BuiltinFunction,
    arguments: Vec<hir::Id>,
    environment: Environment,
) -> DiscoverResult {
    if TRACE_BUILTIN_FUNCTION_CALLS {
        log::trace!(
            "run_builtin_function: builtin{:?} {}",
            builtin_function,
            arguments.iter().join(" ")
        );
    }

    // Handle builtin functions that don't need to resolve the arguments.
    match builtin_function {
        BuiltinFunction::IfElse => return if_else(db, arguments, environment),
        _ => {}
    }

    let arguments = arguments
        .iter()
        .map(|it| environment.get(it).transitive())
        .collect::<DiscoverResult<_>>()?;
    match builtin_function {
        BuiltinFunction::Add => add(arguments),
        BuiltinFunction::Equals => equals(arguments),
        BuiltinFunction::GetArgumentCount => get_argument_count(db, arguments),
        BuiltinFunction::Panic => panic(arguments),
        BuiltinFunction::Print => print(arguments),
        BuiltinFunction::StructGet => struct_get(arguments),
        BuiltinFunction::StructGetKeys => struct_get_keys(arguments),
        BuiltinFunction::StructHasKey => struct_has_key(arguments),
        BuiltinFunction::TypeOf => type_of(arguments),
        BuiltinFunction::Use => use_(db, arguments),
        _ => panic!("Unhandled builtin function: {:?}", builtin_function),
    }
}

macro_rules! destructure {
    ($arguments:expr, $enum:pat, $body:block) => {{
        if let $enum = &$arguments[..] {
            $body
        } else {
            DiscoverResult::panic(format!("Invalid arguments").to_owned())
        }
    }};
}

fn add(arguments: Vec<Value>) -> DiscoverResult {
    destructure!(arguments, [Value::Int(a), Value::Int(b)], {
        Value::Int(a + b).into()
    })
}

fn equals(arguments: Vec<Value>) -> DiscoverResult {
    destructure!(arguments, [a, b], { Value::bool(a == b).into() })
}

fn get_argument_count(db: &dyn Discover, arguments: Vec<Value>) -> DiscoverResult {
    destructure!(arguments, [Value::Lambda(function)], {
        // TODO: support parameter counts > 2^64 on 128-bit systems and better
        let expression = match db.find_expression(function.id.to_owned()).unwrap() {
            Expression::Lambda(lambda) => lambda,
            _ => panic!("Lambda's function"),
        };
        Value::Int(expression.parameters.len() as u64).into()
    })
}

fn if_else(db: &dyn Discover, arguments: Vec<hir::Id>, environment: Environment) -> DiscoverResult {
    if let [condition, then, else_] = &arguments[..] {
        let body_id = match environment.get(condition)? {
            value if value == Value::bool(true) => then,
            value if value == Value::bool(false) => else_,
            value => {
                return DiscoverResult::panic(format!(
                    "Condition must be a boolean, but was {:?}.",
                    value
                ));
            }
        };

        run_call(db, body_id.to_owned(), vec![], environment)
    } else {
        DiscoverResult::panic(format!(
            "Builtin if/else called with wrong number of arguments: {}, expected: {}",
            arguments.len(),
            3
        ))
    }
}

fn panic(arguments: Vec<Value>) -> DiscoverResult {
    destructure!(arguments, [value], { DiscoverResult::Panic(value.clone()) })
}

fn print(arguments: Vec<Value>) -> DiscoverResult {
    destructure!(arguments, [value], {
        println!("{:?}", value);
        Value::nothing().into()
    })
}

fn struct_get(arguments: Vec<Value>) -> DiscoverResult {
    destructure!(arguments, [struct_, key], {
        let struct_ = expect_struct("builtinStructGet".to_owned(), struct_)?;
        struct_
            .get(key)
            .map(|value| value.clone().into())
            .unwrap_or_else(|| {
                DiscoverResult::panic(format!("Struct does not contain key {:?}", key))
            })
    })
}
fn struct_get_keys(arguments: Vec<Value>) -> DiscoverResult {
    destructure!(arguments, [struct_], {
        let struct_ = expect_struct("builtinStructGetKeys".to_owned(), struct_)?;
        Value::list(struct_.keys().cloned().collect()).into()
    })
}
fn struct_has_key(arguments: Vec<Value>) -> DiscoverResult {
    destructure!(arguments, [struct_, key], {
        let struct_ = expect_struct("builtinStructHasKey".to_owned(), struct_)?;
        Value::bool(struct_.contains_key(key)).into()
    })
}
fn expect_struct(function_name: String, value: &Value) -> DiscoverResult<&HashMap<Value, Value>> {
    match value {
        Value::Struct(struct_) => struct_.into(),
        _ => {
            return DiscoverResult::panic(format!(
                "`{}` expected a struct as its first parameter, but received: {:?}",
                function_name, value
            ))
        }
    }
}

fn type_of(arguments: Vec<Value>) -> DiscoverResult {
    destructure!(arguments, [value], {
        match value {
            Value::Int(_) => Value::Symbol("Int".to_owned()).into(),
            Value::Text(_) => Value::Symbol("Text".to_owned()).into(),
            Value::Symbol(_) => Value::Symbol("Symbol".to_owned()).into(),
            Value::Struct(_) => Value::Symbol("Struct".to_owned()).into(),
            Value::Lambda(_) => Value::Symbol("Function".to_owned()).into(),
        }
    })
}

fn use_(db: &dyn Discover, arguments: Vec<Value>) -> DiscoverResult {
    destructure!(arguments, [current_path, target], {
        // `current_path` is set by us and not users, hence we don't have to validate it that strictly.
        let current_path_struct = match current_path {
            Value::Struct(value) => value,
            _ => unreachable!(),
        };
        let mut current_path = vec![];
        let mut index = 0;
        loop {
            if let Some(component) = current_path_struct.get(&Value::Int(index)) {
                match component {
                    Value::Text(component) => current_path.push(component.clone()),
                    _ => unreachable!(),
                }
            } else {
                break;
            }
            index += 1;
        }

        let target = match target {
            Value::Text(value) => value,
            it => {
                return DiscoverResult::panic(format!(
                    "`use` expected a text as its second parameter, but received: {:?}",
                    it
                ))
            }
        };
        let target = match UseTarget::parse(target) {
            Ok(target) => target,
            Err(error) => return DiscoverResult::panic(error),
        };

        if target.parent_navigations > current_path.len() {
            return DiscoverResult::panic("Too many parent navigations.".to_owned());
        }

        let inputs = target.resolve(&current_path[..]);
        let input = match inputs
            .iter()
            .filter(|&it| db.get_input(it.to_owned()).is_some())
            .next()
        {
            Some(target) => target,
            None => {
                return DiscoverResult::panic(format!(
                    "Target doesn't exist. Checked the following path(s): {}",
                    inputs.iter().map(|it| format!("{}", it)).join(", ")
                ));
            }
        };

        let (hir, _) = db.hir(input.clone()).unwrap();
        let discover_result = db.run_all(input.to_owned());

        hir.identifiers
            .iter()
            .map(|(id, key)| {
                let mut key = key.to_owned();
                key.get_mut(0..1).unwrap().make_ascii_uppercase();
                let key = Value::Symbol(key.to_owned());

                let value = match discover_result.get(id) {
                    Some(value) => value.to_owned()?,
                    None => return DiscoverResult::ErrorInHir,
                };

                DiscoverResult::Value((key, value))
            })
            .collect::<DiscoverResult<HashMap<Value, Value>>>()
            .map(|it| Value::Struct(it))
    })
}
struct UseTarget {
    parent_navigations: usize,
    path: Vec<String>,
}
impl UseTarget {
    const PARENT_NAVIGATION_CHAR: char = '.';

    fn parse(target: &str) -> Result<Self, String> {
        let mut parent_navigations = 0;
        let mut target = target;
        while target.chars().next() == Some(UseTarget::PARENT_NAVIGATION_CHAR) {
            parent_navigations += 1;
            target = &target[UseTarget::PARENT_NAVIGATION_CHAR.len_utf8()..];
        }

        let mut path = vec![];
        loop {
            let mut chars = vec![];
            while let Some(c) = target.chars().next() {
                if c == UseTarget::PARENT_NAVIGATION_CHAR {
                    break;
                }
                chars.push(c);
                target = &target[c.len_utf8()..];
            }

            if target.is_empty() {
                path.push(chars.into_iter().join(""));
                break;
            }

            if chars.is_empty() {
                return Err("Target contains consecutive dots (`.`) in the path.".to_owned());
            }

            path.push(chars.into_iter().join(""));
        }
        Ok(UseTarget {
            parent_navigations,
            path,
        })
    }

    fn resolve(&self, current_path: &[String]) -> Vec<Input> {
        let mut path = current_path.to_owned();
        if self.parent_navigations == 0 {
            assert!(!path.is_empty());
            let last = path.last_mut().unwrap();
            if last == ".candy" {
                path.pop();
            } else {
                *last = last
                    .strip_suffix(".candy")
                    .expect("File name must end with `.candy`.")
                    .to_owned();
            }
        } else {
            for _ in 0..self.parent_navigations {
                if path.is_empty() {
                    return vec![];
                }
                path.pop();
            }
        }

        for part in &self.path {
            path.push(part.to_owned());
        }

        let mut result = vec![];

        let mut subdirectory = path.clone();
        subdirectory.push(".candy".to_owned());
        result.push(Input::File(subdirectory));

        if path.len() >= 1 {
            let last = path.last_mut().unwrap();
            *last = format!("{}.candy", last);
            result.push(Input::File(path));
        }
        result
    }
}
<|endoftext|>


<commit_before>/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

//! High-level, safe bindings for JS typed array APIs. Allows creating new
//! typed arrays or wrapping existing JS reflectors, and prevents reinterpreting
//! existing buffers as different types except in well-defined cases.

use glue::GetFloat32ArrayLengthAndData;
use glue::GetFloat64ArrayLengthAndData;
use glue::GetInt16ArrayLengthAndData;
use glue::GetInt32ArrayLengthAndData;
use glue::GetInt8ArrayLengthAndData;
use glue::GetUint16ArrayLengthAndData;
use glue::GetUint32ArrayLengthAndData;
use glue::GetUint8ArrayLengthAndData;
use glue::GetUint8ClampedArrayLengthAndData;
use jsapi::GetArrayBufferLengthAndData;
use jsapi::GetArrayBufferViewLengthAndData;
use jsapi::HandleObject;
use jsapi::JSContext;
use jsapi::JSObject;
use jsapi::JS_GetArrayBufferData;
use jsapi::JS_GetArrayBufferViewType;
use jsapi::JS_GetFloat32ArrayData;
use jsapi::JS_GetFloat64ArrayData;
use jsapi::JS_GetInt16ArrayData;
use jsapi::JS_GetInt32ArrayData;
use jsapi::JS_GetInt8ArrayData;
use jsapi::JS_GetUint16ArrayData;
use jsapi::JS_GetUint32ArrayData;
use jsapi::JS_GetUint8ArrayData;
use jsapi::JS_GetUint8ClampedArrayData;
use jsapi::JS_NewArrayBuffer;
use jsapi::JS_NewFloat32Array;
use jsapi::JS_NewFloat64Array;
use jsapi::JS_NewInt16Array;
use jsapi::JS_NewInt32Array;
use jsapi::JS_NewInt8Array;
use jsapi::JS_NewUint16Array;
use jsapi::JS_NewUint32Array;
use jsapi::JS_NewUint8Array;
use jsapi::JS_NewUint8ClampedArray;
use jsapi::MutableHandleObject;
use jsapi::Rooted;
use jsapi::Type;
use jsapi::UnwrapArrayBuffer;
use jsapi::UnwrapArrayBufferView;
use jsapi::UnwrapFloat32Array;
use jsapi::UnwrapFloat64Array;
use jsapi::UnwrapInt16Array;
use jsapi::UnwrapInt32Array;
use jsapi::UnwrapInt8Array;
use jsapi::UnwrapUint16Array;
use jsapi::UnwrapUint32Array;
use jsapi::UnwrapUint8Array;
use jsapi::UnwrapUint8ClampedArray;
use rust::RootedGuard;
use std::ptr;
use std::slice;

pub enum CreateWith<'a, T: 'a> {
    Length(u32),
    Slice(&'a [T]),
}

/// A rooted typed array.
pub struct TypedArray<'a, T: 'a + TypedArrayElement> {
    object: RootedGuard<'a, *mut JSObject>,
    computed: Option<(*mut T::Element, u32)>,
}

impl<'a, T: TypedArrayElement> TypedArray<'a, T> {
    /// Create a typed array representation that wraps an existing JS reflector.
    /// This operation will fail if attempted on a JS object that does not match
    /// the expected typed array details.
    pub fn from(cx: *mut JSContext,
                root: &'a mut Rooted<*mut JSObject>,
                object: *mut JSObject)
                -> Result<Self, ()> {
        if object.is_null() {
            return Err(());
        }
        unsafe {
            let mut guard = RootedGuard::new(cx, root, object);
            let unwrapped = T::unwrap_array(*guard);
            if unwrapped.is_null() {
                return Err(());
            }

            *guard = unwrapped;
            Ok(TypedArray {
                object: guard,
                computed: None,
            })
        }
    }

    fn data(&mut self) -> (*mut T::Element, u32) {
        if let Some(data) = self.computed {
            return data;
        }

        let data = unsafe { T::length_and_data(*self.object) };
        self.computed = Some(data);
        data
    }

    /// # Unsafety
    ///
    /// The returned slice can be invalidated if the underlying typed array
    /// is neutered.
    pub unsafe fn as_slice(&mut self) -> &[T::Element] {
        let (pointer, length) = self.data();
        slice::from_raw_parts(pointer as *const T::Element, length as usize)
    }

    /// # Unsafety
    ///
    /// The returned slice can be invalidated if the underlying typed array
    /// is neutered.
    ///
    /// The underlying `JSObject` can be aliased, which can lead to
    /// Undefined Behavior due to mutable aliasing.
    pub unsafe fn as_mut_slice(&mut self) -> &mut [T::Element] {
        let (pointer, length) = self.data();
        slice::from_raw_parts_mut(pointer, length as usize)
    }
}

impl<'a, T: TypedArrayElementCreator + TypedArrayElement> TypedArray<'a, T> {
    /// Create a new JS typed array, optionally providing initial data that will
    /// be copied into the newly-allocated buffer. Returns the new JS reflector.
    pub unsafe fn create(cx: *mut JSContext,
                         with: CreateWith<T::Element>,
                         result: MutableHandleObject)
                         -> Result<(), ()> {
        let length = match with {
            CreateWith::Length(len) => len,
            CreateWith::Slice(slice) => slice.len() as u32,
        };

        result.set(T::create_new(cx, length));
        if result.get().is_null() {
            return Err(());
        }

        if let CreateWith::Slice(data) = with {
            TypedArray::<T>::update_raw(data, result.handle());
        }

        Ok(())
    }

    ///  Update an existed JS typed array
    pub unsafe fn update(&mut self, data: &[T::Element]) {
        TypedArray::<T>::update_raw(data, self.object.handle());
    }

    unsafe fn update_raw(data: &[T::Element], result: HandleObject) {
        let (buf, length) = T::length_and_data(result.get());
        assert!(data.len() <= length as usize);
        ptr::copy_nonoverlapping(data.as_ptr(), buf, data.len());
    }
}

/// Internal trait used to associate an element type with an underlying representation
/// and various functions required to manipulate typed arrays of that element type.
pub trait TypedArrayElement {
    /// Underlying primitive representation of this element type.
    type Element;
    /// Unwrap a typed array JS reflector for this element type.
    unsafe fn unwrap_array(obj: *mut JSObject) -> *mut JSObject;
    /// Retrieve the length and data of a typed array's buffer for this element type.
    unsafe fn length_and_data(obj: *mut JSObject) -> (*mut Self::Element, u32);
}

/// Internal trait for creating new typed arrays.
pub trait TypedArrayElementCreator: TypedArrayElement {
    /// Create a new typed array.
    unsafe fn create_new(cx: *mut JSContext, length: u32) -> *mut JSObject;
    /// Get the data.
    unsafe fn get_data(obj: *mut JSObject) -> *mut Self::Element;
}

macro_rules! typed_array_element {
    ($t: ident,
     $element: ty,
     $unwrap: ident,
     $length_and_data: ident) => (
        /// A kind of typed array.
        pub struct $t;

        impl TypedArrayElement for $t {
            type Element = $element;
            unsafe fn unwrap_array(obj: *mut JSObject) -> *mut JSObject {
                $unwrap(obj)
            }

            unsafe fn length_and_data(obj: *mut JSObject) -> (*mut Self::Element, u32) {
                let mut len = 0;
                let mut shared = false;
                let mut data = ptr::null_mut();
                $length_and_data(obj, &mut len, &mut shared, &mut data);
                assert!(!shared);
                (data, len)
            }
        }
    );

    ($t: ident,
     $element: ty,
     $unwrap: ident,
     $length_and_data: ident,
     $create_new: ident,
     $get_data: ident) => (
        typed_array_element!($t, $element, $unwrap, $length_and_data);

        impl TypedArrayElementCreator for $t {
            unsafe fn create_new(cx: *mut JSContext, length: u32) -> *mut JSObject {
                $create_new(cx, length)
            }

            unsafe fn get_data(obj: *mut JSObject) -> *mut Self::Element {
                let mut shared = false;
                let data = $get_data(obj, &mut shared, ptr::null_mut());
                assert!(!shared);
                data
            }
        }
    );
}

typed_array_element!(Uint8,
                     u8,
                     UnwrapUint8Array,
                     GetUint8ArrayLengthAndData,
                     JS_NewUint8Array,
                     JS_GetUint8ArrayData);
typed_array_element!(Uint16,
                     u16,
                     UnwrapUint16Array,
                     GetUint16ArrayLengthAndData,
                     JS_NewUint16Array,
                     JS_GetUint16ArrayData);
typed_array_element!(Uint32,
                     u32,
                     UnwrapUint32Array,
                     GetUint32ArrayLengthAndData,
                     JS_NewUint32Array,
                     JS_GetUint32ArrayData);
typed_array_element!(Int8,
                     i8,
                     UnwrapInt8Array,
                     GetInt8ArrayLengthAndData,
                     JS_NewInt8Array,
                     JS_GetInt8ArrayData);
typed_array_element!(Int16,
                     i16,
                     UnwrapInt16Array,
                     GetInt16ArrayLengthAndData,
                     JS_NewInt16Array,
                     JS_GetInt16ArrayData);
typed_array_element!(Int32,
                     i32,
                     UnwrapInt32Array,
                     GetInt32ArrayLengthAndData,
                     JS_NewInt32Array,
                     JS_GetInt32ArrayData);
typed_array_element!(Float32,
                     f32,
                     UnwrapFloat32Array,
                     GetFloat32ArrayLengthAndData,
                     JS_NewFloat32Array,
                     JS_GetFloat32ArrayData);
typed_array_element!(Float64,
                     f64,
                     UnwrapFloat64Array,
                     GetFloat64ArrayLengthAndData,
                     JS_NewFloat64Array,
                     JS_GetFloat64ArrayData);
typed_array_element!(ClampedU8,
                     u8,
                     UnwrapUint8ClampedArray,
                     GetUint8ClampedArrayLengthAndData,
                     JS_NewUint8ClampedArray,
                     JS_GetUint8ClampedArrayData);
typed_array_element!(ArrayBufferU8,
                     u8,
                     UnwrapArrayBuffer,
                     GetArrayBufferLengthAndData,
                     JS_NewArrayBuffer,
                     JS_GetArrayBufferData);
typed_array_element!(ArrayBufferViewU8,
                     u8,
                     UnwrapArrayBufferView,
                     GetArrayBufferViewLengthAndData);

/// The Uint8ClampedArray type.
pub type Uint8ClampedArray<'a> = TypedArray<'a, ClampedU8>;
/// The Uint8Array type.
pub type Uint8Array<'a> = TypedArray<'a, Uint8>;
/// The Int8Array type.
pub type Int8Array<'a> = TypedArray<'a, Int8>;
/// The Uint16Array type.
pub type Uint16Array<'a> = TypedArray<'a, Uint16>;
/// The Int16Array type.
pub type Int16Array<'a> = TypedArray<'a, Int16>;
/// The Uint32Array type.
pub type Uint32Array<'a> = TypedArray<'a, Uint32>;
/// The Int32Array type.
pub type Int32Array<'a> = TypedArray<'a, Int32>;
/// The Float32Array type.
pub type Float32Array<'a> = TypedArray<'a, Float32>;
/// The Float64Array type.
pub type Float64Array<'a> = TypedArray<'a, Float64>;
/// The ArrayBuffer type.
pub type ArrayBuffer<'a> = TypedArray<'a, ArrayBufferU8>;
/// The ArrayBufferView type
pub type ArrayBufferView<'a> = TypedArray<'a, ArrayBufferViewU8>;

impl<'a> ArrayBufferView<'a> {
    pub fn get_array_type(&self) -> Type {
        unsafe { JS_GetArrayBufferViewType(self.object.get()) }
    }
}

#[macro_export]
macro_rules! typedarray {
    (in($cx:expr) let $name:ident : $ty:ident = $init:expr) => {
        let mut __root = $crate::jsapi::Rooted::new_unrooted();
        let $name = $crate::typedarray::$ty::from($cx, &mut __root, $init);
    };
    (in($cx:expr) let mut $name:ident : $ty:ident = $init:expr) => {
        let mut __root = $crate::jsapi::Rooted::new_unrooted();
        let mut $name = $crate::typedarray::$ty::from($cx, &mut __root, $init);
    }
}
<commit_msg>Support typed arrays to be also stored on heap<commit_after>/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

//! High-level, safe bindings for JS typed array APIs. Allows creating new
//! typed arrays or wrapping existing JS reflectors, and prevents reinterpreting
//! existing buffers as different types except in well-defined cases.

use glue::GetFloat32ArrayLengthAndData;
use glue::GetFloat64ArrayLengthAndData;
use glue::GetInt16ArrayLengthAndData;
use glue::GetInt32ArrayLengthAndData;
use glue::GetInt8ArrayLengthAndData;
use glue::GetUint16ArrayLengthAndData;
use glue::GetUint32ArrayLengthAndData;
use glue::GetUint8ArrayLengthAndData;
use glue::GetUint8ClampedArrayLengthAndData;
use jsapi::GetArrayBufferLengthAndData;
use jsapi::GetArrayBufferViewLengthAndData;
use jsapi::Heap;
use jsapi::JSContext;
use jsapi::JSObject;
use jsapi::JSTracer;
use jsapi::JS_GetArrayBufferData;
use jsapi::JS_GetArrayBufferViewType;
use jsapi::JS_GetFloat32ArrayData;
use jsapi::JS_GetFloat64ArrayData;
use jsapi::JS_GetInt16ArrayData;
use jsapi::JS_GetInt32ArrayData;
use jsapi::JS_GetInt8ArrayData;
use jsapi::JS_GetUint16ArrayData;
use jsapi::JS_GetUint32ArrayData;
use jsapi::JS_GetUint8ArrayData;
use jsapi::JS_GetUint8ClampedArrayData;
use jsapi::JS_NewArrayBuffer;
use jsapi::JS_NewFloat32Array;
use jsapi::JS_NewFloat64Array;
use jsapi::JS_NewInt16Array;
use jsapi::JS_NewInt32Array;
use jsapi::JS_NewInt8Array;
use jsapi::JS_NewUint16Array;
use jsapi::JS_NewUint32Array;
use jsapi::JS_NewUint8Array;
use jsapi::JS_NewUint8ClampedArray;
use jsapi::MutableHandleObject;
use jsapi::Type;
use jsapi::UnwrapArrayBuffer;
use jsapi::UnwrapArrayBufferView;
use jsapi::UnwrapFloat32Array;
use jsapi::UnwrapFloat64Array;
use jsapi::UnwrapInt16Array;
use jsapi::UnwrapInt32Array;
use jsapi::UnwrapInt8Array;
use jsapi::UnwrapUint16Array;
use jsapi::UnwrapUint32Array;
use jsapi::UnwrapUint8Array;
use jsapi::UnwrapUint8ClampedArray;
use rust::CustomTrace;
use std::ptr;
use std::slice;

/// Trait that specifies how pointers to wrapped objects are stored. It supports
/// two variants, one with bare pointer (to be rooted on stack using
/// CustomAutoRooter) and wrapped in a Box<Heap<T>>, which can be stored in a
/// heap-allocated structure, to be rooted with JSTraceable-implementing tracers
/// (currently implemented in Servo).
pub trait JSObjectStorage {
    fn as_raw(&self) -> *mut JSObject;
    fn from_raw(raw: *mut JSObject) -> Self;
}

impl JSObjectStorage for *mut JSObject {
    fn as_raw(&self) -> *mut JSObject { *self }
    fn from_raw(raw: *mut JSObject) -> Self { raw }
}

impl JSObjectStorage for Box<Heap<*mut JSObject>> {
    fn as_raw(&self) -> *mut JSObject { self.get() }
    fn from_raw(raw: *mut JSObject) -> Self {
        let boxed = Box::new(Heap::default());
        boxed.set(raw);
        boxed
    }
}

pub enum CreateWith<'a, T: 'a> {
    Length(u32),
    Slice(&'a [T]),
}

/// A typed array wrapper.
pub struct TypedArray<T: TypedArrayElement, S: JSObjectStorage> {
    object: S,
    computed: Option<(*mut T::Element, u32)>,
}

unsafe impl<T> CustomTrace for TypedArray<T, *mut JSObject> where T: TypedArrayElement {
    fn trace(&self, trc: *mut JSTracer) {
        self.object.trace(trc);
    }
}

impl<T: TypedArrayElement, S: JSObjectStorage> TypedArray<T, S> {
    /// Create a typed array representation that wraps an existing JS reflector.
    /// This operation will fail if attempted on a JS object that does not match
    /// the expected typed array details.
    pub fn from(object: *mut JSObject) -> Result<Self, ()> {
        if object.is_null() {
            return Err(());
        }
        unsafe {
            let unwrapped = T::unwrap_array(object);
            if unwrapped.is_null() {
                return Err(());
            }

            Ok(TypedArray {
                object: S::from_raw(unwrapped),
                computed: None,
            })
        }
    }

    fn data(&mut self) -> (*mut T::Element, u32) {
        if let Some(data) = self.computed {
            return data;
        }

        let data = unsafe { T::length_and_data(self.object.as_raw()) };
        self.computed = Some(data);
        data
    }

    /// # Unsafety
    ///
    /// Returned wrapped pointer to the underlying `JSObject` is meant to be
    /// read-only, modifying it can lead to Undefined Behaviour and violation
    /// of TypedArray API guarantees.
    ///
    /// Practically, this exists only to implement `JSTraceable` trait in Servo
    /// for Box<Heap<*mut JSObject>> variant.
    pub unsafe fn underlying_object(&self) -> &S {
        &self.object
    }

    /// # Unsafety
    ///
    /// The returned slice can be invalidated if the underlying typed array
    /// is neutered.
    pub unsafe fn as_slice(&mut self) -> &[T::Element] {
        let (pointer, length) = self.data();
        slice::from_raw_parts(pointer as *const T::Element, length as usize)
    }

    /// # Unsafety
    ///
    /// The returned slice can be invalidated if the underlying typed array
    /// is neutered.
    ///
    /// The underlying `JSObject` can be aliased, which can lead to
    /// Undefined Behavior due to mutable aliasing.
    pub unsafe fn as_mut_slice(&mut self) -> &mut [T::Element] {
        let (pointer, length) = self.data();
        slice::from_raw_parts_mut(pointer, length as usize)
    }
}

impl<T: TypedArrayElementCreator + TypedArrayElement, S: JSObjectStorage> TypedArray<T, S> {
    /// Create a new JS typed array, optionally providing initial data that will
    /// be copied into the newly-allocated buffer. Returns the new JS reflector.
    pub unsafe fn create(cx: *mut JSContext,
                         with: CreateWith<T::Element>,
                         result: MutableHandleObject)
                         -> Result<(), ()> {
        let length = match with {
            CreateWith::Length(len) => len,
            CreateWith::Slice(slice) => slice.len() as u32,
        };

        result.set(T::create_new(cx, length));
        if result.get().is_null() {
            return Err(());
        }

        if let CreateWith::Slice(data) = with {
            Self::update_raw(data, result.get());
        }

        Ok(())
    }

    ///  Update an existed JS typed array
    pub unsafe fn update(&mut self, data: &[T::Element]) {
        Self::update_raw(data, self.object.as_raw());
    }

    unsafe fn update_raw(data: &[T::Element], result: *mut JSObject) {
        let (buf, length) = T::length_and_data(result);
        assert!(data.len() <= length as usize);
        ptr::copy_nonoverlapping(data.as_ptr(), buf, data.len());
    }
}

/// Internal trait used to associate an element type with an underlying representation
/// and various functions required to manipulate typed arrays of that element type.
pub trait TypedArrayElement {
    /// Underlying primitive representation of this element type.
    type Element;
    /// Unwrap a typed array JS reflector for this element type.
    unsafe fn unwrap_array(obj: *mut JSObject) -> *mut JSObject;
    /// Retrieve the length and data of a typed array's buffer for this element type.
    unsafe fn length_and_data(obj: *mut JSObject) -> (*mut Self::Element, u32);
}

/// Internal trait for creating new typed arrays.
pub trait TypedArrayElementCreator: TypedArrayElement {
    /// Create a new typed array.
    unsafe fn create_new(cx: *mut JSContext, length: u32) -> *mut JSObject;
    /// Get the data.
    unsafe fn get_data(obj: *mut JSObject) -> *mut Self::Element;
}

macro_rules! typed_array_element {
    ($t: ident,
     $element: ty,
     $unwrap: ident,
     $length_and_data: ident) => (
        /// A kind of typed array.
        pub struct $t;

        impl TypedArrayElement for $t {
            type Element = $element;
            unsafe fn unwrap_array(obj: *mut JSObject) -> *mut JSObject {
                $unwrap(obj)
            }

            unsafe fn length_and_data(obj: *mut JSObject) -> (*mut Self::Element, u32) {
                let mut len = 0;
                let mut shared = false;
                let mut data = ptr::null_mut();
                $length_and_data(obj, &mut len, &mut shared, &mut data);
                assert!(!shared);
                (data, len)
            }
        }
    );

    ($t: ident,
     $element: ty,
     $unwrap: ident,
     $length_and_data: ident,
     $create_new: ident,
     $get_data: ident) => (
        typed_array_element!($t, $element, $unwrap, $length_and_data);

        impl TypedArrayElementCreator for $t {
            unsafe fn create_new(cx: *mut JSContext, length: u32) -> *mut JSObject {
                $create_new(cx, length)
            }

            unsafe fn get_data(obj: *mut JSObject) -> *mut Self::Element {
                let mut shared = false;
                let data = $get_data(obj, &mut shared, ptr::null_mut());
                assert!(!shared);
                data
            }
        }
    );
}

typed_array_element!(Uint8,
                     u8,
                     UnwrapUint8Array,
                     GetUint8ArrayLengthAndData,
                     JS_NewUint8Array,
                     JS_GetUint8ArrayData);
typed_array_element!(Uint16,
                     u16,
                     UnwrapUint16Array,
                     GetUint16ArrayLengthAndData,
                     JS_NewUint16Array,
                     JS_GetUint16ArrayData);
typed_array_element!(Uint32,
                     u32,
                     UnwrapUint32Array,
                     GetUint32ArrayLengthAndData,
                     JS_NewUint32Array,
                     JS_GetUint32ArrayData);
typed_array_element!(Int8,
                     i8,
                     UnwrapInt8Array,
                     GetInt8ArrayLengthAndData,
                     JS_NewInt8Array,
                     JS_GetInt8ArrayData);
typed_array_element!(Int16,
                     i16,
                     UnwrapInt16Array,
                     GetInt16ArrayLengthAndData,
                     JS_NewInt16Array,
                     JS_GetInt16ArrayData);
typed_array_element!(Int32,
                     i32,
                     UnwrapInt32Array,
                     GetInt32ArrayLengthAndData,
                     JS_NewInt32Array,
                     JS_GetInt32ArrayData);
typed_array_element!(Float32,
                     f32,
                     UnwrapFloat32Array,
                     GetFloat32ArrayLengthAndData,
                     JS_NewFloat32Array,
                     JS_GetFloat32ArrayData);
typed_array_element!(Float64,
                     f64,
                     UnwrapFloat64Array,
                     GetFloat64ArrayLengthAndData,
                     JS_NewFloat64Array,
                     JS_GetFloat64ArrayData);
typed_array_element!(ClampedU8,
                     u8,
                     UnwrapUint8ClampedArray,
                     GetUint8ClampedArrayLengthAndData,
                     JS_NewUint8ClampedArray,
                     JS_GetUint8ClampedArrayData);
typed_array_element!(ArrayBufferU8,
                     u8,
                     UnwrapArrayBuffer,
                     GetArrayBufferLengthAndData,
                     JS_NewArrayBuffer,
                     JS_GetArrayBufferData);
typed_array_element!(ArrayBufferViewU8,
                     u8,
                     UnwrapArrayBufferView,
                     GetArrayBufferViewLengthAndData);

// Default type aliases, uses bare pointer by default, since stack lifetime
// should be the most common scenario
macro_rules! array_alias {
    ($arr: ident, $heap_arr: ident, $elem: ty) => {
        pub type $arr = TypedArray<$elem, *mut JSObject>;
        pub type $heap_arr = TypedArray<$elem, Box<Heap<*mut JSObject>>>;
    }
}

array_alias!(Uint8ClampedArray, HeapUint8ClampedArray, ClampedU8);
array_alias!(Uint8Array, HeapUint8Array, Uint8);
array_alias!(Int8Array, HeapInt8Array, Int8);
array_alias!(Uint16Array, HeapUint16Array, Uint16);
array_alias!(Int16Array, HeapInt16Array, Int16);
array_alias!(Uint32Array, HeapUint32Array, Uint32);
array_alias!(Int32Array, HeapInt32Array, Int32);
array_alias!(Float32Array, HeapFloat32Array, Float32);
array_alias!(Float64Array, HeapFloat64Array, Float64);
array_alias!(ArrayBuffer, HeapArrayBuffer, ArrayBufferU8);
array_alias!(ArrayBufferView, HeapArrayBufferView, ArrayBufferViewU8);

impl<S: JSObjectStorage> TypedArray<ArrayBufferViewU8, S> {
    pub fn get_array_type(&self) -> Type {
        unsafe { JS_GetArrayBufferViewType(self.object.as_raw()) }
    }
}

#[macro_export]
macro_rules! typedarray {
    (in($cx:expr) let $name:ident : $ty:ident = $init:expr) => {
        let mut __array = $crate::typedarray::$ty::from($init)
            .map($crate::rust::CustomAutoRooter::new);

        let $name = __array.as_mut().map(|ok| ok.root($cx));
    };
    (in($cx:expr) let mut $name:ident : $ty:ident = $init:expr) => {
        let mut __array = $crate::typedarray::$ty::from($init)
            .map($crate::rust::CustomAutoRooter::new);

        let mut $name = __array.as_mut().map(|ok| ok.root($cx));
    }
}
<|endoftext|>


<commit_before>use std::collections::hashmap::HashMap;
use url::form_urlencoded;
use groupable::Groupable;

pub fn parse (encoded_string : &str) -> HashMap<String, Vec<String>> {
    form_urlencoded::parse_str(encoded_string).into_iter().group()
}

#[test]
fn parses_encoded_string_with_duplicate_keys() {
    let map = parse(
      "foo=bar&message=hello&message=world"
    );
    assert!(map.get(&"foo".to_string()).len() == 1);
    assert!(map.get(&"foo".to_string()).contains(&"bar".to_string()));
    assert!(map.get(&"message".to_string()).len() == 2);
    assert!(map.get(&"message".to_string()).contains(&"hello".to_string()));
    assert!(map.get(&"message".to_string()).contains(&"world".to_string()));
}

#[test]
fn parses_urlencoded_characters() {
    let map = parse(
        "message=hello%20world"
    );
    assert!(map.get(&"message".to_string()).len() == 1);
    assert!(map.get(&"message".to_string()).contains(&"hello world".to_string()));
}
<commit_msg>urlencoded: Simplify tests.<commit_after>use std::collections::hashmap::HashMap;
use url::form_urlencoded;
use groupable::Groupable;

pub fn parse (encoded_string : &str) -> HashMap<String, Vec<String>> {
    form_urlencoded::parse_str(encoded_string).into_iter().group()
}

#[test]
fn parses_encoded_string_with_duplicate_keys() {
    let map = parse("foo=bar&message=hello&message=world");
    assert_eq!(map["foo".to_string()],
                vec!["bar".to_string()]);
    // Ensure the ordering is correct
    assert_eq!(map["message".to_string()],
                vec!["hello".to_string(), "world".to_string()]);
}

#[test]
fn parses_urlencoded_characters() {
    let map = parse("message=hello%20world");

    assert_eq!(map["message".to_string()],
                vec!["hello world".to_string()]);
}
<|endoftext|>


<commit_before>#![feature(core_intrinsics)]

use std::intrinsics;

fn main() {
    unsafe { intrinsics::forget(); } //~ ERROR this function takes 1 argument but 0 arguments were supplied
}
<commit_msg>Test for too many args.<commit_after>#![feature(core_intrinsics)]

use std::intrinsics;

fn main() {
    unsafe { intrinsics::forget(); } //~ ERROR this function takes 1 argument but 0 arguments were supplied
    unsafe { intrinsics::forget(1, 2); } //~ ERROR this function takes 1 argument but 2 arguments were supplied
}
<|endoftext|>


<commit_before>// Submitted by jess 3jane

extern crate rand;

fn shuffle(arr : &mut Vec<i32>) {
    for i in 0..arr.len() {
        let t = arr[i];
        let r : usize = rand::random::<usize>() % arr.len();
        arr[i] = arr[r];
        arr[r] = t;
    }
}

fn is_sorted(arr : &Vec<i32>) -> bool {
    for i in 1..arr.len() {
        if arr[i-1] > arr[i] {
            return false;
        }
    }
    true
}

fn bogo_sort(arr : &mut Vec<i32>) {
    while !is_sorted(arr) {
        shuffle(arr)
    }
}

fn main() {
    let mut v = vec!(1,2,3,4,5);
    shuffle(&mut v);
    println!("Original array: {:?}", v);
    bogo_sort(&mut v);
    println!("Sorted array: {:?}", v);
}
<commit_msg>Now operates on slices instead of Vec<commit_after>// Submitted by jess 3jane

extern crate rand;

fn shuffle(arr : &mut [i32]) {
    for i in 0..arr.len() {
        let r : usize = rand::random::<usize>() % arr.len();
        arr.swap(r,i);
    }
}

fn is_sorted(arr : &[i32]) -> bool {
    for i in 1..arr.len() {
        if arr[i-1] > arr[i] {
            return false;
        }
    }
    true
}

fn bogo_sort(arr : &mut [i32]) {
    while !is_sorted(arr) {
        shuffle(arr)
    }
}

fn main() {
    let mut v = vec!(1,2,3,4,5);
    shuffle(&mut v);
    println!("Original array: {:?}", v);
    bogo_sort(&mut v);
    println!("Sorted array: {:?}", v);
}
<|endoftext|>


<commit_before>// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at http://mozilla.org/MPL/2.0/.

use std::{fs::File, io::Read, path::PathBuf};

use libmount;
use nix::mount::{umount2, MntFlags};

use devicemapper::{DevId, DmOptions};

use crate::engine::strat_engine::{
    cmd,
    dm::{get_dm, get_dm_init},
};

// For an explanation see:
// https://github.com/rust-lang-nursery/error-chain/issues/254.
// FIXME: Drop dependence on error-chain entirely.
#[allow(deprecated)]
mod cleanup_errors {
    use libmount;
    use nix;
    use std;

    error_chain! {
        foreign_links {
            Ioe(std::io::Error);
            Mnt(libmount::mountinfo::ParseError);
            Nix(nix::Error);
        }
    }
}

use self::cleanup_errors::{Error, Result};

/// Attempt to remove all device mapper devices which match the stratis naming convention.
/// FIXME: Current implementation complicated by https://bugzilla.redhat.com/show_bug.cgi?id=1506287
fn dm_stratis_devices_remove() -> Result<()> {
    /// One iteration of removing devicemapper devices
    fn one_iteration() -> Result<(bool, Vec<String>)> {
        let mut progress_made = false;
        let mut remain = Vec::new();

        for n in get_dm()
            .list_devices()
            .map_err(|e| {
                let err_msg = "failed while listing DM devices, giving up";
                Error::with_chain(e, err_msg)
            })?
            .iter()
            .map(|d| &d.0)
            .filter(|n| n.to_string().starts_with("stratis-1"))
        {
            match get_dm().device_remove(&DevId::Name(n), &DmOptions::new()) {
                Ok(_) => progress_made = true,
                Err(_) => remain.push(n.to_string()),
            }
        }
        Ok((progress_made, remain))
    }

    /// Do one iteration of removals until progress stops. Return remaining
    /// dm devices.
    fn do_while_progress() -> Result<Vec<String>> {
        let mut result = one_iteration()?;
        while result.0 {
            result = one_iteration()?;
        }
        Ok(result.1)
    }

    || -> Result<()> {
        cmd::udev_settle().unwrap();
        get_dm_init().map_err(|err| Error::with_chain(err, "Unable to initialize DM"))?;
        do_while_progress().and_then(|remain| {
            if !remain.is_empty() {
                Err(format!("Some Stratis DM devices remaining: {:?}", remain).into())
            } else {
                Ok(())
            }
        })
    }()
    .map_err(|e| e.chain_err(|| "Failed to ensure removal of all Stratis DM devices"))
}

/// Try and un-mount any filesystems that have the name stratis in the mount point, returning
/// immediately on the first one we are unable to unmount.
fn stratis_filesystems_unmount() -> Result<()> {
    || -> Result<()> {
        let mut mount_data = String::new();
        File::open("/proc/self/mountinfo")?.read_to_string(&mut mount_data)?;
        let parser = libmount::mountinfo::Parser::new(mount_data.as_bytes());

        for mount_point in parser
            .filter_map(|x| x.ok())
            .filter_map(|m| m.mount_point.into_owned().into_string().ok())
            .filter(|mp| mp.contains("stratis"))
        {
            umount2(&PathBuf::from(mount_point), MntFlags::MNT_DETACH)?;
        }

        Ok(())
    }()
    .map_err(|e| e.chain_err(|| "Failed to ensure all Stratis filesystems were unmounted"))
}

/// When a unit test panics we can leave the system in an inconsistent state.  This function
/// tries to clean up by un-mounting any mounted file systems which contain the string
/// "stratis_testing" and then it tries to remove any device mapper tables which are also stratis
/// created.
pub fn clean_up() -> Result<()> {
    stratis_filesystems_unmount()?;
    dm_stratis_devices_remove()?;
    Ok(())
}
<commit_msg>Tidy up imports in tests submodule<commit_after>// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at http://mozilla.org/MPL/2.0/.

use std::{fs::File, io::Read, path::PathBuf};

use libmount;
use nix::mount::{umount2, MntFlags};

use devicemapper::{DevId, DmOptions};

use crate::engine::strat_engine::{
    cmd::udev_settle,
    dm::{get_dm, get_dm_init},
};

// For an explanation see:
// https://github.com/rust-lang-nursery/error-chain/issues/254.
// FIXME: Drop dependence on error-chain entirely.
#[allow(deprecated)]
mod cleanup_errors {
    use libmount;
    use nix;
    use std;

    error_chain! {
        foreign_links {
            Ioe(std::io::Error);
            Mnt(libmount::mountinfo::ParseError);
            Nix(nix::Error);
        }
    }
}

use self::cleanup_errors::{Error, Result};

/// Attempt to remove all device mapper devices which match the stratis naming convention.
/// FIXME: Current implementation complicated by https://bugzilla.redhat.com/show_bug.cgi?id=1506287
fn dm_stratis_devices_remove() -> Result<()> {
    /// One iteration of removing devicemapper devices
    fn one_iteration() -> Result<(bool, Vec<String>)> {
        let mut progress_made = false;
        let mut remain = Vec::new();

        for n in get_dm()
            .list_devices()
            .map_err(|e| {
                let err_msg = "failed while listing DM devices, giving up";
                Error::with_chain(e, err_msg)
            })?
            .iter()
            .map(|d| &d.0)
            .filter(|n| n.to_string().starts_with("stratis-1"))
        {
            match get_dm().device_remove(&DevId::Name(n), &DmOptions::new()) {
                Ok(_) => progress_made = true,
                Err(_) => remain.push(n.to_string()),
            }
        }
        Ok((progress_made, remain))
    }

    /// Do one iteration of removals until progress stops. Return remaining
    /// dm devices.
    fn do_while_progress() -> Result<Vec<String>> {
        let mut result = one_iteration()?;
        while result.0 {
            result = one_iteration()?;
        }
        Ok(result.1)
    }

    || -> Result<()> {
        udev_settle().unwrap();
        get_dm_init().map_err(|err| Error::with_chain(err, "Unable to initialize DM"))?;
        do_while_progress().and_then(|remain| {
            if !remain.is_empty() {
                Err(format!("Some Stratis DM devices remaining: {:?}", remain).into())
            } else {
                Ok(())
            }
        })
    }()
    .map_err(|e| e.chain_err(|| "Failed to ensure removal of all Stratis DM devices"))
}

/// Try and un-mount any filesystems that have the name stratis in the mount point, returning
/// immediately on the first one we are unable to unmount.
fn stratis_filesystems_unmount() -> Result<()> {
    || -> Result<()> {
        let mut mount_data = String::new();
        File::open("/proc/self/mountinfo")?.read_to_string(&mut mount_data)?;
        let parser = libmount::mountinfo::Parser::new(mount_data.as_bytes());

        for mount_point in parser
            .filter_map(|x| x.ok())
            .filter_map(|m| m.mount_point.into_owned().into_string().ok())
            .filter(|mp| mp.contains("stratis"))
        {
            umount2(&PathBuf::from(mount_point), MntFlags::MNT_DETACH)?;
        }

        Ok(())
    }()
    .map_err(|e| e.chain_err(|| "Failed to ensure all Stratis filesystems were unmounted"))
}

/// When a unit test panics we can leave the system in an inconsistent state.  This function
/// tries to clean up by un-mounting any mounted file systems which contain the string
/// "stratis_testing" and then it tries to remove any device mapper tables which are also stratis
/// created.
pub fn clean_up() -> Result<()> {
    stratis_filesystems_unmount()?;
    dm_stratis_devices_remove()?;
    Ok(())
}
<|endoftext|>