<commit_before>use domination::DominationOrd;
use std::cmp::Ordering;
use std::mem;
use std::collections::VecDeque;

struct Entry<'a, S, I = usize>
where
    S: 'a,
{
    /// A reference to the solution
    solution: &'a S,

    /// The index that `solution` has within the `solutions` array.
    index: I,

    /// By how many other solutions is this solution dominated
    domination_count: I,

    /// Which solutions we dominate
    dominated_solutions: VecDeque<I>,
}

pub struct NonDominatedSorter<'a, S, I = usize>
where
    S: 'a,
{
    entries: Vec<Entry<'a, S, I>>,
    current_front: Vec<(I, &'a S)>,
}

impl<'a, S> NonDominatedSorter<'a, S> {
    /// Perform a non-dominated sort of `solutions`.
    ///
    /// Each pareto front (the indices of the `solutions`) can be obtained by calling `next()`.

    pub fn new<D>(solutions: &'a [S], domination: &D) -> Self
    where
        D: DominationOrd<Solution = S>,
    {
        let mut current_front = Vec::new();

        let mut entries: Vec<_> = solutions
            .iter()
            .enumerate()
            .map(|(index, solution)| Entry {
                solution,
                index,
                domination_count: 0,
                dominated_solutions: VecDeque::new(),
            })
            .collect();

        for mid in 1..entries.len() + 1 {
            let (front_slice, tail_slice) = entries.split_at_mut(mid);
            debug_assert!(front_slice.len() > 0);
            let p = front_slice.last_mut().unwrap();
            for q in tail_slice.iter_mut() {
                match domination.domination_ord(p.solution, q.solution) {
                    Ordering::Less => {
                        // p dominates q
                        // Add `q` to the set of solutions dominated by `p`.
                        p.dominated_solutions.push_back(q.index);
                        // q is dominated by p
                        q.domination_count += 1;
                    }
                    Ordering::Greater => {
                        // p is dominated by q
                        // Add `p` to the set of solutions dominated by `q`.
                        q.dominated_solutions.push_back(p.index);
                        // q dominates p
                        // Increment domination counter of `p`.
                        p.domination_count += 1;
                    }
                    Ordering::Equal => {}
                }
            }
            if p.domination_count == 0 {
                // `p` belongs to the first front as it is not dominated by any
                // other solution.
                current_front.push((p.index, p.solution));
            }
        }

        Self {
            entries,
            current_front,
        }
    }

    // Returns an iterator that yields all pareto fronts
    // pub fn pareto_front_iter()
}

/// Iterate over the pareto fronts. Each call to next() will yield the
/// next pareto front.
impl<'a, S> Iterator for NonDominatedSorter<'a, S> {
    type Item = Vec<(usize, &'a S)>;

    /// Return the next pareto front

    fn next(&mut self) -> Option<Self::Item> {
        if self.current_front.is_empty() {
            return None;
        }

        // Calculate the next front

        let mut next_front = Vec::new();
        for &(p_i, _) in self.current_front.iter() {
            // to calculate the next front, we have to remove the
            // solutions of the current front, and as such, decrease the
            // domination_count of they dominated_solutions. We can
            // destruct the dominated_solutions array here, as we will
            // no longer need it.
            // The only problem with poping off solutions off the end is
            // that we will populate the fronts in reverse order. For
            // that reason, we are using a VecDeque. This should give us
            // a stable sort.

            while let Some(q_i) = self.entries[p_i].dominated_solutions.pop_front() {
                let q = &mut self.entries[q_i];
                debug_assert!(q.domination_count > 0);
                q.domination_count -= 1;
                if q.domination_count == 0 {
                    // q is not dominated by any other solution. it belongs to the next front.
                    next_front.push((q_i, q.solution));
                }
            }
        }

        // and return the current front, swapping it with the next

        let current_front = mem::replace(&mut self.current_front, next_front);

        return Some(current_front);
    }
}

pub fn non_dominated_sort<'a, S, D>(
    solutions: &'a [S],
    domination: &D,
    cap_fronts_at: usize,
) -> Vec<Vec<(usize, &'a S)>>
where
    D: DominationOrd<Solution = S>,
{
    let sorter = NonDominatedSorter::new(solutions, domination);
    let mut found_solutions: usize = 0;
    let mut fronts = Vec::new();

    for front in sorter {
        found_solutions += front.len();
        fronts.push(front);
        if found_solutions >= cap_fronts_at {
            break;
        }
    }
    return fronts;
}

#[cfg(test)]
mod helper {
    use test_helper_domination::Tuple;
    pub fn get_solutions() -> Vec<Tuple> {
        vec![
            Tuple(1, 2),
            Tuple(1, 2),
            Tuple(2, 1),
            Tuple(1, 3),
            Tuple(0, 2),
        ]
    }
    pub fn keep_only_index(front: &[(usize, &Tuple)]) -> Vec<usize> {
        front.iter().map(|&(i, _)| i).collect()
    }

    pub fn assert_front_eq(expected: &[usize], front: &[(usize, &Tuple)]) {
        assert_eq!(expected.to_owned(), keep_only_index(front));
    }
}

#[test]
fn test_non_dominated_sort() {
    use test_helper_domination::TupleDominationOrd;
    let solutions = helper::get_solutions();
    let fronts = non_dominated_sort(&solutions, &TupleDominationOrd, solutions.len());

    assert_eq!(3, fronts.len());
    helper::assert_front_eq(&[2, 4], &fronts[0]);
    helper::assert_front_eq(&[0, 1], &fronts[1]);
    helper::assert_front_eq(&[3], &fronts[2]);
}

#[test]
fn test_non_dominated_sort_iter() {
    use test_helper_domination::TupleDominationOrd;
    let solutions = helper::get_solutions();
    let mut fronts = NonDominatedSorter::new(&solutions, &TupleDominationOrd);
    let f = &|front: Vec<_>| helper::keep_only_index(&front);

    assert_eq!(Some(vec![2, 4]), fronts.next().map(f));
    assert_eq!(Some(vec![0, 1]), fronts.next().map(f));
    assert_eq!(Some(vec![3]), fronts.next().map(f));
    assert_eq!(None, fronts.next().map(f));
}
<commit_msg>Remove non_dominated_sort function. Incoorporate into NonDominatedSorter#pareto_front()<commit_after>use domination::DominationOrd;
use std::cmp::Ordering;
use std::mem;
use std::collections::VecDeque;

struct Entry<'a, S, I = usize>
where
    S: 'a,
{
    /// A reference to the solution
    solution: &'a S,

    /// The index that `solution` has within the `solutions` array.
    index: I,

    /// By how many other solutions is this solution dominated
    domination_count: I,

    /// Which solutions we dominate
    dominated_solutions: VecDeque<I>,
}

pub struct NonDominatedSorter<'a, S, I = usize>
where
    S: 'a,
{
    entries: Vec<Entry<'a, S, I>>,
    current_front: Vec<(I, &'a S)>,
}

impl<'a, S> NonDominatedSorter<'a, S> {
    /// Perform a non-dominated sort of `solutions`.
    ///
    /// Each pareto front (the indices of the `solutions`) can be obtained by calling `next()`.

    pub fn new<D>(solutions: &'a [S], domination: &D) -> Self
    where
        D: DominationOrd<Solution = S>,
    {
        let mut current_front = Vec::new();

        let mut entries: Vec<_> = solutions
            .iter()
            .enumerate()
            .map(|(index, solution)| Entry {
                solution,
                index,
                domination_count: 0,
                dominated_solutions: VecDeque::new(),
            })
            .collect();

        for mid in 1..entries.len() + 1 {
            let (front_slice, tail_slice) = entries.split_at_mut(mid);
            debug_assert!(front_slice.len() > 0);
            let p = front_slice.last_mut().unwrap();
            for q in tail_slice.iter_mut() {
                match domination.domination_ord(p.solution, q.solution) {
                    Ordering::Less => {
                        // p dominates q
                        // Add `q` to the set of solutions dominated by `p`.
                        p.dominated_solutions.push_back(q.index);
                        // q is dominated by p
                        q.domination_count += 1;
                    }
                    Ordering::Greater => {
                        // p is dominated by q
                        // Add `p` to the set of solutions dominated by `q`.
                        q.dominated_solutions.push_back(p.index);
                        // q dominates p
                        // Increment domination counter of `p`.
                        p.domination_count += 1;
                    }
                    Ordering::Equal => {}
                }
            }
            if p.domination_count == 0 {
                // `p` belongs to the first front as it is not dominated by any
                // other solution.
                current_front.push((p.index, p.solution));
            }
        }

        Self {
            entries,
            current_front,
        }
    }

    /// Returns an array containing all pareto fronts.
    pub fn pareto_fronts(self) -> Vec<Vec<(usize, &'a S)>> {
        let mut fronts = Vec::new();
        for front in self {
            fronts.push(front);
        }
        return fronts;
    }

    /// Returns an array containing the first pareto fronts, until
    /// `max_solutions` have been found. Note that always the whole fronts are
    /// returned, i.e. the number of solutions returned may be higher.
    pub fn pareto_fronts_stop_at(self, max_solutions: usize) -> Vec<Vec<(usize, &'a S)>> {
        let mut found_solutions = 0;
        let mut fronts = Vec::new();

        for front in self {
            found_solutions += front.len();
            fronts.push(front);
            if found_solutions >= max_solutions {
                break;
            }
        }
        return fronts;
    }
}

/// Iterate over the pareto fronts. Each call to next() will yield the
/// next pareto front.
impl<'a, S> Iterator for NonDominatedSorter<'a, S> {
    type Item = Vec<(usize, &'a S)>;

    /// Return the next pareto front

    fn next(&mut self) -> Option<Self::Item> {
        if self.current_front.is_empty() {
            return None;
        }

        // Calculate the next front

        let mut next_front = Vec::new();
        for &(p_i, _) in self.current_front.iter() {
            // to calculate the next front, we have to remove the
            // solutions of the current front, and as such, decrease the
            // domination_count of they dominated_solutions. We can
            // destruct the dominated_solutions array here, as we will
            // no longer need it.
            // The only problem with poping off solutions off the end is
            // that we will populate the fronts in reverse order. For
            // that reason, we are using a VecDeque. This should give us
            // a stable sort.

            while let Some(q_i) = self.entries[p_i].dominated_solutions.pop_front() {
                let q = &mut self.entries[q_i];
                debug_assert!(q.domination_count > 0);
                q.domination_count -= 1;
                if q.domination_count == 0 {
                    // q is not dominated by any other solution. it belongs to the next front.
                    next_front.push((q_i, q.solution));
                }
            }
        }

        // and return the current front, swapping it with the next

        let current_front = mem::replace(&mut self.current_front, next_front);

        return Some(current_front);
    }
}

#[cfg(test)]
mod helper {
    use test_helper_domination::Tuple;
    pub fn get_solutions() -> Vec<Tuple> {
        vec![
            Tuple(1, 2),
            Tuple(1, 2),
            Tuple(2, 1),
            Tuple(1, 3),
            Tuple(0, 2),
        ]
    }
    pub fn keep_only_index(front: &[(usize, &Tuple)]) -> Vec<usize> {
        front.iter().map(|&(i, _)| i).collect()
    }

    pub fn assert_front_eq(expected: &[usize], front: &[(usize, &Tuple)]) {
        assert_eq!(expected.to_owned(), keep_only_index(front));
    }
}

#[test]
fn test_non_dominated_sort() {
    use test_helper_domination::TupleDominationOrd;
    let solutions = helper::get_solutions();
    let fronts = NonDominatedSorter::new(&solutions, &TupleDominationOrd).pareto_fronts();

    assert_eq!(3, fronts.len());
    helper::assert_front_eq(&[2, 4], &fronts[0]);
    helper::assert_front_eq(&[0, 1], &fronts[1]);
    helper::assert_front_eq(&[3], &fronts[2]);
}

#[test]
fn test_non_dominated_sort_stop_at() {
    use test_helper_domination::TupleDominationOrd;
    let solutions = helper::get_solutions();

    {
        let fronts =
            NonDominatedSorter::new(&solutions, &TupleDominationOrd).pareto_fronts_stop_at(2);
        assert_eq!(1, fronts.len());
        helper::assert_front_eq(&[2, 4], &fronts[0]);
    }
    {
        let fronts =
            NonDominatedSorter::new(&solutions, &TupleDominationOrd).pareto_fronts_stop_at(3);
        assert_eq!(2, fronts.len());
        helper::assert_front_eq(&[2, 4], &fronts[0]);
        helper::assert_front_eq(&[0, 1], &fronts[1]);
    }
}

#[test]
fn test_non_dominated_sort_iter() {
    use test_helper_domination::TupleDominationOrd;
    let solutions = helper::get_solutions();
    let mut fronts = NonDominatedSorter::new(&solutions, &TupleDominationOrd);
    let f = &|front: Vec<_>| helper::keep_only_index(&front);

    assert_eq!(Some(vec![2, 4]), fronts.next().map(f));
    assert_eq!(Some(vec![0, 1]), fronts.next().map(f));
    assert_eq!(Some(vec![3]), fronts.next().map(f));
    assert_eq!(None, fronts.next().map(f));
}
<|endoftext|>


<commit_before>/// Represents a PhotoSize object
#[derive(Clone, Deserialize, Debug)]
pub struct PhotoSize {
    pub file_id: String,
    pub file_path: Option<String>,
    pub width: i64,
    pub height: i64,
    pub file_size: Option<i64>,
}
<commit_msg>added more documentation to photo_size<commit_after>/// Represents a PhotoSize object, which is basically a photo
#[derive(Clone, Deserialize, Debug)]
pub struct PhotoSize {
    pub file_id: String,
    pub file_path: Option<String>,
    pub width: i64,
    pub height: i64,
    pub file_size: Option<i64>,
}
<|endoftext|>


<commit_before>use regex::Regex;
use reqwest;
use serde_json;

use web::data::SolrTermSummary;

pub struct Search {
    solr_url: String,
}

#[derive(Deserialize, Debug)]
struct SolrResponse {
    pub docs: Vec<SolrTermSummary>,
}

#[derive(Deserialize, Debug)]
struct SolrResponseContainer {
    pub response: SolrResponse,
}

impl Search {
    pub fn new(solr_url: String) -> Search {
        Search {
            solr_url: solr_url,
        }
    }

    pub fn term_complete(&self, cv_name: &str, q: &str)
                         -> Result<Vec<SolrTermSummary>, reqwest::Error>
    {
        let mut terms_url =
            self.solr_url.to_owned() + "/terms/select?wt=json&q=cv_name:" +
            cv_name + " AND name:(";

        let clean_words: Vec<String> =
            Regex::new(r"(\w+)").unwrap().captures_iter(q)
            .map(|cap| cap.at(1).unwrap().to_owned()).collect();

        if clean_words.len() == 0 {
            return Ok(vec![]);
        }

        let clean_words_length = clean_words.len();

        for (i, word) in clean_words.into_iter().enumerate() {
            if i == clean_words_length - 1 {
                terms_url += &format!("{}^2 {}*", word, word);
            } else {
                terms_url += &format!("{}^2 {}~1 ", word, word);
            }
        }
        terms_url += ")";

        print!("{:?}\n", terms_url);

        let res = reqwest::get(&terms_url)?;

        println!("Status: {}", res.status());
        println!("Headers:\n{}", res.headers());

        match serde_json::from_reader(res) {
            Ok(solr_response_container) => {
                let container: SolrResponseContainer = solr_response_container;
                Ok(container.response.docs)
            },
            Err(err) => {
                panic!(err);
            }
        }
    }
}
<commit_msg>Fix autocompletion to allow a bit of fuzziness<commit_after>use regex::Regex;
use reqwest;
use serde_json;

use web::data::SolrTermSummary;

pub struct Search {
    solr_url: String,
}

#[derive(Deserialize, Debug)]
struct SolrResponse {
    pub docs: Vec<SolrTermSummary>,
}

#[derive(Deserialize, Debug)]
struct SolrResponseContainer {
    pub response: SolrResponse,
}

impl Search {
    pub fn new(solr_url: String) -> Search {
        Search {
            solr_url: solr_url,
        }
    }

    pub fn term_complete(&self, cv_name: &str, q: &str)
                         -> Result<Vec<SolrTermSummary>, reqwest::Error>
    {
        let mut terms_url =
            self.solr_url.to_owned() + "/terms/select?wt=json&q=cv_name:" +
            cv_name + " AND name:(";

        let clean_words: Vec<String> =
            Regex::new(r"(\w+)").unwrap().captures_iter(q)
            .map(|cap| cap.at(1).unwrap().to_owned()).collect();

        if clean_words.len() == 0 {
            return Ok(vec![]);
        }

        let clean_words_length = clean_words.len();

        for (i, word) in clean_words.into_iter().enumerate() {
            if i == clean_words_length - 1 {
                terms_url += &format!("{}^2 {}*", word, word);
            } else {
                terms_url += &format!("{}^2 {}~0.8 ", word, word);
            }
        }
        terms_url += ")";

        print!("{:?}\n", terms_url);

        let res = reqwest::get(&terms_url)?;

        println!("Status: {}", res.status());
        println!("Headers:\n{}", res.headers());

        match serde_json::from_reader(res) {
            Ok(solr_response_container) => {
                let container: SolrResponseContainer = solr_response_container;
                Ok(container.response.docs)
            },
            Err(err) => {
                panic!(err);
            }
        }
    }
}
<|endoftext|>


<commit_before>use error::Error;
use client::Client;
use params::{List, Metadata, Timestamp};
use resources::{Currency, Discount, Plan};
use serde_qs as query;

/// The set of parameters that can be used when creating or updating an invoice.
///
/// For more details see https://stripe.com/docs/api#create_invoice, https://stripe.com/docs/api#update_invoice.
#[derive(Default, Serialize)]
pub struct InvoiceParams<'a> {
    #[serde(skip_serializing_if = "Option::is_none")] pub application_fee: Option<u64>,
    #[serde(skip_serializing_if = "Option::is_none")] pub customer: Option<&'a str>,
    #[serde(skip_serializing_if = "Option::is_none")] pub description: Option<&'a str>,
    #[serde(skip_serializing_if = "Option::is_none")] pub statement_descriptor: Option<&'a str>,
    #[serde(skip_serializing_if = "Option::is_none")] pub subscription: Option<&'a str>,
    #[serde(skip_serializing_if = "Option::is_none")] pub tax_percent: Option<f64>,

    #[serde(skip_serializing_if = "Option::is_none")] pub closed: Option<bool>,
    #[serde(skip_serializing_if = "Option::is_none")] pub forgiven: Option<bool>,
}

#[derive(Default, Serialize)]
pub struct InvoiceItemParams<'a> {
    #[serde(skip_serializing_if = "Option::is_none")] pub amount: Option<i64>,
    #[serde(skip_serializing_if = "Option::is_none")] pub currency: Option<Currency>,
    #[serde(skip_serializing_if = "Option::is_none")] pub customer: Option<&'a str>,
    #[serde(skip_serializing_if = "Option::is_none")] pub description: Option<&'a str>,
    #[serde(skip_serializing_if = "Option::is_none")] pub discountable: Option<bool>,
    #[serde(skip_serializing_if = "Option::is_none")] pub invoice: Option<&'a str>,
    #[serde(skip_serializing_if = "Option::is_none")] pub metadata: Option<bool>,
    #[serde(skip_serializing_if = "Option::is_none")] pub subscription: Option<bool>,
}

/*
#[derive(Serialize)]
pub struct InvoiceListLinesParams {
    #[serde(skip_serializing_if = "Option::is_none")] pub limit: Option<u64>,
    #[serde(skip_serializing_if = "Option::is_none")] pub ending_before: Option<String>,
    #[serde(skip_serializing_if = "Option::is_none")] pub starting_after: Option<String>,

    ..
}
*/

/// Period is a structure representing a start and end dates.
#[derive(Debug, Deserialize)]
pub struct Period {
    pub start: Timestamp,
    pub end: Timestamp,
}

/// The resource representing a Stripe invoice line item.
///
/// For more details see https://stripe.com/docs/api#invoice_line_item_object.
#[derive(Debug, Deserialize)]
pub struct InvoiceLine {
    pub id: String,
    pub amount: u64,
    pub currency: Currency,
    pub description: Option<String>,
    pub discountable: bool,
    pub livemode: bool,
    pub metadata: Metadata,
    pub period: Period,
    pub plan: Option<Plan>,
    pub proration: bool,
    pub quantity: Option<u64>,
    pub subscription: Option<String>,
    pub subscription_item: Option<String>,
    #[serde(rename = "type")] pub item_type: String, // (invoiceitem, subscription)
}

/// The resource representing a Stripe invoice.
///
/// For more details see https://stripe.com/docs/api#invoice_object.
#[derive(Debug, Deserialize)]
pub struct Invoice {
    pub id: String,
    pub amount_due: u64,
    pub application_fee: Option<u64>,
    pub attempt_count: u64,
    pub attempted: bool,
    pub charge: Option<String>,
    pub closed: bool,
    pub currency: Currency,
    pub customer: String,
    pub date: Timestamp,
    pub description: Option<String>,
    pub discount: Option<Discount>,
    pub ending_balance: Option<i64>,
    pub forgiven: bool,
    pub lines: List<InvoiceLine>,
    pub livemode: bool,
    pub metadata: Metadata,
    pub next_payment_attempt: Option<Timestamp>,
    pub paid: bool,
    pub period_end: Timestamp,
    pub period_start: Timestamp,
    pub receipt_number: Option<String>,
    pub starting_balance: i64,
    pub statment_descriptor: Option<String>,
    pub subscription: Option<String>,
    pub subscription_proration_date: Option<Timestamp>,
    pub subtotal: i64,
    pub tax: Option<i64>,
    pub tax_percent: Option<f64>,
    pub total: i64,
    pub webhooks_delivered_at: Option<Timestamp>,
}

#[derive(Default, Serialize)]
pub struct InvoiceListParams<'a> {
    #[serde(skip_serializing_if = "Option::is_none")] pub limit: Option<u64>,
    #[serde(skip_serializing_if = "Option::is_none")] pub customer: Option<&'a str>,
}

impl Invoice {
    /// Creates a new invoice.
    ///
    /// For more details see https://stripe.com/docs/api#create_invoice.
    pub fn create(client: &Client, params: InvoiceParams) -> Result<Invoice, Error> {
        client.post("/invoices", params)
    }

    /// Retrieves the details of an invoice.
    ///
    /// For more details see https://stripe.com/docs/api#retrieve_invoice.
    pub fn retrieve(client: &Client, invoice_id: &str) -> Result<Invoice, Error> {
        client.get(&format!("/invoices/{}", invoice_id))
    }

    // TODO: Implement InvoiceListLinesParams
    // pub fn get_lines(client: &Client, invoice_id: &str, params: InvoiceListLinesParams) -> Result<List<InvoiceLine>, Error> {
    //     client.get(&format!("/invoices/{}/lines", invoice_id))
    // }

    // TODO: Implement InvoiceUpcomingParams
    // pub fn get_upcoming(client: &Client, params: InvoiceUpcomingParams) -> Result<Invoice, Error> {
    //     client.get(&format!("/invoices/upcoming?customer={}", invoice_id))
    // }

    /// Pays an invoice.
    ///
    /// For more details see https://stripe.com/docs/api#pay_invoice.
    pub fn pay(client: &Client, invoice_id: &str) -> Result<Invoice, Error> {
        client.post_empty(&format!("/invoices/{}/pay", invoice_id))
    }

    /// Updates an invoice.
    ///
    /// For more details see https://stripe.com/docs/api#update_invoice.
    pub fn update(client: &Client, invoice_id: &str, params: InvoiceParams) -> Result<Invoice, Error> {
        client.post(&format!("/invoices/{}", invoice_id), &params)
    }

    /// Lists all invoices with optional customer_id and limit params
    ///
    /// For more details see https://stripe.com/docs/api#list_invoices.
    pub fn list(client: &Client, params: InvoiceListParams) -> Result<List<Invoice>, Error> {
        client.get(&format!("/invoices?{}", query::to_string(&params)?))
    }
}

impl InvoiceLine {
    /// Creates an invoice line item.
    ///
    /// For more details see https://stripe.com/docs/api/node#invoice_line_item_object
    pub fn create(client: &Client, params: InvoiceItemParams) -> Result<InvoiceLine, Error> {
        client.post(&format!("/invoiceitems"), &params)
    }

}
<commit_msg>Invoice Items can have a negative line amount<commit_after>use error::Error;
use client::Client;
use params::{List, Metadata, Timestamp};
use resources::{Currency, Discount, Plan};
use serde_qs as query;

/// The set of parameters that can be used when creating or updating an invoice.
///
/// For more details see https://stripe.com/docs/api#create_invoice, https://stripe.com/docs/api#update_invoice.
#[derive(Default, Serialize)]
pub struct InvoiceParams<'a> {
    #[serde(skip_serializing_if = "Option::is_none")] pub application_fee: Option<u64>,
    #[serde(skip_serializing_if = "Option::is_none")] pub customer: Option<&'a str>,
    #[serde(skip_serializing_if = "Option::is_none")] pub description: Option<&'a str>,
    #[serde(skip_serializing_if = "Option::is_none")] pub statement_descriptor: Option<&'a str>,
    #[serde(skip_serializing_if = "Option::is_none")] pub subscription: Option<&'a str>,
    #[serde(skip_serializing_if = "Option::is_none")] pub tax_percent: Option<f64>,

    #[serde(skip_serializing_if = "Option::is_none")] pub closed: Option<bool>,
    #[serde(skip_serializing_if = "Option::is_none")] pub forgiven: Option<bool>,
}

#[derive(Default, Serialize)]
pub struct InvoiceItemParams<'a> {
    #[serde(skip_serializing_if = "Option::is_none")] pub amount: Option<i64>,
    #[serde(skip_serializing_if = "Option::is_none")] pub currency: Option<Currency>,
    #[serde(skip_serializing_if = "Option::is_none")] pub customer: Option<&'a str>,
    #[serde(skip_serializing_if = "Option::is_none")] pub description: Option<&'a str>,
    #[serde(skip_serializing_if = "Option::is_none")] pub discountable: Option<bool>,
    #[serde(skip_serializing_if = "Option::is_none")] pub invoice: Option<&'a str>,
    #[serde(skip_serializing_if = "Option::is_none")] pub metadata: Option<bool>,
    #[serde(skip_serializing_if = "Option::is_none")] pub subscription: Option<bool>,
}

/*
#[derive(Serialize)]
pub struct InvoiceListLinesParams {
    #[serde(skip_serializing_if = "Option::is_none")] pub limit: Option<u64>,
    #[serde(skip_serializing_if = "Option::is_none")] pub ending_before: Option<String>,
    #[serde(skip_serializing_if = "Option::is_none")] pub starting_after: Option<String>,

    ..
}
*/

/// Period is a structure representing a start and end dates.
#[derive(Debug, Deserialize)]
pub struct Period {
    pub start: Timestamp,
    pub end: Timestamp,
}

/// The resource representing a Stripe invoice line item.
///
/// For more details see https://stripe.com/docs/api#invoice_line_item_object.
#[derive(Debug, Deserialize)]
pub struct InvoiceItem {
    pub id: String,
    pub amount: i64,
    pub currency: Currency,
    pub description: Option<String>,
    pub discountable: bool,
    pub livemode: bool,
    pub metadata: Metadata,
    pub period: Period,
    pub plan: Option<Plan>,
    pub proration: bool,
    pub quantity: Option<u64>,
    pub subscription: Option<String>,
    pub subscription_item: Option<String>,
    #[serde(rename = "type")] pub item_type: String, // (invoiceitem, subscription)
}

/// The resource representing a Stripe invoice.
///
/// For more details see https://stripe.com/docs/api#invoice_object.
#[derive(Debug, Deserialize)]
pub struct Invoice {
    pub id: String,
    pub amount_due: u64,
    pub application_fee: Option<u64>,
    pub attempt_count: u64,
    pub attempted: bool,
    pub charge: Option<String>,
    pub closed: bool,
    pub currency: Currency,
    pub customer: String,
    pub date: Timestamp,
    pub description: Option<String>,
    pub discount: Option<Discount>,
    pub ending_balance: Option<i64>,
    pub forgiven: bool,
    pub lines: List<InvoiceItem>,
    pub livemode: bool,
    pub metadata: Metadata,
    pub next_payment_attempt: Option<Timestamp>,
    pub paid: bool,
    pub period_end: Timestamp,
    pub period_start: Timestamp,
    pub receipt_number: Option<String>,
    pub starting_balance: i64,
    pub statment_descriptor: Option<String>,
    pub subscription: Option<String>,
    pub subscription_proration_date: Option<Timestamp>,
    pub subtotal: i64,
    pub tax: Option<i64>,
    pub tax_percent: Option<f64>,
    pub total: i64,
    pub webhooks_delivered_at: Option<Timestamp>,
}

#[derive(Default, Serialize)]
pub struct InvoiceListParams<'a> {
    #[serde(skip_serializing_if = "Option::is_none")] pub limit: Option<u64>,
    #[serde(skip_serializing_if = "Option::is_none")] pub customer: Option<&'a str>,
}

