<commit_before>// Copyright © 2016, Canal TP and/or its affiliates. All rights reserved.
//
// This file is part of Navitia,
//     the software to build cool stuff with public transport.
//
// Hope you'll enjoy and contribute to this project,
//     powered by Canal TP (www.canaltp.fr).
// Help us simplify mobility and open public transport:
//     a non ending quest to the responsive locomotion way of traveling!
//
// LICENCE: This program is free software; you can redistribute it
// and/or modify it under the terms of the GNU Affero General Public
// License as published by the Free Software Foundation, either
// version 3 of the License, or (at your option) any later version.
//
// This program is distributed in the hope that it will be useful, but
// WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
// Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public
// License along with this program. If not, see
// <http://www.gnu.org/licenses/>.
//
// Stay tuned using
// twitter @navitia
// IRC #navitia on freenode
// https://groups.google.com/d/forum/navitia
// www.navitia.io
use super::{Args, model};
use regex;
use rs_es;
use rs_es::query::Query as rs_q;
use rs_es::operations::search::SearchResult;
use mimir;

fn build_rs_client(args: &Args) -> rs_es::Client {
    let re = regex::Regex::new(r"(?:https?://)?(?P<host>.+?):(?P<port>\d+)/(?P<index>\w+)")
                 .unwrap();
    let cap = re.captures(&args.flag_connection_string).unwrap();
    let host = cap.name("host").unwrap();
    let port = cap.name("port").unwrap().parse::<u32>().unwrap();

    rs_es::Client::new(&host, port)
}

fn query(q: &String, args: &Args) -> Result<Vec<mimir::Place>, rs_es::error::EsError> {
    let sub_query = rs_q::build_bool()
                   .with_should(vec![
                       rs_q::build_term("_type","addr").with_boost(1000).build(),
                       rs_q::build_match("name.prefix", q.to_string())
                              .with_boost(100)
                              .build(),
                       rs_q::build_function_score()
                              .with_boost_mode(rs_es::query::compound::BoostMode::Multiply)
                              .with_boost(30)
                              .with_query(rs_q::build_match_all().build())
			                  .with_function(
                          rs_es::query::functions::Function::build_field_value_factor("weight")
			                                  .with_factor(1)
                                      .with_modifier(rs_es::query::functions::Modifier::Log1p)
			                                                          .build())
                              .build()])
                       .build();
    let filter = rs_q::build_bool()
                     .with_should(vec![rs_q::build_bool()
                                           .with_must_not(rs_q::build_exists("house_number")
                                                              .build())
                                           .build(),
                                       rs_q::build_match("house_number", q.to_string()).build()])
                     .with_must(vec![rs_q::build_match("name.prefix", q.to_string())
             .with_minimum_should_match(rs_es::query::MinimumShouldMatch::from(100f64)).build()])
                     .build();

    let final_query = rs_q::build_bool()
                          .with_must(vec![sub_query])
                          .with_filter(filter)
                          .build();

    let mut client = build_rs_client(args);

    let result: SearchResult<mimir::Addr> = try!(client.search_query()
                                                   .with_indexes(&["munin"])
                                                   .with_query(&final_query)
                                                   .send());

    debug!("{} documents found", result.hits.total);

    // for the moment we can only get Addr, so they are transformed into Places
    // TODO: reads Place, not Addr
    Ok(result.hits.hits.into_iter()
    .map(|hit| mimir::Place::Addr(*hit.source.unwrap())).collect())
}

fn query_location(_q: &String, _coord: &model::Coord) -> Result<Vec<mimir::Place>, rs_es::error::EsError> {
    panic!("todo!");
    // use rustc_serialize::json::Json::String;
    // let query = format!(include_str!("../../../json/query_exact_location.json"),
    // query=String(q.to_string()),
    // lon=coord.lon,
    // lat=coord.lat);
    // let resp = try!(curl::http::handle()
    // .post("http://localhost:9200/munin/_search?pretty", &query)
    // .exec());
    // let body = Json::from_str(str::from_utf8(resp.get_body()).unwrap()).unwrap();
    // if body["hits"]["total"].as_u64().unwrap() > 0 { return Ok(resp); }
    // let query = format!(include_str!("../../../json/query_location.json"),
    // query=String(q.to_string()),
    // lon=coord.lon,
    // lat=coord.lat);
    // let resp = curl::http::handle()
    // .post("http://localhost:9200/munin/_search?pretty", &query)
    // .exec();
    // resp
}

pub fn autocomplete(q: String, coord: Option<model::Coord>) -> Result<Vec<mimir::Place>, rs_es::error::EsError> {
    if let Some(ref coord) = coord {
         query_location(&q, coord)
    } else {
        let args = Args {

    flag_bind: "".to_string(),
    flag_connection_string: "".to_string(),
};
         query(&q, &args)
     }
}
<commit_msg>cleanup<commit_after>// Copyright © 2016, Canal TP and/or its affiliates. All rights reserved.
//
// This file is part of Navitia,
//     the software to build cool stuff with public transport.
//
// Hope you'll enjoy and contribute to this project,
//     powered by Canal TP (www.canaltp.fr).
// Help us simplify mobility and open public transport:
//     a non ending quest to the responsive locomotion way of traveling!
//
// LICENCE: This program is free software; you can redistribute it
// and/or modify it under the terms of the GNU Affero General Public
// License as published by the Free Software Foundation, either
// version 3 of the License, or (at your option) any later version.
//
// This program is distributed in the hope that it will be useful, but
// WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
// Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public
// License along with this program. If not, see
// <http://www.gnu.org/licenses/>.
//
// Stay tuned using
// twitter @navitia
// IRC #navitia on freenode
// https://groups.google.com/d/forum/navitia
// www.navitia.io
use super::{Args, model};
use regex;
use rs_es;
use rs_es::query::Query as rs_q;
use rs_es::operations::search::SearchResult;
use mimir;

fn build_rs_client(args: &Args) -> rs_es::Client {
    let re = regex::Regex::new(r"(?:https?://)?(?P<host>.+?):(?P<port>\d+)/(?P<index>\w+)")
                 .unwrap();
    let cap = re.captures(&args.flag_connection_string).unwrap();
    let host = cap.name("host").unwrap();
    let port = cap.name("port").unwrap().parse::<u32>().unwrap();

    rs_es::Client::new(&host, port)
}

fn query(q: &String, args: &Args) -> Result<Vec<mimir::Place>, rs_es::error::EsError> {
    let sub_query = rs_q::build_bool()
                   .with_should(vec![
                       rs_q::build_term("_type","addr").with_boost(1000).build(),
                       rs_q::build_match("name.prefix", q.to_string())
                              .with_boost(100)
                              .build(),
                       rs_q::build_function_score()
                              .with_boost_mode(rs_es::query::compound::BoostMode::Multiply)
                              .with_boost(30)
                              .with_query(rs_q::build_match_all().build())
			                  .with_function(
                          rs_es::query::functions::Function::build_field_value_factor("weight")
			                                  .with_factor(1)
                                      .with_modifier(rs_es::query::functions::Modifier::Log1p)
			                                                          .build())
                              .build()])
                       .build();
    let filter = rs_q::build_bool()
                     .with_should(vec![rs_q::build_bool()
                                           .with_must_not(rs_q::build_exists("house_number")
                                                              .build())
                                           .build(),
                                       rs_q::build_match("house_number", q.to_string()).build()])
                     .with_must(vec![rs_q::build_match("name.prefix", q.to_string())
             .with_minimum_should_match(rs_es::query::MinimumShouldMatch::from(100f64)).build()])
                     .build();

    let final_query = rs_q::build_bool()
                          .with_must(vec![sub_query])
                          .with_filter(filter)
                          .build();

    let mut client = build_rs_client(args);

    let result: SearchResult<mimir::Addr> = try!(client.search_query()
                                                   .with_indexes(&["munin"])
                                                   .with_query(&final_query)
                                                   .send());

    debug!("{} documents found", result.hits.total);

    // for the moment we can only get Addr, so they are transformed into Places
    // TODO: reads Place, not Addr
    Ok(result.hits.hits.into_iter()
    .map(|hit| mimir::Place::Addr(*hit.source.unwrap())).collect())
}

fn query_location(_q: &String, _coord: &model::Coord) -> Result<Vec<mimir::Place>, rs_es::error::EsError> {
    panic!("todo!");
}

pub fn autocomplete(q: String, coord: Option<model::Coord>) -> Result<Vec<mimir::Place>, rs_es::error::EsError> {
    if let Some(ref coord) = coord {
         query_location(&q, coord)
    } else {
        let args = Args {

    flag_bind: "".to_string(),
    flag_connection_string: "http://localhost:9200/munin".to_string(),
};
         query(&q, &args)
     }
}
<|endoftext|>


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

use document_loader::DocumentLoader;
use dom::bindings::codegen::Bindings::DocumentBinding::DocumentMethods;
use dom::bindings::codegen::Bindings::WindowBinding::WindowMethods;
use dom::bindings::codegen::Bindings::XMLDocumentBinding::{self, XMLDocumentMethods};
use dom::bindings::global::GlobalRef;
use dom::bindings::inheritance::Castable;
use dom::bindings::js::{Root, RootedReference};
use dom::bindings::reflector::{Reflectable, reflect_dom_object};
use dom::browsingcontext::BrowsingContext;
use dom::document::{Document, DocumentSource, IsHTMLDocument};
use dom::location::Location;
use dom::node::Node;
use dom::window::Window;
use js::jsapi::{JSContext, JSObject};
use url::Url;
use util::str::DOMString;

