<commit_before>use diesel::expression::dsl::any;
use diesel::{insert, update};
use diesel::pg::PgConnection;
use diesel::prelude::*;
use models::{Author, NewAuthor, NewQuote, Quote};
use rand::distributions::{IndependentSample, Range};
use rand::thread_rng;
use regex::Regex;
use schema::author::table as author_table;
use schema::quote::table as quote_table;
use std::collections::{HashSet, HashMap};
use std::io::{stdin, stdout, Write};
use std::iter::FromIterator;

struct UnlinkedNewQuote<'a> {
    author_name: &'a str,
    note: &'a str,
    text: &'a str,
}

pub fn store_quotes<'a>(dbsession: PgConnection, quotes: &'a Vec<String>, mark_retrieved: bool) {
    use schema::author::dsl::{author, name, id};

    lazy_static! {
        static ref RE: Regex = Regex::new(r#"^"(.*)" - ([\w .]*)(, (.*))?$"#).unwrap();
    }

    let mut new_quote_count = 0;
    let mut new_author_count = 0;
    let mut author_names: HashSet<&str> = HashSet::new();
    let mut unlinked_new_quotes = Vec::with_capacity(quotes.len());

    for string_quote in quotes {
        let group = match RE.captures(&string_quote) {
            Some(g) => g,
            None => panic!("Invalidly formatted quote found: {}", string_quote)
        };

        let quote_text = group.get(1).unwrap().as_str();
        let author_name = group.get(2).unwrap().as_str();
        let quote_note = group.get(4).as_ref().map(|m| m.as_str()).unwrap_or("");

        author_names.insert(author_name);

        let unlinked_new_quote = UnlinkedNewQuote {
            text: quote_text,
            note: quote_note,
            author_name: author_name,
        };

        unlinked_new_quotes.push(unlinked_new_quote);

        new_quote_count += 1;
    }

    let existing_authors: Vec<(String, _)> = author.filter(name.eq(any(Vec::from_iter(author_names))))
                                                   .select((name, id))
                                                   .load(&dbsession)
                                                   .expect("Error loading authors");

    let mut author_id_by_name = HashMap::new();

    for (author_name, quote_author_id) in existing_authors {
        author_id_by_name.insert(author_name, quote_author_id);
    }

    let mut new_quotes: Vec<NewQuote> = vec![];

    for ul_quote in unlinked_new_quotes {
        let mut update_hash_map = false;
        let author_id = match author_id_by_name.get(ul_quote.author_name) {
            Some(author_id) => *author_id,
            None => {
                println!("Found new author: {}", ul_quote.author_name);
                print!("Add an author note [optional]: ");

                let mut author_note = String::with_capacity(17);

                stdout().flush().expect("Error flushing stdout");
                stdin().read_line(&mut author_note).expect("Error reading from stdin");

                if let Some('\n') = author_note.chars().next_back() {
                    author_note.pop();
                }

                if let Some('\r') = author_note.chars().next_back() {
                    author_note.pop();
                }

                let new_author = NewAuthor {
                    name: ul_quote.author_name,
                    note: &author_note,
                };

                let author_insert: Author = insert(&new_author).into(author_table)
                                                               .get_result(&dbsession)
                                                               .expect("Error inserting new author");
                new_author_count += 1;

                update_hash_map = true;

                author_insert.id
            }
        };

        if update_hash_map {
            author_id_by_name.insert(ul_quote.author_name.into(), author_id);
        }

        let new_quote = NewQuote {
            author_id: author_id,
            note: ul_quote.note,
            retrieved: mark_retrieved,
            text: ul_quote.text,
        };

        new_quotes.push(new_quote);
    }

    insert(&new_quotes).into(quote_table)
                       .execute(&dbsession)
                       .expect("Error saving new quotes");

    println!("Created {} new authors and {} new quotes", new_author_count, new_quote_count);
}

pub enum RetrievalRequest {
    Random,
    RandomRetrieved,
    RandomUnretrievedAndMark(bool),
    FirstUnretrievedAndMark(bool),
    IdAndMark(i64, bool),
}

pub fn retrieve_quote(dbsession: PgConnection, request: RetrievalRequest) -> String {
    use schema::quote::dsl::{quote, id as quote_id, retrieved};

    let mut rng = thread_rng();

    let (quote_dbo, author_dbo) = match request {
        RetrievalRequest::Random => {
            let count: i64 = quote.count()
                                  .first(&dbsession)
                                  .expect("Unable to count quotes in the database");

            let random_quote_id = Range::new(1, count + 1).ind_sample(&mut rng);

            quote_table.inner_join(author_table)
                       .filter(quote_id.eq(random_quote_id))
                       .first(&dbsession)
                       .expect("Could not retrieve quote")
        },
        RetrievalRequest::RandomRetrieved => {
            let count: i64 = quote.count()
                                  .filter(retrieved.eq(true))
                                  .first(&dbsession)
                                  .expect("Unable to count quotes in the database");

            let offset = Range::new(0, count).ind_sample(&mut rng);

            quote_table.inner_join(author_table)
                       .filter(retrieved.eq(true))
                       .offset(offset)
                       .first(&dbsession)
                       .expect("Could not retrieve quote from the database")
        },
        RetrievalRequest::RandomUnretrievedAndMark(mark_retrieved) => {
            let count: i64 = quote.count()
                                  .filter(retrieved.eq(false))
                                  .first(&dbsession)
                                  .expect("Unable to count quotes in the database");

            if count == 0 {
                panic!("No unretrieved quotes found in the database"); // FIXME
            }

            let offset: i64 = Range::new(0, count).ind_sample(&mut rng);

            let (quote_dbo, author_dbo) = quote_table.inner_join(author_table)
                                                     .filter(retrieved.eq(false))
                                                     .offset(offset)
                                                     .first(&dbsession)
                                                     .expect("Unable to retrieve quote from the database");
            if mark_retrieved {
                update(&quote_dbo).set(retrieved.eq(true))
                                  .execute(&dbsession)
                                  .expect("Unable to save changes to quote dbo");
            }

            (quote_dbo, author_dbo)
        },
        RetrievalRequest::FirstUnretrievedAndMark(mark_retrieved) => {
            let (quote_dbo, author_dbo) = quote_table.inner_join(author_table)
                                                     .filter(retrieved.eq(false))
                                                     .first(&dbsession)
                                                     .expect("Unable to retrieve quote from the database");
            if mark_retrieved {
                update(&quote_dbo).set(retrieved.eq(true))
                                  .execute(&dbsession)
                                  .expect("Unable to save changes to quote dbo");
            }

            (quote_dbo, author_dbo)
        },
        RetrievalRequest::IdAndMark(id, mark_retrieved) => {
            // FIXME: Possible issue when value out of range
            let (quote_dbo, author_dbo) = quote_table.inner_join(author_table)
                                                     .filter(quote_id.eq(id))
                                                     .first(&dbsession)
                                                     .expect("Could not retrieve quote");

            if mark_retrieved {
                update(&quote_dbo).set(retrieved.eq(true))
                                  .execute(&dbsession)
                                  .expect("Unable to save changes to quote dbo");
            }

            (quote_dbo, author_dbo)
        }
    };

    format_quote(quote_dbo, author_dbo)
}

fn format_quote(quote: Quote, author: Author) -> String {
    let mut quote_len = quote.text.len() + 5; // 2 quotation marks + 2 spaces + dash

    if quote.note.len() > 0 {
        quote_len += quote.note.len() + 2; // + comma + space
    }

    if author.note.len() > 0 {
        quote_len += author.note.len() + 3; // + space + 2 brackets
    }

    let mut quote_string = String::with_capacity(quote_len);

    quote_string.push('"');
    quote_string.push_str(&quote.text);
    quote_string.push('"');
    quote_string.push_str(" - ");
    quote_string.push_str(&author.name);

    if author.note.len() > 0 {
        quote_string.push_str(" [");
        quote_string.push_str(&author.note);
        quote_string.push(']');
    }

    if quote.note.len() > 0 {
        quote_string.push_str(", ");
        quote_string.push_str(&quote.note);
    }

    quote_string
}
<commit_msg>Fixed first quote ordering issue<commit_after>use diesel::expression::dsl::any;
use diesel::{insert, update};
use diesel::pg::PgConnection;
use diesel::prelude::*;
use models::{Author, NewAuthor, NewQuote, Quote};
use rand::distributions::{IndependentSample, Range};
use rand::thread_rng;
use regex::Regex;
use schema::author::table as author_table;
use schema::quote::table as quote_table;
use std::collections::{HashSet, HashMap};
use std::io::{stdin, stdout, Write};
use std::iter::FromIterator;

struct UnlinkedNewQuote<'a> {
    author_name: &'a str,
    note: &'a str,
    text: &'a str,
}

