<commit_before>use crate::core::prelude::*;
use maud::{html, Markup, DOCTYPE};
use rocket::request::FlashMessage;
use std::collections::HashMap;

const LEAFLET_CSS_URL: &str = "https://cdnjs.cloudflare.com/ajax/libs/leaflet/1.4.0/leaflet.css";
const LEAFLET_CSS_SHA512: &str="sha512-puBpdR0798OZvTTbP4A8Ix/l+A4dHDD0DGqYW6RQ+9jxkRFclaxxQb/SJAWZfWAkuyeQUytO7+7N4QKrDh+drA==";
const LEAFLET_JS_URL: &str = "https://cdnjs.cloudflare.com/ajax/libs/leaflet/1.4.0/leaflet.js";
const LEAFLET_JS_SHA512 : &str="sha512-QVftwZFqvtRNi0ZyCtsznlKSWOStnDORoefr1enyq5mVL4tmKB3S/EnC3rRJcxCPavG10IcrVGSmPh6Qw5lwrg==";
const MAIN_CSS_URL: &str = "/main.css";
const MAP_JS_URL: &str = "/map.js";

pub fn index(email: Option<&str>) -> Markup {
    page(
        "OpenFairDB Search",
        None,
        html! {
            (header(email))
            div class="search" {
                h1 {"OpenFairDB Search"}
                (global_search_form(None))
            }
        },
    )
}

fn header(email: Option<&str>) -> Markup {
    html! {
    header {
        @if let Some(email) = email {
            div class="msg" { "Your are logged with " span class="email" { (email) } }
            nav {
                a href="/" { "search" }
                a href="dashboard" { "dashboard" }
                form class="logout" action="logout" method ="POST" {
                    input type="submit" value="logout";
                }
            }
        }
        @ else {
            nav {
                a href="login"  { "login" }
                a href="register" { "register" }
            }
        }
    }
    }
}

pub struct DashBoardPresenter<'a> {
    pub email: &'a str,
    pub entry_count: usize,
    pub event_count: usize,
    pub tag_count: usize,
    pub user_count: usize,
}

pub fn dashboard(data: DashBoardPresenter) -> Markup {
    page(
        "Admin dashboard",
        None,
        html! {
            (header(Some(data.email)))
            main {
                h3 { "Stats" }
                table {
                    tr {
                        td {"Number of Entries"}
                        td {(data.entry_count)}
                    }
                    tr {
                        td {"Number of Events"}
                        td {(data.event_count)}
                    }
                    tr {
                        td {"Number of Users"}
                        td {(data.user_count)}
                    }
                    tr {
                        td {"Number of Tags"}
                        td {(data.tag_count)}
                    }
                }
            }
        },
    )
}

pub fn global_search_form(search_term: Option<&str>) -> Markup {
    html! {
        div class="search-form" {
            form action="search" method="GET" {
                input
                    type="text"
                    name="q"
                    value=(search_term.unwrap_or(""))
                    size=(50)
                    maxlength=(200)
                    placeholer="search term, empty = all";
                br;
                input class="btn" type="submit" value="search";
            }
        }
    }
}

fn leaflet_css_link() -> Markup {
    html! {
            link
                rel="stylesheet"
                href=(LEAFLET_CSS_URL)
                integrity=(LEAFLET_CSS_SHA512)
                crossorigin="anonymous";
    }
}

pub fn search_results(search_term: &str, entries: &[IndexedEntry]) -> Markup {
    page(
        "OpenFariDB Search Results",
        None,
        html! {
            div class="search" {
                h1 {"OpenFairDB Search"}
                (global_search_form(Some(search_term)))
            }
            div class="results" {
                @if entries.is_empty(){
                    p{ "We are so sorry but we could not find any entries
                        that are related to your search term "
                            em {
                                (format!("'{}'", search_term))
                            }
                    }
                } @else {
                    p {
                        ul class="result-list" {
                            @for e in entries {
                                li{
                                    (entry_result(e))
                                }
                            }
                        }
                    }
                }
            }
        },
    )
}

fn entry_result(e: &IndexedEntry) -> Markup {
    html! {
        h3 {
            a href=(format!("entries/{}",e.id)) {(e.title)}
        }
        p {(e.description)}
    }
}

type Ratings = Vec<(Rating, Vec<Comment>)>;

pub struct EntryPresenter {
    pub entry: Entry,
    pub ratings: HashMap<RatingContext, Ratings>,
}

impl From<(Entry, Vec<(Rating, Vec<Comment>)>)> for EntryPresenter {
    fn from((entry, rtngs): (Entry, Vec<(Rating, Vec<Comment>)>)) -> EntryPresenter {
        let mut ratings: HashMap<RatingContext, Ratings> = HashMap::new();

        for (r, comments) in rtngs {
            if let Some(x) = ratings.get_mut(&r.context) {
                x.push((r, comments));
            } else {
                ratings.insert(r.context, vec![(r, comments)]);
            }
        }

        EntryPresenter { entry, ratings }
    }
}

pub fn entry(e: EntryPresenter) -> Markup {
    page(
        &format!("{} | OpenFairDB", e.entry.title),
        Some(leaflet_css_link()),
        entry_detail(e),
    )
}

fn entry_detail(e: EntryPresenter) -> Markup {
    html! {
        h3 { (e.entry.title) }
        p {(e.entry.description)}
        p {
            table {
                @if let Some(ref h) = e.entry.homepage {
                    tr {
                        td { "Homepage" }
                        td { a href=(h) { (h) } }
                    }
                }
                @if let Some(ref c) = e.entry.contact {
                    @if let Some(ref m) = c.email {
                        tr {
                            td { "eMail" }
                            td { a href=(format!("mailto:{}",m)) { (m) } }
                        }
                    }
                    @if let Some(ref t) = c.telephone {
                        tr {
                            td { "Telephone" }
                            td { a href=(format!("tel:{}",t)) { (t) } }
                        }
                    }
                }
                @if let Some(ref a) = e.entry.location.address {
                    @if !a.is_empty() {
                        tr {
                            td { "Address" }
                            td { (address_to_html(&a)) }
                        }
                    }
                }
            }
        }
        p {
            ul {
                @for t in &e.entry.tags{
                    li{ (format!("#{}", t)) }
                }
            }
        }
        h3 { "Ratings" }

        @for (ctx, ratings) in e.ratings {
            h4 { (format!("{:?}",ctx)) }
            ul {
                @for (r,comments) in ratings {
                    li {
                        (rating(&r, &comments))
                    }
                }
            }
        }
        div id="map" style="height:300px;" { }
        (map_scripts(&[e.entry.into()]))
    }
}

fn rating(r: &Rating, comments: &[Comment]) -> Markup {
    html! {
      h5 { (r.title) " " span { (format!("({})",i8::from(r.value))) } }
      // TODO:
      // form action = "/rating/delete" method = "POST" {
      //     input type="hidden" name="id" value=(r.id);
      //     input type="submit" value="delete rating";
      // }
      @if let Some(ref src) = r.source {
          p { (format!("source: {}",src)) }
      }
      ul {
          @for c in comments {
              li {
                  p { (c.text) }
                  // TODO:
                  // form action = "/comments/delete" method = "POST" {
                  //     input type="hidden" name="id" value=(c.id);
                  //     input type="submit" value="delete comment";
                  // }
              }
          }
      }
    }
}

fn address_to_html(addr: &Address) -> Markup {
    html! {
        @if let Some(ref s) = addr.street {
            (s) br;
        }
        @if let Some(ref z) = addr.zip {
            (z)
        }
        @if let Some(ref z) = addr.city {
            (z) br;
        }
        @if let Some(ref c) = addr.country {
            (c)
        }
    }
}

pub fn event(ev: Event) -> Markup {
    page(
        &ev.title,
        Some(html! {
            link
                rel="stylesheet"
                href=(LEAFLET_CSS_URL)
                integrity=(LEAFLET_CSS_SHA512)
                crossorigin="anonymous";
        }),
        html! {
            h2{ (ev.title) }
            h4 { "Zeit" }
            p{
                (ev.start.to_string())
                    @if let Some(end) = ev.end{
                        " bis "
                        (end.to_string())
                    }
            }
            h4 { "Beschreibung" }
            p{ (ev.description.unwrap_or("".to_string())) }

            @if let Some(ref location) = ev.location{
                    h4{ "Ort" }
                    @if let Some(ref addr) = location.address {
                        @if !addr.is_empty(){
                            @if let Some(ref s) = addr.street {
                             (s) br;
                            }
                            @if let Some(ref z) = addr.zip {
                             (z) " "
                            }
                            @if let Some(ref c) = addr.city {
                             (c) br;
                            }
                            @if let Some(ref c) = addr.country {
                             (c)
                            }
                        }
                    }
                    h4 {"Koordinaten"}
                    p{
                        (format!("{:.2} / {:.2}",location.pos.lat().to_deg(), location.pos.lng().to_deg()))
                    }
            }
            @if let Some(org) = ev.organizer {
                h4{"Veranstalter"}
                p{(org)}
            }
            @if let Some(contact) = ev.contact{
                @if !contact.is_empty(){
                    h4{ "Kontakt" }
                    @if let Some(email) = contact.email{
                        (email)
                        br;
                    }
                    @if let Some(phone) = contact.telephone{
                        (phone)
                    }
                }
            }
            @if let Some(url) = ev.homepage{
                    h4{ "Webseite" }
                    p{
                        a href=(url) { (url) }
                    }
            }
            @if let Some(reg) = ev.registration{
                h4{ "Anmeldung"}
                p {
                    @match reg{
                        RegistrationType::Email => "eMail" ,
                        RegistrationType::Phone => "Telefon",
                            RegistrationType::Homepage => "Webseite",
                    }
                }
            }
            p {
                h4{"Tags"}
                ul{
                    @for t in ev.tags{
                        li {(t)}
                    }
                }
            }

            @if let Some(l) = ev.location {
                div id="map" style="height:300px;" { }
                (map_scripts(&[l.into()]))
            }
        },
    )
}

struct MapPin {
    lat: f64,
    lng: f64,
}

impl MapPin {
    fn to_js_object_string(&self) -> String {
        format!("{{lat:{},lng:{}}}", self.lat, self.lng)
    }
}

impl From<Entry> for MapPin {
    fn from(e: Entry) -> Self {
        e.location.into()
    }
}

impl From<&Entry> for MapPin {
    fn from(e: &Entry) -> Self {
        (&e.location).into()
    }
}

impl From<Location> for MapPin {
    fn from(l: Location) -> Self {
        (&l).into()
    }
}

impl From<&Location> for MapPin {
    fn from(l: &Location) -> Self {
        MapPin {
            lat: l.pos.lat().to_deg(),
            lng: l.pos.lng().to_deg(),
        }
    }
}

fn map_scripts(pins: &[MapPin]) -> Markup {
    let (center, zoom) = match pins.len() {
        1 => ((pins[0].lat, pins[0].lng), 13.0),
        _ => {
            //TODO: calculate center & zoom
            ((48.720, 9.152), 6.0)
        }
    };

    let center = format!("[{},{}]", center.0, center.1);

    let pins: String = pins
        .iter()
        .map(|p| p.to_js_object_string())
        .collect::<Vec<_>>()
        .join(",");

    html! {
      script{
        (format!("window.OFDB_MAP_PINS=[{}];window.OFDB_MAP_ZOOM={};OFDB_MAP_CENTER={};",
                 pins,
                 zoom,
                 center))
      }
      script
        src=(LEAFLET_JS_URL)
        integrity=(LEAFLET_JS_SHA512)
        crossorigin="anonymous" {}
      script src=(MAP_JS_URL){}
    }
}

