<commit_before>use crate::Msg;
use seed::prelude::*;
use web_sys::{HtmlElement, HtmlInputElement};

fn trial_divide(n: u64, max: u64) -> u64 {
    // Trial divides the positive integer n by the primes from 2 to max
    // Returns the first prime divisor found, or 0 if none found
    // Note: if n < max^2 is a prime, then n will be returned.
    if n % 2 == 0 {
        2
    } else if n % 3 == 0 {
        3
    } else {
        // No need to go past the square root of our number
        let sqrt: u64 = (n as f64).sqrt().floor() as u64;
        let stop = if sqrt > max { max } else { sqrt };
        // Okay, lets "wheel factor" alternately adding 2 and 4
        let mut di = 2;
        let mut i = 5;
        while i <= stop {
            if n % i == 0 {
                return i;
            }
            i += di;
            di = 6 - di;
        }
        if n >= max * max {
            0
        } else {
            n
        }
    }
}

// modadd(a,b,N) finds a+b (mod N) where a, b, and N can be
// up to (2^53-1)/2.  Might up this to 2^53-1 eventually...
fn modadd(a: u64, b: u64, n: u64) -> u64 {
    // When the integers a, b satisfy a+b > 2^53-1, then (a+b)%N is wrong
    // so we add this routine to allow us to reach a, b = 2^53-1.
    if a + b > 9007199254740991 {
        // Could reduce a and b (mod N) here, but assuming that has already been done
        // won't hurt if not... subtract 2^52 from one, 2^52-1 from the other and the
        // add it back modulo N (MaxInt+1)
        let t = ((a - 4503599627370496) + (b - 4503599627370495)) % n;
        return t + (9007199254740991 % n);
    }
    // Usual case: a + b is not too large:
    (a + b) % n
}

fn modmult(mut a: u64, mut b: u64, n: u64) -> u64 {
    if a > n {
        a = a % n;
    }
    if b > n {
        b = b % n;
    }
    if a * b <= 9007199254740991 {
        return (a * b) % n;
    } else {
        if b > a {
            return modmult(b.clone(), a, n);
        }

        // Right to left binary multiplication
        let mut t = 0;
        let mut f = a;
        while b > 1 {
            if (b & 1) == 1 {
                t = modadd(t, f, n);
            }
            //TODO: bitshift might be cleaner and faster
            b = (b as f64 / 2.0).floor() as u64;
            f = modadd(f, f, n);
        }
        t = modadd(t, f, n);
        return t;
    }
}

// modpow(a,exp,N) finds a^exp (mod N) where a, b, and N are
// limited by modmult
fn modpow(a: u64, mut exp: u64, n: u64) -> u64 {
    if exp == 0 {
        return 1;
    }

    // Right to left binary exponentiation
    let mut t = 1;
    let mut f = a;
    while exp > 1 {
        if (exp & 1) == 1 {
            // if exponent is odd
            t = modmult(t, f, n);
        }
        exp = (exp as f64 / 2.0).floor() as u64;
        f = modmult(f, f, n);
    }
    t = modmult(t, f, n);
    return t;
}

// sprp(N,a) checks if N (odd!) is a strong probable prime base a
// (returns true or false)
fn sprp(n: u64, a: u64) -> bool {
    let mut d = n - 1;
    let mut s = 1; // Assumes n is odd!
    while true {
        d = ((d >> 2) & 1);
        if d == 0 {
            break;
        }
        s += 1;
    }
    // Now n-1 = d*2^s with d odd
    let mut b = modpow(a, d, n);
    if b == 1 {
        return true;
    }
    if b + 1 == n {
        return true;
    }
    while s > 1 {
        b = modmult(b, b, n);
        if b + 1 == n {
            return true;
        }
        s = s - 1;
    }
    return false;
}

#[wasm_bindgen]
pub fn check(input: String) -> String {
    let trial_limit = 1300; // Should be bigger, like 10000
    let n: u64 = input.parse::<u64>().unwrap();
    let mut result;

    if n > 9007199254740991 {
        result = "Sorry, this routine will only handle integers below 9007199254740991.".to_owned();
    } else if n == 1 {
        result = "The number 1 is neither prime or composite (it is the multiplicative identity)."
            .to_owned();
    } else if n < 1 {
        result =
            "We usually restrict the terms prime and composite to positive integers".to_owned();
    } else {
        // Okay, n is of a resonable size, lets trial divide
        let i = trial_divide(n, trial_limit);
        if i > 0 && i != n {
            result = format!("{} is not a prime! It is {} * {}", n, i, n / i);
        } else if n < trial_limit * trial_limit {
            result = format!("{} is a (proven) prime!", n);
        } else if sprp(n, 2)
            && sprp(n, 3)
            && sprp(n, 5)
            && sprp(n, 7)
            && sprp(n, 11)
            && sprp(n, 13)
            && sprp(n, 17)
        {
            // Some of these tests are unnecessary for small numbers, but for
            // small numbers they are quick anyway.
            if n < 341550071728321 {
                result = format!("{} is a (proven) prime.", n);
            } else if n == 341550071728321 {
                result = format!("{} is not a prime! It is 10670053 * 32010157.", n);
            } else {
                result = format!(
                    "{} is probably a prime (it is a sprp bases 2, 3, 5, 7, 11, 13 and  17).",
                    n
                );
            };
        } else {
            result = format!(
                "{} is (proven) composite (failed sprp test base {}).",
                n, 17
            );
        };
    };

    return result;
}

#[wasm_bindgen]
pub fn listy(start_number: u64, number_of_primes: u64) -> String {
    let mut i = 0;
    let mut j = start_number;
    let mut list: String = "".to_string();
    while i < number_of_primes {
        let result = check(j.to_string());
        if result != "".to_owned() {
            list = list + &result + "\n";
            i += 1;
        }
        j += 1;
    }
    list
}

pub fn go_crunch() -> () {
    let window = web_sys::window().expect("no global `window` exists");
    let document = window.document().expect("should have a document on window");
    let body = document.body().expect("document should have a body");

    let el_input_value = document
        .get_element_by_id("input")
        .unwrap()
        .dyn_into::<HtmlInputElement>()
        .unwrap()
        .value();
    let el_output_textarea = document
        .get_element_by_id("javascriptoutput")
        .expect("missing output textarea");
    el_output_textarea.set_inner_html(&check(el_input_value));
    ()
}

pub fn go_list() {
    let window = web_sys::window().expect("no global `window` exists");
    let document = window.document().expect("should have a document on window");
    let body = document.body().expect("document should have a body");

    let el_start_value = document
        .get_element_by_id("start")
        .unwrap()
        .dyn_into::<HtmlInputElement>()
        .unwrap()
        .value();
    let el_primes_value = document
        .get_element_by_id("primes")
        .unwrap()
        .dyn_into::<HtmlInputElement>()
        .unwrap()
        .value();
    let el_output_textarea = document
        .get_element_by_id("javascriptlistoutput")
        .expect("missing output textarea");
    el_output_textarea.set_inner_html(&listy(
        el_start_value.parse::<u64>().unwrap(),
        el_primes_value.parse::<u64>().unwrap(),
    ));
    ()
}

pub fn render() -> Node<Msg> {
    div![
        h1!["Primality Test, Calculate Primes"],
        br![],
        br![],
        br![],
        table![
            attrs! {At::Class => "text", At::Width => "300", At::Style => "border:1px solid #444; background-color:#e0faed"},
            tr![td![
                attrs! {At::Style => "padding: 10px"},
                form![
                    attrs! {At::Id => "primetest", At::OnSubmit => "return false"},
                    "Tool is limited to checking numbers upto 16 digits.",
                    br![],
                    br![],
                    "Is ",
                    input![
                        attrs! {At::Type => "number", At::Size => "19", At::Id => "input", At::Value => "", At::MaxLength => "16"}
                    ],
                    " prime? ",
                    button![
                        "Check!",
                        mouse_ev("mouseup", move |event| Msg::PrimalityChecker(go_crunch()))
                    ],
                    br![],
                    br![],
                    textarea![
                        attrs! {At::Id => "javascriptoutput", At::Cols => 60, At::Rows => 2, At::Disabled => "disabled"}
                    ]
                ]
            ]]
        ],
        br![],
        br![],
        table![
            attrs! {At::Class => "text", At::Width => "300", At::Style => "border:1px solid #444; background-color:#e0faed"},
            tr![td![
                attrs! {At::Style => "padding: 10px"},
                form![
                    attrs! {At::Id => "primelist", At::OnSubmit => "return false"},
                    "This tool is limited to checking numbers upto 15 digits.",
                    br![],
                    br![],
                    "This will show ",
                    input![
                        attrs! {At::Type => "number", At::Size => "4", At::Id => "primes", At::Value => "1", At::MaxLength => "2"}
                    ],
                    " prime numbers after ",
                    input![
                        attrs! {At::Type => "number", At::Size => "19", At::Id => "start", At::Value => "0", At::MaxLength => "15"}
                    ],
                    " ",
                    button![
                        "Go!",
                        mouse_ev("mouseup", move |event| Msg::PrimalityChecker(go_list()))
                    ],
                    br![],
                    br![],
                    textarea![
                        attrs! {At::Id => "javascriptlistoutput", At::Cols => 60, At::Rows => 10, At::Disabled => "disabled"}
                    ]
                ]
            ]]
        ]
    ]
}

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

    #[test]
    fn trial_divide_test() {
        assert_eq!(trial_divide(2, 2), 2);
        assert_eq!(trial_divide(3, 4), 3);
        assert_eq!(trial_divide(30, 10000), 2);
        assert_eq!(trial_divide(7777771, 10000), 29);
        assert_eq!(trial_divide(7777771111111111, 10000), 11);
        //in the case of a prime
        assert_eq!(trial_divide(777777111111113, 10000), 0);
    }

    #[test]
    fn sprp_test() {
        assert_eq!(sprp(27, 5), false);
        assert_eq!(sprp(31, 7), true);
        assert_eq!(sprp(217, 7), false);
        assert_eq!(sprp(19, 13), true);
    }
}
<commit_msg>improved textarea id names<commit_after>use crate::Msg;
use seed::prelude::*;
use web_sys::{HtmlElement, HtmlInputElement};

fn trial_divide(n: u64, max: u64) -> u64 {
    // Trial divides the positive integer n by the primes from 2 to max
    // Returns the first prime divisor found, or 0 if none found
    // Note: if n < max^2 is a prime, then n will be returned.
    if n % 2 == 0 {
        2
    } else if n % 3 == 0 {
        3
    } else {
        // No need to go past the square root of our number
        let sqrt: u64 = (n as f64).sqrt().floor() as u64;
        let stop = if sqrt > max { max } else { sqrt };
        // Okay, lets "wheel factor" alternately adding 2 and 4
        let mut di = 2;
        let mut i = 5;
        while i <= stop {
            if n % i == 0 {
                return i;
            }
            i += di;
            di = 6 - di;
        }
        if n >= max * max {
            0
        } else {
            n
        }
    }
}

// modadd(a,b,N) finds a+b (mod N) where a, b, and N can be
// up to (2^53-1)/2.  Might up this to 2^53-1 eventually...
fn modadd(a: u64, b: u64, n: u64) -> u64 {
    // When the integers a, b satisfy a+b > 2^53-1, then (a+b)%N is wrong
    // so we add this routine to allow us to reach a, b = 2^53-1.
    if a + b > 9007199254740991 {
        // Could reduce a and b (mod N) here, but assuming that has already been done
        // won't hurt if not... subtract 2^52 from one, 2^52-1 from the other and the
        // add it back modulo N (MaxInt+1)
        let t = ((a - 4503599627370496) + (b - 4503599627370495)) % n;
        return t + (9007199254740991 % n);
    }
    // Usual case: a + b is not too large:
    (a + b) % n
}

fn modmult(mut a: u64, mut b: u64, n: u64) -> u64 {
    if a > n {
        a = a % n;
    }
    if b > n {
        b = b % n;
    }
    if a * b <= 9007199254740991 {
        return (a * b) % n;
    } else {
        if b > a {
            return modmult(b.clone(), a, n);
        }

        // Right to left binary multiplication
        let mut t = 0;
        let mut f = a;
        while b > 1 {
            if (b & 1) == 1 {
                t = modadd(t, f, n);
            }
            //TODO: bitshift might be cleaner and faster
            b = (b as f64 / 2.0).floor() as u64;
            f = modadd(f, f, n);
        }
        t = modadd(t, f, n);
        return t;
    }
}