pub fn store_quotes<'a>(dbsession: PgConnection, quotes: &'a Vec<String>, mark_retrieved: bool) {
    use schema::author::dsl::{author, name, id};

    lazy_static! {
        static ref RE: Regex = Regex::new(r#"^"(.*)" - ([\w .]*)(, (.*))?$"#).unwrap();
    }

    let mut new_quote_count = 0;
    let mut new_author_count = 0;
    let mut author_names: HashSet<&str> = HashSet::new();
    let mut unlinked_new_quotes = Vec::with_capacity(quotes.len());

    for string_quote in quotes {
        let group = match RE.captures(&string_quote) {
            Some(g) => g,
            None => panic!("Invalidly formatted quote found: {}", string_quote)
        };

        let quote_text = group.get(1).unwrap().as_str();
        let author_name = group.get(2).unwrap().as_str();
        let quote_note = group.get(4).as_ref().map(|m| m.as_str()).unwrap_or("");

        author_names.insert(author_name);

        let unlinked_new_quote = UnlinkedNewQuote {
            text: quote_text,
            note: quote_note,
            author_name: author_name,
        };

        unlinked_new_quotes.push(unlinked_new_quote);

        new_quote_count += 1;
    }

    let existing_authors: Vec<(String, _)> = author.filter(name.eq(any(Vec::from_iter(author_names))))
                                                   .select((name, id))
                                                   .load(&dbsession)
                                                   .expect("Error loading authors");

    let mut author_id_by_name = HashMap::new();

    for (author_name, quote_author_id) in existing_authors {
        author_id_by_name.insert(author_name, quote_author_id);
    }

    let mut new_quotes: Vec<NewQuote> = vec![];

    for ul_quote in unlinked_new_quotes {
        let mut update_hash_map = false;
        let author_id = match author_id_by_name.get(ul_quote.author_name) {
            Some(author_id) => *author_id,
            None => {
                println!("Found new author: {}", ul_quote.author_name);
                print!("Add an author note [optional]: ");

                let mut author_note = String::with_capacity(17);

                stdout().flush().expect("Error flushing stdout");
                stdin().read_line(&mut author_note).expect("Error reading from stdin");

                if let Some('\n') = author_note.chars().next_back() {
                    author_note.pop();
                }

                if let Some('\r') = author_note.chars().next_back() {
                    author_note.pop();
                }

                let new_author = NewAuthor {
                    name: ul_quote.author_name,
                    note: &author_note,
                };

                let author_insert: Author = insert(&new_author).into(author_table)
                                                               .get_result(&dbsession)
                                                               .expect("Error inserting new author");
                new_author_count += 1;

                update_hash_map = true;

                author_insert.id
            }
        };

        if update_hash_map {
            author_id_by_name.insert(ul_quote.author_name.into(), author_id);
        }

        let new_quote = NewQuote {
            author_id: author_id,
            note: ul_quote.note,
            retrieved: mark_retrieved,
            text: ul_quote.text,
        };

        new_quotes.push(new_quote);
    }

    insert(&new_quotes).into(quote_table)
                       .execute(&dbsession)
                       .expect("Error saving new quotes");

    println!("Created {} new authors and {} new quotes", new_author_count, new_quote_count);
}

pub enum RetrievalRequest {
    Random,
    RandomRetrieved,
    RandomUnretrievedAndMark(bool),
    FirstUnretrievedAndMark(bool),
    IdAndMark(i64, bool),
}

pub fn retrieve_quote(dbsession: PgConnection, request: RetrievalRequest) -> String {
    use schema::quote::dsl::{quote, id as quote_id, retrieved};

    let mut rng = thread_rng();

    let (quote_dbo, author_dbo) = match request {
        RetrievalRequest::Random => {
            let count: i64 = quote.count()
                                  .first(&dbsession)
                                  .expect("Unable to count quotes in the database");

            let random_quote_id = Range::new(1, count + 1).ind_sample(&mut rng);

            quote_table.inner_join(author_table)
                       .filter(quote_id.eq(random_quote_id))
                       .first(&dbsession)
                       .expect("Could not retrieve quote")
        },
        RetrievalRequest::RandomRetrieved => {
            let count: i64 = quote.count()
                                  .filter(retrieved.eq(true))
                                  .first(&dbsession)
                                  .expect("Unable to count quotes in the database");

            let offset = Range::new(0, count).ind_sample(&mut rng);

            quote_table.inner_join(author_table)
                       .filter(retrieved.eq(true))
                       .offset(offset)
                       .first(&dbsession)
                       .expect("Could not retrieve quote from the database")
        },
        RetrievalRequest::RandomUnretrievedAndMark(mark_retrieved) => {
            let count: i64 = quote.count()
                                  .filter(retrieved.eq(false))
                                  .first(&dbsession)
                                  .expect("Unable to count quotes in the database");

            if count == 0 {
                panic!("No unretrieved quotes found in the database"); // FIXME
            }

            let offset: i64 = Range::new(0, count).ind_sample(&mut rng);

            let (quote_dbo, author_dbo) = quote_table.inner_join(author_table)
                                                     .filter(retrieved.eq(false))
                                                     .offset(offset)
                                                     .first(&dbsession)
                                                     .expect("Unable to retrieve quote from the database");
            if mark_retrieved {
                update(&quote_dbo).set(retrieved.eq(true))
                                  .execute(&dbsession)
                                  .expect("Unable to save changes to quote dbo");
            }

            (quote_dbo, author_dbo)
        },
        RetrievalRequest::FirstUnretrievedAndMark(mark_retrieved) => {
            let (quote_dbo, author_dbo) = quote_table.inner_join(author_table)
                                                     .filter(retrieved.eq(false))
                                                     .order(quote_id)
                                                     .first(&dbsession)
                                                     .expect("Unable to retrieve quote from the database");
            if mark_retrieved {
                update(&quote_dbo).set(retrieved.eq(true))
                                  .execute(&dbsession)
                                  .expect("Unable to save changes to quote dbo");
            }

            (quote_dbo, author_dbo)
        },
        RetrievalRequest::IdAndMark(id, mark_retrieved) => {
            // FIXME: Possible issue when value out of range
            let (quote_dbo, author_dbo) = quote_table.inner_join(author_table)
                                                     .filter(quote_id.eq(id))
                                                     .first(&dbsession)
                                                     .expect("Could not retrieve quote");

            if mark_retrieved {
                update(&quote_dbo).set(retrieved.eq(true))
                                  .execute(&dbsession)
                                  .expect("Unable to save changes to quote dbo");
            }

            (quote_dbo, author_dbo)
        }
    };

    format_quote(quote_dbo, author_dbo)
}

fn format_quote(quote: Quote, author: Author) -> String {
    let mut quote_len = quote.text.len() + 5; // 2 quotation marks + 2 spaces + dash

    if quote.note.len() > 0 {
        quote_len += quote.note.len() + 2; // + comma + space
    }

    if author.note.len() > 0 {
        quote_len += author.note.len() + 3; // + space + 2 brackets
    }

    let mut quote_string = String::with_capacity(quote_len);

    quote_string.push('"');
    quote_string.push_str(&quote.text);
    quote_string.push('"');
    quote_string.push_str(" - ");
    quote_string.push_str(&author.name);

    if author.note.len() > 0 {
        quote_string.push_str(" [");
        quote_string.push_str(&author.note);
        quote_string.push(']');
    }

    if quote.note.len() > 0 {
        quote_string.push_str(", ");
        quote_string.push_str(&quote.note);
    }

    quote_string
}
<|endoftext|>


<commit_before>#![feature(test)]

extern crate test;
use test::Bencher;
extern crate lonlat_bng;
use lonlat_bng::convert_to_bng_threaded_vec;

extern crate rand;
use rand::distributions::{IndependentSample, Range};

#[bench]
fn bench_threads(b: &mut Bencher) {
    let num_coords = 100000;
    let between_lon = Range::new(-6.379880, 1.768960);
    let between_lat = Range::new(49.871159, 55.811741);
    let mut rng = rand::thread_rng();

    b.iter(||{
        let mut lon_vec = vec![between_lon.ind_sample(&mut rng); num_coords];
        let mut lat_vec = vec![between_lat.ind_sample(&mut rng); num_coords];
        convert_to_bng_threaded_vec(
            &mut lon_vec,
            &mut lat_vec
        );
    });
}
<commit_msg>Use a smaller number of coords in benchmark<commit_after>#![feature(test)]

extern crate test;
use test::Bencher;
extern crate lonlat_bng;
use lonlat_bng::convert_to_bng_threaded_vec;

extern crate rand;
use rand::distributions::{IndependentSample, Range};

#[bench]
fn bench_threads(b: &mut Bencher) {
    let num_coords = 10000;
    let between_lon = Range::new(-6.379880, 1.768960);
    let between_lat = Range::new(49.871159, 55.811741);
    let mut rng = rand::thread_rng();

    b.iter(||{
        let mut lon_vec = vec![between_lon.ind_sample(&mut rng); num_coords];
        let mut lat_vec = vec![between_lat.ind_sample(&mut rng); num_coords];
        convert_to_bng_threaded_vec(
            &mut lon_vec,
            &mut lat_vec
        );
    });
}
<|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/. */

//! Specified types for text properties.

use cssparser::Parser;
use parser::{Parse, ParserContext};
use selectors::parser::SelectorParseError;
use std::ascii::AsciiExt;
use style_traits::ParseError;
use values::computed::{Context, ToComputedValue};
use values::computed::text::LineHeight as ComputedLineHeight;
use values::generics::text::InitialLetter as GenericInitialLetter;
use values::generics::text::LineHeight as GenericLineHeight;
use values::generics::text::Spacing;
use values::specified::{AllowQuirks, Integer, Number};
use values::specified::length::{FontRelativeLength, Length, LengthOrPercentage, NoCalcLength};

/// A specified type for the `initial-letter` property.
pub type InitialLetter = GenericInitialLetter<Number, Integer>;

/// A specified value for the `letter-spacing` property.
pub type LetterSpacing = Spacing<Length>;

/// A specified value for the `word-spacing` property.
pub type WordSpacing = Spacing<LengthOrPercentage>;

/// A specified value for the `line-height` property.
pub type LineHeight = GenericLineHeight<Number, LengthOrPercentage>;

impl Parse for InitialLetter {
    fn parse<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>) -> Result<Self, ParseError<'i>> {
        if input.try(|i| i.expect_ident_matching("normal")).is_ok() {
            return Ok(GenericInitialLetter::Normal);
        }
        let size = Number::parse_at_least_one(context, input)?;
        let sink = input.try(|i| Integer::parse_positive(context, i)).ok();
        Ok(GenericInitialLetter::Specified(size, sink))
    }
}

impl Parse for LetterSpacing {
    fn parse<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>) -> Result<Self, ParseError<'i>> {
        Spacing::parse_with(context, input, |c, i| {
            Length::parse_quirky(c, i, AllowQuirks::Yes)
        })
    }
}

impl Parse for WordSpacing {
    fn parse<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>) -> Result<Self, ParseError<'i>> {
        Spacing::parse_with(context, input, |c, i| {
            LengthOrPercentage::parse_quirky(c, i, AllowQuirks::Yes)
        })
    }
}

impl Parse for LineHeight {
    fn parse<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>) -> Result<Self, ParseError<'i>> {
        if let Ok(number) = input.try(|i| Number::parse_non_negative(context, i)) {
            return Ok(GenericLineHeight::Number(number))
        }
        if let Ok(lop) = input.try(|i| LengthOrPercentage::parse_non_negative(context, i)) {
            return Ok(GenericLineHeight::Length(lop))
        }
        let ident = input.expect_ident()?;
        match ident {
            ref ident if ident.eq_ignore_ascii_case("normal") => {
                Ok(GenericLineHeight::Normal)
            },
            #[cfg(feature = "gecko")]
            ref ident if ident.eq_ignore_ascii_case("-moz-block-height") => {
                Ok(GenericLineHeight::MozBlockHeight)
            },
            ident => Err(SelectorParseError::UnexpectedIdent(ident.clone()).into()),
        }
    }
}

impl ToComputedValue for LineHeight {
    type ComputedValue = ComputedLineHeight;