impl Invoice {
    /// Creates a new invoice.
    ///
    /// For more details see https://stripe.com/docs/api#create_invoice.
    pub fn create(client: &Client, params: InvoiceParams) -> Result<Invoice, Error> {
        client.post("/invoices", params)
    }

    /// Retrieves the details of an invoice.
    ///
    /// For more details see https://stripe.com/docs/api#retrieve_invoice.
    pub fn retrieve(client: &Client, invoice_id: &str) -> Result<Invoice, Error> {
        client.get(&format!("/invoices/{}", invoice_id))
    }

    // TODO: Implement InvoiceListLinesParams
    // pub fn get_lines(client: &Client, invoice_id: &str, params: InvoiceListLinesParams) -> Result<List<InvoiceItem>, Error> {
    //     client.get(&format!("/invoices/{}/lines", invoice_id))
    // }

    // TODO: Implement InvoiceUpcomingParams
    // pub fn get_upcoming(client: &Client, params: InvoiceUpcomingParams) -> Result<Invoice, Error> {
    //     client.get(&format!("/invoices/upcoming?customer={}", invoice_id))
    // }

    /// Pays an invoice.
    ///
    /// For more details see https://stripe.com/docs/api#pay_invoice.
    pub fn pay(client: &Client, invoice_id: &str) -> Result<Invoice, Error> {
        client.post_empty(&format!("/invoices/{}/pay", invoice_id))
    }

