<commit_before>/*
 * Copyright (c) 2017 Boucher, Antoni <bouanto@zoho.com>
 *
 * 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.
 */

#![feature(conservative_impl_trait, fn_traits, unboxed_closures)]

extern crate futures;
extern crate gdk_pixbuf;
extern crate gtk;
extern crate hyper;
extern crate hyper_tls;
extern crate json;
#[macro_use]
extern crate relm;
#[macro_use]
extern crate relm_derive;
extern crate simplelog;

use futures::{Future, Stream};
use gdk_pixbuf::PixbufLoader;
use gtk::{Button, ButtonExt, ContainerExt, Image, Label, WidgetExt, Window, WindowType};
use hyper::Client;
use hyper_tls::HttpsConnector;
use gtk::Orientation::Vertical;
use relm::{EventStream, Handle, Relm, Widget};
use simplelog::{Config, TermLogger};
use simplelog::LogLevelFilter::Warn;

use self::Msg::*;

#[derive(Clone)]
struct Model {
    gif_url: String,
    topic: String,
}

#[derive(SimpleMsg)]
enum Msg {
    DownloadCompleted,
    FetchUrl,
    ImageChunk(Vec<u8>),
    NewGif(Vec<u8>),
    Quit,
}

struct Widgets {
    button: Button,
    image: Image,
    label: Label,
    window: Window,
}

struct Win {
    loader: PixbufLoader,
    widgets: Widgets,
}

impl Win {
    fn view(stream: &EventStream<Msg>) -> Widgets {
        let vbox = gtk::Box::new(Vertical, 0);

        let label = Label::new(None);
        vbox.add(&label);

        let image = Image::new();
        vbox.add(&image);

        let button = Button::new_with_label("Load image");
        vbox.add(&button);

        let window = Window::new(WindowType::Toplevel);

        window.add(&vbox);

        window.show_all();

        connect!(stream, button, connect_clicked(_), FetchUrl);
        connect_no_inhibit!(stream, window, connect_delete_event(_, _), Quit);

        Widgets {
            button: button,
            image: image,
            label: label,
            window: window,
        }
    }
}

impl Widget<Msg> for Win {
    type Container = Window;
    type Model = Model;

    fn container(&self) -> &Self::Container {
        &self.widgets.window
    }

    fn new(stream: &EventStream<Msg>) -> (Self, Model) {
        let model = Model {
            gif_url: "waiting.gif".to_string(),
            topic: "cats".to_string(),
        };
        let widgets = Self::view(stream);
        widgets.label.set_text(&model.topic);
        let window = Win {
            loader: PixbufLoader::new(),
            widgets: widgets,
        };
        (window, model)
    }

    fn update(&mut self, event: Msg) {
        match event {
            DownloadCompleted => {
                self.widgets.button.set_sensitive(true);
                self.loader.close().unwrap();
                self.widgets.image.set_from_pixbuf(self.loader.get_pixbuf().as_ref());
                self.loader = PixbufLoader::new();
            },
            FetchUrl => {
                // Disable the button because loading 2 images at the same time crashes the pixbuf
                // loader.
                self.widgets.button.set_sensitive(false);
            },
            ImageChunk(chunk) => {
                self.loader.loader_write(&chunk).unwrap();
            },
            Quit => gtk::main_quit(),
            _ => (),
        }
    }

    fn update_command(relm: &Relm<Msg>, event: Msg, model: &mut Model) {
        match event {
            FetchUrl => {
                let url = format!("https://api.giphy.com/v1/gifs/random?api_key=dc6zaTOxFJmzC&tag={}", model.topic);
                let http_future = http_get(&url, relm.handle());
                relm.connect_exec(http_future, NewGif);
            },
            NewGif(result) => {
                let string = String::from_utf8(result).unwrap();
                let json = json::parse(&string).unwrap();
                let url = &json["data"]["image_url"].as_str().unwrap();
                let http_future = http_get_stream(url, relm.handle());
                let future = relm.connect(http_future, ImageChunk);
                relm.connect_exec(future, DownloadCompleted);
            },
            _ => (),
        }
    }
}

impl Drop for Win {
    fn drop(&mut self) {
        // This is necessary to avoid a GDK warning.
        self.loader.close().ok(); // Ignore the error since no data was loaded.
    }
}

fn http_get<'a>(url: &str, handle: &Handle) -> impl Future<Item=Vec<u8>, Error=()> + 'a {
    let stream = http_get_stream(url, handle);
    // TODO: use the new Stream::concat().
    stream.fold(vec![], |mut acc, chunk| {
        acc.extend_from_slice(&chunk);
        Ok(acc)
    })
}

fn http_get_stream<'a>(url: &str, handle: &Handle) -> impl Stream<Item=Vec<u8>, Error=()> + 'a {
    let url = hyper::Url::parse(url).unwrap();
    let connector = HttpsConnector::new(2, handle);
    let client = Client::configure()
        .connector(connector)
        .build(handle);
    client.get(url).and_then(|res| {
        Ok(res.body()
           .map(|chunk| chunk.to_vec())
           .map_err(|_| ())
       )
    })
        .map_err(|_| ())
        .flatten_stream()
}

fn main() {
    TermLogger::init(Warn, Config::default()).unwrap();
    Relm::run::<Win>().unwrap();
}
<commit_msg>Fix http example<commit_after>/*
 * Copyright (c) 2017 Boucher, Antoni <bouanto@zoho.com>
 *
 * 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.
 */

#![feature(conservative_impl_trait, fn_traits, unboxed_closures)]

extern crate futures;
extern crate gdk_pixbuf;
extern crate gtk;
extern crate hyper;
extern crate hyper_tls;
extern crate json;
#[macro_use]
extern crate relm;
#[macro_use]
extern crate relm_derive;
extern crate simplelog;

use futures::{Future, Stream};
use gdk_pixbuf::PixbufLoader;
use gtk::{Button, ButtonExt, ContainerExt, Image, Label, WidgetExt, Window, WindowType};
use hyper::Client;
use hyper_tls::HttpsConnector;
use gtk::Orientation::Vertical;
use relm::{EventStream, Handle, Relm, Widget};
use simplelog::{Config, TermLogger};
use simplelog::LogLevelFilter::Warn;

use self::Msg::*;

#[derive(Clone)]
struct Model {
    gif_url: String,
    topic: String,
}

#[derive(SimpleMsg)]
enum Msg {
    DownloadCompleted,
    FetchUrl,
    ImageChunk(Vec<u8>),
    NewGif(Vec<u8>),
    Quit,
}

struct Widgets {
    button: Button,
    image: Image,
    label: Label,
    window: Window,
}

struct Win {
    loader: PixbufLoader,
    widgets: Widgets,
}

impl Win {
    fn view(stream: &EventStream<Msg>) -> Widgets {
        let vbox = gtk::Box::new(Vertical, 0);

        let label = Label::new(None);
        vbox.add(&label);

        let image = Image::new();
        vbox.add(&image);

        let button = Button::new_with_label("Load image");
        vbox.add(&button);

        let window = Window::new(WindowType::Toplevel);

        window.add(&vbox);

        window.show_all();

        connect!(stream, button, connect_clicked(_), FetchUrl);
        connect_no_inhibit!(stream, window, connect_delete_event(_, _), Quit);

        Widgets {
            button: button,
            image: image,
            label: label,
            window: window,
        }
    }
}

impl Widget<Msg> for Win {
    type Container = Window;
    type Model = Model;

    fn container(&self) -> &Self::Container {
        &self.widgets.window
    }

    fn new(stream: &EventStream<Msg>) -> (Self, Model) {
        let model = Model {
            gif_url: "waiting.gif".to_string(),
            topic: "cats".to_string(),
        };
        let widgets = Self::view(stream);
        widgets.label.set_text(&model.topic);
        let window = Win {
            loader: PixbufLoader::new(),
            widgets: widgets,
        };
        (window, model)
    }

    fn update(&mut self, event: Msg, _model: &mut Model) {
        match event {
            DownloadCompleted => {
                self.widgets.button.set_sensitive(true);
                self.loader.close().unwrap();
                self.widgets.image.set_from_pixbuf(self.loader.get_pixbuf().as_ref());
                self.loader = PixbufLoader::new();
            },
            FetchUrl => {
                // Disable the button because loading 2 images at the same time crashes the pixbuf
                // loader.
                self.widgets.button.set_sensitive(false);
            },
            ImageChunk(chunk) => {
                self.loader.loader_write(&chunk).unwrap();
            },
            Quit => gtk::main_quit(),
            _ => (),
        }
    }

    fn update_command(relm: &Relm<Msg>, event: Msg, model: &mut Model) {
        match event {
            FetchUrl => {
                let url = format!("https://api.giphy.com/v1/gifs/random?api_key=dc6zaTOxFJmzC&tag={}", model.topic);
                let http_future = http_get(&url, relm.handle());
                relm.connect_exec(http_future, NewGif);
            },
            NewGif(result) => {
                let string = String::from_utf8(result).unwrap();
                let json = json::parse(&string).unwrap();
                let url = &json["data"]["image_url"].as_str().unwrap();
                let http_future = http_get_stream(url, relm.handle());
                let future = relm.connect(http_future, ImageChunk);
                relm.connect_exec(future, DownloadCompleted);
            },
            _ => (),
        }
    }
}

impl Drop for Win {
    fn drop(&mut self) {
        // This is necessary to avoid a GDK warning.
        self.loader.close().ok(); // Ignore the error since no data was loaded.
    }
}

fn http_get<'a>(url: &str, handle: &Handle) -> impl Future<Item=Vec<u8>, Error=()> + 'a {
    let stream = http_get_stream(url, handle);
    // TODO: use the new Stream::concat().
    stream.fold(vec![], |mut acc, chunk| {
        acc.extend_from_slice(&chunk);
        Ok(acc)
    })
}

fn http_get_stream<'a>(url: &str, handle: &Handle) -> impl Stream<Item=Vec<u8>, Error=()> + 'a {
    let url = hyper::Url::parse(url).unwrap();
    let connector = HttpsConnector::new(2, handle);
    let client = Client::configure()
        .connector(connector)
        .build(handle);
    client.get(url).and_then(|res| {
        Ok(res.body()
           .map(|chunk| chunk.to_vec())
           .map_err(|_| ())
       )
    })
        .map_err(|_| ())
        .flatten_stream()
}

fn main() {
    TermLogger::init(Warn, Config::default()).unwrap();
    Relm::run::<Win>().unwrap();
}
<|endoftext|>


