<commit_before>// Copyright 2014 Alexis Mousset. See the COPYRIGHT
// file at the top-level directory of this distribution.
//
// 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.

//! # Rust SMTP client
//!
//! The client does its best to follow RFC 5321 (https://tools.ietf.org/html/rfc5321).
//!
//! It also implements the following extensions :
//!
//! * 8BITMIME (RFC 6152 : https://tools.ietf.org/html/rfc6152)
//! * SIZE (RFC 1427 : https://tools.ietf.org/html/rfc1427)
//!
//! ## What this client is NOT made for
//!
//! Send emails to public email servers. It is not designed to smartly handle servers responses,
//! to rate-limit emails, to make retries, and all that complicated stuff needed to politely
//! talk to public servers.
//!
//! What this client does is basically try once to send the email, and say if it worked.
//! It should only be used to transfer emails to a relay server.
//!
//! ## Usage
//!
//! ```rust
//! extern crate smtp;
//! use std::io::net::tcp::TcpStream;
//! use smtp::client::SmtpClient;
//! use std::strbuf::StrBuf;
//!
//! let mut email_client: SmtpClient<StrBuf, TcpStream> =
//!     SmtpClient::new(StrBuf::from_str("localhost"), None, None);
//! email_client.send_mail(
//!     StrBuf::from_str("user@example.com"),
//!     vec!(StrBuf::from_str("user@example.org")),
//!     StrBuf::from_str("Test email")
//! );
//! ```

#![crate_id = "smtp#0.1-pre"]
#![crate_type = "rlib"]
#![crate_type = "dylib"]

#![desc = "Rust SMTP client"]
#![comment = "Simple SMTP client"]
#![license = "MIT/ASL2"]
#![doc(html_root_url = "http://amousset.github.io/rust-smtp/smtp/"]

#![feature(macro_rules)]
#![feature(phase)]
#![deny(non_camel_case_types)]
#![deny(missing_doc)]
#![deny(unnecessary_qualification)]
#![deny(non_uppercase_statics)]
#![deny(unnecessary_typecast)]
#![deny(unused_result)]
#![deny(deprecated_owned_vector)]

#![feature(phase)] #[phase(syntax, link)] extern crate log;

pub mod commands;
pub mod common;
pub mod client;
<commit_msg>Add html_root_url to the crate doc<commit_after>// Copyright 2014 Alexis Mousset. See the COPYRIGHT
// file at the top-level directory of this distribution.
//
// 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.

//! # Rust SMTP client
//!
//! The client does its best to follow RFC 5321 (https://tools.ietf.org/html/rfc5321).
//!
//! It also implements the following extensions :
//!
//! * 8BITMIME (RFC 6152 : https://tools.ietf.org/html/rfc6152)
//! * SIZE (RFC 1427 : https://tools.ietf.org/html/rfc1427)
//!
//! ## What this client is NOT made for
//!
//! Send emails to public email servers. It is not designed to smartly handle servers responses,
//! to rate-limit emails, to make retries, and all that complicated stuff needed to politely
//! talk to public servers.
//!
//! What this client does is basically try once to send the email, and say if it worked.
//! It should only be used to transfer emails to a relay server.
//!
//! ## Usage
//!
//! ```rust
//! extern crate smtp;
//! use std::io::net::tcp::TcpStream;
//! use smtp::client::SmtpClient;
//! use std::strbuf::StrBuf;
//!
//! let mut email_client: SmtpClient<StrBuf, TcpStream> =
//!     SmtpClient::new(StrBuf::from_str("localhost"), None, None);
//! email_client.send_mail(
//!     StrBuf::from_str("user@example.com"),
//!     vec!(StrBuf::from_str("user@example.org")),
//!     StrBuf::from_str("Test email")
//! );
//! ```

#![crate_id = "smtp#0.1-pre"]
#![crate_type = "rlib"]
#![crate_type = "dylib"]

#![desc = "Rust SMTP client"]
#![comment = "Simple SMTP client"]
#![license = "MIT/ASL2"]
#![doc(html_root_url = "http://amousset.github.io/rust-smtp/smtp/")]

#![feature(macro_rules)]
#![feature(phase)]
#![deny(non_camel_case_types)]
#![deny(missing_doc)]
#![deny(unnecessary_qualification)]
#![deny(non_uppercase_statics)]
#![deny(unnecessary_typecast)]
#![deny(unused_result)]
#![deny(deprecated_owned_vector)]

#![feature(phase)] #[phase(syntax, link)] extern crate log;

pub mod commands;
pub mod common;
pub mod client;
<|endoftext|>


<commit_before>//! Endpoints for the public room directory.
<commit_msg>publicRooms endpoint<commit_after>//! Endpoints for the public room directory.

/// GET /_matrix/client/r0/publicRooms
///
/// [Matrix spec link](http://matrix.org/docs/spec/client_server/r0.2.0.html#get-matrix-client-r0-publicrooms)
pub mod public_rooms {
    use ruma_identifiers::{RoomId, RoomAliasId};

    /// A chunk of the response, describing one room
    #[derive(Clone, Debug, Deserialize, Serialize)]
    pub struct PublicRoomsChunk {
        pub world_readable: bool,
        pub topic: Option<String>,
        pub num_joined_members: u64,
        pub avatar_url: Option<String>,
        pub room_id: RoomId,
        pub guest_can_join: bool,
        pub aliases: Vec<RoomAliasId>,
        pub name: Option<String>
    }

    /// This API response type
    #[derive(Clone, Debug, Deserialize, Serialize)]
    pub struct Response {
        pub start: String,
        pub chunk: Vec<PublicRoomsChunk>,
        pub end: String
    }

    /// Details about this API endpoint.
    pub struct Endpoint;

    impl ::Endpoint for Endpoint {
        type BodyParams = ();
        type PathParams = ();
        type QueryParams = ();
        type Response = Response;

        fn method() -> ::Method {
            ::Method::Get
        }

        fn request_path(_params: Self::PathParams) -> String {
            Self::router_path()
        }

        fn router_path() -> String {
            "/_matrix/client/r0/publicRooms".to_string()
        }
    }
}
<|endoftext|>


<commit_before>extern crate hyper;
extern crate image;

use self::hyper::client::Client;
use self::hyper::header::UserAgent;

use std::io::{Read,Write};
use std::fs::{File,OpenOptions,read_dir,create_dir};
use std::path::Path;

pub use super::DB;

use rustc_serialize::json::Json;

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

use self::image::FilterType;

#[derive(Debug)]
pub struct Image {
    name: String,
    tags: Vec<String>,
    got_from: String,
    url: String,
    rating: char,
    post_url: String
}

pub mod e621;
pub mod derpy;
pub mod danbooru;
pub mod konachan;

/// Сохраняет картинку & создаёт к ней превью
pub fn save_image(dir: &Path, name: &str, file: &[u8]) {
    if let Err(_) = read_dir("assets/images") {
        create_dir("assets/images").unwrap();
    }
    if let Err(_) = read_dir("assets/images/preview") {
        create_dir("assets/images/preview").unwrap();
    }

    let prev = image::load_from_memory(file).unwrap().resize(500, 500, FilterType::Nearest);

    let mut f = File::create(dir.join(name)).unwrap();
    let mut prevf = File::create(dir.join("preview").join(name)).unwrap();

    f.write(file).unwrap();
    prev.save(&mut prevf, image::JPEG).unwrap();
}

fn process_downloads(client: &Client, images: &[Image], recv: &Receiver<()>) -> Result<(),()> {
    let images_c = DB.get_images(None,0).unwrap();
    let mut outf = OpenOptions::new().append(true).create(true).open("OUTPUT").unwrap();

    for im in images {
        match recv.try_recv() {
            Ok(_) | Err(TryRecvError::Disconnected) => {
                return Err(());
            }
            Err(TryRecvError::Empty) => {}
        }

        if !images_c.iter().any(|x| x.name == im.name ) {
            if im.got_from == "konachan" || im.got_from == "danbooru" {
                download(&Client::new(), im)?;
            } else {
                download(client, im)?;
            }
        } else {
            let mut m_tags = images_c.iter().find(|x| x.name == im.name ).unwrap().tags.clone();
            let mut curr_tags = im.tags.clone();
            m_tags.dedup();
            curr_tags.dedup();
            if m_tags != curr_tags {
                DB.add_image(&im.name, &im.tags, im.got_from.as_str(), im.post_url.as_str(), im.rating).unwrap();
                writeln!(&mut outf, "UPDATE tags on {}", im.name).unwrap();
            }
        }
    }
    Ok(())
}

/// Качает картинку, прерываясь, если из консоли поступил kill
fn download(client: &Client, im: &Image) -> Result<(),()> {
    let mut outf = OpenOptions::new().append(true).create(true).open("OUTPUT").unwrap();

    let mut res = client.get(&im.url)
        .header(UserAgent("Zeph/1.0".to_owned()))
        .send().unwrap();
    let mut body = Vec::new();
    res.read_to_end(&mut body).unwrap();

    DB.add_image(&im.name, &im.tags, im.got_from.as_str(), im.post_url.as_str(), im.rating).unwrap();

    save_image(Path::new("assets/images"), &im.name, &body);

    writeln!(&mut outf, "{} DONE", im.name).unwrap();

    Ok(())
}

/// Запросить и распарсить JSON
fn req_and_parse(client: &Client, url: &str) -> Result<Json, hyper::Error> {
    let mut outf = OpenOptions::new().append(true).create(true).open("OUTPUT").unwrap();
    let mut res = match client.get(url)
        .header(UserAgent("Zeph/1.0".to_owned()))
        .send() {
            Ok(x)   => x,
            Err(x)  => {
                writeln!(&mut outf, "ERROR: {}", x).unwrap();
                return Err(x)
            }
        };

    let mut body = String::new();
    res.read_to_string(&mut body).unwrap();

    Ok(Json::from_str(&body).unwrap())
}
<commit_msg>Так выглядит лучше<commit_after>extern crate hyper;
extern crate image;

use self::hyper::client::Client;
use self::hyper::header::UserAgent;

