<commit_before>use crate::Msg;
use seed::prelude::*;
use web_sys::{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;
}

pub struct Check {
    pub is_prime: bool,
    pub result: String,
}

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

    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);
            is_prime = true;
        } 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);
                is_prime = true;
            } 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
                );
                is_prime = true;
            };
        } else {
            result = format!(
                "{} is (proven) composite (failed sprp test base {}).",
                n, 17
            );
        };
    };

    return Check{is_prime, result};
}

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.is_prime == true {
            list = list + &result.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).result);
    ()
}

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 => "31", 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 => "5", At::MaxLength => "2"}
                    ],
                    " prime numbers after ",
                    input![
                        attrs! {At::Type => "number", At::Size => "19", At::Id => "start", At::Value => "31", 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);
    }
}
<commit_msg>while true -> loop<commit_after>use crate::Msg;
use seed::prelude::*;
use web_sys::{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!
    loop {
        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;
}

pub struct Check {
    pub is_prime: bool,
    pub result: String,
}

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

    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);
            is_prime = true;
        } 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);
                is_prime = true;
            } 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
                );
                is_prime = true;
            };
        } else {
            result = format!(
                "{} is (proven) composite (failed sprp test base {}).",
                n, 17
            );
        };
    };

    return Check{is_prime, result};
}

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.is_prime == true {
            list = list + &result.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).result);
    ()
}

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 => "31", 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 => "5", At::MaxLength => "2"}
                    ],
                    " prime numbers after ",
                    input![
                        attrs! {At::Type => "number", At::Size => "19", At::Id => "start", At::Value => "31", 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>// Copyright (c) Aptos
// SPDX-License-Identifier: Apache-2.0

use aptos_types::vm_status::StatusCode;
use poem_openapi::{Enum, Object};
use serde::Deserialize;

/// This is the generic struct we use for all API errors, it contains a string
/// message and an Aptos API specific error code.
#[derive(Debug, Deserialize, Object)]
pub struct AptosError {
    /// A message describing the error
    pub message: String,
    /// A code providing more granular error information beyond the HTTP status code
    pub error_code: AptosErrorCode,
    /// A code providing VM error details when submitting transactions to the VM
    #[serde(skip_serializing_if = "Option::is_none")]
    pub vm_error_code: Option<u64>,
}

impl AptosError {
    pub fn new_with_error_code<ErrorType: std::fmt::Display>(
        error: ErrorType,
        error_code: AptosErrorCode,
    ) -> AptosError {
        Self {
            message: error.to_string(),
            error_code,
            vm_error_code: None,
        }
    }

    pub fn new_with_vm_status<ErrorType: std::fmt::Display>(
        error: ErrorType,
        error_code: AptosErrorCode,
        vm_error_code: StatusCode,
    ) -> AptosError {
        Self {
            message: error.to_string(),
            error_code,
            vm_error_code: Some(vm_error_code as u64),
        }
    }
}

/// These codes provide more granular error information beyond just the HTTP
/// status code of the response.
#[derive(Debug, Deserialize, Enum)]
#[oai(rename_all = "snake_case")]
#[serde(rename_all = "snake_case")]
pub enum AptosErrorCode {
    /// Account not found at the requested version
    AccountNotFound = 101,
    /// Resource not found at the requested version
    ResourceNotFound = 102,
    /// Module not found at the requested version
    ModuleNotFound = 103,
    /// Struct field not found at the requested version
    StructFieldNotFound = 104,
    /// Ledger version not found at the requested version
    ///
    /// Usually means that the version is ahead of the latest version
    VersionNotFound = 105,
    /// Transaction not found at the requested version or with the requested hash
    TransactionNotFound = 106,
    /// Table item not found at the requested version
    TableItemNotFound = 107,
    /// Block not found at the requested version or height
    ///
    /// Usually means the block is fully or partially pruned or the height / version is ahead
    /// of the latest version
    BlockNotFound = 108,

    /// Ledger version is pruned
    VersionPruned = 200,
    /// Block is fully or partially pruned
    BlockPruned = 201,

    /// The API's inputs were invalid
    InvalidInput = 300,
    /// The start param given for paging is invalid.
    InvalidStartParam = 301,
    /// The limit param given for paging is invalid.
    InvalidLimitParam = 302,
    /// The event key for events is invalid.
    InvalidEventKey = 303,

    /// The transaction submitted was invalid.
    InvalidSubmittedTransaction = 400,
    /// The transaction was an invalid update to an already submitted transaction.
    InvalidTransactionUpdate = 401,
    /// The sequence number for the transaction is behind the latest sequence number.
    SequenceNumberTooOld = 402,
    /// The submitted transaction failed VM checks.
    VmError = 403,
    /// The transaction failed to submit.
    TransactionSubmissionFailed = 404,

    /// Health check failed.
    HealthCheckFailed = 500,
    /// The mempool is full, no new transactions can be submitted.
    MempoolIsFull = 501,
    /// The mempool is full for this account's quota, no new transactions can be submitted.
    MempoolIsFullForAccount = 502,

    /// Internal server error
    InternalError = 600,
    /// The API failed to read from storage for this request, not because of a
    /// bad request, but because of some internal error.
    ReadFromStorageError = 601,
    /// The data we read from the DB was not valid BCS.
    InvalidBcsInStorageError = 602,
    /// We were unexpectedly unable to convert a Rust type to BCS.
    BcsSerializationError = 603,
    /// Error from the web framework
    WebFrameworkError = 604,

    /// BCS format is not supported on this API.
    BcsNotSupported = 701,
}
<commit_msg>[api] Implement std::error::Error for AptosError<commit_after>// Copyright (c) Aptos
// SPDX-License-Identifier: Apache-2.0

use aptos_types::vm_status::StatusCode;
use poem_openapi::{Enum, Object};
use serde::Deserialize;
use std::fmt::Formatter;

/// This is the generic struct we use for all API errors, it contains a string
/// message and an Aptos API specific error code.
#[derive(Debug, Deserialize, Object)]
pub struct AptosError {
    /// A message describing the error
    pub message: String,
    /// A code providing more granular error information beyond the HTTP status code
    pub error_code: AptosErrorCode,
    /// A code providing VM error details when submitting transactions to the VM
    #[serde(skip_serializing_if = "Option::is_none")]
    pub vm_error_code: Option<u64>,
}

impl std::fmt::Display for AptosError {
    fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
        write!(f, "{:?}", self)
    }
}

impl std::error::Error for AptosError {}

impl AptosError {
    pub fn new_with_error_code<ErrorType: std::fmt::Display>(
        error: ErrorType,
        error_code: AptosErrorCode,
    ) -> AptosError {
        Self {
            message: error.to_string(),
            error_code,
            vm_error_code: None,
        }
    }

    pub fn new_with_vm_status<ErrorType: std::fmt::Display>(
        error: ErrorType,
        error_code: AptosErrorCode,
        vm_error_code: StatusCode,
    ) -> AptosError {
        Self {
            message: error.to_string(),
            error_code,
            vm_error_code: Some(vm_error_code as u64),
        }
    }
}

/// These codes provide more granular error information beyond just the HTTP
/// status code of the response.
#[derive(Debug, Deserialize, Enum)]
#[oai(rename_all = "snake_case")]
#[serde(rename_all = "snake_case")]
pub enum AptosErrorCode {
    /// Account not found at the requested version
    AccountNotFound = 101,
    /// Resource not found at the requested version
    ResourceNotFound = 102,
    /// Module not found at the requested version
    ModuleNotFound = 103,
    /// Struct field not found at the requested version
    StructFieldNotFound = 104,
    /// Ledger version not found at the requested version
    ///
    /// Usually means that the version is ahead of the latest version
    VersionNotFound = 105,
    /// Transaction not found at the requested version or with the requested hash
    TransactionNotFound = 106,
    /// Table item not found at the requested version
    TableItemNotFound = 107,
    /// Block not found at the requested version or height
    ///
    /// Usually means the block is fully or partially pruned or the height / version is ahead
    /// of the latest version
    BlockNotFound = 108,

    /// Ledger version is pruned
    VersionPruned = 200,
    /// Block is fully or partially pruned
    BlockPruned = 201,

    /// The API's inputs were invalid
    InvalidInput = 300,
    /// The start param given for paging is invalid.
    InvalidStartParam = 301,
    /// The limit param given for paging is invalid.
    InvalidLimitParam = 302,
    /// The event key for events is invalid.
    InvalidEventKey = 303,

    /// The transaction submitted was invalid.
    InvalidSubmittedTransaction = 400,
    /// The transaction was an invalid update to an already submitted transaction.
    InvalidTransactionUpdate = 401,
    /// The sequence number for the transaction is behind the latest sequence number.
    SequenceNumberTooOld = 402,
    /// The submitted transaction failed VM checks.
    VmError = 403,
    /// The transaction failed to submit.
    TransactionSubmissionFailed = 404,

    /// Health check failed.
    HealthCheckFailed = 500,
    /// The mempool is full, no new transactions can be submitted.
    MempoolIsFull = 501,
    /// The mempool is full for this account's quota, no new transactions can be submitted.
    MempoolIsFullForAccount = 502,

    /// Internal server error
    InternalError = 600,
    /// The API failed to read from storage for this request, not because of a
    /// bad request, but because of some internal error.
    ReadFromStorageError = 601,
    /// The data we read from the DB was not valid BCS.
    InvalidBcsInStorageError = 602,
    /// We were unexpectedly unable to convert a Rust type to BCS.
    BcsSerializationError = 603,
    /// Error from the web framework
    WebFrameworkError = 604,

    /// BCS format is not supported on this API.
    BcsNotSupported = 701,
}
<|endoftext|>


<commit_before>use crate::gen::{CfgEvaluator, CfgResult};
use once_cell::sync::OnceCell;
use std::borrow::Borrow;
use std::cmp::Ordering;
use std::collections::{BTreeMap as Map, BTreeSet as Set};
use std::env;

static ENV: OnceCell<CargoEnv> = OnceCell::new();

struct CargoEnv {
    features: Set<Name>,
    cfgs: Map<Name, String>,
}

pub(super) struct CargoEnvCfgEvaluator;

impl CfgEvaluator for CargoEnvCfgEvaluator {
    fn eval(&self, name: &str, query_value: Option<&str>) -> CfgResult {
        let env = ENV.get_or_init(CargoEnv::load);
        if name == "feature" {
            return if let Some(query_value) = query_value {
                CfgResult::from(env.features.contains(Lookup::new(query_value)))
            } else {
                let msg = "expected `feature = \"...\"`".to_owned();
                CfgResult::Undetermined { msg }
            };
        }
        if name == "test" && query_value.is_none() {
            let msg = "cfg(test) is not supported because Cargo runs your build script only once across the lib and test build of the same crate".to_owned();
            return CfgResult::Undetermined { msg };
        }
        if let Some(cargo_value) = env.cfgs.get(Lookup::new(name)) {
            return if let Some(query_value) = query_value {
                CfgResult::from(cargo_value.split(',').any(|value| value == query_value))
            } else {
                CfgResult::True
            };
        }
        CfgResult::False
    }
}

impl CargoEnv {
    fn load() -> Self {
        const CARGO_FEATURE_PREFIX: &str = "CARGO_FEATURE_";
        const CARGO_CFG_PREFIX: &str = "CARGO_CFG_";

        let mut features = Set::new();
        let mut cfgs = Map::new();
        for (k, v) in env::vars_os() {
            let k = match k.to_str() {
                Some(k) => k,
                None => continue,
            };
            let v = match v.into_string() {
                Ok(v) => v,
                Err(_) => continue,
            };
            if let Some(feature_name) = k.strip_prefix(CARGO_FEATURE_PREFIX) {
                let feature_name = Name(feature_name.to_owned());
                features.insert(feature_name);
            } else if let Some(cfg_name) = k.strip_prefix(CARGO_CFG_PREFIX) {
                let cfg_name = Name(cfg_name.to_owned());
                cfgs.insert(cfg_name, v);
            }
        }
        CargoEnv { features, cfgs }
    }
}

struct Name(String);

impl Ord for Name {
    fn cmp(&self, rhs: &Self) -> Ordering {
        Lookup::new(&self.0).cmp(Lookup::new(&rhs.0))
    }
}

impl PartialOrd for Name {
    fn partial_cmp(&self, rhs: &Self) -> Option<Ordering> {
        Some(self.cmp(rhs))
    }
}

impl Eq for Name {}

impl PartialEq for Name {
    fn eq(&self, rhs: &Self) -> bool {
        Lookup::new(&self.0).eq(Lookup::new(&rhs.0))
    }
}

#[repr(transparent)]
struct Lookup(str);

impl Lookup {
    fn new(name: &str) -> &Self {
        unsafe { &*(name as *const str as *const Self) }
    }
}

impl Borrow<Lookup> for Name {
    fn borrow(&self) -> &Lookup {
        Lookup::new(&self.0)
    }
}

impl Ord for Lookup {
    fn cmp(&self, rhs: &Self) -> Ordering {
        self.0
            .bytes()
            .map(CaseAgnosticByte)
            .cmp(rhs.0.bytes().map(CaseAgnosticByte))
    }
}

impl PartialOrd for Lookup {
    fn partial_cmp(&self, rhs: &Self) -> Option<Ordering> {
        Some(self.cmp(rhs))
    }
}

impl Eq for Lookup {}

impl PartialEq for Lookup {
    fn eq(&self, rhs: &Self) -> bool {
        self.0
            .bytes()
            .map(CaseAgnosticByte)
            .eq(rhs.0.bytes().map(CaseAgnosticByte))
    }
}

struct CaseAgnosticByte(u8);

impl Ord for CaseAgnosticByte {
    fn cmp(&self, rhs: &Self) -> Ordering {
        self.0.to_ascii_lowercase().cmp(&rhs.0.to_ascii_lowercase())
    }
}

impl PartialOrd for CaseAgnosticByte {
    fn partial_cmp(&self, rhs: &Self) -> Option<Ordering> {
        Some(self.cmp(rhs))
    }
}

impl Eq for CaseAgnosticByte {}

impl PartialEq for CaseAgnosticByte {
    fn eq(&self, rhs: &Self) -> bool {
        self.cmp(rhs) == Ordering::Equal
    }
}
<commit_msg>Add workaround for evaluating cfg(debug_assertions)<commit_after>use crate::gen::{CfgEvaluator, CfgResult};
use once_cell::sync::OnceCell;
use std::borrow::Borrow;
use std::cmp::Ordering;
use std::collections::{BTreeMap as Map, BTreeSet as Set};
use std::env;

static ENV: OnceCell<CargoEnv> = OnceCell::new();

struct CargoEnv {
    features: Set<Name>,
    cfgs: Map<Name, String>,
}

pub(super) struct CargoEnvCfgEvaluator;

impl CfgEvaluator for CargoEnvCfgEvaluator {
    fn eval(&self, name: &str, query_value: Option<&str>) -> CfgResult {
        let env = ENV.get_or_init(CargoEnv::load);
        if name == "feature" {
            return if let Some(query_value) = query_value {
                CfgResult::from(env.features.contains(Lookup::new(query_value)))
            } else {
                let msg = "expected `feature = \"...\"`".to_owned();
                CfgResult::Undetermined { msg }
            };
        }
        if name == "test" && query_value.is_none() {
            let msg = "cfg(test) is not supported because Cargo runs your build script only once across the lib and test build of the same crate".to_owned();
            return CfgResult::Undetermined { msg };
        }
        if let Some(cargo_value) = env.cfgs.get(Lookup::new(name)) {
            return if let Some(query_value) = query_value {
                CfgResult::from(cargo_value.split(',').any(|value| value == query_value))
            } else {
                CfgResult::True
            };
        }
        if name == "debug_assertions" && query_value.is_none() {
            return CfgResult::from(cfg!(debug_assertions));
        }
        CfgResult::False
    }
}

impl CargoEnv {
    fn load() -> Self {
        const CARGO_FEATURE_PREFIX: &str = "CARGO_FEATURE_";
        const CARGO_CFG_PREFIX: &str = "CARGO_CFG_";

        let mut features = Set::new();
        let mut cfgs = Map::new();
        for (k, v) in env::vars_os() {
            let k = match k.to_str() {
                Some(k) => k,
                None => continue,
            };
            let v = match v.into_string() {
                Ok(v) => v,
                Err(_) => continue,
            };
            if let Some(feature_name) = k.strip_prefix(CARGO_FEATURE_PREFIX) {
                let feature_name = Name(feature_name.to_owned());
                features.insert(feature_name);
            } else if let Some(cfg_name) = k.strip_prefix(CARGO_CFG_PREFIX) {
                let cfg_name = Name(cfg_name.to_owned());
                cfgs.insert(cfg_name, v);
            }
        }
        CargoEnv { features, cfgs }
    }
}

struct Name(String);

impl Ord for Name {
    fn cmp(&self, rhs: &Self) -> Ordering {
        Lookup::new(&self.0).cmp(Lookup::new(&rhs.0))
    }
}

impl PartialOrd for Name {
    fn partial_cmp(&self, rhs: &Self) -> Option<Ordering> {
        Some(self.cmp(rhs))
    }
}

impl Eq for Name {}

impl PartialEq for Name {
    fn eq(&self, rhs: &Self) -> bool {
        Lookup::new(&self.0).eq(Lookup::new(&rhs.0))
    }
}

#[repr(transparent)]
struct Lookup(str);

impl Lookup {
    fn new(name: &str) -> &Self {
        unsafe { &*(name as *const str as *const Self) }
    }
}

impl Borrow<Lookup> for Name {
    fn borrow(&self) -> &Lookup {
        Lookup::new(&self.0)
    }
}

impl Ord for Lookup {
    fn cmp(&self, rhs: &Self) -> Ordering {
        self.0
            .bytes()
            .map(CaseAgnosticByte)
            .cmp(rhs.0.bytes().map(CaseAgnosticByte))
    }
}

impl PartialOrd for Lookup {
    fn partial_cmp(&self, rhs: &Self) -> Option<Ordering> {
        Some(self.cmp(rhs))
    }
}

impl Eq for Lookup {}

impl PartialEq for Lookup {
    fn eq(&self, rhs: &Self) -> bool {
        self.0
            .bytes()
            .map(CaseAgnosticByte)
            .eq(rhs.0.bytes().map(CaseAgnosticByte))
    }
}

struct CaseAgnosticByte(u8);

impl Ord for CaseAgnosticByte {
    fn cmp(&self, rhs: &Self) -> Ordering {
        self.0.to_ascii_lowercase().cmp(&rhs.0.to_ascii_lowercase())
    }
}

impl PartialOrd for CaseAgnosticByte {
    fn partial_cmp(&self, rhs: &Self) -> Option<Ordering> {
        Some(self.cmp(rhs))
    }
}

impl Eq for CaseAgnosticByte {}

impl PartialEq for CaseAgnosticByte {
    fn eq(&self, rhs: &Self) -> bool {
        self.cmp(rhs) == Ordering::Equal
    }
}
<|endoftext|>


<commit_before>use super::allocators::{Allocator, DefaultHeap};
use super::pointer_to_maybe_compact::PointerToMaybeCompact;
use super::compact::Compact;
use ::std::marker::PhantomData;
use ::std::ptr;
use ::std::ops::{Deref, DerefMut};
use ::std::iter::FromIterator;

pub struct CompactVec <T, A: Allocator = DefaultHeap> {
    ptr: PointerToMaybeCompact<T>,
    len: usize,
    cap: usize,
    _alloc: PhantomData<*const A>
}

impl<T: Compact + Clone, A: Allocator> CompactVec<T, A> {
    pub fn len(&self) -> usize {
        self.len
    }

    pub fn is_empty(&self) -> bool {
        self.len == 0
    }

    pub fn new() -> CompactVec<T, A> {
        CompactVec {
            ptr: PointerToMaybeCompact::default(),
            len: 0,
            cap: 0,
            _alloc: PhantomData
        }
    }

    pub fn with_capacity(cap: usize) -> CompactVec<T, A> {
        let mut vec = CompactVec {
            ptr: PointerToMaybeCompact::default(),
            len: 0,
            cap: cap,
            _alloc: PhantomData
        };

        vec.ptr.set_to_free(A::allocate::<T>(cap));
        vec
    }

    fn double_buf(&mut self) {
        let new_cap = if self.cap == 0 {1} else {self.cap * 2};
        let new_ptr = A::allocate::<T>(new_cap);

        // items should be decompacted, else internal relative pointers get messed up!
        #[allow(needless_range_loop)]
        for i in 0..self.len() {
            unsafe {ptr::write(new_ptr.offset(i as isize), self[i].decompact())};
        }

        // items shouldn't be dropped here, they live on in the new backing store!
        if !self.ptr.is_compact() {
            unsafe {A::deallocate(self.ptr.mut_ptr(), self.cap);}
        }
        self.ptr.set_to_free(new_ptr);
        self.cap = new_cap;
    }

    pub fn push(&mut self, value: T) {
        if self.len == self.cap {
            self.double_buf();
        }

        unsafe {
            let end = self.as_mut_ptr().offset(self.len as isize);
            ptr::write(end, value);
            self.len += 1;
        }
    }

    pub fn pop(&mut self) -> Option<T> {
        if self.len == 0 {
            None
        } else {
            unsafe {
                self.len -= 1;
                Some(ptr::read(self.get_unchecked(self.len())))
            }
        }
    }

    pub fn insert(&mut self, index: usize, value: T) {
        if self.len == self.cap {
            self.double_buf();
        }

        unsafe {
            // infallible
            {
                let ptr = self.as_mut_ptr().offset(index as isize);
                // items should be decompacted, else internal relative pointers get messed up!
                for i in (0..self.len - index).rev() {
                    ptr::write(ptr.offset((i + 1) as isize), self[index + i].decompact());
                }
                //ptr::copy(p, p.offset(1), self.len - index);
                ptr::write(ptr, value);
            }
            self.len += 1;
        }
    }

    pub fn remove(&mut self, index: usize) -> T {
        let len = self.len;
        assert!(index < len);
        unsafe {
            // infallible
            let ret;
            {
                // the place we are taking from.
                let ptr = self.as_mut_ptr().offset(index as isize);
                // copy it out, unsafely having a copy of the value on
                // the stack and in the vector at the same time.
                ret = ptr::read(ptr);

                // Shift everything down to fill in that spot.
                // items should be decompacted, else internal relative pointers get messed up!
                #[allow(needless_range_loop)]
                for i in 0..len - index - 1 {
                    ptr::write(ptr.offset(i as isize), self[index + i + 1].decompact())
                }
                //ptr::copy(ptr.offset(1), ptr, len - index - 1);
            }
            self.len -= 1;
            ret
        }
    }

    pub fn clear(&mut self) {
        // TODO: Drop?
        self.len = 0;
    }
}

impl<T, A: Allocator> From<Vec<T>> for CompactVec<T, A> {
    fn from(mut vec: Vec<T>) -> Self {
        let p = vec.as_mut_ptr();
        let len = vec.len();
        let cap = vec.capacity();

        ::std::mem::forget(vec);

        CompactVec{
            ptr: PointerToMaybeCompact::new_free(p),
            len: len,
            cap: cap,
            _alloc: PhantomData
        }
    }
}

impl<T, A: Allocator> Drop for CompactVec<T, A> {
    fn drop(&mut self) {
        unsafe {ptr::drop_in_place(&mut self[..])};
        if !self.ptr.is_compact() {
            unsafe {A::deallocate(self.ptr.mut_ptr(), self.cap);}
        }
    }
}

impl<T, A: Allocator> Deref for CompactVec<T, A> {
    type Target = [T];

    fn deref(&self) -> &[T] {
        unsafe {
            ::std::slice::from_raw_parts(self.ptr.ptr(), self.len)
        }
    }
}

impl<T, A: Allocator> DerefMut for CompactVec<T, A> {
    fn deref_mut(&mut self) -> &mut [T] {
        unsafe {
            ::std::slice::from_raw_parts_mut(self.ptr.mut_ptr(), self.len)
        }
    }
}

pub struct IntoIter<T, A: Allocator> {
    ptr: PointerToMaybeCompact<T>,
    len: usize,
    cap: usize,
    index: usize,
    _alloc: PhantomData<*const A>
}

impl<T, A: Allocator> Iterator for IntoIter<T, A>{
    type Item=T;

    fn next(&mut self) -> Option<T> {
        if self.index < self.len {
            let item = unsafe{ptr::read(self.ptr.ptr().offset(self.index as isize))};
            self.index += 1;
            Some(item)
        } else {None}
    }
}

impl<T, A: Allocator> Drop for IntoIter<T, A> {
    fn drop(&mut self) {
        // drop all remaining elements
        unsafe {ptr::drop_in_place(&mut ::std::slice::from_raw_parts(
            self.ptr.ptr().offset(self.index as isize), self.len
        ))};
        if !self.ptr.is_compact() {
            unsafe {A::deallocate(self.ptr.mut_ptr(), self.cap);}
        }
    }
}

impl<T, A: Allocator> IntoIterator for CompactVec<T, A> {
    type Item = T;
    type IntoIter = IntoIter<T, A>;

    fn into_iter(self) -> Self::IntoIter {
        let iter = IntoIter{
            ptr: unsafe{ptr::read(&self.ptr)},
            len: self.len,
            cap: self.cap,
            index: 0,
            _alloc: PhantomData
        };
        ::std::mem::forget(self);
        iter
    }
}

impl<'a, T, A: Allocator> IntoIterator for &'a CompactVec<T, A> {
    type Item = &'a T;
    type IntoIter = ::std::slice::Iter<'a, T>;

    fn into_iter(self) -> Self::IntoIter {self.iter()}
}

impl<'a, T, A: Allocator> IntoIterator for &'a mut CompactVec<T, A> {
    type Item = &'a mut T;
    type IntoIter = ::std::slice::IterMut<'a, T>;

    fn into_iter(self) -> Self::IntoIter {self.iter_mut()}
}

impl<T: Compact + Clone, A: Allocator> Compact for CompactVec<T, A> {
    default fn is_still_compact(&self) -> bool {
        self.ptr.is_compact() && self.iter().all(|elem| elem.is_still_compact())
    }

    default fn dynamic_size_bytes(&self) -> usize {
        self.cap * ::std::mem::size_of::<T>() + self.iter().map(|elem| elem.dynamic_size_bytes()).sum::<usize>()
    }

    default unsafe fn compact_from(&mut self, source: &Self, new_dynamic_part: *mut u8) {
        self.cap = source.cap;
        self.len = source.len;
        self.ptr.set_to_compact(new_dynamic_part as *mut T);

        let mut offset = self.cap * ::std::mem::size_of::<T>();
        for i in 0..self.len {
            self[i].compact_from(&source[i], new_dynamic_part.offset(offset as isize));
            offset += self[i].dynamic_size_bytes();
        }
    }

    default unsafe fn decompact(&self) -> Self {
        if self.ptr.is_compact() {
            self.clone()
        } else {
            CompactVec{
                ptr: ptr::read(&self.ptr as *const PointerToMaybeCompact<T>),
                len: self.len,
                cap: self.cap,
                _alloc: self._alloc
            }
            // caller has to make sure that self will not be dropped!
        }
    }
}

impl<T: Copy, A: Allocator> Compact for CompactVec<T, A> {
    fn is_still_compact(&self) -> bool {
        self.ptr.is_compact()
    }

    fn dynamic_size_bytes(&self) -> usize {
        self.cap * ::std::mem::size_of::<T>()
    }

    unsafe fn compact_from(&mut self, source: &Self, new_dynamic_part: *mut u8) {
        self.cap = source.cap;
        self.len = source.len;
        self.ptr.set_to_compact(new_dynamic_part as *mut T);
        ptr::copy_nonoverlapping(source.ptr.ptr(), self.ptr.mut_ptr(), self.len);
    }
}

impl<T: Clone, A: Allocator> Clone for CompactVec<T, A> {
    default fn clone(&self) -> CompactVec<T, A> {
        self.iter().cloned().collect::<Vec<_>>().into()
    }
}

impl<T: Copy, A: Allocator> Clone for CompactVec<T, A> {
    fn clone(&self) -> CompactVec<T, A> {
        let mut new_vec = Self::with_capacity(self.cap);
        unsafe {
            ptr::copy_nonoverlapping(self.ptr.ptr(), new_vec.ptr.mut_ptr(), self.len);
        }
        new_vec.len = self.len;
        new_vec
    }
}

impl<T: Compact + Clone, A: Allocator> FromIterator<T> for CompactVec<T, A> {
    fn from_iter<I: IntoIterator<Item=T>>(iter: I) -> Self {
        let mut vec = CompactVec::new();
        for item in iter {
            vec.push(item);
        }
        vec
    }
}

impl<T: Compact + Clone, A: Allocator> Extend<T> for CompactVec<T, A> {
    fn extend<I: IntoIterator<Item=T>>(&mut self, iter: I) {
        for item in iter {
            self.push(item);
        }
    }
}

impl<T: Compact, A: Allocator> Default for CompactVec<T, A> {
    fn default() -> CompactVec<T, A> {
        CompactVec::new()
    }
}

impl<T: Compact + ::std::fmt::Debug, A: Allocator> ::std::fmt::Debug for CompactVec<T, A> {
    fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result {
        (self.deref()).fmt(f)
    }
}<commit_msg>Smarter CVec::collect() #14<commit_after>use super::allocators::{Allocator, DefaultHeap};
use super::pointer_to_maybe_compact::PointerToMaybeCompact;
use super::compact::Compact;
use ::std::marker::PhantomData;
use ::std::ptr;
use ::std::ops::{Deref, DerefMut};
use ::std::iter::FromIterator;

pub struct CompactVec <T, A: Allocator = DefaultHeap> {
    ptr: PointerToMaybeCompact<T>,
    len: usize,
    cap: usize,
    _alloc: PhantomData<*const A>
}

impl<T: Compact + Clone, A: Allocator> CompactVec<T, A> {
    pub fn len(&self) -> usize {
        self.len
    }

    pub fn is_empty(&self) -> bool {
        self.len == 0
    }

    pub fn new() -> CompactVec<T, A> {
        CompactVec {
            ptr: PointerToMaybeCompact::default(),
            len: 0,
            cap: 0,
            _alloc: PhantomData
        }
    }

    pub fn with_capacity(cap: usize) -> CompactVec<T, A> {
        let mut vec = CompactVec {
            ptr: PointerToMaybeCompact::default(),
            len: 0,
            cap: cap,
            _alloc: PhantomData
        };

        vec.ptr.set_to_free(A::allocate::<T>(cap));
        vec
    }

    fn double_buf(&mut self) {
        let new_cap = if self.cap == 0 {1} else {self.cap * 2};
        let new_ptr = A::allocate::<T>(new_cap);

        // items should be decompacted, else internal relative pointers get messed up!
        #[allow(needless_range_loop)]
        for i in 0..self.len() {
            unsafe {ptr::write(new_ptr.offset(i as isize), self[i].decompact())};
        }

        // items shouldn't be dropped here, they live on in the new backing store!
        if !self.ptr.is_compact() {
            unsafe {A::deallocate(self.ptr.mut_ptr(), self.cap);}
        }
        self.ptr.set_to_free(new_ptr);
        self.cap = new_cap;
    }

    pub fn push(&mut self, value: T) {
        if self.len == self.cap {
            self.double_buf();
        }

        unsafe {
            let end = self.as_mut_ptr().offset(self.len as isize);
            ptr::write(end, value);
            self.len += 1;
        }
    }

    pub fn pop(&mut self) -> Option<T> {
        if self.len == 0 {
            None
        } else {
            unsafe {
                self.len -= 1;
                Some(ptr::read(self.get_unchecked(self.len())))
            }
        }
    }

    pub fn insert(&mut self, index: usize, value: T) {
        if self.len == self.cap {
            self.double_buf();
        }

        unsafe {
            // infallible
            {
                let ptr = self.as_mut_ptr().offset(index as isize);
                // items should be decompacted, else internal relative pointers get messed up!
                for i in (0..self.len - index).rev() {
                    ptr::write(ptr.offset((i + 1) as isize), self[index + i].decompact());
                }
                //ptr::copy(p, p.offset(1), self.len - index);
                ptr::write(ptr, value);
            }
            self.len += 1;
        }
    }

    pub fn remove(&mut self, index: usize) -> T {
        let len = self.len;
        assert!(index < len);
        unsafe {
            // infallible
            let ret;
            {
                // the place we are taking from.
                let ptr = self.as_mut_ptr().offset(index as isize);
                // copy it out, unsafely having a copy of the value on
                // the stack and in the vector at the same time.
                ret = ptr::read(ptr);

                // Shift everything down to fill in that spot.
                // items should be decompacted, else internal relative pointers get messed up!
                #[allow(needless_range_loop)]
                for i in 0..len - index - 1 {
                    ptr::write(ptr.offset(i as isize), self[index + i + 1].decompact())
                }
                //ptr::copy(ptr.offset(1), ptr, len - index - 1);
            }
            self.len -= 1;
            ret
        }
    }

    pub fn clear(&mut self) {
        // TODO: Drop?
        self.len = 0;
    }
}

impl<T, A: Allocator> From<Vec<T>> for CompactVec<T, A> {
    fn from(mut vec: Vec<T>) -> Self {
        let p = vec.as_mut_ptr();
        let len = vec.len();
        let cap = vec.capacity();

        ::std::mem::forget(vec);

        CompactVec{
            ptr: PointerToMaybeCompact::new_free(p),
            len: len,
            cap: cap,
            _alloc: PhantomData
        }
    }
}

impl<T, A: Allocator> Drop for CompactVec<T, A> {
    fn drop(&mut self) {
        unsafe {ptr::drop_in_place(&mut self[..])};
        if !self.ptr.is_compact() {
            unsafe {A::deallocate(self.ptr.mut_ptr(), self.cap);}
        }
    }
}

impl<T, A: Allocator> Deref for CompactVec<T, A> {
    type Target = [T];

    fn deref(&self) -> &[T] {
        unsafe {
            ::std::slice::from_raw_parts(self.ptr.ptr(), self.len)
        }
    }
}

impl<T, A: Allocator> DerefMut for CompactVec<T, A> {
    fn deref_mut(&mut self) -> &mut [T] {
        unsafe {
            ::std::slice::from_raw_parts_mut(self.ptr.mut_ptr(), self.len)
        }
    }
}

pub struct IntoIter<T, A: Allocator> {
    ptr: PointerToMaybeCompact<T>,
    len: usize,
    cap: usize,
    index: usize,
    _alloc: PhantomData<*const A>
}

impl<T, A: Allocator> Iterator for IntoIter<T, A>{
    type Item=T;

    fn next(&mut self) -> Option<T> {
        if self.index < self.len {
            let item = unsafe{ptr::read(self.ptr.ptr().offset(self.index as isize))};
            self.index += 1;
            Some(item)
        } else {None}
    }
}

impl<T, A: Allocator> Drop for IntoIter<T, A> {
    fn drop(&mut self) {
        // drop all remaining elements
        unsafe {ptr::drop_in_place(&mut ::std::slice::from_raw_parts(
            self.ptr.ptr().offset(self.index as isize), self.len
        ))};
        if !self.ptr.is_compact() {
            unsafe {A::deallocate(self.ptr.mut_ptr(), self.cap);}
        }
    }
}

impl<T, A: Allocator> IntoIterator for CompactVec<T, A> {
    type Item = T;
    type IntoIter = IntoIter<T, A>;

    fn into_iter(self) -> Self::IntoIter {
        let iter = IntoIter{
            ptr: unsafe{ptr::read(&self.ptr)},
            len: self.len,
            cap: self.cap,
            index: 0,
            _alloc: PhantomData
        };
        ::std::mem::forget(self);
        iter
    }
}

impl<'a, T, A: Allocator> IntoIterator for &'a CompactVec<T, A> {
    type Item = &'a T;
    type IntoIter = ::std::slice::Iter<'a, T>;

    fn into_iter(self) -> Self::IntoIter {self.iter()}
}

impl<'a, T, A: Allocator> IntoIterator for &'a mut CompactVec<T, A> {
    type Item = &'a mut T;
    type IntoIter = ::std::slice::IterMut<'a, T>;

    fn into_iter(self) -> Self::IntoIter {self.iter_mut()}
}

impl<T: Compact + Clone, A: Allocator> Compact for CompactVec<T, A> {
    default fn is_still_compact(&self) -> bool {
        self.ptr.is_compact() && self.iter().all(|elem| elem.is_still_compact())
    }

    default fn dynamic_size_bytes(&self) -> usize {
        self.cap * ::std::mem::size_of::<T>() + self.iter().map(|elem| elem.dynamic_size_bytes()).sum::<usize>()
    }

    default unsafe fn compact_from(&mut self, source: &Self, new_dynamic_part: *mut u8) {
        self.cap = source.cap;
        self.len = source.len;
        self.ptr.set_to_compact(new_dynamic_part as *mut T);

        let mut offset = self.cap * ::std::mem::size_of::<T>();
        for i in 0..self.len {
            self[i].compact_from(&source[i], new_dynamic_part.offset(offset as isize));
            offset += self[i].dynamic_size_bytes();
        }
    }

    default unsafe fn decompact(&self) -> Self {
        if self.ptr.is_compact() {
            self.clone()
        } else {
            CompactVec{
                ptr: ptr::read(&self.ptr as *const PointerToMaybeCompact<T>),
                len: self.len,
                cap: self.cap,
                _alloc: self._alloc
            }
            // caller has to make sure that self will not be dropped!
        }
    }
}

impl<T: Copy, A: Allocator> Compact for CompactVec<T, A> {
    fn is_still_compact(&self) -> bool {
        self.ptr.is_compact()
    }

    fn dynamic_size_bytes(&self) -> usize {
        self.cap * ::std::mem::size_of::<T>()
    }

    unsafe fn compact_from(&mut self, source: &Self, new_dynamic_part: *mut u8) {
        self.cap = source.cap;
        self.len = source.len;
        self.ptr.set_to_compact(new_dynamic_part as *mut T);
        ptr::copy_nonoverlapping(source.ptr.ptr(), self.ptr.mut_ptr(), self.len);
    }
}

impl<T: Clone, A: Allocator> Clone for CompactVec<T, A> {
    default fn clone(&self) -> CompactVec<T, A> {
        self.iter().cloned().collect::<Vec<_>>().into()
    }
}

impl<T: Copy, A: Allocator> Clone for CompactVec<T, A> {
    fn clone(&self) -> CompactVec<T, A> {
        let mut new_vec = Self::with_capacity(self.cap);
        unsafe {
            ptr::copy_nonoverlapping(self.ptr.ptr(), new_vec.ptr.mut_ptr(), self.len);
        }
        new_vec.len = self.len;
        new_vec
    }
}

impl<T: Compact + Clone, A: Allocator> FromIterator<T> for CompactVec<T, A> {
    fn from_iter<I: IntoIterator<Item=T>>(iter: I) -> Self {
        let into_iter = iter.into_iter();
        let mut vec = CompactVec::with_capacity(into_iter.size_hint().0);
        for item in into_iter {
            vec.push(item);
        }
        vec
    }
}

impl<T: Compact + Clone, A: Allocator> Extend<T> for CompactVec<T, A> {
    fn extend<I: IntoIterator<Item=T>>(&mut self, iter: I) {
        for item in iter {
            self.push(item);
        }
    }
}

impl<T: Compact, A: Allocator> Default for CompactVec<T, A> {
    fn default() -> CompactVec<T, A> {
        CompactVec::new()
    }
}

impl<T: Compact + ::std::fmt::Debug, A: Allocator> ::std::fmt::Debug for CompactVec<T, A> {
    fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result {
        (self.deref()).fmt(f)
    }
}<|endoftext|>


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

use std::collections::BTreeMap;
use std::path::Path;
use std::path::PathBuf;
use std::vec::Vec;

use uuid::Uuid;

use engine::EngineError;
use engine::EngineResult;
use engine::ErrorEnum;
use engine::Pool;
use engine::Filesystem;
use engine::Dev;
use engine::RenameAction;

use super::blockdev::{BlockDev, initialize, resolve_devices};

use super::filesystem::StratFilesystem;

use super::consts::*;

#[derive(Debug)]
pub struct StratPool {
    pub name: String,
    pub pool_uuid: Uuid,
    pub cache_devs: BTreeMap<Uuid, BlockDev>,
    pub block_devs: BTreeMap<Uuid, BlockDev>,
    pub filesystems: BTreeMap<String, StratFilesystem>,
    pub raid_level: u16,
}

impl StratPool {
    pub fn new(name: &str,
               paths: &[&Path],
               raid_level: u16,
               force: bool)
               -> EngineResult<StratPool> {
        let devices = try!(resolve_devices(paths));
        let pool_uuid = Uuid::new_v4();
        let bds = try!(initialize(&pool_uuid, devices, MIN_MDA_SIZE, force));

        Ok(StratPool {
            name: name.to_owned(),
            pool_uuid: pool_uuid,
            cache_devs: BTreeMap::new(),
            block_devs: bds,
            filesystems: BTreeMap::new(),
            raid_level: raid_level,
        })
    }
}

impl Pool for StratPool {
    fn create_filesystems<'a, 'b, 'c>(&'a mut self,
                                      _specs: &[(&'b str, &'c str, Option<u64>)])
                                      -> EngineResult<Vec<&'b str>> {
        Ok(vec![])
    }

    fn create_snapshot<'a, 'b, 'c>(&'a mut self,
                                   _snapshot_name: &'b str,
                                   _source: &'c str)
                                   -> EngineResult<&'b str> {
        unimplemented!()
    }

    fn add_blockdevs(&mut self, paths: &[&Path], force: bool) -> EngineResult<Vec<PathBuf>> {
        let devices = try!(resolve_devices(paths));
        let mut bds = try!(initialize(&self.pool_uuid, devices, MIN_MDA_SIZE, force));
        let bdev_paths = bds.iter().map(|p| p.1.devnode.clone()).collect();
        self.block_devs.append(&mut bds);
        Ok(bdev_paths)
    }

    fn add_cachedevs(&mut self, paths: &[&Path], force: bool) -> EngineResult<Vec<PathBuf>> {
        let devices = try!(resolve_devices(paths));
        let mut bds = try!(initialize(&self.pool_uuid, devices, MIN_MDA_SIZE, force));
        let bdev_paths = bds.iter().map(|p| p.1.devnode.clone()).collect();
        self.cache_devs.append(&mut bds);
        Ok(bdev_paths)
    }

    fn destroy_filesystems<'a, 'b>(&'a mut self,
                                   fs_names: &[&'b str])
                                   -> EngineResult<Vec<&'b str>> {
        destroy_filesystems!{self; fs_names}
    }

    fn filesystems(&mut self) -> BTreeMap<&str, &mut Filesystem> {
        unimplemented!()
    }

    fn remove_blockdevs(&mut self, _paths: &[&Path]) -> EngineResult<Vec<PathBuf>> {
        unimplemented!()
    }

    fn remove_cachedevs(&mut self, _paths: &[&Path]) -> EngineResult<Vec<PathBuf>> {
        unimplemented!()
    }

    fn blockdevs(&mut self) -> Vec<&mut Dev> {
        unimplemented!()
    }

    fn cachedevs(&mut self) -> Vec<&mut Dev> {
        unimplemented!()
    }

    fn rename_filesystem(&mut self, old_name: &str, new_name: &str) -> EngineResult<RenameAction> {
        rename_filesystem!{self; old_name; new_name}
    }
}
<commit_msg>In real engine's Pool, use device nodes as keys in device maps.<commit_after>// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at http://mozilla.org/MPL/2.0/.

