<commit_before>extern crate bindgen;

#[cfg(any(target_os = "macos", target_os = "ios"))]
fn main() {
    use std::env;
    use std::path::PathBuf;

    // Generate one large set of bindings for all frameworks.
    //
    // We do this rather than generating a module per framework as some frameworks depend on other
    // frameworks and in turn share types. To ensure all types are compatible across each
    // framework, we feed all headers to bindgen at once.
    //
    // Only link to each framework and include their headers if their features are enabled and they
    // are available on the target os.

    let mut frameworks = vec![];
    let mut headers = vec![];

    #[cfg(feature = "audio_toolbox")]
    {
        println!("cargo:rustc-link-lib=framework=AudioToolbox");
        frameworks.push("/System/Library/Frameworks/AudioToolbox");
        headers.push("/System/Library/Frameworks/AudioToolbox.framework/Headers/AudioToolbox.h");
    }

    #[cfg(feature = "audio_unit")]
    {
        println!("cargo:rustc-link-lib=framework=AudioUnit");
        frameworks.push("/System/Library/Frameworks/AudioUnit");
        headers.push("/System/Library/Frameworks/AudioUnit.framework/Headers/AudioUnit.h");
    }

    #[cfg(feature = "core_audio")]
    {
        println!("cargo:rustc-link-lib=framework=CoreAudio");
        frameworks.push("/System/Library/Frameworks/CoreAudio");
        headers.push("/System/Library/Frameworks/CoreAudio.framework/Headers/CoreAudio.h");
    }

    #[cfg(feature = "open_al")]
    {
        println!("cargo:rustc-link-lib=framework=OpenAL");
        frameworks.push("/System/Library/Frameworks/OpenAL");
        headers.push("/System/Library/Frameworks/OpenAL.framework/Headers/al.h");
        headers.push("/System/Library/Frameworks/OpenAL.framework/Headers/alc.h");
    }

    #[cfg(all(feature = "core_midi", target_os = "macos"))]
    {
        println!("cargo:rustc-link-lib=framework=CoreMIDI");
        frameworks.push("/System/Library/Frameworks/CoreMIDI");
        headers.push("/System/Library/Frameworks/CoreMIDI.framework/Headers/CoreMIDI.h");
    }

    // Get the cargo out directory.
    let out_dir = PathBuf::from(env::var("OUT_DIR").expect("env variable OUT_DIR not found"));

    // Begin building the bindgen params.
    let mut builder = bindgen::Builder::default();

    // Add all headers.
    for header_path in headers {
        builder = builder.header(header_path);
    }

    // Link to all frameworks.
    for framework in frameworks {
        builder = builder.link_framework(framework);
    }

    // Generate the bindings.
    let bindings = builder
        .trust_clang_mangling(false)
        .derive_default(true)
        .generate()
        .expect("unable to generate bindings");

    // Write them to the crate root.
    bindings.write_to_file(out_dir.join("coreaudio.rs")).expect("could not write bindings");
}

#[cfg(not(any(target_os = "macos", target_os = "ios")))]
fn main() {
    eprintln!("coreaudio-sys requires macos or ios");
}
<commit_msg>Added logic for (hopefully) properly detecting framework paths<commit_after>extern crate bindgen;

fn frameworks_path() -> Result<String, std::io::Error> {
    // While macOS has its system frameworks located at "/System/Library/Frameworks"
    // for actually linking against them (especially for cross-compilation) once
    // has to refer to the frameworks as found within "Xcode.app/Contents/Developer/…".

    use std::process::Command;

    let output = Command::new("xcode-select").arg("-p").output()?.stdout;
    let prefix_str = std::str::from_utf8(&output).expect("invalid output from `xcode-select`");
    let prefix = prefix_str.trim_right();

    let platform = if cfg!(target_os = "macos") {
        "MacOSX"
    } else if cfg!(target_os = "ios") {
        "iPhoneOS"
    } else {
        unreachable!();
    };

    let infix = format!("Platforms/{}.platform/Developer/SDKs/{}.sdk", platform, platform);
    let suffix = "System/Library/Frameworks";
    let directory = format!("{}/{}/{}", prefix, infix, suffix);

    Ok(directory)
}

fn build(frameworks_path: &str) {
    // Generate one large set of bindings for all frameworks.
    //
    // We do this rather than generating a module per framework as some frameworks depend on other
    // frameworks and in turn share types. To ensure all types are compatible across each
    // framework, we feed all headers to bindgen at once.
    //
    // Only link to each framework and include their headers if their features are enabled and they
    // are available on the target os.

    use std::env;
    use std::path::PathBuf;

    let mut frameworks = vec![];
    let mut headers = vec![];

    #[cfg(feature = "audio_toolbox")]
    {
        println!("cargo:rustc-link-lib=framework=AudioToolbox");
        frameworks.push("AudioToolbox");
        headers.push("AudioToolbox.framework/Headers/AudioToolbox.h");
    }

    #[cfg(feature = "audio_unit")]
    {
        println!("cargo:rustc-link-lib=framework=AudioUnit");
        frameworks.push("AudioUnit");
        headers.push("AudioUnit.framework/Headers/AudioUnit.h");
    }

    #[cfg(feature = "core_audio")]
    {
        println!("cargo:rustc-link-lib=framework=CoreAudio");
        frameworks.push("CoreAudio");
        headers.push("CoreAudio.framework/Headers/CoreAudio.h");
    }

    #[cfg(feature = "open_al")]
    {
        println!("cargo:rustc-link-lib=framework=OpenAL");
        frameworks.push("OpenAL");
        headers.push("OpenAL.framework/Headers/al.h");
        headers.push("OpenAL.framework/Headers/alc.h");
    }

    #[cfg(all(feature = "core_midi", target_os = "macos"))]
    {
        println!("cargo:rustc-link-lib=framework=CoreMIDI");
        frameworks.push("CoreMIDI");
        headers.push("CoreMIDI.framework/Headers/CoreMIDI.h");
    }

    // Get the cargo out directory.
    let out_dir = PathBuf::from(env::var("OUT_DIR").expect("env variable OUT_DIR not found"));

    // Begin building the bindgen params.
    let mut builder = bindgen::Builder::default();

    builder = builder.clang_arg(format!("-F/{}", frameworks_path));

    // Add all headers.
    for relative_path in headers {
        let absolute_path = format!("{}/{}", frameworks_path, relative_path);
        builder = builder.header(absolute_path);
    }

    // Link to all frameworks.
    for relative_path in frameworks {
        let absolute_path = format!("{}/{}", frameworks_path, relative_path);
        builder = builder.link_framework(absolute_path);
    }

    // Generate the bindings.
    let bindings = builder
        .trust_clang_mangling(false)
        .derive_default(true)
        .generate()
        .expect("unable to generate bindings");

    // Write them to the crate root.
    bindings.write_to_file(out_dir.join("coreaudio.rs")).expect("could not write bindings");
}

#[cfg(any(target_os = "macos", target_os = "ios"))]
fn main() {
    if let Ok(directory) = frameworks_path() {
        build(&directory);
    } else {
        eprintln!("coreaudio-sys could not find frameworks path");
    }
}

#[cfg(not(any(target_os = "macos", target_os = "ios")))]
fn main() {
    eprintln!("coreaudio-sys requires macos or ios target");
}
<|endoftext|>


<commit_before>

#[cfg(feature = "skeptic")]
mod gen_skeptic {
    extern crate skeptic;

    use std::io::prelude::*;
    use std::fs::File;
    use std::path::Path;

    /// skeptic templates look for `rust` after the opening code fences so writing
    /// ```f#,rust
    /// ```
    /// gives f# syntax highlight while still running the tests through the template
    const TEMPLATE: &'static str = r##"
```rust,skeptic-template
extern crate env_logger;
extern crate gluon;

use gluon::vm::api::{{Hole, OpaqueValue}};
use gluon::{{new_vm, Compiler, Thread}};

fn main() {{
    let _ = ::env_logger::init();
    let text = r#\"{}\"#;
    let vm = new_vm();
    match Compiler::new().run_expr::<OpaqueValue<&Thread, Hole>>(&vm, \"example\", text) {{
        Ok(_value) => (),
        Err(err) => {{
            panic!(\"{{}}\", err);
        }}
    }}
    return;
}}
```

"##;

    fn generate_skeptic_tests(file: &str) -> String {
        // Preprocess the readme to inject the skeptic template needed to to run the examples
        let out_file_name = Path::new(env!("OUT_DIR")).join(file);
        let mut contents = TEMPLATE.as_bytes().into();
        File::open(file)
            .and_then(|mut raw_file| raw_file.read_to_end(&mut contents))
            .unwrap();
        File::create(&out_file_name)
            .and_then(|mut out_file| out_file.write(&contents))
            .unwrap();
        out_file_name.to_str().expect("UTF-8 string").into()
    }

    pub fn generate() {
        let test_locations: Vec<_> = ["README.md", "TUTORIAL.md"]
            .iter()
            .cloned()
            .map(generate_skeptic_tests)
            .collect();

        let str_vec: Vec<_> = test_locations.iter().map(|s| &s[..]).collect();
        skeptic::generate_doc_tests(&str_vec);
    }
}

#[cfg(not(feature = "skeptic"))]
mod gen_skeptic {
    pub fn generate() {}
}

fn main() {
    gen_skeptic::generate();
}
<commit_msg>Fix build failure due to missing environment var<commit_after>#[cfg(feature = "skeptic")]
mod gen_skeptic {
    extern crate skeptic;

    use std::env;
    use std::fs::File;
    use std::io::prelude::*;
    use std::path::Path;

    /// skeptic templates look for `rust` after the opening code fences so writing
    /// ```f#,rust
    /// ```
    /// gives f# syntax highlight while still running the tests through the template
    const TEMPLATE: &'static str = r##"
```rust,skeptic-template
extern crate env_logger;
extern crate gluon;

use gluon::vm::api::{{Hole, OpaqueValue}};
use gluon::{{new_vm, Compiler, Thread}};

fn main() {{
    let _ = ::env_logger::init();
    let text = r#\"{}\"#;
    let vm = new_vm();
    match Compiler::new().run_expr::<OpaqueValue<&Thread, Hole>>(&vm, \"example\", text) {{
        Ok(_value) => (),
        Err(err) => {{
            panic!(\"{{}}\", err);
        }}
    }}
    return;
}}
```

"##;

    fn generate_skeptic_tests(file: &str) -> String {
        // Preprocess the readme to inject the skeptic template needed to to run the examples
        let out_file_name = Path::new(&env::var("OUT_DIR").unwrap()).join(file);
        let mut contents = TEMPLATE.as_bytes().into();
        File::open(file)
            .and_then(|mut raw_file| raw_file.read_to_end(&mut contents))
            .unwrap();
        File::create(&out_file_name)
            .and_then(|mut out_file| out_file.write(&contents))
            .unwrap();
        out_file_name.to_str().expect("UTF-8 string").into()
    }

    pub fn generate() {
        let test_locations: Vec<_> = ["README.md", "TUTORIAL.md"]
            .iter()
            .cloned()
            .map(generate_skeptic_tests)
            .collect();

        let str_vec: Vec<_> = test_locations.iter().map(|s| &s[..]).collect();
        skeptic::generate_doc_tests(&str_vec);
    }
}

#[cfg(not(feature = "skeptic"))]
mod gen_skeptic {
    pub fn generate() {}
}