use std::io::{Read,Write};
use std::fs::{File,OpenOptions,read_dir,create_dir};
use std::path::Path;

pub use super::DB;

use rustc_serialize::json::Json;

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

use self::image::FilterType;

#[derive(Debug)]
pub struct Image {
    name: String,
    tags: Vec<String>,
    got_from: String,
    url: String,
    rating: char,
    post_url: String
}

pub mod e621;
pub mod derpy;
pub mod danbooru;
pub mod konachan;

/// Сохраняет картинку & создаёт к ней превью
pub fn save_image(dir: &Path, name: &str, file: &[u8]) {
    if let Err(_) = read_dir("assets/images") {
        create_dir("assets/images").unwrap();
    }
    if let Err(_) = read_dir("assets/images/preview") {
        create_dir("assets/images/preview").unwrap();
    }

    let prev = image::load_from_memory(file).unwrap().resize(500, 500, FilterType::Nearest);

    let mut f = File::create(dir.join(name)).unwrap();
    let mut prevf = File::create(dir.join("preview").join(name)).unwrap();

    f.write(file).unwrap();
    prev.save(&mut prevf, image::JPEG).unwrap();
}

fn process_downloads(client: &Client, images: &[Image], recv: &Receiver<()>) -> Result<(),()> {
    let images_c = DB.get_images(None,0).unwrap();
    let mut outf = OpenOptions::new().append(true).create(true).open("OUTPUT").unwrap();

    for im in images {
        match recv.try_recv() {
            Ok(_) | Err(TryRecvError::Disconnected) => {
                return Err(());
            }
            Err(TryRecvError::Empty) => {}
        }

        if !images_c.iter().any(|x| x.name == im.name ) {
            if im.got_from == "konachan" || im.got_from == "danbooru" {
                download(&Client::new(), im)?;
            } else {
                download(client, im)?;
            }
        } else {
            let mut m_tags = images_c.iter().find(|x| x.name == im.name ).unwrap().tags.clone();
            let mut curr_tags = im.tags.clone();
            m_tags.dedup();
            curr_tags.dedup();
            if m_tags != curr_tags {
                DB.add_image(&im.name, &im.tags, im.got_from.as_str(), im.post_url.as_str(), im.rating).unwrap();
                writeln!(&mut outf, "UPDATE tags on {}", im.name).unwrap();
            }
        }
    }
    Ok(())
}

/// Качает картинку, прерываясь, если из консоли поступил kill
fn download(client: &Client, im: &Image) -> Result<(),()> {
    let mut outf = OpenOptions::new().append(true).create(true).open("OUTPUT").unwrap();

    let mut res = client.get(&im.url)
        .header(UserAgent("Zeph/1.0".to_owned()))
        .send().unwrap();
    let mut body = Vec::new();
    res.read_to_end(&mut body).unwrap();

    DB.add_image(&im.name, &im.tags, im.got_from.as_str(), im.post_url.as_str(), im.rating).unwrap();

    save_image(Path::new("assets/images"), &im.name, &body);

    writeln!(&mut outf, "DONE {}", im.name).unwrap();

    Ok(())
}

/// Запросить и распарсить JSON
fn req_and_parse(client: &Client, url: &str) -> Result<Json, hyper::Error> {
    let mut outf = OpenOptions::new().append(true).create(true).open("OUTPUT").unwrap();
    let mut res = match client.get(url)
        .header(UserAgent("Zeph/1.0".to_owned()))
        .send() {
            Ok(x)   => x,
            Err(x)  => {
                writeln!(&mut outf, "ERROR: {}", x).unwrap();
                return Err(x)
            }
        };

    let mut body = String::new();
    res.read_to_string(&mut body).unwrap();

    Ok(Json::from_str(&body).unwrap())
}
<|endoftext|>


<commit_before>// Copyright (c) 2013-2016 Sandstorm Development Group, Inc. and contributors
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.

use futures::{Future};

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

use stack::Stack;

enum Slot<T> {
    Next(usize),
    Data(T),
}

struct Inner<T, E> {
    // A slab of futures that are being executed. Each slot in this vector is
    // either an active future or a pointer to the next empty slot. This is used
    // to get O(1) deallocation in the slab and O(1) allocation.
    //
    // The `next_future` field is the next slot in the `futures` array that's a
    // `Slot::Next` variant. If it points to the end of the array then the array
    // is full.
    futures: RefCell<Vec<Slot<Box<Future<Item=T, Error=E>>>>>,
    next_future: Cell<usize>,

    new_futures: RefCell<Vec<Box<Future<Item=T, Error=E>>>>,

    stack: Arc<Stack<usize>>,
    reaper: RefCell<Box<TaskReaper<T, E>>>,

    terminate_with: RefCell<Option<Result<(), E>>>,

    handle_count: Cell<usize>,
    task: RefCell<Option<::futures::task::Task>>,
}

#[must_use = "a TaskSet does nothing unless polled"]
pub struct TaskSet<T, E> {
    inner: Rc<Inner<T, E>>,
}

impl<T, E> TaskSet<T, E> where T: 'static, E: 'static {
    pub fn new(reaper: Box<TaskReaper<T, E>>)
               -> (TaskSetHandle<T, E>, TaskSet<T, E>)
        where E: 'static, T: 'static, E: ::std::fmt::Debug,
    {
        let inner = Rc::new(Inner {
            futures: RefCell::new(Vec::new()),
            next_future: Cell::new(0),
            new_futures: RefCell::new(Vec::new()),
            stack: Arc::new(Stack::new()),
            reaper: RefCell::new(reaper),
            terminate_with: RefCell::new(None),
            handle_count: Cell::new(1),
            task: RefCell::new(None),
        });

        let weak_inner = Rc::downgrade(&inner);

        let set = TaskSet {
            inner: inner,
        };

        let handle = TaskSetHandle {
            inner: weak_inner,
        };

        (handle, set)
    }
}

pub struct TaskSetHandle<T, E> {
    inner: Weak<Inner<T, E>>,
}

impl<T, E> Clone for TaskSetHandle<T, E> {
    fn clone(&self) -> TaskSetHandle<T, E> {
        match self.inner.upgrade() {
            None => (),
            Some(inner) => {
                inner.handle_count.set(inner.handle_count.get() + 1);
            }
        }
        TaskSetHandle {
            inner: self.inner.clone()
        }
    }
}

impl <T, E> Drop for TaskSetHandle<T, E> {
    fn drop(&mut self) {
        match self.inner.upgrade() {
            None => (),
            Some(inner) => {
                inner.handle_count.set(inner.handle_count.get() - 1);
            }
        }
    }
}

impl <T, E> TaskSetHandle<T, E> where T: 'static, E: 'static {
    pub fn add<F>(&mut self, promise: F)
        where F: Future<Item=T, Error=E> + 'static
    {
        match self.inner.upgrade() {
            None => (),
            Some(rc_inner) => {
                rc_inner.new_futures.borrow_mut().push(Box::new(promise));

                match rc_inner.task.borrow_mut().take() {
                    Some(t) => t.unpark(),
                    None => (),
                }
            }
        }
    }

    pub fn terminate(&mut self, result: Result<(), E>) {
        match self.inner.upgrade() {
            None => (),
            Some(rc_inner) => {
                *rc_inner.terminate_with.borrow_mut() = Some(result);

                match rc_inner.task.borrow_mut().take() {
                    Some(t) => t.unpark(),
                    None => (),
                }
            }
        }
    }
}

pub trait TaskReaper<T, E> where T: 'static, E: 'static
{
    fn task_succeeded(&mut self, _value: T) {}
    fn task_failed(&mut self, error: E);
}

impl <T, E> Future for TaskSet<T, E> where T: 'static, E: 'static {
    type Item = ();
    type Error = E;

    fn poll(&mut self) -> ::futures::Poll<Self::Item, Self::Error> {

        match self.inner.terminate_with.borrow_mut().take() {
            None => (),
            Some(Ok(v)) => return Ok(::futures::Async::Ready(v)),
            Some(Err(e)) => return Err(e),
        }

        let new_futures = ::std::mem::replace(&mut *self.inner.new_futures.borrow_mut(), Vec::new());
        for future in new_futures {
            let added_idx = self.inner.next_future.get();
            if self.inner.next_future.get() == self.inner.futures.borrow().len() {
                self.inner.futures.borrow_mut().push(Slot::Data(future));
                self.inner.next_future.set(self.inner.next_future.get() + 1);
            } else {
                match ::std::mem::replace(&mut self.inner.futures.borrow_mut()[self.inner.next_future.get()],
                                          Slot::Data(future)) {
                    Slot::Next(next) => self.inner.next_future.set(next),
                    Slot::Data(_) => unreachable!(),
                }
            }

            self.inner.stack.push(added_idx);
        }

        let drain = self.inner.stack.drain();
        for idx in drain {
            match self.inner.futures.borrow_mut()[idx] {
                Slot::Next(_) => unreachable!(),
                Slot::Data(ref mut f) => {
                    let event = ::futures::task::UnparkEvent::new(self.inner.stack.clone(), idx);
                    match ::futures::task::with_unpark_event(event, || f.poll()) {
                        Ok(::futures::Async::NotReady) => continue,
                        Ok(::futures::Async::Ready(v)) => {
                            self.inner.reaper.borrow_mut().task_succeeded(v);
                        }
                        Err(e) => {
                            self.inner.reaper.borrow_mut().task_failed(e);
                        }
                    }
                }
            }
            self.inner.futures.borrow_mut()[idx] = Slot::Next(self.inner.next_future.get());
            self.inner.next_future.set(idx);
        }

        if self.inner.futures.borrow().len() == 0 && self.inner.handle_count.get() == 0 {
            Ok(::futures::Async::Ready(()))
        } else {
            let task = ::futures::task::park();
            if self.inner.new_futures.borrow().len() > 0 {
                // Some new futures got added when we called poll().
                task.unpark();
            }
            *self.inner.task.borrow_mut() = Some(task);
            Ok(::futures::Async::NotReady)
        }
    }
}
<commit_msg>don't panic if a future wakes itself up<commit_after>// Copyright (c) 2013-2016 Sandstorm Development Group, Inc. and contributors
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.