use std::collections::BTreeMap;
use std::path::Path;
use std::path::PathBuf;
use std::vec::Vec;

use uuid::Uuid;

use engine::EngineError;
use engine::EngineResult;
use engine::ErrorEnum;
use engine::Pool;
use engine::Filesystem;
use engine::Dev;
use engine::RenameAction;

use super::blockdev::{BlockDev, initialize, resolve_devices};

use super::filesystem::StratFilesystem;

use super::consts::*;

#[derive(Debug)]
pub struct StratPool {
    pub name: String,
    pub pool_uuid: Uuid,
    pub cache_devs: BTreeMap<PathBuf, BlockDev>,
    pub block_devs: BTreeMap<PathBuf, BlockDev>,
    pub filesystems: BTreeMap<String, StratFilesystem>,
    pub raid_level: u16,
}

impl StratPool {
    pub fn new(name: &str,
               paths: &[&Path],
               raid_level: u16,
               force: bool)
               -> EngineResult<StratPool> {
        let devices = try!(resolve_devices(paths));
        let pool_uuid = Uuid::new_v4();
        let bds = try!(initialize(&pool_uuid, devices, MIN_MDA_SIZE, force));

        Ok(StratPool {
            name: name.to_owned(),
            pool_uuid: pool_uuid,
            cache_devs: BTreeMap::new(),
            block_devs: bds,
            filesystems: BTreeMap::new(),
            raid_level: raid_level,
        })
    }
}