pub fn events(events: &[Event]) -> Markup {
    page(
        "List of events",
        None,
        html! {
            div class="events" {
                h3 { "Events" }
                ul class="event-list" {
                    @for e in events {
                        li {
                            a href=(format!("/events/{}", e.id)) {
                                div {
                                    h4 {
                                        span class="title" { (e.title) }
                                        " "
                                        span class="date" {
                                            (e.start.format("%d.%m.%y"))
                                        }
                                    }
                                    p {
                                        @if let Some(ref l) = e.location {
                                            @if let Some(ref a) = l.address {
                                                @if let Some(ref city) = a.city {
                                                    span class="city" { (city) }
                                                    br;
                                                }
                                            }
                                        }
                                        @if let Some(ref o) = e.organizer {
                                        span class="organizier" { (o) }
                                        }
                                    }
                                }
                            }
                        }
                    }
                }
            }
        },
    )
}

pub fn login(flash: Option<FlashMessage>) -> Markup {
    flash_page(
        "Login",
        None,
        flash,
        html! {
          form class="login" action="login" method="POST" {
              fieldset{
                label {
                    "eMail:"
                    br;
                    input type="email" name="email" placeholder="eMail address";
                }
                    br;
                label{
                    "Password:"
                    br;
                    input type="password" name="password" placeholder="Password";
                }
                br;
                input type="submit" value="login";
              }
          }
        },
    )
}

pub fn register(flash: Option<FlashMessage>) -> Markup {
    flash_page(
        "Register",
        None,
        flash,
        html! {
          form class="register" action="register" method="POST" {
              fieldset{
                label {
                    "eMail:"
                    br;
                    input type="email" name="email" placeholder="eMail address";
                }
                    br;
                label{
                    "Password:"
                    br;
                    input type="password" name="password" placeholder="Password";
                }
                br;
                input type="submit" value="register";
              }
          }
        },
    )
}

fn flash_msg(flash: Option<FlashMessage>) -> Markup {
    html! {
        @if let Some(msg) = flash {
            div class=(format!("flash {}", msg.name())) {
                (msg.msg())
            }
        }
    }
}

fn flash_page(
    title: &str,
    h: Option<Markup>,
    flash: Option<FlashMessage>,
    content: Markup,
) -> Markup {
    page(
        title,
        h,
        html! {
          (flash_msg(flash))
          (content)
        },
    )
}

fn page(title: &str, h: Option<Markup>, content: Markup) -> Markup {
    html! {
        (DOCTYPE)
        head{
            meta charset="utf-8";
            meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no";
            title {(title)}
            link rel="stylesheet" href=(MAIN_CSS_URL);
            @if let Some(h) = h {
               (h)
            }
        }
        body{
            (content)
        }
    }
}
<commit_msg>Fix typos and wording<commit_after>use crate::core::prelude::*;
use maud::{html, Markup, DOCTYPE};
use rocket::request::FlashMessage;
use std::collections::HashMap;

const LEAFLET_CSS_URL: &str = "https://cdnjs.cloudflare.com/ajax/libs/leaflet/1.4.0/leaflet.css";
const LEAFLET_CSS_SHA512: &str="sha512-puBpdR0798OZvTTbP4A8Ix/l+A4dHDD0DGqYW6RQ+9jxkRFclaxxQb/SJAWZfWAkuyeQUytO7+7N4QKrDh+drA==";
const LEAFLET_JS_URL: &str = "https://cdnjs.cloudflare.com/ajax/libs/leaflet/1.4.0/leaflet.js";
const LEAFLET_JS_SHA512 : &str="sha512-QVftwZFqvtRNi0ZyCtsznlKSWOStnDORoefr1enyq5mVL4tmKB3S/EnC3rRJcxCPavG10IcrVGSmPh6Qw5lwrg==";
const MAIN_CSS_URL: &str = "/main.css";
const MAP_JS_URL: &str = "/map.js";

pub fn index(email: Option<&str>) -> Markup {
    page(
        "OpenFairDB Search",
        None,
        html! {
            (header(email))
            div class="search" {
                h1 {"OpenFairDB Search"}
                (global_search_form(None))
            }
        },
    )
}

fn header(email: Option<&str>) -> Markup {
    html! {
    header {
        @if let Some(email) = email {
            div class="msg" { "Your are logged in as " span class="email" { (email) } }
            nav {
                a href="/" { "search" }
                a href="dashboard" { "dashboard" }
                form class="logout" action="logout" method ="POST" {
                    input type="submit" value="logout";
                }
            }
        }
        @ else {
            nav {
                a href="login"  { "login" }
                a href="register" { "register" }
            }
        }
    }
    }
}

pub struct DashBoardPresenter<'a> {
    pub email: &'a str,
    pub entry_count: usize,
    pub event_count: usize,
    pub tag_count: usize,
    pub user_count: usize,
}

pub fn dashboard(data: DashBoardPresenter) -> Markup {
    page(
        "Admin Dashboard",
        None,
        html! {
            (header(Some(data.email)))
            main {
                h3 { "Database Statistics" }
                table {
                    tr {
                        td {"Number of Entries"}
                        td {(data.entry_count)}
                    }
                    tr {
                        td {"Number of Events"}
                        td {(data.event_count)}
                    }
                    tr {
                        td {"Number of Users"}
                        td {(data.user_count)}
                    }
                    tr {
                        td {"Number of Tags"}
                        td {(data.tag_count)}
                    }
                }
            }
        },
    )
}

pub fn global_search_form(search_term: Option<&str>) -> Markup {
    html! {
        div class="search-form" {
            form action="search" method="GET" {
                input
                    type="text"
                    name="q"
                    value=(search_term.unwrap_or(""))
                    size=(50)
                    maxlength=(200)
                    placeholer="search term, empty = all";
                br;
                input class="btn" type="submit" value="search";
            }
        }
    }
}

fn leaflet_css_link() -> Markup {
    html! {
            link
                rel="stylesheet"
                href=(LEAFLET_CSS_URL)
                integrity=(LEAFLET_CSS_SHA512)
                crossorigin="anonymous";
    }
}

pub fn search_results(search_term: &str, entries: &[IndexedEntry]) -> Markup {
    page(
        "OpenFairDB Search Results",
        None,
        html! {
            div class="search" {
                h1 {"OpenFairDB Search"}
                (global_search_form(Some(search_term)))
            }
            div class="results" {
                @if entries.is_empty(){
                    p{ "We are so sorry but we could not find any entries
                        that are related to your search term "
                            em {
                                (format!("'{}'", search_term))
                            }
                    }
                } @else {
                    p {
                        ul class="result-list" {
                            @for e in entries {
                                li{
                                    (entry_result(e))
                                }
                            }
                        }
                    }
                }
            }
        },
    )
}

fn entry_result(e: &IndexedEntry) -> Markup {
    html! {
        h3 {
            a href=(format!("entries/{}",e.id)) {(e.title)}
        }
        p {(e.description)}
    }
}

type Ratings = Vec<(Rating, Vec<Comment>)>;

pub struct EntryPresenter {
    pub entry: Entry,
    pub ratings: HashMap<RatingContext, Ratings>,
}

impl From<(Entry, Vec<(Rating, Vec<Comment>)>)> for EntryPresenter {
    fn from((entry, rtngs): (Entry, Vec<(Rating, Vec<Comment>)>)) -> EntryPresenter {
        let mut ratings: HashMap<RatingContext, Ratings> = HashMap::new();

        for (r, comments) in rtngs {
            if let Some(x) = ratings.get_mut(&r.context) {
                x.push((r, comments));
            } else {
                ratings.insert(r.context, vec![(r, comments)]);
            }
        }

        EntryPresenter { entry, ratings }
    }
}

pub fn entry(e: EntryPresenter) -> Markup {
    page(
        &format!("{} | OpenFairDB", e.entry.title),
        Some(leaflet_css_link()),
        entry_detail(e),
    )
}

fn entry_detail(e: EntryPresenter) -> Markup {
    html! {
        h3 { (e.entry.title) }
        p {(e.entry.description)}
        p {
            table {
                @if let Some(ref h) = e.entry.homepage {
                    tr {
                        td { "Homepage" }
                        td { a href=(h) { (h) } }
                    }
                }
                @if let Some(ref c) = e.entry.contact {
                    @if let Some(ref m) = c.email {
                        tr {
                            td { "eMail" }
                            td { a href=(format!("mailto:{}",m)) { (m) } }
                        }
                    }
                    @if let Some(ref t) = c.telephone {
                        tr {
                            td { "Telephone" }
                            td { a href=(format!("tel:{}",t)) { (t) } }
                        }
                    }
                }
                @if let Some(ref a) = e.entry.location.address {
                    @if !a.is_empty() {
                        tr {
                            td { "Address" }
                            td { (address_to_html(&a)) }
                        }
                    }
                }
            }
        }
        p {
            ul {
                @for t in &e.entry.tags{
                    li{ (format!("#{}", t)) }
                }
            }
        }
        h3 { "Ratings" }

        @for (ctx, ratings) in e.ratings {
            h4 { (format!("{:?}",ctx)) }
            ul {
                @for (r,comments) in ratings {
                    li {
                        (rating(&r, &comments))
                    }
                }
            }
        }
        div id="map" style="height:300px;" { }
        (map_scripts(&[e.entry.into()]))
    }
}

fn rating(r: &Rating, comments: &[Comment]) -> Markup {
    html! {
      h5 { (r.title) " " span { (format!("({})",i8::from(r.value))) } }
      // TODO:
      // form action = "/rating/delete" method = "POST" {
      //     input type="hidden" name="id" value=(r.id);
      //     input type="submit" value="delete rating";
      // }
      @if let Some(ref src) = r.source {
          p { (format!("source: {}",src)) }
      }
      ul {
          @for c in comments {
              li {
                  p { (c.text) }
                  // TODO:
                  // form action = "/comments/delete" method = "POST" {
                  //     input type="hidden" name="id" value=(c.id);
                  //     input type="submit" value="delete comment";
                  // }
              }
          }
      }
    }
}

fn address_to_html(addr: &Address) -> Markup {
    html! {
        @if let Some(ref s) = addr.street {
            (s) br;
        }
        @if let Some(ref z) = addr.zip {
            (z)
        }
        @if let Some(ref z) = addr.city {
            (z) br;
        }
        @if let Some(ref c) = addr.country {
            (c)
        }
    }
}

pub fn event(ev: Event) -> Markup {
    page(
        &ev.title,
        Some(html! {
            link
                rel="stylesheet"
                href=(LEAFLET_CSS_URL)
                integrity=(LEAFLET_CSS_SHA512)
                crossorigin="anonymous";
        }),
        html! {
            h2{ (ev.title) }
            h4 { "Zeit" }
            p{
                (ev.start.to_string())
                    @if let Some(end) = ev.end{
                        " bis "
                        (end.to_string())
                    }
            }
            h4 { "Beschreibung" }
            p{ (ev.description.unwrap_or("".to_string())) }

            @if let Some(ref location) = ev.location{
                    h4{ "Ort" }
                    @if let Some(ref addr) = location.address {
                        @if !addr.is_empty(){
                            @if let Some(ref s) = addr.street {
                             (s) br;
                            }
                            @if let Some(ref z) = addr.zip {
                             (z) " "
                            }
                            @if let Some(ref c) = addr.city {
                             (c) br;
                            }
                            @if let Some(ref c) = addr.country {
                             (c)
                            }
                        }
                    }
                    h4 {"Koordinaten"}
                    p{
                        (format!("{:.2} / {:.2}",location.pos.lat().to_deg(), location.pos.lng().to_deg()))
                    }
            }
            @if let Some(org) = ev.organizer {
                h4{"Veranstalter"}
                p{(org)}
            }
            @if let Some(contact) = ev.contact{
                @if !contact.is_empty(){
                    h4{ "Kontakt" }
                    @if let Some(email) = contact.email{
                        (email)
                        br;
                    }
                    @if let Some(phone) = contact.telephone{
                        (phone)
                    }
                }
            }
            @if let Some(url) = ev.homepage{
                    h4{ "Webseite" }
                    p{
                        a href=(url) { (url) }
                    }
            }
            @if let Some(reg) = ev.registration{
                h4{ "Anmeldung"}
                p {
                    @match reg{
                        RegistrationType::Email => "eMail" ,
                        RegistrationType::Phone => "Telefon",
                            RegistrationType::Homepage => "Webseite",
                    }
                }
            }
            p {
                h4{"Tags"}
                ul{
                    @for t in ev.tags{
                        li {(t)}
                    }
                }
            }

            @if let Some(l) = ev.location {
                div id="map" style="height:300px;" { }
                (map_scripts(&[l.into()]))
            }
        },
    )
}

