<commit_before>use calx::{seeded_rng, HexFov, HexFovIter};
use calx_ecs::Entity;
use command::{Command, CommandResult};
use components;
use event::Event;
use flags::Flags;
use fov::SightFov;
use item::Slot;
use location::{Location, Portal};
use mutate::Mutate;
use query::Query;
use ron;
use spatial::{Place, Spatial};
use std::collections::HashSet;
use std::error::Error;
use std::io::{Read, Write};
use std::iter::FromIterator;
use std::slice;
use terraform::{Terraform, TerrainQuery};
use terrain::Terrain;
use volume::Volume;
use worldgen::Worldgen;
use Rng;

pub const GAME_VERSION: &'static str = "0.1.0";

Ecs! {
    desc: components::Desc,
    anim: components::Anim,
    map_memory: components::MapMemory,
    health: components::Health,
    brain: components::Brain,
    item: components::Item,
    stats: components::StatsComponent,
    status: components::Statuses,
}

/// Toplevel game state object.
#[derive(Serialize, Deserialize)]
pub struct World {
    /// Game version. Not mutable in the slightest, but the simplest way to
    /// get versioned save files is to just drop it here.
    version: String,
    /// Entity component system.
    ecs: Ecs,
    /// Static startup game world
    worldgen: Worldgen,
    /// Spatial index for game entities.
    spatial: Spatial,
    /// Global gamestate flags.
    flags: Flags,
    /// Persistent random number generator.
    rng: Rng,
    /// Event queue
    events: Vec<Event>,
}

impl<'a> World {
    pub fn new(seed: u32) -> World {
        let mut ret = World {
            version: GAME_VERSION.to_string(),
            ecs: Ecs::new(),
            worldgen: Worldgen::new(seed),
            spatial: Spatial::new(),
            flags: Flags::new(),
            rng: seeded_rng(&seed),
            events: Vec::new(),
        };

        // XXX: Clone to not run into borrow checker...
        for (loc, spawn) in ret.worldgen
            .spawns()
            .cloned()
            .collect::<Vec<(Location, Loadout)>>()
        {
            ret.spawn(&spawn, loc);
        }

        // TODO non-lexical borrow
        let player_entry = ret.worldgen.player_entry();
        ret.spawn_player(player_entry);

        ret
    }

    pub fn load<R: Read>(reader: &mut R) -> Result<World, Box<Error>> {
        let ret: ron::de::Result<World> = ron::de::from_reader(reader);
        if let Ok(ref x) = ret {
            if x.version != GAME_VERSION {
                panic!(
                    "Save game version {} does not match current version {}",
                    x.version, GAME_VERSION
                );
            }
        }
        Ok(ret?)
    }

    pub fn save<W: Write>(&self, writer: &mut W) -> Result<(), Box<Error>> {
        let enc = ron::ser::to_string_pretty(self, Default::default())?;
        // TODO: Handle error from writer too...
        writeln!(writer, "{}", enc)?;
        Ok(())
    }
}

impl TerrainQuery for World {
    fn is_valid_location(&self, _loc: Location) -> bool {
        //Location::origin().v2_at(loc).map_or(false, ::on_screen)
        true
    }

    fn terrain(&self, loc: Location) -> Terrain {
        let mut t = self.worldgen.get_terrain(loc);

        if t == Terrain::Door && self.has_mobs(loc) {
            // Standing in the doorway opens the door.
            t = Terrain::OpenDoor;
        }

        t
    }

    fn portal(&self, loc: Location) -> Option<Location> { self.worldgen.get_portal(loc) }

    fn is_untouched(&self, _loc: Location) -> bool { unimplemented!() }
}

impl Query for World {
    fn location(&self, e: Entity) -> Option<Location> {
        match self.spatial.get(e) {
            Some(Place::At(loc)) => Some(loc),
            Some(Place::In(container, _)) => self.location(container),
            _ => None,
        }
    }

    fn player(&self) -> Option<Entity> {
        if let Some(p) = self.flags.player {
            if self.is_alive(p) {
                return Some(p);
            }
        }

        None
    }

    fn get_tick(&self) -> u64 { self.flags.tick }

    fn rng_seed(&self) -> u32 { self.worldgen.seed() }

    fn entities(&self) -> slice::Iter<Entity> { self.ecs.iter() }

    fn entities_at(&self, loc: Location) -> Vec<Entity> { self.spatial.entities_at(loc) }

    fn entities_in(&self, parent: Entity) -> Vec<Entity> { self.spatial.entities_in(parent) }

    fn ecs(&self) -> &Ecs { &self.ecs }

    fn entity_equipped(&self, parent: Entity, slot: Slot) -> Option<Entity> {
        self.spatial.entity_equipped(parent, slot)
    }

    fn entity_contains(&self, parent: Entity, child: Entity) -> bool {
        self.spatial.contains(parent, child)
    }

    fn sphere_volume(&self, origin: Location, radius: u32) -> Volume {
        Volume::sphere(self, origin, radius)
    }
}

impl Mutate for World {
    fn next_tick(&mut self) -> CommandResult {
        use std::mem;

        self.tick_anims();

        self.ai_main();

        self.clean_dead();
        self.flags.tick += 1;

        // Dump events.
        let mut events = Vec::new();
        mem::swap(&mut self.events, &mut events);
        Ok(events)
    }

    fn set_entity_location(&mut self, e: Entity, loc: Location) { self.spatial.insert_at(e, loc); }

    fn equip_item(&mut self, e: Entity, parent: Entity, slot: Slot) {
        self.spatial.equip(e, parent, slot);
        self.rebuild_stats(parent);
    }

    fn set_player(&mut self, player: Option<Entity>) { self.flags.player = player; }

    fn spawn(&mut self, loadout: &Loadout, loc: Location) -> Entity {
        let e = loadout.make(&mut self.ecs);
        self.place_entity(e, loc);
        e
    }

    fn kill_entity(&mut self, e: Entity) { self.spatial.remove(e); }

    fn remove_entity(&mut self, e: Entity) { self.ecs.remove(e); }

    fn do_fov(&mut self, e: Entity) {
        if !self.ecs.map_memory.contains(e) {
            return;
        }

        if let Some(origin) = self.location(e) {
            const DEFAULT_FOV_RANGE: u32 = 12;
            const OVERLAND_FOV_RANGE: u32 = 40;

            // Long-range sight while in overworld.
            let range = if origin.z == 0 {
                OVERLAND_FOV_RANGE
            } else {
                DEFAULT_FOV_RANGE
            };

            let fov: HashSet<Location> = HashSet::from_iter(
                HexFov::new(SightFov::new(self, range, origin))
                    .add_fake_isometric_acute_corners(|pos, a| {
                        self.terrain(a.origin + pos).is_wall()
                    })
                    .map(|(pos, a)| a.origin + pos),
            );

            let memory = &mut self.ecs.map_memory[e];
            memory.seen.clear();

            for &loc in &fov {
                memory.seen.insert(loc);
                // Don't spread map memory to other sectors we haven't "properly" seen yet.
                // The edges are still shown in visual FOV for display niceness.
                if loc.sector() == origin.sector() {
                    memory.remembered.insert(loc);
                }
            }
        }
    }

    fn push_event(&mut self, event: Event) { self.events.push(event); }

    fn rng(&mut self) -> &mut Rng { &mut self.rng }

    fn ecs_mut(&mut self) -> &mut Ecs { &mut self.ecs }
}

impl Command for World {}

impl Terraform for World {
    fn set_terrain(&mut self, _loc: Location, _terrain: Terrain) {
        unimplemented!();
    }

    fn set_portal(&mut self, _loc: Location, _portal: Portal) {
        unimplemented!();
    }

    fn remove_portal(&mut self, _loc: Location) {
        unimplemented!();
    }
}
<commit_msg>Adjust underground FOV radius down to 7<commit_after>use calx::{seeded_rng, HexFov, HexFovIter};
use calx_ecs::Entity;
use command::{Command, CommandResult};
use components;
use event::Event;
use flags::Flags;
use fov::SightFov;
use item::Slot;
use location::{Location, Portal};
use mutate::Mutate;
use query::Query;
use ron;
use spatial::{Place, Spatial};
use std::collections::HashSet;
use std::error::Error;
use std::io::{Read, Write};
use std::iter::FromIterator;
use std::slice;
use terraform::{Terraform, TerrainQuery};
use terrain::Terrain;
use volume::Volume;
use worldgen::Worldgen;
use Rng;

pub const GAME_VERSION: &'static str = "0.1.0";

Ecs! {
    desc: components::Desc,
    anim: components::Anim,
    map_memory: components::MapMemory,
    health: components::Health,
    brain: components::Brain,
    item: components::Item,
    stats: components::StatsComponent,
    status: components::Statuses,
}

/// Toplevel game state object.
#[derive(Serialize, Deserialize)]
pub struct World {
    /// Game version. Not mutable in the slightest, but the simplest way to
    /// get versioned save files is to just drop it here.
    version: String,
    /// Entity component system.
    ecs: Ecs,
    /// Static startup game world
    worldgen: Worldgen,
    /// Spatial index for game entities.
    spatial: Spatial,
    /// Global gamestate flags.
    flags: Flags,
    /// Persistent random number generator.
    rng: Rng,
    /// Event queue
    events: Vec<Event>,
}

impl<'a> World {
    pub fn new(seed: u32) -> World {
        let mut ret = World {
            version: GAME_VERSION.to_string(),
            ecs: Ecs::new(),
            worldgen: Worldgen::new(seed),
            spatial: Spatial::new(),
            flags: Flags::new(),
            rng: seeded_rng(&seed),
            events: Vec::new(),
        };

        // XXX: Clone to not run into borrow checker...
        for (loc, spawn) in ret.worldgen
            .spawns()
            .cloned()
            .collect::<Vec<(Location, Loadout)>>()
        {
            ret.spawn(&spawn, loc);
        }

        // TODO non-lexical borrow
        let player_entry = ret.worldgen.player_entry();
        ret.spawn_player(player_entry);

        ret
    }

    pub fn load<R: Read>(reader: &mut R) -> Result<World, Box<Error>> {
        let ret: ron::de::Result<World> = ron::de::from_reader(reader);
        if let Ok(ref x) = ret {
            if x.version != GAME_VERSION {
                panic!(
                    "Save game version {} does not match current version {}",
                    x.version, GAME_VERSION
                );
            }
        }
        Ok(ret?)
    }

    pub fn save<W: Write>(&self, writer: &mut W) -> Result<(), Box<Error>> {
        let enc = ron::ser::to_string_pretty(self, Default::default())?;
        // TODO: Handle error from writer too...
        writeln!(writer, "{}", enc)?;
        Ok(())
    }
}

impl TerrainQuery for World {
    fn is_valid_location(&self, _loc: Location) -> bool {
        //Location::origin().v2_at(loc).map_or(false, ::on_screen)
        true
    }

    fn terrain(&self, loc: Location) -> Terrain {
        let mut t = self.worldgen.get_terrain(loc);

        if t == Terrain::Door && self.has_mobs(loc) {
            // Standing in the doorway opens the door.
            t = Terrain::OpenDoor;
        }

        t
    }

    fn portal(&self, loc: Location) -> Option<Location> { self.worldgen.get_portal(loc) }

    fn is_untouched(&self, _loc: Location) -> bool { unimplemented!() }
}

impl Query for World {
    fn location(&self, e: Entity) -> Option<Location> {
        match self.spatial.get(e) {
            Some(Place::At(loc)) => Some(loc),
            Some(Place::In(container, _)) => self.location(container),
            _ => None,
        }
    }

    fn player(&self) -> Option<Entity> {
        if let Some(p) = self.flags.player {
            if self.is_alive(p) {
                return Some(p);
            }
        }

        None
    }

    fn get_tick(&self) -> u64 { self.flags.tick }

    fn rng_seed(&self) -> u32 { self.worldgen.seed() }

    fn entities(&self) -> slice::Iter<Entity> { self.ecs.iter() }

    fn entities_at(&self, loc: Location) -> Vec<Entity> { self.spatial.entities_at(loc) }

    fn entities_in(&self, parent: Entity) -> Vec<Entity> { self.spatial.entities_in(parent) }

    fn ecs(&self) -> &Ecs { &self.ecs }