    #[inline]
    fn to_computed_value(&self, context: &Context) -> Self::ComputedValue {
        match *self {
            GenericLineHeight::Normal => {
                GenericLineHeight::Normal
            },
            #[cfg(feature = "gecko")]
            GenericLineHeight::MozBlockHeight => {
                GenericLineHeight::MozBlockHeight
            },
            GenericLineHeight::Number(number) => {
                GenericLineHeight::Number(number.to_computed_value(context))
            },
            GenericLineHeight::Length(LengthOrPercentage::Length(ref length)) => {
                GenericLineHeight::Length(length.to_computed_value(context))
            },
            GenericLineHeight::Length(LengthOrPercentage::Percentage(p)) => {
                let font_relative_length =
                    Length::NoCalc(NoCalcLength::FontRelative(FontRelativeLength::Em(p.0)));
                GenericLineHeight::Length(font_relative_length.to_computed_value(context))
            },
            GenericLineHeight::Length(LengthOrPercentage::Calc(ref calc)) => {
                let computed_calc = calc.to_computed_value(context);
                let font_relative_length =
                    Length::NoCalc(NoCalcLength::FontRelative(FontRelativeLength::Em(computed_calc.percentage())));
                let absolute_length = computed_calc.unclamped_length();
                let computed_length = computed_calc.clamping_mode.clamp(
                    absolute_length + font_relative_length.to_computed_value(context)
                );
                GenericLineHeight::Length(computed_length)
            },
        }
    }

    #[inline]
    fn from_computed_value(computed: &Self::ComputedValue) -> Self {
        match *computed {
            GenericLineHeight::Normal => {
                GenericLineHeight::Normal
            },
            #[cfg(feature = "gecko")]
            GenericLineHeight::MozBlockHeight => {
                GenericLineHeight::MozBlockHeight
            },
            GenericLineHeight::Number(ref number) => {
                GenericLineHeight::Number(Number::from_computed_value(number))
            },
            GenericLineHeight::Length(ref length) => {
                GenericLineHeight::Length(LengthOrPercentage::Length(
                    NoCalcLength::from_computed_value(length)
                ))
            }
        }
    }
}
<commit_msg>stylo: Handle text-zoom for line-height<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/. */

//! Specified types for text properties.

use cssparser::Parser;
use parser::{Parse, ParserContext};
use selectors::parser::SelectorParseError;
use std::ascii::AsciiExt;
use style_traits::ParseError;
use values::computed::{Context, ToComputedValue};
use values::computed::text::LineHeight as ComputedLineHeight;
use values::generics::text::InitialLetter as GenericInitialLetter;
use values::generics::text::LineHeight as GenericLineHeight;
use values::generics::text::Spacing;
use values::specified::{AllowQuirks, Integer, Number};
use values::specified::length::{FontRelativeLength, Length, LengthOrPercentage, NoCalcLength};

/// A specified type for the `initial-letter` property.
pub type InitialLetter = GenericInitialLetter<Number, Integer>;

/// A specified value for the `letter-spacing` property.
pub type LetterSpacing = Spacing<Length>;

/// A specified value for the `word-spacing` property.
pub type WordSpacing = Spacing<LengthOrPercentage>;

/// A specified value for the `line-height` property.
pub type LineHeight = GenericLineHeight<Number, LengthOrPercentage>;

impl Parse for InitialLetter {
    fn parse<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>) -> Result<Self, ParseError<'i>> {
        if input.try(|i| i.expect_ident_matching("normal")).is_ok() {
            return Ok(GenericInitialLetter::Normal);
        }
        let size = Number::parse_at_least_one(context, input)?;
        let sink = input.try(|i| Integer::parse_positive(context, i)).ok();
        Ok(GenericInitialLetter::Specified(size, sink))
    }
}

impl Parse for LetterSpacing {
    fn parse<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>) -> Result<Self, ParseError<'i>> {
        Spacing::parse_with(context, input, |c, i| {
            Length::parse_quirky(c, i, AllowQuirks::Yes)
        })
    }
}

impl Parse for WordSpacing {
    fn parse<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>) -> Result<Self, ParseError<'i>> {
        Spacing::parse_with(context, input, |c, i| {
            LengthOrPercentage::parse_quirky(c, i, AllowQuirks::Yes)
        })
    }
}

impl Parse for LineHeight {
    fn parse<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>) -> Result<Self, ParseError<'i>> {
        if let Ok(number) = input.try(|i| Number::parse_non_negative(context, i)) {
            return Ok(GenericLineHeight::Number(number))
        }
        if let Ok(lop) = input.try(|i| LengthOrPercentage::parse_non_negative(context, i)) {
            return Ok(GenericLineHeight::Length(lop))
        }
        let ident = input.expect_ident()?;
        match ident {
            ref ident if ident.eq_ignore_ascii_case("normal") => {
                Ok(GenericLineHeight::Normal)
            },
            #[cfg(feature = "gecko")]
            ref ident if ident.eq_ignore_ascii_case("-moz-block-height") => {
                Ok(GenericLineHeight::MozBlockHeight)
            },
            ident => Err(SelectorParseError::UnexpectedIdent(ident.clone()).into()),
        }
    }
}

impl ToComputedValue for LineHeight {
    type ComputedValue = ComputedLineHeight;

    #[inline]
    fn to_computed_value(&self, context: &Context) -> Self::ComputedValue {
        match *self {
            GenericLineHeight::Normal => {
                GenericLineHeight::Normal
            },
            #[cfg(feature = "gecko")]
            GenericLineHeight::MozBlockHeight => {
                GenericLineHeight::MozBlockHeight
            },
            GenericLineHeight::Number(number) => {
                GenericLineHeight::Number(number.to_computed_value(context))
            },
            GenericLineHeight::Length(LengthOrPercentage::Length(ref length)) => {
                GenericLineHeight::Length(context.maybe_zoom_text(length.to_computed_value(context)))
            },
            GenericLineHeight::Length(LengthOrPercentage::Percentage(p)) => {
                let font_relative_length =
                    Length::NoCalc(NoCalcLength::FontRelative(FontRelativeLength::Em(p.0)));
                GenericLineHeight::Length(font_relative_length.to_computed_value(context))
            },
            GenericLineHeight::Length(LengthOrPercentage::Calc(ref calc)) => {
                let computed_calc = calc.to_computed_value_zoomed(context);
                let font_relative_length =
                    Length::NoCalc(NoCalcLength::FontRelative(FontRelativeLength::Em(computed_calc.percentage())));
                let absolute_length = computed_calc.unclamped_length();
                let computed_length = computed_calc.clamping_mode.clamp(
                    absolute_length + font_relative_length.to_computed_value(context)
                );
                GenericLineHeight::Length(computed_length)
            },
        }
    }

    #[inline]
    fn from_computed_value(computed: &Self::ComputedValue) -> Self {
        match *computed {
            GenericLineHeight::Normal => {
                GenericLineHeight::Normal
            },
            #[cfg(feature = "gecko")]
            GenericLineHeight::MozBlockHeight => {
                GenericLineHeight::MozBlockHeight
            },
            GenericLineHeight::Number(ref number) => {
                GenericLineHeight::Number(Number::from_computed_value(number))
            },
            GenericLineHeight::Length(ref length) => {
                GenericLineHeight::Length(LengthOrPercentage::Length(
                    NoCalcLength::from_computed_value(length)
                ))
            }
        }
    }
}
<|endoftext|>


<commit_before>use crate::gen::code_writer::CodeWriter;
use crate::gen::field::elem::FieldElem;
use crate::gen::field::elem::FieldElemEnum;
use crate::gen::field::option_kind::OptionKind;
use crate::gen::field::repeated::RepeatedField;
use crate::gen::field::repeated::RepeatedFieldKind;
use crate::gen::field::singular::SingularField;
use crate::gen::field::singular::SingularFieldFlag;
use crate::gen::field::FieldGen;
use crate::gen::field::FieldKind;
use crate::gen::field::MapField;
use crate::gen::inside::protobuf_crate_path;
use crate::gen::oneof::OneofField;
use crate::gen::rust_types_values::RustType;
use crate::gen::scope::WithScope;

struct AccessorFn {
    name: String,
    // function type params after first underscore
    type_params: Vec<String>,
    callback_params: Vec<String>,
}

impl AccessorFn {
    fn sig(&self) -> String {
        let mut s = self.name.clone();
        s.push_str("::<_");
        for p in &self.type_params {
            s.push_str(", ");
            s.push_str(&p);
        }
        s.push_str(">");
        s
    }
}