struct MapPin {
    lat: f64,
    lng: f64,
}

impl MapPin {
    fn to_js_object_string(&self) -> String {
        format!("{{lat:{},lng:{}}}", self.lat, self.lng)
    }
}

impl From<Entry> for MapPin {
    fn from(e: Entry) -> Self {
        e.location.into()
    }
}

impl From<&Entry> for MapPin {
    fn from(e: &Entry) -> Self {
        (&e.location).into()
    }
}

impl From<Location> for MapPin {
    fn from(l: Location) -> Self {
        (&l).into()
    }
}

impl From<&Location> for MapPin {
    fn from(l: &Location) -> Self {
        MapPin {
            lat: l.pos.lat().to_deg(),
            lng: l.pos.lng().to_deg(),
        }
    }
}

fn map_scripts(pins: &[MapPin]) -> Markup {
    let (center, zoom) = match pins.len() {
        1 => ((pins[0].lat, pins[0].lng), 13.0),
        _ => {
            //TODO: calculate center & zoom
            ((48.720, 9.152), 6.0)
        }
    };

    let center = format!("[{},{}]", center.0, center.1);

    let pins: String = pins
        .iter()
        .map(|p| p.to_js_object_string())
        .collect::<Vec<_>>()
        .join(",");

    html! {
      script{
        (format!("window.OFDB_MAP_PINS=[{}];window.OFDB_MAP_ZOOM={};OFDB_MAP_CENTER={};",
                 pins,
                 zoom,
                 center))
      }
      script
        src=(LEAFLET_JS_URL)
        integrity=(LEAFLET_JS_SHA512)
        crossorigin="anonymous" {}
      script src=(MAP_JS_URL){}
    }
}

pub fn events(events: &[Event]) -> Markup {
    page(
        "List of Events",
        None,
        html! {
            div class="events" {
                h3 { "Events" }
                ul class="event-list" {
                    @for e in events {
                        li {
                            a href=(format!("/events/{}", e.id)) {
                                div {
                                    h4 {
                                        span class="title" { (e.title) }
                                        " "
                                        span class="date" {
                                            (e.start.format("%d.%m.%y"))
                                        }
                                    }
                                    p {
                                        @if let Some(ref l) = e.location {
                                            @if let Some(ref a) = l.address {
                                                @if let Some(ref city) = a.city {
                                                    span class="city" { (city) }
                                                    br;
                                                }
                                            }
                                        }
                                        @if let Some(ref o) = e.organizer {
                                        span class="organizer" { (o) }
                                        }
                                    }
                                }
                            }
                        }
                    }
                }
            }
        },
    )
}

pub fn login(flash: Option<FlashMessage>) -> Markup {
    flash_page(
        "Login",
        None,
        flash,
        html! {
          form class="login" action="login" method="POST" {
              fieldset{
                label {
                    "eMail:"
                    br;
                    input type="email" name="email" placeholder="eMail address";
                }
                    br;
                label{
                    "Password:"
                    br;
                    input type="password" name="password" placeholder="Password";
                }
                br;
                input type="submit" value="login";
              }
          }
        },
    )
}

pub fn register(flash: Option<FlashMessage>) -> Markup {
    flash_page(
        "Register",
        None,
        flash,
        html! {
          form class="register" action="register" method="POST" {
              fieldset{
                label {
                    "eMail:"
                    br;
                    input type="email" name="email" placeholder="eMail address";
                }
                    br;
                label{
                    "Password:"
                    br;
                    input type="password" name="password" placeholder="Password";
                }
                br;
                input type="submit" value="register";
              }
          }
        },
    )
}

fn flash_msg(flash: Option<FlashMessage>) -> Markup {
    html! {
        @if let Some(msg) = flash {
            div class=(format!("flash {}", msg.name())) {
                (msg.msg())
            }
        }
    }
}

fn flash_page(
    title: &str,
    h: Option<Markup>,
    flash: Option<FlashMessage>,
    content: Markup,
) -> Markup {
    page(
        title,
        h,
        html! {
          (flash_msg(flash))
          (content)
        },
    )
}

fn page(title: &str, h: Option<Markup>, content: Markup) -> Markup {
    html! {
        (DOCTYPE)
        head{
            meta charset="utf-8";
            meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no";
            title {(title)}
            link rel="stylesheet" href=(MAIN_CSS_URL);
            @if let Some(h) = h {
               (h)
            }
        }
        body{
            (content)
        }
    }
}
<|endoftext|>


<commit_before>
use {Field, Borrowed, Value};
use vecmath::{rotate_radians, multiply, translate, scale, shear};
use {Transform2d, Matrix2d, Rectangle, Color};
use {Fill, Clear, BackEnd};
use triangulation::{rect_tri_list_xy_f32, rect_tri_list_rgba_f32};

/// A rectangle color context.
pub struct RectangleColorContext<'a> {
    /// Base/original transformation.
    pub base: Field<'a, Matrix2d>,
    /// Current transformation.
    pub transform: Field<'a, Matrix2d>,
    /// Current rectangle.
    pub rect: Field<'a, Rectangle>,
    /// Current color.
    pub color: Field<'a, Color>,
}