impl Pool for StratPool {
    fn create_filesystems<'a, 'b, 'c>(&'a mut self,
                                      _specs: &[(&'b str, &'c str, Option<u64>)])
                                      -> EngineResult<Vec<&'b str>> {
        Ok(vec![])
    }

    fn create_snapshot<'a, 'b, 'c>(&'a mut self,
                                   _snapshot_name: &'b str,
                                   _source: &'c str)
                                   -> EngineResult<&'b str> {
        unimplemented!()
    }

    fn add_blockdevs(&mut self, paths: &[&Path], force: bool) -> EngineResult<Vec<PathBuf>> {
        let devices = try!(resolve_devices(paths));
        let mut bds = try!(initialize(&self.pool_uuid, devices, MIN_MDA_SIZE, force));
        let bdev_paths = bds.iter().map(|p| p.1.devnode.clone()).collect();
        self.block_devs.append(&mut bds);
        Ok(bdev_paths)
    }

    fn add_cachedevs(&mut self, paths: &[&Path], force: bool) -> EngineResult<Vec<PathBuf>> {
        let devices = try!(resolve_devices(paths));
        let mut bds = try!(initialize(&self.pool_uuid, devices, MIN_MDA_SIZE, force));
        let bdev_paths = bds.iter().map(|p| p.1.devnode.clone()).collect();
        self.cache_devs.append(&mut bds);
        Ok(bdev_paths)
    }

    fn destroy_filesystems<'a, 'b>(&'a mut self,
                                   fs_names: &[&'b str])
                                   -> EngineResult<Vec<&'b str>> {
        destroy_filesystems!{self; fs_names}
    }

    fn filesystems(&mut self) -> BTreeMap<&str, &mut Filesystem> {
        unimplemented!()
    }

    fn remove_blockdevs(&mut self, _paths: &[&Path]) -> EngineResult<Vec<PathBuf>> {
        unimplemented!()
    }

    fn remove_cachedevs(&mut self, _paths: &[&Path]) -> EngineResult<Vec<PathBuf>> {
        unimplemented!()
    }

    fn blockdevs(&mut self) -> Vec<&mut Dev> {
        unimplemented!()
    }

    fn cachedevs(&mut self) -> Vec<&mut Dev> {
        unimplemented!()
    }

    fn rename_filesystem(&mut self, old_name: &str, new_name: &str) -> EngineResult<RenameAction> {
        rename_filesystem!{self; old_name; new_name}
    }
}
<|endoftext|>