impl FieldGen<'_> {
    fn make_accessor_fns_lambda(&self) -> Vec<String> {
        let message = self.proto_field.message.rust_name();
        vec![
            format!("|m: &{}| {{ &m.{} }}", message, self.rust_name),
            format!("|m: &mut {}| {{ &mut m.{} }}", message, self.rust_name),
        ]
    }

    fn make_accessor_fns_has_get_set(&self) -> Vec<String> {
        let message = self.proto_field.message.rust_name();
        vec![
            format!("{}::{}", message, self.has_name()),
            format!("{}::{}", message, self.rust_name),
            format!("{}::{}", message, self.set_name()),
        ]
    }

    fn make_accessor_fns_has_get_mut_set(&self) -> Vec<String> {
        let message = self.proto_field.message.rust_name();
        vec![
            format!("{}::{}", message, self.has_name()),
            format!("{}::{}", message, self.rust_name),
            format!("{}::{}", message, self.mut_name()),
            format!("{}::{}", message, self.set_name()),
        ]
    }

    fn accessor_fn_map(&self, map_field: &MapField) -> AccessorFn {
        let MapField { .. } = map_field;
        AccessorFn {
            name: "make_map_simpler_accessor".to_owned(),
            type_params: vec![format!("_"), format!("_")],
            callback_params: self.make_accessor_fns_lambda(),
        }
    }

    fn accessor_fn_repeated(&self, repeated_field: &RepeatedField) -> AccessorFn {
        let RepeatedField { .. } = repeated_field;
        let name = match repeated_field.kind() {
            RepeatedFieldKind::Vec => "make_vec_simpler_accessor",
        };
        AccessorFn {
            name: name.to_owned(),
            type_params: vec![format!("_")],
            callback_params: self.make_accessor_fns_lambda(),
        }
    }

    fn accessor_fn_oneof_enum(&self, oneof: &OneofField, en: &FieldElemEnum) -> AccessorFn {
        let message = self.proto_field.message.rust_name();

        let variant_path = oneof.variant_path(&self.proto_field.message.scope.rust_path_to_file());

        let getter = CodeWriter::with_no_error(|w| {
            w.expr_block(
                &format!(
                    "|message: &{}| match &message.{}",
                    message, oneof.oneof_field_name
                ),
                |w| {
                    w.case_expr(
                        &format!("::std::option::Option::Some({}(e))", variant_path),
                        "::std::option::Option::Some(*e)",
                    );
                    w.case_expr("_", "::std::option::Option::None");
                },
            );
        });

        let setter = CodeWriter::with_no_error(|w| {
            w.expr_block(
                &format!(
                    "|message: &mut {}, e: {}::EnumOrUnknown<{}>|",
                    message,
                    protobuf_crate_path(&self.customize),
                    en.enum_rust_type(&self.file_and_mod())
                        .to_code(&self.customize)
                ),
                |w| {
                    w.write_line(&format!(
                        "message.{} = ::std::option::Option::Some({}(e));",
                        oneof.oneof_field_name, variant_path
                    ));
                },
            )
        });

        let default = self.xxx_default_value_rust();

        AccessorFn {
            name: "make_oneof_enum_accessors".to_owned(),
            type_params: vec![format!("_")],
            callback_params: vec![getter, setter, default],
        }
    }

    fn accessor_fn_singular_without_flag(&self, _elem: &FieldElem) -> AccessorFn {
        AccessorFn {
            name: "make_simpler_field_accessor".to_owned(),
            type_params: vec![format!("_")],
            callback_params: self.make_accessor_fns_lambda(),
        }
    }

    fn accessor_fn_singular_with_flag(
        &self,
        elem: &FieldElem,
        _option_kind: OptionKind,
    ) -> AccessorFn {
        match elem {
            FieldElem::Message(m) => AccessorFn {
                name: "make_message_field_accessor".to_owned(),
                type_params: vec![format!("{}", m.rust_name_relative(&self.file_and_mod()))],
                callback_params: self.make_accessor_fns_lambda(),
            },
            FieldElem::Primitive(..) | FieldElem::Enum(..) => AccessorFn {
                name: "make_option_accessor".to_owned(),
                type_params: vec!["_".to_owned()],
                callback_params: self.make_accessor_fns_lambda(),
            },
            FieldElem::Group => {
                unreachable!("no accessor for group field");
            }
        }
    }

    fn accessor_fn_oneof(&self, oneof: &OneofField) -> AccessorFn {
        let OneofField { ref elem, .. } = oneof;
        // TODO: uses old style

        let reference = self
            .proto_field
            .message
            .scope
            .file_and_mod(self.customize.clone());

        if let FieldElem::Enum(en) = &oneof.elem {
            return self.accessor_fn_oneof_enum(oneof, en);
        }

        if elem.is_copy() {
            return AccessorFn {
                name: "make_oneof_copy_has_get_set_simpler_accessors".to_owned(),
                type_params: vec![format!("_")],
                callback_params: self.make_accessor_fns_has_get_set(),
            };
        }

        if let RustType::Message(name) = elem.rust_storage_elem_type(&reference) {
            return AccessorFn {
                name: "make_oneof_message_has_get_mut_set_accessor".to_owned(),
                type_params: vec![format!("{}", name)],
                callback_params: self.make_accessor_fns_has_get_mut_set(),
            };
        }

        // string or bytes
        AccessorFn {
            name: "make_oneof_deref_has_get_set_simpler_accessor".to_owned(),
            type_params: vec![format!("_")],
            callback_params: self.make_accessor_fns_has_get_set(),
        }
    }

    fn accessor_fn(&self) -> AccessorFn {
        match self.kind {
            FieldKind::Repeated(ref repeated_field) => self.accessor_fn_repeated(repeated_field),
            FieldKind::Map(ref map_field) => self.accessor_fn_map(map_field),
            FieldKind::Singular(SingularField {
                ref elem,
                flag: SingularFieldFlag::WithoutFlag,
            }) => self.accessor_fn_singular_without_flag(elem),
            FieldKind::Singular(SingularField {
                ref elem,
                flag: SingularFieldFlag::WithFlag { option_kind, .. },
            }) => self.accessor_fn_singular_with_flag(elem, option_kind),
            FieldKind::Oneof(ref oneof) => self.accessor_fn_oneof(oneof),
        }
    }

    pub fn write_push_accessor(&self, fields_var: &str, w: &mut CodeWriter) {
        let accessor_fn = self.accessor_fn();
        w.write_line(&format!(
            "{}.push({}::reflect::rt::v2::{}(",
            fields_var,
            protobuf_crate_path(&self.customize),
            accessor_fn.sig()
        ));
        w.indented(|w| {
            w.write_line(&format!("\"{}\",", self.proto_field.name()));
            for callback in &accessor_fn.callback_params {
                let callback_lines: Vec<&str> = callback.lines().collect();
                for (i, callback_line) in callback_lines.iter().enumerate() {
                    let comma = if i == callback_lines.len() - 1 {
                        ","
                    } else {
                        ""
                    };
                    w.write_line(&format!("{}{}", callback_line, comma));
                }
            }
        });
        w.write_line("));");
    }
}
<commit_msg>Outdated todo<commit_after>use crate::gen::code_writer::CodeWriter;
use crate::gen::field::elem::FieldElem;
use crate::gen::field::elem::FieldElemEnum;
use crate::gen::field::option_kind::OptionKind;
use crate::gen::field::repeated::RepeatedField;
use crate::gen::field::repeated::RepeatedFieldKind;
use crate::gen::field::singular::SingularField;
use crate::gen::field::singular::SingularFieldFlag;
use crate::gen::field::FieldGen;
use crate::gen::field::FieldKind;
use crate::gen::field::MapField;
use crate::gen::inside::protobuf_crate_path;
use crate::gen::oneof::OneofField;
use crate::gen::rust_types_values::RustType;
use crate::gen::scope::WithScope;

struct AccessorFn {
    name: String,
    // function type params after first underscore
    type_params: Vec<String>,
    callback_params: Vec<String>,
}

impl AccessorFn {
    fn sig(&self) -> String {
        let mut s = self.name.clone();
        s.push_str("::<_");
        for p in &self.type_params {
            s.push_str(", ");
            s.push_str(&p);
        }
        s.push_str(">");
        s
    }
}

impl FieldGen<'_> {
    fn make_accessor_fns_lambda(&self) -> Vec<String> {
        let message = self.proto_field.message.rust_name();
        vec![
            format!("|m: &{}| {{ &m.{} }}", message, self.rust_name),
            format!("|m: &mut {}| {{ &mut m.{} }}", message, self.rust_name),
        ]
    }

    fn make_accessor_fns_has_get_set(&self) -> Vec<String> {
        let message = self.proto_field.message.rust_name();
        vec![
            format!("{}::{}", message, self.has_name()),
            format!("{}::{}", message, self.rust_name),
            format!("{}::{}", message, self.set_name()),
        ]
    }

    fn make_accessor_fns_has_get_mut_set(&self) -> Vec<String> {
        let message = self.proto_field.message.rust_name();
        vec![
            format!("{}::{}", message, self.has_name()),
            format!("{}::{}", message, self.rust_name),
            format!("{}::{}", message, self.mut_name()),
            format!("{}::{}", message, self.set_name()),
        ]
    }

    fn accessor_fn_map(&self, map_field: &MapField) -> AccessorFn {
        let MapField { .. } = map_field;
        AccessorFn {
            name: "make_map_simpler_accessor".to_owned(),
            type_params: vec![format!("_"), format!("_")],
            callback_params: self.make_accessor_fns_lambda(),
        }
    }

    fn accessor_fn_repeated(&self, repeated_field: &RepeatedField) -> AccessorFn {
        let RepeatedField { .. } = repeated_field;
        let name = match repeated_field.kind() {
            RepeatedFieldKind::Vec => "make_vec_simpler_accessor",
        };
        AccessorFn {
            name: name.to_owned(),
            type_params: vec![format!("_")],
            callback_params: self.make_accessor_fns_lambda(),
        }
    }

    fn accessor_fn_oneof_enum(&self, oneof: &OneofField, en: &FieldElemEnum) -> AccessorFn {
        let message = self.proto_field.message.rust_name();

        let variant_path = oneof.variant_path(&self.proto_field.message.scope.rust_path_to_file());

        let getter = CodeWriter::with_no_error(|w| {
            w.expr_block(
                &format!(
                    "|message: &{}| match &message.{}",
                    message, oneof.oneof_field_name
                ),
                |w| {
                    w.case_expr(
                        &format!("::std::option::Option::Some({}(e))", variant_path),
                        "::std::option::Option::Some(*e)",
                    );
                    w.case_expr("_", "::std::option::Option::None");
                },
            );
        });

        let setter = CodeWriter::with_no_error(|w| {
            w.expr_block(
                &format!(
                    "|message: &mut {}, e: {}::EnumOrUnknown<{}>|",
                    message,
                    protobuf_crate_path(&self.customize),
                    en.enum_rust_type(&self.file_and_mod())
                        .to_code(&self.customize)
                ),
                |w| {
                    w.write_line(&format!(
                        "message.{} = ::std::option::Option::Some({}(e));",
                        oneof.oneof_field_name, variant_path
                    ));
                },
            )
        });

        let default = self.xxx_default_value_rust();

        AccessorFn {
            name: "make_oneof_enum_accessors".to_owned(),
            type_params: vec![format!("_")],
            callback_params: vec![getter, setter, default],
        }
    }

    fn accessor_fn_singular_without_flag(&self, _elem: &FieldElem) -> AccessorFn {
        AccessorFn {
            name: "make_simpler_field_accessor".to_owned(),
            type_params: vec![format!("_")],
            callback_params: self.make_accessor_fns_lambda(),
        }
    }

    fn accessor_fn_singular_with_flag(
        &self,
        elem: &FieldElem,
        _option_kind: OptionKind,
    ) -> AccessorFn {
        match elem {
            FieldElem::Message(m) => AccessorFn {
                name: "make_message_field_accessor".to_owned(),
                type_params: vec![format!("{}", m.rust_name_relative(&self.file_and_mod()))],
                callback_params: self.make_accessor_fns_lambda(),
            },
            FieldElem::Primitive(..) | FieldElem::Enum(..) => AccessorFn {
                name: "make_option_accessor".to_owned(),
                type_params: vec!["_".to_owned()],
                callback_params: self.make_accessor_fns_lambda(),
            },
            FieldElem::Group => {
                unreachable!("no accessor for group field");
            }
        }
    }

    fn accessor_fn_oneof(&self, oneof: &OneofField) -> AccessorFn {
        let OneofField { ref elem, .. } = oneof;

        let reference = self
            .proto_field
            .message
            .scope
            .file_and_mod(self.customize.clone());

        if let FieldElem::Enum(en) = &oneof.elem {
            return self.accessor_fn_oneof_enum(oneof, en);
        }

        if elem.is_copy() {
            return AccessorFn {
                name: "make_oneof_copy_has_get_set_simpler_accessors".to_owned(),
                type_params: vec![format!("_")],
                callback_params: self.make_accessor_fns_has_get_set(),
            };
        }

        if let RustType::Message(name) = elem.rust_storage_elem_type(&reference) {
            return AccessorFn {
                name: "make_oneof_message_has_get_mut_set_accessor".to_owned(),
                type_params: vec![format!("{}", name)],
                callback_params: self.make_accessor_fns_has_get_mut_set(),
            };
        }

        // string or bytes
        AccessorFn {
            name: "make_oneof_deref_has_get_set_simpler_accessor".to_owned(),
            type_params: vec![format!("_")],
            callback_params: self.make_accessor_fns_has_get_set(),
        }
    }

    fn accessor_fn(&self) -> AccessorFn {
        match self.kind {
            FieldKind::Repeated(ref repeated_field) => self.accessor_fn_repeated(repeated_field),
            FieldKind::Map(ref map_field) => self.accessor_fn_map(map_field),
            FieldKind::Singular(SingularField {
                ref elem,
                flag: SingularFieldFlag::WithoutFlag,
            }) => self.accessor_fn_singular_without_flag(elem),
            FieldKind::Singular(SingularField {
                ref elem,
                flag: SingularFieldFlag::WithFlag { option_kind, .. },
            }) => self.accessor_fn_singular_with_flag(elem, option_kind),
            FieldKind::Oneof(ref oneof) => self.accessor_fn_oneof(oneof),
        }
    }

    pub fn write_push_accessor(&self, fields_var: &str, w: &mut CodeWriter) {
        let accessor_fn = self.accessor_fn();
        w.write_line(&format!(
            "{}.push({}::reflect::rt::v2::{}(",
            fields_var,
            protobuf_crate_path(&self.customize),
            accessor_fn.sig()
        ));
        w.indented(|w| {
            w.write_line(&format!("\"{}\",", self.proto_field.name()));
            for callback in &accessor_fn.callback_params {
                let callback_lines: Vec<&str> = callback.lines().collect();
                for (i, callback_line) in callback_lines.iter().enumerate() {
                    let comma = if i == callback_lines.len() - 1 {
                        ","
                    } else {
                        ""
                    };
                    w.write_line(&format!("{}{}", callback_line, comma));
                }
            }
        });
        w.write_line("));");
    }
}
<|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 dom::bindings::callback::ExceptionHandling::Report;
use dom::bindings::codegen::Bindings::EventBinding::EventMethods;
use dom::bindings::codegen::InheritTypes::{EventTargetCast, NodeCast};
use dom::bindings::js::JS;
use dom::bindings::trace::RootedVec;
use dom::event::{Event, EventPhase};
use dom::eventtarget::{EventTarget, ListenerPhase};
use dom::node::Node;
use dom::virtualmethods::vtable_for;