use futures::{Future};

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

use stack::Stack;

enum Slot<T> {
    Next(usize),
    Data(T),
}

struct Inner<T, E> {
    // A slab of futures that are being executed. Each slot in this vector is
    // either an active future or a pointer to the next empty slot. This is used
    // to get O(1) deallocation in the slab and O(1) allocation.
    //
    // The `next_future` field is the next slot in the `futures` array that's a
    // `Slot::Next` variant. If it points to the end of the array then the array
    // is full.
    futures: RefCell<Vec<Slot<Box<Future<Item=T, Error=E>>>>>,
    next_future: Cell<usize>,

    new_futures: RefCell<Vec<Box<Future<Item=T, Error=E>>>>,

    stack: Arc<Stack<usize>>,
    reaper: RefCell<Box<TaskReaper<T, E>>>,

    terminate_with: RefCell<Option<Result<(), E>>>,

    handle_count: Cell<usize>,
    task: RefCell<Option<::futures::task::Task>>,
}

#[must_use = "a TaskSet does nothing unless polled"]
pub struct TaskSet<T, E> {
    inner: Rc<Inner<T, E>>,
}

impl<T, E> TaskSet<T, E> where T: 'static, E: 'static {
    pub fn new(reaper: Box<TaskReaper<T, E>>)
               -> (TaskSetHandle<T, E>, TaskSet<T, E>)
        where E: 'static, T: 'static, E: ::std::fmt::Debug,
    {
        let inner = Rc::new(Inner {
            futures: RefCell::new(Vec::new()),
            next_future: Cell::new(0),
            new_futures: RefCell::new(Vec::new()),
            stack: Arc::new(Stack::new()),
            reaper: RefCell::new(reaper),
            terminate_with: RefCell::new(None),
            handle_count: Cell::new(1),
            task: RefCell::new(None),
        });

        let weak_inner = Rc::downgrade(&inner);

        let set = TaskSet {
            inner: inner,
        };

        let handle = TaskSetHandle {
            inner: weak_inner,
        };

        (handle, set)
    }
}

pub struct TaskSetHandle<T, E> {
    inner: Weak<Inner<T, E>>,
}

impl<T, E> Clone for TaskSetHandle<T, E> {
    fn clone(&self) -> TaskSetHandle<T, E> {
        match self.inner.upgrade() {
            None => (),
            Some(inner) => {
                inner.handle_count.set(inner.handle_count.get() + 1);
            }
        }
        TaskSetHandle {
            inner: self.inner.clone()
        }
    }
}

impl <T, E> Drop for TaskSetHandle<T, E> {
    fn drop(&mut self) {
        match self.inner.upgrade() {
            None => (),
            Some(inner) => {
                inner.handle_count.set(inner.handle_count.get() - 1);
            }
        }
    }
}

impl <T, E> TaskSetHandle<T, E> where T: 'static, E: 'static {
    pub fn add<F>(&mut self, promise: F)
        where F: Future<Item=T, Error=E> + 'static
    {
        match self.inner.upgrade() {
            None => (),
            Some(rc_inner) => {
                rc_inner.new_futures.borrow_mut().push(Box::new(promise));

                match rc_inner.task.borrow_mut().take() {
                    Some(t) => t.unpark(),
                    None => (),
                }
            }
        }
    }

    pub fn terminate(&mut self, result: Result<(), E>) {
        match self.inner.upgrade() {
            None => (),
            Some(rc_inner) => {
                *rc_inner.terminate_with.borrow_mut() = Some(result);

                match rc_inner.task.borrow_mut().take() {
                    Some(t) => t.unpark(),
                    None => (),
                }
            }
        }
    }
}

pub trait TaskReaper<T, E> where T: 'static, E: 'static
{
    fn task_succeeded(&mut self, _value: T) {}
    fn task_failed(&mut self, error: E);
}

impl <T, E> Future for TaskSet<T, E> where T: 'static, E: 'static {
    type Item = ();
    type Error = E;

    fn poll(&mut self) -> ::futures::Poll<Self::Item, Self::Error> {

        match self.inner.terminate_with.borrow_mut().take() {
            None => (),
            Some(Ok(v)) => return Ok(::futures::Async::Ready(v)),
            Some(Err(e)) => return Err(e),
        }

        let new_futures = ::std::mem::replace(&mut *self.inner.new_futures.borrow_mut(), Vec::new());
        for future in new_futures {
            let added_idx = self.inner.next_future.get();
            if self.inner.next_future.get() == self.inner.futures.borrow().len() {
                self.inner.futures.borrow_mut().push(Slot::Data(future));
                self.inner.next_future.set(self.inner.next_future.get() + 1);
            } else {
                match ::std::mem::replace(&mut self.inner.futures.borrow_mut()[self.inner.next_future.get()],
                                          Slot::Data(future)) {
                    Slot::Next(next) => self.inner.next_future.set(next),
                    Slot::Data(_) => unreachable!(),
                }
            }

            self.inner.stack.push(added_idx);
        }

        let drain = self.inner.stack.drain();
        for idx in drain {
            match self.inner.futures.borrow_mut()[idx] {
                Slot::Next(_) => continue,
                Slot::Data(ref mut f) => {
                    let event = ::futures::task::UnparkEvent::new(self.inner.stack.clone(), idx);
                    match ::futures::task::with_unpark_event(event, || f.poll()) {
                        Ok(::futures::Async::NotReady) => continue,
                        Ok(::futures::Async::Ready(v)) => {
                            self.inner.reaper.borrow_mut().task_succeeded(v);
                        }
                        Err(e) => {
                            self.inner.reaper.borrow_mut().task_failed(e);
                        }
                    }
                }
            }
            self.inner.futures.borrow_mut()[idx] = Slot::Next(self.inner.next_future.get());
            self.inner.next_future.set(idx);
        }

        if self.inner.futures.borrow().len() == 0 && self.inner.handle_count.get() == 0 {
            Ok(::futures::Async::Ready(()))
        } else {
            let task = ::futures::task::park();
            if self.inner.new_futures.borrow().len() > 0 {
                // Some new futures got added when we called poll().
                task.unpark();
            }
            *self.inner.task.borrow_mut() = Some(task);
            Ok(::futures::Async::NotReady)
        }
    }
}
<|endoftext|>


<commit_before>use std::str;

use sexpr::Sexpr;
use module::{Module, ModuleBuilder, MemoryInfo};

macro_rules! vec_form {
    ($val:expr => () => $code:expr) => {{
        if $val.len() == 0 {
            Some($code)
        } else {
            None
        }
    }};
    ($val:expr => (*$rest:ident) => $code:expr) => {{
        let $rest = &$val[..];
        Some($code)
    }};
    ($val:expr => (ident:&$ident:ident $($parts:tt)*) => $code:expr) => {{
        if $val.len() > 0 {
            if let &Sexpr::Identifier(ref name) = &$val[0] {
                let $ident = &$val[0];
                vec_form!($val[1..] => ($($parts)*) => $code)
            } else {
                None
            }
        } else {
            None
        }
    }};
    ($val:expr => (&$ident:ident $($parts:tt)*) => $code:expr) => {{
        if $val.len() > 0 {
            let $ident = &$val[0];

            vec_form!($val[1..] => ($($parts)*) => $code)
        } else {
            None
        }
    }};
    ($val:expr => ($ident:ident $($parts:tt)*) => $code:expr) => {{
        if $val.len() > 0 {
            if let &Sexpr::Identifier(ref name) = &$val[0] {
                if name == stringify!($ident) {
                    vec_form!($val[1..] => ($($parts)*) => $code)
                } else {
                    None
                }
            } else {
                None
            }
        } else {
            None
        }
    }};
}

macro_rules! sexpr_match {
    ($val:expr;) => {{ None }};
    ($val:expr; _ => $code:expr) => {{ Some($code) }};
    ($val:expr; $sexpr:tt => $code:expr; $($sexpr_rest:tt => $code_rest:expr);*) => {{
        let val = $val;
        let res = if let &Sexpr::List(ref items) = val {
            vec_form!(items => $sexpr => $code)
        } else {
            None
        };
        if let None = res {
            sexpr_match!(val; $($sexpr_rest => $code_rest);*)
        } else {
            res
        }
    }};
}

pub struct TestCase {

}

impl TestCase {
    pub fn parse(bytes: &[u8]) -> TestCase {
        let text = str::from_utf8(bytes).unwrap();
        let exprs = Sexpr::parse(text);

        for s in &exprs {
            sexpr_match!(s;
                (module *it) => {
                    let mut m = ModuleBuilder::new();

                    for s in it {
                        sexpr_match!(s;
                            (func) => {};
                            (func &name *it) => {
                                for s in it {
                                    sexpr_match!(s;
                                        (param &id &ty) => {
                                            println!("found param!");
                                        };
                                        (result &ty) => {
                                            println!("found result!");
                                        };
                                        (local &id &ty) => {
                                            println!("found local!");
                                        };
                                        _ => {
                                            parse_instr(s);
                                        }
                                    );
                                }
                            };
                            (export &name &id) => {
                                // println!("found export!");
                            };
                            (import &module &name &ty) => {
                                // println!("found import!");
                            };
                            (import &id &module &name &ty) => {
                                // println!("found import!");
                            };
                            (type &id &ty) => {
                                // println!("found type!");
                            };
                            (type &ty) => {
                                // println!("found type!");
                            };
                            (memory *args) => {
                                // m.memory_info.initial_64k_pages = parse_int(initial);
                                // m.memory_info.maximum_64k_pages = parse_int(max);
                                //
                                // assert!(m.memory_info.maximum_64k_pages >= m.memory_info.initial_64k_pages);
                                //
                                // for s in segments {
                                //     sexpr_match!(s;
                                //         (segment &offset &data) => {
                                //             m.memory_chunks.push(MemoryChunk {
                                //                 offset: parse_int(offset),
                                //                 data: parse_bin_string(data),
                                //             })
                                //         };
                                //         _ => panic!("a")
                                //     );
                                // }
                            };
                            (table *items) => {
                                // println!("found table!");
                            };
                            (start &id) => {
                                // println!("found start!");
                            };
                            _ => {
                                panic!("unhandled inner: {}", s);
                            }
                        );
                    }
                };
                (assert_invalid &module &text) => {
                    // println!("found assert_invalid");
                };
                (assert_return &module) => {
                    // println!("found assert_return (no text)");
                };
                (assert_return &module &text) => {
                    // println!("found assert_return (text)");
                };
                (assert_return_nan &module) => {
                    // println!("found assert_return_nan");
                };
                (assert_trap &module &text) => {
                    // println!("found assert_trap");
                };
                (invoke &ident *args) => {
                    // println!("found invoke");
                };
                _ => {
                    panic!("unhandled: {}", s);
                }
            );
        }

        TestCase {
        }
    }