<commit_before>extern crate bismuth;

use bismuth::LSystem;
use std::collections::HashMap;
use std::fs::File;
use std::io::prelude::*;

#[test]
fn test_lsystem_example() {
    // Integration test for example 7 on wiki page
    // https://en.wikipedia.org/wiki/L-system#Example_7:_Fractal_plant
    let mut lsys: LSystem = LSystem::new("X".to_string());
    lsys.add('F');
    lsys.add_constant('+');
    lsys.add_constant('-');
    lsys.add_constant('[');
    lsys.add_constant(']');
    let mut rule: HashMap<char, String> = HashMap::new();
    rule.insert('X', "F[−X][X]F[−X]+FX".to_string());
    rule.insert('F', "FF".to_string());
    lsys.push(rule);

    // Iterate 6 times
    for _ in 0..6 {
        lsys = lsys.next();
    }

    // Read solution file
    let mut file = File::open("tests/ex7sol.txt").unwrap();
    let mut soln = String::new();
    file.read_to_string(&mut soln).unwrap();
    assert_eq!(lsys.to_string(), soln);
}
<commit_msg>rustfmt lsystem tests<commit_after>extern crate bismuth;

use bismuth::LSystem;
use std::collections::HashMap;
use std::fs::File;
use std::io::prelude::*;