    /// Updates an invoice.
    ///
    /// For more details see https://stripe.com/docs/api#update_invoice.
    pub fn update(client: &Client, invoice_id: &str, params: InvoiceParams) -> Result<Invoice, Error> {
        client.post(&format!("/invoices/{}", invoice_id), &params)
    }

    /// Lists all invoices with optional customer_id and limit params
    ///
    /// For more details see https://stripe.com/docs/api#list_invoices.
    pub fn list(client: &Client, params: InvoiceListParams) -> Result<List<Invoice>, Error> {
        client.get(&format!("/invoices?{}", query::to_string(&params)?))
    }
}

impl InvoiceItem {
    /// Creates an invoice line item.
    ///
    /// For more details see https://stripe.com/docs/api/node#invoice_line_item_object
    pub fn create(client: &Client, params: InvoiceItemParams) -> Result<InvoiceItem, Error> {
        client.post(&format!("/invoiceitems"), &params)
    }

}
<|endoftext|>


<commit_before>extern crate gtk;
extern crate glib;
extern crate gstreamer as gst;

/*extern crate chrono;
use chrono::Utc;*/

use std::rc::{Rc, Weak};
use std::cell::RefCell;

use std::path::PathBuf;

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

use gtk::prelude::*;
use gtk::{ApplicationWindow, Button, FileChooserAction, FileChooserDialog,
          HeaderBar, ResponseType, Label, ToolButton};