<commit_before>///
/// This example parses, sorts and groups the iris dataset
/// and does some simple manipulations.
///
/// Iterators and itertools functionality are used throughout.
///
///

extern crate itertools;

use itertools::Itertools;
use std::str::FromStr;
use std::collections::HashMap;
use std::num::ParseFloatError;

static DATA: &'static str = include_str!("iris.data");

#[derive(Clone, Debug)]
struct Iris {
    name: String,
    data: [f32; 4],
}

#[derive(Clone, Debug)]
enum ParseError {
    Numeric(ParseFloatError),
    Other(&'static str),
}

impl From<ParseFloatError> for ParseError {
    fn from(err: ParseFloatError) -> Self {
        ParseError::Numeric(err)
    }
}

/// Parse an Iris from a comma-separated line
impl FromStr for Iris {
    type Err = ParseError;

    fn from_str(s: &str) -> Result<Self, Self::Err> {
        let mut iris = Iris { name: "".into(), data: [0.; 4] };
        let mut parts = s.split(",").map(str::trim);

        // using Iterator::by_ref()
        for (index, part) in parts.by_ref().take(4).enumerate() {
            iris.data[index] = try!(part.parse::<f32>());
        }
        if let Some(name) = parts.next() {
            iris.name = name.into();
        } else {
            return Err(ParseError::Other("Missing name"))
        }
        Ok(iris)
    }
}

fn main() {
    // using itertools::Itertools::fold_results to create the result of parsing
    let irises = DATA.lines()
                     .map(str::parse)
                     .fold_results(Vec::new(), |mut v, iris: Iris| {
                         v.push(iris);
                         v
                     }).unwrap();

    // Sort them and group them
    let mut irises = irises;
    irises.sort_by(|a, b| Ord::cmp(&a.name, &b.name));

    // using Iterator::cycle()
    let mut plot_symbols = "+ox".chars().cycle();
    let mut symbolmap = HashMap::new();

    // using itertools::Itertools::group_by
    for (species, species_data) in irises.iter().group_by(|iris| &iris.name) {
        // assign a plot symbol
        symbolmap.entry(species).or_insert_with(|| {
            plot_symbols.next().unwrap()
        });

        println!("Species = {} has symbol {}", species, symbolmap[species]);

        for column in 0..4 {
            for &iris in &species_data {
                print!("{:>3.1}, ", iris.data[column]);
            }
            println!("");
        }

    }

    // Look at all combinations of the four columns
    //
    // See https://en.wikipedia.org/wiki/Iris_flower_data_set
    //
    // using itertools::Itertools::combinations
    for (a, b) in (0..4).combinations() {
        println!("Column {} vs {}:", a, b);
        let n = 30;
        let mut plot = vec![' '; n * n];

        // using itertools::Itertools::fold1
        let min_max = |vec: &[Iris], col| {
            vec.iter()
               .map(move |iris| iris.data[col])
               .map(|x| (x, x))
               .fold1(|(min, max), (elt, _)|
                   (f32::min(min, elt), f32::max(max, elt))
               ).expect("Can't find min/max of empty iterator")
        };
        let (min_x, max_x) = min_max(&irises, a);
        let (min_y, max_y) = min_max(&irises, b);

        for (symbol, x, y) in irises.iter()
            .map(|ir| (symbolmap[&ir.name], ir.data[a], ir.data[b]))
        {
            // round to the grid
            let ix = ((x - min_x) / (max_x - min_x) * ((n - 1) as f32)) as usize;
            let iy = ((y - min_y) / (max_y - min_y) * ((n - 1) as f32)) as usize;
            let iy = n - 1 - iy; // reverse y axis' direction

            plot[n * iy + ix] = symbol;
        }

        // render plot
        //
        // using itertools::Itertools::join
        for line in plot.chunks(n) {
            println!("{}", line.iter().join(" "))
        }
    }
}
<commit_msg>Update examples to use .group_by_lazy() and .format()<commit_after>///
/// This example parses, sorts and groups the iris dataset
/// and does some simple manipulations.
///
/// Iterators and itertools functionality are used throughout.
///
///

extern crate itertools;

use itertools::Itertools;
use std::str::FromStr;
use std::collections::HashMap;
use std::num::ParseFloatError;

static DATA: &'static str = include_str!("iris.data");

#[derive(Clone, Debug)]
struct Iris {
    name: String,
    data: [f32; 4],
}

#[derive(Clone, Debug)]
enum ParseError {
    Numeric(ParseFloatError),
    Other(&'static str),
}

impl From<ParseFloatError> for ParseError {
    fn from(err: ParseFloatError) -> Self {
        ParseError::Numeric(err)
    }
}

/// Parse an Iris from a comma-separated line
impl FromStr for Iris {
    type Err = ParseError;

    fn from_str(s: &str) -> Result<Self, Self::Err> {
        let mut iris = Iris { name: "".into(), data: [0.; 4] };
        let mut parts = s.split(",").map(str::trim);

        // using Iterator::by_ref()
        for (index, part) in parts.by_ref().take(4).enumerate() {
            iris.data[index] = try!(part.parse::<f32>());
        }
        if let Some(name) = parts.next() {
            iris.name = name.into();
        } else {
            return Err(ParseError::Other("Missing name"))
        }
        Ok(iris)
    }
}

fn main() {
    // using Itertools::fold_results to create the result of parsing
    let irises = DATA.lines()
                     .map(str::parse)
                     .fold_results(Vec::new(), |mut v, iris: Iris| {
                         v.push(iris);
                         v
                     });
    let mut irises = match irises {
        Err(e) => {
            println!("Error parsing: {:?}", e);
            std::process::exit(1);
        }
        Ok(data) => data,
    };

    // Sort them and group them
    irises.sort_by(|a, b| Ord::cmp(&a.name, &b.name));

    // using Iterator::cycle()
    let mut plot_symbols = "+ox".chars().cycle();
    let mut symbolmap = HashMap::new();

    // using Itertools::group_by_lazy
    for species_group in &irises.iter().group_by_lazy(|iris| &iris.name) {
        for (index, iris) in species_group.enumerate() {
            if index == 0 {
                // assign a plot symbol
                let species = &iris.name;
                symbolmap.entry(species).or_insert_with(|| {
                    plot_symbols.next().unwrap()
                });
                println!("{} (symbol={})", species, symbolmap[species]);
            }

            // using Itertools::format for lazy formatting
            println!("{}",
                     iris.data.iter()
                     .format(", ", |elt, f| f(&format_args!("{:>3.1}", elt))));
        }

    }

    // Look at all combinations of the four columns
    //
    // See https://en.wikipedia.org/wiki/Iris_flower_data_set
    //
    // using Itertools::combinations
    for (a, b) in (0..4).combinations() {
        println!("Column {} vs {}:", a, b);
        let n = 30;
        let mut plot = vec![' '; n * n];

        // using Itertools::fold1
        let min_max = |vec: &[Iris], col| {
            vec.iter()
               .map(move |iris| iris.data[col])
               .map(|x| (x, x))
               .fold1(|(min, max), (elt, _)|
                   (f32::min(min, elt), f32::max(max, elt))
               ).expect("Can't find min/max of empty iterator")
        };
        let (min_x, max_x) = min_max(&irises, a);
        let (min_y, max_y) = min_max(&irises, b);

        for (symbol, x, y) in irises.iter()
            .map(|ir| (symbolmap[&ir.name], ir.data[a], ir.data[b]))
        {
            // round to the grid
            let ix = ((x - min_x) / (max_x - min_x) * ((n - 1) as f32)) as usize;
            let iy = ((y - min_y) / (max_y - min_y) * ((n - 1) as f32)) as usize;
            let iy = n - 1 - iy; // reverse y axis' direction

            plot[n * iy + ix] = symbol;
        }

        // render plot
        //
        // using Itertools::join
        for line in plot.chunks(n) {
            println!("{}", line.iter().join(" "))
        }
    }
}
<|endoftext|>


<commit_before>use std::hash::{hash,Hash};
use std::collections::HashMap;
use std::thunk::Invoke;
use std::mem::replace;
use std::sync::Arc;
use std::cell::RefCell;

// "One big memo table" design

pub trait Adapton {
    fn new () -> Self ;

    // Names
    fn name_of_string (self:&mut Self, String) -> Name ;
    fn name_of_u64 (self:&mut Self, u64) -> Name ;
    fn name_pair (self: &Self, Name, Name) -> Name ;
    fn name_fork (self:&mut Self, Name) -> (Name, Name) ;

    fn ns<T,F> (self: &mut Self, Name,
                 body:F) -> T where F:FnOnce(&mut Self) -> T;

    fn put<T:Eq> (self:&mut Self, T) -> Art<T> ;

    // Mutable cells
    fn cell<T:Eq> (self:&mut Self, ArtId, T) -> MutArt<T> ;
    fn set<T:Eq> (self:&mut Self, MutArt<T>) ;