    pub fn run_all(&self) {

    }
}

fn parse_instr(s: &Sexpr) {
    sexpr_match!(s;
        (&instr *args) => {
        };
        _ => panic!("unexpected instr: {}", s)
    );
}

fn parse_int(node: &Sexpr) -> usize {
    match node {
        &Sexpr::Identifier(ref text) => {
            str::parse(text).unwrap()
        }
        _ => panic!("expected number id: {}", node)
    }
}

fn parse_bin_string(node: &Sexpr) -> Vec<u8> {
    match node {
        &Sexpr::String(ref text) => {
            let text = text.as_bytes();
            let mut res = Vec::new();

            assert!(text[0] == b'"');

            let mut pos = 1;

            while pos < text.len() {
                match text[pos] {
                    b'\\' => {
                        assert!(pos + 2 < text.len());
                        res.push(u8::from_str_radix(str::from_utf8(&text[pos + 1..pos + 2]).unwrap(), 16).unwrap());
                    }
                    b'"' => break,
                    ch => res.push(ch)
                }
                pos += 1;
            }

            res
        }
        _ => panic!()
    }
}
<commit_msg>begin parsing wast instructions<commit_after>use std::str;
use std::collections::HashMap;

use sexpr::Sexpr;
use module::{Module, ModuleBuilder, MemoryInfo};
use types::Type;
use ops::NormalOp;

macro_rules! vec_form {
    ($val:expr => () => $code:expr) => {{
        if $val.len() == 0 {
            Some($code)
        } else {
            None
        }
    }};
    ($val:expr => (*$rest:ident) => $code:expr) => {{
        let $rest = &$val[..];
        Some($code)
    }};
    ($val:expr => (ident:&$ident:ident $($parts:tt)*) => $code:expr) => {{
        if $val.len() > 0 {
            if let &Sexpr::Identifier(ref $ident) = &$val[0] {
                vec_form!($val[1..] => ($($parts)*) => $code)
            } else {
                None
            }
        } else {
            None
        }
    }};
    ($val:expr => (&$ident:ident $($parts:tt)*) => $code:expr) => {{
        if $val.len() > 0 {
            let $ident = &$val[0];

            vec_form!($val[1..] => ($($parts)*) => $code)
        } else {
            None
        }
    }};
    ($val:expr => ($ident:ident $($parts:tt)*) => $code:expr) => {{
        if $val.len() > 0 {
            if let &Sexpr::Identifier(ref name) = &$val[0] {
                if name == stringify!($ident) {
                    vec_form!($val[1..] => ($($parts)*) => $code)
                } else {
                    None
                }
            } else {
                None
            }
        } else {
            None
        }
    }};
}

macro_rules! sexpr_match {
    ($val:expr;) => {{ None }};
    ($val:expr; _ => $code:expr) => {{ Some($code) }};
    ($val:expr; $sexpr:tt => $code:expr; $($sexpr_rest:tt => $code_rest:expr);*) => {{
        let val = $val;
        let res = if let &Sexpr::List(ref items) = val {
            vec_form!(items => $sexpr => $code)
        } else {
            None
        };
        if let None = res {
            sexpr_match!(val; $($sexpr_rest => $code_rest);*)
        } else {
            res
        }
    }};
}

pub struct TestCase {

}

fn parse_type(text: &str) -> Type {
    match text {
        "i32" => Type::Int32,
        "i64" => Type::Int64,
        "f32" => Type::Float32,
        "f64" => Type::Float64,
        _ => panic!()
    }
}

impl TestCase {
    pub fn parse(bytes: &[u8]) -> TestCase {
        let text = str::from_utf8(bytes).unwrap();
        let exprs = Sexpr::parse(text);

        for s in &exprs {
            sexpr_match!(s;
                (module *it) => {
                    let mut m = ModuleBuilder::new();

                    let mut function_names = HashMap::new();
                    let mut functions = Vec::new();

                    for s in it {
                        sexpr_match!(s;
                            (func *it) => {
                                let mut it = it.iter();

                                let name = if let Some(&Sexpr::Variable(ref v)) = it.next() {
                                    Some(v)
                                } else {
                                    None
                                };

                                let mut param_types = Vec::new();

                                let mut param_names = HashMap::new();

                                let mut result_type = None;

                                let mut local_types = Vec::new();
                                let mut local_names = HashMap::new();

                                let mut ops = Vec::new();

                                while let Some(s) = it.next() {
                                    sexpr_match!(s;
                                        (param &id &ty) => {
                                            if let &Sexpr::Variable(ref v) = id {
                                                param_names.insert(v, param_types.len());
                                            } else {
                                                panic!();
                                            }
                                            if let &Sexpr::Identifier(ref v) = ty {
                                                param_types.push(parse_type(v.as_str()));
                                            } else {
                                                panic!();
                                            }
                                        };
                                        (result &ty) => {
                                            if let &Sexpr::Identifier(ref v) = ty {
                                                result_type = Some(parse_type(v.as_str()));
                                            } else {
                                                panic!();
                                            }
                                        };
                                        (local &id &ty) => {
                                            if let &Sexpr::Variable(ref v) = id {
                                                local_names.insert(v, local_types.len());
                                            } else {
                                                panic!();
                                            }
                                            if let &Sexpr::Identifier(ref v) = ty {
                                                local_types.push(parse_type(v.as_str()));
                                            } else {
                                                panic!();
                                            }
                                        };
                                        _ => {
                                            ops.push(parse_op(s));
                                        }
                                    );
                                }

                                if let Some(name) = name {
                                    function_names.insert(name, functions.len());
                                }

                                functions.push(0);
                            };
                            (export &name &id) => {
                                // println!("found export!");
                            };
                            (import &module &name &ty) => {
                                // println!("found import!");
                            };
                            (import &id &module &name &ty) => {
                                // println!("found import!");
                            };
                            (type &id &ty) => {
                                // println!("found type!");
                            };
                            (type &ty) => {
                                // println!("found type!");
                            };
                            (memory *args) => {
                                // m.memory_info.initial_64k_pages = parse_int(initial);
                                // m.memory_info.maximum_64k_pages = parse_int(max);
                                //
                                // assert!(m.memory_info.maximum_64k_pages >= m.memory_info.initial_64k_pages);
                                //
                                // for s in segments {
                                //     sexpr_match!(s;
                                //         (segment &offset &data) => {
                                //             m.memory_chunks.push(MemoryChunk {
                                //                 offset: parse_int(offset),
                                //                 data: parse_bin_string(data),
                                //             })
                                //         };
                                //         _ => panic!("a")
                                //     );
                                // }
                            };
                            (table *items) => {
                                // println!("found table!");
                            };
                            (start &id) => {
                                // println!("found start!");
                            };
                            _ => {
                                panic!("unhandled inner: {}", s);
                            }
                        );
                    }
                };
                (assert_invalid &module &text) => {
                    // println!("found assert_invalid");
                };
                (assert_return &module) => {
                    // println!("found assert_return (no text)");
                };
                (assert_return &module &text) => {
                    // println!("found assert_return (text)");
                };
                (assert_return_nan &module) => {
                    // println!("found assert_return_nan");
                };
                (assert_trap &module &text) => {
                    // println!("found assert_trap");
                };
                (invoke &ident *args) => {
                    // println!("found invoke");
                };
                _ => {
                    panic!("unhandled: {}", s);
                }
            );
        }

        TestCase {
        }
    }

    pub fn run_all(&self) {

    }
}