fn dispatch_to_listeners(event: &Event, target: &EventTarget, chain: &[&EventTarget]) {
    assert!(!event.stop_propagation());
    assert!(!event.stop_immediate());

    let type_ = event.Type();

    /* capturing */
    event.set_phase(EventPhase::Capturing);
    for cur_target in chain.iter().rev() {
        let stopped = match cur_target.get_listeners_for(&type_, ListenerPhase::Capturing) {
            Some(listeners) => {
                event.set_current_target(cur_target);
                for listener in &listeners {
                    // Explicitly drop any exception on the floor.
                    listener.call_or_handle_event(*cur_target, event, Report);

                    if event.stop_immediate() {
                        break;
                    }
                }

                event.stop_propagation()
            }
            None => false
        };

        if stopped {
            break;
        }
    }

    /* at target */
    if !event.stop_propagation() {
        event.set_phase(EventPhase::AtTarget);
        event.set_current_target(target.clone());

        let opt_listeners = target.get_listeners(&type_);
        for listeners in opt_listeners {
            for listener in listeners {
                // Explicitly drop any exception on the floor.
                listener.call_or_handle_event(target, event, Report);

                if event.stop_immediate() {
                    break;
                }
            }
        }
    }

    /* bubbling */
    if event.bubbles() && !event.stop_propagation() {
        event.set_phase(EventPhase::Bubbling);

        for cur_target in chain {
            let stopped = match cur_target.get_listeners_for(&type_, ListenerPhase::Bubbling) {
                Some(listeners) => {
                    event.set_current_target(cur_target);
                    for listener in &listeners {
                        // Explicitly drop any exception on the floor.
                        listener.call_or_handle_event(*cur_target, event, Report);

                        if event.stop_immediate() {
                            break;
                        }
                    }

                    event.stop_propagation()
                }
                None => false
            };
            if stopped {
                break;
            }
        }
    }
}

// See https://dom.spec.whatwg.org/#concept-event-dispatch for the full dispatch algorithm
pub fn dispatch_event(target: &EventTarget, pseudo_target: Option<&EventTarget>,
                      event: &Event) -> bool {
    assert!(!event.dispatching());
    assert!(event.initialized());
    assert_eq!(event.phase(), EventPhase::None);
    assert!(event.GetCurrentTarget().is_none());

    event.set_target(match pseudo_target {
        Some(pseudo_target) => pseudo_target,
        None => target.clone(),
    });

    if event.stop_propagation() {
        return !event.DefaultPrevented();
    }

    event.set_dispatching(true);

    //TODO: no chain if not participating in a tree
    let mut chain: RootedVec<JS<EventTarget>> = RootedVec::new();
    if let Some(target_node) = NodeCast::to_ref(target) {
        for ancestor in target_node.ancestors() {
            let ancestor_target = EventTargetCast::from_ref(ancestor.r());
            chain.push(JS::from_ref(ancestor_target))
        }
    }

    dispatch_to_listeners(event, target, chain.r());

    /* default action */
    let target = event.GetTarget();
    match target {
        Some(ref target) => {
            let node: Option<&Node> = NodeCast::to_ref(target.r());
            match node {
                Some(node) => {
                    let vtable = vtable_for(&node);
                    vtable.handle_event(event);
                }
                None => {}
            }
        }
        None => {}
    }

    event.set_dispatching(false);
    event.set_phase(EventPhase::None);
    event.clear_current_target();

    !event.DefaultPrevented()
}
<commit_msg>Use if-let in dispatch_to_listeners, and simplify break conditions.<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 dom::bindings::callback::ExceptionHandling::Report;
use dom::bindings::codegen::Bindings::EventBinding::EventMethods;
use dom::bindings::codegen::InheritTypes::{EventTargetCast, NodeCast};
use dom::bindings::js::JS;
use dom::bindings::trace::RootedVec;
use dom::event::{Event, EventPhase};
use dom::eventtarget::{EventTarget, ListenerPhase};
use dom::node::Node;
use dom::virtualmethods::vtable_for;

fn dispatch_to_listeners(event: &Event, target: &EventTarget, chain: &[&EventTarget]) {
    assert!(!event.stop_propagation());
    assert!(!event.stop_immediate());

    let type_ = event.Type();

    /* capturing */
    event.set_phase(EventPhase::Capturing);
    for cur_target in chain.iter().rev() {
        if let Some(listeners) = cur_target.get_listeners_for(&type_, ListenerPhase::Capturing) {
            event.set_current_target(cur_target);
            for listener in &listeners {
                // Explicitly drop any exception on the floor.
                listener.call_or_handle_event(*cur_target, event, Report);

                if event.stop_immediate() {
                    break;
                }
            }

            if event.stop_propagation() {
                break;
            }
        }
    }

    /* at target */
    if !event.stop_propagation() {
        event.set_phase(EventPhase::AtTarget);
        event.set_current_target(target.clone());

        if let Some(listeners) = target.get_listeners(&type_) {
            for listener in listeners {
                // Explicitly drop any exception on the floor.
                listener.call_or_handle_event(target, event, Report);

                if event.stop_immediate() {
                    break;
                }
            }
        }
    }

    /* bubbling */
    if event.bubbles() && !event.stop_propagation() {
        event.set_phase(EventPhase::Bubbling);

        for cur_target in chain {
            if let Some(listeners) = cur_target.get_listeners_for(&type_, ListenerPhase::Bubbling) {
                event.set_current_target(cur_target);
                for listener in &listeners {
                    // Explicitly drop any exception on the floor.
                    listener.call_or_handle_event(*cur_target, event, Report);

                    if event.stop_immediate() {
                        break;
                    }
                }

                if event.stop_propagation() {
                    break;
                }
            }
        }
    }
}

// See https://dom.spec.whatwg.org/#concept-event-dispatch for the full dispatch algorithm
pub fn dispatch_event(target: &EventTarget, pseudo_target: Option<&EventTarget>,
                      event: &Event) -> bool {
    assert!(!event.dispatching());
    assert!(event.initialized());
    assert_eq!(event.phase(), EventPhase::None);
    assert!(event.GetCurrentTarget().is_none());

    event.set_target(match pseudo_target {
        Some(pseudo_target) => pseudo_target,
        None => target.clone(),
    });

    if event.stop_propagation() {
        return !event.DefaultPrevented();
    }

    event.set_dispatching(true);

    //TODO: no chain if not participating in a tree
    let mut chain: RootedVec<JS<EventTarget>> = RootedVec::new();
    if let Some(target_node) = NodeCast::to_ref(target) {
        for ancestor in target_node.ancestors() {
            let ancestor_target = EventTargetCast::from_ref(ancestor.r());
            chain.push(JS::from_ref(ancestor_target))
        }
    }

    dispatch_to_listeners(event, target, chain.r());

    /* default action */
    let target = event.GetTarget();
    match target {
        Some(ref target) => {
            let node: Option<&Node> = NodeCast::to_ref(target.r());
            match node {
                Some(node) => {
                    let vtable = vtable_for(&node);
                    vtable.handle_event(event);
                }
                None => {}
            }
        }
        None => {}
    }

    event.set_dispatching(false);
    event.set_phase(EventPhase::None);
    event.clear_current_target();

    !event.DefaultPrevented()
}
<|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 dom::bindings::cell::DOMRefCell;
use dom::bindings::codegen::Bindings::URLSearchParamsBinding;
use dom::bindings::codegen::Bindings::URLSearchParamsBinding::URLSearchParamsMethods;
use dom::bindings::codegen::UnionTypes::USVStringOrURLSearchParams;
use dom::bindings::codegen::UnionTypes::USVStringOrURLSearchParams::{eUSVString, eURLSearchParams};
use dom::bindings::error::Fallible;
use dom::bindings::global::GlobalRef;
use dom::bindings::js::Root;
use dom::bindings::reflector::{Reflector, reflect_dom_object};
use dom::bindings::str::USVString;
use encoding::types::EncodingRef;
use url::form_urlencoded::{parse, serialize_with_encoding};
use util::str::DOMString;

// https://url.spec.whatwg.org/#interface-urlsearchparams
#[dom_struct]
pub struct URLSearchParams {
    reflector_: Reflector,
    // https://url.spec.whatwg.org/#concept-urlsearchparams-list
    list: DOMRefCell<Vec<(String, String)>>,
}