    fn thunk<Arg:Eq+Hash,T:Eq>
        (self:&mut Self, id:ArtId,
         fn_body:Box<Invoke<Arg, T> + 'static>, arg:Arg) -> Art<T> ;

    fn force<T:Eq> (self:&mut Self, Art<T>) -> T ;
}

#[derive(Hash,Show,PartialEq,Eq)]
pub enum Lineage {
    Unknown, Structural,
    Root,
    Pair(Arc<Lineage>,Arc<Lineage>),
    ForkL(Arc<Lineage>),
    ForkR(Arc<Lineage>),
    String(String),
    U64(u64),
    Arc(Arc<Lineage>),
}

#[derive(Hash,Show,PartialEq,Eq)]
pub enum Path {
    Empty,
    Child(Arc<Path>,Name),
}

#[derive(Hash,Show,PartialEq,Eq)]
pub struct Name {
    hash : u64,
    lineage : Arc<Lineage>,
}

#[derive(Hash,Show,PartialEq,Eq)]
pub struct Loc {
    hash : u64,
    name : Arc<Name>,
    path : Arc<Path>
}

#[derive(Hash,Show,PartialEq,Eq)]
pub enum ArtId {
    None,
    Structural(u64),
    Nominal(Name),
}

#[derive(Hash,Show,PartialEq,Eq)]
pub enum Art<T> {
    Box(Box<T>),
    Node(Arc<Loc>),
}

#[derive(Hash,Show,PartialEq,Eq)]
pub enum MutArt<T> {
    MutArt(Art<T>)
}

enum Node<T> {
    Pure(PureNode<T>),
    Mut(MutNode<T>),
    Compute(ComputeNode<T>),
}

struct PureNode<T> {
    name : Name,
    val : T,
}

struct MutNode<T> {
    name : Name,
    dem_precs : Vec<DemPrec>,
    val : RefCell<T>,
}

trait Body<T> {
    fn run (self:&Self, st:&mut AdaptonState) -> T ;
}

struct ComputeNode<T> {
    name : Name,
    dem_precs : Vec<DemPrec>,
    dem_succs : Vec<DemSucc>,
    body : Box<Body<T> + 'static>, // Trait in Type: Need lifetime.
    val  : RefCell<Option<T>>,
}

struct DemPrec {
    name : Name,
}

struct DemSucc {
    name : Name,
    dirty : RefCell<bool>
}

pub struct AdaptonState {
    memo_table : HashMap<ArtId, *mut ()>, // memo table
    curr_path : Arc<Path>, // current_namespace
    curr_name : Arc<Name>, // current articulation point
}

impl Adapton for AdaptonState {
    fn new () -> AdaptonState {
        let empty = Arc::new(Path::Empty);
        let root = Arc::new(Name{hash:0, lineage:Arc::new(Lineage::Root) });
        AdaptonState {
            memo_table : HashMap::new (),
            curr_path : empty,
            curr_name : root,
        }
    }
    fn name_of_string (self:&mut AdaptonState, sym:String) -> Name {
        let h = hash::<_>(&sym) ;
        let s = Lineage::String(sym) ;
        Name{ hash:h, lineage:Arc::new(s) }
    }
    fn name_of_u64 (self:&mut AdaptonState, sym:u64) -> Name {
        let h = hash::<_>(&sym) ;
        let s = Lineage::U64(sym) ;
        Name{ hash:h, lineage:Arc::new(s) }
    }
    fn name_pair (self: &AdaptonState, fst: Name, snd: Name) -> Name {
        let h = hash::<_>( &(fst.hash,snd.hash) ) ;
        let p = Lineage::Pair(fst.lineage, snd.lineage) ;
        Name{ hash:h, lineage:Arc::new(p) }
    }
    fn name_fork (self:&mut AdaptonState, nm:Name) -> (Name, Name) {
        let h1 = hash::<_>( &(&nm, 11111111) ) ; // TODO: make this hashing better.
        let h2 = hash::<_>( &(&nm, 22222222) ) ;
        ( Name{ hash:h1,
                lineage:Arc::new(Lineage::ForkL(nm.lineage.clone())) } ,
          Name{ hash:h2,
                lineage:Arc::new(Lineage::ForkR(nm.lineage)) } )
    }
    fn ns<T,F> (self: &mut Self, nm:Name, body:F) -> T where F:FnOnce(&mut Self) -> T {
        let path_body = Arc::new(Path::Child(self.curr_path.clone(), nm)) ;
        let path_pre = replace(&mut self.curr_path, path_body ) ;
        let x = body(self) ;
        let path_body = replace(&mut self.curr_path, path_pre) ;
        drop(path_body);
        x
    }
    fn put<T:Eq> (self:&mut AdaptonState, x:T) -> Art<T> {
        Art::Box(box x)
    }
    fn cell<T:Eq> (self:&mut AdaptonState, id:ArtId, x:T) -> MutArt<T> {
        panic!("")
    }
    fn set<T:Eq> (self:&mut Self, cell:MutArt<T>) {
        panic!("")
    }
    fn thunk<Arg:Eq+Hash,T:Eq>
        (self:&mut AdaptonState,
         id:ArtId, fn_body:Box<Invoke<Arg,T>+'static>, arg:Arg) -> Art<T>
    {
        panic!("")
    }
    fn force<T:Eq> (self:&mut AdaptonState, art:Art<T>) -> T {
        match art {
            Art::Box(b) => *b,
            Art::Node(nm) => panic!(""),
        }
    }
}

pub fn main () {

}
<commit_msg>using Loc instead of Name; using Rc instad of Arc<commit_after>use std::hash::{hash,Hash};
use std::collections::HashMap;
use std::thunk::Invoke;
use std::mem::replace;
//use std::sync::Arc;
use std::cell::RefCell;
use std::rc::Rc;

// "One big memo table" design

pub trait Adapton {
    fn new () -> Self ;

    // Names
    fn name_of_string (self:&mut Self, String) -> Name ;
    fn name_of_u64 (self:&mut Self, u64) -> Name ;
    fn name_pair (self: &Self, Name, Name) -> Name ;
    fn name_fork (self:&mut Self, Name) -> (Name, Name) ;

    fn ns<T,F> (self: &mut Self, Name, body:F) -> T
        where F:FnOnce(&mut Self) -> T ;

    fn put<T:Eq> (self:&mut Self, T) -> Art<T> ;

    // Mutable cells
    fn cell<T:Eq> (self:&mut Self, ArtId, T) -> MutArt<T> ;
    fn set<T:Eq> (self:&mut Self, MutArt<T>) ;

    fn thunk<Arg:Eq+Hash,T:Eq>
        (self:&mut Self, id:ArtId,
         fn_body:Box<Invoke<Arg, T> + 'static>, arg:Arg) -> Art<T> ;

    fn force<T:Eq> (self:&mut Self, Art<T>) -> T ;
}

#[derive(Hash,Show,PartialEq,Eq)]
pub enum Lineage {
    Unknown, Structural,
    Root,
    Pair(Rc<Lineage>,Rc<Lineage>),
    ForkL(Rc<Lineage>),
    ForkR(Rc<Lineage>),
    String(String),
    U64(u64),
    Rc(Rc<Lineage>),
}

#[derive(Hash,Show,PartialEq,Eq)]
pub enum Path {
    Empty,
    Child(Rc<Path>,Name),
}

#[derive(Hash,Show,PartialEq,Eq)]
pub struct Name {
    hash : u64,
    lineage : Rc<Lineage>,
}

#[derive(Hash,Show,PartialEq,Eq)]
pub struct Loc {
    hash : u64,
    name : Rc<Name>,
    path : Rc<Path>
}

#[derive(Hash,Show,PartialEq,Eq)]
pub enum ArtId {
    None,
    Structural(u64),
    Nominal(Name),
}

#[derive(Hash,Show,PartialEq,Eq)]
pub enum Art<T> {
    Box(Box<T>),
    Loc(Rc<Loc>),
}

#[derive(Hash,Show,PartialEq,Eq)]
pub enum MutArt<T> {
    MutArt(Art<T>)
}

enum Node<T> {
    Pure(PureNode<T>),
    Mut(MutNode<T>),
    Compute(ComputeNode<T>),
}

struct PureNode<T> {
    loc : Rc<Loc>,
    val : T,
}

struct MutNode<T> {
    loc : Rc<Loc>,
    dem_precs : Vec<DemPrec>,
    val : RefCell<T>,
}

trait Body<T> {
    fn run (self:&Self, st:&mut AdaptonState) -> T ;
}

struct ComputeNode<T> {
    loc : Rc<Loc>,
    dem_precs : Vec<DemPrec>,
    dem_succs : Vec<DemSucc>,
    body : Box<Body<T> + 'static>, // Trait in Type: Need lifetime.
    val  : RefCell<Option<T>>,
}

struct DemPrec {
    loc : Rc<Loc>,
}

struct DemSucc {
    loc : Rc<Loc>,
    dirty : RefCell<bool>
}

pub struct AdaptonState {
    memo_table : HashMap<Rc<Loc>, *mut ()>, // memo table
    curr_path : Rc<Path>, // current_namespace
    curr_name : Rc<Name>, // current articulation point
}

impl Adapton for AdaptonState {
    fn new () -> AdaptonState {
        let empty = Rc::new(Path::Empty);
        let root = Rc::new(Name{hash:0, lineage:Rc::new(Lineage::Root) });
        AdaptonState {
            memo_table : HashMap::new (),
            curr_path : empty,
            curr_name : root,
        }
    }
    fn name_of_string (self:&mut AdaptonState, sym:String) -> Name {
        let h = hash::<_>(&sym) ;
        let s = Lineage::String(sym) ;
        Name{ hash:h, lineage:Rc::new(s) }
    }
    fn name_of_u64 (self:&mut AdaptonState, sym:u64) -> Name {
        let h = hash::<_>(&sym) ;
        let s = Lineage::U64(sym) ;
        Name{ hash:h, lineage:Rc::new(s) }
    }
    fn name_pair (self: &AdaptonState, fst: Name, snd: Name) -> Name {
        let h = hash::<_>( &(fst.hash,snd.hash) ) ;
        let p = Lineage::Pair(fst.lineage, snd.lineage) ;
        Name{ hash:h, lineage:Rc::new(p) }
    }
    fn name_fork (self:&mut AdaptonState, nm:Name) -> (Name, Name) {
        let h1 = hash::<_>( &(&nm, 11111111) ) ; // TODO: make this hashing better.
        let h2 = hash::<_>( &(&nm, 22222222) ) ;
        ( Name{ hash:h1,
                lineage:Rc::new(Lineage::ForkL(nm.lineage.clone())) } ,
          Name{ hash:h2,
                lineage:Rc::new(Lineage::ForkR(nm.lineage)) } )
    }
    fn ns<T,F> (self: &mut Self, nm:Name, body:F) -> T where F:FnOnce(&mut Self) -> T {
        let path_body = Rc::new(Path::Child(self.curr_path.clone(), nm)) ;
        let path_pre = replace(&mut self.curr_path, path_body ) ;
        let x = body(self) ;
        let path_body = replace(&mut self.curr_path, path_pre) ;
        drop(path_body);
        x
    }
    fn put<T:Eq> (self:&mut AdaptonState, x:T) -> Art<T> {
        Art::Box(box x)
    }
    fn cell<T:Eq> (self:&mut AdaptonState, id:ArtId, x:T) -> MutArt<T> {
        panic!("")
    }
    fn set<T:Eq> (self:&mut Self, cell:MutArt<T>) {
        panic!("")
    }
    fn thunk<Arg:Eq+Hash,T:Eq>
        (self:&mut AdaptonState,
         id:ArtId, fn_body:Box<Invoke<Arg,T>+'static>, arg:Arg) -> Art<T>
    {
        panic!("")
    }
    fn force<T:Eq> (self:&mut AdaptonState, art:Art<T>) -> T {
        match art {
            Art::Box(b) => *b,
            Art::Loc(l) => panic!(""),
        }
    }
}

pub fn main () {

}
<|endoftext|>


<commit_before>// Claxon -- A FLAC decoding library in Rust
// Copyright 2017 Ruud van Asseldonk
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// A copy of the License has been included in the root of the repository.

// This file contains a minimal example of using Claxon and Hound to decode a
// flac file. This can be done more efficiently, but it is also more verbose.
// See the `decode` example for that.

extern crate claxon;

use std::env;

fn main() {
    for fname in env::args().skip(1) {
        let reader = claxon::FlacReader::open(&fname).expect("failed to open FLAC stream");

        // We can use `tags()` to iterate over all tags. When looking for a
        // specific tag, `get_tag()` may be useful instead.
        for (name, value) in reader.tags() {
            // Print comments in a format similar to what
            // `metaflac --block-type=VORBIS_COMMENT --list` would print.
            println!("{}: {}={}", fname, name, value);
        }
    }
}
<commit_msg>Fix comment in tags example<commit_after>// Claxon -- A FLAC decoding library in Rust
// Copyright 2017 Ruud van Asseldonk
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// A copy of the License has been included in the root of the repository.

// This file contains a minimal example of using Claxon to read metadata tags
// (also called Vorbis comments) from a flac file. It behaves similarly to
// `metaflac --block-type=VORBIS_COMMENT --list <file>`.

extern crate claxon;

use std::env;

fn main() {
    for fname in env::args().skip(1) {
        let reader = claxon::FlacReader::open(&fname).expect("failed to open FLAC stream");

        // We can use `tags()` to iterate over all tags. When looking for a
        // specific tag, `get_tag()` may be useful instead.
        for (name, value) in reader.tags() {
            // Print comments in a format similar to what
            // `metaflac --block-type=VORBIS_COMMENT --list` would print.
            println!("{}: {}={}", fname, name, value);
        }
    }
}
<|endoftext|>


<commit_before>extern crate whois;
extern crate rustc_serialize;

use whois::WhoIs;
use rustc_serialize::json::Json;

fn main() {
    let data = WhoIs::new("google.com".to_owned()).lookup();
    let foo = &Json::from_str(&data).unwrap();
    let object = foo.as_object().unwrap();
    for (key, value) in object {
        println!("{}: {}", key, match *value {
            Json::String(ref v) => format!("{}", v),
            _ => break
        });
    }
}
<commit_msg>Update test.rs<commit_after>extern crate whois;
extern crate rustc_serialize;

use whois::WhoIs;
use rustc_serialize::json::Json;

fn main() {
    let data = WhoIs::new("google.com".to_owned()).lookup();
    let foo = &Json::from_str(&data.unwrap()).unwrap();
    let object = foo.as_object().unwrap();
    for (key, value) in object {
        println!("{}: {}", key, match *value {
            Json::String(ref v) => format!("{}", v),
            _ => break
        });
    }
}
<|endoftext|>


<commit_before>/// Multiclass analyses of the iris dataset build on binary logistic classifaction
///
/// Also demonstrates online training, and usage of custom feature type
extern crate csv;
extern crate vikos;
extern crate rustc_serialize;

use vikos::{Teacher, Training, Model};
use std::default::Default;

const PATH : &'static str = "examples/data/iris.csv";

/// A custom type used to hold all features
#[derive(Clone, Default, RustcDecodable)]
struct Features{
    sepal_length : f64,
    sepal_width : f64,
    petal_length : f64,
    petal_width : f64
}

//trait required by `vikos::model::Logistic`
impl vikos::linear_algebra::Vector for Features{
    type Scalar = f64;