fn main() {
    gen_skeptic::generate();
}
<|endoftext|>


<commit_before>use std::env::*;
use std::ffi::{OsStr, OsString};

use rand::distributions::Alphanumeric;
use rand::{thread_rng, Rng};

fn make_rand_name() -> OsString {
    let rng = thread_rng();
    let n = format!("TEST{}", rng.sample_iter(&Alphanumeric).take(10).collect::<String>());
    let n = OsString::from(n);
    assert!(var_os(&n).is_none());
    n
}

fn eq(a: Option<OsString>, b: Option<&str>) {
    assert_eq!(a.as_ref().map(|s| &**s), b.map(OsStr::new).map(|s| &*s));
}

#[test]
fn test_set_var() {
    let n = make_rand_name();
    set_var(&n, "VALUE");
    eq(var_os(&n), Some("VALUE"));
}

#[test]
fn test_remove_var() {
    let n = make_rand_name();
    set_var(&n, "VALUE");
    remove_var(&n);
    eq(var_os(&n), None);
}

#[test]
fn test_set_var_overwrite() {
    let n = make_rand_name();
    set_var(&n, "1");
    set_var(&n, "2");
    eq(var_os(&n), Some("2"));
    set_var(&n, "");
    eq(var_os(&n), Some(""));
}

#[test]
#[cfg_attr(target_os = "emscripten", ignore)]
fn test_var_big() {
    let mut s = "".to_string();
    let mut i = 0;
    while i < 100 {
        s.push_str("aaaaaaaaaa");
        i += 1;
    }
    let n = make_rand_name();
    set_var(&n, &s);
    eq(var_os(&n), Some(&s));
}

#[test]
#[cfg_attr(target_os = "emscripten", ignore)]
fn test_env_set_get_huge() {
    let n = make_rand_name();
    let s = "x".repeat(10000);
    set_var(&n, &s);
    eq(var_os(&n), Some(&s));
    remove_var(&n);
    eq(var_os(&n), None);
}

#[test]
fn test_env_set_var() {
    let n = make_rand_name();

    let mut e = vars_os();
    set_var(&n, "VALUE");
    assert!(!e.any(|(k, v)| { &*k == &*n && &*v == "VALUE" }));

    assert!(vars_os().any(|(k, v)| { &*k == &*n && &*v == "VALUE" }));
}

#[test]
#[cfg_attr(any(target_os = "emscripten", target_env = "sgx"), ignore)]
#[allow(deprecated)]
fn env_home_dir() {
    fn var_to_os_string(var: Result<String, VarError>) -> Option<OsString> {
        match var {
            Ok(var) => Some(OsString::from(var)),
            Err(VarError::NotUnicode(var)) => Some(var),
            _ => None,
        }
    }

    cfg_if::cfg_if! {
        if #[cfg(unix)] {
            use std::path::PathBuf;

            let oldhome = var_to_os_string(var("HOME"));

            set_var("HOME", "/home/MountainView");
            assert_eq!(home_dir(), Some(PathBuf::from("/home/MountainView")));

            remove_var("HOME");
            if cfg!(target_os = "android") {
                assert!(home_dir().is_none());
            } else {
                // When HOME is not set, some platforms return `None`,
                // but others return `Some` with a default.
                // Just check that it is not "/home/MountainView".
                assert_ne!(home_dir(), Some(PathBuf::from("/home/MountainView")));
            }

            if let Some(oldhome) = oldhome { set_var("HOME", oldhome); }
        } else if #[cfg(windows)] {
            use std::path::PathBuf;

            let oldhome = var_to_os_string(var("HOME"));
            let olduserprofile = var_to_os_string(var("USERPROFILE"));

            remove_var("HOME");
            remove_var("USERPROFILE");

            assert!(home_dir().is_some());

            set_var("HOME", "/home/MountainView");
            assert_eq!(home_dir(), Some(PathBuf::from("/home/MountainView")));

            remove_var("HOME");

            set_var("USERPROFILE", "/home/MountainView");
            assert_eq!(home_dir(), Some(PathBuf::from("/home/MountainView")));

            set_var("HOME", "/home/MountainView");
            set_var("USERPROFILE", "/home/PaloAlto");
            assert_eq!(home_dir(), Some(PathBuf::from("/home/MountainView")));

            remove_var("HOME");
            remove_var("USERPROFILE");

            if let Some(oldhome) = oldhome { set_var("HOME", oldhome); }
            if let Some(olduserprofile) = olduserprofile { set_var("USERPROFILE", olduserprofile); }
        }
    }
}
<commit_msg>Fix SGX CI, take 3<commit_after>use std::env::*;
use std::ffi::{OsStr, OsString};

use rand::distributions::Alphanumeric;
use rand::{thread_rng, Rng};

fn make_rand_name() -> OsString {
    let rng = thread_rng();
    let n = format!("TEST{}", rng.sample_iter(&Alphanumeric).take(10).collect::<String>());
    let n = OsString::from(n);
    assert!(var_os(&n).is_none());
    n
}

fn eq(a: Option<OsString>, b: Option<&str>) {
    assert_eq!(a.as_ref().map(|s| &**s), b.map(OsStr::new).map(|s| &*s));
}

#[test]
fn test_set_var() {
    let n = make_rand_name();
    set_var(&n, "VALUE");
    eq(var_os(&n), Some("VALUE"));
}

#[test]
fn test_remove_var() {
    let n = make_rand_name();
    set_var(&n, "VALUE");
    remove_var(&n);
    eq(var_os(&n), None);
}

#[test]
fn test_set_var_overwrite() {
    let n = make_rand_name();
    set_var(&n, "1");
    set_var(&n, "2");
    eq(var_os(&n), Some("2"));
    set_var(&n, "");
    eq(var_os(&n), Some(""));
}

#[test]
#[cfg_attr(target_os = "emscripten", ignore)]
fn test_var_big() {
    let mut s = "".to_string();
    let mut i = 0;
    while i < 100 {
        s.push_str("aaaaaaaaaa");
        i += 1;
    }
    let n = make_rand_name();
    set_var(&n, &s);
    eq(var_os(&n), Some(&s));
}

#[test]
#[cfg_attr(target_os = "emscripten", ignore)]
fn test_env_set_get_huge() {
    let n = make_rand_name();
    let s = "x".repeat(10000);
    set_var(&n, &s);
    eq(var_os(&n), Some(&s));
    remove_var(&n);
    eq(var_os(&n), None);
}

#[test]
fn test_env_set_var() {
    let n = make_rand_name();

    let mut e = vars_os();
    set_var(&n, "VALUE");
    assert!(!e.any(|(k, v)| { &*k == &*n && &*v == "VALUE" }));

    assert!(vars_os().any(|(k, v)| { &*k == &*n && &*v == "VALUE" }));
}

#[test]
#[cfg_attr(not(any(unix, windows)), ignore, allow(unused))]
#[allow(deprecated)]
fn env_home_dir() {
    use std::path::PathBuf;

    fn var_to_os_string(var: Result<String, VarError>) -> Option<OsString> {
        match var {
            Ok(var) => Some(OsString::from(var)),
            Err(VarError::NotUnicode(var)) => Some(var),
            _ => None,
        }
    }

    cfg_if::cfg_if! {
        if #[cfg(unix)] {
            let oldhome = var_to_os_string(var("HOME"));

            set_var("HOME", "/home/MountainView");
            assert_eq!(home_dir(), Some(PathBuf::from("/home/MountainView")));

            remove_var("HOME");
            if cfg!(target_os = "android") {
                assert!(home_dir().is_none());
            } else {
                // When HOME is not set, some platforms return `None`,
                // but others return `Some` with a default.
                // Just check that it is not "/home/MountainView".
                assert_ne!(home_dir(), Some(PathBuf::from("/home/MountainView")));
            }

            if let Some(oldhome) = oldhome { set_var("HOME", oldhome); }
        } else if #[cfg(windows)] {
            let oldhome = var_to_os_string(var("HOME"));
            let olduserprofile = var_to_os_string(var("USERPROFILE"));

            remove_var("HOME");
            remove_var("USERPROFILE");

            assert!(home_dir().is_some());

            set_var("HOME", "/home/MountainView");
            assert_eq!(home_dir(), Some(PathBuf::from("/home/MountainView")));

            remove_var("HOME");

            set_var("USERPROFILE", "/home/MountainView");
            assert_eq!(home_dir(), Some(PathBuf::from("/home/MountainView")));

            set_var("HOME", "/home/MountainView");
            set_var("USERPROFILE", "/home/PaloAlto");
            assert_eq!(home_dir(), Some(PathBuf::from("/home/MountainView")));

            remove_var("HOME");
            remove_var("USERPROFILE");

            if let Some(oldhome) = oldhome { set_var("HOME", oldhome); }
            if let Some(olduserprofile) = olduserprofile { set_var("USERPROFILE", olduserprofile); }
        }
    }
}
<|endoftext|>


<commit_before>extern crate bincode;
extern crate rustc_serialize;

use rustc_serialize::{Encodable, Decodable};

use ::{KeyType, ValueType};

use std::collections::{BTreeMap, BTreeSet};
use std::collections::btree_map::Iter as MIter;
use std::collections::btree_set::Iter as SIter;
use std::iter::Peekable;

#[derive(RustcEncodable, RustcDecodable, PartialEq)]
struct WALRecord<K: KeyType, V: ValueType> {
    key: K,
    value: V,
}

impl <K: KeyType, V: ValueType> Iterator for WALRecord<K,V> {
    type Item = WALRecord<K,V>;

    fn next(&mut self) -> Option<Self::Item> {

    }
}

struct MemoryRecordIterator<'a, 'b, K: KeyType, V: ValueType> {
    key_size: usize,
    value_size: usize,
    key_iter: Peekable<MIter<'a, K, BTreeSet<V>>>,
    value_iter: Option<Peekable<SIter<'b, V>>>
}

impl <'a, 'b, K: KeyType, V: ValueType> MemoryRecordIterator<'a, 'b, K, V> {
    fn new(key_size: usize, value_size: usize, mem_tree: BTreeMap<K, BTreeSet<V>>) -> MemoryRecordIterator<'a, 'b, K,V> {
        let key_it = mem_tree.iter().peekable();

        MemoryRecordIterator {key_size: key_size,
                              value_size: value_size,
                              key_iter: key_it,
                              value_iter: key_it.peek().iter().peekable()}
    }
}

impl <'a, 'b, K: KeyType, V: ValueType> Iterator for MemoryRecordIterator<'a, 'b, K,V> {
    type Item = Vec<u8>;

    fn next(&mut self) -> Option<Self::Item> {

    }
}

<commit_msg>Got WALIterator compiling<commit_after>extern crate bincode;
extern crate rustc_serialize;

use bincode::rustc_serialize::{encode, decode};
use rustc_serialize::{Encodable, Decodable};

use ::{KeyType, ValueType};

use std::collections::{BTreeMap, BTreeSet};
use std::collections::btree_map::Iter as MIter;
use std::collections::btree_set::Iter as SIter;
use std::error::Error;
use std::fs::{File, OpenOptions};
use std::io::Read;
use std::iter::Peekable;
use std::marker::PhantomData;

#[derive(RustcEncodable, RustcDecodable, PartialEq)]
struct KeyValuePair<K: KeyType, V: ValueType> {
    key: K,
    value: V,
}