    fn entity_equipped(&self, parent: Entity, slot: Slot) -> Option<Entity> {
        self.spatial.entity_equipped(parent, slot)
    }

    fn entity_contains(&self, parent: Entity, child: Entity) -> bool {
        self.spatial.contains(parent, child)
    }

    fn sphere_volume(&self, origin: Location, radius: u32) -> Volume {
        Volume::sphere(self, origin, radius)
    }
}

impl Mutate for World {
    fn next_tick(&mut self) -> CommandResult {
        use std::mem;

        self.tick_anims();

        self.ai_main();

        self.clean_dead();
        self.flags.tick += 1;

        // Dump events.
        let mut events = Vec::new();
        mem::swap(&mut self.events, &mut events);
        Ok(events)
    }

    fn set_entity_location(&mut self, e: Entity, loc: Location) { self.spatial.insert_at(e, loc); }

    fn equip_item(&mut self, e: Entity, parent: Entity, slot: Slot) {
        self.spatial.equip(e, parent, slot);
        self.rebuild_stats(parent);
    }

    fn set_player(&mut self, player: Option<Entity>) { self.flags.player = player; }

    fn spawn(&mut self, loadout: &Loadout, loc: Location) -> Entity {
        let e = loadout.make(&mut self.ecs);
        self.place_entity(e, loc);
        e
    }

    fn kill_entity(&mut self, e: Entity) { self.spatial.remove(e); }

    fn remove_entity(&mut self, e: Entity) { self.ecs.remove(e); }

    fn do_fov(&mut self, e: Entity) {
        if !self.ecs.map_memory.contains(e) {
            return;
        }

        if let Some(origin) = self.location(e) {
            const DEFAULT_FOV_RANGE: u32 = 7;
            const OVERLAND_FOV_RANGE: u32 = 40;

            // Long-range sight while in overworld.
            let range = if origin.z == 0 {
                OVERLAND_FOV_RANGE
            } else {
                DEFAULT_FOV_RANGE
            };

            let fov: HashSet<Location> = HashSet::from_iter(
                HexFov::new(SightFov::new(self, range, origin))
                    .add_fake_isometric_acute_corners(|pos, a| {
                        self.terrain(a.origin + pos).is_wall()
                    })
                    .map(|(pos, a)| a.origin + pos),
            );

            let memory = &mut self.ecs.map_memory[e];
            memory.seen.clear();

            for &loc in &fov {
                memory.seen.insert(loc);
                // Don't spread map memory to other sectors we haven't "properly" seen yet.
                // The edges are still shown in visual FOV for display niceness.
                if loc.sector() == origin.sector() {
                    memory.remembered.insert(loc);
                }
            }
        }
    }

    fn push_event(&mut self, event: Event) { self.events.push(event); }

    fn rng(&mut self) -> &mut Rng { &mut self.rng }

    fn ecs_mut(&mut self) -> &mut Ecs { &mut self.ecs }
}

impl Command for World {}

impl Terraform for World {
    fn set_terrain(&mut self, _loc: Location, _terrain: Terrain) {
        unimplemented!();
    }

    fn set_portal(&mut self, _loc: Location, _portal: Portal) {
        unimplemented!();
    }

    fn remove_portal(&mut self, _loc: Location) {
        unimplemented!();
    }
}
<|endoftext|>


<commit_before>use rosxmlrpc;
use std;

pub struct Master {
    client: rosxmlrpc::Client,
    client_id: String,
    caller_api: String,
}

impl Master {
    pub fn new(client_id: &str, caller_api: &str) -> Master {
        let master_uri = std::env::var("ROS_MASTER_URI")
            .unwrap_or("http://localhost:11311/".to_string());
        Master {
            client: rosxmlrpc::Client::new(&master_uri),
            client_id: client_id.to_string(),
            caller_api: caller_api.to_string(),
        }
    }

    pub fn register_service(&self, service: &str, service_api: &str) -> rosxmlrpc::client::Member {
        self.client.request("registerService",
                            &vec![self.client_id.as_str(),
                                  service,
                                  service_api,
                                  self.caller_api.as_str()])
    }

    pub fn unregister_service(&self,
                              service: &str,
                              service_api: &str)
                              -> rosxmlrpc::client::Member {
        self.client.request("unregisterService",
                            &vec![self.client_id.as_str(), service, service_api])
    }

    pub fn register_subscriber(&self, topic: &str, topic_type: &str) -> rosxmlrpc::client::Member {
        self.client.request("registerSubscriber",
                            &vec![self.client_id.as_str(),
                                  topic,
                                  topic_type,
                                  self.caller_api.as_str()])
    }

    pub fn unregister_subscriber(&self, topic: &str) -> rosxmlrpc::client::Member {
        self.client.request("unregisterSubscriber",
                            &vec![self.client_id.as_str(), topic, self.caller_api.as_str()])
    }

    pub fn register_publisher(&self, topic: &str, topic_type: &str) -> rosxmlrpc::client::Member {
        self.client.request("registerPublisher",
                            &vec![self.client_id.as_str(),
                                  topic,
                                  topic_type,
                                  self.caller_api.as_str()])
    }

    pub fn unregister_publisher(&self, topic: &str) -> rosxmlrpc::client::Member {
        self.client.request("unregisterPublisher",
                            &vec![self.client_id.as_str(), topic, self.caller_api.as_str()])
    }
}
<commit_msg>Don't use vectors where they are not needed<commit_after>use rosxmlrpc;
use std;

pub struct Master {
    client: rosxmlrpc::Client,
    client_id: String,
    caller_api: String,
}

impl Master {
    pub fn new(client_id: &str, caller_api: &str) -> Master {
        let master_uri = std::env::var("ROS_MASTER_URI")
            .unwrap_or("http://localhost:11311/".to_string());
        Master {
            client: rosxmlrpc::Client::new(&master_uri),
            client_id: client_id.to_string(),
            caller_api: caller_api.to_string(),
        }
    }

    pub fn register_service(&self, service: &str, service_api: &str) -> rosxmlrpc::client::Member {
        self.client.request("registerService",
                            &[self.client_id.as_str(),
                              service,
                              service_api,
                              self.caller_api.as_str()])
    }

    pub fn unregister_service(&self,
                              service: &str,
                              service_api: &str)
                              -> rosxmlrpc::client::Member {
        self.client.request("unregisterService",
                            &[self.client_id.as_str(), service, service_api])
    }

    pub fn register_subscriber(&self, topic: &str, topic_type: &str) -> rosxmlrpc::client::Member {
        self.client.request("registerSubscriber",
                            &[self.client_id.as_str(), topic, topic_type, self.caller_api.as_str()])
    }

    pub fn unregister_subscriber(&self, topic: &str) -> rosxmlrpc::client::Member {
        self.client.request("unregisterSubscriber",
                            &[self.client_id.as_str(), topic, self.caller_api.as_str()])
    }

    pub fn register_publisher(&self, topic: &str, topic_type: &str) -> rosxmlrpc::client::Member {
        self.client.request("registerPublisher",
                            &[self.client_id.as_str(), topic, topic_type, self.caller_api.as_str()])
    }

    pub fn unregister_publisher(&self, topic: &str) -> rosxmlrpc::client::Member {
        self.client.request("unregisterPublisher",
                            &[self.client_id.as_str(), topic, self.caller_api.as_str()])
    }
}
<|endoftext|>


<commit_before>// Copyright 2015 Nathan Sizemore <nathanrsizemore@gmail.com>
//
// This Source Code Form is subject to the
// terms of the Mozilla Public License, v.
// 2.0. If a copy of the MPL was not
// distributed with this file, You can
// obtain one at
// http://mozilla.org/MPL/2.0/.
//
// This Source Code Form is "Incompatible
// With Secondary Licenses", as defined by
// the Mozilla Public License, v. 2.0.

use std::{str};
use std::ffi::{CStr, CString};
use std::thread;
use std::net::TcpStream;
use std::sync::mpsc::{channel, Sender, Receiver};

use super::libc::{c_int, c_char};
use super::simple_stream::bstream::Bstream;

/// This client's writer channel
static mut writer_tx: *mut Sender<Vec<u8>> = 0 as *mut Sender<Vec<u8>>;

/// This client's kill channel
static mut kill_tx: *mut Sender<()> = 0 as *mut Sender<()>;

#[no_mangle]
pub extern "C" fn start(address: *const c_char,
    data_handler: extern fn(*const c_char),
    on_connect_handler: extern fn(),
    on_disconnect_handler: extern fn()) -> c_int {

    // TODO - adjust this to accept a log level adjustable by whoever is running
    // the application
    super::init();
    //
    // trace!("Rust - start()");
    //
    // let mut r_address;
    // unsafe {
    //     r_address = CStr::from_ptr(address);
    // }
    // let s_address = r_address.to_bytes();
    // let host_address = match str::from_utf8(s_address) {
    //     Ok(safe_str) => safe_str,
    //     Err(_) => {
    //         error!("Invalid host address");
    //         return -1 as c_int;
    //     }
    // };
    //
    // // Create and register a way to kill this client
    // let (k_tx, kill_rx): (Sender<()>, Receiver<()>) = channel();
    // unsafe { *kill_tx = k_tx.clone(); }
    //
    // // Writer thread's channel
    // let (w_tx, writer_rx): (Sender<Vec<u8>>, Receiver<Vec<u8>>) = channel();
    // unsafe { *writer_tx = w_tx.clone(); }
    //
    // debug!("Attempting connect to: {}", host_address);
    //
    // let result = TcpStream::connect(host_address);
    // if result.is_err() {
    //     error!("Error connecting to {} - {}", host_address, result.unwrap_err());
    //     return -1 as c_int;
    // }
    // debug!("Connected");
    // on_connect_handler();
    //
    // let stream = result.unwrap();
    // let client = Bstream::new(stream);
    // let r_client = client.clone();
    // let w_client = client.clone();
    //
    // // Start the reader thread
    // thread::Builder::new()
    //     .name("ReaderThread".to_string())
    //     .spawn(move||{
    //         reader_thread(r_client, data_handler)
    //     }).unwrap();
    //
    // // Start the writer thread
    // thread::Builder::new()
    //     .name("WriterThread".to_string())
    //     .spawn(move||{
    //         writer_thread(writer_rx, w_client)
    //     }).unwrap();
    //
    // // Wait for the kill signal
    // match kill_rx.recv() {
    //     Ok(_) => { }
    //     Err(e) => {
    //         error!("Error on kill channel: {}", e);
    //         on_disconnect_handler();
    //         return -1 as c_int;
    //     }
    // };
    // on_disconnect_handler();

    // Exit out in standard C fashion
    0 as c_int
}

/// Writes the complete contents of buffer to the server
/// Returns -1 on error
#[no_mangle]
pub extern "C" fn hydrogen_write(buffer: *const c_char) -> c_int {
    trace!("Rust.write");

    let mut buf_as_cstr;
    unsafe {
        buf_as_cstr = CStr::from_ptr(buffer);
    }
    let buf_as_slice = buf_as_cstr.to_bytes();

    let mut n_buffer = Vec::<u8>::with_capacity(buf_as_slice.len());
    for byte in buf_as_slice.iter() {
        n_buffer.push(*byte);
    }

    unsafe {
        match (*writer_tx).send(n_buffer) {
            Ok(_) => { }
            Err(e) => {
                warn!("Error sending buffer: {}", e);
                let _ = (*kill_tx).send(());
                return -1 as c_int;
            }
        };
    }

    0 as c_int
}

/// Forever listens to incoming data and when a complete message is received,
/// the passed callback is hit
fn reader_thread(client: Bstream, handler: extern fn(*const c_char)) {
    trace!("Rust.reader_thread started");

    let mut reader = client.clone();
    loop {
        match reader.read() {
            Ok(buffer) => {
                // Launch the handler in a new thread
                thread::Builder::new()
                    .name("Reader-Worker".to_string())
                    .spawn(move||{
                        let slice = &buffer[..];
                        let c_buffer = CString::new(slice).unwrap();
                        handler(c_buffer.as_ptr());
                    }).unwrap();
            }
            Err(e) => {
                error!("Error: {}", e);
                break;
            }
        };
    }
    debug!("Rust.reader_thread finished");
    unsafe { let _ = (*kill_tx).send(()); }
}