fn parse_op(s: &Sexpr) -> NormalOp {
    sexpr_match!(s;
        (ident:&op *args) => {
            return match op.as_str() {
                "nop" => NormalOp::Nop,
                "block" => NormalOp::Nop,
                "loop" => NormalOp::Nop,
                "if" => NormalOp::Nop,
                "else" => NormalOp::Nop,
                "select" => NormalOp::Nop,
                "br" => NormalOp::Nop,
                "brif" => NormalOp::Nop,
                "brtable" => NormalOp::Nop,
                "return" => NormalOp::Nop,
                "unreachable" => NormalOp::Nop,
                "drop" => NormalOp::Nop,
                "end" => NormalOp::Nop,
                "i32.const" => NormalOp::Nop,
                "i64.const" => NormalOp::Nop,
                "f64.const" => NormalOp::Nop,
                "f32.const" => NormalOp::Nop,
                "get_local" => NormalOp::Nop,
                "set_local" => NormalOp::Nop,
                "tee_local" => NormalOp::Nop,
                "call" => NormalOp::Nop,
                "callindirect" => NormalOp::Nop,
                "callimport" => NormalOp::Nop,
                "i32.load8s" => NormalOp::Nop,
                "i32.load8u" => NormalOp::Nop,
                "i32.load16s" => NormalOp::Nop,
                "i32.load16u" => NormalOp::Nop,
                "i64.load8s" => NormalOp::Nop,
                "i64.load8u" => NormalOp::Nop,
                "i64.load16s" => NormalOp::Nop,
                "i64.load16u" => NormalOp::Nop,
                "i64.load32s" => NormalOp::Nop,
                "i64.load32u" => NormalOp::Nop,
                "i32.load" => NormalOp::Nop,
                "i64.load" => NormalOp::Nop,
                "f32.load" => NormalOp::Nop,
                "f64.load" => NormalOp::Nop,
                "i32.store8" => NormalOp::Nop,
                "i32.store16" => NormalOp::Nop,
                "i64.store8" => NormalOp::Nop,
                "i64.store16" => NormalOp::Nop,
                "i64.store32" => NormalOp::Nop,
                "i32.store" => NormalOp::Nop,
                "i64.store" => NormalOp::Nop,
                "f32.store" => NormalOp::Nop,
                "f64.store" => NormalOp::Nop,
                "current_memory" => NormalOp::Nop,
                "grow_memory" => NormalOp::Nop,
                "i32.add" => NormalOp::Nop,
                "i32.sub" => NormalOp::Nop,
                "i32.mul" => NormalOp::Nop,
                "i32.div_s" => NormalOp::Nop,
                "i32.div_u" => NormalOp::Nop,
                "i32.rem_s" => NormalOp::Nop,
                "i32.rem_u" => NormalOp::Nop,
                "i32.and" => NormalOp::Nop,
                "i32.or" => NormalOp::Nop,
                "i32.xor" => NormalOp::Nop,
                "i32.shl" => NormalOp::Nop,
                "i32.shr_u" => NormalOp::Nop,
                "i32.shr_s" => NormalOp::Nop,
                "i32.rotr" => NormalOp::Nop,
                "i32.rotl" => NormalOp::Nop,
                "i32.eq" => NormalOp::Nop,
                "i32.ne" => NormalOp::Nop,
                "i32.lt_s" => NormalOp::Nop,
                "i32.le_s" => NormalOp::Nop,
                "i32.lt_u" => NormalOp::Nop,
                "i32.le_u" => NormalOp::Nop,
                "i32.gt_s" => NormalOp::Nop,
                "i32.ge_s" => NormalOp::Nop,
                "i32.gt_u" => NormalOp::Nop,
                "i32.ge_u" => NormalOp::Nop,
                "i32.clz" => NormalOp::Nop,
                "i32.ctz" => NormalOp::Nop,
                "i32.popcnt" => NormalOp::Nop,
                "i32.eqz" => NormalOp::Nop,
                "i64.add" => NormalOp::Nop,
                "i64.sub" => NormalOp::Nop,
                "i64.mul" => NormalOp::Nop,
                "i64.divs" => NormalOp::Nop,
                "i64.divu" => NormalOp::Nop,
                "i64.rems" => NormalOp::Nop,
                "i64.remu" => NormalOp::Nop,
                "i64.and" => NormalOp::Nop,
                "i64.or" => NormalOp::Nop,
                "i64.xor" => NormalOp::Nop,
                "i64.shl" => NormalOp::Nop,
                "i64.shru" => NormalOp::Nop,
                "i64.shrs" => NormalOp::Nop,
                "i64.rotr" => NormalOp::Nop,
                "i64.rotl" => NormalOp::Nop,
                "i64.eq" => NormalOp::Nop,
                "i64.ne" => NormalOp::Nop,
                "i64.lts" => NormalOp::Nop,
                "i64.les" => NormalOp::Nop,
                "i64.ltu" => NormalOp::Nop,
                "i64.leu" => NormalOp::Nop,
                "i64.gts" => NormalOp::Nop,
                "i64.ges" => NormalOp::Nop,
                "i64.gtu" => NormalOp::Nop,
                "i64.geu" => NormalOp::Nop,
                "i64.clz" => NormalOp::Nop,
                "i64.ctz" => NormalOp::Nop,
                "i64.popcnt" => NormalOp::Nop,
                "i64.eqz" => NormalOp::Nop,
                "f32.add" => NormalOp::Nop,
                "f32.sub" => NormalOp::Nop,
                "f32.mul" => NormalOp::Nop,
                "f32.div" => NormalOp::Nop,
                "f32.min" => NormalOp::Nop,
                "f32.max" => NormalOp::Nop,
                "f32.abs" => NormalOp::Nop,
                "f32.neg" => NormalOp::Nop,
                "f32.copysign" => NormalOp::Nop,
                "f32.ceil" => NormalOp::Nop,
                "f32.floor" => NormalOp::Nop,
                "f32.trunc" => NormalOp::Nop,
                "f32.nearest" => NormalOp::Nop,
                "f32.sqrt" => NormalOp::Nop,
                "f32.eq" => NormalOp::Nop,
                "f32.ne" => NormalOp::Nop,
                "f32.lt" => NormalOp::Nop,
                "f32.le" => NormalOp::Nop,
                "f32.gt" => NormalOp::Nop,
                "f32.ge" => NormalOp::Nop,
                "f64.add" => NormalOp::Nop,
                "f64.sub" => NormalOp::Nop,
                "f64.mul" => NormalOp::Nop,
                "f64.div" => NormalOp::Nop,
                "f64.min" => NormalOp::Nop,
                "f64.max" => NormalOp::Nop,
                "f64.abs" => NormalOp::Nop,
                "f64.neg" => NormalOp::Nop,
                "f64.copysign" => NormalOp::Nop,
                "f64.ceil" => NormalOp::Nop,
                "f64.floor" => NormalOp::Nop,
                "f64.trunc" => NormalOp::Nop,
                "f64.nearest" => NormalOp::Nop,
                "f64.sqrt" => NormalOp::Nop,
                "f64.eq" => NormalOp::Nop,
                "f64.ne" => NormalOp::Nop,
                "f64.lt" => NormalOp::Nop,
                "f64.le" => NormalOp::Nop,
                "f64.gt" => NormalOp::Nop,
                "f64.ge" => NormalOp::Nop,
                "i32.trunc_s/f32" => NormalOp::Nop,
                "i32.trunc_s/f64" => NormalOp::Nop,
                "i32.trunc_u/f32" => NormalOp::Nop,
                "i32.trunc_u/f64" => NormalOp::Nop,
                "i32.wrap/i64" => NormalOp::Nop,
                "i64.trunc_s/f32" => NormalOp::Nop,
                "i64.trunc_s/f64" => NormalOp::Nop,
                "i64.trunc_u/f32" => NormalOp::Nop,
                "i64.trunc_u/f64" => NormalOp::Nop,
                "i64.extend_s/i32" => NormalOp::Nop,
                "i64.extend_u/i32" => NormalOp::Nop,
                "f32.convert_s/i32" => NormalOp::Nop,
                "f32.convert_u/i32" => NormalOp::Nop,
                "f32.convert_s/i64" => NormalOp::Nop,
                "f32.convert_u/i64" => NormalOp::Nop,
                "f32.demote/f64" => NormalOp::Nop,
                "f32.reinterpret/i32" => NormalOp::Nop,
                "f64.convert_s/i32" => NormalOp::Nop,
                "f64.convert_u/i32" => NormalOp::Nop,
                "f64.convert_s/i64" => NormalOp::Nop,
                "f64.convert_u/i64" => NormalOp::Nop,
                "f64.promote/f32" => NormalOp::Nop,
                "f64.reinterpret/i64" => NormalOp::Nop,
                "i32.reinterpret/f32" => NormalOp::Nop,
                "i64.reinterpret/f64" => NormalOp::Nop,
                _ => panic!("unexpected instr: {}", op)
            };
        };
        _ => panic!("unexpected instr: {}", s)
    );
    panic!();
}

fn parse_int(node: &Sexpr) -> usize {
    match node {
        &Sexpr::Identifier(ref text) => {
            str::parse(text).unwrap()
        }
        _ => panic!("expected number id: {}", node)
    }
}

fn parse_bin_string(node: &Sexpr) -> Vec<u8> {
    match node {
        &Sexpr::String(ref text) => {
            let text = text.as_bytes();
            let mut res = Vec::new();

            assert!(text[0] == b'"');

            let mut pos = 1;

            while pos < text.len() {
                match text[pos] {
                    b'\\' => {
                        assert!(pos + 2 < text.len());
                        res.push(u8::from_str_radix(str::from_utf8(&text[pos + 1..pos + 2]).unwrap(), 16).unwrap());
                    }
                    b'"' => break,
                    ch => res.push(ch)
                }
                pos += 1;
            }

            res
        }
        _ => panic!()
    }
}
<|endoftext|>


<commit_before>use super::raw;
use std::fmt;
use std::kinds::marker::InvariantLifetime;

pub struct Storage<'d> {
    storage: &'d raw::Storage,
}

impl<'d> Storage<'d> {
    pub fn new(storage: &raw::Storage) -> Storage {
        Storage {
            storage: storage,
        }
    }

    pub fn create_element(&'d self, name: &str) -> Element<'d> {
        Element::wrap(self.storage.create_element(name))
    }

    pub fn create_attribute(&'d self, name: &str, value: &str) -> Attribute<'d> {
        Attribute::wrap(self.storage.create_attribute(name, value))
    }

    pub fn element_set_name(&self, element: &Element, name: &str) {
        self.storage.element_set_name(element.node, name)
    }
}

pub struct Connections<'d> {
    connections: &'d raw::Connections,
}

impl<'d> Connections<'d> {
    pub fn new(connections: &raw::Connections) -> Connections {
        Connections {
            connections: connections,
        }
    }