struct WALIterator<K: KeyType, V: ValueType> {
    fd: File,  // the WAL file
    key_size: usize,
    value_size: usize,
    _k_marker: PhantomData<K>,
    _v_marker: PhantomData<V>
}

impl <K: KeyType, V: ValueType> WALIterator<K,V> {
    fn new(wal_file_path: String, key_size: usize, value_size: usize) -> Result<WALIterator<K,V>, Box<Error>> {
        let mut wal_file = try!(OpenOptions::new().read(true).create(false).open(wal_file_path));

        return Ok(WALIterator{fd: wal_file,
                              key_size: key_size,
                              value_size: value_size,
                              _k_marker: PhantomData,
                              _v_marker: PhantomData});
    }
}

impl <K: KeyType, V: ValueType> Iterator for WALIterator<K,V> {
    type Item = KeyValuePair<K,V>;

    fn next(&mut self) -> Option<Self::Item> {
        let total_size = self.key_size + self.value_size;
        let mut buff = vec![0; total_size];

        // attempt to read a buffer's worth and decode
        match self.fd.read_exact(&mut buff) {
            Ok(_) => {
                match decode(&buff) {
                    Ok(record) => Some(record),
                    Err(e) => None
                }
            },
            Err(e) => None
        }
    }
}

/*

struct MemoryRecordIterator<'a, 'b, K: KeyType, V: ValueType> {
    key_size: usize,
    value_size: usize,
    key_iter: Peekable<MIter<'a, K, BTreeSet<V>>>,
    value_iter: Option<Peekable<SIter<'b, V>>>
}

impl <'a, 'b, K: KeyType, V: ValueType> MemoryRecordIterator<'a, 'b, K, V> {
    fn new(key_size: usize, value_size: usize, mem_tree: BTreeMap<K, BTreeSet<V>>) -> MemoryRecordIterator<'a, 'b, K,V> {
        let key_it = mem_tree.iter().peekable();

        MemoryRecordIterator {key_size: key_size,
                              value_size: value_size,
                              key_iter: key_it,
                              value_iter: key_it.peek().iter().peekable()}
    }
}

impl <'a, 'b, K: KeyType, V: ValueType> Iterator for MemoryRecordIterator<'a, 'b, K,V> {
    type Item = Vec<u8>;

    fn next(&mut self) -> Option<Self::Item> {

    }
}

*/

<|endoftext|>


<commit_before>#[cfg(test)]
mod tests {
    extern crate futures;
    extern crate hyper;
    extern crate fruitbasket;
    extern crate time;

    use super::super::*;
    use super::super::super::SpotifyEndpoints;

    use std;
    use std::thread;
    use std::thread::sleep;
    use std::sync::atomic::AtomicBool;
    use std::sync::atomic::Ordering;
    use std::time::Duration;
    use std::sync::{Once, ONCE_INIT};

    use self::hyper::{Post, StatusCode};
    use self::hyper::server::{Service, Request, Response};
    use self::hyper::server::Http;
    use self::futures::Stream;
    use self::futures::Future;

    static START: Once = ONCE_INIT;

    lazy_static! {
        static ref WEBSERVER_STARTED: AtomicBool = AtomicBool::new(false);
    }

    pub const TEST_API: SpotifyEndpoints = SpotifyEndpoints {
        scopes: "user-read-private streaming user-read-playback-state",
        authorize: "http://127.0.0.1:9799/en/authorize",
        token: "http://127.0.0.1:9799/api/token",
        devices: "http://127.0.0.1:9799/v1/me/player/devices",
        player_state: "http://127.0.0.1:9799/v1/me/player",
        play: "http://127.0.0.1:9799/v1/me/player/play",
        pause: "http://127.0.0.1:9799/v1/me/player/pause",
        next: "http://127.0.0.1:9799/v1/me/player/next",
        previous: "http://127.0.0.1:9799/v1/me/player/previous",
        seek: "http://127.0.0.1:9799/v1/me/player/seek",
        volume: "http://127.0.0.1:9799/v1/me/player/volume",
        shuffle: "http://127.0.0.1:9799/v1/me/player/shuffle",
        repeat: "http://127.0.0.1:9799/v1/me/player/repeat",
        player: "http://127.0.0.1:9799/v1/me/player",
    };

    /// Macro to parse the body of a POST request and send a response.
    ///
    /// There's probably a "body.to_string()" function somewhere.  I didn't find it.
    /// So instead there's this unreadable, overly complicated bullshit.
    ///
    /// $body_in: a POST body (hyper::Body) from a received POST request
    /// $pairs_out: the name of the key/value pair variable provided to the $block_in
    /// $block_in: a block of code to be executed, with $pairs_out in scope, that evaluates
    ///            to tuple (status_code: StatusCode, body: &str) to send as a response.
    macro_rules! post {
    ($body_in:ident, $pairs_out:ident, $block_in:block) => {
        {
            // Read chunks from user provided body var $body_in
            $body_in.fold(vec![], |mut acc, chunk| {
                acc.extend(chunk);
                Ok::<_, hyper::Error>(acc)
            }).and_then(move |bytes| {
                // [u8] -> String
                let post_data: String = std::str::from_utf8(&bytes).unwrap().to_string();;
                // Split on & to get ["key=value"...]
                let pairs = post_data.split("&");
                // Split on = to get [[key,value]...], put in user provided var name $pairs_out
                let $pairs_out = pairs.map(|pair| pair.split("=").collect::<Vec<&str>>()).collect::<Vec<Vec<&str>>>();
                // User provided block takes $pairs_out and returns response string
                let (code, response) = $block_in;
                let res = Response::new();
                Ok(res.with_status(code).with_body(response))
            }).boxed()
        }
    };
    }