/// Forever listens to Receiver<Vec<u8>> waiting on messages to come in
/// Once available, blocks until the entire message has been written
fn writer_thread(rx: Receiver<Vec<u8>>, client: Bstream) {
    trace!("Rust.writer_thread started");

    let mut writer = client.clone();
    loop {
        match rx.recv() {
            Ok(ref mut buffer) => {
                match writer.write(buffer) {
                    Ok(_) => { }
                    Err(e) => {
                        error!("Error: {}", e);
                        break;
                    }
                };
            }
            Err(e) => {
                error!("Error: {}", e);
                break;
            }
        };
    }

    debug!("Rust.writer_thread finished");
    unsafe { let _ = (*kill_tx).send(()); }
}

/// Drops the current connection and kills all current threads
#[no_mangle]
pub extern "C" fn kill() {
    unsafe { let _ = (*kill_tx).send(()); }
}
<commit_msg>Debugging<commit_after>// Copyright 2015 Nathan Sizemore <nathanrsizemore@gmail.com>
//
// This Source Code Form is subject to the
// terms of the Mozilla Public License, v.
// 2.0. If a copy of the MPL was not
// distributed with this file, You can
// obtain one at
// http://mozilla.org/MPL/2.0/.
//
// This Source Code Form is "Incompatible
// With Secondary Licenses", as defined by
// the Mozilla Public License, v. 2.0.

use std::{str};
use std::ffi::{CStr, CString};
use std::thread;
use std::net::TcpStream;
use std::sync::mpsc::{channel, Sender, Receiver};

use super::libc::{c_int, c_char};
use super::simple_stream::bstream::Bstream;

/// This client's writer channel
static mut writer_tx: *mut Sender<Vec<u8>> = 0 as *mut Sender<Vec<u8>>;

/// This client's kill channel
static mut kill_tx: *mut Sender<()> = 0 as *mut Sender<()>;

#[no_mangle]
pub extern "C" fn start(address: *const c_char,
    data_handler: extern fn(*const c_char),
    on_connect_handler: extern fn(),
    on_disconnect_handler: extern fn()) -> c_int {

    // TODO - adjust this to accept a log level adjustable by whoever is running
    // the application
    super::init();

    trace!("Rust - start()");

    let mut r_address;
    unsafe {
        r_address = CStr::from_ptr(address);
    }
    let s_address = r_address.to_bytes();
    let host_address = match str::from_utf8(s_address) {
        Ok(safe_str) => safe_str,
        Err(_) => {
            error!("Invalid host address");
            return -1 as c_int;
        }
    };
    //
    // // Create and register a way to kill this client
    // let (k_tx, kill_rx): (Sender<()>, Receiver<()>) = channel();
    // unsafe { *kill_tx = k_tx.clone(); }
    //
    // // Writer thread's channel
    // let (w_tx, writer_rx): (Sender<Vec<u8>>, Receiver<Vec<u8>>) = channel();
    // unsafe { *writer_tx = w_tx.clone(); }
    //
    // debug!("Attempting connect to: {}", host_address);
    //
    // let result = TcpStream::connect(host_address);
    // if result.is_err() {
    //     error!("Error connecting to {} - {}", host_address, result.unwrap_err());
    //     return -1 as c_int;
    // }
    // debug!("Connected");
    // on_connect_handler();
    //
    // let stream = result.unwrap();
    // let client = Bstream::new(stream);
    // let r_client = client.clone();
    // let w_client = client.clone();
    //
    // // Start the reader thread
    // thread::Builder::new()
    //     .name("ReaderThread".to_string())
    //     .spawn(move||{
    //         reader_thread(r_client, data_handler)
    //     }).unwrap();
    //
    // // Start the writer thread
    // thread::Builder::new()
    //     .name("WriterThread".to_string())
    //     .spawn(move||{
    //         writer_thread(writer_rx, w_client)
    //     }).unwrap();
    //
    // // Wait for the kill signal
    // match kill_rx.recv() {
    //     Ok(_) => { }
    //     Err(e) => {
    //         error!("Error on kill channel: {}", e);
    //         on_disconnect_handler();
    //         return -1 as c_int;
    //     }
    // };
    // on_disconnect_handler();

    // Exit out in standard C fashion
    0 as c_int
}

/// Writes the complete contents of buffer to the server
/// Returns -1 on error
#[no_mangle]
pub extern "C" fn hydrogen_write(buffer: *const c_char) -> c_int {
    trace!("Rust.write");

    let mut buf_as_cstr;
    unsafe {
        buf_as_cstr = CStr::from_ptr(buffer);
    }
    let buf_as_slice = buf_as_cstr.to_bytes();

    let mut n_buffer = Vec::<u8>::with_capacity(buf_as_slice.len());
    for byte in buf_as_slice.iter() {
        n_buffer.push(*byte);
    }

    unsafe {
        match (*writer_tx).send(n_buffer) {
            Ok(_) => { }
            Err(e) => {
                warn!("Error sending buffer: {}", e);
                let _ = (*kill_tx).send(());
                return -1 as c_int;
            }
        };
    }

    0 as c_int
}

/// Forever listens to incoming data and when a complete message is received,
/// the passed callback is hit
fn reader_thread(client: Bstream, handler: extern fn(*const c_char)) {
    trace!("Rust.reader_thread started");

    let mut reader = client.clone();
    loop {
        match reader.read() {
            Ok(buffer) => {
                // Launch the handler in a new thread
                thread::Builder::new()
                    .name("Reader-Worker".to_string())
                    .spawn(move||{
                        let slice = &buffer[..];
                        let c_buffer = CString::new(slice).unwrap();
                        handler(c_buffer.as_ptr());
                    }).unwrap();
            }
            Err(e) => {
                error!("Error: {}", e);
                break;
            }
        };
    }
    debug!("Rust.reader_thread finished");
    unsafe { let _ = (*kill_tx).send(()); }
}

/// Forever listens to Receiver<Vec<u8>> waiting on messages to come in
/// Once available, blocks until the entire message has been written
fn writer_thread(rx: Receiver<Vec<u8>>, client: Bstream) {
    trace!("Rust.writer_thread started");

    let mut writer = client.clone();
    loop {
        match rx.recv() {
            Ok(ref mut buffer) => {
                match writer.write(buffer) {
                    Ok(_) => { }
                    Err(e) => {
                        error!("Error: {}", e);
                        break;
                    }
                };
            }
            Err(e) => {
                error!("Error: {}", e);
                break;
            }
        };
    }

    debug!("Rust.writer_thread finished");
    unsafe { let _ = (*kill_tx).send(()); }
}

/// Drops the current connection and kills all current threads
#[no_mangle]
pub extern "C" fn kill() {
    unsafe { let _ = (*kill_tx).send(()); }
}
<|endoftext|>


<commit_before>//! HTTP Client

use std::cell::RefCell;
use std::fmt;
use std::io;
use std::marker::PhantomData;
use std::rc::Rc;
use std::time::Duration;

use futures::{Future, Poll, Stream};
use futures::future::{self, Executor};
#[cfg(feature = "compat")]
use http;
use tokio::reactor::Handle;
pub use tokio_service::Service;

use header::{Host};
use proto;
use proto::request;
use method::Method;
use self::pool::Pool;
use uri::{self, Uri};
use version::HttpVersion;

pub use proto::response::Response;
pub use proto::request::Request;
pub use self::connect::{HttpConnector, Connect};

use self::background::{bg, Background};

mod connect;
mod dns;
mod pool;
#[cfg(feature = "compat")]
pub mod compat;

/// A Client to make outgoing HTTP requests.
// If the Connector is clone, then the Client can be clone easily.
pub struct Client<C, B = proto::Body> {
    connector: C,
    executor: Exec,
    pool: Pool<HyperClient<B>>,
}

impl Client<HttpConnector, proto::Body> {
    /// Create a new Client with the default config.
    #[inline]
    pub fn new(handle: &Handle) -> Client<HttpConnector, proto::Body> {
        Config::default().build(handle)
    }
}

impl Client<HttpConnector, proto::Body> {
    /// Configure a Client.
    ///
    /// # Example
    ///
    /// ```no_run
    /// # extern crate hyper;
    /// # extern crate tokio_core;
    ///
    /// # fn main() {
    /// # let core = tokio_core::reactor::Core::new().unwrap();
    /// # let handle = core.handle();
    /// let client = hyper::Client::configure()
    ///     .keep_alive(true)
    ///     .build(&handle);
    /// # drop(client);
    /// # }
    /// ```
    #[inline]
    pub fn configure() -> Config<UseDefaultConnector, proto::Body> {
        Config::default()
    }
}

impl<C, B> Client<C, B> {
    // Eventually, a Client won't really care about a tokio Handle, and only
    // the executor used to spawn background tasks. Removing this method is
    // a breaking change, so for now, it's just deprecated.
    #[doc(hidden)]
    #[deprecated]
    pub fn handle(&self) -> &Handle {
        match self.executor {
            Exec::Handle(ref h) => h,
            Exec::Executor(..) => panic!("Client not built with a Handle"),
        }
    }

    /// Create a new client with a specific connector.
    #[inline]
    fn configured(config: Config<C, B>, exec: Exec) -> Client<C, B> {
        Client {
            connector: config.connector,
            executor: exec,
            pool: Pool::new(config.keep_alive, config.keep_alive_timeout)
        }
    }
}

impl<C, B> Client<C, B>
where C: Connect,
      B: Stream<Error=::Error> + 'static,
      B::Item: AsRef<[u8]>,
{
    /// Send a GET Request using this Client.
    #[inline]
    pub fn get(&self, url: Uri) -> FutureResponse {
        self.request(Request::new(Method::Get, url))
    }

    /// Send a constructed Request using this Client.
    #[inline]
    pub fn request(&self, req: Request<B>) -> FutureResponse {
        self.call(req)
    }

    /// Send an `http::Request` using this Client.
    #[inline]
    #[cfg(feature = "compat")]
    pub fn request_compat(&self, req: http::Request<B>) -> compat::CompatFutureResponse {
        self::compat::future(self.call(req.into()))
    }

    /// Convert into a client accepting `http::Request`.
    #[cfg(feature = "compat")]
    pub fn into_compat(self) -> compat::CompatClient<C, B> {
        self::compat::client(self)
    }
}

/// A `Future` that will resolve to an HTTP Response.
#[must_use = "futures do nothing unless polled"]
pub struct FutureResponse(Box<Future<Item=Response, Error=::Error> + 'static>);

impl fmt::Debug for FutureResponse {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        f.pad("Future<Response>")
    }
}