impl<'a> Transform2d<'a> for RectangleColorContext<'a> {
    #[inline(always)]
    fn trans(&'a self, x: f64, y: f64) -> RectangleColorContext<'a> {
        RectangleColorContext {
            base: Borrowed(self.base.get()),
            transform: {
                let trans = translate(x, y);
                Value(multiply(&trans, self.transform.get()))
            },
            rect: Borrowed(self.rect.get()),
            color: Borrowed(self.color.get()),
        }
    }

    #[inline(always)]
    fn rot_rad(&'a self, angle: f64) -> RectangleColorContext<'a> {
        RectangleColorContext {
            base: Borrowed(self.base.get()),
            transform: {
                let rot = rotate_radians(angle);
                Value(multiply(&rot, self.transform.get()))
            },
            rect: Borrowed(self.rect.get()),
            color: Borrowed(self.color.get()),
        }
    }

    #[inline(always)]
    fn scale(&'a self, sx: f64, sy: f64) -> RectangleColorContext<'a> {
        RectangleColorContext {
            base: Borrowed(self.base.get()),
            transform: {
                let scale = scale(sx, sy);
                Value(multiply(&scale, self.transform.get()))
            },
            rect: Borrowed(self.rect.get()),
            color: Borrowed(self.color.get()),
        }
    }

    #[inline(always)]
    fn shear(&'a self, sx: f64, sy: f64) -> RectangleColorContext<'a> {
        RectangleColorContext {
            base: Borrowed(self.base.get()),
            transform: {
                let shear = shear(sx, sy);
                Value(multiply(&shear, self.transform.get()))
            },
            rect: Borrowed(self.rect.get()),
            color: Borrowed(self.color.get()),
        }
    }
}

impl<'a> Fill<'a> for RectangleColorContext<'a> {
    fn fill<B: BackEnd>(&'a self, back_end: &mut B) {
        if back_end.supports_tri_list_xy_rgba_f32() {
            let rect = self.rect.get();
            let rect: [f32, ..4] = [rect[0] as f32, rect[1] as f32, rect[2] as f32, rect[3] as f32];
            let color = self.color.get();
            let color: [f32, ..4] = [color[0] as f32, color[1] as f32, color[2] as f32, color[3] as f32];
            back_end.tri_list_xy_rgba_f32(
                rect_tri_list_xy_f32(rect),
                rect_tri_list_rgba_f32(color)
            );
            return;
        }

        unimplemented!();
    }
}

impl<'a> Clear for RectangleColorContext<'a> {
    fn clear<B: BackEnd>(&self, back_end: &mut B) {
        if back_end.supports_clear_rgba() {
            let color = self.color.get();
            back_end.clear_rgba(color[0], color[1], color[2], color[3]);
        } else {
            unimplemented!();
        }
    }
}
<commit_msg>Made Fill less error prone to changes<commit_after>
use {Field, Borrowed, Value};
use vecmath::{rotate_radians, multiply, translate, scale, shear};
use {Transform2d, Matrix2d, Rectangle, Color};
use {Fill, Clear, BackEnd};
use triangulation::{rect_tri_list_xy_f32, rect_tri_list_rgba_f32};

/// A rectangle color context.
pub struct RectangleColorContext<'a> {
    /// Base/original transformation.
    pub base: Field<'a, Matrix2d>,
    /// Current transformation.
    pub transform: Field<'a, Matrix2d>,
    /// Current rectangle.
    pub rect: Field<'a, Rectangle>,
    /// Current color.
    pub color: Field<'a, Color>,
}

impl<'a> Transform2d<'a> for RectangleColorContext<'a> {
    #[inline(always)]
    fn trans(&'a self, x: f64, y: f64) -> RectangleColorContext<'a> {
        RectangleColorContext {
            base: Borrowed(self.base.get()),
            transform: {
                let trans = translate(x, y);
                Value(multiply(&trans, self.transform.get()))
            },
            rect: Borrowed(self.rect.get()),
            color: Borrowed(self.color.get()),
        }
    }

    #[inline(always)]
    fn rot_rad(&'a self, angle: f64) -> RectangleColorContext<'a> {
        RectangleColorContext {
            base: Borrowed(self.base.get()),
            transform: {
                let rot = rotate_radians(angle);
                Value(multiply(&rot, self.transform.get()))
            },
            rect: Borrowed(self.rect.get()),
            color: Borrowed(self.color.get()),
        }
    }

    #[inline(always)]
    fn scale(&'a self, sx: f64, sy: f64) -> RectangleColorContext<'a> {
        RectangleColorContext {
            base: Borrowed(self.base.get()),
            transform: {
                let scale = scale(sx, sy);
                Value(multiply(&scale, self.transform.get()))
            },
            rect: Borrowed(self.rect.get()),
            color: Borrowed(self.color.get()),
        }
    }

    #[inline(always)]
    fn shear(&'a self, sx: f64, sy: f64) -> RectangleColorContext<'a> {
        RectangleColorContext {
            base: Borrowed(self.base.get()),
            transform: {
                let shear = shear(sx, sy);
                Value(multiply(&shear, self.transform.get()))
            },
            rect: Borrowed(self.rect.get()),
            color: Borrowed(self.color.get()),
        }
    }
}

impl<'a> Fill<'a> for RectangleColorContext<'a> {
    fn fill<B: BackEnd>(&'a self, back_end: &mut B) {
        if back_end.supports_tri_list_xy_rgba_f32() {
            let rect = self.rect.get();
            let rect: [f32, ..4] = [rect[0] as f32, rect[1] as f32, rect[2] as f32, rect[3] as f32];
            let color = self.color.get();
            let color: [f32, ..4] = [color[0] as f32, color[1] as f32, color[2] as f32, color[3] as f32];
            back_end.tri_list_xy_rgba_f32(
                rect_tri_list_xy_f32(rect),
                rect_tri_list_rgba_f32(color)
            );
        } else {
            unimplemented!();
        }
    }
}

impl<'a> Clear for RectangleColorContext<'a> {
    fn clear<B: BackEnd>(&self, back_end: &mut B) {
        if back_end.supports_clear_rgba() {
            let color = self.color.get();
            back_end.clear_rgba(color[0], color[1], color[2], color[3]);
        } else {
            unimplemented!();
        }
    }
}
<|endoftext|>


<commit_before>use futures::channel::oneshot;

///
/// The queue resumer is used to resume a queue that was suspended using the `suspend()` function in the scheduler
///
pub struct QueueResumer {
    pub (super) resume: oneshot::Sender<()>
}

impl QueueResumer {
    ///
    /// Resumes a suspended queue
    ///
    pub fn resume(mut self) {
        // Send to the channel
        self.resume.send(()).ok();
    }
}
<commit_msg>This does not need to be mut<commit_after>use futures::channel::oneshot;

///
/// The queue resumer is used to resume a queue that was suspended using the `suspend()` function in the scheduler
///
pub struct QueueResumer {
    pub (super) resume: oneshot::Sender<()>
}

impl QueueResumer {
    ///
    /// Resumes a suspended queue
    ///
    pub fn resume(self) {
        // Send to the channel
        self.resume.send(()).ok();
    }
}
<|endoftext|>


<commit_before>// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

/*!
Syntax extension to create floating point literals from hexadecimal strings

Once loaded, hexfloat!() is called with a string containing the hexadecimal
floating-point literal, and an optional type (f32 or f64).
If the type is omitted, the literal is treated the same as a normal unsuffixed
literal.

# Examples

To load the extension and use it:

```rust,ignore
#[phase(syntax)]
extern crate hexfloat;

fn main() {
    let val = hexfloat!("0x1.ffffb4", f32);
}
```

# References

* [ExploringBinary: hexadecimal floating point constants]
  (http://www.exploringbinary.com/hexadecimal-floating-point-constants/)

*/

#![crate_id = "hexfloat#0.11.0-pre"]
#![crate_type = "rlib"]
#![crate_type = "dylib"]
#![license = "MIT/ASL2"]
#![doc(html_logo_url = "http://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png",
       html_favicon_url = "http://www.rust-lang.org/favicon.ico",
       html_root_url = "http://static.rust-lang.org/doc/master")]

#![deny(deprecated_owned_vector)]
#![feature(macro_registrar, managed_boxes)]

extern crate syntax;

use syntax::ast;
use syntax::ast::Name;
use syntax::codemap::{Span, mk_sp};
use syntax::ext::base;
use syntax::ext::base::{SyntaxExtension, BasicMacroExpander, NormalTT, ExtCtxt, MacExpr};
use syntax::ext::build::AstBuilder;
use syntax::parse;
use syntax::parse::token;

#[macro_registrar]
pub fn macro_registrar(register: |Name, SyntaxExtension|) {
    register(token::intern("hexfloat"),
        NormalTT(box BasicMacroExpander {
            expander: expand_syntax_ext,
            span: None,
        },
        None));
}

//Check if the literal is valid (as LLVM expects),
//and return a descriptive error if not.
fn hex_float_lit_err(s: &str) -> Option<(uint, ~str)> {
    let mut chars = s.chars().peekable();
    let mut i = 0;
    if chars.peek() == Some(&'-') { chars.next(); i+= 1 }
    if chars.next() != Some('0') { return Some((i, "Expected '0'".to_owned())); } i+=1;
    if chars.next() != Some('x') { return Some((i, "Expected 'x'".to_owned())); } i+=1;
    let mut d_len = 0;
    for _ in chars.take_while(|c| c.is_digit_radix(16)) { chars.next(); i+=1; d_len += 1;}
    if chars.next() != Some('.') { return Some((i, "Expected '.'".to_owned())); } i+=1;
    let mut f_len = 0;
    for _ in chars.take_while(|c| c.is_digit_radix(16)) { chars.next(); i+=1; f_len += 1;}
    if d_len == 0 && f_len == 0 {
        return Some((i, "Expected digits before or after decimal point".to_owned()));
    }
    if chars.next() != Some('p') { return Some((i, "Expected 'p'".to_owned())); } i+=1;
    if chars.peek() == Some(&'-') { chars.next(); i+= 1 }
    let mut e_len = 0;
    for _ in chars.take_while(|c| c.is_digit()) { chars.next(); i+=1; e_len += 1}
    if e_len == 0 {
        return Some((i, "Expected exponent digits".to_owned()));
    }
    match chars.next() {
        None => None,
        Some(_) => Some((i, "Expected end of string".to_owned()))
    }
}

pub fn expand_syntax_ext(cx: &mut ExtCtxt, sp: Span, tts: &[ast::TokenTree])
                         -> Box<base::MacResult> {
    let (expr, ty_lit) = parse_tts(cx, tts);

    let ty = match ty_lit {
        None => None,
        Some(Ident{ident, span}) => match token::get_ident(ident).get() {
            "f32" => Some(ast::TyF32),
            "f64" => Some(ast::TyF64),
            "f128" => Some(ast::TyF128),
            _ => {
                cx.span_err(span, "invalid floating point type in hexfloat!");
                None
            }
        }
    };

    let s = match expr.node {
        // expression is a literal
        ast::ExprLit(lit) => match lit.node {
            // string literal
            ast::LitStr(ref s, _) => {
                s.clone()
            }
            _ => {
                cx.span_err(expr.span, "unsupported literal in hexfloat!");
                return base::DummyResult::expr(sp);
            }
        },
        _ => {
            cx.span_err(expr.span, "non-literal in hexfloat!");
            return base::DummyResult::expr(sp);
        }
    };

    {
        let err = hex_float_lit_err(s.get());
        match err {
            Some((err_pos, err_str)) => {
                let pos = expr.span.lo + syntax::codemap::Pos::from_uint(err_pos + 1);
                let span = syntax::codemap::mk_sp(pos,pos);
                cx.span_err(span, format!("invalid hex float literal in hexfloat!: {}", err_str));
                return base::DummyResult::expr(sp);
            }
            _ => ()
        }
    }

    let lit = match ty {
        None => ast::LitFloatUnsuffixed(s),
        Some (ty) => ast::LitFloat(s, ty)
    };
    MacExpr::new(cx.expr_lit(sp, lit))
}

struct Ident {
    ident: ast::Ident,
    span: Span
}

fn parse_tts(cx: &ExtCtxt, tts: &[ast::TokenTree]) -> (@ast::Expr, Option<Ident>) {
    let p = &mut parse::new_parser_from_tts(cx.parse_sess(),
                                            cx.cfg(),
                                            tts.iter()
                                               .map(|x| (*x).clone())
                                               .collect());
    let ex = p.parse_expr();
    let id = if p.token == token::EOF {
        None
    } else {
        p.expect(&token::COMMA);
        let lo = p.span.lo;
        let ident = p.parse_ident();
        let hi = p.last_span.hi;
        Some(Ident{ident: ident, span: mk_sp(lo, hi)})
    };
    if p.token != token::EOF {
        p.unexpected();
    }
    (ex, id)
}

// FIXME (10872): This is required to prevent an LLVM assert on Windows
#[test]
fn dummy_test() { }
<commit_msg>libhexfloat: Remove all uses of `~str` from `libhexfloat`<commit_after>// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

/*!
Syntax extension to create floating point literals from hexadecimal strings

Once loaded, hexfloat!() is called with a string containing the hexadecimal
floating-point literal, and an optional type (f32 or f64).
If the type is omitted, the literal is treated the same as a normal unsuffixed
literal.

# Examples

To load the extension and use it:

```rust,ignore
#[phase(syntax)]
extern crate hexfloat;

fn main() {
    let val = hexfloat!("0x1.ffffb4", f32);
}
```

# References

* [ExploringBinary: hexadecimal floating point constants]
  (http://www.exploringbinary.com/hexadecimal-floating-point-constants/)

*/

#![crate_id = "hexfloat#0.11.0-pre"]
#![crate_type = "rlib"]
#![crate_type = "dylib"]
#![license = "MIT/ASL2"]
#![doc(html_logo_url = "http://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png",
       html_favicon_url = "http://www.rust-lang.org/favicon.ico",
       html_root_url = "http://static.rust-lang.org/doc/master")]

#![deny(deprecated_owned_vector)]
#![feature(macro_registrar, managed_boxes)]

extern crate syntax;

use syntax::ast;
use syntax::ast::Name;
use syntax::codemap::{Span, mk_sp};
use syntax::ext::base;
use syntax::ext::base::{SyntaxExtension, BasicMacroExpander, NormalTT, ExtCtxt, MacExpr};
use syntax::ext::build::AstBuilder;
use syntax::parse;
use syntax::parse::token;

#[macro_registrar]
pub fn macro_registrar(register: |Name, SyntaxExtension|) {
    register(token::intern("hexfloat"),
        NormalTT(box BasicMacroExpander {
            expander: expand_syntax_ext,
            span: None,
        },
        None));
}

//Check if the literal is valid (as LLVM expects),
//and return a descriptive error if not.
fn hex_float_lit_err(s: &str) -> Option<(uint, StrBuf)> {
    let mut chars = s.chars().peekable();
    let mut i = 0;
    if chars.peek() == Some(&'-') { chars.next(); i+= 1 }
    if chars.next() != Some('0') {
        return Some((i, "Expected '0'".to_strbuf()));
    } i+=1;
    if chars.next() != Some('x') {
        return Some((i, "Expected 'x'".to_strbuf()));
    } i+=1;
    let mut d_len = 0;
    for _ in chars.take_while(|c| c.is_digit_radix(16)) { chars.next(); i+=1; d_len += 1;}
    if chars.next() != Some('.') {
        return Some((i, "Expected '.'".to_strbuf()));
    } i+=1;
    let mut f_len = 0;
    for _ in chars.take_while(|c| c.is_digit_radix(16)) { chars.next(); i+=1; f_len += 1;}
    if d_len == 0 && f_len == 0 {
        return Some((i, "Expected digits before or after decimal \
                         point".to_strbuf()));
    }
    if chars.next() != Some('p') {
        return Some((i, "Expected 'p'".to_strbuf()));
    } i+=1;
    if chars.peek() == Some(&'-') { chars.next(); i+= 1 }
    let mut e_len = 0;
    for _ in chars.take_while(|c| c.is_digit()) { chars.next(); i+=1; e_len += 1}
    if e_len == 0 {
        return Some((i, "Expected exponent digits".to_strbuf()));
    }
    match chars.next() {
        None => None,
        Some(_) => Some((i, "Expected end of string".to_strbuf()))
    }
}

pub fn expand_syntax_ext(cx: &mut ExtCtxt, sp: Span, tts: &[ast::TokenTree])
                         -> Box<base::MacResult> {
    let (expr, ty_lit) = parse_tts(cx, tts);

    let ty = match ty_lit {
        None => None,
        Some(Ident{ident, span}) => match token::get_ident(ident).get() {
            "f32" => Some(ast::TyF32),
            "f64" => Some(ast::TyF64),
            "f128" => Some(ast::TyF128),
            _ => {
                cx.span_err(span, "invalid floating point type in hexfloat!");
                None
            }
        }
    };

    let s = match expr.node {
        // expression is a literal
        ast::ExprLit(lit) => match lit.node {
            // string literal
            ast::LitStr(ref s, _) => {
                s.clone()
            }
            _ => {
                cx.span_err(expr.span, "unsupported literal in hexfloat!");
                return base::DummyResult::expr(sp);
            }
        },
        _ => {
            cx.span_err(expr.span, "non-literal in hexfloat!");
            return base::DummyResult::expr(sp);
        }
    };

    {
        let err = hex_float_lit_err(s.get());
        match err {
            Some((err_pos, err_str)) => {
                let pos = expr.span.lo + syntax::codemap::Pos::from_uint(err_pos + 1);
                let span = syntax::codemap::mk_sp(pos,pos);
                cx.span_err(span, format!("invalid hex float literal in hexfloat!: {}", err_str));
                return base::DummyResult::expr(sp);
            }
            _ => ()
        }
    }

    let lit = match ty {
        None => ast::LitFloatUnsuffixed(s),
        Some (ty) => ast::LitFloat(s, ty)
    };
    MacExpr::new(cx.expr_lit(sp, lit))
}

struct Ident {
    ident: ast::Ident,
    span: Span
}

fn parse_tts(cx: &ExtCtxt, tts: &[ast::TokenTree]) -> (@ast::Expr, Option<Ident>) {
    let p = &mut parse::new_parser_from_tts(cx.parse_sess(),
                                            cx.cfg(),
                                            tts.iter()
                                               .map(|x| (*x).clone())
                                               .collect());
    let ex = p.parse_expr();
    let id = if p.token == token::EOF {
        None
    } else {
        p.expect(&token::COMMA);
        let lo = p.span.lo;
        let ident = p.parse_ident();
        let hi = p.last_span.hi;
        Some(Ident{ident: ident, span: mk_sp(lo, hi)})
    };
    if p.token != token::EOF {
        p.unexpected();
    }
    (ex, id)
}