// https://dom.spec.whatwg.org/#xmldocument
#[dom_struct]
pub struct XMLDocument {
    document: Document,
}

impl XMLDocument {
    fn new_inherited(window: &Window,
                     browsing_context: Option<&BrowsingContext>,
                     url: Option<Url>,
                     is_html_document: IsHTMLDocument,
                     content_type: Option<DOMString>,
                     last_modified: Option<String>,
                     source: DocumentSource,
                     doc_loader: DocumentLoader) -> XMLDocument {
        XMLDocument {
            document: Document::new_inherited(window,
                                              browsing_context,
                                              url,
                                              is_html_document,
                                              content_type,
                                              last_modified,
                                              source,
                                              doc_loader),
        }
    }

    pub fn new(window: &Window,
               browsing_context: Option<&BrowsingContext>,
               url: Option<Url>,
               doctype: IsHTMLDocument,
               content_type: Option<DOMString>,
               last_modified: Option<String>,
               source: DocumentSource,
               doc_loader: DocumentLoader)
               -> Root<XMLDocument> {
        let doc = reflect_dom_object(
            box XMLDocument::new_inherited(window,
                                           browsing_context,
                                           url,
                                           doctype,
                                           content_type,
                                           last_modified,
                                           source,
                                           doc_loader),
            GlobalRef::Window(window),
            XMLDocumentBinding::Wrap);
        {
            let node = doc.upcast::<Node>();
            node.set_owner_doc(&doc.r().document);
        }
        doc
    }
}

impl XMLDocumentMethods for XMLDocument {
    // https://html.spec.whatwg.org/multipage/#dom-document-location
    fn GetLocation(&self) -> Option<Root<Location>> {
        self.document.GetLocation()
    }

    // https://html.spec.whatwg.org/multipage/#dom-tree-accessors:supported-property-names
    fn SupportedPropertyNames(&self) -> Vec<DOMString> {
        self.document.SupportedPropertyNames()
    }

    // https://html.spec.whatwg.org/multipage/#dom-tree-accessors:dom-document-nameditem-filter
    fn NamedGetter(&self, _cx: *mut JSContext, name: DOMString, found: &mut bool) -> *mut JSObject {
        self.document.NamedGetter(_cx, name, found)
    }
}
<commit_msg>Remove unused import from xmldocument.<commit_after>/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

use document_loader::DocumentLoader;
use dom::bindings::codegen::Bindings::DocumentBinding::DocumentMethods;
use dom::bindings::codegen::Bindings::XMLDocumentBinding::{self, XMLDocumentMethods};
use dom::bindings::global::GlobalRef;
use dom::bindings::inheritance::Castable;
use dom::bindings::js::{Root, RootedReference};
use dom::bindings::reflector::{Reflectable, reflect_dom_object};
use dom::browsingcontext::BrowsingContext;
use dom::document::{Document, DocumentSource, IsHTMLDocument};
use dom::location::Location;
use dom::node::Node;
use dom::window::Window;
use js::jsapi::{JSContext, JSObject};
use url::Url;
use util::str::DOMString;

// https://dom.spec.whatwg.org/#xmldocument
#[dom_struct]
pub struct XMLDocument {
    document: Document,
}

impl XMLDocument {
    fn new_inherited(window: &Window,
                     browsing_context: Option<&BrowsingContext>,
                     url: Option<Url>,
                     is_html_document: IsHTMLDocument,
                     content_type: Option<DOMString>,
                     last_modified: Option<String>,
                     source: DocumentSource,
                     doc_loader: DocumentLoader) -> XMLDocument {
        XMLDocument {
            document: Document::new_inherited(window,
                                              browsing_context,
                                              url,
                                              is_html_document,
                                              content_type,
                                              last_modified,
                                              source,
                                              doc_loader),
        }
    }

    pub fn new(window: &Window,
               browsing_context: Option<&BrowsingContext>,
               url: Option<Url>,
               doctype: IsHTMLDocument,
               content_type: Option<DOMString>,
               last_modified: Option<String>,
               source: DocumentSource,
               doc_loader: DocumentLoader)
               -> Root<XMLDocument> {
        let doc = reflect_dom_object(
            box XMLDocument::new_inherited(window,
                                           browsing_context,
                                           url,
                                           doctype,
                                           content_type,
                                           last_modified,
                                           source,
                                           doc_loader),
            GlobalRef::Window(window),
            XMLDocumentBinding::Wrap);
        {
            let node = doc.upcast::<Node>();
            node.set_owner_doc(&doc.r().document);
        }
        doc
    }
}

impl XMLDocumentMethods for XMLDocument {
    // https://html.spec.whatwg.org/multipage/#dom-document-location
    fn GetLocation(&self) -> Option<Root<Location>> {
        self.document.GetLocation()
    }

    // https://html.spec.whatwg.org/multipage/#dom-tree-accessors:supported-property-names
    fn SupportedPropertyNames(&self) -> Vec<DOMString> {
        self.document.SupportedPropertyNames()
    }

    // https://html.spec.whatwg.org/multipage/#dom-tree-accessors:dom-document-nameditem-filter
    fn NamedGetter(&self, _cx: *mut JSContext, name: DOMString, found: &mut bool) -> *mut JSObject {
        self.document.NamedGetter(_cx, name, found)
    }
}
<|endoftext|>


<commit_before>/* Multi-producer/multi-consumer bounded queue
 * Copyright (c) 2010-2011 Dmitry Vyukov. All rights reserved.
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *
 *    1. Redistributions of source code must retain the above copyright notice,
 *       this list of conditions and the following disclaimer.
 *
 *    2. Redistributions in binary form must reproduce the above copyright
 *       notice, this list of conditions and the following disclaimer in the
 *       documentation and/or other materials provided with the distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY DMITRY VYUKOV "AS IS" AND ANY EXPRESS OR IMPLIED
 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
 * SHALL DMITRY VYUKOV OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
 * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 *
 * The views and conclusions contained in the software and documentation are
 * those of the authors and should not be interpreted as representing official
 * policies, either expressed or implied, of Dmitry Vyukov.
 */

use unstable::sync::UnsafeArc;
use unstable::atomics::{AtomicUint,Relaxed,Release,Acquire};
use option::*;
use vec;
use clone::Clone;
use kinds::Send;
use num::{Exponential,Algebraic,Round};

struct Node<T> {
    sequence: AtomicUint,
    value: Option<T>,
}

struct State<T> {
    pad0: [u8, ..64],
    buffer: ~[Node<T>],
    mask: uint,
    pad1: [u8, ..64],
    enqueue_pos: AtomicUint,
    pad2: [u8, ..64],
    dequeue_pos: AtomicUint,
    pad3: [u8, ..64],
}

struct Queue<T> {
    priv state: UnsafeArc<State<T>>,
}

impl<T: Send> State<T> {
    fn with_capacity(capacity: uint) -> State<T> {
        let capacity = if capacity < 2 || (capacity & (capacity - 1)) != 0 {
            // use next power of 2 as capacity
            2f64.pow(&((capacity as f64).log2().floor()+1f64)) as uint
        } else {
            capacity
        };
        let buffer = do vec::from_fn(capacity) |i:uint| {
            Node{sequence:AtomicUint::new(i),value:None}
        };
        State{
            pad0: [0, ..64],
            buffer: buffer,
            mask: capacity-1,
            pad1: [0, ..64],
            enqueue_pos: AtomicUint::new(0),
            pad2: [0, ..64],
            dequeue_pos: AtomicUint::new(0),
            pad3: [0, ..64],
        }
    }

    fn push(&mut self, value: T) -> bool {
        let mask = self.mask;
        let mut pos = self.enqueue_pos.load(Relaxed);
        loop {
            let node = &mut self.buffer[pos & mask];
            let seq = node.sequence.load(Acquire);
            let diff: int = seq as int - pos as int;

            if diff == 0 {
                let enqueue_pos = self.enqueue_pos.compare_and_swap(pos, pos+1, Relaxed);
                if enqueue_pos == pos {
                    node.value = Some(value);
                    node.sequence.store(pos+1, Release);
                    break
                } else {
                    pos = enqueue_pos;
                }
            } else if (diff < 0) {
                return false
            } else {
                pos = self.enqueue_pos.load(Relaxed);
            }
        }
        true
    }

    fn pop(&mut self) -> Option<T> {
        let mask = self.mask;
        let mut pos = self.dequeue_pos.load(Relaxed);
        loop {
            let node = &mut self.buffer[pos & mask];
            let seq = node.sequence.load(Acquire);
            let diff: int = seq as int - (pos + 1) as int;
            if diff == 0 {
                let dequeue_pos = self.dequeue_pos.compare_and_swap(pos, pos+1, Relaxed);
                if dequeue_pos == pos {
                    let value = node.value.take();
                    node.sequence.store(pos + mask + 1, Release);
                    return value
                } else {
                    pos = dequeue_pos;
                }
            } else if diff < 0 {
                return None
            } else {
                pos = self.dequeue_pos.load(Relaxed);
            }
        }
    }
}