impl Future for FutureResponse {
    type Item = Response;
    type Error = ::Error;

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

impl<C, B> Service for Client<C, B>
where C: Connect,
      B: Stream<Error=::Error> + 'static,
      B::Item: AsRef<[u8]>,
{
    type Request = Request<B>;
    type Response = Response;
    type Error = ::Error;
    type Future = FutureResponse;

    fn call(&self, req: Self::Request) -> Self::Future {
        match req.version() {
            HttpVersion::Http10 |
            HttpVersion::Http11 => (),
            other => {
                error!("Request has unsupported version \"{}\"", other);
                return FutureResponse(Box::new(future::err(::Error::Version)));
            }
        }

        let url = req.uri().clone();
        let domain = match uri::scheme_and_authority(&url) {
            Some(uri) => uri,
            None => {
                return FutureResponse(Box::new(future::err(::Error::Io(
                    io::Error::new(
                        io::ErrorKind::InvalidInput,
                        "invalid URI for Client Request"
                    )
                ))));
            }
        };
        let (mut head, body) = request::split(req);
        if !head.headers.has::<Host>() {
            let host = Host::new(
                domain.host().expect("authority implies host").to_owned(),
                domain.port(),
            );
            head.headers.set_pos(0, host);
        }

        use futures::Sink;
        use futures::sync::{mpsc, oneshot};

        let checkout = self.pool.checkout(domain.as_ref());
        let connect = {
            let executor = self.executor.clone();
            let pool = self.pool.clone();
            let pool_key = Rc::new(domain.to_string());
            self.connector.connect(url)
                .and_then(move |io| {
                    let (tx, rx) = mpsc::channel(0);
                    let tx = HyperClient {
                        tx: RefCell::new(tx),
                        should_close: true,
                    };
                    let pooled = pool.pooled(pool_key, tx);
                    let conn = proto::Conn::<_, _, proto::ClientTransaction, _>::new(io, pooled.clone());
                    let dispatch = proto::dispatch::Dispatcher::new(proto::dispatch::Client::new(rx), conn);
                    executor.execute(dispatch.map_err(|e| debug!("client connection error: {}", e)))?;
                    Ok(pooled)
                })
        };

        let race = checkout.select(connect)
            .map(|(client, _work)| client)
            .map_err(|(e, _work)| {
                // the Pool Checkout cannot error, so the only error
                // is from the Connector
                // XXX: should wait on the Checkout? Problem is
                // that if the connector is failing, it may be that we
                // never had a pooled stream at all
                e.into()
            });

        let resp = race.and_then(move |client| {
            use proto::dispatch::ClientMsg;

            let (callback, rx) = oneshot::channel();

            match client.tx.borrow_mut().start_send(ClientMsg::Request(head, body, callback)) {
                Ok(_) => (),
                Err(e) => match e.into_inner() {
                    ClientMsg::Request(_, _, callback) => {
                        error!("pooled connection was not ready, this is a hyper bug");
                        let err = io::Error::new(
                            io::ErrorKind::BrokenPipe,
                            "pool selected dead connection",
                        );
                        let _ = callback.send(Err(::Error::Io(err)));
                    },
                    _ => unreachable!("ClientMsg::Request was just sent"),
                }
            }

            rx.then(|res| {
                match res {
                    Ok(Ok(res)) => Ok(res),
                    Ok(Err(err)) => Err(err),
                    Err(_) => panic!("dispatch dropped without returning error"),
                }
            })
        });

        FutureResponse(Box::new(resp))
    }

}

impl<C: Clone, B> Clone for Client<C, B> {
    fn clone(&self) -> Client<C, B> {
        Client {
            connector: self.connector.clone(),
            executor: self.executor.clone(),
            pool: self.pool.clone(),
        }
    }
}

impl<C, B> fmt::Debug for Client<C, B> {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        f.pad("Client")
    }
}

struct HyperClient<B> {
    should_close: bool,
    tx: RefCell<::futures::sync::mpsc::Sender<proto::dispatch::ClientMsg<B>>>,
}

impl<B> Clone for HyperClient<B> {
    fn clone(&self) -> HyperClient<B> {
        HyperClient {
            tx: self.tx.clone(),
            should_close: self.should_close,
        }
    }
}

impl<B> self::pool::Ready for HyperClient<B> {
    fn poll_ready(&mut self) -> Poll<(), ()> {
        self.tx
            .borrow_mut()
            .poll_ready()
            .map_err(|_| ())
    }
}

impl<B> Drop for HyperClient<B> {
    fn drop(&mut self) {
        if self.should_close {
            self.should_close = false;
            let _ = self.tx.borrow_mut().try_send(proto::dispatch::ClientMsg::Close);
        }
    }
}

/// Configuration for a Client
pub struct Config<C, B> {
    _body_type: PhantomData<B>,
    //connect_timeout: Duration,
    connector: C,
    keep_alive: bool,
    keep_alive_timeout: Option<Duration>,
    //TODO: make use of max_idle config
    max_idle: usize,
    no_proto: bool,
}

/// Phantom type used to signal that `Config` should create a `HttpConnector`.
#[derive(Debug, Clone, Copy)]
pub struct UseDefaultConnector(());

impl Default for Config<UseDefaultConnector, proto::Body> {
    fn default() -> Config<UseDefaultConnector, proto::Body> {
        Config {
            _body_type: PhantomData::<proto::Body>,
            //connect_timeout: Duration::from_secs(10),
            connector: UseDefaultConnector(()),
            keep_alive: true,
            keep_alive_timeout: Some(Duration::from_secs(90)),
            max_idle: 5,
            no_proto: false,
        }
    }
}

impl<C, B> Config<C, B> {
    /// Set the body stream to be used by the `Client`.
    ///
    /// # Example
    ///
    /// ```rust
    /// # use hyper::client::Config;
    /// let cfg = Config::default()
    ///     .body::<hyper::Body>();
    /// # drop(cfg);
    #[inline]
    pub fn body<BB>(self) -> Config<C, BB> {
        Config {
            _body_type: PhantomData::<BB>,
            //connect_timeout: self.connect_timeout,
            connector: self.connector,
            keep_alive: self.keep_alive,
            keep_alive_timeout: self.keep_alive_timeout,
            max_idle: self.max_idle,
            no_proto: self.no_proto,
        }
    }

    /// Set the `Connect` type to be used.
    #[inline]
    pub fn connector<CC>(self, val: CC) -> Config<CC, B> {
        Config {
            _body_type: self._body_type,
            //connect_timeout: self.connect_timeout,
            connector: val,
            keep_alive: self.keep_alive,
            keep_alive_timeout: self.keep_alive_timeout,
            max_idle: self.max_idle,
            no_proto: self.no_proto,
        }
    }

    /// Enable or disable keep-alive mechanics.
    ///
    /// Default is enabled.
    #[inline]
    pub fn keep_alive(mut self, val: bool) -> Config<C, B> {
        self.keep_alive = val;
        self
    }

    /// Set an optional timeout for idle sockets being kept-alive.
    ///
    /// Pass `None` to disable timeout.
    ///
    /// Default is 90 seconds.
    #[inline]
    pub fn keep_alive_timeout(mut self, val: Option<Duration>) -> Config<C, B> {
        self.keep_alive_timeout = val;
        self
    }

    /*
    /// Set the timeout for connecting to a URL.
    ///
    /// Default is 10 seconds.
    #[inline]
    pub fn connect_timeout(mut self, val: Duration) -> Config<C, B> {
        self.connect_timeout = val;
        self
    }
    */

    #[doc(hidden)]
    #[deprecated(since="0.11.11", note="no_proto is always enabled")]
    pub fn no_proto(self) -> Config<C, B> {
        self
    }
}

impl<C, B> Config<C, B>
where C: Connect,
      B: Stream<Error=::Error>,
      B::Item: AsRef<[u8]>,
{
    /// Construct the Client with this configuration.
    #[inline]
    pub fn build(self, handle: &Handle) -> Client<C, B> {
        Client::configured(self, Exec::Handle(handle.clone()))
    }

    /// Construct a Client with this configuration and an executor.
    ///
    /// The executor will be used to spawn "background" connection tasks
    /// to drive requests and responses.
    pub fn executor<E>(self, executor: E) -> Client<C, B>
    where
        E: Executor<Background> + 'static,
    {
        Client::configured(self, Exec::Executor(Rc::new(executor)))
    }
}

impl<B> Config<UseDefaultConnector, B>
where B: Stream<Error=::Error>,
      B::Item: AsRef<[u8]>,
{
    /// Construct the Client with this configuration.
    #[inline]
    pub fn build(self, handle: &Handle) -> Client<HttpConnector, B> {
        self.connector(HttpConnector::new(4, handle)).build(handle)
    }
}

impl<C, B> fmt::Debug for Config<C, B> {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        f.debug_struct("Config")
            .field("keep_alive", &self.keep_alive)
            .field("keep_alive_timeout", &self.keep_alive_timeout)
            .field("max_idle", &self.max_idle)
            .finish()
    }
}

impl<C: Clone, B> Clone for Config<C, B> {
    fn clone(&self) -> Config<C, B> {
        Config {
            connector: self.connector.clone(),
            .. *self
        }
    }
}

// ===== impl Exec =====

#[derive(Clone)]
enum Exec {
    Handle(Handle),
    Executor(Rc<Executor<Background>>),
}

impl Exec {
    fn execute<F>(&self, fut: F) -> io::Result<()>
    where
        F: Future<Item=(), Error=()> + 'static,
    {
        match *self {
            Exec::Handle(ref h) => h.spawn(fut),
            Exec::Executor(ref e) => {
                e.execute(bg(Box::new(fut)))
                    .map_err(|err| {
                        debug!("executor error: {:?}", err.kind());
                        io::Error::new(
                            io::ErrorKind::Other,
                            "executor error",
                        )
                    })?
            },
        }
        Ok(())
    }
}

// ===== impl Background =====

// The types inside this module are not exported out of the crate,
// so they are in essence un-nameable.
mod background {
    use futures::{Future, Poll};

    // This is basically `impl Future`, since the type is un-nameable,
    // and only implementeds `Future`.
    #[allow(missing_debug_implementations)]
    pub struct Background {
        inner: Box<Future<Item=(), Error=()>>,
    }

    pub fn bg(fut: Box<Future<Item=(), Error=()>>) -> Background {
        Background {
            inner: fut,
        }
    }

    impl Future for Background {
        type Item = ();
        type Error = ();

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

<commit_msg>refactor(client): fix up should_close sentinel value<commit_after>//! HTTP Client

use std::cell::{Cell, RefCell};
use std::fmt;
use std::io;
use std::marker::PhantomData;
use std::rc::Rc;
use std::time::Duration;

use futures::{Future, Poll, Stream};
use futures::future::{self, Executor};
#[cfg(feature = "compat")]
use http;
use tokio::reactor::Handle;
pub use tokio_service::Service;

use header::{Host};
use proto;
use proto::request;
use method::Method;
use self::pool::Pool;
use uri::{self, Uri};
use version::HttpVersion;

pub use proto::response::Response;
pub use proto::request::Request;
pub use self::connect::{HttpConnector, Connect};

use self::background::{bg, Background};

mod connect;
mod dns;
mod pool;
#[cfg(feature = "compat")]
pub mod compat;

/// A Client to make outgoing HTTP requests.
// If the Connector is clone, then the Client can be clone easily.
pub struct Client<C, B = proto::Body> {
    connector: C,
    executor: Exec,
    pool: Pool<HyperClient<B>>,
}

impl Client<HttpConnector, proto::Body> {
    /// Create a new Client with the default config.
    #[inline]
    pub fn new(handle: &Handle) -> Client<HttpConnector, proto::Body> {
        Config::default().build(handle)
    }
}

impl Client<HttpConnector, proto::Body> {
    /// Configure a Client.
    ///
    /// # Example
    ///
    /// ```no_run
    /// # extern crate hyper;
    /// # extern crate tokio_core;
    ///
    /// # fn main() {
    /// # let core = tokio_core::reactor::Core::new().unwrap();
    /// # let handle = core.handle();
    /// let client = hyper::Client::configure()
    ///     .keep_alive(true)
    ///     .build(&handle);
    /// # drop(client);
    /// # }
    /// ```
    #[inline]
    pub fn configure() -> Config<UseDefaultConnector, proto::Body> {
        Config::default()
    }
}

impl<C, B> Client<C, B> {
    // Eventually, a Client won't really care about a tokio Handle, and only
    // the executor used to spawn background tasks. Removing this method is
    // a breaking change, so for now, it's just deprecated.
    #[doc(hidden)]
    #[deprecated]
    pub fn handle(&self) -> &Handle {
        match self.executor {
            Exec::Handle(ref h) => h,
            Exec::Executor(..) => panic!("Client not built with a Handle"),
        }
    }