impl URLSearchParams {
    fn new_inherited() -> URLSearchParams {
        URLSearchParams {
            reflector_: Reflector::new(),
            list: DOMRefCell::new(vec![]),
        }
    }

    pub fn new(global: GlobalRef) -> Root<URLSearchParams> {
        reflect_dom_object(box URLSearchParams::new_inherited(), global,
                           URLSearchParamsBinding::Wrap)
    }

    // https://url.spec.whatwg.org/#dom-urlsearchparams-urlsearchparams
    pub fn Constructor(global: GlobalRef, init: Option<USVStringOrURLSearchParams>) ->
                       Fallible<Root<URLSearchParams>> {
        // Step 1.
        let query = URLSearchParams::new(global);
        match init {
            Some(eUSVString(init)) => {
                // Step 2.
                *query.list.borrow_mut() = parse(init.0.as_bytes());
            },
            Some(eURLSearchParams(init)) => {
                // Step 3.
                *query.list.borrow_mut() = init.list.borrow().clone();
            },
            None => {}
        }
        // Step 4.
        Ok(query)
    }
}

impl URLSearchParamsMethods for URLSearchParams {
    // https://url.spec.whatwg.org/#dom-urlsearchparams-append
    fn Append(&self, name: USVString, value: USVString) {
        // Step 1.
        self.list.borrow_mut().push((name.0, value.0));
        // Step 2.
        self.update_steps();
    }

    // https://url.spec.whatwg.org/#dom-urlsearchparams-delete
    fn Delete(&self, name: USVString) {
        // Step 1.
        self.list.borrow_mut().retain(|&(ref k, _)| k != &name.0);
        // Step 2.
        self.update_steps();
    }

    // https://url.spec.whatwg.org/#dom-urlsearchparams-get
    fn Get(&self, name: USVString) -> Option<USVString> {
        let list = self.list.borrow();
        list.iter().find(|&&(ref k, _)| k == &name.0).map(|&(_, ref v)| USVString(v.clone()))
    }

    // https://url.spec.whatwg.org/#dom-urlsearchparams-getall
    fn GetAll(&self, name: USVString) -> Vec<USVString> {
        let list = self.list.borrow();
        list.iter().filter_map(|&(ref k, ref v)| {
            if k == &name.0 {
                Some(USVString(v.clone()))
            } else {
                None
            }
        }).collect()
    }

    // https://url.spec.whatwg.org/#dom-urlsearchparams-has
    fn Has(&self, name: USVString) -> bool {
        let list = self.list.borrow();
        list.iter().any(|&(ref k, _)| k == &name.0)
    }

    // https://url.spec.whatwg.org/#dom-urlsearchparams-set
    fn Set(&self, name: USVString, value: USVString) {
        let mut list = self.list.borrow_mut();
        let mut index = None;
        let mut i = 0;
        list.retain(|&(ref k, _)| {
            if index.is_none() {
                if k == &name.0 {
                    index = Some(i);
                } else {
                    i += 1;
                }
                true
            } else {
                k != &name.0
            }
        });
        match index {
            Some(index) => list[index].1 = value.0,
            None => list.push((name.0, value.0)),
        };
        self.update_steps();
    }

    // https://url.spec.whatwg.org/#stringification-behavior
    fn Stringifier(&self) -> DOMString {
        DOMString::from(self.serialize(None))
    }
}

impl URLSearchParams {
    // https://url.spec.whatwg.org/#concept-urlencoded-serializer
    pub fn serialize(&self, encoding: Option<EncodingRef>) -> String {
        let list = self.list.borrow();
        serialize_with_encoding(list.iter(), encoding)
    }
}

impl URLSearchParams {
    // https://url.spec.whatwg.org/#concept-uq-update
    fn update_steps(&self) {
        // XXXManishearth Implement this when the URL interface is implemented
    }
}
<commit_msg>Improved .find().map()<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 dom::bindings::cell::DOMRefCell;
use dom::bindings::codegen::Bindings::URLSearchParamsBinding;
use dom::bindings::codegen::Bindings::URLSearchParamsBinding::URLSearchParamsMethods;
use dom::bindings::codegen::UnionTypes::USVStringOrURLSearchParams;
use dom::bindings::codegen::UnionTypes::USVStringOrURLSearchParams::{eUSVString, eURLSearchParams};
use dom::bindings::error::Fallible;
use dom::bindings::global::GlobalRef;
use dom::bindings::js::Root;
use dom::bindings::reflector::{Reflector, reflect_dom_object};
use dom::bindings::str::USVString;
use encoding::types::EncodingRef;
use url::form_urlencoded::{parse, serialize_with_encoding};
use util::str::DOMString;

// https://url.spec.whatwg.org/#interface-urlsearchparams
#[dom_struct]
pub struct URLSearchParams {
    reflector_: Reflector,
    // https://url.spec.whatwg.org/#concept-urlsearchparams-list
    list: DOMRefCell<Vec<(String, String)>>,
}

impl URLSearchParams {
    fn new_inherited() -> URLSearchParams {
        URLSearchParams {
            reflector_: Reflector::new(),
            list: DOMRefCell::new(vec![]),
        }
    }

    pub fn new(global: GlobalRef) -> Root<URLSearchParams> {
        reflect_dom_object(box URLSearchParams::new_inherited(), global,
                           URLSearchParamsBinding::Wrap)
    }

    // https://url.spec.whatwg.org/#dom-urlsearchparams-urlsearchparams
    pub fn Constructor(global: GlobalRef, init: Option<USVStringOrURLSearchParams>) ->
                       Fallible<Root<URLSearchParams>> {
        // Step 1.
        let query = URLSearchParams::new(global);
        match init {
            Some(eUSVString(init)) => {
                // Step 2.
                *query.list.borrow_mut() = parse(init.0.as_bytes());
            },
            Some(eURLSearchParams(init)) => {
                // Step 3.
                *query.list.borrow_mut() = init.list.borrow().clone();
            },
            None => {}
        }
        // Step 4.
        Ok(query)
    }
}

impl URLSearchParamsMethods for URLSearchParams {
    // https://url.spec.whatwg.org/#dom-urlsearchparams-append
    fn Append(&self, name: USVString, value: USVString) {
        // Step 1.
        self.list.borrow_mut().push((name.0, value.0));
        // Step 2.
        self.update_steps();
    }

    // https://url.spec.whatwg.org/#dom-urlsearchparams-delete
    fn Delete(&self, name: USVString) {
        // Step 1.
        self.list.borrow_mut().retain(|&(ref k, _)| k != &name.0);
        // Step 2.
        self.update_steps();
    }

    // https://url.spec.whatwg.org/#dom-urlsearchparams-get
    fn Get(&self, name: USVString) -> Option<USVString> {
        let list = self.list.borrow();
        list.iter().find(|&kv| kv.0 == name.0)
            .map(|ref kv| USVString(kv.1.clone()))
    }

    // https://url.spec.whatwg.org/#dom-urlsearchparams-getall
    fn GetAll(&self, name: USVString) -> Vec<USVString> {
        let list = self.list.borrow();
        list.iter().filter_map(|&(ref k, ref v)| {
            if k == &name.0 {
                Some(USVString(v.clone()))
            } else {
                None
            }
        }).collect()
    }

    // https://url.spec.whatwg.org/#dom-urlsearchparams-has
    fn Has(&self, name: USVString) -> bool {
        let list = self.list.borrow();
        list.iter().any(|&(ref k, _)| k == &name.0)
    }

    // https://url.spec.whatwg.org/#dom-urlsearchparams-set
    fn Set(&self, name: USVString, value: USVString) {
        let mut list = self.list.borrow_mut();
        let mut index = None;
        let mut i = 0;
        list.retain(|&(ref k, _)| {
            if index.is_none() {
                if k == &name.0 {
                    index = Some(i);
                } else {
                    i += 1;
                }
                true
            } else {
                k != &name.0
            }
        });
        match index {
            Some(index) => list[index].1 = value.0,
            None => list.push((name.0, value.0)),
        };
        self.update_steps();
    }

    // https://url.spec.whatwg.org/#stringification-behavior
    fn Stringifier(&self) -> DOMString {
        DOMString::from(self.serialize(None))
    }
}

impl URLSearchParams {
    // https://url.spec.whatwg.org/#concept-urlencoded-serializer
    pub fn serialize(&self, encoding: Option<EncodingRef>) -> String {
        let list = self.list.borrow();
        serialize_with_encoding(list.iter(), encoding)
    }
}

impl URLSearchParams {
    // https://url.spec.whatwg.org/#concept-uq-update
    fn update_steps(&self) {
        // XXXManishearth Implement this when the URL interface is implemented
    }
}
<|endoftext|>


<commit_before>use std::collections::HashMap;
use std::error::Error;
use std::fmt::{Debug, Display, Formatter};
use std::fmt;

use serde_json::{Value, from_str};
use serde_json::error::Result as R;
use serde_json::Serializer;
use serde::ser::Serialize;
use serde::ser::Serializer as Ser;

use storage::parser::{FileHeaderParser, ParserError};
use storage::file::header::spec::FileHeaderSpec;
use storage::file::header::data::FileHeaderData;

pub struct JsonHeaderParser {
    spec: Option<FileHeaderSpec>,
}

impl JsonHeaderParser {

    pub fn new(spec: Option<FileHeaderSpec>) -> JsonHeaderParser {
        JsonHeaderParser {
            spec: spec
        }
    }

}

impl Display for JsonHeaderParser {

    fn fmt(&self, fmt: &mut Formatter) -> fmt::Result {
        write!(fmt, "JsonHeaderParser");
        Ok(())
    }

}

impl Debug for JsonHeaderParser {

    fn fmt(&self, fmt: &mut Formatter) -> fmt::Result {
        write!(fmt, "JsonHeaderParser, Spec: {:?}", self.spec);
        Ok(())
    }

}

impl FileHeaderParser for JsonHeaderParser {

    fn read(&self, string: Option<String>)
        -> Result<FileHeaderData, ParserError>
    {
        if string.is_some() {
            let s = string.unwrap();
            debug!("Deserializing: {}", s);
            let fromstr : R<Value> = from_str(&s[..]);
            if let Ok(ref content) = fromstr {
                return Ok(visit_json(&content))
            }
            let oe = fromstr.err().unwrap();
            let s = format!("JSON parser error: {}", oe.description());
            let e = ParserError::short(&s[..], s.clone(), 0);
            Err(e)
        } else {
            Ok(FileHeaderData::Null)
        }
    }

    fn write(&self, data: &FileHeaderData) -> Result<String, ParserError> {
        let mut s = Vec::<u8>::new();
        {
            let mut ser = Serializer::pretty(&mut s);
            data.serialize(&mut ser);
        }

        String::from_utf8(s).or(
            Err(ParserError::short("Cannot parse utf8 bytes",
                                   String::from("<not printable>"),
                                   0)))
    }

}