impl<T: Send> Queue<T> {
    pub fn with_capacity(capacity: uint) -> Queue<T> {
        Queue{
            state: UnsafeArc::new(State::with_capacity(capacity))
        }
    }

    pub fn push(&mut self, value: T) -> bool {
        unsafe { (*self.state.get()).push(value) }
    }

    pub fn pop(&mut self) -> Option<T> {
        unsafe { (*self.state.get()).pop() }
    }
}

impl<T: Send> Clone for Queue<T> {
    fn clone(&self) -> Queue<T> {
        Queue {
            state: self.state.clone()
        }
    }
}

#[cfg(test)]
mod tests {
    use prelude::*;
    use option::*;
    use task;
    use comm;
    use super::Queue;

    #[test]
    fn test() {
        let nthreads = 8u;
        let nmsgs = 1000u;
        let mut q = Queue::with_capacity(nthreads*nmsgs);
        assert_eq!(None, q.pop());

        for _ in range(0, nthreads) {
            let (port, chan)  = comm::stream();
            chan.send(q.clone());
            do task::spawn_sched(task::SingleThreaded) {
                let mut q = port.recv();
                for i in range(0, nmsgs) {
                    assert!(q.push(i));
                }
            }
        }

        let mut completion_ports = ~[];
        for _ in range(0, nthreads) {
            let (completion_port, completion_chan) = comm::stream();
            completion_ports.push(completion_port);
            let (port, chan)  = comm::stream();
            chan.send(q.clone());
            do task::spawn_sched(task::SingleThreaded) {
                let mut q = port.recv();
                let mut i = 0u;
                loop {
                    match q.pop() {
                        None => {},
                        Some(_) => {
                            i += 1;
                            if i == nmsgs { break }
                        }
                    }
                }
                completion_chan.send(i);
            }
        }

        for completion_port in completion_ports.iter() {
            assert_eq!(nmsgs, completion_port.recv());
        }
    }
}
<commit_msg>minor<commit_after>/* Multi-producer/multi-consumer bounded queue
 * Copyright (c) 2010-2011 Dmitry Vyukov. All rights reserved.
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *
 *    1. Redistributions of source code must retain the above copyright notice,
 *       this list of conditions and the following disclaimer.
 *
 *    2. Redistributions in binary form must reproduce the above copyright
 *       notice, this list of conditions and the following disclaimer in the
 *       documentation and/or other materials provided with the distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY DMITRY VYUKOV "AS IS" AND ANY EXPRESS OR IMPLIED
 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
 * SHALL DMITRY VYUKOV OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
 * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 *
 * The views and conclusions contained in the software and documentation are
 * those of the authors and should not be interpreted as representing official
 * policies, either expressed or implied, of Dmitry Vyukov.
 */

use unstable::sync::UnsafeArc;
use unstable::atomics::{AtomicUint,Relaxed,Release,Acquire};
use option::*;
use vec;
use clone::Clone;
use kinds::Send;
use num::{Exponential,Algebraic,Round};

struct Node<T> {
    sequence: AtomicUint,
    value: Option<T>,
}

struct State<T> {
    pad0: [u8, ..64],
    buffer: ~[Node<T>],
    mask: uint,
    pad1: [u8, ..64],
    enqueue_pos: AtomicUint,
    pad2: [u8, ..64],
    dequeue_pos: AtomicUint,
    pad3: [u8, ..64],
}

struct Queue<T> {
    priv state: UnsafeArc<State<T>>,
}

impl<T: Send> State<T> {
    fn with_capacity(capacity: uint) -> State<T> {
        let capacity = if capacity < 2 || (capacity & (capacity - 1)) != 0 {
            if capacity < 2 {
                2u
            } else {
                // use next power of 2 as capacity
                2f64.pow(&((capacity as f64).log2().ceil())) as uint
            }
        } else {
            capacity
        };
        let buffer = do vec::from_fn(capacity) |i:uint| {
            Node{sequence:AtomicUint::new(i),value:None}
        };
        State{
            pad0: [0, ..64],
            buffer: buffer,
            mask: capacity-1,
            pad1: [0, ..64],
            enqueue_pos: AtomicUint::new(0),
            pad2: [0, ..64],
            dequeue_pos: AtomicUint::new(0),
            pad3: [0, ..64],
        }
    }

    fn push(&mut self, value: T) -> bool {
        let mask = self.mask;
        let mut pos = self.enqueue_pos.load(Relaxed);
        loop {
            let node = &mut self.buffer[pos & mask];
            let seq = node.sequence.load(Acquire);
            let diff: int = seq as int - pos as int;

            if diff == 0 {
                let enqueue_pos = self.enqueue_pos.compare_and_swap(pos, pos+1, Relaxed);
                if enqueue_pos == pos {
                    node.value = Some(value);
                    node.sequence.store(pos+1, Release);
                    break
                } else {
                    pos = enqueue_pos;
                }
            } else if (diff < 0) {
                return false
            } else {
                pos = self.enqueue_pos.load(Relaxed);
            }
        }
        true
    }

    fn pop(&mut self) -> Option<T> {
        let mask = self.mask;
        let mut pos = self.dequeue_pos.load(Relaxed);
        loop {
            let node = &mut self.buffer[pos & mask];
            let seq = node.sequence.load(Acquire);
            let diff: int = seq as int - (pos + 1) as int;
            if diff == 0 {
                let dequeue_pos = self.dequeue_pos.compare_and_swap(pos, pos+1, Relaxed);
                if dequeue_pos == pos {
                    let value = node.value.take();
                    node.sequence.store(pos + mask + 1, Release);
                    return value
                } else {
                    pos = dequeue_pos;
                }
            } else if diff < 0 {
                return None
            } else {
                pos = self.dequeue_pos.load(Relaxed);
            }
        }
    }
}

impl<T: Send> Queue<T> {
    pub fn with_capacity(capacity: uint) -> Queue<T> {
        Queue{
            state: UnsafeArc::new(State::with_capacity(capacity))
        }
    }

    pub fn push(&mut self, value: T) -> bool {
        unsafe { (*self.state.get()).push(value) }
    }

    pub fn pop(&mut self) -> Option<T> {
        unsafe { (*self.state.get()).pop() }
    }
}

impl<T: Send> Clone for Queue<T> {
    fn clone(&self) -> Queue<T> {
        Queue {
            state: self.state.clone()
        }
    }
}

#[cfg(test)]
mod tests {
    use prelude::*;
    use option::*;
    use task;
    use comm;
    use super::Queue;

    #[test]
    fn test() {
        let nthreads = 8u;
        let nmsgs = 1000u;
        let mut q = Queue::with_capacity(nthreads*nmsgs);
        assert_eq!(None, q.pop());

        for _ in range(0, nthreads) {
            let (port, chan)  = comm::stream();
            chan.send(q.clone());
            do task::spawn_sched(task::SingleThreaded) {
                let mut q = port.recv();
                for i in range(0, nmsgs) {
                    assert!(q.push(i));
                }
            }
        }

        let mut completion_ports = ~[];
        for _ in range(0, nthreads) {
            let (completion_port, completion_chan) = comm::stream();
            completion_ports.push(completion_port);
            let (port, chan)  = comm::stream();
            chan.send(q.clone());
            do task::spawn_sched(task::SingleThreaded) {
                let mut q = port.recv();
                let mut i = 0u;
                loop {
                    match q.pop() {
                        None => {},
                        Some(_) => {
                            i += 1;
                            if i == nmsgs { break }
                        }
                    }
                }
                completion_chan.send(i);
            }
        }

        for completion_port in completion_ports.iter() {
            assert_eq!(nmsgs, completion_port.recv());
        }
    }
}
<|endoftext|>


<commit_before>// Automatically generated rust module for 'test_root_pb.proto' file

#![allow(non_snake_case)]
#![allow(non_upper_case_globals)]
#![allow(non_camel_case_types)]
#![allow(unused_imports)]
#![allow(unknown_lints)]
#![allow(clippy)]
#![cfg_attr(rustfmt, rustfmt_skip)]

use std::io::Write;
use quick_protobuf::{MessageRead, MessageWrite, BytesReader, Writer, Result};
use quick_protobuf::sizeofs::*;
use super::*;

#[derive(Debug, Default, PartialEq, Clone)]
pub struct Root {
    pub nested: Vec<mod_Root::Nested>,
}

impl<'a> MessageRead<'a> for Root {
    fn from_reader(r: &mut BytesReader, bytes: &'a [u8]) -> Result<Self> {
        let mut msg = Self::default();
        while !r.is_eof() {
            match r.next_tag(bytes) {
                Ok(10) => msg.nested.push(r.read_message::<mod_Root::Nested>(bytes)?),
                Ok(t) => { r.read_unknown(bytes, t)?; }
                Err(e) => return Err(e),
            }
        }
        Ok(msg)
    }
}

impl MessageWrite for Root {
    fn get_size(&self) -> usize {
        0
        + self.nested.iter().map(|s| 1 + sizeof_len((s).get_size())).sum::<usize>()
    }

    fn write_message<W: Write>(&self, w: &mut Writer<W>) -> Result<()> {
        for s in &self.nested { w.write_with_tag(10, |w| w.write_message(s))?; }
        Ok(())
    }
}