// modpow(a,exp,N) finds a^exp (mod N) where a, b, and N are
// limited by modmult
fn modpow(a: u64, mut exp: u64, n: u64) -> u64 {
    if exp == 0 {
        return 1;
    }

    // Right to left binary exponentiation
    let mut t = 1;
    let mut f = a;
    while exp > 1 {
        if (exp & 1) == 1 {
            // if exponent is odd
            t = modmult(t, f, n);
        }
        exp = (exp as f64 / 2.0).floor() as u64;
        f = modmult(f, f, n);
    }
    t = modmult(t, f, n);
    return t;
}

// sprp(N,a) checks if N (odd!) is a strong probable prime base a
// (returns true or false)
fn sprp(n: u64, a: u64) -> bool {
    let mut d = n - 1;
    let mut s = 1; // Assumes n is odd!
    while true {
        d = ((d >> 2) & 1);
        if d == 0 {
            break;
        }
        s += 1;
    }
    // Now n-1 = d*2^s with d odd
    let mut b = modpow(a, d, n);
    if b == 1 {
        return true;
    }
    if b + 1 == n {
        return true;
    }
    while s > 1 {
        b = modmult(b, b, n);
        if b + 1 == n {
            return true;
        }
        s = s - 1;
    }
    return false;
}

#[wasm_bindgen]
pub fn check(input: String) -> String {
    let trial_limit = 1300; // Should be bigger, like 10000
    let n: u64 = input.parse::<u64>().unwrap();
    let mut result;

    if n > 9007199254740991 {
        result = "Sorry, this routine will only handle integers below 9007199254740991.".to_owned();
    } else if n == 1 {
        result = "The number 1 is neither prime or composite (it is the multiplicative identity)."
            .to_owned();
    } else if n < 1 {
        result =
            "We usually restrict the terms prime and composite to positive integers".to_owned();
    } else {
        // Okay, n is of a resonable size, lets trial divide
        let i = trial_divide(n, trial_limit);
        if i > 0 && i != n {
            result = format!("{} is not a prime! It is {} * {}", n, i, n / i);
        } else if n < trial_limit * trial_limit {
            result = format!("{} is a (proven) prime!", n);
        } else if sprp(n, 2)
            && sprp(n, 3)
            && sprp(n, 5)
            && sprp(n, 7)
            && sprp(n, 11)
            && sprp(n, 13)
            && sprp(n, 17)
        {
            // Some of these tests are unnecessary for small numbers, but for
            // small numbers they are quick anyway.
            if n < 341550071728321 {
                result = format!("{} is a (proven) prime.", n);
            } else if n == 341550071728321 {
                result = format!("{} is not a prime! It is 10670053 * 32010157.", n);
            } else {
                result = format!(
                    "{} is probably a prime (it is a sprp bases 2, 3, 5, 7, 11, 13 and  17).",
                    n
                );
            };
        } else {
            result = format!(
                "{} is (proven) composite (failed sprp test base {}).",
                n, 17
            );
        };
    };

    return result;
}

#[wasm_bindgen]
pub fn listy(start_number: u64, number_of_primes: u64) -> String {
    let mut i = 0;
    let mut j = start_number;
    let mut list: String = "".to_string();
    while i < number_of_primes {
        let result = check(j.to_string());
        if result != "".to_owned() {
            list = list + &result + "\n";
            i += 1;
        }
        j += 1;
    }
    list
}

pub fn go_crunch() -> () {
    let window = web_sys::window().expect("no global `window` exists");
    let document = window.document().expect("should have a document on window");
    let body = document.body().expect("document should have a body");

    let el_input_value = document
        .get_element_by_id("input")
        .unwrap()
        .dyn_into::<HtmlInputElement>()
        .unwrap()
        .value();
    let el_output_textarea = document
        .get_element_by_id("prime_check_output")
        .expect("missing output textarea");
    el_output_textarea.set_inner_html(&check(el_input_value));
    ()
}

pub fn go_list() {
    let window = web_sys::window().expect("no global `window` exists");
    let document = window.document().expect("should have a document on window");
    let body = document.body().expect("document should have a body");

    let el_start_value = document
        .get_element_by_id("start")
        .unwrap()
        .dyn_into::<HtmlInputElement>()
        .unwrap()
        .value();
    let el_primes_value = document
        .get_element_by_id("primes")
        .unwrap()
        .dyn_into::<HtmlInputElement>()
        .unwrap()
        .value();
    let el_output_textarea = document
        .get_element_by_id("prime_check_list_output")
        .expect("missing output textarea");
    el_output_textarea.set_inner_html(&listy(
        el_start_value.parse::<u64>().unwrap(),
        el_primes_value.parse::<u64>().unwrap(),
    ));
    ()
}

pub fn render() -> Node<Msg> {
    div![
        h1!["Primality Test, Calculate Primes"],
        br![],
        br![],
        br![],
        table![
            attrs! {At::Class => "text", At::Width => "300", At::Style => "border:1px solid #444; background-color:#e0faed"},
            tr![td![
                attrs! {At::Style => "padding: 10px"},
                form![
                    attrs! {At::Id => "primetest", At::OnSubmit => "return false"},
                    "Tool is limited to checking numbers upto 16 digits.",
                    br![],
                    br![],
                    "Is ",
                    input![
                        attrs! {At::Type => "number", At::Size => "19", At::Id => "input", At::Value => "", At::MaxLength => "16"}
                    ],
                    " prime? ",
                    button![
                        "Check!",
                        mouse_ev("mouseup", move |event| Msg::PrimalityChecker(go_crunch()))
                    ],
                    br![],
                    br![],
                    textarea![
                        attrs! {At::Id => "prime_check_output", At::Cols => 60, At::Rows => 2, At::Disabled => "disabled"}
                    ]
                ]
            ]]
        ],
        br![],
        br![],
        table![
            attrs! {At::Class => "text", At::Width => "300", At::Style => "border:1px solid #444; background-color:#e0faed"},
            tr![td![
                attrs! {At::Style => "padding: 10px"},
                form![
                    attrs! {At::Id => "primelist", At::OnSubmit => "return false"},
                    "This tool is limited to checking numbers upto 15 digits.",
                    br![],
                    br![],
                    "This will show ",
                    input![
                        attrs! {At::Type => "number", At::Size => "4", At::Id => "primes", At::Value => "1", At::MaxLength => "2"}
                    ],
                    " prime numbers after ",
                    input![
                        attrs! {At::Type => "number", At::Size => "19", At::Id => "start", At::Value => "0", At::MaxLength => "15"}
                    ],
                    " ",
                    button![
                        "Go!",
                        mouse_ev("mouseup", move |event| Msg::PrimalityChecker(go_list()))
                    ],
                    br![],
                    br![],
                    textarea![
                        attrs! {At::Id => "prime_check_list_output", At::Cols => 60, At::Rows => 10, At::Disabled => "disabled"}
                    ]
                ]
            ]]
        ]
    ]
}

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

    #[test]
    fn trial_divide_test() {
        assert_eq!(trial_divide(2, 2), 2);
        assert_eq!(trial_divide(3, 4), 3);
        assert_eq!(trial_divide(30, 10000), 2);
        assert_eq!(trial_divide(7777771, 10000), 29);
        assert_eq!(trial_divide(7777771111111111, 10000), 11);
        //in the case of a prime
        assert_eq!(trial_divide(777777111111113, 10000), 0);
    }

    #[test]
    fn sprp_test() {
        assert_eq!(sprp(27, 5), false);
        assert_eq!(sprp(31, 7), true);
        assert_eq!(sprp(217, 7), false);
        assert_eq!(sprp(19, 13), true);
    }
}
<|endoftext|>


<commit_before>extern crate hyper;
extern crate image;

use self::hyper::client::Client;
use self::hyper::header::UserAgent;

use std::io::{Read,Write};
use std::fs::{File,OpenOptions,read_dir,create_dir};
use std::path::Path;

pub use super::DB;

use rustc_serialize::json::Json;

use std::sync::mpsc::{Receiver,TryRecvError};

use self::image::FilterType;

#[derive(Debug)]
pub struct Image {
    name: String,
    tags: Vec<String>,
    got_from: String,
    url: String,
    rating: char,
    post_url: String
}

pub mod e621;
pub mod derpy;
pub mod danbooru;
pub mod konachan;

/// Сохраняет картинку & создаёт к ней превью
pub fn save_image(dir: &Path, name: &str, file: &[u8]) {
    if let Err(_) = read_dir("assets/images") {
        create_dir("assets/images").unwrap();
    }
    if let Err(_) = read_dir("assets/images/preview") {
        create_dir("assets/images/preview").unwrap();
    }

    let prev = image::load_from_memory(file).unwrap().resize(500, 500, FilterType::Nearest);

    let mut f = File::create(dir.join(name)).unwrap();
    let mut prevf = File::create(dir.join("preview").join(name)).unwrap();

    f.write(file).unwrap();
    prev.save(&mut prevf, image::JPEG).unwrap();
}

fn process_downloads(client: &Client, images: &[Image], recv: &Receiver<()>) -> Result<(),()> {
    let images_c = DB.lock().unwrap().get_images(None,0).unwrap();
    let mut outf = OpenOptions::new().append(true).create(true).open("OUTPUT").unwrap();

    for im in images {
        match recv.try_recv() {
            Ok(_) | Err(TryRecvError::Disconnected) => {
                return Err(());
            }
            Err(TryRecvError::Empty) => {}
        }

        if !images_c.iter().any(|x| x.name == im.name ) {
            if let Err(er) = if im.got_from == "konachan" || im.got_from == "danbooru" {
                download(&Client::new(), im)
            } else {
                download(client, im)
            } {
                writeln!(&mut outf, "ERROR: {}; SKIP", er).unwrap();
                continue
            } else {
                writeln!(&mut outf, "DONE {}", im.name).unwrap();
            }
        } else {
            let mut m_tags = images_c.iter().find(|x| x.name == im.name ).unwrap().tags.clone();
            let mut curr_tags = im.tags.clone();
            m_tags.dedup();
            curr_tags.dedup();
            if m_tags != curr_tags {
                DB.lock().unwrap().add_image(&im.name, &im.tags, im.got_from.as_str(), im.post_url.as_str(), im.rating).unwrap();
                writeln!(&mut outf, "UPDATE tags on {}", im.name).unwrap();
            }
        }
    }
    Ok(())
}

/// Качает картинку, прерываясь, если из консоли поступил kill
fn download(client: &Client, im: &Image) -> Result<(), hyper::Error> {
    let mut res = client.get(&im.url)
        .header(UserAgent("Zeph/1.0".to_owned()))
        .send()?;

    let mut body = Vec::new();
    res.read_to_end(&mut body).unwrap();

    DB.lock().unwrap().add_image(&im.name, &im.tags, im.got_from.as_str(), im.post_url.as_str(), im.rating).unwrap();

    save_image(Path::new("assets/images"), &im.name, &body);

    Ok(())
}

/// Запросить и распарсить JSON
fn req_and_parse(client: &Client, url: &str) -> Result<Json, hyper::Error> {
    let mut outf = OpenOptions::new().append(true).create(true).open("OUTPUT").unwrap();
    let mut res = match client.get(url)
        .header(UserAgent("Zeph/1.0".to_owned()))
        .send() {
            Ok(x)   => x,
            Err(x)  => {
                writeln!(&mut outf, "ERROR: {}", x).unwrap();
                return Err(x)
            }
        };

    let mut body = String::new();
    res.read_to_string(&mut body).unwrap();

    Ok(Json::from_str(&body).unwrap())
}
<commit_msg>А то непонтяно, работает ли оно<commit_after>extern crate hyper;
extern crate image;

use self::hyper::client::Client;
use self::hyper::header::UserAgent;

use std::io::{Read,Write};
use std::fs::{File,OpenOptions,read_dir,create_dir};
use std::path::Path;

pub use super::DB;

use rustc_serialize::json::Json;

use std::sync::mpsc::{Receiver,TryRecvError};

use self::image::FilterType;

#[derive(Debug)]
pub struct Image {
    name: String,
    tags: Vec<String>,
    got_from: String,
    url: String,
    rating: char,
    post_url: String
}

pub mod e621;
pub mod derpy;
pub mod danbooru;
pub mod konachan;