    pub fn element_parent(&self, child: Element<'d>) -> Option<ParentOfChild<'d>> {
        self.connections.element_parent(child.node).map(|n| {
            match n {
                raw::ElementPOC(n) => ElementPOC(Element::wrap(n)),
            }
        })
    }

    pub fn append_element_child(&mut self, parent: Element<'d>, child: Element<'d>) {
        self.connections.append_element_child(parent.node, child.node)
    }

    pub fn element_children(&self, parent: Element<'d>) -> ElementChildren<'d> {
        // This is safe because we disallow mutation while this borrow is active.
        // TODO: Test that
        unsafe { ElementChildren { x: self.connections.element_children(parent.node), idx: 0 } }
    }

    pub fn attribute_parent(&self, attribute: Attribute<'d>) -> Option<Element<'d>> {
        self.connections.attribute_parent(attribute.node).map(|a| Element::wrap(a))
    }

    pub fn attributes(&self, parent: Element<'d>) -> Attributes<'d> {
        // This is safe because we disallow mutation while this borrow is active
        // TODO: Test that
        unsafe { Attributes { x: self.connections.attributes(parent.node), idx: 0 } }
    }

    pub fn set_attribute(&mut self, parent: Element<'d>, attribute: Attribute<'d>) {
        self.connections.set_attribute(parent.node, attribute.node);
    }

    pub fn attribute_value(&self, parent: Element<'d>, name: &str) -> Option<&'d str> {
        self.connections.attribute(parent.node, name).map(|a| {
            let a_r = unsafe { &*a };
            a_r.value()
        })
    }
}

pub struct ElementChildren<'d> {
    x: &'d [raw::ChildOfElement],
    idx: uint,
}

impl<'d> Iterator<ChildOfElement<'d>> for ElementChildren<'d> {
    fn next(&mut self) -> Option<ChildOfElement<'d>> {
        if self.idx >= self.x.len() {
            None
        } else {
            let e = Element {
                lifetime: InvariantLifetime,
                node: match self.x[self.idx] {
                    raw::ElementCOE(n) => n
                },
            };
            self.idx += 1;
            Some(ElementCOE(e))
        }
    }
}

pub struct Attributes<'d> {
    x: &'d [*mut raw::Attribute],
    idx: uint,
}

impl<'d> Iterator<Attribute<'d>> for Attributes<'d> {
    fn next(&mut self) -> Option<Attribute<'d>> {
        if self.idx >= self.x.len() {
            None
        } else {
            let a = Attribute::wrap(self.x[self.idx]);
            self.idx += 1;
            Some(a)
        }
    }
}

macro_rules! node(
    ($name:ident, $raw:ty) => (
        pub struct $name<'d> {
            lifetime: InvariantLifetime<'d>,
            node: *mut $raw,
        }

        impl<'d> $name<'d> {
            fn wrap(node: *mut $raw) -> $name<'d> {
                $name {
                    lifetime: InvariantLifetime,
                    node: node,
                }
            }

            fn node(&self) -> &'d $raw { unsafe { &*self.node } }
        }
    )
)

node!(Element, raw::Element)

impl<'d> Element<'d> {
    pub fn name(&self) -> &'d str { self.node().name() }
}

impl<'d> PartialEq for Element<'d> {
    fn eq(&self, other: &Element<'d>) -> bool {
        self.node == other.node
    }
}

impl<'d> fmt::Show for Element<'d> {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        let node = unsafe { &* self.node };
        write!(f, "Element {{ name: {}  }}", node.name())
    }
}

node!(Attribute, raw::Attribute)

impl<'d> Attribute<'d> {
    pub fn name(&self)  -> &str { self.node().name() }
    pub fn value(&self) -> &str { self.node().value() }
}

#[deriving(PartialEq,Show)]
pub enum ChildOfElement<'d> {
    ElementCOE(Element<'d>),
}

impl<'d> ChildOfElement<'d> {
    pub fn element(self) -> Option<Element<'d>> {
        match self {
            ElementCOE(n) => Some(n)
        }
    }
}

#[deriving(PartialEq,Show)]
pub enum ParentOfChild<'d> {
    ElementPOC(Element<'d>),
}

impl<'d> ParentOfChild<'d> {
    pub fn element(self) -> Option<Element<'d>> {
        match self {
            ElementPOC(n) => Some(n)
        }
    }
}

#[cfg(test)]
mod test {
    use super::super::Package;
    use super::{ChildOfElement,ElementCOE};
    use super::{ElementPOC};
    use super::Attribute;

    #[test]
    fn elements_can_have_element_children() {
        let package = Package::new();
        let (s, mut c) = package.as_thin_document();

        let alpha = s.create_element("alpha");
        let beta  = s.create_element("beta");

        c.append_element_child(alpha, beta);

        let children: Vec<ChildOfElement> = c.element_children(alpha).collect();

        assert_eq!(children[0], ElementCOE(beta));
    }

    #[test]
    fn element_children_are_ordered() {
        let package = Package::new();
        let (s, mut c) = package.as_thin_document();

        let greek = s.create_element("greek");
        let alpha = s.create_element("alpha");
        let omega = s.create_element("omega");

        c.append_element_child(greek, alpha);
        c.append_element_child(greek, omega);

        let children: Vec<ChildOfElement> = c.element_children(greek).collect();

        assert_eq!(children[0], ElementCOE(alpha));
        assert_eq!(children[1], ElementCOE(omega));
    }

    #[test]
    fn element_children_know_their_parent() {
        let package = Package::new();
        let (s, mut c) = package.as_thin_document();

        let alpha = s.create_element("alpha");
        let beta  = s.create_element("beta");

        c.append_element_child(alpha, beta);

        assert_eq!(Some(ElementPOC(alpha)), c.element_parent(beta));
    }

    #[test]
    fn changing_parent_of_element_removes_element_from_original_parent() {
        let package = Package::new();
        let (s, mut c) = package.as_thin_document();

        let parent1 = s.create_element("parent1");
        let parent2 = s.create_element("parent2");
        let child = s.create_element("child");

        c.append_element_child(parent1, child);
        c.append_element_child(parent2, child);

        assert_eq!(0, c.element_children(parent1).count());
        assert_eq!(1, c.element_children(parent2).count());
    }

    #[test]
    fn elements_can_be_renamed() {
        let package = Package::new();
        let (s, _) = package.as_thin_document();

        let alpha = s.create_element("alpha");
        s.element_set_name(&alpha, "beta");
        assert_eq!(alpha.name(), "beta");
    }

    #[test]
    fn elements_have_attributes() {
        let package = Package::new();
        let (s, mut c) = package.as_thin_document();

        let element = s.create_element("element");
        let attr = s.create_attribute("hello", "world");
        c.set_attribute(element, attr);

        assert_eq!(Some("world"), c.attribute_value(element, "hello"));
    }

    #[test]
    fn attributes_know_their_element() {
        let package = Package::new();
        let (s, mut c) = package.as_thin_document();

        let element = s.create_element("element");
        let attr = s.create_attribute("hello", "world");
        c.set_attribute(element, attr);

        assert_eq!(Some(element), c.attribute_parent(attr));
    }

    #[test]
    fn attributes_can_be_reset() {
        let package = Package::new();
        let (s, mut c) = package.as_thin_document();

        let element = s.create_element("element");

        let attr1 = s.create_attribute("hello", "world");
        let attr2 = s.create_attribute("hello", "galaxy");

        c.set_attribute(element, attr1);
        c.set_attribute(element, attr2);

        assert_eq!(Some("galaxy"), c.attribute_value(element, "hello"));
    }

    #[test]
    fn attributes_can_be_iterated() {
        let package = Package::new();
        let (s, mut c) = package.as_thin_document();

        let element = s.create_element("element");

        let attr1 = s.create_attribute("name1", "value1");
        let attr2 = s.create_attribute("name2", "value2");

        c.set_attribute(element, attr1);
        c.set_attribute(element, attr2);

        let mut attrs: Vec<Attribute> = c.attributes(element).collect();
        attrs.sort_by(|a, b| a.name().cmp(b.name()));

        assert_eq!(2, attrs.len());
        assert_eq!("name1",  attrs[0].name());
        assert_eq!("value1", attrs[0].value());
        assert_eq!("name2",  attrs[1].name());
        assert_eq!("value2", attrs[1].value());
    }
}
<commit_msg>All thin DOM nodes delegate equality to the raw layer<commit_after>use super::raw;
use std::fmt;
use std::kinds::marker::InvariantLifetime;

pub struct Storage<'d> {
    storage: &'d raw::Storage,
}

impl<'d> Storage<'d> {
    pub fn new(storage: &raw::Storage) -> Storage {
        Storage {
            storage: storage,
        }
    }

    pub fn create_element(&'d self, name: &str) -> Element<'d> {
        Element::wrap(self.storage.create_element(name))
    }

    pub fn create_attribute(&'d self, name: &str, value: &str) -> Attribute<'d> {
        Attribute::wrap(self.storage.create_attribute(name, value))
    }

    pub fn element_set_name(&self, element: &Element, name: &str) {
        self.storage.element_set_name(element.node, name)
    }
}

pub struct Connections<'d> {
    connections: &'d raw::Connections,
}

impl<'d> Connections<'d> {
    pub fn new(connections: &raw::Connections) -> Connections {
        Connections {
            connections: connections,
        }
    }

    pub fn element_parent(&self, child: Element<'d>) -> Option<ParentOfChild<'d>> {
        self.connections.element_parent(child.node).map(|n| {
            match n {
                raw::ElementPOC(n) => ElementPOC(Element::wrap(n)),
            }
        })
    }

    pub fn append_element_child(&mut self, parent: Element<'d>, child: Element<'d>) {
        self.connections.append_element_child(parent.node, child.node)
    }

    pub fn element_children(&self, parent: Element<'d>) -> ElementChildren<'d> {
        // This is safe because we disallow mutation while this borrow is active.
        // TODO: Test that
        unsafe { ElementChildren { x: self.connections.element_children(parent.node), idx: 0 } }
    }

    pub fn attribute_parent(&self, attribute: Attribute<'d>) -> Option<Element<'d>> {
        self.connections.attribute_parent(attribute.node).map(|a| Element::wrap(a))
    }

    pub fn attributes(&self, parent: Element<'d>) -> Attributes<'d> {
        // This is safe because we disallow mutation while this borrow is active
        // TODO: Test that
        unsafe { Attributes { x: self.connections.attributes(parent.node), idx: 0 } }
    }

    pub fn set_attribute(&mut self, parent: Element<'d>, attribute: Attribute<'d>) {
        self.connections.set_attribute(parent.node, attribute.node);
    }

    pub fn attribute_value(&self, parent: Element<'d>, name: &str) -> Option<&'d str> {
        self.connections.attribute(parent.node, name).map(|a| {
            let a_r = unsafe { &*a };
            a_r.value()
        })
    }
}

pub struct ElementChildren<'d> {
    x: &'d [raw::ChildOfElement],
    idx: uint,
}

impl<'d> Iterator<ChildOfElement<'d>> for ElementChildren<'d> {
    fn next(&mut self) -> Option<ChildOfElement<'d>> {
        if self.idx >= self.x.len() {
            None
        } else {
            let e = Element {
                lifetime: InvariantLifetime,
                node: match self.x[self.idx] {
                    raw::ElementCOE(n) => n
                },
            };
            self.idx += 1;
            Some(ElementCOE(e))
        }
    }
}

pub struct Attributes<'d> {
    x: &'d [*mut raw::Attribute],
    idx: uint,
}

impl<'d> Iterator<Attribute<'d>> for Attributes<'d> {
    fn next(&mut self) -> Option<Attribute<'d>> {
        if self.idx >= self.x.len() {
            None
        } else {
            let a = Attribute::wrap(self.x[self.idx]);
            self.idx += 1;
            Some(a)
        }
    }
}