pub mod mod_Root {

use super::*;

#[derive(Debug, Default, PartialEq, Clone)]
pub struct Nested { }

impl<'a> MessageRead<'a> for Nested {
    fn from_reader(r: &mut BytesReader, _: &[u8]) -> Result<Self> {
        r.read_to_end();
        Ok(Self::default())
    }
}

impl MessageWrite for Nested { }

}

<commit_msg>Delete test_root_pb.rs<commit_after><|endoftext|>


<commit_before>/*
 * Copyright (c) Facebook, Inc. and its affiliates.
 *
 * This source code is licensed under the MIT license found in the
 * LICENSE file in the root directory of this source tree.
 */

use crate::{
    lsp_runtime_error::{LSPRuntimeError, LSPRuntimeResult},
    server::LSPState,
};
use common::PerfLogger;
use lsp_types::{
    request::Request, Position, TextDocumentIdentifier, TextDocumentPositionParams, Url,
};
use schema::Schema;
use schema_documentation::SchemaDocumentation;
use serde::{Deserialize, Serialize};

pub(crate) enum ResolvedTypesAtLocation {}

#[derive(Deserialize, Serialize)]
pub(crate) struct ResolvedTypesAtLocationParams {
    file_name: String,
    line: u32,
    character: u32,
}

impl ResolvedTypesAtLocationParams {
    fn to_text_document_position_params(&self) -> LSPRuntimeResult<TextDocumentPositionParams> {
        Ok(TextDocumentPositionParams {
            text_document: TextDocumentIdentifier {
                uri: Url::parse(&self.file_name).map_err(|_| LSPRuntimeError::ExpectedError)?,
            },
            position: Position {
                character: self.character,
                line: self.line,
            },
        })
    }
}

#[derive(Deserialize, Serialize)]
pub(crate) struct ResolvedTypesAtLocationResponse {
    pub path_and_schema_name: Option<PathAndSchemaName>,
}

#[derive(Deserialize, Serialize)]
pub(crate) struct PathAndSchemaName {
    pub path: Vec<String>,
    pub schema_name: String,
}

impl Request for ResolvedTypesAtLocation {
    type Params = ResolvedTypesAtLocationParams;
    type Result = ResolvedTypesAtLocationResponse;
    const METHOD: &'static str = "relay/getResolvedTypesAtLocation";
}

pub(crate) fn on_get_resolved_types_at_location<
    TPerfLogger: PerfLogger + 'static,
    TSchemaDocumentation: SchemaDocumentation,
>(
    state: &mut LSPState<TPerfLogger, TSchemaDocumentation>,
    params: <ResolvedTypesAtLocation as Request>::Params,
) -> LSPRuntimeResult<<ResolvedTypesAtLocation as Request>::Result> {
    if let Ok(node_resolution_info) =
        state.resolve_node(&params.to_text_document_position_params()?)
    {
        if let Some(schema) = state.get_schemas().get(&node_resolution_info.project_name) {
            // If type_path is empty, type_path.resolve_current_field() will panic.
            if !node_resolution_info.type_path.0.is_empty() {
                let type_and_field = node_resolution_info
                    .type_path
                    .resolve_current_field(&schema);
                if let Some((_parent_type, field)) = type_and_field {
                    let type_name = schema.get_type_name(field.type_.inner()).to_string();
                    // TODO resolve enclosing types, not just types immediately under the cursor
                    return Ok(ResolvedTypesAtLocationResponse {
                        path_and_schema_name: Some(PathAndSchemaName {
                            path: vec![type_name],
                            schema_name: node_resolution_info.project_name.to_string(),
                        }),
                    });
                }
            }
        }
    }

    Ok(ResolvedTypesAtLocationResponse {
        path_and_schema_name: None,
    })
}
<commit_msg>Rename schema => schemaName and other such things<commit_after>/*
 * Copyright (c) Facebook, Inc. and its affiliates.
 *
 * This source code is licensed under the MIT license found in the
 * LICENSE file in the root directory of this source tree.
 */

use crate::{
    lsp_runtime_error::{LSPRuntimeError, LSPRuntimeResult},
    server::LSPState,
};
use common::PerfLogger;
use lsp_types::{
    request::Request, Position, TextDocumentIdentifier, TextDocumentPositionParams, Url,
};
use schema::Schema;
use schema_documentation::SchemaDocumentation;
use serde::{Deserialize, Serialize};

pub(crate) enum ResolvedTypesAtLocation {}

#[derive(Deserialize, Serialize)]
pub(crate) struct ResolvedTypesAtLocationParams {
    file_name: String,
    line: u32,
    character: u32,
}

impl ResolvedTypesAtLocationParams {
    fn to_text_document_position_params(&self) -> LSPRuntimeResult<TextDocumentPositionParams> {
        Ok(TextDocumentPositionParams {
            text_document: TextDocumentIdentifier {
                uri: Url::parse(&self.file_name).map_err(|_| LSPRuntimeError::ExpectedError)?,
            },
            position: Position {
                character: self.character,
                line: self.line,
            },
        })
    }
}

#[derive(Deserialize, Serialize)]
#[serde(rename_all = "camelCase")]
pub(crate) struct ResolvedTypesAtLocationResponse {
    pub path_and_schema_name: Option<PathAndSchemaName>,
}

#[derive(Deserialize, Serialize)]
#[serde(rename_all = "camelCase")]
pub(crate) struct PathAndSchemaName {
    pub path: Vec<String>,
    pub schema_name: String,
}

impl Request for ResolvedTypesAtLocation {
    type Params = ResolvedTypesAtLocationParams;
    type Result = ResolvedTypesAtLocationResponse;
    const METHOD: &'static str = "relay/getResolvedTypesAtLocation";
}

pub(crate) fn on_get_resolved_types_at_location<
    TPerfLogger: PerfLogger + 'static,
    TSchemaDocumentation: SchemaDocumentation,
>(
    state: &mut LSPState<TPerfLogger, TSchemaDocumentation>,
    params: <ResolvedTypesAtLocation as Request>::Params,
) -> LSPRuntimeResult<<ResolvedTypesAtLocation as Request>::Result> {
    if let Ok(node_resolution_info) =
        state.resolve_node(&params.to_text_document_position_params()?)
    {
        if let Some(schema) = state.get_schemas().get(&node_resolution_info.project_name) {
            // If type_path is empty, type_path.resolve_current_field() will panic.
            if !node_resolution_info.type_path.0.is_empty() {
                let type_and_field = node_resolution_info
                    .type_path
                    .resolve_current_field(&schema);
                if let Some((_parent_type, field)) = type_and_field {
                    let type_name = schema.get_type_name(field.type_.inner()).to_string();
                    // TODO resolve enclosing types, not just types immediately under the cursor
                    return Ok(ResolvedTypesAtLocationResponse {
                        path_and_schema_name: Some(PathAndSchemaName {
                            path: vec![type_name],
                            schema_name: node_resolution_info.project_name.to_string(),
                        }),
                    });
                }
            }
        }
    }

    Ok(ResolvedTypesAtLocationResponse {
        path_and_schema_name: None,
    })
}
<|endoftext|>


<commit_before>// http://stackoverflow.com/questions/25877285/how-to-disable-unused-code-warnings-in-rust
// https://users.rust-lang.org/t/turning-off-compiler-warning-messages/4975/2
#![allow(non_snake_case)]

// mod api;
// mod cors;
// mod files;

extern crate actix;
extern crate actix_web;
extern crate env_logger;

extern crate postgres;
extern crate serde_json;
#[macro_use]
extern crate serde_derive;

extern crate dotenv;
use dotenv::dotenv;
use std::env;

use actix_web::{middleware, server, App, HttpRequest};

#[derive(Serialize)]
struct TemplateContext {
    parent: String,
    name: String,
    content: String,
    items: Vec<String>,
}

fn index(_req: &HttpRequest) -> &'static str {
    "Hello world"
}

// use std::path::Path;
// use std::process::Command;

// #[get("/template/<ssr>")]
// fn template(ssr: bool) -> CORS<Template> {
//     println!("ssr {}", ssr);
//     let s2 = getStr();
//     println!("s2 {}", s2);
//     let s: String = if ssr { s2 } else { "".to_owned() };
//     let context = TemplateContext {
//         parent: "index".to_owned(),
//         name: "Roman".to_owned(),
//         content: s.to_owned(),
//         items: vec!["One", "Two", "Three"]
//             .iter()
//             .map(|s| s.to_string())
//             .collect(),
//     };
//     CORS::any(Template::render("template", &context))
// }

// use std::fs;
// use std::fs::OpenOptions;
// use std::io::prelude::*;
// extern crate time;

// fn getStr() -> String {
//     fs::copy(
//         "../client/src/elm/Main.elm",
//         "../client/src/elm/Main.elm.bak",
//     )
//     .expect("file not copied");
//     let stdout: Vec<u8>;
//     {
//         let mut main_file = OpenOptions::new()
//             .append(true)
//             .open("../client/src/elm/Main.elm")
//             .expect("file not opened");

//         let str1 = format!(
//             r#"
// view : Html Msg
// view =
//     viewWithModel <|
//         Model [] HomeRoute <|
//             Flags "" {time} ""
// "#,
//             time = time::get_time().sec
//         );

//         main_file
//             .write(str1.as_bytes())
//             .expect("file content not saved");