// TODO: This function must be able to return a parser error
fn visit_json(v: &Value) -> FileHeaderData {
    match v {
        &Value::Null             => FileHeaderData::Null,
        &Value::Bool(b)          => FileHeaderData::Bool(b),
        &Value::I64(i)           => FileHeaderData::Integer(i),
        &Value::U64(u)           => FileHeaderData::UInteger(u),
        &Value::F64(f)           => FileHeaderData::Float(f),
        &Value::String(ref s)        => FileHeaderData::Text(s.clone()),
        &Value::Array(ref vec)       => {
            FileHeaderData::Array {
                values: Box::new(vec.clone().into_iter().map(|i| visit_json(&i)).collect())
            }
        },
        &Value::Object(ref btree)    => {
            let btree = btree.clone();
            FileHeaderData::Map{
                keys: btree.into_iter().map(|(k, v)|
                    FileHeaderData::Key {
                        name: k,
                        value: Box::new(visit_json(&v)),
                    }
                ).collect()
            }
        }
    }
}

impl Serialize for FileHeaderData {

    fn serialize<S>(&self, ser: &mut S) -> Result<(), S::Error>
        where S: Ser
    {
        match self {
            &FileHeaderData::Null               => {
                let o : Option<bool> = None;
                o.serialize(ser)
            },
            &FileHeaderData::Bool(ref b)            => b.serialize(ser),
            &FileHeaderData::Integer(ref i)         => i.serialize(ser),
            &FileHeaderData::UInteger(ref u)        => u.serialize(ser),
            &FileHeaderData::Float(ref f)           => f.serialize(ser),
            &FileHeaderData::Text(ref s)            => (&s[..]).serialize(ser),
            &FileHeaderData::Array{values: ref vs}  => vs.serialize(ser),
            &FileHeaderData::Map{keys: ref ks}      => {
                let mut hm = HashMap::new();

                for key in ks {
                    if let &FileHeaderData::Key{name: ref n, value: ref v} = key {
                        hm.insert(n, v);
                    } else {
                        panic!("Not a key: {:?}", key);
                    }
                }

                hm.serialize(ser)
            },
            &FileHeaderData::Key{name: ref n, value: ref v} => unreachable!(),

        }
    }

}

#[cfg(test)]
mod test {

    use super::JsonHeaderParser;
    use storage::parser::{FileHeaderParser, ParserError};
    use storage::file::header::data::FileHeaderData as FHD;
    use storage::file::header::spec::FileHeaderSpec as FHS;

    #[test]
    fn test_deserialization() {
        let text = String::from("{\"a\": 1, \"b\": -2}");
        let spec = FHS::Map {
            keys: vec![
                FHS::Key {
                    name: String::from("a"),
                    value_type: Box::new(FHS::UInteger)
                },
                FHS::Key {
                    name: String::from("b"),
                    value_type: Box::new(FHS::Integer)
                }
            ]
        };

        let parser = JsonHeaderParser::new(Some(spec));
        let parsed = parser.read(Some(text));
        assert!(parsed.is_ok(), "Parsed is not ok: {:?}", parsed);

        match parsed.ok() {
            Some(FHD::Map{keys: keys}) => {
                for k in keys {
                    match k {
                        FHD::Key{name: name, value: box value} => {
                            assert!(name == "a" || name == "b", "Key unknown");
                            match &value {
                                &FHD::UInteger(u) => assert_eq!(u, 1),
                                &FHD::Integer(i) => assert_eq!(i, -2),
                                _ => assert!(false, "Integers are not here"),
                            }
                        },
                        _ => assert!(false, "Key is not a Key"),
                    }
                }
            },

            _ => assert!(false, "Parsed is not a map"),
        }
    }

    #[test]
    fn test_deserialization_without_spec() {
        let text    = String::from("{\"a\": [1], \"b\": {\"c\": -2}}");
        let parser  = JsonHeaderParser::new(None);
        let parsed  = parser.read(Some(text));

        assert!(parsed.is_ok(), "Parsed is not ok: {:?}", parsed);

        match parsed.ok() {
            Some(FHD::Map{keys: keys}) => {
                for k in keys {
                    match_key(&k);
                }
            },

            _ => assert!(false, "Parsed is not a map"),
        }
    }

    fn match_key(k: &FHD) {
        use std::ops::Deref;

        match k {
            &FHD::Key{name: ref name, value: ref value} => {
                assert!(name == "a" || name == "b", "Key unknown");
                match value.deref() {
                    &FHD::Array{values: ref vs} => {
                        for value in vs.iter() {
                            match value {
                                &FHD::UInteger(u) => assert_eq!(u, 1),
                                _ => assert!(false, "UInt is not an UInt"),
                            }
                        }
                    }

                    &FHD::Map{keys: ref ks} => {
                        for key in ks.iter() {
                            match key {
                                &FHD::Key{name: ref name, value: ref value} => {
                                    match value.deref() {
                                        &FHD::Integer(i) => {
                                            assert_eq!(i, -2);
                                            assert_eq!(name, "c");
                                        },
                                        _ => assert!(false, "Int is not an Int"),
                                    };
                                },
                                _ => assert!(false, "Key is not a Key"),
                            }
                        }
                    }
                    _ => assert!(false, "Integers are not here"),
                }
            },
            _ => assert!(false, "Key in main Map is not a Key"),
        }
    }

    #[test]
    fn test_desser() {
        use serde_json::error::Result as R;
        use serde_json::{Value, from_str};

        let text    = String::from("{\"a\": [1], \"b\": {\"c\": -2}}");
        let parser  = JsonHeaderParser::new(None);

        let des = parser.read(Some(text.clone()));
        assert!(des.is_ok(), "Deserializing failed");

        let ser = parser.write(&des.unwrap());
        assert!(ser.is_ok(), "Parser error when serializing deserialized text");

        let json_text : R<Value> = from_str(&text[..]);
        let json_ser  : R<Value> = from_str(&ser.unwrap()[..]);

        assert!(json_text.is_ok(), "Could not use serde to serialize text for comparison");
        assert!(json_ser.is_ok(),  "Could not use serde to serialize serialized-deserialized text for comparison");
        assert_eq!(json_text.unwrap(), json_ser.unwrap());
    }

}
<commit_msg>Remove box-syntax in test<commit_after>use std::collections::HashMap;
use std::error::Error;
use std::fmt::{Debug, Display, Formatter};
use std::fmt;

use serde_json::{Value, from_str};
use serde_json::error::Result as R;
use serde_json::Serializer;
use serde::ser::Serialize;
use serde::ser::Serializer as Ser;

use storage::parser::{FileHeaderParser, ParserError};
use storage::file::header::spec::FileHeaderSpec;
use storage::file::header::data::FileHeaderData;

pub struct JsonHeaderParser {
    spec: Option<FileHeaderSpec>,
}

impl JsonHeaderParser {

    pub fn new(spec: Option<FileHeaderSpec>) -> JsonHeaderParser {
        JsonHeaderParser {
            spec: spec
        }
    }

}

impl Display for JsonHeaderParser {

    fn fmt(&self, fmt: &mut Formatter) -> fmt::Result {
        write!(fmt, "JsonHeaderParser");
        Ok(())
    }

}

impl Debug for JsonHeaderParser {

    fn fmt(&self, fmt: &mut Formatter) -> fmt::Result {
        write!(fmt, "JsonHeaderParser, Spec: {:?}", self.spec);
        Ok(())
    }

}

impl FileHeaderParser for JsonHeaderParser {

    fn read(&self, string: Option<String>)
        -> Result<FileHeaderData, ParserError>
    {
        if string.is_some() {
            let s = string.unwrap();
            debug!("Deserializing: {}", s);
            let fromstr : R<Value> = from_str(&s[..]);
            if let Ok(ref content) = fromstr {
                return Ok(visit_json(&content))
            }
            let oe = fromstr.err().unwrap();
            let s = format!("JSON parser error: {}", oe.description());
            let e = ParserError::short(&s[..], s.clone(), 0);
            Err(e)
        } else {
            Ok(FileHeaderData::Null)
        }
    }

    fn write(&self, data: &FileHeaderData) -> Result<String, ParserError> {
        let mut s = Vec::<u8>::new();
        {
            let mut ser = Serializer::pretty(&mut s);
            data.serialize(&mut ser);
        }

        String::from_utf8(s).or(
            Err(ParserError::short("Cannot parse utf8 bytes",
                                   String::from("<not printable>"),
                                   0)))
    }

}

// TODO: This function must be able to return a parser error
fn visit_json(v: &Value) -> FileHeaderData {
    match v {
        &Value::Null             => FileHeaderData::Null,
        &Value::Bool(b)          => FileHeaderData::Bool(b),
        &Value::I64(i)           => FileHeaderData::Integer(i),
        &Value::U64(u)           => FileHeaderData::UInteger(u),
        &Value::F64(f)           => FileHeaderData::Float(f),
        &Value::String(ref s)        => FileHeaderData::Text(s.clone()),
        &Value::Array(ref vec)       => {
            FileHeaderData::Array {
                values: Box::new(vec.clone().into_iter().map(|i| visit_json(&i)).collect())
            }
        },
        &Value::Object(ref btree)    => {
            let btree = btree.clone();
            FileHeaderData::Map{
                keys: btree.into_iter().map(|(k, v)|
                    FileHeaderData::Key {
                        name: k,
                        value: Box::new(visit_json(&v)),
                    }
                ).collect()
            }
        }
    }
}

impl Serialize for FileHeaderData {

    fn serialize<S>(&self, ser: &mut S) -> Result<(), S::Error>
        where S: Ser
    {
        match self {
            &FileHeaderData::Null               => {
                let o : Option<bool> = None;
                o.serialize(ser)
            },
            &FileHeaderData::Bool(ref b)            => b.serialize(ser),
            &FileHeaderData::Integer(ref i)         => i.serialize(ser),
            &FileHeaderData::UInteger(ref u)        => u.serialize(ser),
            &FileHeaderData::Float(ref f)           => f.serialize(ser),
            &FileHeaderData::Text(ref s)            => (&s[..]).serialize(ser),
            &FileHeaderData::Array{values: ref vs}  => vs.serialize(ser),
            &FileHeaderData::Map{keys: ref ks}      => {
                let mut hm = HashMap::new();

                for key in ks {
                    if let &FileHeaderData::Key{name: ref n, value: ref v} = key {
                        hm.insert(n, v);
                    } else {
                        panic!("Not a key: {:?}", key);
                    }
                }

                hm.serialize(ser)
            },
            &FileHeaderData::Key{name: ref n, value: ref v} => unreachable!(),

        }
    }

}