// FIXME (10872): This is required to prevent an LLVM assert on Windows
#[test]
fn dummy_test() { }
<|endoftext|>


<commit_before>#[feature(globs,phase)];
#[phase(syntax, link)] extern crate log;

extern crate leveldb;

#[cfg(test)]
mod tests {
  use leveldb::database::Database;
  use leveldb::iterator::Iterable;
  use leveldb::options::{Options,ReadOptions,WriteOptions};

  #[test]
  fn test_create_options() {
    Options::new();
  }

  #[test]
  fn test_open_database() {
    let mut opts = Options::new();
    opts.create_if_missing(true);
    let res = Database::open(~"testdbs/create_if_missing", opts);
    assert!(res.is_ok());
  }

  #[test]
  fn test_open_non_existant_database_without_create() {
    let mut opts = Options::new();
    opts.create_if_missing(false);
    let res = Database::open(~"testdbs/missing", opts);
    assert!(res.is_err());
  }

  #[test]
  fn test_write_to_database() {
    let mut opts = Options::new();
    opts.create_if_missing(true);
    let mut database = match Database::open(~"testdbs/put_simple", opts) {
      Ok(db) => { db },
      Err(_) => { fail!("failed to open database") }
    };
    let write_opts = WriteOptions::new();
    let result = database.put(write_opts,
                              &[1],
                              &[1]);
    assert!(result.is_ok());
  }

  #[test]
  fn test_delete_from_database() {
    let mut opts = Options::new();
    opts.create_if_missing(true);
    let mut database = match Database::open(~"testdbs/delete_simple", opts) {
      Ok(db) => { db },
      Err(_) => { fail!("failed to open database") }
    };
    let write_opts = WriteOptions::new();
    let result = database.put(write_opts,
                              &[1],
                              &[1]);
    assert!(result.is_ok());
    let write2 = WriteOptions::new();
    let res2 = database.delete(write2,
                               &[1]);
    assert!(res2.is_ok());
  }

  #[test]
  fn test_get_from_empty_database() {
    let mut opts = Options::new();
    opts.create_if_missing(true);
    let mut database = match Database::open(~"testdbs/get_simple", opts) {
      Ok(db) => { db },
      Err(_) => { fail!("failed to open database") }
    };
    let read_opts = ReadOptions::new();
    let res = database.get(read_opts, [1,2,3]);
    match res {
      Ok(data) => { assert!(data.is_none()) },
      Err(_) => { fail!("failed reading data") }
    }
  }

  #[test]
  fn test_get_from_filled_database() {
    let mut opts = Options::new();
    opts.create_if_missing(true);
    let mut database = match Database::open(~"testdbs/get_filled", opts) {
      Ok(db) => { db },
      Err(_) => { fail!("failed to open database") }
    };
    let write_opts = WriteOptions::new();
    let result = database.put(write_opts,
                              &[1],
                              &[1]);
    assert!(result.is_ok());
    let read_opts = ReadOptions::new();
    let res = database.get(read_opts,
                            &[1]);
    match res {
      Ok(data) => {
        assert!(data.is_some())
        let data = data.unwrap();
        assert_eq!(data, ~[1]);
      },
      Err(_) => { fail!("failed reading data") }
    }
  }

  #[test]
  fn test_iterator() {
    let mut opts = Options::new();
    opts.create_if_missing(true);
    let mut database = match Database::open(~"testdbs/iter", opts) {
      Ok(db) => { db },
      Err(_) => { fail!("failed to open database") }
    };
    let write_opts = WriteOptions::new();
    database.put(write_opts,
                 &[1],
                 &[1]);
    let write_opts2 = WriteOptions::new();
    database.put(write_opts2,
                 &[2],
                 &[2]);
    let read_opts = ReadOptions::new();
    let mut iter = database.iter(read_opts);
    assert!(iter.valid());
    assert!(iter.next().is_some());
    assert!(iter.next().is_some());
    assert!(iter.next().is_none());
  }
}
<commit_msg>Refactor test suite<commit_after>#[feature(globs,phase)];
#[phase(syntax, link)] extern crate log;

extern crate leveldb;

#[cfg(test)]
mod tests {
  use leveldb::database::Database;
  use leveldb::iterator::Iterable;
  use leveldb::options::{Options,ReadOptions,WriteOptions};

  fn open_database(name: ~str, create_if_missing: bool) -> Database {
    let mut opts = Options::new();
    opts.create_if_missing(create_if_missing);
    match Database::open(name, opts) {
      Ok(db) => { db },
      Err(_) => { fail!("failed to open database") }
    }
  }

  fn db_put_simple(database: &mut Database, key: &[u8], val: &[u8]) {
    let write_opts = WriteOptions::new();
    match database.put(write_opts, key, val) {
      Ok(_) => { () },
      Err(_) => { fail!("failed to write to database") }
    }
  }

  #[test]
  fn test_create_options() {
    Options::new();
  }

  #[test]
  fn test_open_database() {
    let mut opts = Options::new();
    opts.create_if_missing(true);
    let res = Database::open(~"testdbs/create_if_missing", opts);
    assert!(res.is_ok());
  }

  #[test]
  fn test_open_non_existant_database_without_create() {
    let mut opts = Options::new();
    opts.create_if_missing(false);
    let res = Database::open(~"testdbs/missing", opts);
    assert!(res.is_err());
  }

  #[test]
  fn test_write_to_database() {
    let mut database = open_database(~"testdbs/put_simple", true);
    let write_opts = WriteOptions::new();
    let result = database.put(write_opts,
                              &[1],
                              &[1]);
    assert!(result.is_ok());
  }

  #[test]
  fn test_delete_from_database() {
    let mut database = open_database(~"testdbs/delete_simple", true);
    db_put_simple(&mut database, &[1], &[1]);

    let write2 = WriteOptions::new();
    let res2 = database.delete(write2,
                               &[1]);
    assert!(res2.is_ok());
  }

  #[test]
  fn test_get_from_empty_database() {
    let mut database = open_database(~"testdbs/get_simple", true);
    let read_opts = ReadOptions::new();
    let res = database.get(read_opts, [1,2,3]);
    match res {
      Ok(data) => { assert!(data.is_none()) },
      Err(_) => { fail!("failed reading data") }
    }
  }

  #[test]
  fn test_get_from_filled_database() {
    let mut database = open_database(~"testdbs/get_filled", true);
    db_put_simple(&mut database, &[1], &[1]);

    let read_opts = ReadOptions::new();
    let res = database.get(read_opts,
                            &[1]);
    match res {
      Ok(data) => {
        assert!(data.is_some())
        let data = data.unwrap();
        assert_eq!(data, ~[1]);
      },
      Err(_) => { fail!("failed reading data") }
    }
  }

  #[test]
  fn test_iterator() {
    let mut database = open_database(~"testdbs/iter", true);
    db_put_simple(&mut database, &[1], &[1]);
    db_put_simple(&mut database, &[2], &[2]);

    let read_opts = ReadOptions::new();
    let mut iter = database.iter(read_opts);
    assert!(iter.valid());
    assert!(iter.next().is_some());
    assert!(iter.next().is_some());
    assert!(iter.next().is_none());
  }
}
<|endoftext|>


<commit_before>use num::{Float, Num};
use num::pow;
use std::fmt;
use std::ops::{Add, Sub, Mul, Neg, Div};

/// Vector of 3 dimensions with a defined coordinates and origen
///
/// # Remarks
///
/// * This struct is implemented to be used with numerical types, not tested
///   for strings, bools, or other types.
/// * By default, the origen is [0, 0, 0] and currently this cannot be modified.
#[derive(Clone, Copy)]
pub struct Vector3D<N: Copy> {
    x: N,
    y: N,
    z: N,
}

////////////////////////////////////////////////////////////////////////////////
// Inherent methods
////////////////////////////////////////////////////////////////////////////////

impl<N: Copy + Num> Vector3D<N> {

    /// Returns the `x` coordinate
    #[inline]
    pub fn x(&self) -> N {
        self.x
    }

    /// Returns the `y` coordinate
    #[inline]
    pub fn y(&self) -> N {
        self.y
    }

    /// Returns the `z` coordinate
    #[inline]
    pub fn z(&self) -> N {
        self.z
    }

    /// Modifies the `X` coordinate
    ///
    /// # Arguments
    ///
    /// * `new_x`: new X value
    #[inline]
    pub fn set_x(&mut self, new_x: N) {
        self.x = new_x;
    }

    /// Modifies the `Y` coordinate
    ///
    /// # Arguments
    ///
    /// * `new_y`: new Y value
    #[inline]
    pub fn set_y(&mut self, new_y: N) {
        self.y = new_y;
    }

    // Modifies the `Z` coordinate
    ///
    /// # Arguments
    ///
    /// * `new_z`: new Z value
    #[inline]
    pub fn set_z(&mut self, new_z: N) {
        self.z = new_z;
    }

    /// Modifies all coordinates
    ///
    /// # Arguments
    ///
    /// * `new_x`: new X value
    /// * `new_y`: new Y value
    /// * `new_z`: new Z value
    #[inline]
    pub fn set(&mut self, new_x: N, new_y: N, new_z: N) {
        self.x = new_x;
        self.y = new_y;
        self.z = new_z;
    }

    /// Initializes a Vector3D with default coordinates' values
    #[inline]
    pub fn new() -> Vector3D<N> where N: Default {
        Vector3D { x: N::default(),
                   y: N::default(),
                   z: N::default() }
    }

    /// Initializes a Vector3D with given coordinates
    ///
    /// # Arguments
    ///
    /// * `x`: X value
    /// * `y`: Y value
    /// * `z`: Z value
    #[inline]
    pub fn init(x: N, y: N, z: N) -> Vector3D<N> {
        Vector3D { x: x,
                   y: y,
                   z: z }
    }
    /// Scale a Vector with a given number
    ///
    /// # Arguments
    ///
    /// * `scalar`: scalar value
    #[inline]
    pub fn scale(self, scalar: N) -> Vector3D<N> {
        Vector3D::<N>::init(self.x * scalar, self.y * scalar, self.z * scalar)
    }

    /// Scale a vector with a given vector
    ///
    /// # Arguments
    ///
    /// * `vec`: vector value
    #[inline]
    pub fn scale_vec(self, vec: &Vector3D<N>) -> Vector3D<N> {
        Vector3D::<N>::init(self.x *  vec.x(), self.y *  vec.y(), self.z *  vec.z())
    }

    /// Cross multiplication of two vectors
    ///
    /// # Arguments
    ///
    /// * `first`: first cross vector
    /// * `second`: second cross vector
    ///
    /// # Remarks
    ///
    /// * The `origin` of the output vector will be extracted from the `first` input vector
    #[inline]
    pub fn cross(first: &Vector3D<N>, second: &Vector3D<N>) -> Vector3D<N>
        where N: Default + Neg<Output = N> {

        let new_x: N = (first.y * second.z) - (first.z * second.y);
        let new_y: N = -((first.x * second.z) - (first.z * second.x));
        let new_z: N = (first.x * second.y) - (first.y * second.x);

        Vector3D { x: new_x, y: new_y, z: new_z }
    }

    /// Dot operation for two vectors
    ///
    /// # Arguments
    ///
    /// * `other`: second vector for the dot
    #[inline]
    pub fn dot(&self, other: &Vector3D<N>) -> N {
        ((self.x*other.x) + (self.y*other.y) + (self.z*other.z))
    }

    /// Normalize the vector
    ///
    /// # Remarks
    ///
    /// * Since this operation requires an `sqrt`, it's just available for float vectors
    #[inline]
    pub fn norm(self) -> Vector3D<N> where N: Float {
        let value = (self.x*self.x) + (self.y*self.y) + (self.z*self.z);

        self.scale(value.sqrt().recip())
    }