//         stdout = Command::new("node")
//             .current_dir(&Path::new("../client"))
//             .arg("./node_modules/elm-static-html/index.js")
//             .arg("-f")
//             .arg("src/elm/Main.elm")
//             .output()
//             .expect("elm-static-html command failed to start")
//             .stdout;
//     }
//     fs::rename(
//         "../client/src/elm/Main.elm.bak",
//         "../client/src/elm/Main.elm",
//     )
//     .expect("file not renamed");

//     String::from_utf8_lossy(&*stdout)
//         .lines()
//         .skip_while(|x| x.find("id=\"content\"").is_none())
//         .collect()
// }

// #[error(404)]
// fn not_found(req: &Request) -> CORS<Template> {
//     let mut map = std::collections::HashMap::new();
//     map.insert("path", req.uri().as_str());
//     CORS::any(Template::render("error/404", &map))
// }

fn main() {
    dotenv().ok();
    env::set_var("RUST_LOG", "actix_web=info");
    env_logger::init();
    let sys = actix::System::new("hello-world");

    server::new(|| {
        App::new()
            .middleware(middleware::Logger::default())
            .resource("/", |r| r.f(index))
    })
    .bind("127.0.0.1:8080")
    .unwrap()
    .start();

    println!("Starting http server: 127.0.0.1:8080");

    let _ = sys.run();

    // println!("{:?}", env::var("data_server").unwrap());
    // rocket::ignite()
    //     .mount(
    //         "/",
    //         routes![
    //             template,
    //             files::favicon,
    //             files::index,
    //             files::redirect_to_index,
    //             files::js,
    //             files::styles,
    //             files::styles_with_query,
    //             files::images
    //         ],
    //     )
    //     .mount(
    //         "/api",
    //         routes![
    //             api::user_information,
    //             api::data_sets,
    //             api::data_set,
    //             api::data_set_category,
    //             api::data_sets_categories,
    //             api::data_sets_new
    //         ],
    //     )
    //     .catch(errors![not_found])
    //     .launch();
}
<commit_msg>getStr uncommented<commit_after>// http://stackoverflow.com/questions/25877285/how-to-disable-unused-code-warnings-in-rust
// https://users.rust-lang.org/t/turning-off-compiler-warning-messages/4975/2
#![allow(non_snake_case)]

// mod api;
// mod cors;
// mod files;

extern crate actix;
extern crate actix_web;
extern crate env_logger;

extern crate postgres;
extern crate serde_json;
#[macro_use]
extern crate serde_derive;

extern crate dotenv;
use dotenv::dotenv;
use std::env;

use actix_web::{middleware, server, App, HttpRequest};

#[derive(Serialize)]
struct TemplateContext {
    parent: String,
    name: String,
    content: String,
    items: Vec<String>,
}

fn index(_req: &HttpRequest) -> &'static str {
    "Hello world"
}

use std::path::Path;
use std::process::Command;

// #[get("/template/<ssr>")]
// fn template(ssr: bool) -> CORS<Template> {
//     println!("ssr {}", ssr);
//     let s2 = getStr();
//     println!("s2 {}", s2);
//     let s: String = if ssr { s2 } else { "".to_owned() };
//     let context = TemplateContext {
//         parent: "index".to_owned(),
//         name: "Roman".to_owned(),
//         content: s.to_owned(),
//         items: vec!["One", "Two", "Three"]
//             .iter()
//             .map(|s| s.to_string())
//             .collect(),
//     };
//     CORS::any(Template::render("template", &context))
// }

use std::fs;
use std::fs::OpenOptions;
use std::io::prelude::*;
extern crate time;

fn getStr() -> String {
    fs::copy(
        "../client/src/elm/Main.elm",
        "../client/src/elm/Main.elm.bak",
    )
    .expect("file not copied");
    let stdout: Vec<u8>;
    {
        let mut main_file = OpenOptions::new()
            .append(true)
            .open("../client/src/elm/Main.elm")
            .expect("file not opened");

        let str1 = format!(
            r#"
view : Html Msg
view =
    viewWithModel <|
        Model [] HomeRoute <|
            Flags "" {time} ""
"#,
            time = time::get_time().sec
        );

        main_file
            .write(str1.as_bytes())
            .expect("file content not saved");

        stdout = Command::new("node")
            .current_dir(&Path::new("../client"))
            .arg("./node_modules/elm-static-html/index.js")
            .arg("-f")
            .arg("src/elm/Main.elm")
            .output()
            .expect("elm-static-html command failed to start")
            .stdout;
    }
    fs::rename(
        "../client/src/elm/Main.elm.bak",
        "../client/src/elm/Main.elm",
    )
    .expect("file not renamed");

    String::from_utf8_lossy(&*stdout)
        .lines()
        .skip_while(|x| x.find("id=\"content\"").is_none())
        .collect()
}

// #[error(404)]
// fn not_found(req: &Request) -> CORS<Template> {
//     let mut map = std::collections::HashMap::new();
//     map.insert("path", req.uri().as_str());
//     CORS::any(Template::render("error/404", &map))
// }

fn main() {
    dotenv().ok();
    env::set_var("RUST_LOG", "actix_web=info");
    env_logger::init();
    let sys = actix::System::new("hello-world");

    server::new(|| {
        App::new()
            .middleware(middleware::Logger::default())
            .resource("/", |r| r.f(index))
    })
    .bind("127.0.0.1:8080")
    .unwrap()
    .start();

    println!("Starting http server: 127.0.0.1:8080");

    let _ = sys.run();

    // println!("{:?}", env::var("data_server").unwrap());
    // rocket::ignite()
    //     .mount(
    //         "/",
    //         routes![
    //             template,
    //             files::favicon,
    //             files::index,
    //             files::redirect_to_index,
    //             files::js,
    //             files::styles,
    //             files::styles_with_query,
    //             files::images
    //         ],
    //     )
    //     .mount(
    //         "/api",
    //         routes![
    //             api::user_information,
    //             api::data_sets,
    //             api::data_set,
    //             api::data_set_category,
    //             api::data_sets_categories,
    //             api::data_sets_new
    //         ],
    //     )
    //     .catch(errors![not_found])
    //     .launch();
}
<|endoftext|>


<commit_before>//! [POST /_matrix/client/r0/publicRooms](https://matrix.org/docs/spec/client_server/r0.6.1#post-matrix-client-r0-publicrooms)

use js_int::UInt;
use ruma_api::ruma_api;
use ruma_identifiers::ServerName;
use ruma_common::directory::{
    Filter, IncomingFilter, IncomingRoomNetwork, PublicRoomsChunk, RoomNetwork,
};

ruma_api! {
    metadata: {
        description: "Get the list of rooms in this homeserver's public directory.",
        method: POST,
        name: "get_public_rooms_filtered",
        path: "/_matrix/client/r0/publicRooms",
        rate_limited: false,
        authentication: AccessToken,
    }

    #[derive(Default)]
    request: {
        /// The server to fetch the public room lists from.
        ///
        /// `None` means the server this request is sent to.
        #[serde(skip_serializing_if = "Option::is_none")]
        #[ruma_api(query)]
        pub server: Option<&'a ServerName>,

        /// Limit for the number of results to return.
        #[serde(skip_serializing_if = "Option::is_none")]
        pub limit: Option<UInt>,

        /// Pagination token from a previous request.
        #[serde(skip_serializing_if = "Option::is_none")]
        pub since: Option<&'a str>,

        /// Filter to apply to the results.
        #[serde(skip_serializing_if = "Option::is_none")]
        pub filter: Option<Filter<'a>>,

        /// Network to fetch the public room lists from.
        #[serde(flatten, skip_serializing_if = "ruma_serde::is_default")]
        pub room_network: RoomNetwork<'a>,
    }

    #[derive(Default)]
    response: {
        /// A paginated chunk of public rooms.
        pub chunk: Vec<PublicRoomsChunk>,

        /// A pagination token for the response.
        #[serde(skip_serializing_if = "Option::is_none")]
        pub next_batch: Option<String>,

        /// A pagination token that allows fetching previous results.
        #[serde(skip_serializing_if = "Option::is_none")]
        pub prev_batch: Option<String>,

        /// An estimate on the total number of public rooms, if the server has an estimate.
        #[serde(skip_serializing_if = "Option::is_none")]
        pub total_room_count_estimate: Option<UInt>,
    }

    error: crate::Error
}

impl Request<'_> {
    /// Creates an empty `Request`.
    pub fn new() -> Self {
        Default::default()
    }
}

impl Response {
    /// Creates an empty `Response`.
    pub fn new() -> Self {
        Default::default()
    }
}
<commit_msg>Fix formatting<commit_after>//! [POST /_matrix/client/r0/publicRooms](https://matrix.org/docs/spec/client_server/r0.6.1#post-matrix-client-r0-publicrooms)

use js_int::UInt;
use ruma_api::ruma_api;
use ruma_common::directory::{
    Filter, IncomingFilter, IncomingRoomNetwork, PublicRoomsChunk, RoomNetwork,
};
use ruma_identifiers::ServerName;