/// Сохраняет картинку & создаёт к ней превью
pub fn save_image(dir: &Path, name: &str, file: &[u8]) {
    if let Err(_) = read_dir("assets/images") {
        create_dir("assets/images").unwrap();
    }
    if let Err(_) = read_dir("assets/images/preview") {
        create_dir("assets/images/preview").unwrap();
    }

    let prev = image::load_from_memory(file).unwrap().resize(500, 500, FilterType::Nearest);

    let mut f = File::create(dir.join(name)).unwrap();
    let mut prevf = File::create(dir.join("preview").join(name)).unwrap();

    f.write(file).unwrap();
    prev.save(&mut prevf, image::JPEG).unwrap();
}

fn process_downloads(client: &Client, images: &[Image], recv: &Receiver<()>) -> Result<(),()> {
    let images_c = DB.lock().unwrap().get_images(None,0).unwrap();
    let mut outf = OpenOptions::new().append(true).create(true).open("OUTPUT").unwrap();

    for im in images {
        match recv.try_recv() {
            Ok(_) | Err(TryRecvError::Disconnected) => {
                return Err(());
            }
            Err(TryRecvError::Empty) => {}
        }

        if !images_c.iter().any(|x| x.name == im.name ) {
            if let Err(er) = if im.got_from == "konachan" || im.got_from == "danbooru" {
                download(&Client::new(), im)
            } else {
                download(client, im)
            } {
                writeln!(&mut outf, "ERROR: {}; SKIP", er).unwrap();
                continue
            } else {
                writeln!(&mut outf, "DONE {}", im.name).unwrap();
            }
        } else {
            let mut m_tags = images_c.iter().find(|x| x.name == im.name ).unwrap().tags.clone();
            let mut curr_tags = im.tags.clone();
            m_tags.dedup();
            curr_tags.dedup();
            if m_tags != curr_tags {
                DB.lock().unwrap().add_image(&im.name, &im.tags, im.got_from.as_str(), im.post_url.as_str(), im.rating).unwrap();
                writeln!(&mut outf, "UPDATE tags on {}", im.name).unwrap();
            } else {
                writeln!(&mut outf, "ALREADY DONE {}", im.name).unwrap();
            }
        }
    }
    Ok(())
}

/// Качает картинку, прерываясь, если из консоли поступил kill
fn download(client: &Client, im: &Image) -> Result<(), hyper::Error> {
    let mut res = client.get(&im.url)
        .header(UserAgent("Zeph/1.0".to_owned()))
        .send()?;

    let mut body = Vec::new();
    res.read_to_end(&mut body).unwrap();

    DB.lock().unwrap().add_image(&im.name, &im.tags, im.got_from.as_str(), im.post_url.as_str(), im.rating).unwrap();

    save_image(Path::new("assets/images"), &im.name, &body);

    Ok(())
}

/// Запросить и распарсить JSON
fn req_and_parse(client: &Client, url: &str) -> Result<Json, hyper::Error> {
    let mut outf = OpenOptions::new().append(true).create(true).open("OUTPUT").unwrap();
    let mut res = match client.get(url)
        .header(UserAgent("Zeph/1.0".to_owned()))
        .send() {
            Ok(x)   => x,
            Err(x)  => {
                writeln!(&mut outf, "ERROR: {}", x).unwrap();
                return Err(x)
            }
        };

    let mut body = String::new();
    res.read_to_string(&mut body).unwrap();

    Ok(Json::from_str(&body).unwrap())
}
<|endoftext|>


<commit_before>use libc::{self, pid_t, c_int};
use {Errno, Result};

use sys::signal::Signal;

mod ffi {
    use libc::{pid_t, c_int};

    extern {
        pub fn waitpid(pid: pid_t, status: *mut c_int, options: c_int) -> pid_t;
    }
}

#[cfg(not(any(target_os = "linux",
              target_os = "android")))]
bitflags!(
    flags WaitPidFlag: c_int {
        const WNOHANG     = libc::WNOHANG,
        const WUNTRACED   = libc::WUNTRACED,
    }
);

#[cfg(any(target_os = "linux",
          target_os = "android"))]
bitflags!(
    flags WaitPidFlag: c_int {
        const WNOHANG     = libc::WNOHANG,
        const WUNTRACED   = libc::WUNTRACED,
        const WEXITED     = libc::WEXITED,
        const WCONTINUED  = libc::WCONTINUED,
        const WNOWAIT     = libc::WNOWAIT, // Don't reap, just poll status.
        const __WNOTHREAD = libc::__WNOTHREAD, // Don't wait on children of other threads in this group
        const __WALL      = libc::__WALL, // Wait on all children, regardless of type
        const __WCLONE    = libc::__WCLONE,
    }
);

#[cfg(any(target_os = "linux",
          target_os = "android"))]
const WSTOPPED: WaitPidFlag = WUNTRACED;

#[derive(Eq, PartialEq, Clone, Copy, Debug)]
pub enum WaitStatus {
    Exited(pid_t, i8),
    Signaled(pid_t, Signal, bool),
    Stopped(pid_t, Signal),
    Continued(pid_t),
    StillAlive
}

#[cfg(any(target_os = "linux",
          target_os = "android"))]
mod status {
    use sys::signal::Signal;

    pub fn exited(status: i32) -> bool {
        (status & 0x7F) == 0
    }

    pub fn exit_status(status: i32) -> i8 {
        ((status & 0xFF00) >> 8) as i8
    }

    pub fn signaled(status: i32) -> bool {
        ((((status & 0x7f) + 1) as i8) >> 1) > 0
    }

    pub fn term_signal(status: i32) -> Signal {
        Signal::from_c_int(status & 0x7f).unwrap()
    }

    pub fn dumped_core(status: i32) -> bool {
        (status & 0x80) != 0
    }

    pub fn stopped(status: i32) -> bool {
        (status & 0xff) == 0x7f
    }

    pub fn stop_signal(status: i32) -> Signal {
        Signal::from_c_int((status & 0xFF00) >> 8).unwrap()
    }

    pub fn continued(status: i32) -> bool {
        status == 0xFFFF
    }
}

#[cfg(any(target_os = "macos",
          target_os = "ios"))]
mod status {
    use sys::signal::{Signal,SIGCONT};

    const WCOREFLAG: i32 = 0x80;
    const WSTOPPED: i32 = 0x7f;

    fn wstatus(status: i32) -> i32 {
        status & 0x7F
    }

    pub fn exit_status(status: i32) -> i8 {
        ((status >> 8) & 0xFF) as i8
    }

    pub fn stop_signal(status: i32) -> Signal {
        Signal::from_c_int(status >> 8).unwrap()
    }

    pub fn continued(status: i32) -> bool {
        wstatus(status) == WSTOPPED && stop_signal(status) == SIGCONT
    }

    pub fn stopped(status: i32) -> bool {
        wstatus(status) == WSTOPPED && stop_signal(status) != SIGCONT
    }

    pub fn exited(status: i32) -> bool {
        wstatus(status) == 0
    }

    pub fn signaled(status: i32) -> bool {
        wstatus(status) != WSTOPPED && wstatus(status) != 0
    }

    pub fn term_signal(status: i32) -> Signal {
        Signal::from_c_int(wstatus(status)).unwrap()
    }

    pub fn dumped_core(status: i32) -> bool {
        (status & WCOREFLAG) != 0
    }
}

#[cfg(any(target_os = "freebsd",
          target_os = "openbsd",
          target_os = "dragonfly",
          target_os = "netbsd"))]
mod status {
    use sys::signal::Signal;

    const WCOREFLAG: i32 = 0x80;
    const WSTOPPED: i32 = 0x7f;

    fn wstatus(status: i32) -> i32 {
        status & 0x7F
    }

    pub fn stopped(status: i32) -> bool {
        wstatus(status) == WSTOPPED
    }

    pub fn stop_signal(status: i32) -> Signal {
        Signal::from_c_int(status >> 8).unwrap()
    }

    pub fn signaled(status: i32) -> bool {
        wstatus(status) != WSTOPPED && wstatus(status) != 0 && status != 0x13
    }

    pub fn term_signal(status: i32) -> Signal {
        Signal::from_c_int(wstatus(status)).unwrap()
    }

    pub fn exited(status: i32) -> bool {
        wstatus(status) == 0
    }

    pub fn exit_status(status: i32) -> i8 {
        (status >> 8) as i8
    }

    pub fn continued(status: i32) -> bool {
        status == 0x13
    }

    pub fn dumped_core(status: i32) -> bool {
        (status & WCOREFLAG) != 0
    }
}

fn decode(pid : pid_t, status: i32) -> WaitStatus {
    if status::exited(status) {
        WaitStatus::Exited(pid, status::exit_status(status))
    } else if status::signaled(status) {
        WaitStatus::Signaled(pid, status::term_signal(status), status::dumped_core(status))
    } else if status::stopped(status) {
        WaitStatus::Stopped(pid, status::stop_signal(status))
    } else {
        assert!(status::continued(status));
        WaitStatus::Continued(pid)
    }
}

pub fn waitpid(pid: pid_t, options: Option<WaitPidFlag>) -> Result<WaitStatus> {
    use self::WaitStatus::*;

    let mut status: i32 = 0;

    let option_bits = match options {
        Some(bits) => bits.bits(),
        None => 0
    };

    let res = unsafe { ffi::waitpid(pid as pid_t, &mut status as *mut c_int, option_bits) };

    Ok(match try!(Errno::result(res)) {
        0 => StillAlive,
        res => decode(res, status),
    })
}

pub fn wait() -> Result<WaitStatus> {
    waitpid(-1, None)
}
<commit_msg>wait: Support ptrace events for Linux<commit_after>use libc::{self, pid_t, c_int};
use {Errno, Result};

use sys::signal::Signal;

mod ffi {
    use libc::{pid_t, c_int};

    extern {
        pub fn waitpid(pid: pid_t, status: *mut c_int, options: c_int) -> pid_t;
    }
}

#[cfg(not(any(target_os = "linux",
              target_os = "android")))]
bitflags!(
    flags WaitPidFlag: c_int {
        const WNOHANG     = libc::WNOHANG,
        const WUNTRACED   = libc::WUNTRACED,
    }
);

#[cfg(any(target_os = "linux",
          target_os = "android"))]
bitflags!(
    flags WaitPidFlag: c_int {
        const WNOHANG     = libc::WNOHANG,
        const WUNTRACED   = libc::WUNTRACED,
        const WEXITED     = libc::WEXITED,
        const WCONTINUED  = libc::WCONTINUED,
        const WNOWAIT     = libc::WNOWAIT, // Don't reap, just poll status.
        const __WNOTHREAD = libc::__WNOTHREAD, // Don't wait on children of other threads in this group
        const __WALL      = libc::__WALL, // Wait on all children, regardless of type
        const __WCLONE    = libc::__WCLONE,
    }
);

#[cfg(any(target_os = "linux",
          target_os = "android"))]
const WSTOPPED: WaitPidFlag = WUNTRACED;

#[derive(Eq, PartialEq, Clone, Copy, Debug)]
pub enum WaitStatus {
    Exited(pid_t, i8),
    Signaled(pid_t, Signal, bool),
    Stopped(pid_t, Signal),
    #[cfg(any(target_os = "linux", target_os = "android"))]
    PtraceEvent(pid_t, Signal, c_int),
    Continued(pid_t),
    StillAlive
}

#[cfg(any(target_os = "linux",
          target_os = "android"))]
mod status {
    use sys::signal::Signal;
    use libc::c_int;

    pub fn exited(status: i32) -> bool {
        (status & 0x7F) == 0
    }

    pub fn exit_status(status: i32) -> i8 {
        ((status & 0xFF00) >> 8) as i8
    }

    pub fn signaled(status: i32) -> bool {
        ((((status & 0x7f) + 1) as i8) >> 1) > 0
    }

    pub fn term_signal(status: i32) -> Signal {
        Signal::from_c_int(status & 0x7f).unwrap()
    }

    pub fn dumped_core(status: i32) -> bool {
        (status & 0x80) != 0
    }

    pub fn stopped(status: i32) -> bool {
        (status & 0xff) == 0x7f
    }

    pub fn stop_signal(status: i32) -> Signal {
        Signal::from_c_int((status & 0xFF00) >> 8).unwrap()
    }

    pub fn stop_additional(status: i32) -> c_int {
        (status >> 16) as c_int
    }