#[test]
fn test_lsystem_example() {
    // Integration test for example 7 on wiki page
    // https://en.wikipedia.org/wiki/L-system#Example_7:_Fractal_plant
    let mut lsys: LSystem = LSystem::new("X".to_string());
    lsys.add('F');
    lsys.add_constant('+');
    lsys.add_constant('-');
    lsys.add_constant('[');
    lsys.add_constant(']');
    let mut rule: HashMap<char, String> = HashMap::new();
    rule.insert('X', "F[−X][X]F[−X]+FX".to_string());
    rule.insert('F', "FF".to_string());
    lsys.push(rule);

    // Iterate 6 times
    for _ in 0..6 {
        lsys = lsys.next();
    }

    // Read solution file
    let mut file = File::open("tests/ex7sol.txt").unwrap();
    let mut soln = String::new();
    file.read_to_string(&mut soln).unwrap();
    assert_eq!(lsys.to_string(), soln);
}
<|endoftext|>


<commit_before>extern crate rosc;

#[cfg(feature = "std")]
use rosc::address::Matcher;

#[cfg(feature = "std")]
#[test]
fn test_matcher() {
    let mut matcher;

    // Regular address using only alphanumeric parts
    matcher = Matcher::new("/oscillator/1/frequency").expect("Should be valid");
    matcher.match_address("/oscillator/1/frequency").expect("Should match");
    matcher.match_address("/oscillator/1/phase").expect_err("Should not match");
    matcher.match_address("/oscillator/1/frequencyfoo").expect_err("Should not match");
    matcher.match_address("/prefix/oscillator/1/frequency").expect_err("Should not match");

    // Choice
    matcher = Matcher::new("/foo{bar,baz}").expect("Should be valid");
    matcher.match_address("/foobar").expect("Should match");
    matcher.match_address("/foobaz").expect("Should match");

    matcher = Matcher::new("/foo{bar,baz,tron}").expect("Should be valid");
    matcher.match_address("/footron").expect("Should match");

    // Character class
    // Character classes are sets or ranges of characters to match.
    // e.g. [a-z] will match any lower case alphabetic character. [abcd] will match the characters abcd.
    // They can be negated with '!', e.g. [!0-9] will match all characters except 0-9
    // Basic example
    matcher = Matcher::new("/oscillator/[0-9]").expect("Should be valid");
    matcher.match_address("/oscillator/0").expect("Should match");  // Beginning of range included
    matcher.match_address("/oscillator/6").expect("Should match");  // Middle of range
    matcher.match_address("/oscillator/9").expect("Should match");  // Last member of range included

    // Inverted order should work too
    matcher = Matcher::new("/oscillator/[9-0]").expect("Should be valid");
    matcher.match_address("/oscillator/0").expect("Should match");
    matcher.match_address("/oscillator/6").expect("Should match");
    matcher.match_address("/oscillator/9").expect("Should match");

    // Multiple ranges
    matcher = Matcher::new("/oscillator/[a-zA-Z0-9]").expect("Should be valid");
    matcher.match_address("/oscillator/0").expect("Should match");
    matcher.match_address("/oscillator/a").expect("Should match");
    matcher.match_address("/oscillator/A").expect("Should match");

    // Negated range
    matcher = Matcher::new("/oscillator/[!0-9]").expect("Should be valid");
    matcher.match_address("/oscillator/1").expect_err("Should not match");
    matcher.match_address("/oscillator/a").expect("Should match");

    // Extra exclamation points must be entirely ignored
    matcher = Matcher::new("/oscillator/[!0-9!a-z!]").expect("Should be valid");
    matcher.match_address("/oscillator/A").expect("Should match");

    // Trailing dash has no special meaning
    matcher = Matcher::new("/oscillator/[abcd-]").expect("Should be valid");
    matcher.match_address("/oscillator/a").expect("Should match");
    matcher.match_address("/oscillator/-").expect("Should match");

    // Single wildcard
    // A single wildcard '?' matches excatly one alphanumeric character
    matcher = Matcher::new("/oscillator/?/frequency").expect("Should be valid");
    matcher.match_address("/oscillator/1/frequency").expect("Should match");
    matcher.match_address("/oscillator/F/frequency").expect("Should match");
    matcher.match_address("/oscillator//frequency").expect_err("Should not match");
    matcher.match_address("/oscillator/10/frequency").expect_err("Should not match");

    // Test if two consecutive wildcards match
    matcher = Matcher::new("/oscillator/??/frequency").expect("Should be valid");
    matcher.match_address("/oscillator/10/frequency").expect("Should match");
    matcher.match_address("/oscillator/1/frequency").expect_err("Should not match");

    // Test if it works if it is surrounded by non-wildcards
    matcher = Matcher::new("/oscillator/prefixed?postfixed/frequency").expect("Should be valid");
    matcher.match_address("/oscillator/prefixed1postfixed/frequency").expect("Should match");
    matcher.match_address("/oscillator/prefixedpostfixed/frequency").expect_err("Should not match");

    // Wildcard
    // Wildcards '*' match zero or more alphanumeric characters. The implementation is greedy,
    // meaning it will match the longest possible sequence
    matcher = Matcher::new("/oscillator/*/frequency").expect("Should be valid");
    matcher.match_address("/oscillator/anything123/frequency").expect("Should match");
    // Test that wildcard doesn't cross part boundary
    matcher.match_address("/oscillator/extra/part/frequency").expect_err("Should not match");
    matcher.match_address("/oscillator//frequency").expect_err("Should not match");

    // Test greediness
    matcher = Matcher::new("/oscillator/*bar/frequency").expect("Should be valid");
    matcher.match_address("/oscillator/foobar/frequency").expect("Should match");
    matcher.match_address("/oscillator/foobarbar/frequency").expect("Should match");

    // Minimum length of 2
    matcher = Matcher::new("/oscillator/*??/frequency").expect("Should be valid");
    matcher.match_address("/oscillator/foobar/frequency").expect("Should match");
    matcher.match_address("/oscillator/f/frequency").expect_err("Should not match");

    // Minimum length of 2 and another component follows
    matcher = Matcher::new("/oscillator/*??baz/frequency").expect("Should be valid");
    matcher.match_address("/oscillator/foobarbaz/frequency").expect("Should match");
    matcher.match_address("/oscillator/fbaz/frequency").expect_err("Should not match");

    // Mix with character class
    matcher = Matcher::new("/oscillator/*[a-d]/frequency").expect("Should be valid");
    matcher.match_address("/oscillator/a/frequency").expect("Should match");
    matcher.match_address("/oscillator/fooa/frequency").expect("Should match");
    matcher.match_address("/oscillator/foox/frequency").expect_err("Should not match");

    // Mix with choice
    matcher = Matcher::new("/oscillator/*{bar,baz}/frequency").expect("Should be valid");
    matcher.match_address("/oscillator/foobar/frequency").expect("Should match");
    matcher.match_address("/oscillator/baz/frequency").expect("Should match");
    matcher.match_address("/oscillator/something/frequency").expect_err("Should not match");

    // Check for allowed literal characters
    matcher = Matcher::new("/!\"$%&'()+-.0123456789:;<=>@ABCDEFGHIJKLMNOPQRSTUVWXYZ^_`abcdefghijklmnopqrstuvwxyz|~").expect("Should be valid");
    matcher.match_address("/!\"$%&'()+-.0123456789:;<=>@ABCDEFGHIJKLMNOPQRSTUVWXYZ^_`abcdefghijklmnopqrstuvwxyz|~").expect("Should match");
}