    fn token_response(pairs: &Vec<Vec<&str>>) -> (StatusCode, String) {
        let mut resp = String::new();
        let mut code = StatusCode::Ok;
        resp.push_str("{");
        resp.push_str(r#""access_token": "valid_access_code","#);
        resp.push_str(r#""token_type": "Bearer","#);
        resp.push_str(r#""scope": "user-read-private user-read-email","#);
        resp.push_str(r#""expires_in": 3600"#);
        resp.push_str("}");
        for pair in pairs {
            let (key,value) = (pair[0], pair[1]);
            if key == "refresh_token" && value == "error" {
                code = StatusCode::Forbidden;
            }
        }
        (code, resp)
    }

    fn init() {
        while !WEBSERVER_STARTED.load(Ordering::Relaxed) {
            sleep(Duration::from_millis(100));
        }
        START.call_once(|| {
            #[derive(Clone, Copy)]
            struct Webapi;
            impl Service for Webapi {
                type Request = Request;
                type Response = Response;
                type Error = hyper::Error;
                type Future = futures::BoxFuture<Response, hyper::Error>;
                fn call(&self, req: Request) -> Self::Future {
                    let (method, uri, _, _headers, body) = req.deconstruct();
                    match(method, uri.path()) {
                        (Post, "/api/token") => post!(body, pairs, { token_response(&pairs) }),
                        _ => futures::future::ok(Response::new().with_status(StatusCode::NotFound)).boxed(),
                    }
                }
            }
            thread::spawn(move || {
                let addr = "127.0.0.1:9799".parse().unwrap();
                let server = Http::new().bind(&addr, || Ok(Webapi)).unwrap();
                server.run().unwrap();
                WEBSERVER_STARTED.store(true, Ordering::Relaxed);
            });
        });
    }

    #[test]
    fn test_refresh_oauth_tokens_no_connection() {
        let now = time::now_utc().to_timespec().sec as u64;
        let spotify = SpotifyConnectr::new()
            .with_api(TEST_API)
            .with_oauth_tokens("access", "refresh", now + 3600)
            .build()
            .unwrap();
        let res = spotify.refresh_oauth_tokens();
        // Unlock webserver init so all other tests can run
        WEBSERVER_STARTED.store(true, Ordering::Relaxed);
        assert!(res.is_none());
    }

    #[test]
    fn test_refresh_oauth_tokens_pass() {
        init();
        let now = time::now_utc().to_timespec().sec as u64;
        let spotify = SpotifyConnectr::new()
            .with_api(TEST_API)
            .with_oauth_tokens("access", "refresh", now + 3600)
            .build()
            .unwrap();
        match spotify.refresh_oauth_tokens() {
            Some((access,expires)) => {
                assert_eq!(access, "valid_access_code");
                assert_eq!(expires, 3600);
            },
            None => { assert!(false) },
        }
    }

    #[test]
    fn test_refresh_oauth_tokens_error_status() {
        init();
        let now = time::now_utc().to_timespec().sec as u64;
        let mut spotify = SpotifyConnectr::new()
            .with_api(TEST_API)
            .with_oauth_tokens("access", "refresh", now + 3600)
            .build()
            .unwrap();
        spotify.refresh_token = Some("error".to_string());
        match spotify.refresh_oauth_tokens() {
            Some(_) => { assert!(false) },
            None => { },
        }
    }

}
<commit_msg>Delay automated tests to wait for HTTP server to really start<commit_after>#[cfg(test)]
mod tests {
    extern crate futures;
    extern crate hyper;
    extern crate fruitbasket;
    extern crate time;

    use super::super::*;
    use super::super::super::SpotifyEndpoints;

    use std;
    use std::thread;
    use std::thread::sleep;
    use std::sync::atomic::AtomicBool;
    use std::sync::atomic::Ordering;
    use std::time::Duration;
    use std::sync::{Once, ONCE_INIT};

    use self::hyper::{Post, StatusCode};
    use self::hyper::server::{Service, Request, Response};
    use self::hyper::server::Http;
    use self::futures::Stream;
    use self::futures::Future;

    static START: Once = ONCE_INIT;

    lazy_static! {
        static ref WEBSERVER_STARTED: AtomicBool = AtomicBool::new(false);
    }

    pub const TEST_API: SpotifyEndpoints = SpotifyEndpoints {
        scopes: "user-read-private streaming user-read-playback-state",
        authorize: "http://127.0.0.1:9799/en/authorize",
        token: "http://127.0.0.1:9799/api/token",
        devices: "http://127.0.0.1:9799/v1/me/player/devices",
        player_state: "http://127.0.0.1:9799/v1/me/player",
        play: "http://127.0.0.1:9799/v1/me/player/play",
        pause: "http://127.0.0.1:9799/v1/me/player/pause",
        next: "http://127.0.0.1:9799/v1/me/player/next",
        previous: "http://127.0.0.1:9799/v1/me/player/previous",
        seek: "http://127.0.0.1:9799/v1/me/player/seek",
        volume: "http://127.0.0.1:9799/v1/me/player/volume",
        shuffle: "http://127.0.0.1:9799/v1/me/player/shuffle",
        repeat: "http://127.0.0.1:9799/v1/me/player/repeat",
        player: "http://127.0.0.1:9799/v1/me/player",
    };

    /// Macro to parse the body of a POST request and send a response.
    ///
    /// There's probably a "body.to_string()" function somewhere.  I didn't find it.
    /// So instead there's this unreadable, overly complicated bullshit.
    ///
    /// $body_in: a POST body (hyper::Body) from a received POST request
    /// $pairs_out: the name of the key/value pair variable provided to the $block_in
    /// $block_in: a block of code to be executed, with $pairs_out in scope, that evaluates
    ///            to tuple (status_code: StatusCode, body: &str) to send as a response.
    macro_rules! post {
    ($body_in:ident, $pairs_out:ident, $block_in:block) => {
        {
            // Read chunks from user provided body var $body_in
            $body_in.fold(vec![], |mut acc, chunk| {
                acc.extend(chunk);
                Ok::<_, hyper::Error>(acc)
            }).and_then(move |bytes| {
                // [u8] -> String
                let post_data: String = std::str::from_utf8(&bytes).unwrap().to_string();;
                // Split on & to get ["key=value"...]
                let pairs = post_data.split("&");
                // Split on = to get [[key,value]...], put in user provided var name $pairs_out
                let $pairs_out = pairs.map(|pair| pair.split("=").collect::<Vec<&str>>()).collect::<Vec<Vec<&str>>>();
                // User provided block takes $pairs_out and returns response string
                let (code, response) = $block_in;
                let res = Response::new();
                Ok(res.with_status(code).with_body(response))
            }).boxed()
        }
    };
    }

    fn token_response(pairs: &Vec<Vec<&str>>) -> (StatusCode, String) {
        let mut resp = String::new();
        let mut code = StatusCode::Ok;
        resp.push_str("{");
        resp.push_str(r#""access_token": "valid_access_code","#);
        resp.push_str(r#""token_type": "Bearer","#);
        resp.push_str(r#""scope": "user-read-private user-read-email","#);
        resp.push_str(r#""expires_in": 3600"#);
        resp.push_str("}");
        for pair in pairs {
            let (key,value) = (pair[0], pair[1]);
            if key == "refresh_token" && value == "error" {
                code = StatusCode::Forbidden;
            }
        }
        (code, resp)
    }

    fn init() {
        while !WEBSERVER_STARTED.load(Ordering::Relaxed) {
            sleep(Duration::from_millis(100));
        }
        START.call_once(|| {
            #[derive(Clone, Copy)]
            struct Webapi;
            impl Service for Webapi {
                type Request = Request;
                type Response = Response;
                type Error = hyper::Error;
                type Future = futures::BoxFuture<Response, hyper::Error>;
                fn call(&self, req: Request) -> Self::Future {
                    let (method, uri, _, _headers, body) = req.deconstruct();
                    match(method, uri.path()) {
                        (Post, "/api/token") => post!(body, pairs, { token_response(&pairs) }),
                        _ => futures::future::ok(Response::new().with_status(StatusCode::NotFound)).boxed(),
                    }
                }
            }
            thread::spawn(move || {
                let addr = "127.0.0.1:9799".parse().unwrap();
                let server = Http::new().bind(&addr, || Ok(Webapi)).unwrap();
                server.run().unwrap();
                WEBSERVER_STARTED.store(true, Ordering::Relaxed);
            });
            // Give it some time to really come up.  It would be nicer to
            // actually try to connect to it.
            sleep(Duration::from_millis(500));
        });
    }

    #[test]
    fn test_refresh_oauth_tokens_no_connection() {
        let now = time::now_utc().to_timespec().sec as u64;
        let spotify = SpotifyConnectr::new()
            .with_api(TEST_API)
            .with_oauth_tokens("access", "refresh", now + 3600)
            .build()
            .unwrap();
        let res = spotify.refresh_oauth_tokens();
        // Unlock webserver init so all other tests can run
        WEBSERVER_STARTED.store(true, Ordering::Relaxed);
        assert!(res.is_none());
    }

    #[test]
    fn test_refresh_oauth_tokens_pass() {
        init();
        let now = time::now_utc().to_timespec().sec as u64;
        let spotify = SpotifyConnectr::new()
            .with_api(TEST_API)
            .with_oauth_tokens("access", "refresh", now + 3600)
            .build()
            .unwrap();
        match spotify.refresh_oauth_tokens() {
            Some((access,expires)) => {
                assert_eq!(access, "valid_access_code");
                assert_eq!(expires, 3600);
            },
            None => { assert!(false) },
        }
    }

    #[test]
    fn test_refresh_oauth_tokens_error_status() {
        init();
        let now = time::now_utc().to_timespec().sec as u64;
        let mut spotify = SpotifyConnectr::new()
            .with_api(TEST_API)
            .with_oauth_tokens("access", "refresh", now + 3600)
            .build()
            .unwrap();
        spotify.refresh_token = Some("error".to_string());
        match spotify.refresh_oauth_tokens() {
            Some(_) => { assert!(false) },
            None => { },
        }
    }

}
<|endoftext|>


<commit_before>fn main() {
    println!("Hello, world!");
}
<commit_msg>First pass, start with go solver and convert to rust, before "rustifying" it.<commit_after>use std::thread

//General solver error
enum SolveError {  }

//General solver interface
trait Solver {
	fn Solved(&self) -> Result<bool,SolveError>;
	fn reducePossible(&self) -> Result<bool,SolveError>;
	fn validate(&self) -> bool
}

fn validate(known: &[u8]) -> bool{

	validNums := map[int]bool{1:true,2:true,3:true,4:true,5:true,6:true,7:true,8:true,9:true}

	for _,v := range known{
		if validNums[v]{
			validNums[v] = false
		}else{
			return false
		}
	}

	return true
}

//Cells which store individual numbers in the Grid
type cell struct {
	m_possible 	map[int]bool
	m_x,m_y 	int
}

func (c *cell) init(x,y int){
	c.m_possible = make(map[int]bool,9)
	for i:=1; i<=9; i++{
		c.m_possible[i] = true
	}
	c.m_x = x
	c.m_y = y
}

func (c *cell) validate() bool{
	if len(c.m_possible) < 1{
		return false
	}
	if len(c.m_possible) > 9{
		return false
	}
	return true
}

func (c *cell) SetKnownTo(value int){
	for k,_ := range c.m_possible{
		if k != value {
			delete(c.m_possible,k)
		}
	}
}

func (c *cell) TakeKnownFromPossible(known []int) (bool,error){

	var possibles = len(c.m_possible)

	if !c.IsKnown(){
		for _,v := range known{
			delete(c.m_possible,v)
		}

		if !c.validate(){
			errorStr := fmt.Sprintf("TakeKnownFromPossible() made cell invalid: Known:%T:%q", known,known)
			return false,errors.Wrap(SolveError{errorStr},1)
		}
	}

	return possibles != len(c.m_possible),nil //did we take any?
}

func (c* cell) IsKnown() bool{
	return len(c.m_possible) == 1
}

func (c *cell) Known() (int, error){

	// by convention we delete from the map possibles that are no longer possible
	// so we just need to check map length to see if the cell is solved
	if len(c.m_possible)!=1{
		return 0,errors.Wrap(SolveError{"Value not yet known for this cell"},1)
	}

	//Only one key is now considered "possible", it's value should be true, and it should
	//be the only one in the list, return it if that is the case
	for k,v := range c.m_possible {
		if v{
			return k,nil
		}
	}

	return 0,errors.Wrap(SolveError{"Error in cell storage of known values"},1)
}

func (c *cell) Possibles() ([]int,error){
	possibles := make([]int,0,len(c.m_possible))

	for k,v := range c.m_possible{
		if v{
			possibles = append(possibles,k)
		}
	}

	return possibles,nil
}

func (c cell) String() string {
	val,err := c.Known()
	if(err != nil){
		return "x"
	}

	return strconv.Itoa(val)
}

type cellPtrSlice []*cell

func (cells cellPtrSlice) Solved() (bool, error){
	for _,c := range cells{
		if !c.IsKnown(){
			return false,nil
		}
	}

	return true,nil
}

func (cells cellPtrSlice) Known() ([]int, error){
	known := make([]int,0, len(cells))
	for _,c := range cells{
		if c.IsKnown(){
			val,err := c.Known()
			if err != nil{
				return known,err
			}
			known = append(known,val)
		}
	}

	return known,nil
}

func (cells cellPtrSlice) TakeKnownFromPossible(known []int) (bool,error){

	changed := false
	for _,c := range cells{
		taken, err := c.TakeKnownFromPossible(known)
		if err != nil{
			return false,err
		}
		changed = changed || taken
	}

	return changed,nil
}

//Squares which represent one of each of the 9 squares in a Grid, each of which
//references a 3x3 collection of cells.

type square struct {
	m_cells [][]*cell
}

func (s square) Solved() (bool,error) {
	for _,r := range s.m_cells{
		solved,err := cellPtrSlice(r).Solved()
		if(err != nil){
			return false,err
		}
		if !solved {
			return false,nil
		}

	}
	return true,nil
}
func (s *square) init() {
	s.m_cells = make([][]*cell,SQUARE_SIZE)
	for i,_ := range s.m_cells{
		s.m_cells[i] = make(cellPtrSlice, SQUARE_SIZE)
	}
}

func (s* square) KnownInSquare() ([]int,error){
	known := make([]int,0,SQUARE_SIZE*SQUARE_SIZE)
	for x,_ := range s.m_cells{
		for y,_ := range s.m_cells[x]{
			c := s.m_cells[x][y]
			if c.IsKnown(){
				val,err := c.Known()
				if err != nil{
					return known,err
				}
				known = append(known,val)
			}
		}
	}

	return known,nil
}

func (s* square) reducePossible() (bool,error) {
	known,err := s.KnownInSquare()
	reduced := false
	if err != nil {
		return false,err
	}

	for x,_ := range s.m_cells{
		cells := s.m_cells[x]
		changed, err := cellPtrSlice(cells).TakeKnownFromPossible(known)
		if err != nil{
			return false,err
		}
		reduced = reduced || changed
	}
	return reduced,nil
}

func (s* square) validate() bool{
	known,err := s.KnownInSquare()
	if err != nil {
		return false
	}

	return validate(known)
}

type pair struct{
	m_values 		[2]int
	m_rowAligned	bool
	m_rowOrColNum	int
}

func (s* square) AlignedCellOnlyPairs() ([]pair,error){

	foundPairs := make([]pair,0,SQUARE_SIZE*SQUARE_SIZE)
	/*
	for x1,_ := range s.m_cells{
		for y1,_ := range s.m_cells[x1]{
			c1 := s.m_cells[x1][y1]
			if len(c1.m_possible)==2{
				for x2,_ := range s.m_cells{
					for y2,_ := range s.m_cells[x2]{
						c2 := s.m_cells[x2][y2]
						if c1 != c2{
							if len(c2.m_possible)==2{
								if x2 == x1 || y2 == y1{
									matchBoth := true
									valIdx :=0
									var foundPair pair
									for k,v := range c2.m_possible{
										if val,ok :=c1.m_possible[k]; !ok{
											matchBoth = false
										}else{
											pair.m_values[valIdx] = k
											valIdx++
										}
									}
									if matchBoth{
										foundPair.m_rowAligned = y2==y1
										if foundPair.m_rowAligned{
											foundPair.m_rowOrColNum = c1.m_y
										}else{
											foundPair.m_rowOrColNum = c1.m_x
										}
										foundPairs = append(foundPairs,foundPair)
									}
								}
							}
						}
					}
				}
			}
		}
	}*/

	return foundPairs,nil
}

//A horizontal or vertical line of 9 cells through the entire Grid.
type line struct {
	m_cells 		cellPtrSlice
	m_rowAligned	bool
	m_rowOrColNum	int
}

func(l *line) init(){
	l.m_cells = make([]*cell,COL_LENGTH,COL_LENGTH)
}

func (l line) Solved() (bool,error) {
	return l.m_cells.Solved()
}

func (l* line) reducePossible() (bool,error) {
	known,err := l.m_cells.Known()

	if err != nil {
		return false,err
	}

	reduced, err := l.m_cells.TakeKnownFromPossible(known)
	if err != nil{
		return false,err
	}

	return reduced,nil
}

func (l* line) validate() bool{
	known,err := l.m_cells.Known()
	if err != nil {
		return false
	}
	return validate(known)
}

func (l line) String() string{
	str := ""
	for _,c := range l.m_cells{
		if c.IsKnown(){
			v,err:= c.Known()
			if err == nil{
				str+=strconv.Itoa(v)
			}
		}else{
			str+="x"
		}
	}
	return str
}

//Grid which represents the 3x3 collection of squares which represent the entire puzzle
const ROW_LENGTH = 9
const COL_LENGTH = 9
const NUM_SQUARES = COL_LENGTH
const SQUARE_SIZE = 3

type Grid struct {
	m_squares 	[]square
	m_rows		[]line
	m_cols		[]line

	m_sets		[]Solver
	m_cells		[][]cell
}

func New(puzzle [COL_LENGTH][ROW_LENGTH]int) (*Grid, error){
	var g Grid
	g.Init();
	g.Fill(puzzle)
	return &g,nil
}

func (g *Grid) validate() bool{
	for x,_ := range g.m_cells{
		for y,_:= range g.m_cells[x]{
			if !g.m_cells[x][y].validate(){
				return false
			}
		}
	}

	for i,_ := range g.m_sets{
		if !g.m_sets[i].validate(){
			return false
		}
	}

	return true
}

func (g *Grid) Init() {
	//Init the raw cells themselves that actually store the grid data
	g.m_cells = make([][]cell,COL_LENGTH)
	for i :=0; i< len(g.m_cells); i++{
		g.m_cells[i] = make([]cell, ROW_LENGTH)

		for j :=0; j< len(g.m_cells[i]); j++{
			c := &g.m_cells[i][j]
			c.init(i,j)
		}
	}

	//Init each of the grouping structures that view portions of the grid

	/*

	Squares are indexed into the grid as folows

	S0 S1 S2
	S3 S4 S5
	S6 S7 S8

	*/
	g.m_squares = make([]square,NUM_SQUARES)

	for squareIdx :=0; squareIdx<NUM_SQUARES; squareIdx++{

		g.m_squares[squareIdx].init()
		for x :=0; x<SQUARE_SIZE; x++{
			for y:= 0; y<SQUARE_SIZE; y++{
				//is this correct?
				gridX := SQUARE_SIZE * (squareIdx % SQUARE_SIZE) + x
				gridY := SQUARE_SIZE * (squareIdx / SQUARE_SIZE) + y

				cellPtr := &g.m_cells[gridX][gridY]
				g.m_squares[squareIdx].m_cells[x][y] = cellPtr
			}
		}

	}

	g.m_rows = make([]line, ROW_LENGTH)
	g.m_cols = make([]line,COL_LENGTH)

	//Make m_sets just a big long list of all the cell grouping structures
	//handy for doing iterations over all different ways of looking at the cells
	g.m_sets = make([]Solver,len(g.m_squares) + len(g.m_rows) + len(g.m_cols))

	var idx int
	for i := 0; i<len(g.m_squares); i++{
		s:= &g.m_squares[i]
		g.m_sets[idx] = s
		idx++
	}

	for i:=0; i<len(g.m_rows); i++{
		r:=&g.m_rows[i]
		g.m_sets[idx] = r
		idx++
		r.init()
		for colNum:=0; colNum < COL_LENGTH; colNum++{
			r.m_cells[colNum] = &g.m_cells[colNum][i]
		}
		r.m_rowAligned = true
		r.m_rowOrColNum = i
	}

	for i:= 0; i<len(g.m_cols); i++{
		c := &g.m_cols[i]
		g.m_sets[idx] = c
		idx++
		c.init()
		for rowNum:=0; rowNum < ROW_LENGTH; rowNum++{
			c.m_cells[rowNum] = &g.m_cells[i][rowNum]
		}
		c.m_rowAligned = false
		c.m_rowOrColNum = i
	}

}

func (g *Grid) Fill(puzzle [COL_LENGTH][ROW_LENGTH]int){
	g.Init()

	for x:=0; x<COL_LENGTH; x++{
		for y:=0; y<ROW_LENGTH; y++{
			var puzzVal = puzzle[y][x]

			if puzzVal >=1 && puzzVal<=9{
				g.m_cells[x][y].SetKnownTo(puzzVal)
			}
		}
	}

}

func (g Grid) Solved() (bool,error) {
	for _,s := range g.m_sets{
		solved,err := s.Solved()
		if err != nil{
			fmt.Println("Error during Solved() check on grid: " + err.Error())
			return false,err
		}

		if !solved{
			return false,nil
		}
	}

	return true,nil
}

func (g *Grid) squareExclusionReduce() (bool,error){
	changed := false
	/*for i,_ := range g.m_squares{
		s := &g.m_squares[i]
		pairs, err := s.AlignedCellOnlyPairs()
		if err != nil{
			return false,err
		}
		for _,p := range pairs{

		}

	}*/

	return changed,nil
}

func(g *Grid) reducePossiblePass() (bool, error){
	changed := false

	for pass:=0;pass<2;pass++{
		for i,_ := range g.m_sets{
			reduced,err := g.m_sets[i].reducePossible()
			if err != nil{
				return false,err
			}
			changed = changed || reduced
		}
		sqReduce,err := g.squareExclusionReduce()
		if err != nil{
				return false,err
		}
		changed = changed || sqReduce
	}

	return changed,nil
}

func (g *Grid) Puzzle() [COL_LENGTH][ROW_LENGTH]int{
	var puzzle [COL_LENGTH][ROW_LENGTH]int
	for x,_ := range puzzle{
		for y,_ := range puzzle[x]{
			if g.m_cells[x][y].IsKnown(){
				var err error
				puzzle[y][x],err = g.m_cells[x][y].Known()
				if err != nil{
					return puzzle
				}
			}
		}
	}

	return puzzle
}

func (g *Grid) setKnown( x,y, known int) error{
	//should probably check if grid is initialised and return error if it isn't
	g.m_cells[x][y].SetKnownTo(known)

	return nil
}

func (g *Grid) DuplicateGrid() (*Grid,error){
	return New(g.Puzzle())
}

func (g* Grid) TotalPossible() (int, error){
	totalPoss := 0
	for x,_ := range g.m_cells{
		for y,_:= range g.m_cells[x]{
			if !g.m_cells[x][y].IsKnown(){
				val,err := g.m_cells[x][y].Possibles()
				if err != nil{
					return 0,err
				}
				numPoss := len(val)
				totalPoss += numPoss
			}
		}

	}
	return totalPoss,nil
}

func (g *Grid) GenerateGuessGrids() ([]*Grid, error){

	totalPoss,err := g.TotalPossible()
	guesses := make([]*Grid,0,totalPoss)
	if err != nil{
		return guesses,err
	}
	smallPoss := 99
	smX:=0
	smY:=0
	for x,_ := range g.m_cells{
		for y,_:= range g.m_cells[x]{
			if !g.m_cells[x][y].IsKnown(){

				possibles,err := g.m_cells[x][y].Possibles()
				if err!=nil{
					return guesses,err
				}
				if len(possibles) < smallPoss{
					smallPoss=len(possibles)
					smX=x
					smY=y
				}

			}
		}
	}

	if smallPoss < 99{
		possibles,err := g.m_cells[smX][smY].Possibles()
		if err!=nil{
			return guesses,err
		}
		for _,v := range possibles{
			guess,err := g.DuplicateGrid()
			if err!=nil{
				return guesses,err
			}
			err = guess.setKnown(smX,smY,v)
			if err!=nil{
				return guesses,err
			}
			guesses = append(guesses,guess)
		}
	}

	return guesses,nil

}

type SolveResult struct{
	m_grid 		*Grid
	m_solved 	bool
}

func (s *SolveResult) Grid() *Grid{
	return s.m_grid
}

func (s *SolveResult) Solved() bool{
	return s.m_solved
}

func startSolveRoutine(ch chan SolveResult, g *Grid) {

	defer close(ch)
	res, err := g.Solve()
	if err != nil{
		//this error might be expected, we might have sent in an invalid puzzle
		//only care about this response to print or pass on in the root call to solve.
		return
	}

	ch<-*res
}

func (g *Grid) Solve() (*SolveResult,error){

	var err error
	for changed:=true; changed;{
		changed, err = g.reducePossiblePass()
		if err != nil{
			return &SolveResult{nil,false},err
		}
		if !g.validate(){
			return &SolveResult{nil,false},nil //this was probably an invalid guess, just want to stop trying to process this
		}
	}

	solved,err := g.Solved()
	if err != nil{
			return &SolveResult{nil,false},err
	}

	if solved{
		return &SolveResult{g,true},nil
	}

	guesses,err := g.GenerateGuessGrids()

	if err!=nil{
		return &SolveResult{g,false},err
	}

	resChans := make([]chan SolveResult,0,len(guesses))

	for _,guess := range guesses{
		ch := make(chan SolveResult)
		go startSolveRoutine(ch,guess)
		resChans = append(resChans,ch)
	}

	for i,_ := range resChans{
		for res:= range resChans[i] {
			if res.m_solved{
				return &res,nil
			}
		}
	}

	return &SolveResult{nil,false},errors.Wrap(SolveError{"Unable to solve puzzle"},1)
}

func (g *Grid) KnownEquals(puzzle [COL_LENGTH][ROW_LENGTH]int) bool{
	thisPuzz := g.Puzzle()
	for x,_ := range puzzle{
		for y,_ := range puzzle[x]{
			if puzzle[x][y] != thisPuzz[x][y]{
				return false
			}
		}
	}
	return true
}

func (g Grid) String() string {
	var str string

	if len(g.m_cells) < COL_LENGTH{
		return "Grid probably not initialised"
	}

	for x:=0; x < ROW_LENGTH; x++{
		for y:=0; y < COL_LENGTH; y++{

			if len(g.m_cells[y]) < ROW_LENGTH{
				return "Error in grid not all rows correctly initialised"
			}

			cell := g.m_cells[y][x]
			str += cell.String()
		}
		str+="\n"
	}
	return str
}

<|endoftext|>


<commit_before>use std::collections::HashMap;
use std::path::Path;

#[derive(Debug, Default)]
pub struct LanguageSpec {
    pub reserved_words: HashMap<String, String>,
    pub hash_comment: bool,
    pub c_style_comments: bool,
    pub backtick_strings: bool,
    pub regexp_literals: bool,
    pub triple_quote_literals: bool,
    pub c_preprocessor: bool,
    // Rust is mostly C-like, with a couple of differences.
    pub rust_tweaks: bool,
    pub cxx14_digit_separators: bool,
}

fn make_reserved(v: &[&str]) -> HashMap<String, String> {
    let mut reserved_words = HashMap::new();
    for word in v {
        reserved_words.insert(word.to_string(), "class=\"syn_reserved\" ".to_string());
    }
    reserved_words
}

lazy_static! {
    static ref RESERVED_WORDS_JS : Vec<&'static str> = vec![
        "abstract", "else", "instanceof", "super",
        "boolean", "enum", "int", "switch",
        "break", "export", "interface", "synchronized",
        "byte", "extends", "let", "this",
        "case", "false", "long", "throw",
        "catch", "final", "native", "throws",
        "char", "finally", "new", "transient",
        "class", "float", "null", "true",
        "const", "for", "package", "try",
        "continue", "function", "private", "typeof",
        "debugger", "goto", "protected", "var",
        "default", "if", "public", "void",
        "delete", "implements", "return", "volatile",
        "do", "import", "short", "while",
        "double", "in", "static", "with",
        "get", "set",
    ];

    static ref RESERVED_WORDS_CPP : Vec<&'static str> = vec![
        "alignas", "alignof", "and", "and_eq", "asm", "atomic_cancel",
        "atomic_commit", "atomic_noexcept", "auto", "bitand", "bitor", "bool", "break",
        "case", "catch", "char", "char16_t", "char32_t", "class", "compl", "concept",
        "const", "constexpr", "const_cast", "continue", "decltype", "default", "delete",
        "do", "double", "dynamic_cast", "else", "enum", "explicit", "export", "extern", "false",
        "float", "for", "friend", "goto", "if", "inline", "int", "import", "long", "module",
        "mutable", "namespace", "new", "noexcept", "not", "not_eq", "nullptr",
        // Don't mark "operator" as a keyword so that people can click
        // on it.
        //"operator",
        "or", "or_eq", "private", "protected", "public", "register", "reinterpret_cast",
        "requires", "return", "short", "signed", "sizeof", "static", "static_assert",
        "static_cast", "struct", "switch", "synchronized", "template", "this", "thread_local",
        "throw", "true", "try", "typedef", "typeid", "typename", "union", "unsigned",
        "using", "virtual", "void", "volatile", "wchar_t", "while", "xor", "xor_eq",
        "#if", "#ifdef", "#ifndef", "#else", "#elif", "#endif", "#define", "#undef",
        "#include", "#error", "defined",
    ];

    // From 'reserved' in ipc/ipdl/ipdl/parser.py
    static ref RESERVED_WORDS_IPDL : Vec<&'static str> = vec![
        "async", "both", "child", "class", "compress", "compressall", "from",
        "include", "intr", "manager", "manages", "namespace", "nested",
        "nullable", "or", "parent", "prio", "protocol", "refcounted",
        "moveonly", "returns", "struct", "sync", "union", "UniquePtr", "upto",
        "using", "verify",
    ];

    static ref RESERVED_WORDS_IDL : Vec<&'static str> = vec![
        "cenum", "const", "interface", "in", "inout", "out", "attribute", "raises",
        "readonly", "native", "typedef", "webidl",
        "array", "shared", "iid_is", "size_is", "retval",
        "boolean", "void", "octet", "short", "long",
        "unsigned", "float", "double", "char", "string", "wchar", "wstring",
        "nsid", "AUTF8String", "ACString", "AString", "jsval", "Promise",
        "ptr", "ref",
        "uuid", "scriptable", "builtinclass", "function", "noscript", "deprecated",
        "object", "main_process_scriptable_only",
        "binaryname", "notxpcom", "symbol", "implicit_jscontext", "nostdcall",
        "must_use", "infallible", "can_run_script",
    ];

    static ref RESERVED_WORDS_WEBIDL : Vec<&'static str> = vec![
        "module", "interface", "partial", "dictionary", "exception", "enum", "callback",
        "typedef", "implements", "const", "null", "true", "false", "serializer",
        "stringifier", "jsonifier", "unrestricted", "attribute", "readonly", "inherit",
        "static", "getter", "setter", "creator", "deleter", "legacycaller", "optional",
        "Date", "DOMString", "ByteString", "USVString", "any", "boolean", "byte",
        "double", "float", "long", "object", "octet", "Promise", "required", "sequence",
        "MozMap", "short", "unsigned", "void", "ArrayBuffer", "SharedArrayBuffer", "or",
        "maplike", "setlike", "iterable",
        "Exposed", "ChromeOnly", "ChromeConstructor", "Pref", "Func", "AvailableIn",
        "CheckAnyPermissions", "CheckAllPermissions", "JSImplementation", "HeaderFile",
        "NavigatorProperty", "AvailableIn", "Func", "CheckAnyPermissions", "CheckAllPermissions",
        "Deprecated", "NeedResolve", "OverrideBuiltins", "ChromeOnly", "Unforgeable",
        "UnsafeInPrerendering", "LegacyEventInit", "ProbablyShortLivingObject", "ArrayClass",
        "Clamp", "Constructor", "EnforceRange", "ExceptionClass", "Exposed", "ImplicitThis",
        "Global", "PrimaryGlobal", "LegacyArrayClass", "LegacyUnenumerableNamedProperties",
        "LenientSetter", "LenientThis", "NamedConstructor", "NewObject", "NoInterfaceObject",
        "OverrideBuiltins", "PutForwards", "Replaceable", "SameObject", "SecureContext",
        "Throws", "TreatNonObjectAsNull", "TreatNullAs", "Unforgeable", "Unscopable",
    ];

    static ref RESERVED_WORDS_PYTHON : Vec<&'static str> = vec![
        "and", "del", "from", "not", "while",
        "as", "elif", "global", "or", "with",
        "assert", "else", "if", "pass", "yield",
        "break", "except", "import", "print",
        "class", "exec", "in", "raise", "continue",
        "finally", "is", "return",
        "def", "for", "lambda", "try",
    ];

    // List of Rust reserved words pulled from
    // https://github.com/rust-lang/rust/blob/master/src/libsyntax/symbol.rs
    static ref RESERVED_WORDS_RUST : Vec<&'static str> = vec![
        "as", "box", "break", "const", "continue", "crate",
        "else", "enum", "extern", "false", "fn", "for", "if",
        "impl", "in", "let", "loop", "match", "mod", "move",
        "mut", "pub", "ref", "return", "self", "Self", "static",
        "struct", "super", "trait", "true", "type", "unsafe",
        "use", "where", "while",

        "abstract", "alignof", "become", "do", "final", "macro",
        "offsetof", "override", "priv", "proc", "pure", "sizeof",
        "typeof", "unsized", "virtual", "yield",

        "default", "union",
    ];

    static ref RESERVED_WORDS_JAVA : Vec<&'static str> = vec![
        "abstract", "continue", "for", "new", "switch", "assert", "default",
        "goto", "package", "synchronized", "boolean", "do", "if", "private",
        "this", "break", "double", "implements", "protected", "throw", "byte",
        "else", "import", "public", "throws", "case", "enum", "instanceof",
        "return", "transient", "catch", "extends", "int", "short", "try",
        "char", "final", "interface", "static", "void", "class", "finally",
        "long", "strictfp", "volatile", "const", "float", "native", "super",
        "while", "null", "true", "false",
    ];