    pub fn continued(status: i32) -> bool {
        status == 0xFFFF
    }
}

#[cfg(any(target_os = "macos",
          target_os = "ios"))]
mod status {
    use sys::signal::{Signal,SIGCONT};

    const WCOREFLAG: i32 = 0x80;
    const WSTOPPED: i32 = 0x7f;

    fn wstatus(status: i32) -> i32 {
        status & 0x7F
    }

    pub fn exit_status(status: i32) -> i8 {
        ((status >> 8) & 0xFF) as i8
    }

    pub fn stop_signal(status: i32) -> Signal {
        Signal::from_c_int(status >> 8).unwrap()
    }

    pub fn continued(status: i32) -> bool {
        wstatus(status) == WSTOPPED && stop_signal(status) == SIGCONT
    }

    pub fn stopped(status: i32) -> bool {
        wstatus(status) == WSTOPPED && stop_signal(status) != SIGCONT
    }

    pub fn exited(status: i32) -> bool {
        wstatus(status) == 0
    }

    pub fn signaled(status: i32) -> bool {
        wstatus(status) != WSTOPPED && wstatus(status) != 0
    }

    pub fn term_signal(status: i32) -> Signal {
        Signal::from_c_int(wstatus(status)).unwrap()
    }

    pub fn dumped_core(status: i32) -> bool {
        (status & WCOREFLAG) != 0
    }
}

#[cfg(any(target_os = "freebsd",
          target_os = "openbsd",
          target_os = "dragonfly",
          target_os = "netbsd"))]
mod status {
    use sys::signal::Signal;

    const WCOREFLAG: i32 = 0x80;
    const WSTOPPED: i32 = 0x7f;

    fn wstatus(status: i32) -> i32 {
        status & 0x7F
    }

    pub fn stopped(status: i32) -> bool {
        wstatus(status) == WSTOPPED
    }

    pub fn stop_signal(status: i32) -> Signal {
        Signal::from_c_int(status >> 8).unwrap()
    }

    pub fn signaled(status: i32) -> bool {
        wstatus(status) != WSTOPPED && wstatus(status) != 0 && status != 0x13
    }

    pub fn term_signal(status: i32) -> Signal {
        Signal::from_c_int(wstatus(status)).unwrap()
    }

    pub fn exited(status: i32) -> bool {
        wstatus(status) == 0
    }

    pub fn exit_status(status: i32) -> i8 {
        (status >> 8) as i8
    }

    pub fn continued(status: i32) -> bool {
        status == 0x13
    }

    pub fn dumped_core(status: i32) -> bool {
        (status & WCOREFLAG) != 0
    }
}

fn decode(pid : pid_t, status: i32) -> WaitStatus {
    if status::exited(status) {
        WaitStatus::Exited(pid, status::exit_status(status))
    } else if status::signaled(status) {
        WaitStatus::Signaled(pid, status::term_signal(status), status::dumped_core(status))
    } else if status::stopped(status) {
        if cfg!(any(target_os = "linux", target_os = "android")) {
            let status_additional = status::stop_additional(status);
            if status_additional != 0 {
                return WaitStatus::PtraceEvent(pid, status::stop_signal(status), status::stop_additional(status))
            }
        }
        WaitStatus::Stopped(pid, status::stop_signal(status))
    } else {
        assert!(status::continued(status));
        WaitStatus::Continued(pid)
    }
}

pub fn waitpid(pid: pid_t, options: Option<WaitPidFlag>) -> Result<WaitStatus> {
    use self::WaitStatus::*;

    let mut status: i32 = 0;

    let option_bits = match options {
        Some(bits) => bits.bits(),
        None => 0
    };

    let res = unsafe { ffi::waitpid(pid as pid_t, &mut status as *mut c_int, option_bits) };

    Ok(match try!(Errno::result(res)) {
        0 => StillAlive,
        res => decode(res, status),
    })
}

pub fn wait() -> Result<WaitStatus> {
    waitpid(-1, None)
}
<|endoftext|>


<commit_before>use crate::error::ErrorKind;
use crate::git::Git;
use std::env;

#[test]
fn git_get_current_branch() {
    let cwd = env::current_dir().unwrap();
    let g = Git::new(&cwd, "git");
    let b = g.current_branch();
    assert!(b.is_ok(), "{:?}", b);
}

#[test]
fn git_get_commit_hash() {
    let cwd = env::current_dir().unwrap();
    let g = Git::new(&cwd, "git");
    let b = g.current_branch().unwrap();

    for spec in &["HEAD", &b] {
        match g.hash(spec) {
            Ok(h) => {
                for c in h.chars() {
                    assert!(c.is_ascii_hexdigit(), "{:?}", h);
                }
            }
            Err(err) => assert!(false, "{:?}", err),
        };
    }
}

#[test]
fn git_get_invalid_hash() {
    let cwd = env::current_dir().unwrap();
    let g = Git::new(&cwd, "git");
    match g.hash("HEAD~114514").unwrap_err().kind() {
        ErrorKind::GitObjectNotFound { kind, .. } => assert_eq!(*kind, "commit"),
        e => assert!(false, "Unexpected error: {:?}", e),
    }
}

#[test]
fn git_get_tag_hash() {
    let cwd = env::current_dir().unwrap();
    let g = Git::new(&cwd, "git");
    let h = g.tag_hash("0.10.1").unwrap();
    assert_eq!(h, "601e6c33bb760d8e7d5684a75eec1f0257b8ff22");
}

#[test]
fn git_get_invalid_tag_hash() {
    let cwd = env::current_dir().unwrap();
    let g = Git::new(&cwd, "git");
    match g.tag_hash("this-tag-is-not-existing").unwrap_err().kind() {
        ErrorKind::GitObjectNotFound { kind, .. } => assert_eq!(*kind, "tag name"),
        e => assert!(false, "Unexpected error: {:?}", e),
    }
}

#[test]
fn git_get_remote_url() {
    let cwd = env::current_dir().unwrap();
    let g = Git::new(&cwd, "git");
    let u = g.remote_url("origin").unwrap();
    assert!(
        u.starts_with("git@") || u.starts_with("https://"),
        "invalid url: {:?}",
        u
    );
    assert!(u.contains("git-brws"), "invalid url: {:?}", u);
    // .git may not exist because GitHub allows omitting .git suffix in https Git URL
}

#[test]
fn git_get_invalid_remote_url() {
    let cwd = env::current_dir().unwrap();
    let g = Git::new(&cwd, "git");
    match g
        .remote_url("this-remote-is-not-existing")
        .unwrap_err()
        .kind()
    {
        ErrorKind::GitObjectNotFound { kind, .. } => assert_eq!(*kind, "remote"),
        e => assert!(false, "Unexpected error: {:?}", e),
    }
}

#[test]
fn git_root_dir() {
    let cwd = env::current_dir().unwrap();
    let g = Git::new(&cwd, "git");
    let p = g.root_dir().unwrap();
    assert!(p.join(".git").exists(), "{:?}", p);
}

#[test]
fn git_check_remote_contains() {
    let cwd = env::current_dir().unwrap();
    let g = Git::new(&cwd, "git");
    let h = g.tag_hash("0.10.1").unwrap();
    let b = g.remote_contains(&h, "origin/master").unwrap();
    assert!(
        b,
        "Hash {} is not included in remote branch origin/master",
        &h
    );
}
<commit_msg>add tests for Git::tracking_remote_url()<commit_after>use crate::error::ErrorKind;
use crate::git::Git;
use std::env;

#[test]
fn git_get_current_branch() {
    let cwd = env::current_dir().unwrap();
    let g = Git::new(&cwd, "git");
    let b = g.current_branch();
    assert!(b.is_ok(), "{:?}", b);
}

#[test]
fn git_get_commit_hash() {
    let cwd = env::current_dir().unwrap();
    let g = Git::new(&cwd, "git");
    let b = g.current_branch().unwrap();

    for spec in &["HEAD", &b] {
        match g.hash(spec) {
            Ok(h) => {
                for c in h.chars() {
                    assert!(c.is_ascii_hexdigit(), "{:?}", h);
                }
            }
            Err(err) => assert!(false, "{:?}", err),
        };
    }
}

#[test]
fn git_get_invalid_hash() {
    let cwd = env::current_dir().unwrap();
    let g = Git::new(&cwd, "git");
    match g.hash("HEAD~114514").unwrap_err().kind() {
        ErrorKind::GitObjectNotFound { kind, .. } => assert_eq!(*kind, "commit"),
        e => assert!(false, "Unexpected error: {:?}", e),
    }
}

#[test]
fn git_get_tag_hash() {
    let cwd = env::current_dir().unwrap();
    let g = Git::new(&cwd, "git");
    let h = g.tag_hash("0.10.1").unwrap();
    assert_eq!(h, "601e6c33bb760d8e7d5684a75eec1f0257b8ff22");
}

#[test]
fn git_get_invalid_tag_hash() {
    let cwd = env::current_dir().unwrap();
    let g = Git::new(&cwd, "git");
    match g.tag_hash("this-tag-is-not-existing").unwrap_err().kind() {
        ErrorKind::GitObjectNotFound { kind, .. } => assert_eq!(*kind, "tag name"),
        e => assert!(false, "Unexpected error: {:?}", e),
    }
}

#[test]
fn git_get_remote_url() {
    let cwd = env::current_dir().unwrap();
    let g = Git::new(&cwd, "git");
    let u = g.remote_url("origin").unwrap();
    assert!(
        u.starts_with("git@") || u.starts_with("https://"),
        "invalid url: {:?}",
        u
    );
    assert!(u.contains("git-brws"), "invalid url: {:?}", u);
    // .git may not exist because GitHub allows omitting .git suffix in https Git URL
}

#[test]
fn git_get_invalid_remote_url() {
    let cwd = env::current_dir().unwrap();
    let g = Git::new(&cwd, "git");
    match g
        .remote_url("this-remote-is-not-existing")
        .unwrap_err()
        .kind()
    {
        ErrorKind::GitObjectNotFound { kind, .. } => assert_eq!(*kind, "remote"),
        e => assert!(false, "Unexpected error: {:?}", e),
    }
}

#[test]
fn git_root_dir() {
    let cwd = env::current_dir().unwrap();
    let g = Git::new(&cwd, "git");
    let p = g.root_dir().unwrap();
    assert!(p.join(".git").exists(), "{:?}", p);
}

#[test]
fn git_check_remote_contains() {
    let cwd = env::current_dir().unwrap();
    let g = Git::new(&cwd, "git");
    let h = g.tag_hash("0.10.1").unwrap();
    let b = g.remote_contains(&h, "origin/master").unwrap();
    assert!(
        b,
        "Hash {} is not included in remote branch origin/master",
        &h
    );
}

#[test]
fn git_get_tracking_remote() {
    let cwd = env::current_dir().unwrap();
    let g = Git::new(&cwd, "git");
    let (url, _remote_name) = g.tracking_remote_url(&Some("master")).unwrap();
    assert!(
        url.starts_with("https://") || url.starts_with("git@") || url.starts_with("ssh://"),
        "{:?}",
        url
    );
}

#[test]
fn unknown_branch_for_tracking_remote() {
    let cwd = env::current_dir().unwrap();
    let g = Git::new(&cwd, "git");
    let err = g
        .tracking_remote_url(&Some("unknown-branch-this-is-not-existing"))
        .unwrap_err();
    assert!(matches!(err.kind(), ErrorKind::GitCommandError{ .. }));
}
<|endoftext|>


<commit_before>use std::num::{Zero, One};
use vec::{Vec1, Vec2, Vec3, AlgebraicVec, VecCast, UniformSphereSample, Cross, CrossMatrix, Basis};
use mat::{Mat3, Row};

impl<N: Mul<N, N> + Sub<N, N>> Cross<Vec1<N>> for Vec2<N> {
    #[inline]
    fn cross(&self, other : &Vec2<N>) -> Vec1<N> {
        Vec1::new(self.x * other.y - self.y * other.x)
    }
}

// FIXME: instead of returning a Vec2, define a Mat2x1 matrix?
impl<N: Neg<N> + Clone> CrossMatrix<Vec2<N>> for Vec2<N> {
    #[inline]
    fn cross_matrix(&self) -> Vec2<N> {
        Vec2::new(-self.y, self.x.clone())
    }
}