#[cfg(feature = "std")]
#[test]
fn test_bad_address_pattern() {
    let expected_err = "bad OSC address pattern: bad address pattern";
    assert_eq!(Matcher::new("").unwrap_err().to_string(), expected_err);
    assert_eq!(Matcher::new("/").unwrap_err().to_string(), expected_err);
    assert_eq!(Matcher::new("//empty/parts/").unwrap_err().to_string(), expected_err);
    assert_eq!(Matcher::new("////").unwrap_err().to_string(), expected_err);
    assert_eq!(Matcher::new("/{unclosed,alternative").unwrap_err().to_string(), expected_err);
    assert_eq!(Matcher::new("/unclosed/[range-").unwrap_err().to_string(), expected_err);
}

#[cfg(feature = "std")]
#[test]
fn test_bad_address() {
    let matcher = Matcher::new("/does-not-matter").expect("Matcher::new");
    let expected_err = "bad OSC address: bad address";
    assert_eq!(matcher.match_address("").unwrap_err().to_string(), expected_err);
    assert_eq!(matcher.match_address("/").unwrap_err().to_string(), expected_err);
    assert_eq!(matcher.match_address("/contains/wildcards?").unwrap_err().to_string(), expected_err);
    assert_eq!(matcher.match_address("/contains/wildcards*").unwrap_err().to_string(), expected_err);
    assert_eq!(matcher.match_address("/contains/ranges[a-z]").unwrap_err().to_string(), expected_err);
    assert_eq!(matcher.match_address("/contains/ranges[!a-z]").unwrap_err().to_string(), expected_err);
    assert_eq!(matcher.match_address("/{contains,alternative}").unwrap_err().to_string(), expected_err);
}
<commit_msg>Test if wildcard matches all legal characters<commit_after>extern crate rosc;

#[cfg(feature = "std")]
use rosc::address::Matcher;