    fn dimension(&self) -> usize{
        4
    }

    fn at(&self, index : usize) -> f64{
        match index{
            0 => self.sepal_length,
            1 => self.sepal_width,
            2 => self.petal_length,
            3 => self.petal_width,
            _ => panic!("out of bounds")
        }
    }

    fn mut_at(&mut self, index : usize) -> & mut f64{
        match index{
            0 => &mut self.sepal_length,
            1 => &mut self.sepal_width,
            2 => &mut self.petal_length,
            3 => &mut self.petal_width,
            _ => panic!("out of bounds")
        }
    }
}

fn main() {

    let teacher = vikos::teacher::Nesterov{l0 : 0.0001, t: 1000.0, inertia: 0.99};
    let cost = vikos::cost::MaxLikelihood{};

    // We train three binary classifiers. One for each specis of iris.
    // Each of this classifiers will tell us the propability of an
    // observation belonging to its particular class
    let mut setosa = vikos::model::Logistic::default();
    let mut versicolor = vikos::model::Logistic::default();
    let mut virginica = vikos::model::Logistic::default();

    // Each of the classifieres has its own training state
    let mut train_setosa = teacher.new_training(&setosa);
    let mut train_versicolor = teacher.new_training(&versicolor);
    let mut train_virginica = teacher.new_training(&virginica);

    // read iris Data
    for epoch in 0..300{
        let mut rdr = csv::Reader::from_file(PATH).expect("File is ok");
        let mut hit = 0;
        let mut miss = 0;

        for row in rdr.decode() {

            //learn event
            let (truth, features) : (String, Features) = row.unwrap();
            train_setosa.teach_event(&cost, &mut setosa, &features, truth == "setosa");
            train_versicolor.teach_event(&cost, &mut versicolor, &features, truth == "versicolor");
            train_virginica.teach_event(&cost, &mut virginica, &features, truth == "virginica");

            //make prediction using current expertise
            let p_setosa = setosa.predict(&features);
            let p_versicolor = versicolor.predict(&features);
            let p_virginica = virginica.predict(&features);
            let prediction = if p_setosa > p_versicolor {
                if p_setosa > p_virginica { "setosa" } else { "virginica" }
            } else {
                if p_versicolor > p_virginica { "versicolor" } else { "virginica" }
            };

            if prediction == truth{
                hit += 1;
            } else {
                miss += 1;
            }
        }
        let accuracy = hit as f64 / (hit + miss) as f64;

        println!("epoch: {}, accuracy: {}", epoch, accuracy);
    }
}
<commit_msg>all comments start now with caps<commit_after>/// Multiclass analyses of the iris dataset build on binary logistic classifaction
///
/// Also demonstrates online training, and usage of custom feature type
extern crate csv;
extern crate vikos;
extern crate rustc_serialize;

use vikos::{Teacher, Training, Model};
use std::default::Default;

const PATH : &'static str = "examples/data/iris.csv";

/// A custom type used to hold all features
#[derive(Clone, Default, RustcDecodable)]
struct Features{
    sepal_length : f64,
    sepal_width : f64,
    petal_length : f64,
    petal_width : f64
}

// Trait required by `vikos::model::Logistic`
impl vikos::linear_algebra::Vector for Features{
    type Scalar = f64;

    fn dimension(&self) -> usize{
        4
    }

    fn at(&self, index : usize) -> f64{
        match index{
            0 => self.sepal_length,
            1 => self.sepal_width,
            2 => self.petal_length,
            3 => self.petal_width,
            _ => panic!("out of bounds")
        }
    }

    fn mut_at(&mut self, index : usize) -> & mut f64{
        match index{
            0 => &mut self.sepal_length,
            1 => &mut self.sepal_width,
            2 => &mut self.petal_length,
            3 => &mut self.petal_width,
            _ => panic!("out of bounds")
        }
    }
}

fn main() {

    let teacher = vikos::teacher::Nesterov{l0 : 0.0001, t: 1000.0, inertia: 0.99};
    let cost = vikos::cost::MaxLikelihood{};

    // We train three binary classifiers. One for each specis of iris.
    // Each of this classifiers will tell us the propability of an
    // observation belonging to its particular class
    let mut setosa = vikos::model::Logistic::default();
    let mut versicolor = vikos::model::Logistic::default();
    let mut virginica = vikos::model::Logistic::default();

    // Each of the classifieres has its own training state
    let mut train_setosa = teacher.new_training(&setosa);
    let mut train_versicolor = teacher.new_training(&versicolor);
    let mut train_virginica = teacher.new_training(&virginica);

    // Read iris Data
    for epoch in 0..300{
        let mut rdr = csv::Reader::from_file(PATH).expect("File is ok");
        let mut hit = 0;
        let mut miss = 0;

        for row in rdr.decode() {

            // Learn event
            let (truth, features) : (String, Features) = row.unwrap();
            train_setosa.teach_event(&cost, &mut setosa, &features, truth == "setosa");
            train_versicolor.teach_event(&cost, &mut versicolor, &features, truth == "versicolor");
            train_virginica.teach_event(&cost, &mut virginica, &features, truth == "virginica");

            // Make prediction using current expertise
            let p_setosa = setosa.predict(&features);
            let p_versicolor = versicolor.predict(&features);
            let p_virginica = virginica.predict(&features);
            let prediction = if p_setosa > p_versicolor {
                if p_setosa > p_virginica { "setosa" } else { "virginica" }
            } else {
                if p_versicolor > p_virginica { "versicolor" } else { "virginica" }
            };

            if prediction == truth{
                hit += 1;
            } else {
                miss += 1;
            }
        }
        let accuracy = hit as f64 / (hit + miss) as f64;

        println!("epoch: {}, accuracy: {}", epoch, accuracy);
    }
}
<|endoftext|>


<commit_before>#[macro_use]
extern crate glium;
extern crate isosurface;
extern crate ndarray;

use ndarray::Array;
use isosurface::marching_tetrahedra;
use glium::glutin;

mod support;

mod surface {
    use glium;
    use glium::backend::Facade;
    use support;
    use std;

    #[derive(Copy, Clone)]
    struct Vertex {
        position: [f32; 3],
        color: [f32; 3],
        normal: [f32; 3],
    }

    implement_vertex!(Vertex, position, color, normal);

    pub struct Surface {
        verts: glium::VertexBuffer<Vertex>,
        indices: glium::IndexBuffer<u32>,
        program: glium::Program,
        normal_program: glium::Program,
        model: [[f32; 4]; 4],
    }