impl<N: Mul<N, N> + Sub<N, N>> Cross<Vec3<N>> for Vec3<N> {
    #[inline]
    fn cross(&self, other : &Vec3<N>) -> Vec3<N> {
        Vec3::new(
            self.y * other.z - self.z * other.y,
            self.z * other.x - self.x * other.z,
            self.x * other.y - self.y * other.x
        )
    }
}

impl<N: Neg<N> + Zero + Clone> CrossMatrix<Mat3<N>> for Vec3<N> {
    #[inline]
    fn cross_matrix(&self) -> Mat3<N> {
        Mat3::new(
            Zero::zero()  , -self.z,        self.y.clone(),
            self.z.clone(), Zero::zero(),   -self.x,
            -self.y       , self.x.clone(), Zero::zero()
        )
    }
}

// FIXME: iplement this for all other vectors
impl<N: Clone> Row<Vec1<N>> for Vec2<N> {
    #[inline]
    fn row(&self, i: uint) -> Vec1<N> {
        match i {
            0 => Vec1::new(self.x.clone()),
            1 => Vec1::new(self.y.clone()),
            _ => fail!("Index out of range: 2d vectors do not have " + i.to_str() + " rows.")
        }
    }

    #[inline]
    fn set_row(&mut self, i: uint, r: Vec1<N>) {
        match i {
            0 => self.x = r.x,
            1 => self.y = r.x,
            _ => fail!("Index out of range: 2d vectors do not have " + i.to_str() + " rows.")

        }
    }
}

impl<N: One> Basis for Vec1<N> {
    #[inline(always)]
    fn canonical_basis(f: &fn(Vec1<N>) -> bool) {
        f(Vec1::new(One::one()));
    }

    #[inline(always)]
    fn orthonormal_subspace_basis(&self, _: &fn(Vec1<N>) -> bool ) { }
}

impl<N: Clone + One + Zero + Neg<N>> Basis for Vec2<N> {
    #[inline(always)]
    fn canonical_basis(f: &fn(Vec2<N>) -> bool) {
        if !f(Vec2::new(One::one(), Zero::zero())) { return };
        f(Vec2::new(Zero::zero(), One::one()));
    }

    #[inline]
    fn orthonormal_subspace_basis(&self, f: &fn(Vec2<N>) -> bool) {
        f(Vec2::new(-self.y, self.x.clone()));
    }
}

impl<N: Clone + Ord + Algebraic + Signed>
Basis for Vec3<N> {
    #[inline(always)]
    fn canonical_basis(f: &fn(Vec3<N>) -> bool) {
        if !f(Vec3::new(One::one(), Zero::zero(), Zero::zero())) { return };
        if !f(Vec3::new(Zero::zero(), One::one(), Zero::zero())) { return };
        f(Vec3::new(Zero::zero(), Zero::zero(), One::one()));
    }

    #[inline(always)]
    fn orthonormal_subspace_basis(&self, f: &fn(Vec3<N>) -> bool) {
        let a =
            if self.x.clone().abs() > self.y.clone().abs() {
                Vec3::new(self.z.clone(), Zero::zero(), -self.x).normalized()
            }
            else {
                Vec3::new(Zero::zero(), -self.z, self.y.clone()).normalized()
            };

        if !f(a.cross(self)) { return };
        f(a);
    }
}

// FIXME: this bad: this fixes definitly the number of samples…
static SAMPLES_2_F64: [Vec2<f64>, ..21] = [
    Vec2 { x: 1.0,         y: 0.0         },
    Vec2 { x: 0.95557281,  y: 0.29475517  },
    Vec2 { x: 0.82623877,  y: 0.56332006  },
    Vec2 { x: 0.6234898,   y: 0.78183148  },
    Vec2 { x: 0.36534102,  y: 0.93087375  },
    Vec2 { x: 0.07473009,  y: 0.9972038   },
    Vec2 { x: -0.22252093, y: 0.97492791  },
    Vec2 { x: -0.5,        y: 0.8660254   },
    Vec2 { x: -0.73305187, y: 0.68017274  },
    Vec2 { x: -0.90096887, y: 0.43388374  },
    Vec2 { x: -0.98883083, y: 0.14904227  },
    Vec2 { x: -0.98883083, y: -0.14904227 },
    Vec2 { x: -0.90096887, y: -0.43388374 },
    Vec2 { x: -0.73305187, y: -0.68017274 },
    Vec2 { x: -0.5,        y: -0.8660254  },
    Vec2 { x: -0.22252093, y: -0.97492791 },
    Vec2 { x: 0.07473009,  y: -0.9972038  },
    Vec2 { x: 0.36534102,  y: -0.93087375 },
    Vec2 { x: 0.6234898,   y: -0.78183148 },
    Vec2 { x: 0.82623877,  y: -0.56332006 },
    Vec2 { x: 0.95557281,  y: -0.29475517 },
];

// Those vectors come from bullet 3d
static SAMPLES_3_F64: [Vec3<f64>, ..42] = [
    Vec3 { x: 0.000000 , y: -0.000000, z: -1.000000 },
    Vec3 { x: 0.723608 , y: -0.525725, z: -0.447219 },
    Vec3 { x: -0.276388, y: -0.850649, z: -0.447219 },
    Vec3 { x: -0.894426, y: -0.000000, z: -0.447216 },
    Vec3 { x: -0.276388, y: 0.850649 , z: -0.447220 },
    Vec3 { x: 0.723608 , y: 0.525725 , z: -0.447219 },
    Vec3 { x: 0.276388 , y: -0.850649, z: 0.447220 },
    Vec3 { x: -0.723608, y: -0.525725, z: 0.447219 },
    Vec3 { x: -0.723608, y: 0.525725 , z: 0.447219 },
    Vec3 { x: 0.276388 , y: 0.850649 , z: 0.447219 },
    Vec3 { x: 0.894426 , y: 0.000000 , z: 0.447216 },
    Vec3 { x: -0.000000, y: 0.000000 , z: 1.000000 },
    Vec3 { x: 0.425323 , y: -0.309011, z: -0.850654 },
    Vec3 { x: -0.162456, y: -0.499995, z: -0.850654 },
    Vec3 { x: 0.262869 , y: -0.809012, z: -0.525738 },
    Vec3 { x: 0.425323 , y: 0.309011 , z: -0.850654 },
    Vec3 { x: 0.850648 , y: -0.000000, z: -0.525736 },
    Vec3 { x: -0.525730, y: -0.000000, z: -0.850652 },
    Vec3 { x: -0.688190, y: -0.499997, z: -0.525736 },
    Vec3 { x: -0.162456, y: 0.499995 , z: -0.850654 },
    Vec3 { x: -0.688190, y: 0.499997 , z: -0.525736 },
    Vec3 { x: 0.262869 , y: 0.809012 , z: -0.525738 },
    Vec3 { x: 0.951058 , y: 0.309013 , z: 0.000000 },
    Vec3 { x: 0.951058 , y: -0.309013, z: 0.000000 },
    Vec3 { x: 0.587786 , y: -0.809017, z: 0.000000 },
    Vec3 { x: 0.000000 , y: -1.000000, z: 0.000000 },
    Vec3 { x: -0.587786, y: -0.809017, z: 0.000000 },
    Vec3 { x: -0.951058, y: -0.309013, z: -0.000000 },
    Vec3 { x: -0.951058, y: 0.309013 , z: -0.000000 },
    Vec3 { x: -0.587786, y: 0.809017 , z: -0.000000 },
    Vec3 { x: -0.000000, y: 1.000000 , z: -0.000000 },
    Vec3 { x: 0.587786 , y: 0.809017 , z: -0.000000 },
    Vec3 { x: 0.688190 , y: -0.499997, z: 0.525736 },
    Vec3 { x: -0.262869, y: -0.809012, z: 0.525738 },
    Vec3 { x: -0.850648, y: 0.000000 , z: 0.525736 },
    Vec3 { x: -0.262869, y: 0.809012 , z: 0.525738 },
    Vec3 { x: 0.688190 , y: 0.499997 , z: 0.525736 },
    Vec3 { x: 0.525730 , y: 0.000000 , z: 0.850652 },
    Vec3 { x: 0.162456 , y: -0.499995, z: 0.850654 },
    Vec3 { x: -0.425323, y: -0.309011, z: 0.850654 },
    Vec3 { x: -0.425323, y: 0.309011 , z: 0.850654 },
    Vec3 { x: 0.162456 , y: 0.499995 , z: 0.850654 }
];

impl<N: NumCast + Clone> UniformSphereSample for Vec2<N> {
    #[inline(always)]
    fn sample(f: &fn(Vec2<N>)) {
         for sample in SAMPLES_2_F64.iter() {
             f(VecCast::from(*sample))
         }
     }
}

impl<N: NumCast + Clone> UniformSphereSample for Vec3<N> {
    #[inline(always)]
    fn sample(f: &fn(Vec3<N>)) {
        for sample in SAMPLES_3_F64.iter() {
            f(VecCast::from(*sample))
        }
    }
}
<commit_msg>Implement `UnitSphereSample` for `Vec1`.<commit_after>use std::num::{Zero, One};
use vec::{Vec1, Vec2, Vec3, AlgebraicVec, VecCast, UniformSphereSample, Cross, CrossMatrix, Basis};
use mat::{Mat3, Row};

impl<N: Mul<N, N> + Sub<N, N>> Cross<Vec1<N>> for Vec2<N> {
    #[inline]
    fn cross(&self, other : &Vec2<N>) -> Vec1<N> {
        Vec1::new(self.x * other.y - self.y * other.x)
    }
}

// FIXME: instead of returning a Vec2, define a Mat2x1 matrix?
impl<N: Neg<N> + Clone> CrossMatrix<Vec2<N>> for Vec2<N> {
    #[inline]
    fn cross_matrix(&self) -> Vec2<N> {
        Vec2::new(-self.y, self.x.clone())
    }
}

impl<N: Mul<N, N> + Sub<N, N>> Cross<Vec3<N>> for Vec3<N> {
    #[inline]
    fn cross(&self, other : &Vec3<N>) -> Vec3<N> {
        Vec3::new(
            self.y * other.z - self.z * other.y,
            self.z * other.x - self.x * other.z,
            self.x * other.y - self.y * other.x
        )
    }
}

impl<N: Neg<N> + Zero + Clone> CrossMatrix<Mat3<N>> for Vec3<N> {
    #[inline]
    fn cross_matrix(&self) -> Mat3<N> {
        Mat3::new(
            Zero::zero()  , -self.z,        self.y.clone(),
            self.z.clone(), Zero::zero(),   -self.x,
            -self.y       , self.x.clone(), Zero::zero()
        )
    }
}

// FIXME: iplement this for all other vectors
impl<N: Clone> Row<Vec1<N>> for Vec2<N> {
    #[inline]
    fn row(&self, i: uint) -> Vec1<N> {
        match i {
            0 => Vec1::new(self.x.clone()),
            1 => Vec1::new(self.y.clone()),
            _ => fail!("Index out of range: 2d vectors do not have " + i.to_str() + " rows.")
        }
    }

    #[inline]
    fn set_row(&mut self, i: uint, r: Vec1<N>) {
        match i {
            0 => self.x = r.x,
            1 => self.y = r.x,
            _ => fail!("Index out of range: 2d vectors do not have " + i.to_str() + " rows.")

        }
    }
}

impl<N: One> Basis for Vec1<N> {
    #[inline(always)]
    fn canonical_basis(f: &fn(Vec1<N>) -> bool) {
        f(Vec1::new(One::one()));
    }

    #[inline(always)]
    fn orthonormal_subspace_basis(&self, _: &fn(Vec1<N>) -> bool ) { }
}

impl<N: Clone + One + Zero + Neg<N>> Basis for Vec2<N> {
    #[inline(always)]
    fn canonical_basis(f: &fn(Vec2<N>) -> bool) {
        if !f(Vec2::new(One::one(), Zero::zero())) { return };
        f(Vec2::new(Zero::zero(), One::one()));
    }

    #[inline]
    fn orthonormal_subspace_basis(&self, f: &fn(Vec2<N>) -> bool) {
        f(Vec2::new(-self.y, self.x.clone()));
    }
}