ruma_api! {
    metadata: {
        description: "Get the list of rooms in this homeserver's public directory.",
        method: POST,
        name: "get_public_rooms_filtered",
        path: "/_matrix/client/r0/publicRooms",
        rate_limited: false,
        authentication: AccessToken,
    }

    #[derive(Default)]
    request: {
        /// The server to fetch the public room lists from.
        ///
        /// `None` means the server this request is sent to.
        #[serde(skip_serializing_if = "Option::is_none")]
        #[ruma_api(query)]
        pub server: Option<&'a ServerName>,

        /// Limit for the number of results to return.
        #[serde(skip_serializing_if = "Option::is_none")]
        pub limit: Option<UInt>,

        /// Pagination token from a previous request.
        #[serde(skip_serializing_if = "Option::is_none")]
        pub since: Option<&'a str>,

        /// Filter to apply to the results.
        #[serde(skip_serializing_if = "Option::is_none")]
        pub filter: Option<Filter<'a>>,

        /// Network to fetch the public room lists from.
        #[serde(flatten, skip_serializing_if = "ruma_serde::is_default")]
        pub room_network: RoomNetwork<'a>,
    }

    #[derive(Default)]
    response: {
        /// A paginated chunk of public rooms.
        pub chunk: Vec<PublicRoomsChunk>,

        /// A pagination token for the response.
        #[serde(skip_serializing_if = "Option::is_none")]
        pub next_batch: Option<String>,

        /// A pagination token that allows fetching previous results.
        #[serde(skip_serializing_if = "Option::is_none")]
        pub prev_batch: Option<String>,

        /// An estimate on the total number of public rooms, if the server has an estimate.
        #[serde(skip_serializing_if = "Option::is_none")]
        pub total_room_count_estimate: Option<UInt>,
    }

    error: crate::Error
}

impl Request<'_> {
    /// Creates an empty `Request`.
    pub fn new() -> Self {
        Default::default()
    }
}

impl Response {
    /// Creates an empty `Response`.
    pub fn new() -> Self {
        Default::default()
    }
}
<|endoftext|>


<commit_before>extern crate libsmac;

fn main() {
    println!("Hello, world!");
}
<commit_msg>Add test smac<commit_after>extern crate libsmac;

use libsmac::lexer;
use lexer::matcher::{
    Whitespace, IntLiteral
};

fn main() {
    let mut data = r#"
1 2 3 4 5 6 7 8 9 10 420
    "#.chars();

    let tokenizer = lexer::Tokenizer::new(&mut data);
    let mut lexer = lexer::Lexer::new(tokenizer);

    let whitespace  = Whitespace {};
    let int_literal = IntLiteral {};

    lexer.matchers_mut().push(Box::new(whitespace));
    lexer.matchers_mut().push(Box::new(int_literal));

    for t in lexer {
        println!("{}", t)
    }
}
<|endoftext|>


<commit_before>//
//   Copyright 2016 Andrew Hunter
//
//   Licensed under the Apache License, Version 2.0 (the "License");
//   you may not use this file except in compliance with the License.
//   You may obtain a copy of the License at
//
//       http://www.apache.org/licenses/LICENSE-2.0
//
//   Unless required by applicable law or agreed to in writing, software
//   distributed under the License is distributed on an "AS IS" BASIS,
//   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
//   See the License for the specific language governing permissions and
//   limitations under the License.
//

//!
//! A symbol reader reads one symbol at a time from a source
//!

use std::slice::Iter;
use std::io::Read;
use std::io::Bytes;
use std::str::Chars;

///
/// A symbol reader reads one symbol at a time from a source
///
pub trait SymbolReader<Symbol> {
    ///
    /// Reads the next symbol from this reader
    ///
    fn next_symbol(&mut self) -> Option<Symbol>;
}

///
/// Trait that can be implemented by things that can construct a symbol reader
///
pub trait SymbolSource<'a, Symbol> {
    /// The type of symbol reader that will be generated by this call
    type SymbolReader: SymbolReader<Symbol>+'a;

    /// Returns a new object that can read the symbols from this one
    fn read_symbols(self) -> Self::SymbolReader;
}

impl<'a, Symbol: Clone+'a> SymbolSource<'a, Symbol> for &'a Vec<Symbol> {
    type SymbolReader = Iter<'a, Symbol>;

    fn read_symbols(self) -> Self::SymbolReader {
        self.iter()
    }
}

impl<'a, Symbol: Clone+'a> SymbolReader<Symbol> for Iter<'a, Symbol> {
    fn next_symbol(&mut self) -> Option<Symbol> {
        if let Some(sym) = self.next() {
            Some(sym.clone())
        } else {
            None
        }
    }
}

// Can read from streams

//
// TODO: implementing SymbolSource for Read would be nice
// It's just a matter of calling bytes() on the appropriate type, but Rust's type system is simultaneously too clever and not clever enough
// to allow that in any sensible way. You can't do it an an arbitrary Read because the Bytes object is not sized without knowing its real
// type; I couldn't figure out a trick using the Self type to get around that, though those do work sometimes.
// `impl<X: Read> SymbolReader for X` sounds like a nice idea but Rust thinks X can be anything and won't allow any other implementations
// of the interface, which makes that useless too.
// Screwing around with lifetimes and references like below seems like it should work, but Rust doesn't seem to see the implementations on
// actual streams.
//

/*
impl<'a> SymbolSource<'a, u8> for &'a mut Read {
    type SymbolReader = ByteSymbolReader<Self>;

    fn read_symbols(self) -> Self::SymbolReader {
        ByteSymbolReader::new(self.bytes())
    }
}

impl<'a> SymbolSource<'a, u8> for &'a mut BufRead {
    type SymbolReader = ByteSymbolReader<Self>;

    fn read_symbols(self) -> Self::SymbolReader {
        ByteSymbolReader::new(self.bytes())
    }
}
*/

///
/// The ByteSymbolReader turns a `std::io::Bytes` object into a symbol reader
///
pub struct ByteSymbolReader<Reader: Read> {
    bytes: Bytes<Reader>
}

impl<Reader: Read> ByteSymbolReader<Reader> {
    pub fn new(bytes: Bytes<Reader>) -> ByteSymbolReader<Reader> {
        ByteSymbolReader { bytes: bytes }
    }

    pub fn from(reader: Reader) -> ByteSymbolReader<Reader> {
        Self::new(reader.bytes())
    }
}

impl<Reader: Read> SymbolReader<u8> for ByteSymbolReader<Reader> {
    fn next_symbol(&mut self) -> Option<u8> {
        if let Some(Ok(sym)) = self.bytes.next() {
            Some(sym.clone())
        } else {
            None
        }
    }
}

//
// Can read from strings
//
impl<'a> SymbolSource<'a, char> for &'a str {
    type SymbolReader = Chars<'a>;

    fn read_symbols(self) -> Self::SymbolReader {
        self.chars()
    }
}

impl<'a> SymbolReader<char> for Chars<'a> {
    fn next_symbol(&mut self) -> Option<char> {
        self.next()
    }
}

//
// Can convert symbol streams to vectors
//
pub trait ReaderToVector<Symbol> {
    /// Reads every symbol in this object and returns a vector
    fn to_vec(&mut self) -> Vec<Symbol>;
}

impl<Symbol, Reader: SymbolReader<Symbol>> ReaderToVector<Symbol> for Reader {
    #[inline]
    fn to_vec(&mut self) -> Vec<Symbol> {
        let mut result = vec![];

        while let Some(symbol) = self.next_symbol() {
            result.push(symbol);
        }

        result
    }
}

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

    #[test]
    fn can_read_from_vec() {
        let source      = vec![1, 2, 3];
        let mut reader  = source.read_symbols();

        assert!(reader.next_symbol() == Some(1));
        assert!(reader.next_symbol() == Some(2));
        assert!(reader.next_symbol() == Some(3));
        assert!(reader.next_symbol() == None);
    }

    #[test]
    fn can_convert_to_vec() {
        let source      = vec![1, 2, 3];
        let mut reader  = source.read_symbols();
        let result      = reader.to_vec();

        assert!(result == vec![1, 2, 3]);
    }

    #[test]
    fn can_read_from_bytes_reader() {
        let array: [u8; 3] = [1, 2, 3];
        let slice = &array[..];
        let mut reader = ByteSymbolReader::from(slice);

        assert!(reader.next_symbol() == Some(1));
        assert!(reader.next_symbol() == Some(2));
        assert!(reader.next_symbol() == Some(3));
        assert!(reader.next_symbol() == None);
    }

    #[test]
    fn can_read_from_string_reader() {
        let mut reader = "abc".read_symbols();

        assert!(reader.next_symbol() == Some('a'));
        assert!(reader.next_symbol() == Some('b'));
        assert!(reader.next_symbol() == Some('c'));
        assert!(reader.next_symbol() == None);
    }
}
<commit_msg>Add a way to map the symbols from one stream to another<commit_after>//
//   Copyright 2016 Andrew Hunter
//
//   Licensed under the Apache License, Version 2.0 (the "License");
//   you may not use this file except in compliance with the License.
//   You may obtain a copy of the License at
//
//       http://www.apache.org/licenses/LICENSE-2.0
//
//   Unless required by applicable law or agreed to in writing, software
//   distributed under the License is distributed on an "AS IS" BASIS,
//   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
//   See the License for the specific language governing permissions and
//   limitations under the License.
//

//!
//! A symbol reader reads one symbol at a time from a source
//!

use std::slice::Iter;
use std::io::Read;
use std::io::Bytes;
use std::str::Chars;
use std::marker::PhantomData;