use ::media::{Context, ContextMessage, Timestamp};
use ::media::ContextMessage::*;

use super::{AudioController, InfoController, VideoController};

pub struct MainController {
    window: ApplicationWindow,
    header_bar: HeaderBar,
    play_pause_btn: ToolButton,
    position_lbl: Label,
    info_ctrl: InfoController,
    video_ctrl: VideoController,
    audio_ctrl: Rc<RefCell<AudioController>>,

    context: Option<Rc<RefCell<Context>>>,
    last_position: u64,

    /*min_pos_query: u64,
    max_pos_query: u64,
    sum_pos_query: u64,
    nb_pos_query: u64,*/

    self_weak: Option<Weak<RefCell<MainController>>>,
    keep_going: bool,
    listener_src: Option<glib::SourceId>,
    tracker_src: Option<glib::SourceId>,
}

impl MainController {
    pub fn new(builder: gtk::Builder) -> Rc<RefCell<Self>> {
        let this = Rc::new(RefCell::new(MainController {
            window: builder.get_object("application-window").unwrap(),
            header_bar: builder.get_object("header-bar").unwrap(),
            play_pause_btn: builder.get_object("play_pause-toolbutton").unwrap(),
            position_lbl: builder.get_object("position-lbl").unwrap(),
            info_ctrl: InfoController::new(&builder),
            video_ctrl: VideoController::new(&builder),
            audio_ctrl: AudioController::new(&builder),
            context: None,

            last_position: 0,
            /*min_pos_query: 0,
            max_pos_query: 0,
            sum_pos_query: 0,
            nb_pos_query: 0,*/

            self_weak: None,
            keep_going: true,
            listener_src: None,
            tracker_src: None,
        }));

        let this_weak = Rc::downgrade(&this);
        {
            let mut this_mut = this.borrow_mut();
            this_mut.window.connect_delete_event(|_, _| {
                gtk::main_quit();
                Inhibit(false)
            });
            this_mut.window.set_titlebar(&this_mut.header_bar);

            let this_weak_clone = this_weak.clone();
            this_mut.play_pause_btn.connect_clicked(move |_| {
                if let Some(this_ref) = this_weak_clone.upgrade() {
                    this_ref.borrow_mut().play_pause();
                };
            });

            let this_weak = Rc::downgrade(&this);
            this_mut.self_weak = Some(this_weak);
        }

        let open_btn: Button = builder.get_object("open-btn").unwrap();
        let this_weak_clone = this_weak.clone();
        open_btn.connect_clicked(move |_| {
            if let Some(this_ref) = this_weak_clone.upgrade() {
                this_ref.borrow_mut().select_media();
            }
        });

        this
    }

    pub fn show_all(&self) {
        self.window.show_all();
    }

    pub fn play_pause(&mut self) {
        if let Some(context_rc) = self.context.as_ref() {
            let context = context_rc.borrow();
            match context.get_state() {
                gst::State::Paused => {
                    context.play().unwrap();
                    self.play_pause_btn.set_icon_name("media-playback-pause");
                }
                gst::State::Playing => {
                    context.pause().unwrap();
                    self.play_pause_btn.set_icon_name("media-playback-start");
                },
                state => println!("Can't play/pause in state {:?}", state),
            }
        };
    }

    pub fn stop(&mut self) {
        if let Some(context_rc) = self.context.as_ref() {
            context_rc.borrow().stop();

            // remove callbacks in order to avoid conflict on borrowing of self
            if let Some(source_id) = self.listener_src {
                glib::source_remove(source_id);
            }
            self.listener_src = None;
            if let Some(source_id) = self.tracker_src {
                glib::source_remove(source_id);
            }
            self.tracker_src = None;

            self.audio_ctrl.borrow_mut().cleanup();
        }
        self.play_pause_btn.set_icon_name("media-playback-start");
    }

    fn select_media(&mut self) {
        self.stop();

        let file_dlg = FileChooserDialog::new(
            Some("Open a media file"),
            Some(&self.window),
            FileChooserAction::Open,
        );
        // Note: couldn't find equivalents for STOCK_OK
        file_dlg.add_button("Open", ResponseType::Ok.into());

        if file_dlg.run() == ResponseType::Ok.into() {
            self.open_media(file_dlg.get_filename().unwrap());
        }

        file_dlg.close();
    }

    fn register_listener(&mut self,
        timeout: u32,
        ui_rx: Receiver<ContextMessage>,
    )
    {
        let this_weak = self.self_weak.as_ref()
            .unwrap()
            .clone();

        self.listener_src = Some(gtk::timeout_add(timeout, move || {
            let mut message_iter = ui_rx.try_iter();

            let this_rc = this_weak.upgrade().unwrap();
            let mut this_mut = this_rc.borrow_mut();

            for message in message_iter.next() {
                match message {
                    AsyncDone => {
                        println!("Received AsyncDone");
                    },
                    InitDone => {
                        println!("Received InitDone");

                        let context_rc = this_mut.context.as_ref()
                            .expect("... but no context available")
                            .clone();

                        this_mut.info_ctrl.new_media(&context_rc);
                        this_mut.video_ctrl.new_media(&context_rc);
                        this_mut.audio_ctrl.borrow_mut().new_media(&context_rc);

                        this_mut.header_bar.set_subtitle(
                            Some(context_rc.borrow().file_name.as_str())
                        );
                    },
                    Eos => {
                        println!("Received Eos");
                        this_mut.play_pause_btn.set_icon_name("media-playback-start");
                    },
                    FailedToOpenMedia => {
                        eprintln!("ERROR: failed to open media");
                        this_mut.context = None;
                        this_mut.keep_going = false;
                    },
                };

                if !this_mut.keep_going { break; }
            }

            if !this_mut.keep_going {
                this_mut.listener_src = None;
                println!("Exiting listener");
            }

            glib::Continue(this_mut.keep_going)
        }));
    }