impl<N: Clone + Ord + Algebraic + Signed>
Basis for Vec3<N> {
    #[inline(always)]
    fn canonical_basis(f: &fn(Vec3<N>) -> bool) {
        if !f(Vec3::new(One::one(), Zero::zero(), Zero::zero())) { return };
        if !f(Vec3::new(Zero::zero(), One::one(), Zero::zero())) { return };
        f(Vec3::new(Zero::zero(), Zero::zero(), One::one()));
    }

    #[inline(always)]
    fn orthonormal_subspace_basis(&self, f: &fn(Vec3<N>) -> bool) {
        let a =
            if self.x.clone().abs() > self.y.clone().abs() {
                Vec3::new(self.z.clone(), Zero::zero(), -self.x).normalized()
            }
            else {
                Vec3::new(Zero::zero(), -self.z, self.y.clone()).normalized()
            };

        if !f(a.cross(self)) { return };
        f(a);
    }
}

// FIXME: this bad: this fixes definitly the number of samples…
static SAMPLES_2_F64: [Vec2<f64>, ..21] = [
    Vec2 { x: 1.0,         y: 0.0         },
    Vec2 { x: 0.95557281,  y: 0.29475517  },
    Vec2 { x: 0.82623877,  y: 0.56332006  },
    Vec2 { x: 0.6234898,   y: 0.78183148  },
    Vec2 { x: 0.36534102,  y: 0.93087375  },
    Vec2 { x: 0.07473009,  y: 0.9972038   },
    Vec2 { x: -0.22252093, y: 0.97492791  },
    Vec2 { x: -0.5,        y: 0.8660254   },
    Vec2 { x: -0.73305187, y: 0.68017274  },
    Vec2 { x: -0.90096887, y: 0.43388374  },
    Vec2 { x: -0.98883083, y: 0.14904227  },
    Vec2 { x: -0.98883083, y: -0.14904227 },
    Vec2 { x: -0.90096887, y: -0.43388374 },
    Vec2 { x: -0.73305187, y: -0.68017274 },
    Vec2 { x: -0.5,        y: -0.8660254  },
    Vec2 { x: -0.22252093, y: -0.97492791 },
    Vec2 { x: 0.07473009,  y: -0.9972038  },
    Vec2 { x: 0.36534102,  y: -0.93087375 },
    Vec2 { x: 0.6234898,   y: -0.78183148 },
    Vec2 { x: 0.82623877,  y: -0.56332006 },
    Vec2 { x: 0.95557281,  y: -0.29475517 },
];

// Those vectors come from bullet 3d
static SAMPLES_3_F64: [Vec3<f64>, ..42] = [
    Vec3 { x: 0.000000 , y: -0.000000, z: -1.000000 },
    Vec3 { x: 0.723608 , y: -0.525725, z: -0.447219 },
    Vec3 { x: -0.276388, y: -0.850649, z: -0.447219 },
    Vec3 { x: -0.894426, y: -0.000000, z: -0.447216 },
    Vec3 { x: -0.276388, y: 0.850649 , z: -0.447220 },
    Vec3 { x: 0.723608 , y: 0.525725 , z: -0.447219 },
    Vec3 { x: 0.276388 , y: -0.850649, z: 0.447220 },
    Vec3 { x: -0.723608, y: -0.525725, z: 0.447219 },
    Vec3 { x: -0.723608, y: 0.525725 , z: 0.447219 },
    Vec3 { x: 0.276388 , y: 0.850649 , z: 0.447219 },
    Vec3 { x: 0.894426 , y: 0.000000 , z: 0.447216 },
    Vec3 { x: -0.000000, y: 0.000000 , z: 1.000000 },
    Vec3 { x: 0.425323 , y: -0.309011, z: -0.850654 },
    Vec3 { x: -0.162456, y: -0.499995, z: -0.850654 },
    Vec3 { x: 0.262869 , y: -0.809012, z: -0.525738 },
    Vec3 { x: 0.425323 , y: 0.309011 , z: -0.850654 },
    Vec3 { x: 0.850648 , y: -0.000000, z: -0.525736 },
    Vec3 { x: -0.525730, y: -0.000000, z: -0.850652 },
    Vec3 { x: -0.688190, y: -0.499997, z: -0.525736 },
    Vec3 { x: -0.162456, y: 0.499995 , z: -0.850654 },
    Vec3 { x: -0.688190, y: 0.499997 , z: -0.525736 },
    Vec3 { x: 0.262869 , y: 0.809012 , z: -0.525738 },
    Vec3 { x: 0.951058 , y: 0.309013 , z: 0.000000 },
    Vec3 { x: 0.951058 , y: -0.309013, z: 0.000000 },
    Vec3 { x: 0.587786 , y: -0.809017, z: 0.000000 },
    Vec3 { x: 0.000000 , y: -1.000000, z: 0.000000 },
    Vec3 { x: -0.587786, y: -0.809017, z: 0.000000 },
    Vec3 { x: -0.951058, y: -0.309013, z: -0.000000 },
    Vec3 { x: -0.951058, y: 0.309013 , z: -0.000000 },
    Vec3 { x: -0.587786, y: 0.809017 , z: -0.000000 },
    Vec3 { x: -0.000000, y: 1.000000 , z: -0.000000 },
    Vec3 { x: 0.587786 , y: 0.809017 , z: -0.000000 },
    Vec3 { x: 0.688190 , y: -0.499997, z: 0.525736 },
    Vec3 { x: -0.262869, y: -0.809012, z: 0.525738 },
    Vec3 { x: -0.850648, y: 0.000000 , z: 0.525736 },
    Vec3 { x: -0.262869, y: 0.809012 , z: 0.525738 },
    Vec3 { x: 0.688190 , y: 0.499997 , z: 0.525736 },
    Vec3 { x: 0.525730 , y: 0.000000 , z: 0.850652 },
    Vec3 { x: 0.162456 , y: -0.499995, z: 0.850654 },
    Vec3 { x: -0.425323, y: -0.309011, z: 0.850654 },
    Vec3 { x: -0.425323, y: 0.309011 , z: 0.850654 },
    Vec3 { x: 0.162456 , y: 0.499995 , z: 0.850654 }
];

impl<N: One + Clone> UniformSphereSample for Vec1<N> {
    #[inline(always)]
    fn sample(f: &fn(Vec1<N>)) {
        f(One::one())
     }
}

impl<N: NumCast + Clone> UniformSphereSample for Vec2<N> {
    #[inline(always)]
    fn sample(f: &fn(Vec2<N>)) {
         for sample in SAMPLES_2_F64.iter() {
             f(VecCast::from(*sample))
         }
     }
}

impl<N: NumCast + Clone> UniformSphereSample for Vec3<N> {
    #[inline(always)]
    fn sample(f: &fn(Vec3<N>)) {
        for sample in SAMPLES_3_F64.iter() {
            f(VecCast::from(*sample))
        }
    }
}
<|endoftext|>


<commit_before>pub enum Operator {
    And,
    Or
}

impl Operator {
    pub fn to_sql(&self) -> &str {
        match *self {
            Operator::And => "AND",
            Operator::Or => "OR"
        }
    }
}

trait ToSQL {
    fn to_sql(&self) -> String;
}

struct Where<'a, T: 'a> {
    pub operator: Operator,
    pub clause: &'a [&'a T]
}

impl<'a> ToSQL for &'a str {
    fn to_sql(&self) -> String {
        self.to_string()
    }
}

impl<'a, T: ToSQL> ToSQL for Where<'a, T> {
    fn to_sql(&self) -> String {
        let operator = &format!(" {} ", self.operator.to_sql());
        let mut rv = String::new();
        rv.push_str(&self.clause.into_iter()
                    .map(|x| x.to_sql())
                    .collect::<Vec<_>>()
                    .connect(operator));
        rv
    }
}

#[cfg(test)]
mod tests {
    use super::{Operator, Where};

    #[test]
    fn test_operator() {
        let and = Operator::And;
        let or = Operator::Or;

        assert_eq!(and.to_sql(), "AND");
        assert_eq!(or.to_sql(), "OR");
    }

    #[test]
    fn test_generic() {
        let foo = Where {
            operator: Operator::And,
            clause: &["foo", "bar"]
        };
    }
}
<commit_msg>Fixed `Sized` error<commit_after>pub enum Operator {
    And,
    Or
}

impl Operator {
    pub fn to_sql(&self) -> &str {
        match *self {
            Operator::And => "AND",
            Operator::Or => "OR"
        }
    }
}

trait ToSQL {
    fn to_sql(&self) -> String;
}

struct Where<'a, T: 'a + ?Sized> {
    pub operator: Operator,
    pub clause: &'a [&'a T]
}

impl<'a> ToSQL for &'a str {
    fn to_sql(&self) -> String {
        self.to_string()
    }
}

impl<'a, T: ToSQL> ToSQL for Where<'a, T> {
    fn to_sql(&self) -> String {
        let operator = &format!(" {} ", self.operator.to_sql());
        self.clause.into_iter()
            .map(|x| x.to_sql())
            .collect::<Vec<_>>()
            .join(operator)
    }
}

#[cfg(test)]
mod tests {
    use super::{Operator, Where};

    #[test]
    fn test_operator() {
        let and = Operator::And;
        let or = Operator::Or;

        assert_eq!(and.to_sql(), "AND");
        assert_eq!(or.to_sql(), "OR");
    }

    #[test]
    fn test_generic() {
        let foo = Where {
            operator: Operator::And,
            clause: &["foo", "bar"]
        };
    }
}
<|endoftext|>


<commit_before>use std::fmt;
use std::marker::PhantomData;

use hyper::method::Method;
use serde::json;

use response;
use request::RequestBuilder;
use request::DoRequest;

/// Lists the types of supported DNS records
doapi_enum! {
    #[derive(Debug)]
    pub enum DnsRecType {
        A,
        AAAA,
        CNAME,
        MX,
        NS,
        SRV,
        TXT
    }
}

// type     string  The record type (A, MX, CNAME, etc).    All Records
// name     string  The host name, alias, or service being defined by the record.   A, AAAA, CNAME, TXT, SRV
// data     string  Variable data depending on record type. See the [Domain Records]() section for more detail on each record type. A, AAAA, CNAME, MX, TXT, SRV, NS
// priority    nullable number The priority of the host (for SRV and MX records. null otherwise).  MX, SRV
// port     nullable number The port that the service is accessible on (for SRV records only. null otherwise).  SRV
// weight   nullable number The weight of records with the same priority (for SRV records only. null otherwise).    SRV
/// A struct for creating a DNS Record
#[derive(Serialize)]
pub struct DnsRecord {
    /// The type of record (A, AAAA, MX, NS, etc.)
    ///
    /// **NOTE:** You can use the `DnsRecType`'s implementation of `std::fmt::Display` to get a
    /// `String`
    #[serde(rename = "type")]
    pub rec_type: String,
    /// The name of the record (Required for: A, AAAA, CNAME, TXT, and SRV)
    pub name: Option<String>,
    /// The priority of the record (Required for: MX and SRV)
    pub priority: Option<u64>,
    /// The port of the record (Required for: SRV)
    pub port: Option<u64>,
    /// Various data used for record (Required for: A, AAAA, CNAME, MX, TXT, SRV, NS)
    pub data: Option<String>,
    /// The weight of the record (Required for: SRV)
    pub weight: Option<u64>,
}

impl fmt::Display for DnsRecord {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f,
            "Record Type: {}\n\
             Name: {}\n\
             Data: {}\n\
             Priority: {}\n\
             Port: {}\n\
             Weight: {}\n",
             self.rec_type,
             if let Some(n) = self.name.clone() {
                n
             } else {
                "None".to_owned()
             },
             if let Some(d) = self.data.clone() {
                d
             } else {
                "None".to_owned()
             },
             if let Some(p) = self.priority {
                p.to_string()
             } else {
                "None".to_owned()
             },
             if let Some(p) = self.port {
                p.to_string()
             } else {
                "None".to_owned()
             },
             if let Some(w) = self.weight {
                w.to_string()
             } else {
                "None".to_owned()
             }
        )
    }
}