    /// Create a new client with a specific connector.
    #[inline]
    fn configured(config: Config<C, B>, exec: Exec) -> Client<C, B> {
        Client {
            connector: config.connector,
            executor: exec,
            pool: Pool::new(config.keep_alive, config.keep_alive_timeout)
        }
    }
}

impl<C, B> Client<C, B>
where C: Connect,
      B: Stream<Error=::Error> + 'static,
      B::Item: AsRef<[u8]>,
{
    /// Send a GET Request using this Client.
    #[inline]
    pub fn get(&self, url: Uri) -> FutureResponse {
        self.request(Request::new(Method::Get, url))
    }

    /// Send a constructed Request using this Client.
    #[inline]
    pub fn request(&self, req: Request<B>) -> FutureResponse {
        self.call(req)
    }

    /// Send an `http::Request` using this Client.
    #[inline]
    #[cfg(feature = "compat")]
    pub fn request_compat(&self, req: http::Request<B>) -> compat::CompatFutureResponse {
        self::compat::future(self.call(req.into()))
    }

    /// Convert into a client accepting `http::Request`.
    #[cfg(feature = "compat")]
    pub fn into_compat(self) -> compat::CompatClient<C, B> {
        self::compat::client(self)
    }
}

/// A `Future` that will resolve to an HTTP Response.
#[must_use = "futures do nothing unless polled"]
pub struct FutureResponse(Box<Future<Item=Response, Error=::Error> + 'static>);

impl fmt::Debug for FutureResponse {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        f.pad("Future<Response>")
    }
}

impl Future for FutureResponse {
    type Item = Response;
    type Error = ::Error;

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

impl<C, B> Service for Client<C, B>
where C: Connect,
      B: Stream<Error=::Error> + 'static,
      B::Item: AsRef<[u8]>,
{
    type Request = Request<B>;
    type Response = Response;
    type Error = ::Error;
    type Future = FutureResponse;

    fn call(&self, req: Self::Request) -> Self::Future {
        match req.version() {
            HttpVersion::Http10 |
            HttpVersion::Http11 => (),
            other => {
                error!("Request has unsupported version \"{}\"", other);
                return FutureResponse(Box::new(future::err(::Error::Version)));
            }
        }

        let url = req.uri().clone();
        let domain = match uri::scheme_and_authority(&url) {
            Some(uri) => uri,
            None => {
                return FutureResponse(Box::new(future::err(::Error::Io(
                    io::Error::new(
                        io::ErrorKind::InvalidInput,
                        "invalid URI for Client Request"
                    )
                ))));
            }
        };
        let (mut head, body) = request::split(req);
        if !head.headers.has::<Host>() {
            let host = Host::new(
                domain.host().expect("authority implies host").to_owned(),
                domain.port(),
            );
            head.headers.set_pos(0, host);
        }

        use futures::Sink;
        use futures::sync::{mpsc, oneshot};

        let checkout = self.pool.checkout(domain.as_ref());
        let connect = {
            let executor = self.executor.clone();
            let pool = self.pool.clone();
            let pool_key = Rc::new(domain.to_string());
            self.connector.connect(url)
                .and_then(move |io| {
                    // 1 extra slot for possible Close message
                    let (tx, rx) = mpsc::channel(1);
                    let tx = HyperClient {
                        tx: RefCell::new(tx),
                        should_close: Cell::new(true),
                    };
                    let pooled = pool.pooled(pool_key, tx);
                    let conn = proto::Conn::<_, _, proto::ClientTransaction, _>::new(io, pooled.clone());
                    let dispatch = proto::dispatch::Dispatcher::new(proto::dispatch::Client::new(rx), conn);
                    executor.execute(dispatch.map_err(|e| debug!("client connection error: {}", e)))?;
                    Ok(pooled)
                })
        };

        let race = checkout.select(connect)
            .map(|(client, _work)| client)
            .map_err(|(e, _work)| {
                // the Pool Checkout cannot error, so the only error
                // is from the Connector
                // XXX: should wait on the Checkout? Problem is
                // that if the connector is failing, it may be that we
                // never had a pooled stream at all
                e.into()
            });

        let resp = race.and_then(move |client| {
            use proto::dispatch::ClientMsg;

            let (callback, rx) = oneshot::channel();
            client.should_close.set(false);

            match client.tx.borrow_mut().start_send(ClientMsg::Request(head, body, callback)) {
                Ok(_) => (),
                Err(e) => match e.into_inner() {
                    ClientMsg::Request(_, _, callback) => {
                        error!("pooled connection was not ready, this is a hyper bug");
                        let err = io::Error::new(
                            io::ErrorKind::BrokenPipe,
                            "pool selected dead connection",
                        );
                        let _ = callback.send(Err(::Error::Io(err)));
                    },
                    _ => unreachable!("ClientMsg::Request was just sent"),
                }
            }

            rx.then(|res| {
                match res {
                    Ok(Ok(res)) => Ok(res),
                    Ok(Err(err)) => Err(err),
                    Err(_) => panic!("dispatch dropped without returning error"),
                }
            })
        });

        FutureResponse(Box::new(resp))
    }

}

impl<C: Clone, B> Clone for Client<C, B> {
    fn clone(&self) -> Client<C, B> {
        Client {
            connector: self.connector.clone(),
            executor: self.executor.clone(),
            pool: self.pool.clone(),
        }
    }
}

impl<C, B> fmt::Debug for Client<C, B> {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        f.pad("Client")
    }
}

struct HyperClient<B> {
    // A sentinel that is usually always true. If this is dropped
    // while true, this will try to shutdown the dispatcher task.
    //
    // This should be set to false whenever it is checked out of the
    // pool and successfully used to send a request.
    should_close: Cell<bool>,
    tx: RefCell<::futures::sync::mpsc::Sender<proto::dispatch::ClientMsg<B>>>,
}

impl<B> Clone for HyperClient<B> {
    fn clone(&self) -> HyperClient<B> {
        HyperClient {
            tx: self.tx.clone(),
            should_close: self.should_close.clone(),
        }
    }
}

impl<B> self::pool::Ready for HyperClient<B> {
    fn poll_ready(&mut self) -> Poll<(), ()> {
        self.tx
            .borrow_mut()
            .poll_ready()
            .map_err(|_| ())
    }
}

impl<B> Drop for HyperClient<B> {
    fn drop(&mut self) {
        if self.should_close.get() {
            self.should_close.set(false);
            let _ = self.tx.borrow_mut().try_send(proto::dispatch::ClientMsg::Close);
        }
    }
}

/// Configuration for a Client
pub struct Config<C, B> {
    _body_type: PhantomData<B>,
    //connect_timeout: Duration,
    connector: C,
    keep_alive: bool,
    keep_alive_timeout: Option<Duration>,
    //TODO: make use of max_idle config
    max_idle: usize,
    no_proto: bool,
}

/// Phantom type used to signal that `Config` should create a `HttpConnector`.
#[derive(Debug, Clone, Copy)]
pub struct UseDefaultConnector(());

impl Default for Config<UseDefaultConnector, proto::Body> {
    fn default() -> Config<UseDefaultConnector, proto::Body> {
        Config {
            _body_type: PhantomData::<proto::Body>,
            //connect_timeout: Duration::from_secs(10),
            connector: UseDefaultConnector(()),
            keep_alive: true,
            keep_alive_timeout: Some(Duration::from_secs(90)),
            max_idle: 5,
            no_proto: false,
        }
    }
}

impl<C, B> Config<C, B> {
    /// Set the body stream to be used by the `Client`.
    ///
    /// # Example
    ///
    /// ```rust
    /// # use hyper::client::Config;
    /// let cfg = Config::default()
    ///     .body::<hyper::Body>();
    /// # drop(cfg);
    #[inline]
    pub fn body<BB>(self) -> Config<C, BB> {
        Config {
            _body_type: PhantomData::<BB>,
            //connect_timeout: self.connect_timeout,
            connector: self.connector,
            keep_alive: self.keep_alive,
            keep_alive_timeout: self.keep_alive_timeout,
            max_idle: self.max_idle,
            no_proto: self.no_proto,
        }
    }

    /// Set the `Connect` type to be used.
    #[inline]
    pub fn connector<CC>(self, val: CC) -> Config<CC, B> {
        Config {
            _body_type: self._body_type,
            //connect_timeout: self.connect_timeout,
            connector: val,
            keep_alive: self.keep_alive,
            keep_alive_timeout: self.keep_alive_timeout,
            max_idle: self.max_idle,
            no_proto: self.no_proto,
        }
    }

    /// Enable or disable keep-alive mechanics.
    ///
    /// Default is enabled.
    #[inline]
    pub fn keep_alive(mut self, val: bool) -> Config<C, B> {
        self.keep_alive = val;
        self
    }

    /// Set an optional timeout for idle sockets being kept-alive.
    ///
    /// Pass `None` to disable timeout.
    ///
    /// Default is 90 seconds.
    #[inline]
    pub fn keep_alive_timeout(mut self, val: Option<Duration>) -> Config<C, B> {
        self.keep_alive_timeout = val;
        self
    }

    /*
    /// Set the timeout for connecting to a URL.
    ///
    /// Default is 10 seconds.
    #[inline]
    pub fn connect_timeout(mut self, val: Duration) -> Config<C, B> {
        self.connect_timeout = val;
        self
    }
    */

    #[doc(hidden)]
    #[deprecated(since="0.11.11", note="no_proto is always enabled")]
    pub fn no_proto(self) -> Config<C, B> {
        self
    }
}

impl<C, B> Config<C, B>
where C: Connect,
      B: Stream<Error=::Error>,
      B::Item: AsRef<[u8]>,
{
    /// Construct the Client with this configuration.
    #[inline]
    pub fn build(self, handle: &Handle) -> Client<C, B> {
        Client::configured(self, Exec::Handle(handle.clone()))
    }

    /// Construct a Client with this configuration and an executor.
    ///
    /// The executor will be used to spawn "background" connection tasks
    /// to drive requests and responses.
    pub fn executor<E>(self, executor: E) -> Client<C, B>
    where
        E: Executor<Background> + 'static,
    {
        Client::configured(self, Exec::Executor(Rc::new(executor)))
    }
}

impl<B> Config<UseDefaultConnector, B>
where B: Stream<Error=::Error>,
      B::Item: AsRef<[u8]>,
{
    /// Construct the Client with this configuration.
    #[inline]
    pub fn build(self, handle: &Handle) -> Client<HttpConnector, B> {
        self.connector(HttpConnector::new(4, handle)).build(handle)
    }
}

impl<C, B> fmt::Debug for Config<C, B> {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        f.debug_struct("Config")
            .field("keep_alive", &self.keep_alive)
            .field("keep_alive_timeout", &self.keep_alive_timeout)
            .field("max_idle", &self.max_idle)
            .finish()
    }
}

impl<C: Clone, B> Clone for Config<C, B> {
    fn clone(&self) -> Config<C, B> {
        Config {
            connector: self.connector.clone(),
            .. *self
        }
    }
}

// ===== impl Exec =====

#[derive(Clone)]
enum Exec {
    Handle(Handle),
    Executor(Rc<Executor<Background>>),
}

impl Exec {
    fn execute<F>(&self, fut: F) -> io::Result<()>
    where
        F: Future<Item=(), Error=()> + 'static,
    {
        match *self {
            Exec::Handle(ref h) => h.spawn(fut),
            Exec::Executor(ref e) => {
                e.execute(bg(Box::new(fut)))
                    .map_err(|err| {
                        debug!("executor error: {:?}", err.kind());
                        io::Error::new(
                            io::ErrorKind::Other,
                            "executor error",
                        )
                    })?
            },
        }
        Ok(())
    }
}

// ===== impl Background =====

// The types inside this module are not exported out of the crate,
// so they are in essence un-nameable.
mod background {
    use futures::{Future, Poll};

    // This is basically `impl Future`, since the type is un-nameable,
    // and only implementeds `Future`.
    #[allow(missing_debug_implementations)]
    pub struct Background {
        inner: Box<Future<Item=(), Error=()>>,
    }

    pub fn bg(fut: Box<Future<Item=(), Error=()>>) -> Background {
        Background {
            inner: fut,
        }
    }