    /// Return the Eucledian distance from vector
    #[inline]
    pub fn dist(&self) -> f64 where N: Into<f64> {
        (pow(self.x, 2) + pow(self.y, 2) + pow(self.z, 2)).into().sqrt()
    }

    #[inline]
    pub fn max(&self) -> N where N: PartialOrd {
        if self.x >= self.y && self.x >= self.z {
           self.x
        } else if self.y >= self.z {
            self.y
        } else {
            self.z
        }
    }

    #[inline]
    pub fn min(&self) -> N where N: PartialOrd {
        if self.x <= self.y && self.x <= self.z {
            self.x
        } else if self.y <= self.z {
           self.y
        } else {
            self.z
        }
    }
}

////////////////////////////////////////////////////////////////////////////////
// Traits
////////////////////////////////////////////////////////////////////////////////

/// Equivalence ´==´ implementation for Vector3D
impl<N: Copy + PartialEq> PartialEq for Vector3D<N> {
    fn eq(&self, other: &Vector3D<N>) -> bool {
        if (self.x == other.x) && (self.y == other.y) && (self.z == other.z) {
            return true;
        }
        false
    }
}

/// Add implementation `+` for Vector3D
///
/// # Remarks
///
/// * The `origin` of the output vector will be extracted from the `self` input vector
impl<N: Copy + Num> Add for Vector3D<N> {
    type Output = Vector3D<N>;

    fn add(self, other: Vector3D<N>) -> Vector3D<N> {
        Vector3D {x: self.x + other.x, y: self.y + other.y, z: self.z + other.z}
    }
}

/// Sub implementation `-` for Vector3D
///
/// # Remarks
///
/// * The `origin` of the output vector will be extracted from the `self` input vector
impl<N: Copy + Num> Sub for Vector3D<N> {
    type Output = Vector3D<N>;

    fn sub(self, other: Vector3D<N>) -> Vector3D<N> {
        Vector3D {x: self.x - other.x, y: self.y - other.y, z: self.z - other.z}
    }
}

/// Mul implementation `*` for Vector3D
///
/// # Remarks
///
/// * The `origin` of the output vector will be extracted from the `self` input vector
impl<N: Copy + Num> Mul for Vector3D<N> {
    type Output = Vector3D<N>;

    fn mul(self, other: Vector3D<N>) -> Vector3D<N> {
        Vector3D {x: self.x * other.x, y: self.y * other.y, z: self.z * other.z}
    }
}

impl<N: Copy + Num> Mul<N> for Vector3D<N> {
    type Output = Vector3D<N>;

    fn mul(self, other: N) -> Vector3D<N> {
        Vector3D {x: self.x * other, y: self.y * other, z: self.z * other}
    }
}

impl<N: Copy + Num> Div<N> for Vector3D<N> {
    type Output = Vector3D<N>;

    fn div(self, other: N) -> Vector3D<N> {
        Vector3D { x: self.x / other, y: self.y / other, z: self.z / other }
    }
}

impl<N: Copy + Num + Neg<Output = N>> Neg for Vector3D<N> {
    type Output = Vector3D<N>;

    fn neg(self) -> Vector3D<N> {
        Vector3D { x: -self.x, y: -self.y, z: -self.z }
    }
}

/// Display implementation for Vector3D
impl<N: Copy + Num> fmt::Display for Vector3D<N> where N: fmt::Display {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "( {x}, {y}, {z} )", x = self.x, y = self.y, z = self.z)
    }
}
<commit_msg>add clamp function for linspace vector3d<commit_after>use num::{Float, Num};
use num::pow;
use std::fmt;
use std::ops::{Add, Sub, Mul, Neg, Div};

/// Vector of 3 dimensions with a defined coordinates and origen
///
/// # Remarks
///
/// * This struct is implemented to be used with numerical types, not tested
///   for strings, bools, or other types.
/// * By default, the origen is [0, 0, 0] and currently this cannot be modified.
#[derive(Clone, Copy)]
pub struct Vector3D<N: Copy> {
    x: N,
    y: N,
    z: N,
}

////////////////////////////////////////////////////////////////////////////////
// Inherent methods
////////////////////////////////////////////////////////////////////////////////

impl<N: Copy + Num> Vector3D<N> {

    /// Returns the `x` coordinate
    #[inline]
    pub fn x(&self) -> N {
        self.x
    }

    /// Returns the `y` coordinate
    #[inline]
    pub fn y(&self) -> N {
        self.y
    }

    /// Returns the `z` coordinate
    #[inline]
    pub fn z(&self) -> N {
        self.z
    }

    /// Modifies the `X` coordinate
    ///
    /// # Arguments
    ///
    /// * `new_x`: new X value
    #[inline]
    pub fn set_x(&mut self, new_x: N) {
        self.x = new_x;
    }

    /// Modifies the `Y` coordinate
    ///
    /// # Arguments
    ///
    /// * `new_y`: new Y value
    #[inline]
    pub fn set_y(&mut self, new_y: N) {
        self.y = new_y;
    }

    // Modifies the `Z` coordinate
    ///
    /// # Arguments
    ///
    /// * `new_z`: new Z value
    #[inline]
    pub fn set_z(&mut self, new_z: N) {
        self.z = new_z;
    }

    /// Modifies all coordinates
    ///
    /// # Arguments
    ///
    /// * `new_x`: new X value
    /// * `new_y`: new Y value
    /// * `new_z`: new Z value
    #[inline]
    pub fn set(&mut self, new_x: N, new_y: N, new_z: N) {
        self.x = new_x;
        self.y = new_y;
        self.z = new_z;
    }

    /// Initializes a Vector3D with default coordinates' values
    #[inline]
    pub fn new() -> Vector3D<N> where N: Default {
        Vector3D { x: N::default(),
                   y: N::default(),
                   z: N::default() }
    }

    /// Initializes a Vector3D with given coordinates
    ///
    /// # Arguments
    ///
    /// * `x`: X value
    /// * `y`: Y value
    /// * `z`: Z value
    #[inline]
    pub fn init(x: N, y: N, z: N) -> Vector3D<N> {
        Vector3D { x: x,
                   y: y,
                   z: z }
    }
    /// Scale a Vector with a given number
    ///
    /// # Arguments
    ///
    /// * `scalar`: scalar value
    #[inline]
    pub fn scale(self, scalar: N) -> Vector3D<N> {
        Vector3D::<N>::init(self.x * scalar, self.y * scalar, self.z * scalar)
    }

    /// Scale a vector with a given vector
    ///
    /// # Arguments
    ///
    /// * `vec`: vector value
    #[inline]
    pub fn scale_vec(self, vec: &Vector3D<N>) -> Vector3D<N> {
        Vector3D::<N>::init(self.x *  vec.x(), self.y *  vec.y(), self.z *  vec.z())
    }

    /// Cross multiplication of two vectors
    ///
    /// # Arguments
    ///
    /// * `first`: first cross vector
    /// * `second`: second cross vector
    ///
    /// # Remarks
    ///
    /// * The `origin` of the output vector will be extracted from the `first` input vector
    #[inline]
    pub fn cross(first: &Vector3D<N>, second: &Vector3D<N>) -> Vector3D<N>
        where N: Default + Neg<Output = N> {

        let new_x: N = (first.y * second.z) - (first.z * second.y);
        let new_y: N = -((first.x * second.z) - (first.z * second.x));
        let new_z: N = (first.x * second.y) - (first.y * second.x);

        Vector3D { x: new_x, y: new_y, z: new_z }
    }

    /// Dot operation for two vectors
    ///
    /// # Arguments
    ///
    /// * `other`: second vector for the dot
    #[inline]
    pub fn dot(&self, other: &Vector3D<N>) -> N {
        ((self.x*other.x) + (self.y*other.y) + (self.z*other.z))
    }

    /// Normalize the vector
    ///
    /// # Remarks
    ///
    /// * Since this operation requires an `sqrt`, it's just available for float vectors
    #[inline]
    pub fn norm(self) -> Vector3D<N> where N: Float {
        let value = (self.x*self.x) + (self.y*self.y) + (self.z*self.z);

        self.scale(value.sqrt().recip())
    }

    /// Return the Eucledian distance from vector
    #[inline]
    pub fn dist(&self) -> f64 where N: Into<f64> {
        (pow(self.x, 2) + pow(self.y, 2) + pow(self.z, 2)).into().sqrt()
    }

    #[inline]
    pub fn max(&self) -> N where N: PartialOrd {
        if self.x >= self.y && self.x >= self.z {
           self.x
        } else if self.y >= self.z {
            self.y
        } else {
            self.z
        }
    }

    #[inline]
    pub fn min(&self) -> N where N: PartialOrd {
        if self.x <= self.y && self.x <= self.z {
            self.x
        } else if self.y <= self.z {
           self.y
        } else {
            self.z
        }
    }

    #[inline]
    pub fn clamp(&self) -> Vector3D<N> where N: Float {
        let func = |x: N| {
            if x < N::zero() { N::zero()  }
                else if x > N::one() { N::one() }
                    else { x }
        };
        Vector3D {
            x: func(self.x),
            y: func(self.y),
            z: func(self.z)
        }
    }
}

////////////////////////////////////////////////////////////////////////////////
// Traits
////////////////////////////////////////////////////////////////////////////////

/// Equivalence ´==´ implementation for Vector3D
impl<N: Copy + PartialEq> PartialEq for Vector3D<N> {
    fn eq(&self, other: &Vector3D<N>) -> bool {
        if (self.x == other.x) && (self.y == other.y) && (self.z == other.z) {
            return true;
        }
        false
    }
}

/// Add implementation `+` for Vector3D
///
/// # Remarks
///
/// * The `origin` of the output vector will be extracted from the `self` input vector
impl<N: Copy + Num> Add for Vector3D<N> {
    type Output = Vector3D<N>;

    fn add(self, other: Vector3D<N>) -> Vector3D<N> {
        Vector3D {x: self.x + other.x, y: self.y + other.y, z: self.z + other.z}
    }
}

/// Sub implementation `-` for Vector3D
///
/// # Remarks
///
/// * The `origin` of the output vector will be extracted from the `self` input vector
impl<N: Copy + Num> Sub for Vector3D<N> {
    type Output = Vector3D<N>;

    fn sub(self, other: Vector3D<N>) -> Vector3D<N> {
        Vector3D {x: self.x - other.x, y: self.y - other.y, z: self.z - other.z}
    }
}

/// Mul implementation `*` for Vector3D
///
/// # Remarks
///
/// * The `origin` of the output vector will be extracted from the `self` input vector
impl<N: Copy + Num> Mul for Vector3D<N> {
    type Output = Vector3D<N>;

    fn mul(self, other: Vector3D<N>) -> Vector3D<N> {
        Vector3D {x: self.x * other.x, y: self.y * other.y, z: self.z * other.z}
    }
}

impl<N: Copy + Num> Mul<N> for Vector3D<N> {
    type Output = Vector3D<N>;

    fn mul(self, other: N) -> Vector3D<N> {
        Vector3D {x: self.x * other, y: self.y * other, z: self.z * other}
    }
}

impl<N: Copy + Num> Div<N> for Vector3D<N> {
    type Output = Vector3D<N>;

    fn div(self, other: N) -> Vector3D<N> {
        Vector3D { x: self.x / other, y: self.y / other, z: self.z / other }
    }
}

impl<N: Copy + Num + Neg<Output = N>> Neg for Vector3D<N> {
    type Output = Vector3D<N>;

    fn neg(self) -> Vector3D<N> {
        Vector3D { x: -self.x, y: -self.y, z: -self.z }
    }
}

/// Display implementation for Vector3D
impl<N: Copy + Num> fmt::Display for Vector3D<N> where N: fmt::Display {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "( {x}, {y}, {z} )", x = self.x, y = self.y, z = self.z)
    }
}
<|endoftext|>


<commit_before>
//! Repeat a stream multiple times.

use std::iter;