#[cfg(test)]
mod test {

    use std::ops::Deref;

    use super::JsonHeaderParser;
    use storage::parser::{FileHeaderParser, ParserError};
    use storage::file::header::data::FileHeaderData as FHD;
    use storage::file::header::spec::FileHeaderSpec as FHS;

    #[test]
    fn test_deserialization() {
        let text = String::from("{\"a\": 1, \"b\": -2}");
        let spec = FHS::Map {
            keys: vec![
                FHS::Key {
                    name: String::from("a"),
                    value_type: Box::new(FHS::UInteger)
                },
                FHS::Key {
                    name: String::from("b"),
                    value_type: Box::new(FHS::Integer)
                }
            ]
        };

        let parser = JsonHeaderParser::new(Some(spec));
        let parsed = parser.read(Some(text));
        assert!(parsed.is_ok(), "Parsed is not ok: {:?}", parsed);

        match parsed.ok() {
            Some(FHD::Map{keys: keys}) => {
                for k in keys {
                    match k {
                        FHD::Key{name: name, value: value} => {
                            assert!(name == "a" || name == "b", "Key unknown");
                            match value.deref() {
                                &FHD::UInteger(u) => assert_eq!(u, 1),
                                &FHD::Integer(i) => assert_eq!(i, -2),
                                _ => assert!(false, "Integers are not here"),
                            }
                        },
                        _ => assert!(false, "Key is not a Key"),
                    }
                }
            },

            _ => assert!(false, "Parsed is not a map"),
        }
    }

    #[test]
    fn test_deserialization_without_spec() {
        let text    = String::from("{\"a\": [1], \"b\": {\"c\": -2}}");
        let parser  = JsonHeaderParser::new(None);
        let parsed  = parser.read(Some(text));

        assert!(parsed.is_ok(), "Parsed is not ok: {:?}", parsed);

        match parsed.ok() {
            Some(FHD::Map{keys: keys}) => {
                for k in keys {
                    match_key(&k);
                }
            },

            _ => assert!(false, "Parsed is not a map"),
        }
    }

    fn match_key(k: &FHD) {
        use std::ops::Deref;

        match k {
            &FHD::Key{name: ref name, value: ref value} => {
                assert!(name == "a" || name == "b", "Key unknown");
                match value.deref() {
                    &FHD::Array{values: ref vs} => {
                        for value in vs.iter() {
                            match value {
                                &FHD::UInteger(u) => assert_eq!(u, 1),
                                _ => assert!(false, "UInt is not an UInt"),
                            }
                        }
                    }

                    &FHD::Map{keys: ref ks} => {
                        for key in ks.iter() {
                            match key {
                                &FHD::Key{name: ref name, value: ref value} => {
                                    match value.deref() {
                                        &FHD::Integer(i) => {
                                            assert_eq!(i, -2);
                                            assert_eq!(name, "c");
                                        },
                                        _ => assert!(false, "Int is not an Int"),
                                    };
                                },
                                _ => assert!(false, "Key is not a Key"),
                            }
                        }
                    }
                    _ => assert!(false, "Integers are not here"),
                }
            },
            _ => assert!(false, "Key in main Map is not a Key"),
        }
    }

    #[test]
    fn test_desser() {
        use serde_json::error::Result as R;
        use serde_json::{Value, from_str};

        let text    = String::from("{\"a\": [1], \"b\": {\"c\": -2}}");
        let parser  = JsonHeaderParser::new(None);

        let des = parser.read(Some(text.clone()));
        assert!(des.is_ok(), "Deserializing failed");

        let ser = parser.write(&des.unwrap());
        assert!(ser.is_ok(), "Parser error when serializing deserialized text");

        let json_text : R<Value> = from_str(&text[..]);
        let json_ser  : R<Value> = from_str(&ser.unwrap()[..]);

        assert!(json_text.is_ok(), "Could not use serde to serialize text for comparison");
        assert!(json_ser.is_ok(),  "Could not use serde to serialize serialized-deserialized text for comparison");
        assert_eq!(json_text.unwrap(), json_ser.unwrap());
    }

}
<|endoftext|>


<commit_before>// Compare bounded and unbounded protocol performance.

// xfail-test
// xfail-pretty

use std;

import pipes::{spawn_service, recv};
import std::time::precise_time_s;

proto! pingpong {
    ping: send {
        ping -> pong
    }

    pong: recv {
        pong -> ping
    }
}

proto! pingpong_unbounded {
    ping: send {
        ping -> pong
    }

    pong: recv {
        pong -> ping
    }

    you_will_never_catch_me: send {
        never_ever_ever -> you_will_never_catch_me
    }
}

// This stuff should go in libcore::pipes
macro_rules! move {
    { $x:expr } => { unsafe { let y <- *ptr::addr_of($x); y } }
}

macro_rules! follow {
    {
        $($message:path($($x: ident),+) -> $next:ident $e:expr)+
    } => (
        |m| alt move(m) {
          $(some($message($($x,)* next)) {
            let $next = move!{next};
            $e })+
          _ { fail }
        }
    );

    {
        $($message:path -> $next:ident $e:expr)+
    } => (
        |m| alt move(m) {
            $(some($message(next)) {
                let $next = move!{next};
                $e })+
                _ { fail }
        }
    )
}

fn switch<T: send, Tb: send, U>(+endp: pipes::recv_packet_buffered<T, Tb>,
                      f: fn(+option<T>) -> U) -> U {
    f(pipes::try_recv(endp))
}

fn move<T>(-x: T) -> T { x }

// Here's the benchmark

fn bounded(count: uint) {
    import pingpong::*;

    let mut ch = do spawn_service(init) |ch| {
        let mut count = count;
        let mut ch = ch;
        while count > 0 {
            ch = switch(ch, follow! {
                ping -> next { server::pong(next) }
            });

            count -= 1;
        }
    };

    let mut count = count;
    while count > 0 {
        let ch_ = client::ping(ch);

        ch = switch(ch_, follow! {
            pong -> next { next }
        });

        count -= 1;
    }
}

fn unbounded(count: uint) {
    import pingpong_unbounded::*;

    let mut ch = do spawn_service(init) |ch| {
        let mut count = count;
        let mut ch = ch;
        while count > 0 {
            ch = switch(ch, follow! {
                ping -> next { server::pong(next) }
            });

            count -= 1;
        }
    };

    let mut count = count;
    while count > 0 {
        let ch_ = client::ping(ch);

        ch = switch(ch_, follow! {
            pong -> next { next }
        });

        count -= 1;
    }
}

fn timeit(f: fn()) -> float {
    let start = precise_time_s();
    f();
    let stop = precise_time_s();
    stop - start
}

fn main() {
    let count = 1000000;
    let bounded = do timeit { bounded(count) };
    let unbounded = do timeit { unbounded(count) };

    io::println(fmt!{"count: %?\n", count});
    io::println(fmt!{"bounded:   %? s\t(%? μs/message)",
                     bounded, bounded * 1000000. / (count as float)});
    io::println(fmt!{"unbounded: %? s\t(%? μs/message)",
                     unbounded, unbounded * 1000000. / (count as float)});

    io::println(fmt!{"\n\
                      bounded is %?%% faster",
                     (unbounded - bounded) / bounded * 100.});
}
<commit_msg>Enabling pingpong benchmark.<commit_after>// Compare bounded and unbounded protocol performance.

// xfail-pretty

use std;

import pipes::{spawn_service, recv};
import std::time::precise_time_s;

proto! pingpong {
    ping: send {
        ping -> pong
    }

    pong: recv {
        pong -> ping
    }
}

proto! pingpong_unbounded {
    ping: send {
        ping -> pong
    }

    pong: recv {
        pong -> ping
    }

    you_will_never_catch_me: send {
        never_ever_ever -> you_will_never_catch_me
    }
}

// This stuff should go in libcore::pipes
macro_rules! move_it {
    { $x:expr } => { let t <- *ptr::addr_of($x); t }
}

macro_rules! follow {
    {
        $($message:path($($x: ident),+) -> $next:ident $e:expr)+
    } => (
        |m| alt move m {
            $(some($message($($x,)* next)) => {
                // FIXME (#2329) use regular move here once move out of
                // enums is supported.
                let $next = unsafe { move_it!(next) };
                $e })+
                _ => { fail }
        }
    );

    {
        $($message:path -> $next:ident $e:expr)+
    } => (
        |m| alt move m {
            $(some($message(next)) => {
                // FIXME (#2329) use regular move here once move out of
                // enums is supported.
                let $next = unsafe { move_it!(next) };
                $e })+
                _ => { fail }
        }
    )
}

fn switch<T: send, Tb: send, U>(+endp: pipes::recv_packet_buffered<T, Tb>,
                      f: fn(+option<T>) -> U) -> U {
    f(pipes::try_recv(endp))
}

// Here's the benchmark

fn bounded(count: uint) {
    import pingpong::*;

    let mut ch = do spawn_service(init) |ch| {
        let mut count = count;
        let mut ch = ch;
        while count > 0 {
            ch = switch(ch, follow! {
                ping -> next { server::pong(next) }
            });

            count -= 1;
        }
    };

    let mut count = count;
    while count > 0 {
        let ch_ = client::ping(ch);

        ch = switch(ch_, follow! {
            pong -> next { next }
        });

        count -= 1;
    }
}

fn unbounded(count: uint) {
    import pingpong_unbounded::*;

    let mut ch = do spawn_service(init) |ch| {
        let mut count = count;
        let mut ch = ch;
        while count > 0 {
            ch = switch(ch, follow! {
                ping -> next { server::pong(next) }
            });

            count -= 1;
        }
    };

    let mut count = count;
    while count > 0 {
        let ch_ = client::ping(ch);

        ch = switch(ch_, follow! {
            pong -> next { next }
        });

        count -= 1;
    }
}

fn timeit(f: fn()) -> float {
    let start = precise_time_s();
    f();
    let stop = precise_time_s();
    stop - start
}

fn main() {
    let count = if os::getenv(~"RUST_BENCH").is_some() {
        250000
    } else {
        100
    };
    let bounded = do timeit { bounded(count) };
    let unbounded = do timeit { unbounded(count) };

    io::println(fmt!{"count: %?\n", count});
    io::println(fmt!{"bounded:   %? s\t(%? μs/message)",
                     bounded, bounded * 1000000. / (count as float)});
    io::println(fmt!{"unbounded: %? s\t(%? μs/message)",
                     unbounded, unbounded * 1000000. / (count as float)});

    io::println(fmt!{"\n\
                      bounded is %?%% faster",
                     (unbounded - bounded) / bounded * 100.});
}
<|endoftext|>