    fn register_tracker(&mut self, timeout: u32) {
        let this_weak = self.self_weak.as_ref()
            .unwrap()
            .clone();

        self.tracker_src = Some(gtk::timeout_add(timeout, move || {
            let this = this_weak.upgrade().unwrap();
            let mut this_mut = this.borrow_mut();

            if this_mut.keep_going {
                let context_rc = this_mut.context.as_ref()
                    .expect("Tracking... but no context available")
                    .clone();

                let mut context = context_rc.borrow_mut();

                //let before = Utc::now();
                let position = context.get_position();
                /*let after = Utc::now();
                let delta = after.signed_duration_since(before)
                    .num_nanoseconds()
                    .unwrap() as u64;

                this_mut.max_pos_query = this_mut.max_pos_query.max(delta);
                this_mut.sum_pos_query += delta;
                this_mut.nb_pos_query += 1;
                println!("{} - {} - {}", this_mut.max_pos_query, this_mut.sum_pos_query / this_mut.nb_pos_query, delta);

                if this_mut.nb_pos_query > 10 * 60 {
                    this_mut.max_pos_query = 0;
                    this_mut.sum_pos_query = 0;
                    this_mut.nb_pos_query = 0;
                }*/

                if this_mut.last_position != position {
                    this_mut.position_lbl.set_text(
                        &format!("{}", Timestamp::from_nano(position as i64))
                    );
                    this_mut.last_position = position;

                    this_mut.audio_ctrl.borrow_mut().tic(position);
                }
            } else {
                this_mut.tracker_src = None;
                println!("Exiting tracker");
            }

            glib::Continue(this_mut.keep_going)
        }));
    }

    fn open_media(&mut self, filepath: PathBuf) {
        assert_eq!(self.listener_src, None);

        self.position_lbl.set_text("00:00.000");

        let (ctx_tx, ui_rx) = channel();

        self.keep_going = true;
        self.register_listener(500, ui_rx);
        self.register_tracker(16); // 60 Hz

        match Context::open_media_path(
                filepath,
                10_000_000_000,
                self.video_ctrl.video_box.clone(),
                ctx_tx
            )
            {
            Ok(context) => {
                self.context = Some(Rc::new(RefCell::new(context)));
                self.last_position = 0;
            },
            Err(error) => eprintln!("Error opening media: {}", error),
        };
    }
}
<commit_msg>Register / unregister tracker when switch playing state (#19)<commit_after>extern crate gtk;
extern crate glib;
extern crate gstreamer as gst;

/*extern crate chrono;
use chrono::Utc;*/

use std::rc::{Rc, Weak};
use std::cell::RefCell;

use std::path::PathBuf;

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

use gtk::prelude::*;
use gtk::{ApplicationWindow, Button, FileChooserAction, FileChooserDialog,
          HeaderBar, ResponseType, Label, ToolButton};

use ::media::{Context, ContextMessage, Timestamp};
use ::media::ContextMessage::*;

use super::{AudioController, InfoController, VideoController};

pub struct MainController {
    window: ApplicationWindow,
    header_bar: HeaderBar,
    play_pause_btn: ToolButton,
    position_lbl: Label,
    info_ctrl: InfoController,
    video_ctrl: VideoController,
    audio_ctrl: Rc<RefCell<AudioController>>,

    context: Option<Rc<RefCell<Context>>>,
    last_position: u64,

    /*min_pos_query: u64,
    max_pos_query: u64,
    sum_pos_query: u64,
    nb_pos_query: u64,*/

    self_weak: Option<Weak<RefCell<MainController>>>,
    keep_going: bool,
    listener_src: Option<glib::SourceId>,
    tracker_src: Option<glib::SourceId>,
}

impl MainController {
    pub fn new(builder: gtk::Builder) -> Rc<RefCell<Self>> {
        let this = Rc::new(RefCell::new(MainController {
            window: builder.get_object("application-window").unwrap(),
            header_bar: builder.get_object("header-bar").unwrap(),
            play_pause_btn: builder.get_object("play_pause-toolbutton").unwrap(),
            position_lbl: builder.get_object("position-lbl").unwrap(),
            info_ctrl: InfoController::new(&builder),
            video_ctrl: VideoController::new(&builder),
            audio_ctrl: AudioController::new(&builder),
            context: None,

            last_position: 0,
            /*min_pos_query: 0,
            max_pos_query: 0,
            sum_pos_query: 0,
            nb_pos_query: 0,*/

            self_weak: None,
            keep_going: true,
            listener_src: None,
            tracker_src: None,
        }));

        let this_weak = Rc::downgrade(&this);
        {
            let mut this_mut = this.borrow_mut();
            this_mut.window.connect_delete_event(|_, _| {
                gtk::main_quit();
                Inhibit(false)
            });
            this_mut.window.set_titlebar(&this_mut.header_bar);

            let this_weak_clone = this_weak.clone();
            this_mut.play_pause_btn.connect_clicked(move |_| {
                if let Some(this_ref) = this_weak_clone.upgrade() {
                    this_ref.borrow_mut().play_pause();
                };
            });

            let this_weak = Rc::downgrade(&this);
            this_mut.self_weak = Some(this_weak);
        }

        let open_btn: Button = builder.get_object("open-btn").unwrap();
        let this_weak_clone = this_weak.clone();
        open_btn.connect_clicked(move |_| {
            if let Some(this_ref) = this_weak_clone.upgrade() {
                this_ref.borrow_mut().select_media();
            }
        });

        this
    }

    pub fn show_all(&self) {
        self.window.show_all();
    }

    pub fn play_pause(&mut self) {
        let state =
            if let Some(context_rc) = self.context.as_ref() {
                let context = context_rc.borrow();
                match context.get_state() {
                    gst::State::Paused => {
                        context.play().unwrap();
                        gst::State::Paused
                    }
                    gst::State::Playing => {
                        context.pause().unwrap();
                        gst::State::Playing
                    },
                    state => {
                        println!("Can't play/pause in state {:?}", state);
                        return;
                    },
                }
            } else {
                return;
            };

        match state {
            gst::State::Paused => {
                self.register_tracker(16); // 60 Hz
                self.play_pause_btn.set_icon_name("media-playback-pause");
            }
            gst::State::Playing => {
                self.play_pause_btn.set_icon_name("media-playback-start");
                self.remove_tracker();
            },
            state => println!("Can't play/pause in state {:?}", state),
        };
    }

    pub fn stop(&mut self) {
        if let Some(context_rc) = self.context.as_ref() {
            context_rc.borrow().stop();
        };

        // remove callbacks in order to avoid conflict on borrowing of self
        self.remove_listener();
        self.remove_tracker();

        self.audio_ctrl.borrow_mut().cleanup();

        self.play_pause_btn.set_icon_name("media-playback-start");
    }

    fn select_media(&mut self) {
        self.stop();

        let file_dlg = FileChooserDialog::new(
            Some("Open a media file"),
            Some(&self.window),
            FileChooserAction::Open,
        );
        // Note: couldn't find equivalents for STOCK_OK
        file_dlg.add_button("Open", ResponseType::Ok.into());

        if file_dlg.run() == ResponseType::Ok.into() {
            self.open_media(file_dlg.get_filename().unwrap());
        }

        file_dlg.close();
    }

    fn remove_listener(&mut self) {
        if let Some(source_id) = self.listener_src {
            glib::source_remove(source_id);
        }
        self.listener_src = None;
    }

    fn register_listener(&mut self,
        timeout: u32,
        ui_rx: Receiver<ContextMessage>,
    )
    {
        let this_weak = self.self_weak.as_ref()
            .unwrap()
            .clone();

        self.listener_src = Some(gtk::timeout_add(timeout, move || {
            let mut message_iter = ui_rx.try_iter();

            let this_rc = this_weak.upgrade().unwrap();
            let mut this_mut = this_rc.borrow_mut();

            for message in message_iter.next() {
                match message {
                    AsyncDone => {
                        println!("Received AsyncDone");
                    },
                    InitDone => {
                        println!("Received InitDone");

                        let context_rc = this_mut.context.as_ref()
                            .expect("... but no context available")
                            .clone();

                        this_mut.info_ctrl.new_media(&context_rc);
                        this_mut.video_ctrl.new_media(&context_rc);
                        this_mut.audio_ctrl.borrow_mut().new_media(&context_rc);

                        this_mut.header_bar.set_subtitle(
                            Some(context_rc.borrow().file_name.as_str())
                        );
                    },
                    Eos => {
                        println!("Received Eos");
                        this_mut.play_pause_btn.set_icon_name("media-playback-start");
                    },
                    FailedToOpenMedia => {
                        eprintln!("ERROR: failed to open media");
                        this_mut.context = None;
                        this_mut.keep_going = false;
                    },
                };

                if !this_mut.keep_going { break; }
            }

            if !this_mut.keep_going {
                this_mut.listener_src = None;
                println!("Exiting listener");
            }

            glib::Continue(this_mut.keep_going)
        }));
    }

    fn remove_tracker(&mut self) {
        if let Some(source_id) = self.tracker_src {
            glib::source_remove(source_id);
        }
        self.tracker_src = None;
    }

    fn register_tracker(&mut self, timeout: u32) {
        let this_weak = self.self_weak.as_ref()
            .unwrap()
            .clone();

        self.tracker_src = Some(gtk::timeout_add(timeout, move || {
            let this = this_weak.upgrade().unwrap();
            let mut this_mut = this.borrow_mut();

            if this_mut.keep_going {
                let context_rc = this_mut.context.as_ref()
                    .expect("Tracking... but no context available")
                    .clone();

                let mut context = context_rc.borrow_mut();

                //let before = Utc::now();
                let position = context.get_position();
                /*let after = Utc::now();
                let delta = after.signed_duration_since(before)
                    .num_nanoseconds()
                    .unwrap() as u64;

                this_mut.max_pos_query = this_mut.max_pos_query.max(delta);
                this_mut.sum_pos_query += delta;
                this_mut.nb_pos_query += 1;
                println!("{} - {} - {}", this_mut.max_pos_query, this_mut.sum_pos_query / this_mut.nb_pos_query, delta);

                if this_mut.nb_pos_query > 10 * 60 {
                    this_mut.max_pos_query = 0;
                    this_mut.sum_pos_query = 0;
                    this_mut.nb_pos_query = 0;
                }*/

                if this_mut.last_position != position {
                    this_mut.position_lbl.set_text(
                        &format!("{}", Timestamp::from_nano(position as i64))
                    );
                    this_mut.last_position = position;

                    this_mut.audio_ctrl.borrow_mut().tic(position);
                }
            } else {
                this_mut.tracker_src = None;
                println!("Exiting tracker");
            }

            glib::Continue(this_mut.keep_going)
        }));
    }

    fn open_media(&mut self, filepath: PathBuf) {
        assert_eq!(self.listener_src, None);

        self.position_lbl.set_text("00:00.000");

        let (ctx_tx, ui_rx) = channel();

        self.keep_going = true;
        self.register_listener(500, ui_rx);

        match Context::open_media_path(
                filepath,
                10_000_000_000,
                self.video_ctrl.video_box.clone(),
                ctx_tx
            )
            {
            Ok(context) => {
                self.context = Some(Rc::new(RefCell::new(context)));
                self.last_position = 0;
            },
            Err(error) => eprintln!("Error opening media: {}", error),
        };
    }
}
<|endoftext|>


<commit_before>pub mod errors;

use std::ops::{Deref, Range};

pub use self::errors::{Error, Result};

/// An `Interval` wraps the `std::ops::Range` from the stdlib and is defined by a start and end field
/// where end should be >= start.
#[derive(Debug, Clone, Eq, PartialEq, Serialize, Deserialize)]
pub struct Interval<N: Ord + Clone>(Range<N>);

impl<N: Ord + Clone> Interval<N> {
    /// Construct a new `Interval` from the given Range.
    /// Will return `Err` if end < start.
    pub fn new(r: Range<N>) -> Result<Interval<N>> {
        if r.end >= r.start {
            Ok(Interval(r))
        } else {
            Err(Error::InvalidRange)
        }
    }
}

/// Convert a `Range` into an `Interval`. This conversion will panic if the `Range` has end < start
impl<N: Ord + Clone> From<Range<N>> for Interval<N> {
    fn from(r: Range<N>) -> Self {
        match Interval::new(r) {
            Ok(interval) => interval,
            Err(Error::InvalidRange) => panic!("Cannot convert negative width range to interval"),
        }
    }
}

/// Convert a reference to a `Range` to an interval by cloning. This conversion will panic if the
/// `Range` has end < start
impl<'a, N: Ord + Clone> From<&'a Range<N>> for Interval<N> {
    fn from(r: &Range<N>) -> Self {
        match Interval::new(r.clone()) {
            Ok(interval) => interval,
            Err(Error::InvalidRange) => panic!("Cannot convert negative width range to interval"),
        }
    }
}

/// Use the `Deref` operator to get a reference to `Range` wrapped by the `Interval` newtype.
impl<N: Ord + Clone> Deref for Interval<N> {
    type Target = Range<N>;

    fn deref(&self) -> &Self::Target {
        &self.0
    }
}

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

    #[test]
    #[should_panic]
    fn negative_width_range() {
        let _ = Interval::from(10..5);
    }

    #[test]
    fn range_interval_conversions() {
        assert_eq!(Interval::new(1..10).unwrap(), (1..10).into());
        assert_eq!(Interval::from(1..10), Interval::new(1..10).unwrap());
        //deref access
        let r = Interval::new(1..10).unwrap();
        assert_eq!(*r, (1..10));
        assert_eq!(r.start, 1);
        assert_eq!(r.end, 10);
    }
}
<commit_msg>Examples for utils::Interval (#299)<commit_after>//! This module defines a newtype `Interval` for `std::ops::Range`, which will panic if `end` < `start`.
//!
//! # Examples
//! Create a new `Interval` given a `Range`.
//! ```
//! use bio::utils::Interval;
//! assert_eq!(Interval::new(3..6).unwrap(), (3..6).into());
//! ```
//!
//! Building an `Interval` from a `Range` with start > end should panic.
//! ```should_panic
//! use bio::utils::Interval;
//! Interval::from(7..1);
//! ```
//!
//! If you want to handle invalid ranges properly, use the `new` constructor
//! ```
//! use bio::utils::Interval;
//! match Interval::new(7..1) {
//!     Ok(interval) => println!("{:?}", interval),
//!     Err(error) => eprintln!("interval start > end"),
//! }
//! ```

pub mod errors;

use std::ops::{Deref, Range};

pub use self::errors::{Error, Result};

/// An `Interval` wraps the `std::ops::Range` from the stdlib and is defined by a start and end field
/// where end should be >= start.
#[derive(Debug, Clone, Eq, PartialEq, Serialize, Deserialize)]
pub struct Interval<N: Ord + Clone>(Range<N>);

impl<N: Ord + Clone> Interval<N> {
    /// Construct a new `Interval` from the given Range.
    /// Will return `Err` if end < start.
    pub fn new(r: Range<N>) -> Result<Interval<N>> {
        if r.end >= r.start {
            Ok(Interval(r))
        } else {
            Err(Error::InvalidRange)
        }
    }
}

/// Convert a `Range` into an `Interval`. This conversion will panic if the `Range` has end < start
impl<N: Ord + Clone> From<Range<N>> for Interval<N> {
    fn from(r: Range<N>) -> Self {
        match Interval::new(r) {
            Ok(interval) => interval,
            Err(Error::InvalidRange) => panic!("Cannot convert negative width range to interval"),
        }
    }
}

/// Convert a reference to a `Range` to an interval by cloning. This conversion will panic if the
/// `Range` has end < start
impl<'a, N: Ord + Clone> From<&'a Range<N>> for Interval<N> {
    fn from(r: &Range<N>) -> Self {
        match Interval::new(r.clone()) {
            Ok(interval) => interval,
            Err(Error::InvalidRange) => panic!("Cannot convert negative width range to interval"),
        }
    }
}

/// Use the `Deref` operator to get a reference to `Range` wrapped by the `Interval` newtype.
impl<N: Ord + Clone> Deref for Interval<N> {
    type Target = Range<N>;

    fn deref(&self) -> &Self::Target {
        &self.0
    }
}

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

    #[test]
    #[should_panic]
    fn negative_width_range() {
        let _ = Interval::from(10..5);
    }

    #[test]
    fn range_interval_conversions() {
        assert_eq!(Interval::new(1..10).unwrap(), (1..10).into());
        assert_eq!(Interval::from(1..10), Interval::new(1..10).unwrap());
        //deref access
        let r = Interval::new(1..10).unwrap();
        assert_eq!(*r, (1..10));
        assert_eq!(r.start, 1);
        assert_eq!(r.end, 10);
    }
}
<|endoftext|>