macro_rules! node(
    ($name:ident, $raw:ty) => (
        pub struct $name<'d> {
            lifetime: InvariantLifetime<'d>,
            node: *mut $raw,
        }

        impl<'d> $name<'d> {
            fn wrap(node: *mut $raw) -> $name<'d> {
                $name {
                    lifetime: InvariantLifetime,
                    node: node,
                }
            }

            fn node(&self) -> &'d $raw { unsafe { &*self.node } }
        }

        impl<'d> PartialEq for $name<'d> {
            fn eq(&self, other: &$name<'d>) -> bool {
                self.node == other.node
            }
        }
    )
)

node!(Element, raw::Element)

impl<'d> Element<'d> {
    pub fn name(&self) -> &'d str { self.node().name() }
}

impl<'d> fmt::Show for Element<'d> {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        let node = unsafe { &* self.node };
        write!(f, "Element {{ name: {}  }}", node.name())
    }
}

node!(Attribute, raw::Attribute)

impl<'d> Attribute<'d> {
    pub fn name(&self)  -> &str { self.node().name() }
    pub fn value(&self) -> &str { self.node().value() }
}

#[deriving(PartialEq,Show)]
pub enum ChildOfElement<'d> {
    ElementCOE(Element<'d>),
}

impl<'d> ChildOfElement<'d> {
    pub fn element(self) -> Option<Element<'d>> {
        match self {
            ElementCOE(n) => Some(n)
        }
    }
}

#[deriving(PartialEq,Show)]
pub enum ParentOfChild<'d> {
    ElementPOC(Element<'d>),
}

impl<'d> ParentOfChild<'d> {
    pub fn element(self) -> Option<Element<'d>> {
        match self {
            ElementPOC(n) => Some(n)
        }
    }
}

#[cfg(test)]
mod test {
    use super::super::Package;
    use super::{ChildOfElement,ElementCOE};
    use super::{ElementPOC};
    use super::Attribute;

    #[test]
    fn elements_can_have_element_children() {
        let package = Package::new();
        let (s, mut c) = package.as_thin_document();

        let alpha = s.create_element("alpha");
        let beta  = s.create_element("beta");

        c.append_element_child(alpha, beta);

        let children: Vec<ChildOfElement> = c.element_children(alpha).collect();

        assert_eq!(children[0], ElementCOE(beta));
    }

    #[test]
    fn element_children_are_ordered() {
        let package = Package::new();
        let (s, mut c) = package.as_thin_document();

        let greek = s.create_element("greek");
        let alpha = s.create_element("alpha");
        let omega = s.create_element("omega");

        c.append_element_child(greek, alpha);
        c.append_element_child(greek, omega);

        let children: Vec<ChildOfElement> = c.element_children(greek).collect();

        assert_eq!(children[0], ElementCOE(alpha));
        assert_eq!(children[1], ElementCOE(omega));
    }

    #[test]
    fn element_children_know_their_parent() {
        let package = Package::new();
        let (s, mut c) = package.as_thin_document();

        let alpha = s.create_element("alpha");
        let beta  = s.create_element("beta");

        c.append_element_child(alpha, beta);

        assert_eq!(Some(ElementPOC(alpha)), c.element_parent(beta));
    }

    #[test]
    fn changing_parent_of_element_removes_element_from_original_parent() {
        let package = Package::new();
        let (s, mut c) = package.as_thin_document();

        let parent1 = s.create_element("parent1");
        let parent2 = s.create_element("parent2");
        let child = s.create_element("child");

        c.append_element_child(parent1, child);
        c.append_element_child(parent2, child);

        assert_eq!(0, c.element_children(parent1).count());
        assert_eq!(1, c.element_children(parent2).count());
    }

    #[test]
    fn elements_can_be_renamed() {
        let package = Package::new();
        let (s, _) = package.as_thin_document();

        let alpha = s.create_element("alpha");
        s.element_set_name(&alpha, "beta");
        assert_eq!(alpha.name(), "beta");
    }

    #[test]
    fn elements_have_attributes() {
        let package = Package::new();
        let (s, mut c) = package.as_thin_document();

        let element = s.create_element("element");
        let attr = s.create_attribute("hello", "world");
        c.set_attribute(element, attr);

        assert_eq!(Some("world"), c.attribute_value(element, "hello"));
    }

    #[test]
    fn attributes_know_their_element() {
        let package = Package::new();
        let (s, mut c) = package.as_thin_document();

        let element = s.create_element("element");
        let attr = s.create_attribute("hello", "world");
        c.set_attribute(element, attr);

        assert_eq!(Some(element), c.attribute_parent(attr));
    }

    #[test]
    fn attributes_can_be_reset() {
        let package = Package::new();
        let (s, mut c) = package.as_thin_document();

        let element = s.create_element("element");

        let attr1 = s.create_attribute("hello", "world");
        let attr2 = s.create_attribute("hello", "galaxy");

        c.set_attribute(element, attr1);
        c.set_attribute(element, attr2);

        assert_eq!(Some("galaxy"), c.attribute_value(element, "hello"));
    }

    #[test]
    fn attributes_can_be_iterated() {
        let package = Package::new();
        let (s, mut c) = package.as_thin_document();

        let element = s.create_element("element");

        let attr1 = s.create_attribute("name1", "value1");
        let attr2 = s.create_attribute("name2", "value2");

        c.set_attribute(element, attr1);
        c.set_attribute(element, attr2);

        let mut attrs: Vec<Attribute> = c.attributes(element).collect();
        attrs.sort_by(|a, b| a.name().cmp(b.name()));

        assert_eq!(2, attrs.len());
        assert_eq!("name1",  attrs[0].name());
        assert_eq!("value1", attrs[0].value());
        assert_eq!("name2",  attrs[1].name());
        assert_eq!("value2", attrs[1].value());
    }
}
<|endoftext|>


<commit_before>use tile::{Tile,Bbox};
use std::cmp::min;
use std::f32;

pub const TILE_SIZE: usize = 256;

/// Holds data and provides methods to regrid data into a 256 x 256 grid.
#[derive(Debug)]
pub struct TileData {
    /// Must be expressed in meters, in ascending order
    pub lat: Vec<f64>,
    /// Must be expressed in meters, in ascending order
    pub lon: Vec<f64>,
    /// Values must be a flattened array (lat, lon)
    pub values: Vec<f32>,
    pub bbox: Bbox,
    pub tile: Tile,
}
impl TileData {

    /**
     * regrid self.values into a TILE_SIZE x TILE_SIZE grid.
     */
    pub fn to_tile_grid(&self) -> [[f32; TILE_SIZE]; TILE_SIZE] {

        // fetch nearest latitudes indices:
        // loop on GRID latitudes, and for each of those, find the closest one in self.lat,
        // and store its index in an array (lat_ids)
        let mut lat_ids: [usize; TILE_SIZE] = [0; TILE_SIZE];
        let lat_inc: f64 = (self.bbox.north - self.bbox.south) / (TILE_SIZE as f64);

        let mut current_idx: usize = 0;
        let mut current_lat: f64 = self.bbox.south;
        for i in 0..TILE_SIZE {
            // If the closest lat value is the biggest one,
            // it won't change over the next iteration
            if current_idx == self.lat.len() -1 {
                for following_i in i..TILE_SIZE {
                    lat_ids[following_i] = current_idx;
                }
                break;
            }
            while (self.lat[current_idx] - current_lat).abs() >  (self.lat[current_idx + 1] - current_lat).abs() {
                current_idx += 1;
                if current_idx == self.lat.len() -1 {
                    break;
                }
            }
            lat_ids[i] = current_idx;
            current_lat += lat_inc;
        }

        // fetch nearest longitude indices
        //   loop on the tile grid longitude , and for each of those, find the closest one in self.lon,
        //   and store its index in an array (lon_ids)
        let mut lon_ids: [usize; TILE_SIZE] = [0; TILE_SIZE];
        let lon_inc: f64 = (self.bbox.east - self.bbox.west) / (TILE_SIZE as f64);

        let mut current_idx: usize = 0;
        let mut current_lon: f64 = self.bbox.west;
        for i in 0..TILE_SIZE {
            if current_idx == self.lon.len() -1 {
                for following_i in i..TILE_SIZE {
                    lon_ids[following_i] = current_idx;
                }
                break;
            }
            while (self.lon[current_idx] - current_lon).abs() >  (self.lon[current_idx + 1] - current_lon).abs() {
                current_idx += 1;
                if current_idx == self.lon.len() -1 {
                    break;
                }
            }
            lon_ids[i] = current_idx;
            current_lon += lon_inc;
        }

        // Exclude coordinates outside the dataset bounding box
        //   (Check "how far" are the actual latitudes values from the requested ones (self.bbox))
        let mut data_lat_min: usize = 0;
        let mut boundary = self.bbox.south + lat_inc * 1.5;
        while self.lat[lat_ids[data_lat_min]] > boundary && data_lat_min < (lat_ids.len() - 1) {
            boundary += lat_inc;
            data_lat_min += 1;
        }
        let mut data_lat_max: usize = lat_ids.len() - 1;
        boundary = self.bbox.north - lat_inc * 1.5;
        while self.lat[lat_ids[data_lat_max]] < boundary && data_lat_max > 0 {
            boundary -= lat_inc;
            data_lat_max -= 1;
        }
        //   (Check "how far" are the actual longitude values from the requested ones (self.bbox))
        let mut data_lon_min: usize = 0;
        boundary = self.bbox.west + lon_inc * 1.5;
        while self.lon[lon_ids[data_lon_min]] > boundary && data_lon_min < (lon_ids.len() - 1) {
            boundary += lon_inc;
            data_lon_min += 1;
        }
        let mut data_lon_max: usize = lon_ids.len() - 1;
        boundary = self.bbox.east - lon_inc * 1.5;
        while self.lon[lon_ids[data_lon_max]] < boundary && data_lon_max > 0 {
            boundary -= lon_inc;
            data_lon_max -= 1;
        }

        // pick values using precomputed indices
        let mut values: [[f32; TILE_SIZE]; TILE_SIZE] = [[f32::NAN; TILE_SIZE]; TILE_SIZE];
        for i_lat in 0..TILE_SIZE {
            for i_lon in 0..TILE_SIZE {
                if i_lat < data_lat_min
                    || i_lat > data_lat_max
                    || i_lon < data_lon_min
                    || i_lon > data_lon_max {
                    values[i_lat][i_lon] = f32::NAN;
                } else {
                    values[i_lat][i_lon] = self.value_at(lat_ids[i_lat], lon_ids[i_lon]);
                }
            }
        }
        values
    }