    impl Future for Background {
        type Item = ();
        type Error = ();

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

<|endoftext|>


<commit_before>use core::cmp::{Eq, Ord};
use iter::BaseIter;

pub trait PersistentMap<K: Copy Eq Ord, V: Copy> {
  pure fn get(k: K) -> Option<V>;
  pure fn put(k: K, v: V) -> self;
  pure fn delete(k: K) -> self;
}

enum RBColor {
  Red,
  Black
}

pub enum RBMap<K: Copy Eq Ord, V: Copy> {
  //   color    left         k  value       right
  Tree(RBColor, @RBMap<K,V>, K, Option<V>, @RBMap<K,V>),
  Leaf
}

pure fn RBMap<K: Copy Eq Ord, V: Copy>(key: K, value: V) -> @RBMap<K, V> {
  @Tree(Red, @Leaf, key, Some(value), @Leaf)
}

priv impl<K: Copy Eq Ord, V: Copy> @RBMap<K, V> {
  pure fn modify(k: K, new_value: Option<V>) -> @RBMap<K, V> {
    match self {
      @Leaf => @Tree(Red, self, k, copy new_value, self),
      @Tree(color, left, key, original_value, right) => {
        if (k.lt(&key)) {
          self.balanceLeft(color, left.modify(k, new_value), key, original_value, right)
        } else if (k == key) {
          @Tree(color, left, k, copy new_value, right)
        } else {
          self.balanceRight(color, left, key, original_value, right.modify(k, new_value))
        }
      }
    }
  }

  pure fn balanceLeft(c: RBColor, l: @RBMap<K,V>, k: K, v: Option<V>, r: @RBMap<K,V>) -> @RBMap<K,V> {
    match (c, l, k, v, r) {
      (Black,@Tree(Red,@Tree(Red,a,xK,xV,b),yK,yV,c),zK,zV,d) =>
        @Tree(Red,@Tree(Black,a,xK,xV,b),yK,yV,@Tree(Black,c,zK,zV,d)),
      (c,a,xK,xV,b) =>
        @Tree(c,a,xK,xV,b)
    }
  }

  pure fn balanceRight(c: RBColor, l: @RBMap<K,V>, k: K, v: Option<V>, r: @RBMap<K,V>) -> @RBMap<K,V> {
    match (c, l, k, v, r) {
      (Black, @Tree(Red, t1, k1, v1, t2), k0, v0, @Tree(Red, t3, k2, v2, t4)) =>
        @Tree(Red, @Tree(Black, t1, k1, v1, t2), k0, v0, @Tree(Black, t3, k2, v2, t4)),
      (c, l, k, v, @Tree(Red, t1, k1, v1, t2)) =>
        @Tree(c, @Tree(Red, l, k, v, t1), k1, v1, t2),
      (c,a,xK,xV,b) =>
        @Tree(c,a,xK,xV,b)
    }
  }
}

/**
 * A purely functional Left-Leaning Red-Black Tree.
 */
impl<K: Copy Eq Ord, V: Copy> @RBMap<K, V> : PersistentMap<K, V> {
  pure fn get(k: K) -> Option<V> {
    match self {
      @Leaf => None,
      @Tree(_, left, key, maybe_value, right) => {
        if (k.lt(&key)) {
          left.get(k)
        } else if (k.gt(&key)) {
          right.get(k)
        } else {
          copy maybe_value
        }
      }
    }
  }

  pure fn put(k: K, new_value: V) -> @RBMap<K, V> {
    self.modify(k, Some(new_value))
  }

  pure fn delete(k: K) -> @RBMap<K, V> {
    self.modify(k, None)
  }
}

impl<K: Copy Eq Ord, V: Copy> RBMap<K, V>: BaseIter<(&K, &V)> {
  pure fn size_hint(&self) -> Option<uint> {
    None
  }

  pure fn each(&self, f: fn(&(&self/K, &self/V)) -> bool) {
    match *self {
      Leaf => (),
      Tree(_, ref left, ref key, ref maybe_value, ref right) => {
        let left: &self/@RBMap<K,V> = left;
        let key: &self/K = key;
        let maybe_value: &self/Option<V> = maybe_value;
        let right: &self/@RBMap<K,V> = right;
        left.each(f);
        match *maybe_value {
            Some(ref value) => {
                let value: &self/V = value;
                f(&(key, value));
            }
            None => ()
        };
        right.each(f);
      }
    }
  }
}

#[test]
fn test_rb_tree() {
  let v1 = RBMap("stevej", 150);
  let v2 = v1.put("thatstacy", 187);

  assert(v2.get("stevej") == Some(150));
  assert(v2.get("thatstacy") == Some(187));

  let v3 = v2.delete("stevej");
  assert(v3.get("stevej") == None);
  assert(v3.get("thatstacy") == Some(187));

  let v4 = v2.put("jeremy", 16);

  let v5 = v4.put("ev", 20);
  let v6 = v5.put("zhanna", 51573);

  assert(v6.get("jeremy") == Some(16));
  assert(v6.get("stevej") == Some(150));
  assert(v6.get("thatstacy") == Some(187));
  assert(v6.get("ev") == Some(20));
  assert(v6.get("zhana") == Some(51573));
}

#[test]
fn test_base_iter_each() {
  let v1 = RBMap(1, 0);
  let v2 = v1.put(4, 0);
  let v3 = v2.put(3, 0);
  let v4 = v3.put(5, 0);
  let v5 = v4.put(2, 0);

  let n = @mut 1;

  fn t(n: @mut int, kv: &(&int, &int)) -> bool{
    match kv {
      &(k, _) => {
        assert (*n == *k);
        *n += 1;
      }
    }
    false
  }

  v5.each(|z| t(n, z));
}
<commit_msg>fix broken unit test case<commit_after>use core::cmp::{Eq, Ord};
use iter::BaseIter;

pub trait PersistentMap<K: Copy Eq Ord, V: Copy> {
  pure fn get(k: K) -> Option<V>;
  pure fn put(k: K, v: V) -> self;
  pure fn delete(k: K) -> self;
}

enum RBColor {
  Red,
  Black
}

pub enum RBMap<K: Copy Eq Ord, V: Copy> {
  //   color    left         k  value       right
  Tree(RBColor, @RBMap<K,V>, K, Option<V>, @RBMap<K,V>),
  Leaf
}

pure fn RBMap<K: Copy Eq Ord, V: Copy>(key: K, value: V) -> @RBMap<K, V> {
  @Tree(Red, @Leaf, key, Some(value), @Leaf)
}

priv impl<K: Copy Eq Ord, V: Copy> @RBMap<K, V> {
  pure fn modify(k: K, new_value: Option<V>) -> @RBMap<K, V> {
    match self {
      @Leaf => @Tree(Red, self, k, copy new_value, self),
      @Tree(color, left, key, original_value, right) => {
        if (k.lt(&key)) {
          self.balanceLeft(color, left.modify(k, new_value), key, original_value, right)
        } else if (k == key) {
          @Tree(color, left, k, copy new_value, right)
        } else {
          self.balanceRight(color, left, key, original_value, right.modify(k, new_value))
        }
      }
    }
  }

  pure fn balanceLeft(c: RBColor, l: @RBMap<K,V>, k: K, v: Option<V>, r: @RBMap<K,V>) -> @RBMap<K,V> {
    match (c, l, k, v, r) {
      (Black,@Tree(Red,@Tree(Red,a,xK,xV,b),yK,yV,c),zK,zV,d) =>
        @Tree(Red,@Tree(Black,a,xK,xV,b),yK,yV,@Tree(Black,c,zK,zV,d)),
      (c,a,xK,xV,b) =>
        @Tree(c,a,xK,xV,b)
    }
  }

  pure fn balanceRight(c: RBColor, l: @RBMap<K,V>, k: K, v: Option<V>, r: @RBMap<K,V>) -> @RBMap<K,V> {
    match (c, l, k, v, r) {
      (Black, @Tree(Red, t1, k1, v1, t2), k0, v0, @Tree(Red, t3, k2, v2, t4)) =>
        @Tree(Red, @Tree(Black, t1, k1, v1, t2), k0, v0, @Tree(Black, t3, k2, v2, t4)),
      (c, l, k, v, @Tree(Red, t1, k1, v1, t2)) =>
        @Tree(c, @Tree(Red, l, k, v, t1), k1, v1, t2),
      (c,a,xK,xV,b) =>
        @Tree(c,a,xK,xV,b)
    }
  }
}

/**
 * A purely functional Left-Leaning Red-Black Tree.
 */
impl<K: Copy Eq Ord, V: Copy> @RBMap<K, V> : PersistentMap<K, V> {
  pure fn get(k: K) -> Option<V> {
    match self {
      @Leaf => None,
      @Tree(_, left, key, maybe_value, right) => {
        if (k.lt(&key)) {
          left.get(k)
        } else if (k.gt(&key)) {
          right.get(k)
        } else {
          copy maybe_value
        }
      }
    }
  }

  pure fn put(k: K, new_value: V) -> @RBMap<K, V> {
    self.modify(k, Some(new_value))
  }

  pure fn delete(k: K) -> @RBMap<K, V> {
    self.modify(k, None)
  }
}

impl<K: Copy Eq Ord, V: Copy> RBMap<K, V>: BaseIter<(&K, &V)> {
  pure fn size_hint(&self) -> Option<uint> {
    None
  }