<commit_before>// Copyright 2016 Johannes Köster.
// Licensed under the MIT license (http://opensource.org/licenses/MIT)
// This file may not be copied, modified, or distributed
// except according to those terms.

use std::f64;
use std::iter;
use std::slice;

use num::traits::{cast, NumCast};
use itertools::Itertools;

use bio::stats::logprobs::{self, LogProb};

/// Implementation of a cumulative distribution function.
#[derive(Debug, Clone)]
pub struct CDF<T: PartialOrd> {
    inner: Vec<(T, LogProb)>
}

impl<T: PartialOrd> CDF<T> {
    /// Create CDF from given probability mass function (PMF). The PMF may contain duplicate values
    /// the probabilities of which are summed during generation of the CDF.
    pub fn from_pmf(mut entries: Vec<(T, LogProb)>) -> Self {
        entries.sort_by(|&(ref a, _), &(ref b, _)| a.partial_cmp(b).unwrap());
        let mut inner: Vec<(T, LogProb)> = Vec::new();
        for mut e in entries.into_iter() {
            let p = logprobs::add(inner.last().map_or(f64::NEG_INFINITY, |e| e.1), e.1);
            if !inner.is_empty() && inner.last().unwrap().0 == e.0 {
                inner.last_mut().unwrap().1 = p;
            }
            else {
                e.1 = p;
                inner.push(e);
            }
        }
        let mut cdf = CDF {
            inner: inner
        };

        if relative_eq!(cdf.total_prob(), 0.0) && cdf.total_prob() > 0.0 {
            cdf.inner.last_mut().unwrap().1 = 0.0;
        }

        cdf
    }

    /// Create CDF from iterator. This can be used to replace the values of a CDF.
    pub fn from_cdf<I: Iterator<Item = (T, LogProb)>>(entries: I) -> Self {
        CDF { inner: entries.collect_vec() }
    }

    pub fn reduce(self) -> Self {
        let mut inner = Vec::new();
        let mut last = f64::NEG_INFINITY;
        for e in self.inner.into_iter() {
            if last != e.1 {
                last = e.1;
                inner.push(e);
            }
        }
        CDF { inner: inner }
    }