    #[inline]
    /// Return the value of self.values as if it was a bi-dimensional array.
    fn value_at(&self, lat_idx: usize, lon_idx: usize) -> f32 {
        return self.values[self.lon.len() * lat_idx + lon_idx];
    }

    /// Creates up to 4 tiles, representing the n+1 zoom level using self.values
    pub fn sub_tiledata(&self) -> Vec<Self> {
        let mut sub_tiledata: Vec<Self> = Vec::new();
        let base_x = self.tile.x * 2;
        let base_y = self.tile.y * 2;
        let z = self.tile.z + 1;
        for x in  base_x..(base_x + 2) {
            for y in base_y..(base_y + 2) {
                let tile = Tile { x: x, y: y, z: z };
                let xy = tile.xy_bounds();

                // get min latitude index
                let mut i_lat_min: usize = 0;
                for (i, lat) in self.lat.iter().enumerate() {
                    if *lat >= xy.south {
                        i_lat_min = if i > 0 { i - 1 } else { 0 };
                        break;
                    }
                }
                // get max latitude index
                let mut i_lat_max: usize = 0;
                for (i, lat) in self.lat.iter().rev().enumerate() {
                    if *lat <= xy.north {
                        i_lat_max = if i != (self.lat.len() - 1 ) { self.lat.len() - i } else { self.lat.len() -1 };
                        break;
                    }
                }

                // get min longitude index
                let mut i_lon_min: usize = 0;
                for (i, lon) in self.lon.iter().enumerate() {
                    if *lon >= xy.west {
                        i_lon_min = if i > 0 { i - 1 } else { 0 };
                        break;
                    }
                }
                // get max longitude index
                let mut i_lon_max: usize = 0;
                for (i, lon) in self.lon.iter().rev().enumerate() {
                    if *lon <= xy.east {
                        i_lon_max = if i != (self.lon.len() - 1 ) { self.lon.len() - i } else { self.lon.len() -1 };
                        break;
                    }
                }

                // Extract lat, lon and values using the computed indices
                let subset_lat: Vec<f64> = self.lat[i_lat_min..min(i_lat_max +1, self.lat.len() -1)].to_vec();
                let subset_lon: Vec<f64> = self.lon[i_lon_min..min(i_lon_max +1, self.lon.len() -1)].to_vec();
                let mut subset_values: Vec<f32> = Vec::with_capacity(subset_lat.len() * subset_lon.len());
                for i_lat in i_lat_min..min(i_lat_max +1, self.lat.len() -1) {
                    for i_lon in i_lon_min..min(i_lon_max +1, self.lon.len() -1) {
                        subset_values.push(self.value_at(i_lat, i_lon));
                    }
                }

                sub_tiledata.push(
                    Self {
                        lon: subset_lon,
                        lat: subset_lat,
                        values: subset_values,
                        bbox: xy,
                        tile: tile
                    }
                );
            }
        }
        sub_tiledata
    }
}
<commit_msg>Removed out of bound mask<commit_after>use tile::{Tile,Bbox};
use std::cmp::min;
use std::f32;

pub const TILE_SIZE: usize = 256;

/// Holds data and provides methods to regrid data into a 256 x 256 grid.
#[derive(Debug)]
pub struct TileData {
    /// Must be expressed in meters, in ascending order
    pub lat: Vec<f64>,
    /// Must be expressed in meters, in ascending order
    pub lon: Vec<f64>,
    /// Values must be a flattened array (lat, lon)
    pub values: Vec<f32>,
    pub bbox: Bbox,
    pub tile: Tile,
}
impl TileData {

    /**
     * regrid self.values into a TILE_SIZE x TILE_SIZE grid.
     */
    pub fn to_tile_grid(&self) -> [[f32; TILE_SIZE]; TILE_SIZE] {

        // fetch nearest latitudes indices:
        // loop on GRID latitudes, and for each of those, find the closest one in self.lat,
        // and store its index in an array (lat_ids)
        let mut lat_ids: [usize; TILE_SIZE] = [0; TILE_SIZE];
        let lat_inc: f64 = (self.bbox.north - self.bbox.south) / (TILE_SIZE as f64);

        let mut current_idx: usize = 0;
        let mut current_lat: f64 = self.bbox.south;
        for i in 0..TILE_SIZE {
            // If the closest lat value is the biggest one,
            // it won't change over the next iteration
            if current_idx == self.lat.len() -1 {
                for following_i in i..TILE_SIZE {
                    lat_ids[following_i] = current_idx;
                }
                break;
            }
            while (self.lat[current_idx] - current_lat).abs() >  (self.lat[current_idx + 1] - current_lat).abs() {
                current_idx += 1;
                if current_idx == self.lat.len() -1 {
                    break;
                }
            }
            lat_ids[i] = current_idx;
            current_lat += lat_inc;
        }

        // fetch nearest longitude indices
        //   loop on the tile grid longitude , and for each of those, find the closest one in self.lon,
        //   and store its index in an array (lon_ids)
        let mut lon_ids: [usize; TILE_SIZE] = [0; TILE_SIZE];
        let lon_inc: f64 = (self.bbox.east - self.bbox.west) / (TILE_SIZE as f64);

        let mut current_idx: usize = 0;
        let mut current_lon: f64 = self.bbox.west;
        for i in 0..TILE_SIZE {
            if current_idx == self.lon.len() -1 {
                for following_i in i..TILE_SIZE {
                    lon_ids[following_i] = current_idx;
                }
                break;
            }
            while (self.lon[current_idx] - current_lon).abs() >  (self.lon[current_idx + 1] - current_lon).abs() {
                current_idx += 1;
                if current_idx == self.lon.len() -1 {
                    break;
                }
            }
            lon_ids[i] = current_idx;
            current_lon += lon_inc;
        }

        // pick values using precomputed indices
        let mut values: [[f32; TILE_SIZE]; TILE_SIZE] = [[f32::NAN; TILE_SIZE]; TILE_SIZE];
        for i_lat in 0..TILE_SIZE {
            for i_lon in 0..TILE_SIZE {
                values[i_lat][i_lon] = self.value_at(lat_ids[i_lat], lon_ids[i_lon]);
            }
        }
        values
    }

    #[inline]
    /// Return the value of self.values as if it was a bi-dimensional array.
    fn value_at(&self, lat_idx: usize, lon_idx: usize) -> f32 {
        return self.values[self.lon.len() * lat_idx + lon_idx];
    }

    /// Creates up to 4 tiles, representing the n+1 zoom level using self.values
    pub fn sub_tiledata(&self) -> Vec<Self> {
        let mut sub_tiledata: Vec<Self> = Vec::new();
        let base_x = self.tile.x * 2;
        let base_y = self.tile.y * 2;
        let z = self.tile.z + 1;
        for x in  base_x..(base_x + 2) {
            for y in base_y..(base_y + 2) {
                let tile = Tile { x: x, y: y, z: z };
                let xy = tile.xy_bounds();

                // get min latitude index
                let mut i_lat_min: usize = 0;
                for (i, lat) in self.lat.iter().enumerate() {
                    if *lat >= xy.south {
                        i_lat_min = if i > 0 { i - 1 } else { 0 };
                        break;
                    }
                }
                // get max latitude index
                let mut i_lat_max: usize = 0;
                for (i, lat) in self.lat.iter().rev().enumerate() {
                    if *lat <= xy.north {
                        i_lat_max = if i != (self.lat.len() - 1 ) { self.lat.len() - i } else { self.lat.len() -1 };
                        break;
                    }
                }

                // get min longitude index
                let mut i_lon_min: usize = 0;
                for (i, lon) in self.lon.iter().enumerate() {
                    if *lon >= xy.west {
                        i_lon_min = if i > 0 { i - 1 } else { 0 };
                        break;
                    }
                }
                // get max longitude index
                let mut i_lon_max: usize = 0;
                for (i, lon) in self.lon.iter().rev().enumerate() {
                    if *lon <= xy.east {
                        i_lon_max = if i != (self.lon.len() - 1 ) { self.lon.len() - i } else { self.lon.len() -1 };
                        break;
                    }
                }

                // Extract lat, lon and values using the computed indices
                let subset_lat: Vec<f64> = self.lat[i_lat_min..min(i_lat_max +1, self.lat.len() -1)].to_vec();
                let subset_lon: Vec<f64> = self.lon[i_lon_min..min(i_lon_max +1, self.lon.len() -1)].to_vec();
                let mut subset_values: Vec<f32> = Vec::with_capacity(subset_lat.len() * subset_lon.len());
                for i_lat in i_lat_min..min(i_lat_max +1, self.lat.len() -1) {
                    for i_lon in i_lon_min..min(i_lon_max +1, self.lon.len() -1) {
                        subset_values.push(self.value_at(i_lat, i_lon));
                    }
                }

                sub_tiledata.push(
                    Self {
                        lon: subset_lon,
                        lat: subset_lat,
                        values: subset_values,
                        bbox: xy,
                        tile: tile
                    }
                );
            }
        }
        sub_tiledata
    }
}
<|endoftext|>