    // http://kotlinlang.org/docs/reference/keyword-reference.html
    static ref RESERVED_WORDS_KOTLIN : Vec<&'static str> = vec![
        "as", "as?", "break", "class", "continue", "do", "else", "false",
        "for", "fun", "if", "in", "!in", "interface", "is", "!is", "null",
        "object", "package", "return", "super", "this", "throw", "true",
        "try", "typealias", "val", "var", "when", "while",

        "by", "catch", "constructor", "delegate", "dynamic", "field", "file",
        "finally", "get", "import", "init", "param", "property", "receiver",
        "set", "setparam", "where",

        "actual", "abstract", "annotation", "companion", "const",
        "crossinline", "data", "enum", "expect", "external", "final", "infix",
        "inline", "inner", "internal", "lateinit", "noinline", "open",
        "operator", "out", "override", "private", "protected", "public",
        "reified", "sealed", "suspend", "tailrec", "vararg",

        "field", "it",
    ];

    static ref JS_SPEC : LanguageSpec = LanguageSpec {
        reserved_words: make_reserved(&*RESERVED_WORDS_JS),
        c_style_comments: true,
        backtick_strings: true,
        regexp_literals: true,
        .. LanguageSpec::default()
    };

    static ref CPP_SPEC : LanguageSpec = LanguageSpec {
        reserved_words: make_reserved(&*RESERVED_WORDS_CPP),
        c_style_comments: true,
        c_preprocessor: true,
        cxx14_digit_separators: true,
        .. LanguageSpec::default()
    };

    static ref IPDL_SPEC : LanguageSpec = LanguageSpec {
        reserved_words: make_reserved(&*RESERVED_WORDS_IPDL),
        c_style_comments: true,
        .. LanguageSpec::default()
    };

    static ref IDL_SPEC : LanguageSpec = LanguageSpec {
        reserved_words: make_reserved(&*RESERVED_WORDS_IDL),
        c_style_comments: true,
        .. LanguageSpec::default()
    };

    static ref WEBIDL_SPEC : LanguageSpec = LanguageSpec {
        reserved_words: make_reserved(&*RESERVED_WORDS_WEBIDL),
        c_style_comments: true,
        .. LanguageSpec::default()
    };

    static ref PYTHON_SPEC : LanguageSpec = LanguageSpec {
        reserved_words: make_reserved(&*RESERVED_WORDS_PYTHON),
        hash_comment: true,
        triple_quote_literals: true,
        .. LanguageSpec::default()
    };

    static ref RUST_SPEC : LanguageSpec = LanguageSpec {
        reserved_words: make_reserved(&*RESERVED_WORDS_RUST),
        hash_comment: true, // for now, for attributes
        c_style_comments: true,
        rust_tweaks: true,
        .. LanguageSpec::default()
    };

    static ref JAVA_SPEC : LanguageSpec = LanguageSpec {
        reserved_words: make_reserved(&*RESERVED_WORDS_JAVA),
        c_style_comments: true,
        .. LanguageSpec::default()
    };

    static ref KOTLIN_SPEC : LanguageSpec = LanguageSpec {
        reserved_words: make_reserved(&*RESERVED_WORDS_KOTLIN),
        c_style_comments: true,
        .. LanguageSpec::default()
    };
}