    pub fn sample(mut self, n: usize) -> Self {
        if self.inner.len() <= n {
            self
        }
        else {
            let s = self.inner.len() / (n - 1);
            let last = self.inner.pop().unwrap();
            let mut inner = self.inner.into_iter().step(s).collect_vec();
            inner.push(last);
            CDF {
                inner: inner
            }
        }
    }

    pub fn iter(&self) -> slice::Iter<(T, f64)>{
        self.inner.iter()
    }

    pub fn iter_pmf<'a>(&'a self) -> CDFPMFIter<'a, T> {
        fn cdf_to_pmf<'a, G>(last_prob: &mut LogProb, e: &'a (G, LogProb)) -> Option<(&'a G, LogProb)> {
            let &(ref value, cdf_prob) = e;
            let prob = logprobs::sub(cdf_prob, *last_prob);
            *last_prob = cdf_prob;
            Some((value, prob))
        }
        self.inner.iter().scan(f64::NEG_INFINITY, cdf_to_pmf)
    }

    /// Get cumulative probability for a given value. If the value is not present,
    /// return the probability of the previous value.
    pub fn get(&self, value: &T) -> Option<LogProb> {
        if self.inner.is_empty() {
            None
        }
        else {
            Some(match self.inner.binary_search_by(|e| e.0.partial_cmp(value).unwrap()) {
                Ok(i) => self.inner[i].1,
                Err(i) => if i > 0 { self.inner[i - 1].1 } else { f64::NEG_INFINITY }
            })
        }
    }

    pub fn get_pmf(&self, value: &T) -> Option<LogProb> {
        if self.inner.is_empty() {
            None
        }
        else {
            Some(match self.inner.binary_search_by(|e| e.0.partial_cmp(value).unwrap()) {
                Ok(i) => if i > 0 { logprobs::sub(self.inner[i].1, self.inner[i - 1].1) } else { self.inner[0].1 },
                Err(i) => if i > 0 { self.inner[i - 1].1 } else { f64::NEG_INFINITY }
            })
        }
    }

    pub fn total_prob(&self) -> LogProb {
        let &(_, prob) = self.inner.last().unwrap();
        prob
    }

    /// Return maximum a posteriori probability estimate (MAP).
    pub fn map(&self) -> &T {
        let mut max = self.iter_pmf().next().unwrap();
        for e in self.iter_pmf() {
            if e.1 >= max.1 {
                max = e;
            }
        }
        &max.0
    }

    /// Return the 95% credible interval.
    pub fn credible_interval(&self) -> (&T, &T) {
        let lower = self.inner.binary_search_by(|&(_, p)| p.partial_cmp(&0.025f64.ln()).unwrap()).unwrap_or_else(|i| if i > 0 { i - 1 } else { 0 });
        let lower_p = self.inner[lower].1;
        let mut upper = self.inner.binary_search_by(|&(_, p)| logprobs::sub(p, lower_p).partial_cmp(&0.95f64.ln()).unwrap()).unwrap_or_else(|i| i);
        if upper == self.inner.len() {
            upper -= 1;
        }

        (&self.inner[lower].0, &self.inner[upper].0)
    }

    pub fn len(&self) -> usize {
        self.inner.len()
    }
}

impl<T: NumCast + Clone + PartialOrd> CDF<T> {
    pub fn expected_value(&self) -> f64 {
        self.iter_pmf().map(|(value, prob)| {
            cast::<T, f64>(value.clone()).unwrap() * prob.exp()
        }).fold(0.0f64, |s, e| s + e)
    }

    pub fn variance(&self) -> f64 {
        let ev = self.expected_value();
        self.iter_pmf().map(|(value, prob)| {
                (cast::<T, f64>(value.clone()).unwrap() - ev).powi(2) * prob.exp()
        }).fold(0.0, |s, e| s + e)
    }

    pub fn standard_deviation(&self) -> f64 {
        self.variance().sqrt()
    }
}

pub type CDFPMFIter<'a, T> = iter::Scan<slice::Iter<'a, (T, LogProb)>, LogProb, fn(&mut LogProb, &'a (T, LogProb)) -> Option<(&'a T, LogProb)>>;

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

    #[test]
    fn test_cdf() {
        let mut pmf = vec![(0.0, 0.1f64.ln())];
        for i in 0..9 {
            pmf.push((i as f64, 0.1f64.ln()));
        }
        println!("{:?}", pmf);

        let cdf = CDF::from_pmf(pmf.clone());
        println!("{:?}", cdf);
        for &(value, prob) in pmf.iter().skip(2) {
            assert_ulps_eq!(prob, cdf.get_pmf(&value).unwrap(), epsilon = 0.0000000000001);
        }
        assert_relative_eq!(cdf.total_prob(), 1.0f64.ln());
        assert_relative_eq!(cdf.get(&1.0).unwrap(), 0.3f64.ln(), epsilon = 0.00000001);
    }
}
<commit_msg>Start from lower bound.<commit_after>// Copyright 2016 Johannes Köster.
// Licensed under the MIT license (http://opensource.org/licenses/MIT)
// This file may not be copied, modified, or distributed
// except according to those terms.

use std::f64;
use std::iter;
use std::slice;

use num::traits::{cast, NumCast};
use itertools::Itertools;

use bio::stats::logprobs::{self, LogProb};

/// Implementation of a cumulative distribution function.
#[derive(Debug, Clone)]
pub struct CDF<T: PartialOrd> {
    inner: Vec<(T, LogProb)>
}

impl<T: PartialOrd> CDF<T> {
    /// Create CDF from given probability mass function (PMF). The PMF may contain duplicate values
    /// the probabilities of which are summed during generation of the CDF.
    pub fn from_pmf(mut entries: Vec<(T, LogProb)>) -> Self {
        entries.sort_by(|&(ref a, _), &(ref b, _)| a.partial_cmp(b).unwrap());
        let mut inner: Vec<(T, LogProb)> = Vec::new();
        for mut e in entries.into_iter() {
            let p = logprobs::add(inner.last().map_or(f64::NEG_INFINITY, |e| e.1), e.1);
            if !inner.is_empty() && inner.last().unwrap().0 == e.0 {
                inner.last_mut().unwrap().1 = p;
            }
            else {
                e.1 = p;
                inner.push(e);
            }
        }
        let mut cdf = CDF {
            inner: inner
        };

        if relative_eq!(cdf.total_prob(), 0.0) && cdf.total_prob() > 0.0 {
            cdf.inner.last_mut().unwrap().1 = 0.0;
        }

        cdf
    }

    /// Create CDF from iterator. This can be used to replace the values of a CDF.
    pub fn from_cdf<I: Iterator<Item = (T, LogProb)>>(entries: I) -> Self {
        CDF { inner: entries.collect_vec() }
    }

    pub fn reduce(self) -> Self {
        let mut inner = Vec::new();
        let mut last = f64::NEG_INFINITY;
        for e in self.inner.into_iter() {
            if last != e.1 {
                last = e.1;
                inner.push(e);
            }
        }
        CDF { inner: inner }
    }

    pub fn sample(mut self, n: usize) -> Self {
        if self.inner.len() <= n {
            self
        }
        else {
            let s = self.inner.len() / (n - 1);
            let last = self.inner.pop().unwrap();
            let mut inner = self.inner.into_iter().step(s).collect_vec();
            inner.push(last);
            CDF {
                inner: inner
            }
        }
    }

    pub fn iter(&self) -> slice::Iter<(T, f64)>{
        self.inner.iter()
    }

    pub fn iter_pmf<'a>(&'a self) -> CDFPMFIter<'a, T> {
        fn cdf_to_pmf<'a, G>(last_prob: &mut LogProb, e: &'a (G, LogProb)) -> Option<(&'a G, LogProb)> {
            let &(ref value, cdf_prob) = e;
            let prob = logprobs::sub(cdf_prob, *last_prob);
            *last_prob = cdf_prob;
            Some((value, prob))
        }
        self.inner.iter().scan(f64::NEG_INFINITY, cdf_to_pmf)
    }

    /// Get cumulative probability for a given value. If the value is not present,
    /// return the probability of the previous value.
    pub fn get(&self, value: &T) -> Option<LogProb> {
        if self.inner.is_empty() {
            None
        }
        else {
            Some(match self.inner.binary_search_by(|e| e.0.partial_cmp(value).unwrap()) {
                Ok(i) => self.inner[i].1,
                Err(i) => if i > 0 { self.inner[i - 1].1 } else { f64::NEG_INFINITY }
            })
        }
    }

    pub fn get_pmf(&self, value: &T) -> Option<LogProb> {
        if self.inner.is_empty() {
            None
        }
        else {
            Some(match self.inner.binary_search_by(|e| e.0.partial_cmp(value).unwrap()) {
                Ok(i) => if i > 0 { logprobs::sub(self.inner[i].1, self.inner[i - 1].1) } else { self.inner[0].1 },
                Err(i) => if i > 0 { self.inner[i - 1].1 } else { f64::NEG_INFINITY }
            })
        }
    }

    pub fn total_prob(&self) -> LogProb {
        let &(_, prob) = self.inner.last().unwrap();
        prob
    }

    /// Return maximum a posteriori probability estimate (MAP).
    pub fn map(&self) -> &T {
        let mut max = self.iter_pmf().next().unwrap();
        for e in self.iter_pmf() {
            if e.1 >= max.1 {
                max = e;
            }
        }
        &max.0
    }

    /// Return the 95% credible interval.
    pub fn credible_interval(&self) -> (&T, &T) {
        let lower = self.inner.binary_search_by(|&(_, p)| p.partial_cmp(&0.025f64.ln()).unwrap()).unwrap_or_else(|i| if i > 0 { i - 1 } else { 0 });
        let lower_p = self.inner[lower].1;
        let mut upper = self.inner[lower + 1..].binary_search_by(|&(_, p)| logprobs::sub(p, lower_p).partial_cmp(&0.95f64.ln()).unwrap()).unwrap_or_else(|i| i);
        if upper == self.inner.len() {
            upper -= 1;
        }

        (&self.inner[lower].0, &self.inner[upper].0)
    }

    pub fn len(&self) -> usize {
        self.inner.len()
    }
}