    impl Surface {
        pub fn new<F: Facade>(facade: &F,
                              verts: &[[f64; 3]],
                              faces: &[[u32; 3]],
                              normals: &[[f64; 3]])
                              -> Surface {

            // compute the bounding box
            let mut xmin = std::f64::MAX;
            let mut ymin = std::f64::MAX;
            let mut zmin = std::f64::MAX;
            let mut xmax = std::f64::MIN;
            let mut ymax = std::f64::MIN;
            let mut zmax = std::f64::MIN;

            for v in verts {
                xmin = xmin.min(v[0]);
                ymin = ymin.min(v[1]);
                zmin = zmin.min(v[2]);
                xmax = xmax.max(v[0]);
                ymax = ymax.max(v[1]);
                zmax = zmax.max(v[2]);
            }

            let cx = ((xmax + xmin) / 2.) as f32;
            let cy = ((ymax + ymin) / 2.) as f32;
            let cz = ((zmax + zmin) / 2.) as f32;
            let sx = ((xmax - xmin) / 2.) as f32;
            let sy = ((ymax - ymin) / 2.) as f32;
            let sz = ((zmax - zmin) / 2.) as f32;

            // center the object and scale to max size 1 in any direction
            let scale = 1. / sx.max(sy).max(sz);
            let model = [[scale, 0.0, 0.0, 0.0],
                         [0.0, scale, 0.0, 0.0],
                         [0.0, 0.0, scale, 0.0],
                         [-scale * cx, -scale * cy, -scale * cz, 1.0f32]];

            let verts = {

                let verts: Vec<_> = verts.iter()
                    .zip(normals.iter())
                    .map(|(v, n)| {
                        Vertex {
                            position: [v[0] as f32, v[1] as f32, v[2] as f32],
                            color: [1.0, 0.0, 0.0],
                            normal: [n[0] as f32, n[1] as f32, n[2] as f32],
                        }
                    })
                    .collect();
                glium::VertexBuffer::new(facade, &verts).unwrap()
            };

            let indices = {
                let mut buf = Vec::with_capacity(faces.len() * 3);
                for i in faces {
                    buf.extend_from_slice(i);
                }
                glium::IndexBuffer::new(facade, glium::index::PrimitiveType::TrianglesList, &buf)
                    .unwrap()
            };

            let vertex_shader_src = r#"
        #version 150

        in vec3 position;
        in vec3 normal;

        out vec3 v_normal;
        out vec3 v_position;

        uniform mat4 perspective;
        uniform mat4 view;
        uniform mat4 model;

        void main() {
            mat4 modelview = view * model;
            v_normal = transpose(inverse(mat3(modelview))) * normal;
            gl_Position = perspective * modelview * vec4(position, 1.0);
            v_position = gl_Position.xyz / gl_Position.w;
        }
    "#;

            let fragment_shader_src = r#"
        #version 150

        in vec3 v_normal;
        in vec3 v_position;

        out vec4 color;

        uniform vec3 u_light;

        const vec3 ambient_color = vec3(0.2, 0.0, 0.0);
        const vec3 diffuse_color = vec3(0.6, 0.0, 0.0);
        const vec3 specular_color = vec3(1.0, 1.0, 1.0);

        void main() {
            float diffuse = max(dot(normalize(v_normal), normalize(u_light)), 0.0);

            vec3 camera_dir = normalize(v_position);
            vec3 half_direction = normalize(normalize(u_light) + camera_dir);
            float specular = pow(max(dot(half_direction, normalize(v_normal)), 0.0), 16.0);

            color = vec4(ambient_color + diffuse * diffuse_color + specular * specular_color, 1.0);
        }
    "#;

            let program =
                glium::Program::from_source(facade, vertex_shader_src, fragment_shader_src, None)
                    .unwrap();

            let normal_vertex_shader_src = r#"
    #version 150
    in vec3 position;
    in vec3 normal;

    out Vertex
    {
      vec3 normal;
    } vertex;

    void main()
    {
      gl_Position = vec4(position, 1.0);
      vertex.normal = normal;
    }
    "#;

            let normal_geometry_shader_src = r#"
    #version 150
    layout(triangles) in;

    // Three lines will be generated: 6 vertices
    layout(line_strip, max_vertices=6) out;

    uniform float normal_length;
    uniform mat4 perspective;
    uniform mat4 view;
    uniform mat4 model;

    in Vertex
    {
      vec3 normal;
    } vertex[];

    out vec4 vertex_color;

    void main()
    {
      int i;
      mat4 matrix = perspective * view * model;
      for(i=0; i < gl_in.length(); i++)
      {
        vec3 p = gl_in[i].gl_Position.xyz;
        vec3 n = vertex[i].normal;

        gl_Position =  matrix * vec4(p, 1.0);
        EmitVertex();

        gl_Position = matrix * vec4(p + n * normal_length, 1.0);
        EmitVertex();

        EndPrimitive();
      }
    }
            "#;

            let normal_fragment_shader_src = r#"
        #version 150

        const vec4 normal_color = vec4(0.0, 1.0, 0.0, 1.0);
        out vec4 color;

        void main() {
            color = normal_color;
        }
    "#;

            let normal_program = glium::Program::from_source(facade,
                                                             normal_vertex_shader_src,
                                                             normal_fragment_shader_src,
                                                             Some(normal_geometry_shader_src))
                .unwrap();
            Surface {
                verts: verts,
                indices: indices,
                program: program,
                normal_program: normal_program,
                model: model,
            }
        }

        pub fn draw<S: glium::Surface>(&self,
                                       target: &mut S,
                                       camera: &support::camera::CameraState,
                                       wireframe: bool,
                                       normals: bool)
                                       -> Result<(), glium::DrawError> {
            let light = [1., 1., 1.0f32];
            // let light = [1.4, 0.4, -0.7f32];

            let params = glium::DrawParameters {
                depth: glium::Depth {
                    test: glium::draw_parameters::DepthTest::IfLess,
                    write: true,
                    ..Default::default()
                },
                polygon_mode: if wireframe {
                    glium::draw_parameters::PolygonMode::Line
                } else {
                    glium::draw_parameters::PolygonMode::Fill
                },
                line_width: Some(3.),
                // backface_culling: glium::draw_parameters::BackfaceCullingMode::CullClockWise,
                ..Default::default()
            };

            try!(target.draw(&self.verts,
                             &self.indices,
                             &self.program,
                             &uniform! { model: self.model,
                                view: camera.get_view(),
                                perspective: camera.get_perspective(),
                                u_light: light },
                             &params));
            if normals {

                try!(target.draw(&self.verts,
                                 &self.indices,
                                 &self.normal_program,
                                 &uniform! { model: self.model,
                                view: camera.get_view(),
                                perspective: camera.get_perspective(),
                                normal_length: 1f32 },
                                 &params));
            }

            Ok(())

        }
    }

}

fn main() {
    let res = 10;
    let xs = Array::linspace(-0.5, 0.5, res);
    let ys = Array::linspace(-0.5, 0.5, res);
    let zs = Array::linspace(-0.5, 0.5, res);

    let dim = (xs.len(), ys.len(), zs.len());

    let u = {
        let mut u = Array::from_elem(dim, 0.);

        let r = 0.4;
        for ((i, j, k), u) in u.indexed_iter_mut() {
            let (x, y, z) = (xs[i], ys[j], zs[k]);
            *u = x * x + y * y + z * z - r * r;
        }
        u
    };

    let level = 0.0;
    let (verts, faces, normals) = marching_tetrahedra(u.as_slice().unwrap(), dim, level);

    use glium::{DisplayBuild, Surface};
    let display = glium::glutin::WindowBuilder::new()
        .with_depth_buffer(24)
        .build_glium()
        .unwrap();

    let surface = surface::Surface::new(&display, &verts, &faces, &normals);

    let mut camera = support::camera::CameraState::new();
    let mut wireframe = false;
    let mut show_normals = false;

    loop {
        camera.update();

        let mut target = display.draw();
        target.clear_color_and_depth((0.0, 0.0, 0.0, 1.0), 1.0);

        surface.draw(&mut target, &camera, wireframe, show_normals).unwrap();

        target.finish().unwrap();

        for ev in display.poll_events() {
            match ev {
                glium::glutin::Event::Closed => return,
                glutin::Event::KeyboardInput(glutin::ElementState::Pressed,
                                             _,
                                             Some(glutin::VirtualKeyCode::F)) => {
                    wireframe = !wireframe
                }
                glutin::Event::KeyboardInput(glutin::ElementState::Pressed,
                                             _,
                                             Some(glutin::VirtualKeyCode::N)) => {
                    show_normals = !show_normals
                }
                ev => camera.process_input(&ev),
            }
        }
    }
}
<commit_msg>Normalize normals<commit_after>#[macro_use]
extern crate glium;
extern crate isosurface;
extern crate ndarray;

use ndarray::Array;
use isosurface::marching_tetrahedra;
use glium::glutin;

mod support;

mod surface {
    use glium;
    use glium::backend::Facade;
    use support;
    use std;

    #[derive(Copy, Clone)]
    struct Vertex {
        position: [f32; 3],
        color: [f32; 3],
        normal: [f32; 3],
    }

    implement_vertex!(Vertex, position, color, normal);

    pub struct Surface {
        verts: glium::VertexBuffer<Vertex>,
        indices: glium::IndexBuffer<u32>,
        program: glium::Program,
        normal_program: glium::Program,
        model: [[f32; 4]; 4],
    }