#[derive(Debug)]
pub enum FormatAs {
    FormatCLike(&'static LanguageSpec),
    FormatTagLike(&'static LanguageSpec),
    Plain,
    Binary,
}

pub fn select_formatting(filename: &str) -> FormatAs {
    let ext = match Path::new(filename).extension() {
        Some(ext) => ext.to_str().unwrap(),
        None => "",
    };
    match ext {
        "c" | "cc" | "cpp" | "cxx" | "h" | "hh" | "hxx" | "hpp" | "mm" => FormatAs::FormatCLike(&*CPP_SPEC),
        "ipdl" | "ipdlh" => FormatAs::FormatCLike(&*IPDL_SPEC),
        "idl" => FormatAs::FormatCLike(&*IDL_SPEC),
        "webidl" => FormatAs::FormatCLike(&*WEBIDL_SPEC),
        "js" | "jsm" | "json" | "sjs" => FormatAs::FormatCLike(&*JS_SPEC),
        "py" | "build" | "configure" => FormatAs::FormatCLike(&*PYTHON_SPEC),
        "rs" => FormatAs::FormatCLike(&*RUST_SPEC),
        "java" => FormatAs::FormatCLike(&*JAVA_SPEC),
        "kt" => FormatAs::FormatCLike(&*KOTLIN_SPEC),

        "html" | "htm" | "xhtml" | "xht" | "xml" | "xul" => FormatAs::FormatTagLike(&*JS_SPEC),

        // Keep this list in sync with the binary types list in nginx-setup.py
        "ogg" | "ttf" | "xpi" | "png" | "bcmap" | "gif" | "ogv" | "jpg" | "jpeg" | "bmp"
        | "icns" | "ico" | "mp4" | "sqlite" | "jar" | "webm" | "webp" | "woff" | "class"
        | "m4s" | "mgif" | "wav" | "opus" | "mp3" | "otf" => FormatAs::Binary,

        _ => FormatAs::Plain,
    }
}
<commit_msg>Use less lazy_static in languages.rs<commit_after>use std::collections::HashMap;
use std::path::Path;

#[derive(Debug, Default)]
pub struct LanguageSpec {
    pub reserved_words: HashMap<String, String>,
    pub hash_comment: bool,
    pub c_style_comments: bool,
    pub backtick_strings: bool,
    pub regexp_literals: bool,
    pub triple_quote_literals: bool,
    pub c_preprocessor: bool,
    // Rust is mostly C-like, with a couple of differences.
    pub rust_tweaks: bool,
    pub cxx14_digit_separators: bool,
}

fn make_reserved(v: &[&str]) -> HashMap<String, String> {
    let mut reserved_words = HashMap::new();
    for word in v {
        reserved_words.insert(word.to_string(), "class=\"syn_reserved\" ".to_string());
    }
    reserved_words
}

static RESERVED_WORDS_JS: &'static [&'static str] = &[
    "abstract", "else", "instanceof", "super",
    "boolean", "enum", "int", "switch",
    "break", "export", "interface", "synchronized",
    "byte", "extends", "let", "this",
    "case", "false", "long", "throw",
    "catch", "final", "native", "throws",
    "char", "finally", "new", "transient",
    "class", "float", "null", "true",
    "const", "for", "package", "try",
    "continue", "function", "private", "typeof",
    "debugger", "goto", "protected", "var",
    "default", "if", "public", "void",
    "delete", "implements", "return", "volatile",
    "do", "import", "short", "while",
    "double", "in", "static", "with",
    "get", "set",
];

static RESERVED_WORDS_CPP: &'static [&'static str] = &[
    "alignas", "alignof", "and", "and_eq", "asm", "atomic_cancel",
    "atomic_commit", "atomic_noexcept", "auto", "bitand", "bitor", "bool", "break",
    "case", "catch", "char", "char16_t", "char32_t", "class", "compl", "concept",
    "const", "constexpr", "const_cast", "continue", "decltype", "default", "delete",
    "do", "double", "dynamic_cast", "else", "enum", "explicit", "export", "extern", "false",
    "float", "for", "friend", "goto", "if", "inline", "int", "import", "long", "module",
    "mutable", "namespace", "new", "noexcept", "not", "not_eq", "nullptr",
    // Don't mark "operator" as a keyword so that people can click
    // on it.
    //"operator",
    "or", "or_eq", "private", "protected", "public", "register", "reinterpret_cast",
    "requires", "return", "short", "signed", "sizeof", "static", "static_assert",
    "static_cast", "struct", "switch", "synchronized", "template", "this", "thread_local",
    "throw", "true", "try", "typedef", "typeid", "typename", "union", "unsigned",
    "using", "virtual", "void", "volatile", "wchar_t", "while", "xor", "xor_eq",
    "#if", "#ifdef", "#ifndef", "#else", "#elif", "#endif", "#define", "#undef",
    "#include", "#error", "defined",
];