impl<'t> RequestBuilder<'t, response::DnsRecords> {
    /// Returns a `RequestBuilder` for creating a DNS record.
    ///
    /// **Parameters:**
    /// `record`: The instance of `DnsRecord` you'd like to create
    ///
    /// # Example
    ///
    /// ```no_run
    /// # use doapi::DoManager;
    /// # use doapi::DoRequest;
    /// # use doapi::request::DnsRecord;
    /// # let domgr = DoManager::with_token("asfasdfasdf");
    /// # let record = DnsRecord {
    /// #   rec_type: "A".to_owned(),
    /// #   name: None,
    /// #   priority: None,
    /// #   port: None,
    /// #   data: None,
    /// #   weight: None,
    /// # };
    /// // ... domgr set up same as before
    /// // ... assumes "record" is an instance of doapi::request::DnsRecord
    /// match domgr.domain("super.com")
    ///            .dns_records()
    ///            .create(&record)
    ///            .retrieve() {
    ///     Ok(dns_rec) => println!("Record: {}", dns_rec),
    ///     Err(e)     => println!("Error: {}", e)
    /// }
    /// ```
    pub fn create(self, record: &DnsRecord) -> RequestBuilder<'t, response::DnsRecord> {
        // POST: "https://api.digitalocean.com/v2/domains/$DOMAIN/records"
        // body:
        //      "type" : "MX"            All records
        //      "name" : "alias"         A, AAAA, CNAME, TXT, SRV
        //      "data" : "varies"        A, AAAA, CNAME, MX, TXT, SRV, NS
        //      "priority" : 20          MX, SRV
        //      "port" : 80              SRV
        //      "weight" : 200           SRV

        // FIXME: Don't unwrap()
        RequestBuilder {
            method: Method::Post,
            auth: self.auth,
            url: self.url,
            resp_t: PhantomData,
            body: Some(json::to_string(record).ok().unwrap())
        }
    }
}

impl<'t> RequestBuilder<'t, response::DnsRecord> {
    /// Returns a `RequestBuilder` for updating an existing DNS record.
    ///
    /// **Parameters:**
    /// `record`: The new instance of `DnsRecord` you'd like to update to
    ///
    /// # Example
    ///
    /// ```no_run
    /// # use doapi::DoManager;
    /// # use doapi::DoRequest;
    /// # use doapi::request::DnsRecord;
    /// # let domgr = DoManager::with_token("asfasdfasdf");
    /// # let record = DnsRecord {
    /// #   rec_type: "A".to_owned(),
    /// #   name: None,
    /// #   priority: None,
    /// #   port: None,
    /// #   data: None,
    /// #   weight: None,
    /// # };
    /// // ... domgr set up same as before
    /// // ... assumes "record" is an instance of doapi::request::DnsRecord
    /// match domgr.domain("super.com")
    ///            .dns_record("1234")
    ///            .update(&record)
    ///            .retrieve() {
    ///     Ok(dns_rec) => println!("Record: {}", dns_rec),
    ///     Err(e)     => println!("Error: {}", e)
    /// }
    /// ```
    pub fn update(self, record: &DnsRecord) -> RequestBuilder<'t, response::DnsRecord> {
        // PUT: "https://api.digitalocean.com/v2/domains/$DOMAIN/records/$ID"
        // body:
        //      "type" : "MX"           All records
        //      "name" : "alias"        A, AAAA, CNAME, TXT, SRV
        //      "data" : "varies"       A, AAAA, CNAME, MX, TXT, SRV, NS
        //      "priority" : 20         MX, SRV
        //      "port" : 80             SRV
        //      "weight" : 200          SRV
        // FIXME: Don't unwrap()
        RequestBuilder {
            method: Method::Put,
            auth: self.auth,
            url: self.url,
            resp_t: PhantomData,
            body: Some(json::to_string(record).ok().unwrap())
        }
    }

    /// Returns a `RequestBuilder` for deleting an existing DNS record.
    ///
    /// # Example
    ///
    /// ```no_run
    /// # use doapi::DoManager;
    /// # use doapi::DoRequest;
    /// # let domgr = DoManager::with_token("asfasdfasdf");
    /// // ... domgr set up same as before
    /// match domgr.domain("super.com")
    ///            .dns_record("1234")
    ///            .delete()
    ///            .retrieve() {
    ///     Ok(_)  => println!("Success"),
    ///     Err(_) => println!("Error")
    /// }
    /// ```
    pub fn delete(self) -> RequestBuilder<'t, response::HeaderOnly> {
        // DELETE: "https://api.digitalocean.com/v2/domains/$id"
        RequestBuilder {
            method: Method::Delete,
            auth: self.auth,
            url: self.url,
            resp_t: PhantomData,
            body: None
        }
    }
}

impl<'t> DoRequest<response::DnsRecord> for RequestBuilder<'t, response::DnsRecord> {}<commit_msg>fix: corrects dns record update command<commit_after>use std::fmt::{self, Write};
use std::marker::PhantomData;

use hyper::method::Method;
use serde::json;

use response;
use request::RequestBuilder;
use request::DoRequest;

/// Lists the types of supported DNS records
doapi_enum! {
    #[derive(Debug)]
    pub enum DnsRecType {
        A,
        AAAA,
        CNAME,
        MX,
        NS,
        SRV,
        TXT
    }
}

// type     string  The record type (A, MX, CNAME, etc).    All Records
// name     string  The host name, alias, or service being defined by the record.   A, AAAA, CNAME, TXT, SRV
// data     string  Variable data depending on record type. See the [Domain Records]() section for more detail on each record type. A, AAAA, CNAME, MX, TXT, SRV, NS
// priority    nullable number The priority of the host (for SRV and MX records. null otherwise).  MX, SRV
// port     nullable number The port that the service is accessible on (for SRV records only. null otherwise).  SRV
// weight   nullable number The weight of records with the same priority (for SRV records only. null otherwise).    SRV
/// A struct for creating a DNS Record
#[derive(Serialize)]
pub struct DnsRecord {
    /// The type of record (A, AAAA, MX, NS, etc.)
    ///
    /// **NOTE:** You can use the `DnsRecType`'s implementation of `std::fmt::Display` to get a
    /// `String`
    #[serde(rename = "type")]
    pub rec_type: Option<String>,
    /// The name of the record (Required for: A, AAAA, CNAME, TXT, and SRV)
    pub name: Option<String>,
    /// The priority of the record (Required for: MX and SRV)
    pub priority: Option<u64>,
    /// The port of the record (Required for: SRV)
    pub port: Option<u64>,
    /// Various data used for record (Required for: A, AAAA, CNAME, MX, TXT, SRV, NS)
    pub data: Option<String>,
    /// The weight of the record (Required for: SRV)
    pub weight: Option<u64>,
}

impl fmt::Display for DnsRecord {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f,
            "Record Type: {}\n\
             Name: {}\n\
             Data: {}\n\
             Priority: {}\n\
             Port: {}\n\
             Weight: {}\n",
             if let Some(t) = self.rec_type.clone() {
                t
            } else {
                "None".to_owned()
            },
             if let Some(n) = self.name.clone() {
                n
             } else {
                "None".to_owned()
             },
             if let Some(d) = self.data.clone() {
                d
             } else {
                "None".to_owned()
             },
             if let Some(p) = self.priority {
                p.to_string()
             } else {
                "None".to_owned()
             },
             if let Some(p) = self.port {
                p.to_string()
             } else {
                "None".to_owned()
             },
             if let Some(w) = self.weight {
                w.to_string()
             } else {
                "None".to_owned()
             }
        )
    }
}

impl<'t> RequestBuilder<'t, response::DnsRecords> {
    /// Returns a `RequestBuilder` for creating a DNS record.
    ///
    /// **Parameters:**
    /// `record`: The instance of `DnsRecord` you'd like to create
    ///
    /// # Example
    ///
    /// ```no_run
    /// # use doapi::DoManager;
    /// # use doapi::DoRequest;
    /// # use doapi::request::DnsRecord;
    /// # let domgr = DoManager::with_token("asfasdfasdf");
    /// # let record = DnsRecord {
    /// #   rec_type: "A".to_owned(),
    /// #   name: None,
    /// #   priority: None,
    /// #   port: None,
    /// #   data: None,
    /// #   weight: None,
    /// # };
    /// // ... domgr set up same as before
    /// // ... assumes "record" is an instance of doapi::request::DnsRecord
    /// match domgr.domain("super.com")
    ///            .dns_records()
    ///            .create(&record)
    ///            .retrieve() {
    ///     Ok(dns_rec) => println!("Record: {}", dns_rec),
    ///     Err(e)     => println!("Error: {}", e)
    /// }
    /// ```
    pub fn create(self, record: &DnsRecord) -> RequestBuilder<'t, response::DnsRecord> {
        // POST: "https://api.digitalocean.com/v2/domains/$DOMAIN/records"
        // body:
        //      "type" : "MX"            All records
        //      "name" : "alias"         A, AAAA, CNAME, TXT, SRV
        //      "data" : "varies"        A, AAAA, CNAME, MX, TXT, SRV, NS
        //      "priority" : 20          MX, SRV
        //      "port" : 80              SRV
        //      "weight" : 200           SRV

        // FIXME: Don't unwrap()
        RequestBuilder {
            method: Method::Post,
            auth: self.auth,
            url: self.url,
            resp_t: PhantomData,
            body: Some(json::to_string(record).ok().unwrap())
        }
    }
}

impl<'t> RequestBuilder<'t, response::DnsRecord> {
    /// Returns a `RequestBuilder` for updating an existing DNS record.
    ///
    /// **Parameters:**
    /// `record`: The new instance of `DnsRecord` you'd like to update to
    ///
    /// # Example
    ///
    /// ```no_run
    /// # use doapi::DoManager;
    /// # use doapi::DoRequest;
    /// # use doapi::request::DnsRecord;
    /// # let domgr = DoManager::with_token("asfasdfasdf");
    /// # let record = DnsRecord {
    /// #   rec_type: "A".to_owned(),
    /// #   name: None,
    /// #   priority: None,
    /// #   port: None,
    /// #   data: None,
    /// #   weight: None,
    /// # };
    /// // ... domgr set up same as before
    /// // ... assumes "record" is an instance of doapi::request::DnsRecord
    /// match domgr.domain("super.com")
    ///            .dns_record("1234")
    ///            .update(&record)
    ///            .retrieve() {
    ///     Ok(dns_rec) => println!("Record: {}", dns_rec),
    ///     Err(e)     => println!("Error: {}", e)
    /// }
    /// ```
    pub fn update(self, record: &DnsRecord) -> RequestBuilder<'t, response::DnsRecord> {
        // PUT: "https://api.digitalocean.com/v2/domains/$DOMAIN/records/$ID"
        // body:
        //      "type" : "MX"           All records
        //      "name" : "alias"        A, AAAA, CNAME, TXT, SRV
        //      "data" : "varies"       A, AAAA, CNAME, MX, TXT, SRV, NS
        //      "priority" : 20         MX, SRV
        //      "port" : 80             SRV
        //      "weight" : 200          SRV
        // FIXME: Don't unwrap()
        let mut s = String::new();
        write!(s,
            "{{{}{}{}{}{}{}}}",
             if let Some(t) = record.rec_type.clone() {
                format!("\"type\":{:?},",t)
            } else {
                "".to_owned()
            },
             if let Some(n) = record.name.clone() {
                format!("\"name\":{:?},",n)
             } else {
                "".to_owned()
             },
             if let Some(d) = record.data.clone() {
                format!("\"data\":{:?},",d)
             } else {
                "".to_owned()
             },
             if let Some(p) = record.priority {
                format!("\"priority\":{},",p)
             } else {
                "".to_owned()
             },
             if let Some(p) = record.port {
                format!("\"port\":{},",p)
             } else {
                "".to_owned()
             },
             if let Some(w) = record.weight {
                format!("\"weight\":{}",w)
             } else {
                "".to_owned()
             }
        ).unwrap();
        RequestBuilder {
            method: Method::Put,
            auth: self.auth,
            url: self.url,
            resp_t: PhantomData,
            body: Some(s)
        }
    }

    /// Returns a `RequestBuilder` for deleting an existing DNS record.
    ///
    /// # Example
    ///
    /// ```no_run
    /// # use doapi::DoManager;
    /// # use doapi::DoRequest;
    /// # let domgr = DoManager::with_token("asfasdfasdf");
    /// // ... domgr set up same as before
    /// match domgr.domain("super.com")
    ///            .dns_record("1234")
    ///            .delete()
    ///            .retrieve() {
    ///     Ok(_)  => println!("Success"),
    ///     Err(_) => println!("Error")
    /// }
    /// ```
    pub fn delete(self) -> RequestBuilder<'t, response::HeaderOnly> {
        // DELETE: "https://api.digitalocean.com/v2/domains/$id"
        RequestBuilder {
            method: Method::Delete,
            auth: self.auth,
            url: self.url,
            resp_t: PhantomData,
            body: None
        }
    }
}