#[cfg(feature = "std")]
#[test]
fn test_matcher() {
    let mut matcher;

    // Regular address using only alphanumeric parts
    matcher = Matcher::new("/oscillator/1/frequency").expect("Should be valid");
    matcher.match_address("/oscillator/1/frequency").expect("Should match");
    matcher.match_address("/oscillator/1/phase").expect_err("Should not match");
    matcher.match_address("/oscillator/1/frequencyfoo").expect_err("Should not match");
    matcher.match_address("/prefix/oscillator/1/frequency").expect_err("Should not match");

    // Choice
    matcher = Matcher::new("/foo{bar,baz}").expect("Should be valid");
    matcher.match_address("/foobar").expect("Should match");
    matcher.match_address("/foobaz").expect("Should match");

    matcher = Matcher::new("/foo{bar,baz,tron}").expect("Should be valid");
    matcher.match_address("/footron").expect("Should match");

    // Character class
    // Character classes are sets or ranges of characters to match.
    // e.g. [a-z] will match any lower case alphabetic character. [abcd] will match the characters abcd.
    // They can be negated with '!', e.g. [!0-9] will match all characters except 0-9
    // Basic example
    matcher = Matcher::new("/oscillator/[0-9]").expect("Should be valid");
    matcher.match_address("/oscillator/0").expect("Should match");  // Beginning of range included
    matcher.match_address("/oscillator/6").expect("Should match");  // Middle of range
    matcher.match_address("/oscillator/9").expect("Should match");  // Last member of range included

    // Inverted order should work too
    matcher = Matcher::new("/oscillator/[9-0]").expect("Should be valid");
    matcher.match_address("/oscillator/0").expect("Should match");
    matcher.match_address("/oscillator/6").expect("Should match");
    matcher.match_address("/oscillator/9").expect("Should match");

    // Multiple ranges
    matcher = Matcher::new("/oscillator/[a-zA-Z0-9]").expect("Should be valid");
    matcher.match_address("/oscillator/0").expect("Should match");
    matcher.match_address("/oscillator/a").expect("Should match");
    matcher.match_address("/oscillator/A").expect("Should match");

    // Negated range
    matcher = Matcher::new("/oscillator/[!0-9]").expect("Should be valid");
    matcher.match_address("/oscillator/1").expect_err("Should not match");
    matcher.match_address("/oscillator/a").expect("Should match");

    // Extra exclamation points must be entirely ignored
    matcher = Matcher::new("/oscillator/[!0-9!a-z!]").expect("Should be valid");
    matcher.match_address("/oscillator/A").expect("Should match");

    // Trailing dash has no special meaning
    matcher = Matcher::new("/oscillator/[abcd-]").expect("Should be valid");
    matcher.match_address("/oscillator/a").expect("Should match");
    matcher.match_address("/oscillator/-").expect("Should match");

    // Single wildcard
    // A single wildcard '?' matches excatly one alphanumeric character
    matcher = Matcher::new("/oscillator/?/frequency").expect("Should be valid");
    matcher.match_address("/oscillator/1/frequency").expect("Should match");
    matcher.match_address("/oscillator/F/frequency").expect("Should match");
    matcher.match_address("/oscillator//frequency").expect_err("Should not match");
    matcher.match_address("/oscillator/10/frequency").expect_err("Should not match");

    // Test if two consecutive wildcards match
    matcher = Matcher::new("/oscillator/??/frequency").expect("Should be valid");
    matcher.match_address("/oscillator/10/frequency").expect("Should match");
    matcher.match_address("/oscillator/1/frequency").expect_err("Should not match");

    // Test if it works if it is surrounded by non-wildcards
    matcher = Matcher::new("/oscillator/prefixed?postfixed/frequency").expect("Should be valid");
    matcher.match_address("/oscillator/prefixed1postfixed/frequency").expect("Should match");
    matcher.match_address("/oscillator/prefixedpostfixed/frequency").expect_err("Should not match");

    // Wildcard
    // Wildcards '*' match zero or more alphanumeric characters. The implementation is greedy,
    // meaning it will match the longest possible sequence
    matcher = Matcher::new("/oscillator/*/frequency").expect("Should be valid");
    matcher.match_address("/oscillator/anything123/frequency").expect("Should match");
    matcher.match_address("/oscillator/!\"$%&'()+-.0123456789:;<=>@ABCDEFGHIJKLMNOPQRSTUVWXYZ^_`abcdefghijklmnopqrstuvwxyz|~/frequency").expect("Should match");
    // Test that wildcard doesn't cross part boundary
    matcher.match_address("/oscillator/extra/part/frequency").expect_err("Should not match");
    matcher.match_address("/oscillator//frequency").expect_err("Should not match");

    // Test greediness
    matcher = Matcher::new("/oscillator/*bar/frequency").expect("Should be valid");
    matcher.match_address("/oscillator/foobar/frequency").expect("Should match");
    matcher.match_address("/oscillator/foobarbar/frequency").expect("Should match");

    // Minimum length of 2
    matcher = Matcher::new("/oscillator/*??/frequency").expect("Should be valid");
    matcher.match_address("/oscillator/foobar/frequency").expect("Should match");
    matcher.match_address("/oscillator/f/frequency").expect_err("Should not match");

    // Minimum length of 2 and another component follows
    matcher = Matcher::new("/oscillator/*??baz/frequency").expect("Should be valid");
    matcher.match_address("/oscillator/foobarbaz/frequency").expect("Should match");
    matcher.match_address("/oscillator/fbaz/frequency").expect_err("Should not match");

    // Mix with character class
    matcher = Matcher::new("/oscillator/*[a-d]/frequency").expect("Should be valid");
    matcher.match_address("/oscillator/a/frequency").expect("Should match");
    matcher.match_address("/oscillator/fooa/frequency").expect("Should match");
    matcher.match_address("/oscillator/foox/frequency").expect_err("Should not match");

    // Mix with choice
    matcher = Matcher::new("/oscillator/*{bar,baz}/frequency").expect("Should be valid");
    matcher.match_address("/oscillator/foobar/frequency").expect("Should match");
    matcher.match_address("/oscillator/baz/frequency").expect("Should match");
    matcher.match_address("/oscillator/something/frequency").expect_err("Should not match");

    // Check for allowed literal characters
    matcher = Matcher::new("/!\"$%&'()+-.0123456789:;<=>@ABCDEFGHIJKLMNOPQRSTUVWXYZ^_`abcdefghijklmnopqrstuvwxyz|~").expect("Should be valid");
    matcher.match_address("/!\"$%&'()+-.0123456789:;<=>@ABCDEFGHIJKLMNOPQRSTUVWXYZ^_`abcdefghijklmnopqrstuvwxyz|~").expect("Should match");
}

#[cfg(feature = "std")]
#[test]
fn test_bad_address_pattern() {
    let expected_err = "bad OSC address pattern: bad address pattern";
    assert_eq!(Matcher::new("").unwrap_err().to_string(), expected_err);
    assert_eq!(Matcher::new("/").unwrap_err().to_string(), expected_err);
    assert_eq!(Matcher::new("//empty/parts/").unwrap_err().to_string(), expected_err);
    assert_eq!(Matcher::new("////").unwrap_err().to_string(), expected_err);
    assert_eq!(Matcher::new("/{unclosed,alternative").unwrap_err().to_string(), expected_err);
    assert_eq!(Matcher::new("/unclosed/[range-").unwrap_err().to_string(), expected_err);
}

#[cfg(feature = "std")]
#[test]
fn test_bad_address() {
    let matcher = Matcher::new("/does-not-matter").expect("Matcher::new");
    let expected_err = "bad OSC address: bad address";
    assert_eq!(matcher.match_address("").unwrap_err().to_string(), expected_err);
    assert_eq!(matcher.match_address("/").unwrap_err().to_string(), expected_err);
    assert_eq!(matcher.match_address("/contains/wildcards?").unwrap_err().to_string(), expected_err);
    assert_eq!(matcher.match_address("/contains/wildcards*").unwrap_err().to_string(), expected_err);
    assert_eq!(matcher.match_address("/contains/ranges[a-z]").unwrap_err().to_string(), expected_err);
    assert_eq!(matcher.match_address("/contains/ranges[!a-z]").unwrap_err().to_string(), expected_err);
    assert_eq!(matcher.match_address("/{contains,alternative}").unwrap_err().to_string(), expected_err);
}
<|endoftext|>


<commit_before>// Copyright 2018 Guillaume Pinot (@TeXitoi) <texitoi@texitoi.eu>,
// Kevin Knapp (@kbknapp) <kbknapp@gmail.com>, and
// Ana Hobden (@hoverbear) <operator@hoverbear.org>
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
//
// This work was derived from Structopt (https://github.com/TeXitoi/structopt)
// commit#ea76fa1b1b273e65e3b0b1046643715b49bec51f which is licensed under the
// MIT/Apache 2.0 license.

use clap::Parser;

#[test]
fn bool_type_is_flag() {
    #[derive(Parser, PartialEq, Debug)]
    struct Opt {
        #[clap(short, long)]
        alice: bool,
    }

    assert_eq!(
        Opt { alice: false },
        Opt::try_parse_from(&["test"]).unwrap()
    );
    assert_eq!(
        Opt { alice: true },
        Opt::try_parse_from(&["test", "-a"]).unwrap()
    );
    assert_eq!(
        Opt { alice: true },
        Opt::try_parse_from(&["test", "-a", "-a"]).unwrap()
    );
    assert_eq!(
        Opt { alice: true },
        Opt::try_parse_from(&["test", "--alice"]).unwrap()
    );
    assert!(Opt::try_parse_from(&["test", "-i"]).is_err());
    assert!(Opt::try_parse_from(&["test", "-a", "foo"]).is_err());
}

#[test]
fn count() {
    #[derive(Parser, PartialEq, Debug)]
    struct Opt {
        #[clap(short, long, action = clap::ArgAction::Count)]
        alice: u8,
        #[clap(short, long, action = clap::ArgAction::Count)]
        bob: u8,
    }

    assert_eq!(
        Opt { alice: 0, bob: 0 },
        Opt::try_parse_from(&["test"]).unwrap()
    );
    assert_eq!(
        Opt { alice: 1, bob: 0 },
        Opt::try_parse_from(&["test", "-a"]).unwrap()
    );
    assert_eq!(
        Opt { alice: 2, bob: 0 },
        Opt::try_parse_from(&["test", "-a", "-a"]).unwrap()
    );
    assert_eq!(
        Opt { alice: 2, bob: 2 },
        Opt::try_parse_from(&["test", "-a", "--alice", "-bb"]).unwrap()
    );
    assert_eq!(
        Opt { alice: 3, bob: 1 },
        Opt::try_parse_from(&["test", "-aaa", "--bob"]).unwrap()
    );
    assert!(Opt::try_parse_from(&["test", "-i"]).is_err());
    assert!(Opt::try_parse_from(&["test", "-a", "foo"]).is_err());
}

#[test]
fn mixed_type_flags() {
    #[derive(Parser, PartialEq, Debug)]
    struct Opt {
        #[clap(short, long)]
        alice: bool,
        #[clap(short, long, action = clap::ArgAction::Count)]
        bob: u8,
    }

    assert_eq!(
        Opt {
            alice: false,
            bob: 0
        },
        Opt::try_parse_from(&["test"]).unwrap()
    );
    assert_eq!(
        Opt {
            alice: true,
            bob: 0
        },
        Opt::try_parse_from(&["test", "-a"]).unwrap()
    );
    assert_eq!(
        Opt {
            alice: true,
            bob: 0
        },
        Opt::try_parse_from(&["test", "-a"]).unwrap()
    );
    assert_eq!(
        Opt {
            alice: false,
            bob: 1
        },
        Opt::try_parse_from(&["test", "-b"]).unwrap()
    );
    assert_eq!(
        Opt {
            alice: true,
            bob: 1
        },
        Opt::try_parse_from(&["test", "--alice", "--bob"]).unwrap()
    );
    assert_eq!(
        Opt {
            alice: true,
            bob: 4
        },
        Opt::try_parse_from(&["test", "-bb", "-a", "-bb"]).unwrap()
    );
}

#[test]
fn ignore_qualified_bool_type() {
    mod inner {
        #[allow(non_camel_case_types)]
        #[derive(PartialEq, Debug, Clone)]
        pub struct bool(pub String);

        impl std::str::FromStr for self::bool {
            type Err = String;

            fn from_str(s: &str) -> Result<Self, Self::Err> {
                Ok(self::bool(s.into()))
            }
        }
    }

    #[derive(Parser, PartialEq, Debug)]
    struct Opt {
        arg: inner::bool,
    }

    assert_eq!(
        Opt {
            arg: inner::bool("success".into())
        },
        Opt::try_parse_from(&["test", "success"]).unwrap()
    );
}

#[test]
fn override_implicit_action() {
    #[derive(Parser, PartialEq, Debug)]
    struct Opt {
        #[clap(long, action = clap::ArgAction::Set)]
        arg: bool,
    }

    assert_eq!(
        Opt { arg: false },
        Opt::try_parse_from(&["test", "--arg", "false"]).unwrap()
    );

    assert_eq!(
        Opt { arg: true },
        Opt::try_parse_from(&["test", "--arg", "true"]).unwrap()
    );
}