use event;
use modifier;
use transform;
use template;
use builder;

/// A stored stream representing an element if the parent stream does.
pub type MaybeElementTemplate<D> = modifier::Derived<template::TemplateStream, D>;

enum RepeatOrElseState<S, I, B, BE, SR>
where
    I: Iterator,
//    B: builder::BuildMutMapped<MaybeElementTemplate<S>, I::Item>,
    BE: builder::BuildOnce<S>,
{
    Start {
        stream: S,
        iter: I,
        builder: B,
        else_builder: BE,
    },
    Fallback {
        stream: BE::Stream,
    },
    Repeat {
        stream: SR,
    },
}

impl<S, I, B, BE, SR> RepeatOrElseState<S, I, B, BE, SR>
where
    S: event::Stream,
    SR: event::Stream,
    I: Iterator,
//    B: builder::BuildMutMapped<MaybeElementTemplate<S>, I::Item>,
    BE: builder::BuildOnce<S>,
{
    fn step<F>(self, stepper: F) -> modifier::StateResult<RepeatOrElseState<S, I, B, BE, SR>>
    where
        F: FnOnce(S, iter::Peekable, B) -> SR,
    {
        match self {
            RepeatOrElseState::Start { stream, iter, builder, else_builder } => {
                let mut iter = iter.peekable();
                if iter.peek().is_some() {
                    Ok(Some((event::noop(), Some(RepeatOrElseState::Repeat {
                        stream: stepper(stream, iter, builder),
                    }))))
                } else {
                    Ok(Some((event::noop(), Some(RepeatOrElseState::Fallback {
                        stream: transform::build_once(stream, else_builder),
                    }))))
                }
            },
            RepeatOrElseState::Fallback { stream } =>
                modifier::passthrough(stream, |stream| RepeatOrElseState::Fallback { stream }),
            RepeatOrElseState::Repeat { stream } =>
                modifier::passthrough(stream, |stream| RepeatOrElseState::Repeat { stream }),
        }
    }
}

type PeekableRepeatState<S, I, B, BE> = RepeatOrElseState<
    S, I, B, BE,
    Repeat<S, iter::Peekable, B>,
>;

/// Repeat a stream for each item of an iterator or run a fallback transformation.
pub struct RepeatOrElse<S, I, B, BE>
where
    I: Iterator,
    B: builder::BuildMutMapped<MaybeElementTemplate<S>, I::Item>,
    BE: builder::BuildOnce<S>,
{
    state: modifier::State<PeekableRepeatState<S, I, B, BE>>,
}

impl<S, I, B, BE> RepeatOrElse<S, I, B, BE>
where
    I: Iterator,
    B: builder::BuildMutMapped<MaybeElementTemplate<S>, I::Item>,
    BE: builder::BuildOnce<S>,
{
    pub(crate) fn new(
        stream: S,
        iter: I,
        builder: B,
        else_builder: BE,
    ) -> RepeatOrElse<S, I, B, BE> {
        RepeatOrElse {
            state: modifier::State::new(
                RepeatOrElseState::Start { stream, iter, builder, else_builder },
            ),
        }
    }
}

impl<S, I, B, BE> event::Stream for RepeatOrElse<S, I, B, BE>
where
    S: event::Stream,
    I: Iterator,
    B: builder::BuildMutMapped<MaybeElementTemplate<S>, I::Item>,
    BE: builder::BuildOnce<S>,
{
    fn next_event(&mut self) -> event::StreamResult {
        self.state.step(|state| state.step(
            |stream, iter, builder| Repeat::new(stream, iter, builder),
        ))
    }
}

/// Repeat a stream for each item of an iterator.
pub struct Repeat<S, I, B>
where
    I: Iterator,
    B: builder::BuildMutMapped<MaybeElementTemplate<S>, I::Item>,
{
    state: modifier::State<State<S, I, B, MaybeElementTemplate<S>>>,
}

impl<S, I, B> Repeat<S, I, B>
where
    I: Iterator,
    B: builder::BuildMutMapped<MaybeElementTemplate<S>, I::Item>,
{
    pub(crate) fn new(stream: S, iter: I, builder: B) -> Repeat<S, I, B> {
        Repeat {
            state: modifier::State::new(State::Collect { stream, iter, builder }),
        }
    }
}

impl<S, I, B> event::Stream for Repeat<S, I, B>
where
    S: event::Stream,
    I: Iterator,
    B: builder::BuildMutMapped<MaybeElementTemplate<S>, I::Item>,
{
    fn next_event(&mut self) -> event::StreamResult {
        self.state.step(|state| state.step(modifier::Derived::new))
    }
}

enum State<S, I, B, SB>
where
    I: Iterator,
    B: builder::BuildMutMapped<SB, I::Item>,
{
    Collect {
        stream: S,
        builder: B,
        iter: I,
    },
    Next {
        template: template::Template,
        builder: B,
        iter: I,
    },
    Emit {
        template: template::Template,
        stream: B::Stream,
        builder: B,
        iter: I,
    },
}

impl<S, I, B, SB> State<S, I, B, SB>
where
    I: Iterator,
    B: builder::BuildMutMapped<SB, I::Item>,
    S: event::Stream,
    SB: event::Stream,
{
    fn step<F>(self, stepper: F) -> modifier::StateResult<State<S, I, B, SB>>
    where
        F: FnOnce(template::TemplateStream) -> SB,
    {
        use event::{ Stream };
        match self {
            State::Collect { stream, builder, iter } => {
                let template = template::Template::from_stream(stream)?;
                Ok(Some((event::noop(), Some(State::Next { template, builder, iter }))))
            },
            State::Next { template, mut builder, mut iter } => {
                let item = match iter.next() {
                    Some(value) => value,
                    None => return Ok(None),
                };
                let stream = stepper(template.to_stream());
                let stream = transform::build_mut_mapped(stream, &mut builder, item);
                Ok(Some((event::noop(), Some(State::Emit { template, stream, builder, iter }))))
            },
            State::Emit { template, builder, iter, mut stream } => match stream.next_event()? {
                Some(event) => Ok(Some((
                    event,
                    Some(State::Emit { template, builder, iter, stream }),
                ))),
                None => Ok(Some((
                    event::noop(),
                    Some(State::Next { template, builder, iter }),
                ))),
            },
        }
    }
}

struct RepeatContentStream<S, I, B>
where
    I: Iterator,
    B: builder::BuildMutMapped<template::TemplateStream, I::Item>,
{
    state: modifier::State<State<S, I, B, template::TemplateStream>>,
}

impl<S, I, B> event::Stream for RepeatContentStream<S, I, B>
where
    S: event::Stream,
    I: Iterator,
    B: builder::BuildMutMapped<template::TemplateStream, I::Item>,
{
    fn next_event(&mut self) -> event::StreamResult {
        self.state.step(|state| state.step(|stream| stream))
    }
}

struct Builder {
    iter: I,
    builder: B,
}

impl<S, I, B> builder::BuildOnce<modifier::select::CurrentContent<S>> for Builder
where
    S: event::ElementStream,
    I: Iterator,
    B: builder::BuildMutMapped<template::TemplateStream, I::Item>,
{
    type Stream = RepeatContentStream<modifier::select::CurrentContent<S>, I, B>;

    fn build_once(self, stream: transform::Api<modifier::select::CurrentContent<S>>)
    -> transform::Api<Self::Stream> {
        transform::Api::pack(RepeatContentStream {
            state: modifier::State::new(State::Collect {
                stream: stream.unpack(),
                iter: self.iter,
                builder: self.builder,
            }),
        })
    }
}

type PeekableRepeatContentState<S, I, B, BE> = RepeatOrElseState<
    S, I, B, BE,
    RepeatContent<S, iter::Peekable, B>,
>;

/// Repeat the contents of the current element for each item of an iterator or run a
/// fallback transform.
pub struct RepeatContentOrElse<S, I, B, BE>
where
    S: event::ElementStream,
    I: Iterator,
    B: builder::BuildMutMapped<template::TemplateStream, I::Item>,
    BE: builder::BuildOnce<S>,
{
    state: modifier::State<PeekableRepeatContentState<S, I, B, BE>>,
}

impl<S, I, B, BE> RepeatContentOrElse<S, I, B, BE>
where
    S: event::ElementStream,
    I: Iterator,
    B: builder::BuildMutMapped<template::TemplateStream, I::Item>,
    BE: builder::BuildOnce<S>,
{
    pub(crate) fn new(
        stream: S,
        iter: I,
        builder: B,
        else_builder: BE,
    ) -> RepeatContentOrElse<S, I, B, BE> {
        RepeatContentOrElse {
            state: modifier::State::new(
                RepeatOrElseState::Start { stream, iter, builder, else_builder },
            ),
        }
    }
}

impl<S, I, B, BE> event::Stream for RepeatContentOrElse<S, I, B, BE>
where
    S: event::ElementStream,
    I: Iterator,
    B: builder::BuildMutMapped<template::TemplateStream, I::Item>,
    BE: builder::BuildOnce<S>,
{
    fn next_event(&mut self) -> event::StreamResult {
        self.state.step(|state| state.step(
            |stream, iter, builder| RepeatContent::new(stream, iter, builder),
        ))
    }
}

/// Repeat the contents of the current element for each item of an iterator.
pub struct RepeatContent<S, I, B>
where
    S: event::ElementStream,
    I: Iterator,
    B: builder::BuildMutMapped<template::TemplateStream, I::Item>,
{
    stream: modifier::select::SelectContent<S, Builder>,
}

impl<S, I, B> RepeatContent<S, I, B>
where
    S: event::ElementStream,
    I: Iterator,
    B: builder::BuildMutMapped<template::TemplateStream, I::Item>,
{
    pub(crate) fn new(stream: S, iter: I, builder: B) -> RepeatContent<S, I, B> {
        RepeatContent {
            stream: modifier::select::SelectContent::new(stream, Builder { iter, builder }),
        }
    }
}

impl<S, I, B> event::Stream for RepeatContent<S, I, B>
where
    S: event::ElementStream,
    I: Iterator,
    B: builder::BuildMutMapped<template::TemplateStream, I::Item>,
{
    fn next_event(&mut self) -> event::StreamResult {
        self.stream.next_event()
    }
}

impl<S, I, B> event::ElementStream for RepeatContent<S, I, B>
where
    S: event::ElementStream,
    I: Iterator,
    B: builder::BuildMutMapped<template::TemplateStream, I::Item>,
{}

#[cfg(test)]
mod tests {

    test_group!(repeat_contents:
        "some integers" => transform_test!(
            "23<c></c>45",
            "23<c>3</c>4523<c>4</c>45",
            |html| html.select("b", |html| html.repeat_contents(3..5, |html, n| html
                .select("c", move |html| html.replace_contents(n))
            )),
        ),
        "empty iterator" => transform_test!(
            "23<c></c>45",
            "",
            |html| html.select("b", |html| html.repeat_contents(0..0, |html, n| html
                .select("c", move |html| html.replace_contents(n))
            )),
        ),
        "ensure element stream" => transform_test!(
            "<link>",
            "<link>",
            |html| html.select("b", |html| html
                .repeat_contents(0..0, |html, _n| html
                    .select("c", move |html| html)
                )
                .into_boxed_element()
            ),
        ),
    );

    test_group!(repeat:
        "some integers" => transform_test!(
            "23<c></c>45",
            "23<c>3</c>4523<c>4</c>45",
            |html| html.select("b", |html| html.repeat(3..5, |html, n| html
                .select("c", move |html| html.replace_contents(n))
            )),
        ),
        "empty iterator" => transform_test!(
            "23<c></c>45",
            "",
            |html| html.select("b", |html| html.repeat(0..0, |html, n| html
                .select("c", move |html| html.replace_contents(n))
            )),
        ),
        "ensure element stream" => transform_test!(
            "<link>",
            "<link>",
            |html| html.select("b", |html| html.repeat(0..0, |html, _n| html
                .into_boxed_element()
            )),
        ),
    );
}
<commit_msg>removed redundant closures<commit_after>
//! Repeat a stream multiple times.