// From 'reserved' in ipc/ipdl/ipdl/parser.py
static RESERVED_WORDS_IPDL: &'static [&'static str] = &[
    "async", "both", "child", "class", "compress", "compressall", "from",
    "include", "intr", "manager", "manages", "namespace", "nested",
    "nullable", "or", "parent", "prio", "protocol", "refcounted",
    "moveonly", "returns", "struct", "sync", "union", "UniquePtr", "upto",
    "using", "verify",
];

static RESERVED_WORDS_IDL: &'static [&'static str] = &[
    "cenum", "const", "interface", "in", "inout", "out", "attribute", "raises",
    "readonly", "native", "typedef", "webidl",
    "array", "shared", "iid_is", "size_is", "retval",
    "boolean", "void", "octet", "short", "long",
    "unsigned", "float", "double", "char", "string", "wchar", "wstring",
    "nsid", "AUTF8String", "ACString", "AString", "jsval", "Promise",
    "ptr", "ref",
    "uuid", "scriptable", "builtinclass", "function", "noscript", "deprecated",
    "object", "main_process_scriptable_only",
    "binaryname", "notxpcom", "symbol", "implicit_jscontext", "nostdcall",
    "must_use", "infallible", "can_run_script",
];

static RESERVED_WORDS_WEBIDL: &'static [&'static str] = &[
    "module", "interface", "partial", "dictionary", "exception", "enum", "callback",
    "typedef", "implements", "const", "null", "true", "false", "serializer",
    "stringifier", "jsonifier", "unrestricted", "attribute", "readonly", "inherit",
    "static", "getter", "setter", "creator", "deleter", "legacycaller", "optional",
    "Date", "DOMString", "ByteString", "USVString", "any", "boolean", "byte",
    "double", "float", "long", "object", "octet", "Promise", "required", "sequence",
    "MozMap", "short", "unsigned", "void", "ArrayBuffer", "SharedArrayBuffer", "or",
    "maplike", "setlike", "iterable",
    "Exposed", "ChromeOnly", "ChromeConstructor", "Pref", "Func", "AvailableIn",
    "CheckAnyPermissions", "CheckAllPermissions", "JSImplementation", "HeaderFile",
    "NavigatorProperty", "AvailableIn", "Func", "CheckAnyPermissions", "CheckAllPermissions",
    "Deprecated", "NeedResolve", "OverrideBuiltins", "ChromeOnly", "Unforgeable",
    "UnsafeInPrerendering", "LegacyEventInit", "ProbablyShortLivingObject", "ArrayClass",
    "Clamp", "Constructor", "EnforceRange", "ExceptionClass", "Exposed", "ImplicitThis",
    "Global", "PrimaryGlobal", "LegacyArrayClass", "LegacyUnenumerableNamedProperties",
    "LenientSetter", "LenientThis", "NamedConstructor", "NewObject", "NoInterfaceObject",
    "OverrideBuiltins", "PutForwards", "Replaceable", "SameObject", "SecureContext",
    "Throws", "TreatNonObjectAsNull", "TreatNullAs", "Unforgeable", "Unscopable",
];

static RESERVED_WORDS_PYTHON: &'static [&'static str] = &[
    "and", "del", "from", "not", "while",
    "as", "elif", "global", "or", "with",
    "assert", "else", "if", "pass", "yield",
    "break", "except", "import", "print",
    "class", "exec", "in", "raise", "continue",
    "finally", "is", "return",
    "def", "for", "lambda", "try",
];

// List of Rust reserved words pulled from
// https://github.com/rust-lang/rust/blob/master/src/libsyntax/symbol.rs
static RESERVED_WORDS_RUST: &'static [&'static str] = &[
    "as", "box", "break", "const", "continue", "crate",
    "else", "enum", "extern", "false", "fn", "for", "if",
    "impl", "in", "let", "loop", "match", "mod", "move",
    "mut", "pub", "ref", "return", "self", "Self", "static",
    "struct", "super", "trait", "true", "type", "unsafe",
    "use", "where", "while",

    "abstract", "alignof", "become", "do", "final", "macro",
    "offsetof", "override", "priv", "proc", "pure", "sizeof",
    "typeof", "unsized", "virtual", "yield",

    "default", "union",
];

static RESERVED_WORDS_JAVA: &'static [&'static str] = &[
    "abstract", "continue", "for", "new", "switch", "assert", "default",
    "goto", "package", "synchronized", "boolean", "do", "if", "private",
    "this", "break", "double", "implements", "protected", "throw", "byte",
    "else", "import", "public", "throws", "case", "enum", "instanceof",
    "return", "transient", "catch", "extends", "int", "short", "try",
    "char", "final", "interface", "static", "void", "class", "finally",
    "long", "strictfp", "volatile", "const", "float", "native", "super",
    "while", "null", "true", "false",
];

// http://kotlinlang.org/docs/reference/keyword-reference.html
static RESERVED_WORDS_KOTLIN: &'static [&'static str] = &[
    "as", "as?", "break", "class", "continue", "do", "else", "false",
    "for", "fun", "if", "in", "!in", "interface", "is", "!is", "null",
    "object", "package", "return", "super", "this", "throw", "true",
    "try", "typealias", "val", "var", "when", "while",

    "by", "catch", "constructor", "delegate", "dynamic", "field", "file",
    "finally", "get", "import", "init", "param", "property", "receiver",
    "set", "setparam", "where",

    "actual", "abstract", "annotation", "companion", "const",
    "crossinline", "data", "enum", "expect", "external", "final", "infix",
    "inline", "inner", "internal", "lateinit", "noinline", "open",
    "operator", "out", "override", "private", "protected", "public",
    "reified", "sealed", "suspend", "tailrec", "vararg",

    "field", "it",
];

lazy_static! {
    static ref JS_SPEC : LanguageSpec = LanguageSpec {
        reserved_words: make_reserved(&*RESERVED_WORDS_JS),
        c_style_comments: true,
        backtick_strings: true,
        regexp_literals: true,
        .. LanguageSpec::default()
    };

    static ref CPP_SPEC : LanguageSpec = LanguageSpec {
        reserved_words: make_reserved(&*RESERVED_WORDS_CPP),
        c_style_comments: true,
        c_preprocessor: true,
        cxx14_digit_separators: true,
        .. LanguageSpec::default()
    };

    static ref IPDL_SPEC : LanguageSpec = LanguageSpec {
        reserved_words: make_reserved(&*RESERVED_WORDS_IPDL),
        c_style_comments: true,
        .. LanguageSpec::default()
    };

    static ref IDL_SPEC : LanguageSpec = LanguageSpec {
        reserved_words: make_reserved(&*RESERVED_WORDS_IDL),
        c_style_comments: true,
        .. LanguageSpec::default()
    };

    static ref WEBIDL_SPEC : LanguageSpec = LanguageSpec {
        reserved_words: make_reserved(&*RESERVED_WORDS_WEBIDL),
        c_style_comments: true,
        .. LanguageSpec::default()
    };

    static ref PYTHON_SPEC : LanguageSpec = LanguageSpec {
        reserved_words: make_reserved(&*RESERVED_WORDS_PYTHON),
        hash_comment: true,
        triple_quote_literals: true,
        .. LanguageSpec::default()
    };

    static ref RUST_SPEC : LanguageSpec = LanguageSpec {
        reserved_words: make_reserved(&*RESERVED_WORDS_RUST),
        hash_comment: true, // for now, for attributes
        c_style_comments: true,
        rust_tweaks: true,
        .. LanguageSpec::default()
    };

    static ref JAVA_SPEC : LanguageSpec = LanguageSpec {
        reserved_words: make_reserved(&*RESERVED_WORDS_JAVA),
        c_style_comments: true,
        .. LanguageSpec::default()
    };

    static ref KOTLIN_SPEC : LanguageSpec = LanguageSpec {
        reserved_words: make_reserved(&*RESERVED_WORDS_KOTLIN),
        c_style_comments: true,
        .. LanguageSpec::default()
    };
}