  pure fn each(&self, f: fn(&(&self/K, &self/V)) -> bool) {
    match *self {
      Leaf => (),
      Tree(_, ref left, ref key, ref maybe_value, ref right) => {
        let left: &self/@RBMap<K,V> = left;
        let key: &self/K = key;
        let maybe_value: &self/Option<V> = maybe_value;
        let right: &self/@RBMap<K,V> = right;
        left.each(f);
        match *maybe_value {
            Some(ref value) => {
                let value: &self/V = value;
                f(&(key, value));
            }
            None => ()
        };
        right.each(f);
      }
    }
  }
}

#[test]
fn test_rb_tree() {
  let v1 = RBMap("stevej", 150);
  let v2 = v1.put("thatstacy", 187);

  assert(v2.get("stevej") == Some(150));
  assert(v2.get("thatstacy") == Some(187));

  let v3 = v2.delete("stevej");
  assert(v3.get("stevej") == None);
  assert(v3.get("thatstacy") == Some(187));

  let v4 = v2.put("jeremy", 16);

  let v5 = v4.put("ev", 20);
  let v6 = v5.put("zhanna", 51573);

  assert(v6.get("jeremy") == Some(16));
  assert(v6.get("stevej") == Some(150));
  assert(v6.get("thatstacy") == Some(187));
  assert(v6.get("ev") == Some(20));
  assert(v6.get("zhanna") == Some(51573));
}

#[test]
fn test_base_iter_each() {
  let v1 = RBMap(1, 0);
  let v2 = v1.put(4, 0);
  let v3 = v2.put(3, 0);
  let v4 = v3.put(5, 0);
  let v5 = v4.put(2, 0);

  let n = @mut 1;

  fn t(n: @mut int, kv: &(&int, &int)) -> bool{
    match kv {
      &(k, _) => {
        assert (*n == *k);
        *n += 1;
      }
    }
    false
  }

  v5.each(|z| t(n, z));
}
<|endoftext|>


<commit_before>use std::convert::TryInto;
use std::fmt::{Debug, Error, Formatter};

/// Maximum size of a [`Memory`](struct.Memory.html) block in
/// [`Word`](struct.Word.html)s
///
/// = 2^24
const MAX_MEM_SIZE: u32 = 16_777_216;

#[derive(Clone,Default)]
pub struct Word {
    val: [u8; 3],
}

impl Word {
    pub fn new() -> Self {
        Word { val: [0; 3] }
    }
}

impl Debug for Word {
    fn fmt(&self, f: &mut Formatter) -> Result<(), Error> {
        f.debug_struct("Word")
            .field("val", &format_args!("[{:?}, {:?}, {:?}]",
                                        &self.val[0],
                                        &self.val[1],
                                        &self.val[2]))
            .finish()
    }
}

#[derive(Debug)]
pub struct Memory {
    data: Vec<Word>,
    size: u32,
}

impl Memory {
    /// Creates a new `Memory` block of the given `size`.
    ///
    /// The maximum size of a `Memory` block is
    /// [`MAX_MEM_SIZE`](constant.MAX_MEM_SIZE.html). If `size` is greater
    /// than that, the created `Memory` block will be
    /// [`MAX_MEM_SIZE`](constant.MAX_MEM_SIZE.html) long.
    pub fn new(size: u32) -> Self {
        let size = if size > MAX_MEM_SIZE {
            MAX_MEM_SIZE
        } else {
            size
        };
        Memory { data: vec![Word::default(); size.try_into().unwrap()], size }
    }
}
<commit_msg>Make Word Copy<commit_after>use std::convert::TryInto;
use std::fmt::{Debug, Error, Formatter};

/// Maximum size of a [`Memory`](struct.Memory.html) block in
/// [`Word`](struct.Word.html)s
///
/// = 2^24
const MAX_MEM_SIZE: u32 = 16_777_216;

#[derive(Clone, Copy, Default)]
pub struct Word {
    val: [u8; 3],
}

impl Word {
    pub fn new() -> Self {
        Word { val: [0; 3] }
    }
}

impl Debug for Word {
    fn fmt(&self, f: &mut Formatter) -> Result<(), Error> {
        f.debug_struct("Word")
            .field("val", &format_args!("[{:?}, {:?}, {:?}]",
                                        &self.val[0],
                                        &self.val[1],
                                        &self.val[2]))
            .finish()
    }
}

#[derive(Debug)]
pub struct Memory {
    data: Vec<Word>,
    size: u32,
}

impl Memory {
    /// Creates a new `Memory` block of the given `size`.
    ///
    /// The maximum size of a `Memory` block is
    /// [`MAX_MEM_SIZE`](constant.MAX_MEM_SIZE.html). If `size` is greater
    /// than that, the created `Memory` block will be
    /// [`MAX_MEM_SIZE`](constant.MAX_MEM_SIZE.html) long.
    pub fn new(size: u32) -> Self {
        let size = if size > MAX_MEM_SIZE {
            MAX_MEM_SIZE
        } else {
            size
        };
        Memory { data: vec![Word::default(); size.try_into().unwrap()], size }
    }
}
<|endoftext|>


<commit_before>use core::prelude::*;
use core::mem::{size_of, align_of};
use core::cmp::max;
use core::ptr;

use stack::Stack;

#[allow(non_camel_case_types)]
pub type uintptr_t = u64;

pub struct Registers {
  rsp: *mut uintptr_t
}

impl Copy for Registers {}

#[inline(always)]
pub unsafe fn swap(regs: &mut Registers) {
  asm!(include_str!("swap.s")
        :
        : "{rdi}" (&mut regs.rsp)
        : "rax", "rbx", "rcx", "rdx", "rsi", "rdi",
          "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15",
          "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5", "xmm6", "xmm7",
          "xmm8", "xmm9", "xmm10", "xmm11", "xmm12", "xmm13", "xmm14", "xmm15",
          "cc"
        : "volatile");
}

#[inline]
pub unsafe fn initialize_call_frame<S, F>(stack: &mut S, f: F) -> Registers where S: Stack, F: FnOnce() {
  let sp_limit = stack.limit();
  let mut sp = stack.top() as *mut uintptr_t;
  let f_ptr = push(&mut sp, f);

  asm!(include_str!("init.s")
        : "={rdi}"(sp)
        : "{rdi}" (sp),
          "{rsi}" (rust_trampoline::<F>),
          "{rdx}" (f_ptr),
          "{rcx}" (sp_limit)
        :
        : "volatile");

  Registers { rsp: sp }
}

unsafe extern "C" fn rust_trampoline<F: FnOnce()>(f: *const F) {
  ptr::read(f)()
}

unsafe fn push<T>(spp: &mut *mut uintptr_t, value: T) -> *mut T {
  let mut sp = *spp as *mut T;
  sp = offset_mut(sp, -1);
  sp = align_down_mut(sp, max(align_of::<T>(), 16));
  *sp = value;
  *spp = sp as *mut uintptr_t;
  sp
}

fn align_down_mut<T>(sp: *mut T, n: usize) -> *mut T {
  let sp = (sp as usize) & !(n - 1);
  sp as *mut T
}

// ptr::offset_mut is positive ints only
pub fn offset_mut<T>(ptr: *mut T, count: isize) -> *mut T {
  (ptr as isize + count * (size_of::<T>() as isize)) as *mut T
}
<commit_msg>add AVX registers to clobbers, do some formatting<commit_after>use core::prelude::*;
use core::mem::{size_of, align_of};
use core::cmp::max;
use core::ptr;

use stack::Stack;

#[allow(non_camel_case_types)]
pub type uintptr_t = u64;

pub struct Registers {
  rsp: *mut uintptr_t
}

impl Copy for Registers {}

#[inline(always)]
pub unsafe fn swap(regs: &mut Registers) {
  asm!(include_str!("swap.s")
        :
        : "{rdi}" (&mut regs.rsp)
        : "rax",   "rbx",   "rcx",   "rdx",   "rsi",   "rdi", //"rbp",   "rsp",
          "r8",    "r9",    "r10",   "r11",   "r12",   "r13",   "r14",   "r15",
          "xmm0",  "xmm1",  "xmm2",  "xmm3",  "xmm4",  "xmm5",  "xmm6",  "xmm7",
          "xmm8",  "xmm9",  "xmm10", "xmm11", "xmm12", "xmm13", "xmm14", "xmm15",
          "xmm16", "xmm17", "xmm18", "xmm19", "xmm20", "xmm21", "xmm22", "xmm23",
          "xmm24", "xmm25", "xmm26", "xmm27", "xmm28", "xmm29", "xmm30", "xmm31"
          "cc"
        : "volatile");
}

#[inline]
pub unsafe fn initialize_call_frame<S, F>(stack: &mut S, f: F) -> Registers where S: Stack, F: FnOnce() {
  let sp_limit = stack.limit();
  let mut sp = stack.top() as *mut uintptr_t;
  let f_ptr = push(&mut sp, f);

  asm!(include_str!("init.s")
        : "={rdi}"(sp)
        : "{rdi}" (sp),
          "{rsi}" (rust_trampoline::<F>),
          "{rdx}" (f_ptr),
          "{rcx}" (sp_limit)
        :
        : "volatile");

  Registers { rsp: sp }
}

unsafe extern "C" fn rust_trampoline<F: FnOnce()>(f: *const F) {
  ptr::read(f)()
}

unsafe fn push<T>(spp: &mut *mut uintptr_t, value: T) -> *mut T {
  let mut sp = *spp as *mut T;
  sp = offset_mut(sp, -1);
  sp = align_down_mut(sp, max(align_of::<T>(), 16));
  *sp = value;
  *spp = sp as *mut uintptr_t;
  sp
}

fn align_down_mut<T>(sp: *mut T, n: usize) -> *mut T {
  let sp = (sp as usize) & !(n - 1);
  sp as *mut T
}

// ptr::offset_mut is positive ints only
pub fn offset_mut<T>(ptr: *mut T, count: isize) -> *mut T {
  (ptr as isize + count * (size_of::<T>() as isize)) as *mut T
}
<|endoftext|>


<commit_before>extern crate onmf;
use onmf::helpers::{ToImage, Normalize};
use onmf::testimage_generator;
use onmf::testimage_generator::{magnify};

extern crate nalgebra;
use self::nalgebra::{DMat};

extern crate rand;
use rand::{StdRng, SeedableRng};

fn main() {
    let mag_factor = 10;

    let seed: &[_] = &[1, 2, 3, 4];
    let mut rng: StdRng = SeedableRng::from_seed(seed);

    let steps = 6;
    let per_step = 1000;
    let nsamples = steps * per_step;
    let nobserved = 10 * 10;
    let nhidden = 20;

    let mut data = DMat::<f64>::new_zeros(nsamples, nobserved);

    // write on testimage into each row of data
    for (step, i, factor) in testimage_generator::testimages::<f64, _>(per_step, &mut rng) {
        let row = step * i;
        for (col, val) in factor.as_vec().iter().enumerate() {
            data[(row, col)] = val.clone();
        }
    }

    let mut nmf = onmf::OrthogonalNMF::<f64>::init_randomly(
        nhidden, nobserved, nsamples);

    // 100 iterations
    for _ in 0..100 { nmf.iterate(&data) }

    // snapshot
    // read testimage out of each row of nmf.hidden
    for irow in 0..nhidden {
        let mut column = Vec::<f64>::new();
        for icol in 0..nobserved {
            column.push(nmf.hidden[(irow, icol)]);
        }
        let image = DMat::<f64>::from_col_vec(10, 10, &column[..]);
        // println!("image {}", irow);
        // println!("{:?}", image);
        magnify(image.normalize(), mag_factor).save_to_png(&format!("orthogonal-nmf-hidden-iter-100-{}.png", irow)[..]).unwrap();
    }

    for _ in 0..10000 { nmf.iterate(&data) }

    for irow in 0..nhidden {
        let mut column = Vec::<f64>::new();
        for icol in 0..nobserved {
            column.push(nmf.hidden[(irow, icol)]);
        }
        let image = DMat::<f64>::from_col_vec(10, 10, &column[..]);
        // println!("image {}", irow);
        // println!("{:?}", image);
        magnify(image.normalize(), mag_factor).save_to_png(&format!("orthogonal-nmf-hidden-iter-final-{}.png", irow)[..]).unwrap();
    }
}
<commit_msg>ortho nmf: YES ! 200 iterations give promising results (slow though)<commit_after>extern crate onmf;
use onmf::helpers::{ToImage, Normalize};
use onmf::testimage_generator;
use onmf::testimage_generator::{magnify};

extern crate nalgebra;
use self::nalgebra::{DMat};

extern crate rand;
use rand::{StdRng, SeedableRng};

fn main() {
    let mag_factor = 10;

    let seed: &[_] = &[1, 2, 3, 4];
    let mut rng: StdRng = SeedableRng::from_seed(seed);

    let steps = 6;
    let per_step = 1000;
    let nsamples = steps * per_step;
    let nobserved = 10 * 10;
    let nhidden = 20;

    let mut data = DMat::<f64>::new_zeros(nsamples, nobserved);

    // write on testimage into each row of data
    for (step, i, factor) in testimage_generator::testimages::<f64, _>(per_step, &mut rng) {
        let row = step * i;
        for (col, val) in factor.as_vec().iter().enumerate() {
            data[(row, col)] = val.clone();
        }
    }

    let mut nmf = onmf::OrthogonalNMF::<f64>::init_randomly(
        nhidden, nobserved, nsamples);

    for _ in 0..200 { nmf.iterate(&data) }

    // take a snapshot
    // read testimage out of each row of nmf.hidden
    for irow in 0..nhidden {
        let mut column = Vec::<f64>::new();
        for icol in 0..nobserved {
            column.push(nmf.hidden[(irow, icol)]);
        }
        let image = DMat::<f64>::from_col_vec(10, 10, &column[..]);
        // println!("image {}", irow);
        // println!("{:?}", image);
        magnify(image.normalize(), mag_factor).save_to_png(&format!("orthogonal-nmf-hidden-snapshot-{}.png", irow)[..]).unwrap();
    }
}
<|endoftext|>


<commit_before>use std;
use std::fs::File;
use std::path::Path;
use std::hash::{Hash, Hasher};
use std::collections::{HashMap, HashSet};

use rss;
use serde_json;

use errors::*;

fn get_hash<T: Hash>(t: T) -> u64 {
    let mut hasher = std::collections::hash_map::DefaultHasher::default();
    t.hash(&mut hasher);
    hasher.finish()
}

type FeedID = u64;
type SubscriberID = i64;

#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct Feed {
    pub link: String,
    pub title: String,
    pub error_count: u32,
    pub subscribers: HashSet<SubscriberID>,
    hash_list: HashSet<u64>,
}

#[derive(Debug)]
pub struct Database {
    path: String,
    feeds: HashMap<FeedID, Feed>,
    subscribers: HashMap<SubscriberID, HashSet<FeedID>>,
}

fn gen_item_hash(item: &rss::Item) -> u64 {
    item.guid
        .as_ref()
        .map(|guid| get_hash(&guid.value))
        .unwrap_or_else(|| {
            let default = "".to_string();
            let title = item.title.as_ref().unwrap_or(&default);
            let link = item.link.as_ref().unwrap_or(&default);
            let string = String::with_capacity(title.len() + link.len());
            get_hash(string)
        })
}

fn truncate_hashset<T, S>(set: &mut HashSet<T, S>, u: usize)
    where T: std::hash::Hash + Clone + Eq,
          S: std::hash::BuildHasher
{
    let len = set.len();
    if len <= u {
        return;
    }
    let removed: Vec<T> = set.iter().take(u - len).map(|v| v.clone()).collect();
    for r in removed {
        set.remove(&r);
    }
}

impl Database {
    pub fn create(path: &str) -> Result<Database> {
        let feeds: HashMap<FeedID, Feed> = HashMap::new();
        let subscribers: HashMap<SubscriberID, HashSet<FeedID>> = HashMap::new();
        let mut result = Database {
            path: path.to_owned(),
            feeds: feeds,
            subscribers: subscribers,
        };

        result.save()?;

        Ok(result)
    }

    pub fn open(path: &str) -> Result<Database> {
        let p = Path::new(path);
        if p.exists() {
            let f = File::open(path).chain_err(|| ErrorKind::DatabaseOpen(path.to_owned()))?;
            let feeds_list: Vec<Feed> = serde_json::from_reader(&f).chain_err(|| ErrorKind::DatabaseFormat)?;

            let mut feeds: HashMap<FeedID, Feed> = HashMap::with_capacity(feeds_list.len());
            let mut subscribers: HashMap<SubscriberID, HashSet<FeedID>> = HashMap::new();

            for feed in feeds_list {
                let feed_id = get_hash(&feed.link);
                for subscriber in &feed.subscribers {
                    let subscribed_feeds = subscribers.entry(subscriber.to_owned())
                        .or_insert_with(|| HashSet::new());
                    subscribed_feeds.insert(feed_id);
                }
                feeds.insert(feed_id, feed);
            }

            Ok(Database {
                path: path.to_owned(),
                feeds: feeds,
                subscribers: subscribers,
            })
        } else {
            Database::create(path)
        }
    }