///
/// A symbol reader reads one symbol at a time from a source
///
pub trait SymbolReader<Symbol> {
    ///
    /// Reads the next symbol from this reader
    ///
    fn next_symbol(&mut self) -> Option<Symbol>;
}

///
/// Trait that can be implemented by things that can construct a symbol reader
///
pub trait SymbolSource<'a, Symbol> {
    /// The type of symbol reader that will be generated by this call
    type SymbolReader: SymbolReader<Symbol>+'a;

    /// Returns a new object that can read the symbols from this one
    fn read_symbols(self) -> Self::SymbolReader;
}

impl<'a, Symbol: Clone+'a> SymbolSource<'a, Symbol> for &'a Vec<Symbol> {
    type SymbolReader = Iter<'a, Symbol>;

    fn read_symbols(self) -> Self::SymbolReader {
        self.iter()
    }
}

impl<'a, Symbol: Clone+'a> SymbolReader<Symbol> for Iter<'a, Symbol> {
    fn next_symbol(&mut self) -> Option<Symbol> {
        if let Some(sym) = self.next() {
            Some(sym.clone())
        } else {
            None
        }
    }
}

// Can read from streams

//
// TODO: implementing SymbolSource for Read would be nice
// It's just a matter of calling bytes() on the appropriate type, but Rust's type system is simultaneously too clever and not clever enough
// to allow that in any sensible way. You can't do it an an arbitrary Read because the Bytes object is not sized without knowing its real
// type; I couldn't figure out a trick using the Self type to get around that, though those do work sometimes.
// `impl<X: Read> SymbolReader for X` sounds like a nice idea but Rust thinks X can be anything and won't allow any other implementations
// of the interface, which makes that useless too.
// Screwing around with lifetimes and references like below seems like it should work, but Rust doesn't seem to see the implementations on
// actual streams.
//

/*
impl<'a> SymbolSource<'a, u8> for &'a mut Read {
    type SymbolReader = ByteSymbolReader<Self>;

    fn read_symbols(self) -> Self::SymbolReader {
        ByteSymbolReader::new(self.bytes())
    }
}

impl<'a> SymbolSource<'a, u8> for &'a mut BufRead {
    type SymbolReader = ByteSymbolReader<Self>;

    fn read_symbols(self) -> Self::SymbolReader {
        ByteSymbolReader::new(self.bytes())
    }
}
*/

///
/// The ByteSymbolReader turns a `std::io::Bytes` object into a symbol reader
///
pub struct ByteSymbolReader<Reader: Read> {
    bytes: Bytes<Reader>
}

impl<Reader: Read> ByteSymbolReader<Reader> {
    pub fn new(bytes: Bytes<Reader>) -> ByteSymbolReader<Reader> {
        ByteSymbolReader { bytes: bytes }
    }

    pub fn from(reader: Reader) -> ByteSymbolReader<Reader> {
        Self::new(reader.bytes())
    }
}

impl<Reader: Read> SymbolReader<u8> for ByteSymbolReader<Reader> {
    fn next_symbol(&mut self) -> Option<u8> {
        if let Some(Ok(sym)) = self.bytes.next() {
            Some(sym.clone())
        } else {
            None
        }
    }
}

//
// Can read from strings
//
impl<'a> SymbolSource<'a, char> for &'a str {
    type SymbolReader = Chars<'a>;

    fn read_symbols(self) -> Self::SymbolReader {
        self.chars()
    }
}

impl<'a> SymbolReader<char> for Chars<'a> {
    fn next_symbol(&mut self) -> Option<char> {
        self.next()
    }
}

///
/// Converts symbol streams to vectors
///
pub trait ReaderToVector<Symbol> {
    /// Reads every symbol in this object and returns a vector
    fn to_vec(&mut self) -> Vec<Symbol>;
}

impl<Symbol, Reader: SymbolReader<Symbol>> ReaderToVector<Symbol> for Reader {
    #[inline]
    fn to_vec(&mut self) -> Vec<Symbol> {
        let mut result = vec![];

        while let Some(symbol) = self.next_symbol() {
            result.push(symbol);
        }

        result
    }
}

///
/// Provides a way to map symbol streams to streams of other types
///
pub trait MapSymbolReader<Symbol> : SymbolReader<Symbol>+Sized {
    /// Maps symbols in this stream to symbols in a new stream
    fn map_symbols<'a, OutputSymbol, MapFunction>(&'a mut self, mapping_function: MapFunction) -> MappedStream<'a, Symbol, OutputSymbol, MapFunction, Self>
    where MapFunction: FnMut(Symbol) -> OutputSymbol;
}

pub struct MappedStream<'a, InputSymbol, OutputSymbol, MapFunction, Reader: SymbolReader<InputSymbol>+'a>
where MapFunction: FnMut(InputSymbol) -> OutputSymbol {
    /// The source stream
    source_stream: &'a mut Reader,

    /// A function used to map a symbol from the source stream to a symbol in the output stream
    mapping_function: MapFunction,

    /// Shuts the compiler up
    #[allow(dead_code)]
    these_are_used_in_the_mapping_function_but_rust_cant_see_that: (PhantomData<InputSymbol>, PhantomData<OutputSymbol>)
}

impl<Symbol, Reader: SymbolReader<Symbol>> MapSymbolReader<Symbol> for Reader {
    fn map_symbols<'a, OutputSymbol, MapFunction>(&'a mut self, mapping_function: MapFunction) -> MappedStream<'a, Symbol, OutputSymbol, MapFunction, Self>
    where MapFunction: FnMut(Symbol) -> OutputSymbol {
        MappedStream {
            source_stream: self,
            mapping_function: mapping_function,
            these_are_used_in_the_mapping_function_but_rust_cant_see_that: (PhantomData, PhantomData)
        }
    }
}

impl<'a, InputSymbol, OutputSymbol, MapFunction, Reader: SymbolReader<InputSymbol>+'a> SymbolReader<OutputSymbol> for MappedStream<'a, InputSymbol, OutputSymbol, MapFunction, Reader>
where MapFunction: FnMut(InputSymbol) -> OutputSymbol {
    fn next_symbol(&mut self) -> Option<OutputSymbol> {
        if let Some(input_symbol) = self.source_stream.next_symbol() {
            Some((self.mapping_function)(input_symbol))
        } else {
            None
        }
    }
}

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

    #[test]
    fn can_read_from_vec() {
        let source      = vec![1, 2, 3];
        let mut reader  = source.read_symbols();

        assert!(reader.next_symbol() == Some(1));
        assert!(reader.next_symbol() == Some(2));
        assert!(reader.next_symbol() == Some(3));
        assert!(reader.next_symbol() == None);
    }

    #[test]
    fn can_convert_to_vec() {
        let source      = vec![1, 2, 3];
        let mut reader  = source.read_symbols();
        let result      = reader.to_vec();

        assert!(result == vec![1, 2, 3]);
    }

    #[test]
    fn can_map_stream() {
        let source      = vec![1, 2, 3];
        let mut reader  = source.read_symbols();
        let result      = reader.map_symbols(|sym| sym+1).to_vec();

        assert!(result == vec![2, 3, 4]);
    }

    #[test]
    fn can_read_from_bytes_reader() {
        let array: [u8; 3] = [1, 2, 3];
        let slice = &array[..];
        let mut reader = ByteSymbolReader::from(slice);

        assert!(reader.next_symbol() == Some(1));
        assert!(reader.next_symbol() == Some(2));
        assert!(reader.next_symbol() == Some(3));
        assert!(reader.next_symbol() == None);
    }

    #[test]
    fn can_read_from_string_reader() {
        let mut reader = "abc".read_symbols();

        assert!(reader.next_symbol() == Some('a'));
        assert!(reader.next_symbol() == Some('b'));
        assert!(reader.next_symbol() == Some('c'));
        assert!(reader.next_symbol() == None);
    }
}
<|endoftext|>


<commit_before>use Renderable;
use Block;
use Value;
use template::Template;
use LiquidOptions;
use tags::IfBlock;
use lexer::Token;
use lexer::Token::{Identifier, StringLiteral, NumberLiteral, Comparison};
use lexer::ComparisonOperator;
use lexer::ComparisonOperator::{
    Equals, NotEquals,
    LessThan, GreaterThan,
    LessThanEquals, GreaterThanEquals,
    Contains
};
use parser::parse;
use lexer::Element;
use lexer::Element::{Tag, Raw};
use std::collections::HashMap;
use std::default::Default;

struct If<'a>{
    lh : Token,
    comparison : ComparisonOperator,
    rh : Token,
    if_true: Template<'a>,
    if_false: Option<Template<'a>>
}

impl<'a> If<'a>{
    fn compare(&self, context: &HashMap<String, Value>) -> Result<bool, &'static str>{
        match (&self.lh, &self.rh)  {
            (&NumberLiteral(a), &NumberLiteral(b)) => Ok(compare_numbers(a, b, &self.comparison)),
            (&Identifier(ref var), &NumberLiteral(b)) => {
                match context.get(var.as_slice()) {
                    Some(&Value::Num(a)) => Ok(compare_numbers(a, b, &self.comparison)),
                    _ => Err("not comparable")
                }
            },
            (&NumberLiteral(a), &Identifier(ref var)) => {
                match context.get(var.as_slice()) {
                    Some(&Value::Num(b)) => Ok(compare_numbers(a, b, &self.comparison)),
                    _ => Err("not comparable")
                }
            }
            (&Identifier(ref var_a), &Identifier(ref var_b)) => {
                match (context.get(var_a.as_slice()), context.get(var_b.as_slice())) {
                    (Some(&Value::Num(a)), Some(&Value::Num(b))) => Ok(compare_numbers(a, b, &self.comparison)),
                    _ => Err("not comparable")
                }
            }
            (_, _) => Err("not implemented yet!") // TODO
        }
    }
}