#[test]
fn override_implicit_from_flag_positional() {
    #[derive(Parser, PartialEq, Debug)]
    struct Opt {
        #[clap(action = clap::ArgAction::Set)]
        arg: bool,
    }

    assert_eq!(
        Opt { arg: false },
        Opt::try_parse_from(&["test", "false"]).unwrap()
    );

    assert_eq!(
        Opt { arg: true },
        Opt::try_parse_from(&["test", "true"]).unwrap()
    );
}
<commit_msg>test(derive): Highlight current behavior for version/help<commit_after>// Copyright 2018 Guillaume Pinot (@TeXitoi) <texitoi@texitoi.eu>,
// Kevin Knapp (@kbknapp) <kbknapp@gmail.com>, and
// Ana Hobden (@hoverbear) <operator@hoverbear.org>
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
//
// This work was derived from Structopt (https://github.com/TeXitoi/structopt)
// commit#ea76fa1b1b273e65e3b0b1046643715b49bec51f which is licensed under the
// MIT/Apache 2.0 license.

use clap::CommandFactory;
use clap::Parser;

#[test]
fn bool_type_is_flag() {
    #[derive(Parser, PartialEq, Debug)]
    struct Opt {
        #[clap(short, long)]
        alice: bool,
    }

    assert_eq!(
        Opt { alice: false },
        Opt::try_parse_from(&["test"]).unwrap()
    );
    assert_eq!(
        Opt { alice: true },
        Opt::try_parse_from(&["test", "-a"]).unwrap()
    );
    assert_eq!(
        Opt { alice: true },
        Opt::try_parse_from(&["test", "-a", "-a"]).unwrap()
    );
    assert_eq!(
        Opt { alice: true },
        Opt::try_parse_from(&["test", "--alice"]).unwrap()
    );
    assert!(Opt::try_parse_from(&["test", "-i"]).is_err());
    assert!(Opt::try_parse_from(&["test", "-a", "foo"]).is_err());
}

#[test]
#[ignore] // Not a good path for supporting this atm
fn inferred_help() {
    #[derive(Parser, PartialEq, Debug)]
    struct Opt {
        /// Foo
        #[clap(short, long)]
        help: bool,
    }

    let mut cmd = Opt::command();
    cmd.build();
    let arg = cmd.get_arguments().find(|a| a.get_id() == "help").unwrap();
    assert_eq!(arg.get_help(), Some("Foo"), "Incorrect help");
    assert!(matches!(arg.get_action(), clap::ArgAction::Help));
}

#[test]
#[ignore] // Not a good path for supporting this atm
fn inferred_version() {
    #[derive(Parser, PartialEq, Debug)]
    struct Opt {
        /// Foo
        #[clap(short, long)]
        version: bool,
    }

    let mut cmd = Opt::command();
    cmd.build();
    let arg = cmd
        .get_arguments()
        .find(|a| a.get_id() == "version")
        .unwrap();
    assert_eq!(arg.get_help(), Some("Foo"), "Incorrect help");
    assert!(matches!(arg.get_action(), clap::ArgAction::Version));
}

#[test]
fn count() {
    #[derive(Parser, PartialEq, Debug)]
    struct Opt {
        #[clap(short, long, action = clap::ArgAction::Count)]
        alice: u8,
        #[clap(short, long, action = clap::ArgAction::Count)]
        bob: u8,
    }

    assert_eq!(
        Opt { alice: 0, bob: 0 },
        Opt::try_parse_from(&["test"]).unwrap()
    );
    assert_eq!(
        Opt { alice: 1, bob: 0 },
        Opt::try_parse_from(&["test", "-a"]).unwrap()
    );
    assert_eq!(
        Opt { alice: 2, bob: 0 },
        Opt::try_parse_from(&["test", "-a", "-a"]).unwrap()
    );
    assert_eq!(
        Opt { alice: 2, bob: 2 },
        Opt::try_parse_from(&["test", "-a", "--alice", "-bb"]).unwrap()
    );
    assert_eq!(
        Opt { alice: 3, bob: 1 },
        Opt::try_parse_from(&["test", "-aaa", "--bob"]).unwrap()
    );
    assert!(Opt::try_parse_from(&["test", "-i"]).is_err());
    assert!(Opt::try_parse_from(&["test", "-a", "foo"]).is_err());
}

#[test]
fn mixed_type_flags() {
    #[derive(Parser, PartialEq, Debug)]
    struct Opt {
        #[clap(short, long)]
        alice: bool,
        #[clap(short, long, action = clap::ArgAction::Count)]
        bob: u8,
    }

    assert_eq!(
        Opt {
            alice: false,
            bob: 0
        },
        Opt::try_parse_from(&["test"]).unwrap()
    );
    assert_eq!(
        Opt {
            alice: true,
            bob: 0
        },
        Opt::try_parse_from(&["test", "-a"]).unwrap()
    );
    assert_eq!(
        Opt {
            alice: true,
            bob: 0
        },
        Opt::try_parse_from(&["test", "-a"]).unwrap()
    );
    assert_eq!(
        Opt {
            alice: false,
            bob: 1
        },
        Opt::try_parse_from(&["test", "-b"]).unwrap()
    );
    assert_eq!(
        Opt {
            alice: true,
            bob: 1
        },
        Opt::try_parse_from(&["test", "--alice", "--bob"]).unwrap()
    );
    assert_eq!(
        Opt {
            alice: true,
            bob: 4
        },
        Opt::try_parse_from(&["test", "-bb", "-a", "-bb"]).unwrap()
    );
}

#[test]
fn ignore_qualified_bool_type() {
    mod inner {
        #[allow(non_camel_case_types)]
        #[derive(PartialEq, Debug, Clone)]
        pub struct bool(pub String);

        impl std::str::FromStr for self::bool {
            type Err = String;

            fn from_str(s: &str) -> Result<Self, Self::Err> {
                Ok(self::bool(s.into()))
            }
        }
    }

    #[derive(Parser, PartialEq, Debug)]
    struct Opt {
        arg: inner::bool,
    }

    assert_eq!(
        Opt {
            arg: inner::bool("success".into())
        },
        Opt::try_parse_from(&["test", "success"]).unwrap()
    );
}

#[test]
fn override_implicit_action() {
    #[derive(Parser, PartialEq, Debug)]
    struct Opt {
        #[clap(long, action = clap::ArgAction::Set)]
        arg: bool,
    }

    assert_eq!(
        Opt { arg: false },
        Opt::try_parse_from(&["test", "--arg", "false"]).unwrap()
    );

    assert_eq!(
        Opt { arg: true },
        Opt::try_parse_from(&["test", "--arg", "true"]).unwrap()
    );
}

#[test]
fn override_implicit_from_flag_positional() {
    #[derive(Parser, PartialEq, Debug)]
    struct Opt {
        #[clap(action = clap::ArgAction::Set)]
        arg: bool,
    }

    assert_eq!(
        Opt { arg: false },
        Opt::try_parse_from(&["test", "false"]).unwrap()
    );

    assert_eq!(
        Opt { arg: true },
        Opt::try_parse_from(&["test", "true"]).unwrap()
    );
}
<|endoftext|>


<commit_before>use std::io::{Read, Result};

use super::event::{self, Event, Key};

pub struct Events<R> {
    source: R,
    leftover: Option<u8>
}

impl<R: Read> Events<R> {
    pub fn new(source: R) -> Events<R> {
        Events {
            source: source,
            leftover: None
        }
    }
}

impl<R: Read> Iterator for Events<R> {
    type Item = Result<Event>;

    fn next(&mut self) -> Option<Result<Event>> {
        let mut source = &mut self.source;

        let mut buf = [0u8; 2];

        let result = match source.read(&mut buf) {
            Ok(0) => return None,
            Ok(1) => {
                match buf[0] {
                    b'\x1b' => Ok(Event::Key(Key::Escape)),
                    item => parse_event(item, &mut source.bytes())
                }
            },
            Ok(2) => {
                let mut option_iter = &mut Some(buf[1]).into_iter();

                let result = {
                    let mut iter = option_iter.
                        map(Ok).
                        chain(source.bytes());

                    parse_event(buf[0], &mut iter)
                };

                // If the option_iter wasn't consumed, keep the byte for later.
                self.leftover = option_iter.next();
                result
            },
            Ok(_) => unreachable!(),
            Err(e) => Err(e)
        };

        Some(result)
    }
}

fn parse_event<I>(item: u8, iter: &mut I) -> Result<Event>
    where I: Iterator<Item = Result<u8>>
{
    let mut buf = vec![item];
    let result = {
        let mut iter = iter.inspect(|byte| {
            if let Ok(byte) = *byte {
                buf.push(byte);
            }
        });
        event::parse_event(item, &mut iter)
    };
    result.or_else(|_| Ok(Event::Unknown(buf)))
}
<commit_msg>Actually parse using leftover byte<commit_after>use std::io::{Read, Result};

use super::event::{self, Event, Key};

pub struct Events<R> {
    source: R,
    leftover: Option<u8>
}

impl<R: Read> Events<R> {
    pub fn new(source: R) -> Events<R> {
        Events {
            source: source,
            leftover: None
        }
    }
}

impl<R: Read> Iterator for Events<R> {
    type Item = Result<Event>;

    fn next(&mut self) -> Option<Result<Event>> {
        let mut source = &mut self.source;

        if let Some(c) = self.leftover {
            // we have a leftover byte, use it
            self.leftover = None;
            return Some(parse_event(c, &mut source.bytes()));
        }

        let mut buf = [0u8; 2];

        let result = match source.read(&mut buf) {
            Ok(0) => return None,
            Ok(1) => {
                match buf[0] {
                    b'\x1b' => Ok(Event::Key(Key::Escape)),
                    item => parse_event(item, &mut source.bytes())
                }
            },
            Ok(2) => {
                let mut option_iter = &mut Some(buf[1]).into_iter();

                let result = {
                    let mut iter = option_iter.
                        map(Ok).
                        chain(source.bytes());

                    parse_event(buf[0], &mut iter)
                };

                // If the option_iter wasn't consumed, keep the byte for later.
                self.leftover = option_iter.next();
                result
            },
            Ok(_) => unreachable!(),
            Err(e) => Err(e)
        };

        Some(result)
    }
}

fn parse_event<I>(item: u8, iter: &mut I) -> Result<Event>
    where I: Iterator<Item = Result<u8>>
{
    let mut buf = vec![item];
    let result = {
        let mut iter = iter.inspect(|byte| {
            if let Ok(byte) = *byte {
                buf.push(byte);
            }
        });
        event::parse_event(item, &mut iter)
    };
    result.or_else(|_| Ok(Event::Unknown(buf)))
}
<|endoftext|>