    impl Surface {
        pub fn new<F: Facade>(facade: &F,
                              verts: &[[f64; 3]],
                              faces: &[[u32; 3]],
                              normals: &[[f64; 3]])
                              -> Surface {

            // compute the bounding box
            let mut xmin = std::f64::MAX;
            let mut ymin = std::f64::MAX;
            let mut zmin = std::f64::MAX;
            let mut xmax = std::f64::MIN;
            let mut ymax = std::f64::MIN;
            let mut zmax = std::f64::MIN;

            for v in verts {
                xmin = xmin.min(v[0]);
                ymin = ymin.min(v[1]);
                zmin = zmin.min(v[2]);
                xmax = xmax.max(v[0]);
                ymax = ymax.max(v[1]);
                zmax = zmax.max(v[2]);
            }

            let cx = ((xmax + xmin) / 2.) as f32;
            let cy = ((ymax + ymin) / 2.) as f32;
            let cz = ((zmax + zmin) / 2.) as f32;
            let sx = ((xmax - xmin) / 2.) as f32;
            let sy = ((ymax - ymin) / 2.) as f32;
            let sz = ((zmax - zmin) / 2.) as f32;

            // center the object and scale to max size 1 in any direction
            let scale = 1. / sx.max(sy).max(sz);
            let model = [[scale, 0.0, 0.0, 0.0],
                         [0.0, scale, 0.0, 0.0],
                         [0.0, 0.0, scale, 0.0],
                         [-scale * cx, -scale * cy, -scale * cz, 1.0f32]];

            let verts = {

                let verts: Vec<_> = verts.iter()
                    .zip(normals.iter())
                    .map(|(v, n)| {
                        Vertex {
                            position: [v[0] as f32, v[1] as f32, v[2] as f32],
                            color: [1.0, 0.0, 0.0],
                            normal: [n[0] as f32, n[1] as f32, n[2] as f32],
                        }
                    })
                    .collect();
                glium::VertexBuffer::new(facade, &verts).unwrap()
            };

            let indices = {
                let mut buf = Vec::with_capacity(faces.len() * 3);
                for i in faces {
                    buf.extend_from_slice(i);
                }
                glium::IndexBuffer::new(facade, glium::index::PrimitiveType::TrianglesList, &buf)
                    .unwrap()
            };

            let vertex_shader_src = r#"
        #version 150

        in vec3 position;
        in vec3 normal;

        out vec3 v_normal;
        out vec3 v_position;

        uniform mat4 perspective;
        uniform mat4 view;
        uniform mat4 model;

        void main() {
            mat4 modelview = view * model;
            v_normal = transpose(inverse(mat3(modelview))) * normal;
            gl_Position = perspective * modelview * vec4(position, 1.0);
            v_position = gl_Position.xyz / gl_Position.w;
        }
    "#;

            let fragment_shader_src = r#"
        #version 150

        in vec3 v_normal;
        in vec3 v_position;

        out vec4 color;

        uniform vec3 u_light;

        const vec3 ambient_color = vec3(0.2, 0.0, 0.0);
        const vec3 diffuse_color = vec3(0.6, 0.0, 0.0);
        const vec3 specular_color = vec3(1.0, 1.0, 1.0);

        void main() {
            float diffuse = max(dot(normalize(v_normal), normalize(u_light)), 0.0);

            vec3 camera_dir = normalize(v_position);
            vec3 half_direction = normalize(normalize(u_light) + camera_dir);
            float specular = pow(max(dot(half_direction, normalize(v_normal)), 0.0), 16.0);

            color = vec4(ambient_color + diffuse * diffuse_color + specular * specular_color, 1.0);
        }
    "#;

            let program =
                glium::Program::from_source(facade, vertex_shader_src, fragment_shader_src, None)
                    .unwrap();

            let normal_vertex_shader_src = r#"
    #version 150
    in vec3 position;
    in vec3 normal;

    out Vertex
    {
      vec3 normal;
    } vertex;

    void main()
    {
      gl_Position = vec4(position, 1.0);
      vertex.normal = normal;
    }
    "#;

            let normal_geometry_shader_src = r#"
    #version 150
    layout(triangles) in;

    // Three lines will be generated: 6 vertices
    layout(line_strip, max_vertices=6) out;

    uniform float normal_length;
    uniform mat4 perspective;
    uniform mat4 view;
    uniform mat4 model;

    in Vertex
    {
      vec3 normal;
    } vertex[];

    out vec4 vertex_color;

    void main()
    {
      int i;
      mat4 matrix = perspective * view * model;
      for(i=0; i < gl_in.length(); i++)
      {
        vec3 p = gl_in[i].gl_Position.xyz;
        vec3 n = normalize(vertex[i].normal);

        gl_Position =  matrix * vec4(p, 1.0);
        EmitVertex();

        gl_Position = matrix * vec4(p + n * normal_length, 1.0);
        EmitVertex();

        EndPrimitive();
      }
    }
            "#;

            let normal_fragment_shader_src = r#"
        #version 150

        const vec4 normal_color = vec4(0.0, 1.0, 0.0, 1.0);
        out vec4 color;

        void main() {
            color = normal_color;
        }
    "#;

            let normal_program = glium::Program::from_source(facade,
                                                             normal_vertex_shader_src,
                                                             normal_fragment_shader_src,
                                                             Some(normal_geometry_shader_src))
                .unwrap();
            Surface {
                verts: verts,
                indices: indices,
                program: program,
                normal_program: normal_program,
                model: model,
            }
        }

        pub fn draw<S: glium::Surface>(&self,
                                       target: &mut S,
                                       camera: &support::camera::CameraState,
                                       wireframe: bool,
                                       normals: bool)
                                       -> Result<(), glium::DrawError> {
            let light = [1., 1., 1.0f32];
            // let light = [1.4, 0.4, -0.7f32];

            let params = glium::DrawParameters {
                depth: glium::Depth {
                    test: glium::draw_parameters::DepthTest::IfLess,
                    write: true,
                    ..Default::default()
                },
                polygon_mode: if wireframe {
                    glium::draw_parameters::PolygonMode::Line
                } else {
                    glium::draw_parameters::PolygonMode::Fill
                },
                line_width: Some(3.),
                // backface_culling: glium::draw_parameters::BackfaceCullingMode::CullClockWise,
                ..Default::default()
            };

            try!(target.draw(&self.verts,
                             &self.indices,
                             &self.program,
                             &uniform! { model: self.model,
                                view: camera.get_view(),
                                perspective: camera.get_perspective(),
                                u_light: light },
                             &params));
            if normals {

                try!(target.draw(&self.verts,
                                 &self.indices,
                                 &self.normal_program,
                                 &uniform! { model: self.model,
                                view: camera.get_view(),
                                perspective: camera.get_perspective(),
                                normal_length: 1f32 },
                                 &params));
            }

            Ok(())

        }
    }

}

fn main() {
    let res = 10;
    let xs = Array::linspace(-0.5, 0.5, res);
    let ys = Array::linspace(-0.5, 0.5, res);
    let zs = Array::linspace(-0.5, 0.5, res);

    let dim = (xs.len(), ys.len(), zs.len());

    let u = {
        let mut u = Array::from_elem(dim, 0.);

        let r = 0.4;
        for ((i, j, k), u) in u.indexed_iter_mut() {
            let (x, y, z) = (xs[i], ys[j], zs[k]);
            *u = x * x + y * y + z * z - r * r;
        }
        u
    };

    let level = 0.0;
    let (verts, faces, normals) = marching_tetrahedra(u.as_slice().unwrap(), dim, level);

    use glium::{DisplayBuild, Surface};
    let display = glium::glutin::WindowBuilder::new()
        .with_depth_buffer(24)
        .build_glium()
        .unwrap();

    let surface = surface::Surface::new(&display, &verts, &faces, &normals);

    let mut camera = support::camera::CameraState::new();
    let mut wireframe = false;
    let mut show_normals = false;

    loop {
        camera.update();

        let mut target = display.draw();
        target.clear_color_and_depth((0.0, 0.0, 0.0, 1.0), 1.0);

        surface.draw(&mut target, &camera, wireframe, show_normals).unwrap();

        target.finish().unwrap();

        for ev in display.poll_events() {
            match ev {
                glium::glutin::Event::Closed => return,
                glutin::Event::KeyboardInput(glutin::ElementState::Pressed,
                                             _,
                                             Some(glutin::VirtualKeyCode::F)) => {
                    wireframe = !wireframe
                }
                glutin::Event::KeyboardInput(glutin::ElementState::Pressed,
                                             _,
                                             Some(glutin::VirtualKeyCode::N)) => {
                    show_normals = !show_normals
                }
                ev => camera.process_input(&ev),
            }
        }
    }
}
<|endoftext|>


<commit_before>use cpu::common_defs::OpcodeExecInfo;
use cpu::CpuState;
use cpu::DecodeRegister;
use cpu::common_defs::address_mode::AddressMode;
use memory::Memory;
use std::collections::HashMap;

pub struct CpuExecutor {
    op_table: HashMap<u8,OpcodeExecInfo>,
}

impl CpuExecutor {
    pub fn new(opcodes: Vec<OpcodeExecInfo> ) -> CpuExecutor {
        // Construct the HashMap and copy it over to CpuExecutor's constructor.
        let mut op_table_temp: HashMap<u8, OpcodeExecInfo> = HashMap::new();
        for oc in opcodes {
            if op_table_temp.contains_key(&oc.opcode) {
                println!("Encountered duplicate opcode: {:#x}", oc.opcode);
                println!("Replacing previous opcode, which was {{ opcode: {:#x}, len: {}, cycles: {}, page_cycles: {} }}", oc.opcode, oc.len, oc.cycles, oc.page_cycles);
            }
            op_table_temp.insert(oc.opcode, oc);
        }

        CpuExecutor {
            op_table: op_table_temp,
        }
    }

    pub fn reset(self: &CpuExecutor, cpu_state: &mut CpuState, mem:&mut Memory) {
        cpu_state.pc = mem.read16(0xFFFC).unwrap();
        cpu_state.sp = 0xFD;
        cpu_state.pack_flags(0x24);
    }

    pub fn fetch_and_decode(self: &CpuExecutor, cpu_state: &mut CpuState,mem:&mut Memory) {
        cpu_state.instruction_register = mem.read8(cpu_state.pc).unwrap();
        cpu_state.decode_register = self.decode(cpu_state,mem);

        cpu_state.pc = cpu_state.pc + cpu_state.decode_register.info.len as u16;
    }
    pub fn execute(self: &CpuExecutor, mut cpu_state: &CpuState,mut mem:&Memory) {
    }
    pub fn step(self: &CpuExecutor, cpu_state: &mut CpuState,mem:&mut Memory) {
        self.fetch_and_decode(cpu_state,mem);
        self.execute(cpu_state,mem);
    }