impl<'t> DoRequest<response::DnsRecord> for RequestBuilder<'t, response::DnsRecord> {}<|endoftext|>


<commit_before>//
//  SOS: the Stupid Operating System
//  by Eliza Weisman (eliza@elizas.website)
//
//  Copyright (c) 2015-2017 Eliza Weisman
//  Released under the terms of the MIT license. See `LICENSE` in the root
//  directory of this repository for more information.
//
//! 64-bit IDT gate implementation
use ::segment;
use super::{GateFlags};
use super::super::{InterruptHandler, ErrorCodeHandler};

use core::{convert, mem, ops};
use core::marker::PhantomData;

impl GateFlags {

    /// Returns a new trap gate
    pub const fn new_trap() -> Self {
        GateFlags { bits: super::TRAP_GATE_32.bits | super::PRESENT.bits }
    }

    /// Returns a new call gate
    pub const fn new_task() -> Self {
        GateFlags { bits: super::TASK_GATE_32.bits | super::PRESENT.bits }
    }

    /// Returns a new interrupt gate
    pub const fn new_interrupt() -> Self {
        GateFlags { bits: super::INT_GATE_32.bits | super::PRESENT.bits }
    }

}

/// An IDT entry is called a gate.
///
/// Based on [code](http://wiki.osdev.org/Interrupt_Descriptor_Table#Structure)
/// from the OS Dev Wiki.
///
/// Refer also to "6.14.1 64-Bit Mode IDT"  and "Table 3-2. System-Segment and
/// Gate-Descriptor Types" in the _Intel® 64 and IA-32 Architectures
/// Software Developer’s Manual_
#[repr(C, packed)]
#[derive(Copy, Clone)]
pub struct Gate<H = InterruptHandler>
    { /// bits 0 - 15 of the offset
      pub offset_lower: u16
    , /// code segment selector (GDT or LDT)
      pub selector: segment::Selector
    , /// always zero
      _zero: u8
    , /// indicates the gate's type and attributes.
      /// the second half indicates the type:
      ///   + `0b1100`: Call gate
      ///   + `0b1110`: Interrupt gate
      ///   + `0b1111`: Trap Gate
      pub flags: GateFlags
    , /// bits 16 - 31 of the offset
      pub offset_mid: u16
    , /// bits 32 - 63 of the offset
      pub offset_upper: u32
    , /// always zero (according to the spec, this is "reserved")
      _reserved: u32
    , _handler_type: PhantomData<H>
    }

impl<H> Gate<H> {

    /// Creates a new IDT gate marked as `absent`.
    ///
    /// This is basically just for filling the new IDT table
    /// with valid (but useless) gates upon init.
    ///
    /// Actually triggering an absent interrupt will send a General Protection
    /// fault (13).
    pub const fn absent() -> Self {
       Gate { offset_lower: 0
            , selector: segment::Selector::from_raw(0)
            , _zero: 0
            , flags: GateFlags { bits: 0 }
            , offset_mid: 0
            , offset_upper: 0
            , _reserved: 0
            , _handler_type: PhantomData
            }
    }

    /// Set the handler function corresponding to this gate.
    #[inline]
    pub fn set_handler<F>(&mut self, handler: F) -> &mut Self
    where Self: convert::From<F> {
        *self = Self::from(handler);
        self
    }

}

impl<H> Default for Gate<H> {
    fn default() -> Self {
        Gate { offset_lower: 0
             , selector: segment::Selector::from_raw(0)
             , _zero: 0
             , flags: GateFlags { bits: 0 }
             , offset_mid: 0
             , offset_upper: 0
             , _reserved: 0
             , _handler_type: PhantomData
             }
    }
}

impl<H> ops::Deref for Gate<H> {
    type Target = GateFlags;

    #[inline] fn deref(&self) -> &Self::Target { &self.flags }
}

impl<H> ops::DerefMut for Gate<H> {
    #[inline] fn deref_mut(&mut self) -> &mut Self::Target { &mut self.flags }
}

impl convert::From<InterruptHandler> for Gate<InterruptHandler> {

    /// Creates a new IDT gate pointing at the given handler function.
    ///
    /// The `handler` function must have been created with valid interrupt
    /// calling conventions.
    fn from(handler: InterruptHandler) -> Self {
        unsafe { // trust me on this, `mem::transmute()` is glorious black magic
                let (low, mid, high): (u16, u16, u32) = mem::transmute(handler);

            Gate { offset_lower: low
                 , offset_mid: mid
                 , offset_upper: high
                 , selector: segment::Selector::from_cs()
                 , flags: GateFlags::new_interrupt()
                 , ..Default::default()
                 }
        }
    }
}

impl convert::From<ErrorCodeHandler> for Gate<ErrorCodeHandler> {

    /// Creates a new IDT gate pointing at the given handler function.
    ///
    /// The `handler` function must have been created with valid interrupt
    /// calling conventions.
    fn from(handler: ErrorCodeHandler) -> Self {
        unsafe { // trust me on this, `mem::transmute()` is glorious black magic
                let (low, mid, high): (u16, u16, u32) = mem::transmute(handler);

            Gate { offset_lower: low
                 , offset_mid: mid
                 , offset_upper: high
                 , selector: segment::Selector::from_cs()
                 , flags: GateFlags::new_interrupt()
                 , ..Default::default()
                 }
        }
    }
}

impl convert::From<*const u8> for Gate {

    /// Creates a new IDT gate pointing at the given handler function.
    ///
    /// The `handler` function must have been created with valid interrupt
    /// calling conventions.
    ///
    /// This should probably not be used, if it can possibly be avoided.
    //  TODO: it would be really nice if we didn't need this any more.
    //        after the Revolution, once handlers are created in Rust-land with
    //        naked functions...
    fn from(handler: *const u8) -> Self {
        unsafe {
            let (low, mid, high): (u16, u16, u32) = mem::transmute(handler);

            Gate { offset_lower: low
                 , offset_mid: mid
                 , offset_upper: high
                 , selector: segment::Selector::from_cs()
                 , flags: GateFlags::new_interrupt()
                 , ..Default::default()
                 }
        }
    }
}
<commit_msg>feat(gate64): add function to set a gate to a trap gate<commit_after>//
//  SOS: the Stupid Operating System
//  by Eliza Weisman (eliza@elizas.website)
//
//  Copyright (c) 2015-2017 Eliza Weisman
//  Released under the terms of the MIT license. See `LICENSE` in the root
//  directory of this repository for more information.
//
//! 64-bit IDT gate implementation
use ::segment;
use super::{GateFlags};
use super::super::{InterruptHandler, ErrorCodeHandler};

use core::{convert, mem, ops};
use core::marker::PhantomData;

impl GateFlags {

    /// Returns a new trap gate
    pub const fn new_trap() -> Self {
        GateFlags { bits: super::TRAP_GATE_32.bits | super::PRESENT.bits }
    }

    /// Returns a new call gate
    pub const fn new_task() -> Self {
        GateFlags { bits: super::TASK_GATE_32.bits | super::PRESENT.bits }
    }

    /// Returns a new interrupt gate
    pub const fn new_interrupt() -> Self {
        GateFlags { bits: super::INT_GATE_32.bits | super::PRESENT.bits }
    }

}

/// An IDT entry is called a gate.
///
/// Based on [code](http://wiki.osdev.org/Interrupt_Descriptor_Table#Structure)
/// from the OS Dev Wiki.
///
/// Refer also to "6.14.1 64-Bit Mode IDT"  and "Table 3-2. System-Segment and
/// Gate-Descriptor Types" in the _Intel® 64 and IA-32 Architectures
/// Software Developer’s Manual_
#[repr(C, packed)]
#[derive(Copy, Clone)]
pub struct Gate<H = InterruptHandler>
    { /// bits 0 - 15 of the offset
      pub offset_lower: u16
    , /// code segment selector (GDT or LDT)
      pub selector: segment::Selector
    , /// always zero
      _zero: u8
    , /// indicates the gate's type and attributes.
      /// the second half indicates the type:
      ///   + `0b1100`: Call gate
      ///   + `0b1110`: Interrupt gate
      ///   + `0b1111`: Trap Gate
      pub flags: GateFlags
    , /// bits 16 - 31 of the offset
      pub offset_mid: u16
    , /// bits 32 - 63 of the offset
      pub offset_upper: u32
    , /// always zero (according to the spec, this is "reserved")
      _reserved: u32
    , _handler_type: PhantomData<H>
    }

impl<H> Gate<H> {

    /// Creates a new IDT gate marked as `absent`.
    ///
    /// This is basically just for filling the new IDT table
    /// with valid (but useless) gates upon init.
    ///
    /// Actually triggering an absent interrupt will send a General Protection
    /// fault (13).
    pub const fn absent() -> Self {
       Gate { offset_lower: 0
            , selector: segment::Selector::from_raw(0)
            , _zero: 0
            , flags: GateFlags { bits: 0 }
            , offset_mid: 0
            , offset_upper: 0
            , _reserved: 0
            , _handler_type: PhantomData
            }
    }

    /// Set the handler function corresponding to this gate.
    #[inline]
    pub fn set_handler<F>(&mut self, handler: F) -> &mut Self
    where Self: convert::From<F> {
        *self = Self::from(handler);
        self
    }

    /// Sets the TRAP GATE flag to true
    #[inline]
    pub fn set_trap(&mut self) -> &mut Self {
        self.flags.insert(super::TRAP_GATE_32);
        self
    }

}

impl<H> Default for Gate<H> {
    fn default() -> Self {
        Gate { offset_lower: 0
             , selector: segment::Selector::from_raw(0)
             , _zero: 0
             , flags: GateFlags { bits: 0 }
             , offset_mid: 0
             , offset_upper: 0
             , _reserved: 0
             , _handler_type: PhantomData
             }
    }
}

impl<H> ops::Deref for Gate<H> {
    type Target = GateFlags;

    #[inline] fn deref(&self) -> &Self::Target { &self.flags }
}

impl<H> ops::DerefMut for Gate<H> {
    #[inline] fn deref_mut(&mut self) -> &mut Self::Target { &mut self.flags }
}

impl convert::From<InterruptHandler> for Gate<InterruptHandler> {

    /// Creates a new IDT gate pointing at the given handler function.
    ///
    /// The `handler` function must have been created with valid interrupt
    /// calling conventions.
    fn from(handler: InterruptHandler) -> Self {
        unsafe { // trust me on this, `mem::transmute()` is glorious black magic
                let (low, mid, high): (u16, u16, u32) = mem::transmute(handler);

            Gate { offset_lower: low
                 , offset_mid: mid
                 , offset_upper: high
                 , selector: segment::Selector::from_cs()
                 , flags: GateFlags::new_interrupt()
                 , ..Default::default()
                 }
        }
    }
}

impl convert::From<ErrorCodeHandler> for Gate<ErrorCodeHandler> {

    /// Creates a new IDT gate pointing at the given handler function.
    ///
    /// The `handler` function must have been created with valid interrupt
    /// calling conventions.
    fn from(handler: ErrorCodeHandler) -> Self {
        unsafe { // trust me on this, `mem::transmute()` is glorious black magic
                let (low, mid, high): (u16, u16, u32) = mem::transmute(handler);

            Gate { offset_lower: low
                 , offset_mid: mid
                 , offset_upper: high
                 , selector: segment::Selector::from_cs()
                 , flags: GateFlags::new_interrupt()
                 , ..Default::default()
                 }
        }
    }
}

impl convert::From<*const u8> for Gate {

    /// Creates a new IDT gate pointing at the given handler function.
    ///
    /// The `handler` function must have been created with valid interrupt
    /// calling conventions.
    ///
    /// This should probably not be used, if it can possibly be avoided.
    //  TODO: it would be really nice if we didn't need this any more.
    //        after the Revolution, once handlers are created in Rust-land with
    //        naked functions...
    fn from(handler: *const u8) -> Self {
        unsafe {
            let (low, mid, high): (u16, u16, u32) = mem::transmute(handler);

            Gate { offset_lower: low
                 , offset_mid: mid
                 , offset_upper: high
                 , selector: segment::Selector::from_cs()
                 , flags: GateFlags::new_interrupt()
                 , ..Default::default()
                 }
        }
    }
}
<|endoftext|>