fn compare_numbers(a : f32, b : f32, comparison : &ComparisonOperator) -> bool{
    match comparison {
        &Equals => a == b,
        &NotEquals => a != b,
        &LessThan => a < b,
        &GreaterThan => a > b,
        &LessThanEquals => a <= b,
        &GreaterThanEquals => a >= b,
        &Contains => false, // TODO!!!
    }
}

impl<'a> Renderable for If<'a>{
    fn render(&self, context: &HashMap<String, Value>) -> Option<String>{
        if self.compare(context).unwrap_or(false){
            self.if_true.render(context)
        }else{
            match self.if_false {
                Some(ref template) => template.render(context),
                _ => None
            }
        }
    }
}

impl<'a> Block for IfBlock<'a>{
    fn initialize<'a>(&'a self, tag_name: &str, arguments: &[Token], tokens: Vec<Element>, options : &'a LiquidOptions<'a>) -> Box<Renderable>{
        let mut args = arguments.iter();

        let lh = match args.next() {
            Some(&StringLiteral(ref x)) => StringLiteral(x.clone()),
            Some(&NumberLiteral(ref x)) => NumberLiteral(x.clone()),
            Some(&Identifier(ref x)) => Identifier(x.clone()),
            x => panic!("Expected a value, found {}", x)
        };

        let comp = match args.next() {
            Some(&Comparison(ref x)) => x.clone(),
            x => panic!("Expected a comparison operator, found {}", x)
        };

        let rh = match args.next() {
            Some(&StringLiteral(ref x)) => StringLiteral(x.clone()),
            Some(&NumberLiteral(ref x)) => NumberLiteral(x.clone()),
            Some(&Identifier(ref x)) => Identifier(x.clone()),
            x => panic!("Expected a value, found {}", x)
        };

        let else_block = vec![Identifier("else".to_string())];

        let if_true_tokens = tokens.iter().take_while(|&x| match x  {
            &Tag(ref eb, _) => *eb != else_block,
            _ => true
        }).map(|x| x.clone()).collect();

        let if_false_tokens : Vec<Element> = tokens.iter().skip_while(|&x| match x  {
            &Tag(ref eb, _) => *eb != else_block,
            _ => true
        }).map(|x| x.clone()).collect();

        let if_false = if if_false_tokens.len() > 0 {
            Some(Template::new(parse(if_false_tokens, options)))
        }else{
            None
        };

        box If{
            lh : lh,
            comparison : comp,
            rh : rh,
            if_true: Template::new(parse(if_true_tokens, options)),
            if_false: if_false
        } as Box<Renderable>
    }
}

#[test]
fn test_if() {
    let block = IfBlock;
    let options : LiquidOptions = Default::default();
    let if_tag = block.initialize("if", vec![NumberLiteral(5f32), Comparison(LessThan), NumberLiteral(6f32)][0..], vec![Raw("if true".to_string())], &options);
    assert_eq!(if_tag.render(&HashMap::new()).unwrap(), "if true".to_string());

    let else_tag = block.initialize("if", vec![NumberLiteral(7f32), Comparison(LessThan), NumberLiteral(6f32)][0..], vec![Raw("if true".to_string()), Tag(vec![Identifier("else".to_string())], "".to_string()), Raw("if false".to_string())], &options);
    assert_eq!(else_tag.render(&HashMap::new()).unwrap(), "if false".to_string());
}

<commit_msg>Don't shadow if block lifetime<commit_after>use Renderable;
use Block;
use Value;
use template::Template;
use LiquidOptions;
use tags::IfBlock;
use lexer::Token;
use lexer::Token::{Identifier, StringLiteral, NumberLiteral, Comparison};
use lexer::ComparisonOperator;
use lexer::ComparisonOperator::{
    Equals, NotEquals,
    LessThan, GreaterThan,
    LessThanEquals, GreaterThanEquals,
    Contains
};
use parser::parse;
use lexer::Element;
use lexer::Element::{Tag, Raw};
use std::collections::HashMap;
use std::default::Default;

struct If<'a>{
    lh : Token,
    comparison : ComparisonOperator,
    rh : Token,
    if_true: Template<'a>,
    if_false: Option<Template<'a>>
}

impl<'a> If<'a>{
    fn compare(&self, context: &HashMap<String, Value>) -> Result<bool, &'static str>{
        match (&self.lh, &self.rh)  {
            (&NumberLiteral(a), &NumberLiteral(b)) => Ok(compare_numbers(a, b, &self.comparison)),
            (&Identifier(ref var), &NumberLiteral(b)) => {
                match context.get(var.as_slice()) {
                    Some(&Value::Num(a)) => Ok(compare_numbers(a, b, &self.comparison)),
                    _ => Err("not comparable")
                }
            },
            (&NumberLiteral(a), &Identifier(ref var)) => {
                match context.get(var.as_slice()) {
                    Some(&Value::Num(b)) => Ok(compare_numbers(a, b, &self.comparison)),
                    _ => Err("not comparable")
                }
            }
            (&Identifier(ref var_a), &Identifier(ref var_b)) => {
                match (context.get(var_a.as_slice()), context.get(var_b.as_slice())) {
                    (Some(&Value::Num(a)), Some(&Value::Num(b))) => Ok(compare_numbers(a, b, &self.comparison)),
                    _ => Err("not comparable")
                }
            }
            (_, _) => Err("not implemented yet!") // TODO
        }
    }
}

fn compare_numbers(a : f32, b : f32, comparison : &ComparisonOperator) -> bool{
    match comparison {
        &Equals => a == b,
        &NotEquals => a != b,
        &LessThan => a < b,
        &GreaterThan => a > b,
        &LessThanEquals => a <= b,
        &GreaterThanEquals => a >= b,
        &Contains => false, // TODO!!!
    }
}

impl<'a> Renderable for If<'a>{
    fn render(&self, context: &HashMap<String, Value>) -> Option<String>{
        if self.compare(context).unwrap_or(false){
            self.if_true.render(context)
        }else{
            match self.if_false {
                Some(ref template) => template.render(context),
                _ => None
            }
        }
    }
}

impl<'b> Block for IfBlock<'b>{
    fn initialize<'a>(&'a self, tag_name: &str, arguments: &[Token], tokens: Vec<Element>, options : &'a LiquidOptions<'a>) -> Box<Renderable>{
        let mut args = arguments.iter();

        let lh = match args.next() {
            Some(&StringLiteral(ref x)) => StringLiteral(x.clone()),
            Some(&NumberLiteral(ref x)) => NumberLiteral(x.clone()),
            Some(&Identifier(ref x)) => Identifier(x.clone()),
            x => panic!("Expected a value, found {}", x)
        };

        let comp = match args.next() {
            Some(&Comparison(ref x)) => x.clone(),
            x => panic!("Expected a comparison operator, found {}", x)
        };

        let rh = match args.next() {
            Some(&StringLiteral(ref x)) => StringLiteral(x.clone()),
            Some(&NumberLiteral(ref x)) => NumberLiteral(x.clone()),
            Some(&Identifier(ref x)) => Identifier(x.clone()),
            x => panic!("Expected a value, found {}", x)
        };

        let else_block = vec![Identifier("else".to_string())];

        let if_true_tokens = tokens.iter().take_while(|&x| match x  {
            &Tag(ref eb, _) => *eb != else_block,
            _ => true
        }).map(|x| x.clone()).collect();

        let if_false_tokens : Vec<Element> = tokens.iter().skip_while(|&x| match x  {
            &Tag(ref eb, _) => *eb != else_block,
            _ => true
        }).map(|x| x.clone()).collect();

        let if_false = if if_false_tokens.len() > 0 {
            Some(Template::new(parse(if_false_tokens, options)))
        }else{
            None
        };

        box If{
            lh : lh,
            comparison : comp,
            rh : rh,
            if_true: Template::new(parse(if_true_tokens, options)),
            if_false: if_false
        } as Box<Renderable>
    }
}

#[test]
fn test_if() {
    let block = IfBlock;
    let options : LiquidOptions = Default::default();
    let if_tag = block.initialize("if", vec![NumberLiteral(5f32), Comparison(LessThan), NumberLiteral(6f32)][0..], vec![Raw("if true".to_string())], &options);
    assert_eq!(if_tag.render(&HashMap::new()).unwrap(), "if true".to_string());

    let else_tag = block.initialize("if", vec![NumberLiteral(7f32), Comparison(LessThan), NumberLiteral(6f32)][0..], vec![Raw("if true".to_string()), Tag(vec![Identifier("else".to_string())], "".to_string()), Raw("if false".to_string())], &options);
    assert_eq!(else_tag.render(&HashMap::new()).unwrap(), "if false".to_string());
}

<|endoftext|>