#[derive(Debug)]
pub enum FormatAs {
    FormatCLike(&'static LanguageSpec),
    FormatTagLike(&'static LanguageSpec),
    Plain,
    Binary,
}

pub fn select_formatting(filename: &str) -> FormatAs {
    let ext = match Path::new(filename).extension() {
        Some(ext) => ext.to_str().unwrap(),
        None => "",
    };
    match ext {
        "c" | "cc" | "cpp" | "cxx" | "h" | "hh" | "hxx" | "hpp" | "mm" => FormatAs::FormatCLike(&*CPP_SPEC),
        "ipdl" | "ipdlh" => FormatAs::FormatCLike(&*IPDL_SPEC),
        "idl" => FormatAs::FormatCLike(&*IDL_SPEC),
        "webidl" => FormatAs::FormatCLike(&*WEBIDL_SPEC),
        "js" | "jsm" | "json" | "sjs" => FormatAs::FormatCLike(&*JS_SPEC),
        "py" | "build" | "configure" => FormatAs::FormatCLike(&*PYTHON_SPEC),
        "rs" => FormatAs::FormatCLike(&*RUST_SPEC),
        "java" => FormatAs::FormatCLike(&*JAVA_SPEC),
        "kt" => FormatAs::FormatCLike(&*KOTLIN_SPEC),

        "html" | "htm" | "xhtml" | "xht" | "xml" | "xul" => FormatAs::FormatTagLike(&*JS_SPEC),

        // Keep this list in sync with the binary types list in nginx-setup.py
        "ogg" | "ttf" | "xpi" | "png" | "bcmap" | "gif" | "ogv" | "jpg" | "jpeg" | "bmp"
        | "icns" | "ico" | "mp4" | "sqlite" | "jar" | "webm" | "webp" | "woff" | "class"
        | "m4s" | "mgif" | "wav" | "opus" | "mp3" | "otf" => FormatAs::Binary,

        _ => FormatAs::Plain,
    }
}
<|endoftext|>


<commit_before>// Built-in Lints
// Clippy lints
#![allow(
    clippy::map_unwrap_or,
    clippy::match_same_arms,
    clippy::type_complexity,
    clippy::needless_doctest_main
)]
#![warn(
    clippy::unwrap_used,
    clippy::print_stdout,
    clippy::mut_mut,
    clippy::non_ascii_literal,
    clippy::similar_names,
    clippy::unicode_not_nfc,
    clippy::enum_glob_use,
    clippy::if_not_else,
    clippy::items_after_statements,
    clippy::used_underscore_binding,
    missing_debug_implementations,
    missing_copy_implementations
)]
#![cfg_attr(test, allow(clippy::unwrap_used))]
extern crate proc_macro;

mod embed_migrations;
mod migrations;

use proc_macro::TokenStream;

/// This macro will read your migrations at compile time, and create a constant value containing
/// an embedded list of all your migrations as available at compile time.
/// This is useful if you would like to use Diesel's migration infrastructure, but want to ship a single executable
/// file (such as for embedded applications). It can also be used to apply migrations to an in
/// memory database (Diesel does this for its own test suite).
///
/// You can optionally pass the path to the migrations directory to this macro. When left
/// unspecified, Diesel will search for the migrations directory in the same way that
/// Diesel CLI does. If specified, the path should be relative to the directory where `Cargo.toml`
/// resides.
///
/// # Examples
///
/// ```rust
/// use diesel_migrations::{embed_migrations, EmbeddedMigrations, MigrationHarness};
/// # use std::error::Error;
/// # include!("../../../diesel/src/doctest_setup.rs");
/// #
/// # #[cfg(feature = "postgres")]
/// # fn migration_connection() -> diesel::PgConnection {
/// #    let connection_url = database_url_from_env("PG_DATABASE_URL");
/// #    let mut conn = diesel::PgConnection::establish(&connection_url).unwrap();
/// #    conn.begin_test_transaction().unwrap();
/// #    conn
/// # }
/// #
/// # #[cfg(feature = "sqlite")]
/// # fn migration_connection() -> diesel::SqliteConnection {
/// #    let connection_url = database_url_from_env("SQLITE_DATABASE_URL");
/// #    let mut conn = diesel::SqliteConnection::establish(&connection_url).unwrap();
/// #    conn.begin_test_transaction().unwrap();
/// #    conn
/// # }
/// #
/// # #[cfg(feature = "mysql")]
/// # fn migration_connection() -> diesel::MysqlConnection {
/// #    let connection_url = database_url_from_env("MYSQL_DATABASE_URL");
/// #    let mut conn = diesel::MysqlConnection::establish(&connection_url).unwrap();
/// #    conn
/// # }
/// #
/// #
/// # #[cfg(feature = "postgres")]
/// pub const MIGRATIONS: EmbeddedMigrations = embed_migrations!("../../migrations/postgresql");
/// # #[cfg(all(feature = "mysql", not(feature = "postgres")))]
/// # pub const MIGRATIONS: EmbeddedMigrations = embed_migrations!("../../migrations/mysql");
/// # #[cfg(all(feature = "sqlite", not(any(feature = "postgres", feature = "mysql"))))]
/// # pub const MIGRATIONS: EmbeddedMigrations = embed_migrations!("../../migrations/sqlite");
///
/// # fn main() {
/// #     let connection = &mut migration_connection();
/// #     run_migrations(connection).unwrap();
/// # }
///
/// fn run_migrations(connection: &mut impl MigrationHarness<DB>) -> Result<(), Box<dyn Error + Send + Sync + 'static>> {
/// #   #[cfg(feature = "mysql")]
/// #   connection.revert_all_migrations(MIGRATIONS)?;
///
///     // This will run the necessary migrations.
///     //
///     // See the documentation for `MigrationHarness` for
///     // all available methods.
///     connection.run_pending_migrations(MIGRATIONS)?;
///
///     Ok(())
/// }
/// ```
///
/// # Automatic rebuilds
///
/// Due to limitations in rusts proc-macro API there is currently no
/// way to signal that a specific proc macro should be rerun if some
/// external file changes/is added. This implies that `embed_migrations!`
/// cannot regenerate the list of embedded migrations if **only** the
/// migrations are changed. This limitation can be solved by adding a
/// custom `build.rs` file to your crate, such that the crate is rebuild
/// if the migration directory changes.
///
/// Add the following `build.rs` file to your project to fix the problem
///
/// ```
/// fn main() {
///    println!("cargo:rerun-if-changed=path/to/your/migration/dir/reletive/to/your/Cargo.toml");
/// }
/// ```
#[proc_macro]
pub fn embed_migrations(input: TokenStream) -> TokenStream {
    embed_migrations::expand(input.to_string())
        .to_string()
        .parse()
        .expect("Failed create embedded migrations instance")
}
<commit_msg>Update diesel_migrations/migrations_macros/src/lib.rs<commit_after>// Built-in Lints
// Clippy lints
#![allow(
    clippy::map_unwrap_or,
    clippy::match_same_arms,
    clippy::type_complexity,
    clippy::needless_doctest_main
)]
#![warn(
    clippy::unwrap_used,
    clippy::print_stdout,
    clippy::mut_mut,
    clippy::non_ascii_literal,
    clippy::similar_names,
    clippy::unicode_not_nfc,
    clippy::enum_glob_use,
    clippy::if_not_else,
    clippy::items_after_statements,
    clippy::used_underscore_binding,
    missing_debug_implementations,
    missing_copy_implementations
)]
#![cfg_attr(test, allow(clippy::unwrap_used))]
extern crate proc_macro;

mod embed_migrations;
mod migrations;

use proc_macro::TokenStream;

/// This macro will read your migrations at compile time, and create a constant value containing
/// an embedded list of all your migrations as available at compile time.
/// This is useful if you would like to use Diesel's migration infrastructure, but want to ship a single executable
/// file (such as for embedded applications). It can also be used to apply migrations to an in
/// memory database (Diesel does this for its own test suite).
///
/// You can optionally pass the path to the migrations directory to this macro. When left
/// unspecified, Diesel will search for the migrations directory in the same way that
/// Diesel CLI does. If specified, the path should be relative to the directory where `Cargo.toml`
/// resides.
///
/// # Examples
///
/// ```rust
/// use diesel_migrations::{embed_migrations, EmbeddedMigrations, MigrationHarness};
/// # use std::error::Error;
/// # include!("../../../diesel/src/doctest_setup.rs");
/// #
/// # #[cfg(feature = "postgres")]
/// # fn migration_connection() -> diesel::PgConnection {
/// #    let connection_url = database_url_from_env("PG_DATABASE_URL");
/// #    let mut conn = diesel::PgConnection::establish(&connection_url).unwrap();
/// #    conn.begin_test_transaction().unwrap();
/// #    conn
/// # }
/// #
/// # #[cfg(feature = "sqlite")]
/// # fn migration_connection() -> diesel::SqliteConnection {
/// #    let connection_url = database_url_from_env("SQLITE_DATABASE_URL");
/// #    let mut conn = diesel::SqliteConnection::establish(&connection_url).unwrap();
/// #    conn.begin_test_transaction().unwrap();
/// #    conn
/// # }
/// #
/// # #[cfg(feature = "mysql")]
/// # fn migration_connection() -> diesel::MysqlConnection {
/// #    let connection_url = database_url_from_env("MYSQL_DATABASE_URL");
/// #    let mut conn = diesel::MysqlConnection::establish(&connection_url).unwrap();
/// #    conn
/// # }
/// #
/// #
/// # #[cfg(feature = "postgres")]
/// pub const MIGRATIONS: EmbeddedMigrations = embed_migrations!("../../migrations/postgresql");
/// # #[cfg(all(feature = "mysql", not(feature = "postgres")))]
/// # pub const MIGRATIONS: EmbeddedMigrations = embed_migrations!("../../migrations/mysql");
/// # #[cfg(all(feature = "sqlite", not(any(feature = "postgres", feature = "mysql"))))]
/// # pub const MIGRATIONS: EmbeddedMigrations = embed_migrations!("../../migrations/sqlite");
///
/// # fn main() {
/// #     let connection = &mut migration_connection();
/// #     run_migrations(connection).unwrap();
/// # }
///
/// fn run_migrations(connection: &mut impl MigrationHarness<DB>) -> Result<(), Box<dyn Error + Send + Sync + 'static>> {
/// #   #[cfg(feature = "mysql")]
/// #   connection.revert_all_migrations(MIGRATIONS)?;
///
///     // This will run the necessary migrations.
///     //
///     // See the documentation for `MigrationHarness` for
///     // all available methods.
///     connection.run_pending_migrations(MIGRATIONS)?;
///
///     Ok(())
/// }
/// ```
///
/// # Automatic rebuilds
///
/// Due to limitations in rusts proc-macro API there is currently no
/// way to signal that a specific proc macro should be rerun if some
/// external file changes/is added. This implies that `embed_migrations!`
/// cannot regenerate the list of embedded migrations if **only** the
/// migrations are changed. This limitation can be solved by adding a
/// custom `build.rs` file to your crate, such that the crate is rebuild
/// if the migration directory changes.
///
/// Add the following `build.rs` file to your project to fix the problem
///
/// ```
/// fn main() {
///    println!("cargo:rerun-if-changed=path/to/your/migration/dir/relative/to/your/Cargo.toml");
/// }
/// ```
#[proc_macro]
pub fn embed_migrations(input: TokenStream) -> TokenStream {
    embed_migrations::expand(input.to_string())
        .to_string()
        .parse()
        .expect("Failed create embedded migrations instance")
}
<|endoftext|>