use std::iter;

use event;
use modifier;
use transform;
use template;
use builder;

/// A stored stream representing an element if the parent stream does.
pub type MaybeElementTemplate<D> = modifier::Derived<template::TemplateStream, D>;

enum RepeatOrElseState<S, I, B, BE, SR>
where
    I: Iterator,
//    B: builder::BuildMutMapped<MaybeElementTemplate<S>, I::Item>,
    BE: builder::BuildOnce<S>,
{
    Start {
        stream: S,
        iter: I,
        builder: B,
        else_builder: BE,
    },
    Fallback {
        stream: BE::Stream,
    },
    Repeat {
        stream: SR,
    },
}

impl<S, I, B, BE, SR> RepeatOrElseState<S, I, B, BE, SR>
where
    S: event::Stream,
    SR: event::Stream,
    I: Iterator,
//    B: builder::BuildMutMapped<MaybeElementTemplate<S>, I::Item>,
    BE: builder::BuildOnce<S>,
{
    fn step<F>(self, stepper: F) -> modifier::StateResult<RepeatOrElseState<S, I, B, BE, SR>>
    where
        F: FnOnce(S, iter::Peekable, B) -> SR,
    {
        match self {
            RepeatOrElseState::Start { stream, iter, builder, else_builder } => {
                let mut iter = iter.peekable();
                if iter.peek().is_some() {
                    Ok(Some((event::noop(), Some(RepeatOrElseState::Repeat {
                        stream: stepper(stream, iter, builder),
                    }))))
                } else {
                    Ok(Some((event::noop(), Some(RepeatOrElseState::Fallback {
                        stream: transform::build_once(stream, else_builder),
                    }))))
                }
            },
            RepeatOrElseState::Fallback { stream } =>
                modifier::passthrough(stream, |stream| RepeatOrElseState::Fallback { stream }),
            RepeatOrElseState::Repeat { stream } =>
                modifier::passthrough(stream, |stream| RepeatOrElseState::Repeat { stream }),
        }
    }
}

type PeekableRepeatState<S, I, B, BE> = RepeatOrElseState<
    S, I, B, BE,
    Repeat<S, iter::Peekable, B>,
>;

/// Repeat a stream for each item of an iterator or run a fallback transformation.
pub struct RepeatOrElse<S, I, B, BE>
where
    I: Iterator,
    B: builder::BuildMutMapped<MaybeElementTemplate<S>, I::Item>,
    BE: builder::BuildOnce<S>,
{
    state: modifier::State<PeekableRepeatState<S, I, B, BE>>,
}

impl<S, I, B, BE> RepeatOrElse<S, I, B, BE>
where
    I: Iterator,
    B: builder::BuildMutMapped<MaybeElementTemplate<S>, I::Item>,
    BE: builder::BuildOnce<S>,
{
    pub(crate) fn new(
        stream: S,
        iter: I,
        builder: B,
        else_builder: BE,
    ) -> RepeatOrElse<S, I, B, BE> {
        RepeatOrElse {
            state: modifier::State::new(
                RepeatOrElseState::Start { stream, iter, builder, else_builder },
            ),
        }
    }
}

impl<S, I, B, BE> event::Stream for RepeatOrElse<S, I, B, BE>
where
    S: event::Stream,
    I: Iterator,
    B: builder::BuildMutMapped<MaybeElementTemplate<S>, I::Item>,
    BE: builder::BuildOnce<S>,
{
    fn next_event(&mut self) -> event::StreamResult {
        self.state.step(|state| state.step(Repeat::new))
    }
}

/// Repeat a stream for each item of an iterator.
pub struct Repeat<S, I, B>
where
    I: Iterator,
    B: builder::BuildMutMapped<MaybeElementTemplate<S>, I::Item>,
{
    state: modifier::State<State<S, I, B, MaybeElementTemplate<S>>>,
}

impl<S, I, B> Repeat<S, I, B>
where
    I: Iterator,
    B: builder::BuildMutMapped<MaybeElementTemplate<S>, I::Item>,
{
    pub(crate) fn new(stream: S, iter: I, builder: B) -> Repeat<S, I, B> {
        Repeat {
            state: modifier::State::new(State::Collect { stream, iter, builder }),
        }
    }
}

impl<S, I, B> event::Stream for Repeat<S, I, B>
where
    S: event::Stream,
    I: Iterator,
    B: builder::BuildMutMapped<MaybeElementTemplate<S>, I::Item>,
{
    fn next_event(&mut self) -> event::StreamResult {
        self.state.step(|state| state.step(modifier::Derived::new))
    }
}

enum State<S, I, B, SB>
where
    I: Iterator,
    B: builder::BuildMutMapped<SB, I::Item>,
{
    Collect {
        stream: S,
        builder: B,
        iter: I,
    },
    Next {
        template: template::Template,
        builder: B,
        iter: I,
    },
    Emit {
        template: template::Template,
        stream: B::Stream,
        builder: B,
        iter: I,
    },
}

impl<S, I, B, SB> State<S, I, B, SB>
where
    I: Iterator,
    B: builder::BuildMutMapped<SB, I::Item>,
    S: event::Stream,
    SB: event::Stream,
{
    fn step<F>(self, stepper: F) -> modifier::StateResult<State<S, I, B, SB>>
    where
        F: FnOnce(template::TemplateStream) -> SB,
    {
        use event::{ Stream };
        match self {
            State::Collect { stream, builder, iter } => {
                let template = template::Template::from_stream(stream)?;
                Ok(Some((event::noop(), Some(State::Next { template, builder, iter }))))
            },
            State::Next { template, mut builder, mut iter } => {
                let item = match iter.next() {
                    Some(value) => value,
                    None => return Ok(None),
                };
                let stream = stepper(template.to_stream());
                let stream = transform::build_mut_mapped(stream, &mut builder, item);
                Ok(Some((event::noop(), Some(State::Emit { template, stream, builder, iter }))))
            },
            State::Emit { template, builder, iter, mut stream } => match stream.next_event()? {
                Some(event) => Ok(Some((
                    event,
                    Some(State::Emit { template, builder, iter, stream }),
                ))),
                None => Ok(Some((
                    event::noop(),
                    Some(State::Next { template, builder, iter }),
                ))),
            },
        }
    }
}

struct RepeatContentStream<S, I, B>
where
    I: Iterator,
    B: builder::BuildMutMapped<template::TemplateStream, I::Item>,
{
    state: modifier::State<State<S, I, B, template::TemplateStream>>,
}

impl<S, I, B> event::Stream for RepeatContentStream<S, I, B>
where
    S: event::Stream,
    I: Iterator,
    B: builder::BuildMutMapped<template::TemplateStream, I::Item>,
{
    fn next_event(&mut self) -> event::StreamResult {
        self.state.step(|state| state.step(|stream| stream))
    }
}

struct Builder {
    iter: I,
    builder: B,
}

impl<S, I, B> builder::BuildOnce<modifier::select::CurrentContent<S>> for Builder
where
    S: event::ElementStream,
    I: Iterator,
    B: builder::BuildMutMapped<template::TemplateStream, I::Item>,
{
    type Stream = RepeatContentStream<modifier::select::CurrentContent<S>, I, B>;

    fn build_once(self, stream: transform::Api<modifier::select::CurrentContent<S>>)
    -> transform::Api<Self::Stream> {
        transform::Api::pack(RepeatContentStream {
            state: modifier::State::new(State::Collect {
                stream: stream.unpack(),
                iter: self.iter,
                builder: self.builder,
            }),
        })
    }
}

type PeekableRepeatContentState<S, I, B, BE> = RepeatOrElseState<
    S, I, B, BE,
    RepeatContent<S, iter::Peekable, B>,
>;

/// Repeat the contents of the current element for each item of an iterator or run a
/// fallback transform.
pub struct RepeatContentOrElse<S, I, B, BE>
where
    S: event::ElementStream,
    I: Iterator,
    B: builder::BuildMutMapped<template::TemplateStream, I::Item>,
    BE: builder::BuildOnce<S>,
{
    state: modifier::State<PeekableRepeatContentState<S, I, B, BE>>,
}

impl<S, I, B, BE> RepeatContentOrElse<S, I, B, BE>
where
    S: event::ElementStream,
    I: Iterator,
    B: builder::BuildMutMapped<template::TemplateStream, I::Item>,
    BE: builder::BuildOnce<S>,
{
    pub(crate) fn new(
        stream: S,
        iter: I,
        builder: B,
        else_builder: BE,
    ) -> RepeatContentOrElse<S, I, B, BE> {
        RepeatContentOrElse {
            state: modifier::State::new(
                RepeatOrElseState::Start { stream, iter, builder, else_builder },
            ),
        }
    }
}

impl<S, I, B, BE> event::Stream for RepeatContentOrElse<S, I, B, BE>
where
    S: event::ElementStream,
    I: Iterator,
    B: builder::BuildMutMapped<template::TemplateStream, I::Item>,
    BE: builder::BuildOnce<S>,
{
    fn next_event(&mut self) -> event::StreamResult {
        self.state.step(|state| state.step(RepeatContent::new))
    }
}

/// Repeat the contents of the current element for each item of an iterator.
pub struct RepeatContent<S, I, B>
where
    S: event::ElementStream,
    I: Iterator,
    B: builder::BuildMutMapped<template::TemplateStream, I::Item>,
{
    stream: modifier::select::SelectContent<S, Builder>,
}

impl<S, I, B> RepeatContent<S, I, B>
where
    S: event::ElementStream,
    I: Iterator,
    B: builder::BuildMutMapped<template::TemplateStream, I::Item>,
{
    pub(crate) fn new(stream: S, iter: I, builder: B) -> RepeatContent<S, I, B> {
        RepeatContent {
            stream: modifier::select::SelectContent::new(stream, Builder { iter, builder }),
        }
    }
}

impl<S, I, B> event::Stream for RepeatContent<S, I, B>
where
    S: event::ElementStream,
    I: Iterator,
    B: builder::BuildMutMapped<template::TemplateStream, I::Item>,
{
    fn next_event(&mut self) -> event::StreamResult {
        self.stream.next_event()
    }
}

impl<S, I, B> event::ElementStream for RepeatContent<S, I, B>
where
    S: event::ElementStream,
    I: Iterator,
    B: builder::BuildMutMapped<template::TemplateStream, I::Item>,
{}

#[cfg(test)]
mod tests {

    test_group!(repeat_contents:
        "some integers" => transform_test!(
            "23<c></c>45",
            "23<c>3</c>4523<c>4</c>45",
            |html| html.select("b", |html| html.repeat_contents(3..5, |html, n| html
                .select("c", move |html| html.replace_contents(n))
            )),
        ),
        "empty iterator" => transform_test!(
            "23<c></c>45",
            "",
            |html| html.select("b", |html| html.repeat_contents(0..0, |html, n| html
                .select("c", move |html| html.replace_contents(n))
            )),
        ),
        "ensure element stream" => transform_test!(
            "<link>",
            "<link>",
            |html| html.select("b", |html| html
                .repeat_contents(0..0, |html, _n| html
                    .select("c", move |html| html)
                )
                .into_boxed_element()
            ),
        ),
    );

    test_group!(repeat:
        "some integers" => transform_test!(
            "23<c></c>45",
            "23<c>3</c>4523<c>4</c>45",
            |html| html.select("b", |html| html.repeat(3..5, |html, n| html
                .select("c", move |html| html.replace_contents(n))
            )),
        ),
        "empty iterator" => transform_test!(
            "23<c></c>45",
            "",
            |html| html.select("b", |html| html.repeat(0..0, |html, n| html
                .select("c", move |html| html.replace_contents(n))
            )),
        ),
        "ensure element stream" => transform_test!(
            "<link>",
            "<link>",
            |html| html.select("b", |html| html.repeat(0..0, |html, _n| html
                .into_boxed_element()
            )),
        ),
    );
}
<|endoftext|>


<commit_before><commit_msg>allow unused macro import<commit_after><|endoftext|>