    pub fn get_all_feeds(&self) -> Vec<Feed> {
        self.feeds.iter().map(|(_, v)| v.clone()).collect()
    }

    pub fn get_subscribed_feeds(&self, subscriber: SubscriberID) -> Option<Vec<&Feed>> {
        self.subscribers.get(&subscriber).map(|feeds| {
            feeds.iter()
                .map(|feed_id| &self.feeds[feed_id])
                .collect()
        })
    }

    pub fn inc_error_count(&mut self, rss_link: &str) -> u32 {
        let feed_id = get_hash(rss_link);
        self.feeds
            .get_mut(&feed_id)
            .map(|feed| {
                feed.error_count += 1;
                feed.error_count
            })
            .unwrap_or_default()
    }

    pub fn is_subscribed(&self, subscriber: SubscriberID, rss_link: &str) -> bool {
        self.subscribers.get(&subscriber).map(|feeds| feeds.contains(&get_hash(rss_link))).unwrap_or(false)
    }

    pub fn subscribe(&mut self, subscriber: SubscriberID, rss_link: &str, rss: &rss::Channel) -> Result<()> {
        let feed_id = get_hash(rss_link);
        {
            let subscribed_feeds = self.subscribers.entry(subscriber).or_insert_with(|| HashSet::new());
            if !subscribed_feeds.insert(feed_id) {
                return Err(ErrorKind::AlreadySubscribed.into());
            }
        }
        {
            let feed = self.feeds.entry(feed_id).or_insert_with(|| {
                Feed {
                    link: rss_link.to_owned(),
                    title: rss.title.to_owned(),
                    error_count: 0,
                    hash_list: rss.items.iter().map(gen_item_hash).collect(),
                    subscribers: HashSet::new(),
                }
            });
            feed.subscribers.insert(subscriber);
        }
        self.save()
    }

    pub fn unsubscribe(&mut self, subscriber: SubscriberID, rss_link: &str) -> Result<Feed> {
        let feed_id = get_hash(rss_link);

        {
            let mut clear_subscriber = false;
            self.subscribers
                .get_mut(&subscriber)
                .map(|subscribed_feeds| if !subscribed_feeds.remove(&feed_id) {
                    Err::<(), Error>(ErrorKind::NotSubscribed.into())
                } else {
                    clear_subscriber = subscribed_feeds.len() == 0;
                    Ok(())
                })
                .unwrap_or(Err(ErrorKind::NotSubscribed.into()))?;
            if clear_subscriber {
                self.subscribers.remove(&subscriber);
            }
        }
        let result;
        {
            let mut clear_feed = false;
            result = self.feeds
                .get_mut(&feed_id)
                .map(|feed| if !feed.subscribers.remove(&subscriber) {
                    Err::<Feed, Error>(ErrorKind::NotSubscribed.into())
                } else {
                    clear_feed = feed.subscribers.len() == 0;
                    Ok(feed.clone())
                })
                .unwrap_or(Err(ErrorKind::NotSubscribed.into()))?;
            if clear_feed {
                self.feeds.remove(&feed_id);
            }
        }
        self.save()?;
        Ok(result)
    }

    pub fn update<'a>(&mut self, rss_link: &str, items: Vec<rss::Item>) -> Vec<rss::Item> {
        let feed_id = get_hash(rss_link);
        let mut result = Vec::new();
        let mut new_hash = Vec::new();
        let items_len = items.len();
        for item in items {
            let hash = gen_item_hash(&item);
            if !self.feeds[&feed_id].hash_list.contains(&hash) {
                result.push(item);
                new_hash.push(hash);
            }
        }
        if !new_hash.is_empty() {
            self.feeds.get_mut(&feed_id).map(|feed| {
                truncate_hashset(&mut feed.hash_list, items_len * 2 - new_hash.len());
                for hash in new_hash {
                    feed.hash_list.insert(hash);
                }
            });
        }
        self.save().unwrap_or_default();
        result
    }

    fn save(&mut self) -> Result<()> {
        let feeds_list: Vec<&Feed> = self.feeds.iter().map(|(_id, feed)| feed).collect();
        let mut file = File::create(&self.path).chain_err(|| ErrorKind::DatabaseSave(self.path.to_owned()))?;
        serde_json::to_writer(&mut file, &feeds_list).chain_err(|| ErrorKind::DatabaseSave(self.path.to_owned()))
    }
}
<commit_msg>fix: wrong hash when the feed has no guid element<commit_after>use std;
use std::fs::File;
use std::path::Path;
use std::hash::{Hash, Hasher};
use std::collections::{HashMap, HashSet};

use rss;
use serde_json;

use errors::*;

fn get_hash<T: Hash>(t: T) -> u64 {
    let mut hasher = std::collections::hash_map::DefaultHasher::default();
    t.hash(&mut hasher);
    hasher.finish()
}

type FeedID = u64;
type SubscriberID = i64;

#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct Feed {
    pub link: String,
    pub title: String,
    pub error_count: u32,
    pub subscribers: HashSet<SubscriberID>,
    hash_list: HashSet<u64>,
}

#[derive(Debug)]
pub struct Database {
    path: String,
    feeds: HashMap<FeedID, Feed>,
    subscribers: HashMap<SubscriberID, HashSet<FeedID>>,
}

fn gen_item_hash(item: &rss::Item) -> u64 {
    item.guid
        .as_ref()
        .map(|guid| get_hash(&guid.value))
        .unwrap_or_else(|| {
            let title = item.title.as_ref().map(|s| s.as_str()).unwrap_or_default();
            let link = item.link.as_ref().map(|s| s.as_str()).unwrap_or_default();
            get_hash(format!("{}{}", title, link))
        })
}

fn truncate_hashset<T, S>(set: &mut HashSet<T, S>, u: usize)
    where T: std::hash::Hash + Clone + Eq,
          S: std::hash::BuildHasher
{
    let len = set.len();
    if len <= u {
        return;
    }
    let removed: Vec<T> = set.iter().take(u - len).map(|v| v.clone()).collect();
    for r in removed {
        set.remove(&r);
    }
}

impl Database {
    pub fn create(path: &str) -> Result<Database> {
        let feeds: HashMap<FeedID, Feed> = HashMap::new();
        let subscribers: HashMap<SubscriberID, HashSet<FeedID>> = HashMap::new();
        let mut result = Database {
            path: path.to_owned(),
            feeds: feeds,
            subscribers: subscribers,
        };

        result.save()?;

        Ok(result)
    }

    pub fn open(path: &str) -> Result<Database> {
        let p = Path::new(path);
        if p.exists() {
            let f = File::open(path).chain_err(|| ErrorKind::DatabaseOpen(path.to_owned()))?;
            let feeds_list: Vec<Feed> = serde_json::from_reader(&f).chain_err(|| ErrorKind::DatabaseFormat)?;

            let mut feeds: HashMap<FeedID, Feed> = HashMap::with_capacity(feeds_list.len());
            let mut subscribers: HashMap<SubscriberID, HashSet<FeedID>> = HashMap::new();

            for feed in feeds_list {
                let feed_id = get_hash(&feed.link);
                for subscriber in &feed.subscribers {
                    let subscribed_feeds = subscribers.entry(subscriber.to_owned())
                        .or_insert_with(|| HashSet::new());
                    subscribed_feeds.insert(feed_id);
                }
                feeds.insert(feed_id, feed);
            }

            Ok(Database {
                path: path.to_owned(),
                feeds: feeds,
                subscribers: subscribers,
            })
        } else {
            Database::create(path)
        }
    }

    pub fn get_all_feeds(&self) -> Vec<Feed> {
        self.feeds.iter().map(|(_, v)| v.clone()).collect()
    }

    pub fn get_subscribed_feeds(&self, subscriber: SubscriberID) -> Option<Vec<&Feed>> {
        self.subscribers.get(&subscriber).map(|feeds| {
            feeds.iter()
                .map(|feed_id| &self.feeds[feed_id])
                .collect()
        })
    }

    pub fn inc_error_count(&mut self, rss_link: &str) -> u32 {
        let feed_id = get_hash(rss_link);
        self.feeds
            .get_mut(&feed_id)
            .map(|feed| {
                feed.error_count += 1;
                feed.error_count
            })
            .unwrap_or_default()
    }

    pub fn is_subscribed(&self, subscriber: SubscriberID, rss_link: &str) -> bool {
        self.subscribers.get(&subscriber).map(|feeds| feeds.contains(&get_hash(rss_link))).unwrap_or(false)
    }

    pub fn subscribe(&mut self, subscriber: SubscriberID, rss_link: &str, rss: &rss::Channel) -> Result<()> {
        let feed_id = get_hash(rss_link);
        {
            let subscribed_feeds = self.subscribers.entry(subscriber).or_insert_with(|| HashSet::new());
            if !subscribed_feeds.insert(feed_id) {
                return Err(ErrorKind::AlreadySubscribed.into());
            }
        }
        {
            let feed = self.feeds.entry(feed_id).or_insert_with(|| {
                Feed {
                    link: rss_link.to_owned(),
                    title: rss.title.to_owned(),
                    error_count: 0,
                    hash_list: rss.items.iter().map(gen_item_hash).collect(),
                    subscribers: HashSet::new(),
                }
            });
            feed.subscribers.insert(subscriber);
        }
        self.save()
    }

    pub fn unsubscribe(&mut self, subscriber: SubscriberID, rss_link: &str) -> Result<Feed> {
        let feed_id = get_hash(rss_link);

        {
            let mut clear_subscriber = false;
            self.subscribers
                .get_mut(&subscriber)
                .map(|subscribed_feeds| if !subscribed_feeds.remove(&feed_id) {
                    Err::<(), Error>(ErrorKind::NotSubscribed.into())
                } else {
                    clear_subscriber = subscribed_feeds.len() == 0;
                    Ok(())
                })
                .unwrap_or(Err(ErrorKind::NotSubscribed.into()))?;
            if clear_subscriber {
                self.subscribers.remove(&subscriber);
            }
        }
        let result;
        {
            let mut clear_feed = false;
            result = self.feeds
                .get_mut(&feed_id)
                .map(|feed| if !feed.subscribers.remove(&subscriber) {
                    Err::<Feed, Error>(ErrorKind::NotSubscribed.into())
                } else {
                    clear_feed = feed.subscribers.len() == 0;
                    Ok(feed.clone())
                })
                .unwrap_or(Err(ErrorKind::NotSubscribed.into()))?;
            if clear_feed {
                self.feeds.remove(&feed_id);
            }
        }
        self.save()?;
        Ok(result)
    }

    pub fn update<'a>(&mut self, rss_link: &str, items: Vec<rss::Item>) -> Vec<rss::Item> {
        let feed_id = get_hash(rss_link);
        let mut result = Vec::new();
        let mut new_hash = Vec::new();
        let items_len = items.len();
        for item in items {
            let hash = gen_item_hash(&item);
            if !self.feeds[&feed_id].hash_list.contains(&hash) {
                result.push(item);
                new_hash.push(hash);
            }
        }
        if !new_hash.is_empty() {
            self.feeds.get_mut(&feed_id).map(|feed| {
                truncate_hashset(&mut feed.hash_list, items_len * 2 - new_hash.len());
                for hash in new_hash {
                    feed.hash_list.insert(hash);
                }
            });
        }
        self.save().unwrap_or_default();
        result
    }

    fn save(&mut self) -> Result<()> {
        let feeds_list: Vec<&Feed> = self.feeds.iter().map(|(_id, feed)| feed).collect();
        let mut file = File::create(&self.path).chain_err(|| ErrorKind::DatabaseSave(self.path.to_owned()))?;
        serde_json::to_writer(&mut file, &feeds_list).chain_err(|| ErrorKind::DatabaseSave(self.path.to_owned()))
    }
}
<|endoftext|>