    fn decode(self: &CpuExecutor, cpu_state: &CpuState, mem: &Memory) -> DecodeRegister {
        let mut dr = DecodeRegister {
            info : self.op_table[&cpu_state.instruction_register].clone(),
            ..Default::default()
        };
        match dr.info.address_mode {
            AddressMode::Absolute => {
                dr.addr_final  = Some(mem.read16(cpu_state.pc+1).unwrap());
                dr.value_final = Some(mem.read8(dr.addr_final.unwrap()).unwrap());
            },
            AddressMode::AbsoluteX       => {
                dr.addr_final  = Some(mem.read16(cpu_state.pc+1).unwrap() + cpu_state.x as u16);
                dr.value_final = Some(mem.read8(dr.addr_final.unwrap()).unwrap());
            },
            AddressMode::AbsoluteY       => {
                dr.addr_final  = Some(mem.read16(cpu_state.pc+1).unwrap() + cpu_state.y as u16);
                dr.value_final = Some(mem.read8(dr.addr_final.unwrap()).unwrap());
            },
            AddressMode::Accumulator     => { },
            AddressMode::Immediate       => {
                dr.addr_final  = Some(cpu_state.pc+1);
                dr.value_final = Some(mem.read8(dr.addr_final.unwrap()).unwrap());
            },
            AddressMode::Implied         => { },
            AddressMode::Indirect        => {
                dr.addr_final  = Some(mem.read16(cpu_state.pc+1).unwrap());
            },
            //AddressMode::IndexedIndirect => { },
            //AddressMode::IndirectIndexed => { },
            AddressMode::Relative        => {
                dr.addr_final  = Some(cpu_state.pc+1);
                dr.value_final = Some(mem.read8(dr.addr_final.unwrap()).unwrap());
            },
            AddressMode::ZeroPage        => {
                dr.addr_final  = Some(mem.read8(cpu_state.pc+1).unwrap() as u16);
                dr.value_final = Some(mem.read8(dr.addr_final.unwrap()).unwrap());
            },
            AddressMode::ZeroPageX       => {
                dr.addr_final  = Some( (mem.read8(cpu_state.pc+1).unwrap() + cpu_state.x) as u16);
                dr.value_final = Some(mem.read8(dr.addr_final.unwrap()).unwrap());
            },
            AddressMode::ZeroPageY       => {
                dr.addr_final  = Some( (mem.read8(cpu_state.pc+1).unwrap() + cpu_state.y) as u16);
                dr.value_final = Some(mem.read8(dr.addr_final.unwrap()).unwrap());
            },
            _ => panic!("unrecognized addressing mode while decoding instruction_register!")
        }

        return dr;
    }
}

<commit_msg>fixed implementation of Indirect Addressing Mode<commit_after>use cpu::common_defs::OpcodeExecInfo;
use cpu::CpuState;
use cpu::DecodeRegister;
use cpu::common_defs::address_mode::AddressMode;
use memory::Memory;
use std::collections::HashMap;

pub struct CpuExecutor {
    op_table: HashMap<u8,OpcodeExecInfo>,
}

impl CpuExecutor {
    pub fn new(opcodes: Vec<OpcodeExecInfo> ) -> CpuExecutor {
        // Construct the HashMap and copy it over to CpuExecutor's constructor.
        let mut op_table_temp: HashMap<u8, OpcodeExecInfo> = HashMap::new();
        for oc in opcodes {
            if op_table_temp.contains_key(&oc.opcode) {
                println!("Encountered duplicate opcode: {:#x}", oc.opcode);
                println!("Replacing previous opcode, which was {{ opcode: {:#x}, len: {}, cycles: {}, page_cycles: {} }}", oc.opcode, oc.len, oc.cycles, oc.page_cycles);
            }
            op_table_temp.insert(oc.opcode, oc);
        }

        CpuExecutor {
            op_table: op_table_temp,
        }
    }

    pub fn reset(self: &CpuExecutor, cpu_state: &mut CpuState, mem:&mut Memory) {
        cpu_state.pc = mem.read16(0xFFFC).unwrap();
        cpu_state.sp = 0xFD;
        cpu_state.pack_flags(0x24);
    }

    pub fn fetch_and_decode(self: &CpuExecutor, cpu_state: &mut CpuState,mem:&mut Memory) {
        cpu_state.instruction_register = mem.read8(cpu_state.pc).unwrap();
        cpu_state.decode_register = self.decode(cpu_state,mem);

        cpu_state.pc = cpu_state.pc + cpu_state.decode_register.info.len as u16;
    }
    pub fn execute(self: &CpuExecutor, mut cpu_state: &CpuState,mut mem:&Memory) {
    }
    pub fn step(self: &CpuExecutor, cpu_state: &mut CpuState,mem:&mut Memory) {
        self.fetch_and_decode(cpu_state,mem);
        self.execute(cpu_state,mem);
    }