impl<T: NumCast + Clone + PartialOrd> CDF<T> {
    pub fn expected_value(&self) -> f64 {
        self.iter_pmf().map(|(value, prob)| {
            cast::<T, f64>(value.clone()).unwrap() * prob.exp()
        }).fold(0.0f64, |s, e| s + e)
    }

    pub fn variance(&self) -> f64 {
        let ev = self.expected_value();
        self.iter_pmf().map(|(value, prob)| {
                (cast::<T, f64>(value.clone()).unwrap() - ev).powi(2) * prob.exp()
        }).fold(0.0, |s, e| s + e)
    }

    pub fn standard_deviation(&self) -> f64 {
        self.variance().sqrt()
    }
}

pub type CDFPMFIter<'a, T> = iter::Scan<slice::Iter<'a, (T, LogProb)>, LogProb, fn(&mut LogProb, &'a (T, LogProb)) -> Option<(&'a T, LogProb)>>;

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

    #[test]
    fn test_cdf() {
        let mut pmf = vec![(0.0, 0.1f64.ln())];
        for i in 0..9 {
            pmf.push((i as f64, 0.1f64.ln()));
        }
        println!("{:?}", pmf);

        let cdf = CDF::from_pmf(pmf.clone());
        println!("{:?}", cdf);
        for &(value, prob) in pmf.iter().skip(2) {
            assert_ulps_eq!(prob, cdf.get_pmf(&value).unwrap(), epsilon = 0.0000000000001);
        }
        assert_relative_eq!(cdf.total_prob(), 1.0f64.ln());
        assert_relative_eq!(cdf.get(&1.0).unwrap(), 0.3f64.ln(), epsilon = 0.00000001);
    }
}
<|endoftext|>


<commit_before>// A microframework for Rust.
// Copyright (c) 2014 by Shipeng Feng.
// Licensed under the BSD License, see LICENSE for more details.

//! Pencil is a microframework for Rust inspired by [Flask](http://flask.pocoo.org/).
//!
//! # Installation
//!
//! This crate is called `pencil` and you can depend on it via cargo:
//!
//! ```ini
//! [dependencies.pencil]
//! git = "https://github.com/fengsp/pencil.git"
//! ```
//!
//! # Quickstart
//!
//! A short introduction to Pencil.
//!
//! ## A Minimal Application
//!
//! A minimal Pencil application looks something like this:
//!
//! ```rust,no_run
//! extern crate pencil;
//!
//! use pencil::Pencil;
//! use pencil::{Request, PencilResult, PenString};
//!
//!
//! fn hello(_: Request) -> PencilResult {
//!     Ok(PenString(String::from_str("Hello World!")))
//! }
//!
//!
//! fn main() {
//!     let mut app = Pencil::new("/web/hello");
//!     app.route("/", &["GET"], "hello", hello);
//!     app.run();
//! }
//! ```

#![feature(core, io, collections, old_io, fs, old_path, env)]

#![allow(unused_attributes)]
#![crate_name = "pencil"]
#![crate_type = "lib"]
#![doc(html_logo_url = "https://raw.githubusercontent.com/fengsp/pencil/master/logo/pencil.png",
       html_favicon_url = "https://raw.githubusercontent.com/fengsp/pencil/master/logo/favicon.ico",
       html_root_url = "http://fengsp.github.io/pencil/")]

#![deny(non_camel_case_types)]

#[macro_use]
extern crate log;
extern crate core;
extern crate hyper;
extern crate "rustc-serialize" as serialize;
extern crate regex;
extern crate url;

/* public api */
pub use app::Pencil;
pub use types::{
    PencilValue,
        PenString,
        PenResponse,
    PencilError,
        PenHTTPError,
        PenUserError,
    UserError,
    PencilResult,
    ViewArgs,
    ViewFunc,
    UserErrorHandler,
    HTTPErrorHandler,
    BeforeRequestFunc,
    AfterRequestFunc,
    TeardownRequestFunc,
};
pub use datastructures::{
    MultiDict,
};
pub use wrappers::{
    Request,
    Response,
};
pub use json::jsonify;
pub use config::{
    Config,
};
pub use helpers::{
    make_response,
    PathBound,
    safe_join,
    abort,
    redirect,
    escape,
    send_file,
    send_from_directory,
};
pub use serving::{
    run_server,
};
pub use errors::{
    HTTPError,
        BadRequest,
        Unauthorized,
        Forbidden,
        NotFound,
        MethodNotAllowed,
        NotAcceptable,
        RequestTimeout,
        Conflict,
        Gone,
        LengthRequired,
        PreconditionFailed,
        RequestEntityTooLarge,
        RequestURITooLarge,
        UnsupportedMediaType,
        RequestedRangeNotSatisfiable,
        ExpectationFailed,
        ImATeapot,
        UnprocessableEntity,
        PreconditionRequired,
        TooManyRequests,
        RequestHeaderFieldsTooLarge,
        InternalServerError,
        NotImplemented,
        BadGateway,
        ServiceUnavailable,
};
pub use testing::PencilClient;
pub use httputils::{
    get_name_by_http_code,
};

mod app;
mod types;
mod datastructures;
mod wrappers;
mod json;
mod config;
mod logging;
mod helpers;
mod serving;
mod errors;
mod routing;
mod testing;
mod httputils;
<commit_msg>Drop useless pub api<commit_after>// A microframework for Rust.
// Copyright (c) 2014 by Shipeng Feng.
// Licensed under the BSD License, see LICENSE for more details.

//! Pencil is a microframework for Rust inspired by [Flask](http://flask.pocoo.org/).
//!
//! # Installation
//!
//! This crate is called `pencil` and you can depend on it via cargo:
//!
//! ```ini
//! [dependencies.pencil]
//! git = "https://github.com/fengsp/pencil.git"
//! ```
//!
//! # Quickstart
//!
//! A short introduction to Pencil.
//!
//! ## A Minimal Application
//!
//! A minimal Pencil application looks something like this:
//!
//! ```rust,no_run
//! extern crate pencil;
//!
//! use pencil::Pencil;
//! use pencil::{Request, PencilResult, PenString};
//!
//!
//! fn hello(_: Request) -> PencilResult {
//!     Ok(PenString(String::from_str("Hello World!")))
//! }
//!
//!
//! fn main() {
//!     let mut app = Pencil::new("/web/hello");
//!     app.route("/", &["GET"], "hello", hello);
//!     app.run();
//! }
//! ```

#![feature(core, io, collections, old_io, fs, old_path, env)]

#![allow(unused_attributes)]
#![crate_name = "pencil"]
#![crate_type = "lib"]
#![doc(html_logo_url = "https://raw.githubusercontent.com/fengsp/pencil/master/logo/pencil.png",
       html_favicon_url = "https://raw.githubusercontent.com/fengsp/pencil/master/logo/favicon.ico",
       html_root_url = "http://fengsp.github.io/pencil/")]

#![deny(non_camel_case_types)]

#[macro_use]
extern crate log;
extern crate core;
extern crate hyper;
extern crate "rustc-serialize" as serialize;
extern crate regex;
extern crate url;

/* public api */
pub use app::Pencil;
pub use types::{
    PencilValue,
        PenString,
        PenResponse,
    PencilError,
        PenHTTPError,
        PenUserError,
    UserError,
    PencilResult,
    ViewArgs,
    ViewFunc,
    UserErrorHandler,
    HTTPErrorHandler,
    BeforeRequestFunc,
    AfterRequestFunc,
    TeardownRequestFunc,
};
pub use datastructures::{
    MultiDict,
};
pub use wrappers::{
    Request,
    Response,
};
pub use json::jsonify;
pub use config::{
    Config,
};
pub use helpers::{
    make_response,
    PathBound,
    safe_join,
    abort,
    redirect,
    escape,
    send_file,
    send_from_directory,
};
pub use serving::{
    run_server,
};
pub use errors::{
    HTTPError,
        BadRequest,
        Unauthorized,
        Forbidden,
        NotFound,
        MethodNotAllowed,
        NotAcceptable,
        RequestTimeout,
        Conflict,
        Gone,
        LengthRequired,
        PreconditionFailed,
        RequestEntityTooLarge,
        RequestURITooLarge,
        UnsupportedMediaType,
        RequestedRangeNotSatisfiable,
        ExpectationFailed,
        ImATeapot,
        UnprocessableEntity,
        PreconditionRequired,
        TooManyRequests,
        RequestHeaderFieldsTooLarge,
        InternalServerError,
        NotImplemented,
        BadGateway,
        ServiceUnavailable,
};
pub use testing::PencilClient;

mod app;
mod types;
mod datastructures;
mod wrappers;
mod json;
mod config;
mod logging;
mod helpers;
mod serving;
mod errors;
mod routing;
mod testing;
mod httputils;
<|endoftext|>