    fn decode(self: &CpuExecutor, cpu_state: &CpuState, mem: &Memory) -> DecodeRegister {
        let mut dr = DecodeRegister {
            info : self.op_table[&cpu_state.instruction_register].clone(),
            ..Default::default()
        };
        match dr.info.address_mode {
            AddressMode::Absolute => {
                dr.addr_final  = Some(mem.read16(cpu_state.pc+1).unwrap());
                dr.value_final = Some(mem.read8(dr.addr_final.unwrap()).unwrap());
            },
            AddressMode::AbsoluteX       => {
                dr.addr_final  = Some(mem.read16(cpu_state.pc+1).unwrap() + cpu_state.x as u16);
                dr.value_final = Some(mem.read8(dr.addr_final.unwrap()).unwrap());
            },
            AddressMode::AbsoluteY       => {
                dr.addr_final  = Some(mem.read16(cpu_state.pc+1).unwrap() + cpu_state.y as u16);
                dr.value_final = Some(mem.read8(dr.addr_final.unwrap()).unwrap());
            },
            AddressMode::Accumulator     => { },
            AddressMode::Immediate       => {
                dr.addr_final  = Some(cpu_state.pc+1);
                dr.value_final = Some(mem.read8(dr.addr_final.unwrap()).unwrap());
            },
            AddressMode::Implied         => { },
            AddressMode::Indirect        => {
                dr.addr_final  = Some(mem.read16(mem.read16(cpu_state.pc+1).unwrap()).unwrap());
            },
            //AddressMode::IndexedIndirect => { },
            //AddressMode::IndirectIndexed => { },
            AddressMode::Relative        => {
                dr.addr_final  = Some(cpu_state.pc+1);
                dr.value_final = Some(mem.read8(dr.addr_final.unwrap()).unwrap());
            },
            AddressMode::ZeroPage        => {
                dr.addr_final  = Some(mem.read8(cpu_state.pc+1).unwrap() as u16);
                dr.value_final = Some(mem.read8(dr.addr_final.unwrap()).unwrap());
            },
            AddressMode::ZeroPageX       => {
                dr.addr_final  = Some( (mem.read8(cpu_state.pc+1).unwrap() + cpu_state.x) as u16);
                dr.value_final = Some(mem.read8(dr.addr_final.unwrap()).unwrap());
            },
            AddressMode::ZeroPageY       => {
                dr.addr_final  = Some( (mem.read8(cpu_state.pc+1).unwrap() + cpu_state.y) as u16);
                dr.value_final = Some(mem.read8(dr.addr_final.unwrap()).unwrap());
            },
            _ => panic!("unrecognized addressing mode while decoding instruction_register!")
        }

        return dr;
    }
}

<|endoftext|>


<commit_before>// Copyright 2018 The Grin Developers
//
// 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.

//! High level JSON/HTTP client API

use crate::rest::{Error, ErrorKind};
use crate::util::to_base64;
use failure::{Fail, ResultExt};
use futures::future::{err, ok, Either};
use http::uri::{InvalidUri, Uri};
use hyper::header::{ACCEPT, AUTHORIZATION, USER_AGENT};
use hyper::rt::{Future, Stream};
use hyper::{Body, Client, Request};
use hyper_rustls;
use serde::{Deserialize, Serialize};
use serde_json;
use tokio::runtime::Runtime;

pub type ClientResponseFuture<T> = Box<dyn Future<Item = T, Error = Error> + Send>;

/// Helper function to easily issue a HTTP GET request against a given URL that
/// returns a JSON object. Handles request building, JSON deserialization and
/// response code checking.
pub fn get<'a, T>(url: &'a str, api_secret: Option<String>) -> Result<T, Error>
where
	for<'de> T: Deserialize<'de>,
{
	handle_request(build_request(url, "GET", api_secret, None)?)
}

/// Helper function to easily issue an async HTTP GET request against a given
/// URL that returns a future. Handles request building, JSON deserialization
/// and response code checking.
pub fn get_async<'a, T>(url: &'a str, api_secret: Option<String>) -> ClientResponseFuture<T>
where
	for<'de> T: Deserialize<'de> + Send + 'static,
{
	match build_request(url, "GET", api_secret, None) {
		Ok(req) => Box::new(handle_request_async(req)),
		Err(e) => Box::new(err(e)),
	}
}

/// Helper function to easily issue a HTTP GET request
/// on a given URL that returns nothing. Handles request
/// building and response code checking.
pub fn get_no_ret(url: &str, api_secret: Option<String>) -> Result<(), Error> {
	let req = build_request(url, "GET", api_secret, None)?;
	send_request(req)?;
	Ok(())
}

/// Helper function to easily issue a HTTP POST request with the provided JSON
/// object as body on a given URL that returns a JSON object. Handles request
/// building, JSON serialization and deserialization, and response code
/// checking.
pub fn post<IN, OUT>(url: &str, api_secret: Option<String>, input: &IN) -> Result<OUT, Error>
where
	IN: Serialize,
	for<'de> OUT: Deserialize<'de>,
{
	let req = create_post_request(url, api_secret, input)?;
	handle_request(req)
}

/// Helper function to easily issue an async HTTP POST request with the
/// provided JSON object as body on a given URL that returns a future. Handles
/// request building, JSON serialization and deserialization, and response code
/// checking.
pub fn post_async<IN, OUT>(
	url: &str,
	input: &IN,
	api_secret: Option<String>,
) -> ClientResponseFuture<OUT>
where
	IN: Serialize,
	OUT: Send + 'static,
	for<'de> OUT: Deserialize<'de>,
{
	match create_post_request(url, api_secret, input) {
		Ok(req) => Box::new(handle_request_async(req)),
		Err(e) => Box::new(err(e)),
	}
}

/// Helper function to easily issue a HTTP POST request with the provided JSON
/// object as body on a given URL that returns nothing. Handles request
/// building, JSON serialization, and response code
/// checking.
pub fn post_no_ret<IN>(url: &str, api_secret: Option<String>, input: &IN) -> Result<(), Error>
where
	IN: Serialize,
{
	let req = create_post_request(url, api_secret, input)?;
	send_request(req)?;
	Ok(())
}

/// Helper function to easily issue an async HTTP POST request with the
/// provided JSON object as body on a given URL that returns a future. Handles
/// request building, JSON serialization and deserialization, and response code
/// checking.
pub fn post_no_ret_async<IN>(
	url: &str,
	api_secret: Option<String>,
	input: &IN,
) -> ClientResponseFuture<()>
where
	IN: Serialize,
{
	match create_post_request(url, api_secret, input) {
		Ok(req) => Box::new(send_request_async(req).and_then(|_| ok(()))),
		Err(e) => Box::new(err(e)),
	}
}

fn build_request<'a>(
	url: &'a str,
	method: &str,
	api_secret: Option<String>,
	body: Option<String>,
) -> Result<Request<Body>, Error> {
	let uri = url.parse::<Uri>().map_err::<Error, _>(|e: InvalidUri| {
		e.context(ErrorKind::Argument(format!("Invalid url {}", url)))
			.into()
	})?;
	let mut builder = Request::builder();
	if api_secret.is_some() {
		let basic_auth =
			"Basic ".to_string() + &to_base64(&("grin:".to_string() + &api_secret.unwrap()));
		builder.header(AUTHORIZATION, basic_auth);
	}

	builder
		.method(method)
		.uri(uri)
		.header(USER_AGENT, "grin-client")
		.header(ACCEPT, "application/json")
		.body(match body {
			None => Body::empty(),
			Some(json) => json.into(),
		})
		.map_err(|e| {
			ErrorKind::RequestError(format!("Bad request {} {}: {}", method, url, e)).into()
		})
}

fn create_post_request<IN>(
	url: &str,
	api_secret: Option<String>,
	input: &IN,
) -> Result<Request<Body>, Error>
where
	IN: Serialize,
{
	let json = serde_json::to_string(input).context(ErrorKind::Internal(
		"Could not serialize data to JSON".to_owned(),
	))?;
	build_request(url, "POST", api_secret, Some(json))
}

fn handle_request<T>(req: Request<Body>) -> Result<T, Error>
where
	for<'de> T: Deserialize<'de>,
{
	let data = send_request(req)?;
	serde_json::from_str(&data).map_err(|e| {
		e.context(ErrorKind::ResponseError("Cannot parse response".to_owned()))
			.into()
	})
}

fn handle_request_async<T>(req: Request<Body>) -> ClientResponseFuture<T>
where
	for<'de> T: Deserialize<'de> + Send + 'static,
{
	Box::new(send_request_async(req).and_then(|data| {
		serde_json::from_str(&data).map_err(|e| {
			e.context(ErrorKind::ResponseError("Cannot parse response".to_owned()))
				.into()
		})
	}))
}

fn send_request_async(req: Request<Body>) -> Box<dyn Future<Item = String, Error = Error> + Send> {
	let https = hyper_rustls::HttpsConnector::new(1);
	let client = Client::builder().build::<_, Body>(https);
	Box::new(
		client
			.request(req)
			.map_err(|e| ErrorKind::RequestError(format!("Cannot make request: {}", e)).into())
			.and_then(|resp| {
				if !resp.status().is_success() {
					Either::A(err(ErrorKind::RequestError(
						"Wrong response code".to_owned(),
					)
					.into()))
				} else {
					Either::B(
						resp.into_body()
							.map_err(|e| {
								ErrorKind::RequestError(format!("Cannot read response body: {}", e))
									.into()
							})
							.concat2()
							.and_then(|ch| ok(String::from_utf8_lossy(&ch.to_vec()).to_string())),
					)
				}
			}),
	)
}

fn send_request(req: Request<Body>) -> Result<String, Error> {
	let task = send_request_async(req);
	let mut rt = Runtime::new().unwrap();
	Ok(rt.block_on(task)?)
}
<commit_msg>Set Content-Type in API client (#2680)<commit_after>// Copyright 2018 The Grin Developers
//
// 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.

//! High level JSON/HTTP client API

use crate::rest::{Error, ErrorKind};
use crate::util::to_base64;
use failure::{Fail, ResultExt};
use futures::future::{err, ok, Either};
use http::uri::{InvalidUri, Uri};
use hyper::header::{ACCEPT, AUTHORIZATION, CONTENT_TYPE, USER_AGENT};
use hyper::rt::{Future, Stream};
use hyper::{Body, Client, Request};
use hyper_rustls;
use serde::{Deserialize, Serialize};
use serde_json;
use tokio::runtime::Runtime;

pub type ClientResponseFuture<T> = Box<dyn Future<Item = T, Error = Error> + Send>;

/// Helper function to easily issue a HTTP GET request against a given URL that
/// returns a JSON object. Handles request building, JSON deserialization and
/// response code checking.
pub fn get<'a, T>(url: &'a str, api_secret: Option<String>) -> Result<T, Error>
where
	for<'de> T: Deserialize<'de>,
{
	handle_request(build_request(url, "GET", api_secret, None)?)
}

/// Helper function to easily issue an async HTTP GET request against a given
/// URL that returns a future. Handles request building, JSON deserialization
/// and response code checking.
pub fn get_async<'a, T>(url: &'a str, api_secret: Option<String>) -> ClientResponseFuture<T>
where
	for<'de> T: Deserialize<'de> + Send + 'static,
{
	match build_request(url, "GET", api_secret, None) {
		Ok(req) => Box::new(handle_request_async(req)),
		Err(e) => Box::new(err(e)),
	}
}

/// Helper function to easily issue a HTTP GET request
/// on a given URL that returns nothing. Handles request
/// building and response code checking.
pub fn get_no_ret(url: &str, api_secret: Option<String>) -> Result<(), Error> {
	let req = build_request(url, "GET", api_secret, None)?;
	send_request(req)?;
	Ok(())
}

/// Helper function to easily issue a HTTP POST request with the provided JSON
/// object as body on a given URL that returns a JSON object. Handles request
/// building, JSON serialization and deserialization, and response code
/// checking.
pub fn post<IN, OUT>(url: &str, api_secret: Option<String>, input: &IN) -> Result<OUT, Error>
where
	IN: Serialize,
	for<'de> OUT: Deserialize<'de>,
{
	let req = create_post_request(url, api_secret, input)?;
	handle_request(req)
}

/// Helper function to easily issue an async HTTP POST request with the
/// provided JSON object as body on a given URL that returns a future. Handles
/// request building, JSON serialization and deserialization, and response code
/// checking.
pub fn post_async<IN, OUT>(
	url: &str,
	input: &IN,
	api_secret: Option<String>,
) -> ClientResponseFuture<OUT>
where
	IN: Serialize,
	OUT: Send + 'static,
	for<'de> OUT: Deserialize<'de>,
{
	match create_post_request(url, api_secret, input) {
		Ok(req) => Box::new(handle_request_async(req)),
		Err(e) => Box::new(err(e)),
	}
}

/// Helper function to easily issue a HTTP POST request with the provided JSON
/// object as body on a given URL that returns nothing. Handles request
/// building, JSON serialization, and response code
/// checking.
pub fn post_no_ret<IN>(url: &str, api_secret: Option<String>, input: &IN) -> Result<(), Error>
where
	IN: Serialize,
{
	let req = create_post_request(url, api_secret, input)?;
	send_request(req)?;
	Ok(())
}

/// Helper function to easily issue an async HTTP POST request with the
/// provided JSON object as body on a given URL that returns a future. Handles
/// request building, JSON serialization and deserialization, and response code
/// checking.
pub fn post_no_ret_async<IN>(
	url: &str,
	api_secret: Option<String>,
	input: &IN,
) -> ClientResponseFuture<()>
where
	IN: Serialize,
{
	match create_post_request(url, api_secret, input) {
		Ok(req) => Box::new(send_request_async(req).and_then(|_| ok(()))),
		Err(e) => Box::new(err(e)),
	}
}

fn build_request<'a>(
	url: &'a str,
	method: &str,
	api_secret: Option<String>,
	body: Option<String>,
) -> Result<Request<Body>, Error> {
	let uri = url.parse::<Uri>().map_err::<Error, _>(|e: InvalidUri| {
		e.context(ErrorKind::Argument(format!("Invalid url {}", url)))
			.into()
	})?;
	let mut builder = Request::builder();
	if api_secret.is_some() {
		let basic_auth =
			"Basic ".to_string() + &to_base64(&("grin:".to_string() + &api_secret.unwrap()));
		builder.header(AUTHORIZATION, basic_auth);
	}

	builder
		.method(method)
		.uri(uri)
		.header(USER_AGENT, "grin-client")
		.header(ACCEPT, "application/json")
		.header(CONTENT_TYPE, "application/json")
		.body(match body {
			None => Body::empty(),
			Some(json) => json.into(),
		})
		.map_err(|e| {
			ErrorKind::RequestError(format!("Bad request {} {}: {}", method, url, e)).into()
		})
}

fn create_post_request<IN>(
	url: &str,
	api_secret: Option<String>,
	input: &IN,
) -> Result<Request<Body>, Error>
where
	IN: Serialize,
{
	let json = serde_json::to_string(input).context(ErrorKind::Internal(
		"Could not serialize data to JSON".to_owned(),
	))?;
	build_request(url, "POST", api_secret, Some(json))
}

fn handle_request<T>(req: Request<Body>) -> Result<T, Error>
where
	for<'de> T: Deserialize<'de>,
{
	let data = send_request(req)?;
	serde_json::from_str(&data).map_err(|e| {
		e.context(ErrorKind::ResponseError("Cannot parse response".to_owned()))
			.into()
	})
}

fn handle_request_async<T>(req: Request<Body>) -> ClientResponseFuture<T>
where
	for<'de> T: Deserialize<'de> + Send + 'static,
{
	Box::new(send_request_async(req).and_then(|data| {
		serde_json::from_str(&data).map_err(|e| {
			e.context(ErrorKind::ResponseError("Cannot parse response".to_owned()))
				.into()
		})
	}))
}

fn send_request_async(req: Request<Body>) -> Box<dyn Future<Item = String, Error = Error> + Send> {
	let https = hyper_rustls::HttpsConnector::new(1);
	let client = Client::builder().build::<_, Body>(https);
	Box::new(
		client
			.request(req)
			.map_err(|e| ErrorKind::RequestError(format!("Cannot make request: {}", e)).into())
			.and_then(|resp| {
				if !resp.status().is_success() {
					Either::A(err(ErrorKind::RequestError(
						"Wrong response code".to_owned(),
					)
					.into()))
				} else {
					Either::B(
						resp.into_body()
							.map_err(|e| {
								ErrorKind::RequestError(format!("Cannot read response body: {}", e))
									.into()
							})
							.concat2()
							.and_then(|ch| ok(String::from_utf8_lossy(&ch.to_vec()).to_string())),
					)
				}
			}),
	)
}

fn send_request(req: Request<Body>) -> Result<String, Error> {
	let task = send_request_async(req);
	let mut rt = Runtime::new().unwrap();
	Ok(rt.block_on(task)?)
}
<|endoftext|>