<commit_before>
use libc::{c_uint, c_int, c_float, c_uchar};
use std::fmt::{Show, Error, Formatter};
use std::time::duration::Duration;

use connection::{FromConn, MpdConnection, mpd_connection};
use serialize::{Encoder, Encodable};

#[repr(C)] struct mpd_status;

#[repr(C)]
#[deriving(Show)]
struct mpd_audio_format {
    sample_rate: u32,
    bits: u8,
    channels: u8,

    reserved0: u16,
    reserved1: u32
}

#[deriving(Show, Encodable)]
pub struct AudioFormat {
    pub rate: u32,
    pub bits: u8,
    pub chans: u8
}

#[repr(C)]
#[deriving(Show, Encodable)]
pub enum MpdState {
    Unknown = 0,
    Stop = 1,
    Play = 2,
    Pause = 3,
}

#[link(name = "mpdclient")]
extern "C" {
    fn mpd_run_status(connection: *mut mpd_connection) -> *mut mpd_status;
    fn mpd_status_free(status: *mut mpd_status);
    fn mpd_status_get_volume(status: *const mpd_status) -> c_int;
    fn mpd_status_get_repeat(status: *const mpd_status) -> bool;
    fn mpd_status_get_random(status: *const mpd_status) -> bool;
    fn mpd_status_get_single(status: *const mpd_status) -> bool;
    fn mpd_status_get_consume(status: *const mpd_status) -> bool;
    fn mpd_status_get_queue_length(status: *const mpd_status) -> c_uint;
    fn mpd_status_get_queue_version(status: *const mpd_status) -> c_uint;
    fn mpd_status_get_state(status: *const mpd_status) -> MpdState;
    fn mpd_status_get_crossfade(status: *const mpd_status) -> c_uint;
    fn mpd_status_get_mixrampdb(status: *const mpd_status) -> c_float;
    fn mpd_status_get_mixrampdelay(status: *const mpd_status) -> c_float;
    fn mpd_status_get_song_pos(status: *const mpd_status) -> c_int;
    fn mpd_status_get_song_id(status: *const mpd_status) -> c_int;
    fn mpd_status_get_next_song_pos(status: *const mpd_status) -> c_int;
    fn mpd_status_get_next_song_id(status: *const mpd_status) -> c_int;
    //fn mpd_status_get_elapsed_time(status: *const mpd_status) -> c_uint;
    fn mpd_status_get_elapsed_ms(status: *const mpd_status) -> c_uint;
    fn mpd_status_get_total_time(status: *const mpd_status) -> c_uint;
    fn mpd_status_get_kbit_rate(status: *const mpd_status) -> c_uint;
    fn mpd_status_get_audio_format(status: *const mpd_status) -> *const mpd_audio_format;
    fn mpd_status_get_update_id(status: *const mpd_status) -> c_uint;
    fn mpd_status_get_error(status: *const mpd_status) -> *const c_uchar;
}

pub struct MpdStatus {
    p: *mut mpd_status
}

impl<S: Encoder<E>, E> Encodable<S, E> for MpdStatus {
    fn encode(&self, s: &mut S) -> Result<(), E> {
        s.emit_struct("MpdStatus", 19, |s| {
            s.emit_struct_field("volume", 0, |s| s.emit_int(self.volume())).and_then(|()|
            s.emit_struct_field("repeat", 1, |s| s.emit_bool(self.repeat()))).and_then(|()|
            s.emit_struct_field("random", 2, |s| s.emit_bool(self.random()))).and_then(|()|
            s.emit_struct_field("single", 3, |s| s.emit_bool(self.single()))).and_then(|()|
            s.emit_struct_field("consume", 4, |s| s.emit_bool(self.consume()))).and_then(|()|
            s.emit_struct_field("state", 5, |s| self.state().encode(s))).and_then(|()|
            s.emit_struct_field("crossfade", 6, |s| s.emit_i64(self.crossfade().num_milliseconds()))).and_then(|()|
            s.emit_struct_field("queue_length", 7, |s| s.emit_uint(self.queue_len()))).and_then(|()|
            s.emit_struct_field("queue_version", 8, |s| s.emit_uint(self.queue_version()))).and_then(|()|
            s.emit_struct_field("mixrampdb", 9, |s| s.emit_f32(self.mixrampdb()))).and_then(|()|
            s.emit_struct_field("mixrampdelay", 10, |s| s.emit_option(|s| match self.mixrampdelay() {
                Some(ref d) => s.emit_option_some(|s| s.emit_i64(d.num_milliseconds())),
                None => s.emit_option_none()
            }))).and_then(|()|
            s.emit_struct_field("song", 11, |s| s.emit_option(|s| match self.song() {
                Some(ref v) => s.emit_option_some(|s| v.encode(s)),
                None => s.emit_option_none()
            }))).and_then(|()|
            s.emit_struct_field("next_song", 12, |s| s.emit_option(|s| match self.next_song() {
                Some(ref v) => s.emit_option_some(|s| v.encode(s)),
                None => s.emit_option_none()
            }))).and_then(|()|
            s.emit_struct_field("elapsed_time", 13, |s| s.emit_i64(self.elapsed_time().num_milliseconds()))).and_then(|()|
            s.emit_struct_field("total_time", 14, |s| s.emit_i64(self.elapsed_time().num_milliseconds()))).and_then(|()|
            s.emit_struct_field("kbit_rate", 15, |s| s.emit_uint(self.kbit_rate()))).and_then(|()|
            s.emit_struct_field("audio_format", 16, |s| self.audio_format().encode(s))).and_then(|()|
            s.emit_struct_field("update_id", 17, |s| s.emit_uint(self.update_id()))).and_then(|()|
            s.emit_struct_field("error", 18, |s| s.emit_option(|s| match self.error() {
                Some(ref e) => s.emit_option_some(|s| s.emit_str(e[])),
                None => s.emit_option_none()
            })))
        })
    }
}

impl Show for MpdStatus {
    fn fmt(&self, f: &mut Formatter) -> Result<(), Error> {
        try!(f.write(b"MpdStatus { volume: "));
        try!(self.volume().fmt(f));
        try!(f.write(b", repeat: "));
        try!(self.repeat().fmt(f));
        try!(f.write(b", random: "));
        try!(self.random().fmt(f));
        try!(f.write(b", single: "));
        try!(self.single().fmt(f));
        try!(f.write(b", consume: "));
        try!(self.consume().fmt(f));
        try!(f.write(b", state: "));
        try!(self.state().fmt(f));
        try!(f.write(b", crossfade: "));
        try!(self.crossfade().fmt(f));
        try!(f.write(b", queue_len: "));
        try!(self.queue_len().fmt(f));
        try!(f.write(b", queue_version: "));
        try!(self.queue_version().fmt(f));
        try!(f.write(b", mixrampdb: "));
        try!(self.mixrampdb().fmt(f));
        try!(f.write(b", mixrampdelay: "));
        try!(self.mixrampdelay().fmt(f));
        try!(f.write(b", song: "));
        try!(self.song().fmt(f));
        try!(f.write(b", next_song: "));
        try!(self.next_song().fmt(f));
        try!(f.write(b", elapsed_time: "));
        try!(self.elapsed_time().fmt(f));
        try!(f.write(b", total_time: "));
        try!(self.total_time().fmt(f));
        try!(f.write(b", kbit_rate: "));
        try!(self.kbit_rate().fmt(f));
        try!(f.write(b", audio_format: "));
        try!(self.audio_format().fmt(f));
        try!(f.write(b", update_id: "));
        try!(self.update_id().fmt(f));
        try!(f.write(b", error: "));
        try!(self.error().fmt(f));
        try!(f.write(b" }"));
        Ok(())
    }
}

impl FromConn for MpdStatus {
    fn from_conn(conn: &MpdConnection) -> Option<MpdStatus> {
        let status = unsafe { mpd_run_status(conn.conn) };
        if status.is_null() {
            return None;
        }

        Some(MpdStatus { p: status })
    }
}

impl MpdStatus {
    pub fn volume(&self) -> int { unsafe { mpd_status_get_volume(self.p as *const _) as int } }
    pub fn repeat(&self) -> bool { unsafe { mpd_status_get_repeat(self.p as *const _) } }
    pub fn random(&self) -> bool { unsafe { mpd_status_get_random(self.p as *const _) } }
    pub fn single(&self) -> bool { unsafe { mpd_status_get_single(self.p as *const _) } }
    pub fn consume(&self) -> bool { unsafe { mpd_status_get_consume(self.p as *const _) } }
    pub fn state(&self) -> MpdState { unsafe { mpd_status_get_state(self.p as *const _) } }
    pub fn crossfade(&self) -> Duration { Duration::seconds(unsafe { mpd_status_get_crossfade(self.p as *const _) as i64 }) }
    pub fn queue_len(&self) -> uint { unsafe { mpd_status_get_queue_length(self.p as *const _) as uint } }
    pub fn queue_version(&self) -> uint { unsafe { mpd_status_get_queue_version(self.p as *const _) as uint } }
    pub fn mixrampdb(&self) -> f32 { unsafe { mpd_status_get_mixrampdb(self.p as *const _) } }
    pub fn mixrampdelay(&self) -> Option<Duration> { let v = unsafe { mpd_status_get_mixrampdelay(self.p as *const _) }; if v < 0f32 { None } else { Some(Duration::milliseconds((v * 1000f32) as i64)) } }
    pub fn song(&self) -> Option<(uint, uint)> {
        let song_id = unsafe { mpd_status_get_song_id(self.p as *const _) };
        if song_id < 0 { None } else { Some((song_id as uint, unsafe { mpd_status_get_song_pos(self.p as *const _) as uint })) }
    }
    pub fn next_song(&self) -> Option<(uint, uint)> {
        let song_id = unsafe { mpd_status_get_next_song_id(self.p as *const _) };
        if song_id < 0 { None } else { Some((song_id as uint, unsafe { mpd_status_get_next_song_pos(self.p as *const _) as uint })) }
    }
    pub fn elapsed_time(&self) -> Duration { Duration::milliseconds(unsafe { mpd_status_get_elapsed_ms(self.p as *const _) as i64 }) }
    pub fn total_time(&self) -> Duration { Duration::seconds(unsafe { mpd_status_get_total_time(self.p as *const _) as i64 }) }
    pub fn kbit_rate(&self) -> uint { unsafe { mpd_status_get_kbit_rate(self.p as *const _) as uint } }
    pub fn audio_format(&self) -> Option<AudioFormat> {
        let aformat = unsafe { mpd_status_get_audio_format(self.p as *const _) };
        if aformat.is_null() { None } else { Some(unsafe { AudioFormat { rate: (*aformat).sample_rate, bits: (*aformat).bits, chans: (*aformat).channels } }) }
    }
    pub fn update_id(&self) -> uint { unsafe { mpd_status_get_update_id(self.p as *const _) as uint } }
    pub fn error(&self) -> Option<String> {
        let error = unsafe { mpd_status_get_error(self.p as *const _) };
        if error.is_null() { None } else { Some(unsafe { String::from_raw_buf(error) }) }
    }
}

impl Drop for MpdStatus {
    fn drop(&mut self) {
        unsafe { mpd_status_free(self.p) }
    }
}

<commit_msg>fix total time<commit_after>
use libc::{c_uint, c_int, c_float, c_uchar};
use std::fmt::{Show, Error, Formatter};
use std::time::duration::Duration;

use connection::{FromConn, MpdConnection, mpd_connection};
use serialize::{Encoder, Encodable};

#[repr(C)] struct mpd_status;

#[repr(C)]
#[deriving(Show)]
struct mpd_audio_format {
    sample_rate: u32,
    bits: u8,
    channels: u8,

    reserved0: u16,
    reserved1: u32
}

#[deriving(Show, Encodable)]
pub struct AudioFormat {
    pub rate: u32,
    pub bits: u8,
    pub chans: u8
}

#[repr(C)]
#[deriving(Show, Encodable)]
pub enum MpdState {
    Unknown = 0,
    Stop = 1,
    Play = 2,
    Pause = 3,
}

#[link(name = "mpdclient")]
extern "C" {
    fn mpd_run_status(connection: *mut mpd_connection) -> *mut mpd_status;
    fn mpd_status_free(status: *mut mpd_status);
    fn mpd_status_get_volume(status: *const mpd_status) -> c_int;
    fn mpd_status_get_repeat(status: *const mpd_status) -> bool;
    fn mpd_status_get_random(status: *const mpd_status) -> bool;
    fn mpd_status_get_single(status: *const mpd_status) -> bool;
    fn mpd_status_get_consume(status: *const mpd_status) -> bool;
    fn mpd_status_get_queue_length(status: *const mpd_status) -> c_uint;
    fn mpd_status_get_queue_version(status: *const mpd_status) -> c_uint;
    fn mpd_status_get_state(status: *const mpd_status) -> MpdState;
    fn mpd_status_get_crossfade(status: *const mpd_status) -> c_uint;
    fn mpd_status_get_mixrampdb(status: *const mpd_status) -> c_float;
    fn mpd_status_get_mixrampdelay(status: *const mpd_status) -> c_float;
    fn mpd_status_get_song_pos(status: *const mpd_status) -> c_int;
    fn mpd_status_get_song_id(status: *const mpd_status) -> c_int;
    fn mpd_status_get_next_song_pos(status: *const mpd_status) -> c_int;
    fn mpd_status_get_next_song_id(status: *const mpd_status) -> c_int;
    //fn mpd_status_get_elapsed_time(status: *const mpd_status) -> c_uint;
    fn mpd_status_get_elapsed_ms(status: *const mpd_status) -> c_uint;
    fn mpd_status_get_total_time(status: *const mpd_status) -> c_uint;
    fn mpd_status_get_kbit_rate(status: *const mpd_status) -> c_uint;
    fn mpd_status_get_audio_format(status: *const mpd_status) -> *const mpd_audio_format;
    fn mpd_status_get_update_id(status: *const mpd_status) -> c_uint;
    fn mpd_status_get_error(status: *const mpd_status) -> *const c_uchar;
}

pub struct MpdStatus {
    p: *mut mpd_status
}

impl<S: Encoder<E>, E> Encodable<S, E> for MpdStatus {
    fn encode(&self, s: &mut S) -> Result<(), E> {
        s.emit_struct("MpdStatus", 19, |s| {
            s.emit_struct_field("volume", 0, |s| s.emit_int(self.volume())).and_then(|()|
            s.emit_struct_field("repeat", 1, |s| s.emit_bool(self.repeat()))).and_then(|()|
            s.emit_struct_field("random", 2, |s| s.emit_bool(self.random()))).and_then(|()|
            s.emit_struct_field("single", 3, |s| s.emit_bool(self.single()))).and_then(|()|
            s.emit_struct_field("consume", 4, |s| s.emit_bool(self.consume()))).and_then(|()|
            s.emit_struct_field("state", 5, |s| self.state().encode(s))).and_then(|()|
            s.emit_struct_field("crossfade", 6, |s| s.emit_i64(self.crossfade().num_milliseconds()))).and_then(|()|
            s.emit_struct_field("queue_length", 7, |s| s.emit_uint(self.queue_len()))).and_then(|()|
            s.emit_struct_field("queue_version", 8, |s| s.emit_uint(self.queue_version()))).and_then(|()|
            s.emit_struct_field("mixrampdb", 9, |s| s.emit_f32(self.mixrampdb()))).and_then(|()|
            s.emit_struct_field("mixrampdelay", 10, |s| s.emit_option(|s| match self.mixrampdelay() {
                Some(ref d) => s.emit_option_some(|s| s.emit_i64(d.num_milliseconds())),
                None => s.emit_option_none()
            }))).and_then(|()|
            s.emit_struct_field("song", 11, |s| s.emit_option(|s| match self.song() {
                Some(ref v) => s.emit_option_some(|s| v.encode(s)),
                None => s.emit_option_none()
            }))).and_then(|()|
            s.emit_struct_field("next_song", 12, |s| s.emit_option(|s| match self.next_song() {
                Some(ref v) => s.emit_option_some(|s| v.encode(s)),
                None => s.emit_option_none()
            }))).and_then(|()|
            s.emit_struct_field("elapsed_time", 13, |s| s.emit_i64(self.elapsed_time().num_milliseconds()))).and_then(|()|
            s.emit_struct_field("total_time", 14, |s| s.emit_i64(self.total_time().num_milliseconds()))).and_then(|()|
            s.emit_struct_field("kbit_rate", 15, |s| s.emit_uint(self.kbit_rate()))).and_then(|()|
            s.emit_struct_field("audio_format", 16, |s| self.audio_format().encode(s))).and_then(|()|
            s.emit_struct_field("update_id", 17, |s| s.emit_uint(self.update_id()))).and_then(|()|
            s.emit_struct_field("error", 18, |s| s.emit_option(|s| match self.error() {
                Some(ref e) => s.emit_option_some(|s| s.emit_str(e[])),
                None => s.emit_option_none()
            })))
        })
    }
}

impl Show for MpdStatus {
    fn fmt(&self, f: &mut Formatter) -> Result<(), Error> {
        try!(f.write(b"MpdStatus { volume: "));
        try!(self.volume().fmt(f));
        try!(f.write(b", repeat: "));
        try!(self.repeat().fmt(f));
        try!(f.write(b", random: "));
        try!(self.random().fmt(f));
        try!(f.write(b", single: "));
        try!(self.single().fmt(f));
        try!(f.write(b", consume: "));
        try!(self.consume().fmt(f));
        try!(f.write(b", state: "));
        try!(self.state().fmt(f));
        try!(f.write(b", crossfade: "));
        try!(self.crossfade().fmt(f));
        try!(f.write(b", queue_len: "));
        try!(self.queue_len().fmt(f));
        try!(f.write(b", queue_version: "));
        try!(self.queue_version().fmt(f));
        try!(f.write(b", mixrampdb: "));
        try!(self.mixrampdb().fmt(f));
        try!(f.write(b", mixrampdelay: "));
        try!(self.mixrampdelay().fmt(f));
        try!(f.write(b", song: "));
        try!(self.song().fmt(f));
        try!(f.write(b", next_song: "));
        try!(self.next_song().fmt(f));
        try!(f.write(b", elapsed_time: "));
        try!(self.elapsed_time().fmt(f));
        try!(f.write(b", total_time: "));
        try!(self.total_time().fmt(f));
        try!(f.write(b", kbit_rate: "));
        try!(self.kbit_rate().fmt(f));
        try!(f.write(b", audio_format: "));
        try!(self.audio_format().fmt(f));
        try!(f.write(b", update_id: "));
        try!(self.update_id().fmt(f));
        try!(f.write(b", error: "));
        try!(self.error().fmt(f));
        try!(f.write(b" }"));
        Ok(())
    }
}

impl FromConn for MpdStatus {
    fn from_conn(conn: &MpdConnection) -> Option<MpdStatus> {
        let status = unsafe { mpd_run_status(conn.conn) };
        if status.is_null() {
            return None;
        }

        Some(MpdStatus { p: status })
    }
}

impl MpdStatus {
    pub fn volume(&self) -> int { unsafe { mpd_status_get_volume(self.p as *const _) as int } }
    pub fn repeat(&self) -> bool { unsafe { mpd_status_get_repeat(self.p as *const _) } }
    pub fn random(&self) -> bool { unsafe { mpd_status_get_random(self.p as *const _) } }
    pub fn single(&self) -> bool { unsafe { mpd_status_get_single(self.p as *const _) } }
    pub fn consume(&self) -> bool { unsafe { mpd_status_get_consume(self.p as *const _) } }
    pub fn state(&self) -> MpdState { unsafe { mpd_status_get_state(self.p as *const _) } }
    pub fn crossfade(&self) -> Duration { Duration::seconds(unsafe { mpd_status_get_crossfade(self.p as *const _) as i64 }) }
    pub fn queue_len(&self) -> uint { unsafe { mpd_status_get_queue_length(self.p as *const _) as uint } }
    pub fn queue_version(&self) -> uint { unsafe { mpd_status_get_queue_version(self.p as *const _) as uint } }
    pub fn mixrampdb(&self) -> f32 { unsafe { mpd_status_get_mixrampdb(self.p as *const _) } }
    pub fn mixrampdelay(&self) -> Option<Duration> { let v = unsafe { mpd_status_get_mixrampdelay(self.p as *const _) }; if v < 0f32 { None } else { Some(Duration::milliseconds((v * 1000f32) as i64)) } }
    pub fn song(&self) -> Option<(uint, uint)> {
        let song_id = unsafe { mpd_status_get_song_id(self.p as *const _) };
        if song_id < 0 { None } else { Some((song_id as uint, unsafe { mpd_status_get_song_pos(self.p as *const _) as uint })) }
    }
    pub fn next_song(&self) -> Option<(uint, uint)> {
        let song_id = unsafe { mpd_status_get_next_song_id(self.p as *const _) };
        if song_id < 0 { None } else { Some((song_id as uint, unsafe { mpd_status_get_next_song_pos(self.p as *const _) as uint })) }
    }
    pub fn elapsed_time(&self) -> Duration { Duration::milliseconds(unsafe { mpd_status_get_elapsed_ms(self.p as *const _) as i64 }) }
    pub fn total_time(&self) -> Duration { Duration::seconds(unsafe { mpd_status_get_total_time(self.p as *const _) as i64 }) }
    pub fn kbit_rate(&self) -> uint { unsafe { mpd_status_get_kbit_rate(self.p as *const _) as uint } }
    pub fn audio_format(&self) -> Option<AudioFormat> {
        let aformat = unsafe { mpd_status_get_audio_format(self.p as *const _) };
        if aformat.is_null() { None } else { Some(unsafe { AudioFormat { rate: (*aformat).sample_rate, bits: (*aformat).bits, chans: (*aformat).channels } }) }
    }
    pub fn update_id(&self) -> uint { unsafe { mpd_status_get_update_id(self.p as *const _) as uint } }
    pub fn error(&self) -> Option<String> {
        let error = unsafe { mpd_status_get_error(self.p as *const _) };
        if error.is_null() { None } else { Some(unsafe { String::from_raw_buf(error) }) }
    }
}

impl Drop for MpdStatus {
    fn drop(&mut self) {
        unsafe { mpd_status_free(self.p) }
    }
}

<|endoftext|>


<commit_before>use std::cell::UnsafeCell;
use std::cmp;
use std::collections::HashMap;
use std::fmt;
use std::marker::PhantomData;
use std::mem;
use std::sync::atomic::{AtomicUsize, Ordering, ATOMIC_USIZE_INIT};

use errors::InvalidThreadAccess;

fn next_item_id() -> usize {
    static mut COUNTER: AtomicUsize = ATOMIC_USIZE_INIT;
    unsafe { COUNTER.fetch_add(1, Ordering::SeqCst) }
}

struct Registry(HashMap<usize, (UnsafeCell<*mut ()>, Box<Fn(&UnsafeCell<*mut ()>)>)>);

impl Drop for Registry {
    fn drop(&mut self) {
        for (_, value) in self.0.iter() {
            (value.1)(&value.0);
        }
    }
}

thread_local!(static REGISTRY: UnsafeCell<Registry> = UnsafeCell::new(Registry(Default::default())));

/// A `Sticky<T>` keeps a value T stored in a thread.
///
/// This type works similar in nature to `Fragile<T>` and exposes the
/// same interface.  The difference is that whereas `Fragile<T>` has
/// its destructor called in the thread where the value was sent, a
/// `Sticky<T>` that is moved to another thread will have the internal
/// destructor called when the originating thread tears down.
///
/// As this uses TLS internally the general rules about the platform limitations
/// of destructors for TLS apply.
pub struct Sticky<T> {
    item_id: usize,
    _marker: PhantomData<*mut T>,
}

impl<T> Drop for Sticky<T> {
    fn drop(&mut self) {
        if mem::needs_drop::<T>() {
            unsafe {
                if self.is_valid() {
                    self.unsafe_take_value();
                }
            }
        }
    }
}

impl<T> Sticky<T> {
    /// Creates a new `Sticky` wrapping a `value`.
    ///
    /// The value that is moved into the `Sticky` can be non `Send` and
    /// will be anchored to the thread that created the object.  If the
    /// sticky wrapper type ends up being send from thread to thread
    /// only the original thread can interact with the value.
    pub fn new(value: T) -> Self {
        let item_id = next_item_id();
        REGISTRY.with(|registry| unsafe {
            (*registry.get()).0.insert(
                item_id,
                (
                    UnsafeCell::new(Box::into_raw(Box::new(value)) as *mut _),
                    Box::new(|cell| {
                        let b: Box<T> = Box::from_raw(*(cell.get() as *mut *mut T));
                        mem::drop(b);
                    }),
                ),
            );
        });
        Sticky {
            item_id: item_id,
            _marker: PhantomData,
        }
    }

    #[inline(always)]
    fn with_value<F: FnOnce(&UnsafeCell<Box<T>>) -> R, R>(&self, f: F) -> R {
        REGISTRY.with(|registry| unsafe {
            let reg = &(*(*registry).get()).0;
            if let Some(item) = reg.get(&self.item_id) {
                f(mem::transmute(&item.0))
            } else {
                panic!("trying to access wrapped value in sticky container from incorrect thread.");
            }
        })
    }

    /// Returns `true` if the access is valid.
    ///
    /// This will be `false` if the value was sent to another thread.
    #[inline(always)]
    pub fn is_valid(&self) -> bool {
        unsafe { REGISTRY.with(|registry| (*registry.get()).0.contains_key(&self.item_id)) }
    }

    #[inline(always)]
    fn assert_thread(&self) {
        if !self.is_valid() {
            panic!("trying to access wrapped value in sticky container from incorrect thread.");
        }
    }

    /// Consumes the `Sticky`, returning the wrapped value.
    ///
    /// # Panics
    ///
    /// Panics if called from a different thread than the one where the
    /// original value was created.
    pub fn into_inner(mut self) -> T {
        self.assert_thread();
        unsafe {
            let rv = self.unsafe_take_value();
            mem::forget(self);
            rv
        }
    }

    unsafe fn unsafe_take_value(&mut self) -> T {
        let ptr = REGISTRY
            .with(|registry| (*registry.get()).0.remove(&self.item_id))
            .unwrap()
            .0
            .into_inner();
        let rv = Box::from_raw(ptr as *mut T);
        *rv
    }

    /// Consumes the `Sticky`, returning the wrapped value if successful.
    ///
    /// The wrapped value is returned if this is called from the same thread
    /// as the one where the original value was created, otherwise the
    /// `Sticky` is returned as `Err(self)`.
    pub fn try_into_inner(self) -> Result<T, Self> {
        if self.is_valid() {
            Ok(self.into_inner())
        } else {
            Err(self)
        }
    }

    /// Immutably borrows the wrapped value.
    ///
    /// # Panics
    ///
    /// Panics if the calling thread is not the one that wrapped the value.
    /// For a non-panicking variant, use [`try_get`](#method.try_get`).
    pub fn get(&self) -> &T {
        self.with_value(|value| unsafe { &*value.get() })
    }

    /// Mutably borrows the wrapped value.
    ///
    /// # Panics
    ///
    /// Panics if the calling thread is not the one that wrapped the value.
    /// For a non-panicking variant, use [`try_get_mut`](#method.try_get_mut`).
    pub fn get_mut(&mut self) -> &mut T {
        self.with_value(|value| unsafe { &mut *value.get() })
    }

    /// Tries to immutably borrow the wrapped value.
    ///
    /// Returns `None` if the calling thread is not the one that wrapped the value.
    pub fn try_get(&self) -> Result<&T, InvalidThreadAccess> {
        if self.is_valid() {
            unsafe { Ok(self.with_value(|value| &*value.get())) }
        } else {
            Err(InvalidThreadAccess)
        }
    }

    /// Tries to mutably borrow the wrapped value.
    ///
    /// Returns `None` if the calling thread is not the one that wrapped the value.
    pub fn try_get_mut(&mut self) -> Result<&mut T, InvalidThreadAccess> {
        if self.is_valid() {
            unsafe { Ok(self.with_value(|value| &mut *value.get())) }
        } else {
            Err(InvalidThreadAccess)
        }
    }
}

impl<T> From<T> for Sticky<T> {
    #[inline]
    fn from(t: T) -> Sticky<T> {
        Sticky::new(t)
    }
}

impl<T: Clone> Clone for Sticky<T> {
    #[inline]
    fn clone(&self) -> Sticky<T> {
        Sticky::new(self.get().clone())
    }
}

impl<T: Default> Default for Sticky<T> {
    #[inline]
    fn default() -> Sticky<T> {
        Sticky::new(T::default())
    }
}

impl<T: PartialEq> PartialEq for Sticky<T> {
    #[inline]
    fn eq(&self, other: &Sticky<T>) -> bool {
        *self.get() == *other.get()
    }
}

impl<T: Eq> Eq for Sticky<T> {}

impl<T: PartialOrd> PartialOrd for Sticky<T> {
    #[inline]
    fn partial_cmp(&self, other: &Sticky<T>) -> Option<cmp::Ordering> {
        self.get().partial_cmp(&*other.get())
    }

    #[inline]
    fn lt(&self, other: &Sticky<T>) -> bool {
        *self.get() < *other.get()
    }

    #[inline]
    fn le(&self, other: &Sticky<T>) -> bool {
        *self.get() <= *other.get()
    }

    #[inline]
    fn gt(&self, other: &Sticky<T>) -> bool {
        *self.get() > *other.get()
    }

    #[inline]
    fn ge(&self, other: &Sticky<T>) -> bool {
        *self.get() >= *other.get()
    }
}

impl<T: Ord> Ord for Sticky<T> {
    #[inline]
    fn cmp(&self, other: &Sticky<T>) -> cmp::Ordering {
        self.get().cmp(&*other.get())
    }
}

impl<T: fmt::Display> fmt::Display for Sticky<T> {
    fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
        fmt::Display::fmt(self.get(), f)
    }
}

impl<T: fmt::Debug> fmt::Debug for Sticky<T> {
    fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
        match self.try_get() {
            Ok(value) => f.debug_struct("Sticky").field("value", value).finish(),
            Err(..) => {
                struct InvalidPlaceholder;
                impl fmt::Debug for InvalidPlaceholder {
                    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
                        f.write_str("<invalid thread>")
                    }
                }

                f.debug_struct("Sticky")
                    .field("value", &InvalidPlaceholder)
                    .finish()
            }
        }
    }
}

// similar as for fragile ths type is sync because it only accesses TLS data
// which is thread local.  There is nothing that needs to be synchronized.
unsafe impl<T> Sync for Sticky<T> {}

// The entire point of this type is to be Send
unsafe impl<T> Send for Sticky<T> {}

#[test]
fn test_basic() {
    use std::thread;
    let val = Sticky::new(true);
    assert_eq!(val.to_string(), "true");
    assert_eq!(val.get(), &true);
    assert!(val.try_get().is_ok());
    thread::spawn(move || {
        assert!(val.try_get().is_err());
    }).join()
        .unwrap();
}

#[test]
fn test_mut() {
    let mut val = Sticky::new(true);
    *val.get_mut() = false;
    assert_eq!(val.to_string(), "false");
    assert_eq!(val.get(), &false);
}

#[test]
#[should_panic]
fn test_access_other_thread() {
    use std::thread;
    let val = Sticky::new(true);
    thread::spawn(move || {
        val.get();
    }).join()
        .unwrap();
}

#[test]
fn test_drop_same_thread() {
    use std::sync::atomic::{AtomicBool, Ordering};
    use std::sync::Arc;
    let was_called = Arc::new(AtomicBool::new(false));
    struct X(Arc<AtomicBool>);
    impl Drop for X {
        fn drop(&mut self) {
            self.0.store(true, Ordering::SeqCst);
        }
    }
    let val = Sticky::new(X(was_called.clone()));
    mem::drop(val);
    assert_eq!(was_called.load(Ordering::SeqCst), true);
}

#[test]
fn test_noop_drop_elsewhere() {
    use std::sync::atomic::{AtomicBool, Ordering};
    use std::sync::Arc;
    use std::thread;

    let was_called = Arc::new(AtomicBool::new(false));

    {
        let was_called = was_called.clone();
        thread::spawn(move || {
            struct X(Arc<AtomicBool>);
            impl Drop for X {
                fn drop(&mut self) {
                    self.0.store(true, Ordering::SeqCst);
                }
            }

            let val = Sticky::new(X(was_called.clone()));
            assert!(
                thread::spawn(move || {
                    // moves it here but do not deallocate
                    val.try_get().ok();
                }).join()
                    .is_ok()
            );

            assert_eq!(was_called.load(Ordering::SeqCst), false);
        }).join()
            .unwrap();
    }

    assert_eq!(was_called.load(Ordering::SeqCst), true);
}

#[test]
fn test_rc_sending() {
    use std::rc::Rc;
    use std::thread;
    let val = Sticky::new(Rc::new(true));
    thread::spawn(move || {
        assert!(val.try_get().is_err());
    }).join().unwrap();
}
<commit_msg>Do not panic on TLS teardown. Fixes #2<commit_after>use std::cell::UnsafeCell;
use std::cmp;
use std::collections::HashMap;
use std::fmt;
use std::marker::PhantomData;
use std::mem;
use std::sync::atomic::{AtomicUsize, Ordering, ATOMIC_USIZE_INIT};

use errors::InvalidThreadAccess;

fn next_item_id() -> usize {
    static mut COUNTER: AtomicUsize = ATOMIC_USIZE_INIT;
    unsafe { COUNTER.fetch_add(1, Ordering::SeqCst) }
}

struct Registry(HashMap<usize, (UnsafeCell<*mut ()>, Box<Fn(&UnsafeCell<*mut ()>)>)>);

impl Drop for Registry {
    fn drop(&mut self) {
        for (_, value) in self.0.iter() {
            (value.1)(&value.0);
        }
    }
}

thread_local!(static REGISTRY: UnsafeCell<Registry> = UnsafeCell::new(Registry(Default::default())));

/// A `Sticky<T>` keeps a value T stored in a thread.
///
/// This type works similar in nature to `Fragile<T>` and exposes the
/// same interface.  The difference is that whereas `Fragile<T>` has
/// its destructor called in the thread where the value was sent, a
/// `Sticky<T>` that is moved to another thread will have the internal
/// destructor called when the originating thread tears down.
///
/// As this uses TLS internally the general rules about the platform limitations
/// of destructors for TLS apply.
pub struct Sticky<T> {
    item_id: usize,
    _marker: PhantomData<*mut T>,
}

impl<T> Drop for Sticky<T> {
    fn drop(&mut self) {
        if mem::needs_drop::<T>() {
            unsafe {
                if self.is_valid() {
                    self.unsafe_take_value();
                }
            }
        }
    }
}

impl<T> Sticky<T> {
    /// Creates a new `Sticky` wrapping a `value`.
    ///
    /// The value that is moved into the `Sticky` can be non `Send` and
    /// will be anchored to the thread that created the object.  If the
    /// sticky wrapper type ends up being send from thread to thread
    /// only the original thread can interact with the value.
    pub fn new(value: T) -> Self {
        let item_id = next_item_id();
        REGISTRY.with(|registry| unsafe {
            (*registry.get()).0.insert(
                item_id,
                (
                    UnsafeCell::new(Box::into_raw(Box::new(value)) as *mut _),
                    Box::new(|cell| {
                        let b: Box<T> = Box::from_raw(*(cell.get() as *mut *mut T));
                        mem::drop(b);
                    }),
                ),
            );
        });
        Sticky {
            item_id: item_id,
            _marker: PhantomData,
        }
    }

    #[inline(always)]
    fn with_value<F: FnOnce(&UnsafeCell<Box<T>>) -> R, R>(&self, f: F) -> R {
        REGISTRY.with(|registry| unsafe {
            let reg = &(*(*registry).get()).0;
            if let Some(item) = reg.get(&self.item_id) {
                f(mem::transmute(&item.0))
            } else {
                panic!("trying to access wrapped value in sticky container from incorrect thread.");
            }
        })
    }

    /// Returns `true` if the access is valid.
    ///
    /// This will be `false` if the value was sent to another thread.
    #[inline(always)]
    pub fn is_valid(&self) -> bool {
        // We use `try-with` here to avoid crashing if the TLS is already tearing down.
        unsafe { REGISTRY.try_with(|registry| (*registry.get()).0.contains_key(&self.item_id)).unwrap_or(false) }
    }

    #[inline(always)]
    fn assert_thread(&self) {
        if !self.is_valid() {
            panic!("trying to access wrapped value in sticky container from incorrect thread.");
        }
    }

    /// Consumes the `Sticky`, returning the wrapped value.
    ///
    /// # Panics
    ///
    /// Panics if called from a different thread than the one where the
    /// original value was created.
    pub fn into_inner(mut self) -> T {
        self.assert_thread();
        unsafe {
            let rv = self.unsafe_take_value();
            mem::forget(self);
            rv
        }
    }

    unsafe fn unsafe_take_value(&mut self) -> T {
        let ptr = REGISTRY
            .with(|registry| (*registry.get()).0.remove(&self.item_id))
            .unwrap()
            .0
            .into_inner();
        let rv = Box::from_raw(ptr as *mut T);
        *rv
    }

    /// Consumes the `Sticky`, returning the wrapped value if successful.
    ///
    /// The wrapped value is returned if this is called from the same thread
    /// as the one where the original value was created, otherwise the
    /// `Sticky` is returned as `Err(self)`.
    pub fn try_into_inner(self) -> Result<T, Self> {
        if self.is_valid() {
            Ok(self.into_inner())
        } else {
            Err(self)
        }
    }

    /// Immutably borrows the wrapped value.
    ///
    /// # Panics
    ///
    /// Panics if the calling thread is not the one that wrapped the value.
    /// For a non-panicking variant, use [`try_get`](#method.try_get`).
    pub fn get(&self) -> &T {
        self.with_value(|value| unsafe { &*value.get() })
    }

    /// Mutably borrows the wrapped value.
    ///
    /// # Panics
    ///
    /// Panics if the calling thread is not the one that wrapped the value.
    /// For a non-panicking variant, use [`try_get_mut`](#method.try_get_mut`).
    pub fn get_mut(&mut self) -> &mut T {
        self.with_value(|value| unsafe { &mut *value.get() })
    }

    /// Tries to immutably borrow the wrapped value.
    ///
    /// Returns `None` if the calling thread is not the one that wrapped the value.
    pub fn try_get(&self) -> Result<&T, InvalidThreadAccess> {
        if self.is_valid() {
            unsafe { Ok(self.with_value(|value| &*value.get())) }
        } else {
            Err(InvalidThreadAccess)
        }
    }

    /// Tries to mutably borrow the wrapped value.
    ///
    /// Returns `None` if the calling thread is not the one that wrapped the value.
    pub fn try_get_mut(&mut self) -> Result<&mut T, InvalidThreadAccess> {
        if self.is_valid() {
            unsafe { Ok(self.with_value(|value| &mut *value.get())) }
        } else {
            Err(InvalidThreadAccess)
        }
    }
}

impl<T> From<T> for Sticky<T> {
    #[inline]
    fn from(t: T) -> Sticky<T> {
        Sticky::new(t)
    }
}

impl<T: Clone> Clone for Sticky<T> {
    #[inline]
    fn clone(&self) -> Sticky<T> {
        Sticky::new(self.get().clone())
    }
}

impl<T: Default> Default for Sticky<T> {
    #[inline]
    fn default() -> Sticky<T> {
        Sticky::new(T::default())
    }
}

impl<T: PartialEq> PartialEq for Sticky<T> {
    #[inline]
    fn eq(&self, other: &Sticky<T>) -> bool {
        *self.get() == *other.get()
    }
}

impl<T: Eq> Eq for Sticky<T> {}

impl<T: PartialOrd> PartialOrd for Sticky<T> {
    #[inline]
    fn partial_cmp(&self, other: &Sticky<T>) -> Option<cmp::Ordering> {
        self.get().partial_cmp(&*other.get())
    }

    #[inline]
    fn lt(&self, other: &Sticky<T>) -> bool {
        *self.get() < *other.get()
    }

    #[inline]
    fn le(&self, other: &Sticky<T>) -> bool {
        *self.get() <= *other.get()
    }

    #[inline]
    fn gt(&self, other: &Sticky<T>) -> bool {
        *self.get() > *other.get()
    }

    #[inline]
    fn ge(&self, other: &Sticky<T>) -> bool {
        *self.get() >= *other.get()
    }
}

impl<T: Ord> Ord for Sticky<T> {
    #[inline]
    fn cmp(&self, other: &Sticky<T>) -> cmp::Ordering {
        self.get().cmp(&*other.get())
    }
}

impl<T: fmt::Display> fmt::Display for Sticky<T> {
    fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
        fmt::Display::fmt(self.get(), f)
    }
}

impl<T: fmt::Debug> fmt::Debug for Sticky<T> {
    fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
        match self.try_get() {
            Ok(value) => f.debug_struct("Sticky").field("value", value).finish(),
            Err(..) => {
                struct InvalidPlaceholder;
                impl fmt::Debug for InvalidPlaceholder {
                    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
                        f.write_str("<invalid thread>")
                    }
                }

                f.debug_struct("Sticky")
                    .field("value", &InvalidPlaceholder)
                    .finish()
            }
        }
    }
}

// similar as for fragile ths type is sync because it only accesses TLS data
// which is thread local.  There is nothing that needs to be synchronized.
unsafe impl<T> Sync for Sticky<T> {}

// The entire point of this type is to be Send
unsafe impl<T> Send for Sticky<T> {}

#[test]
fn test_basic() {
    use std::thread;
    let val = Sticky::new(true);
    assert_eq!(val.to_string(), "true");
    assert_eq!(val.get(), &true);
    assert!(val.try_get().is_ok());
    thread::spawn(move || {
        assert!(val.try_get().is_err());
    }).join()
        .unwrap();
}

#[test]
fn test_mut() {
    let mut val = Sticky::new(true);
    *val.get_mut() = false;
    assert_eq!(val.to_string(), "false");
    assert_eq!(val.get(), &false);
}

#[test]
#[should_panic]
fn test_access_other_thread() {
    use std::thread;
    let val = Sticky::new(true);
    thread::spawn(move || {
        val.get();
    }).join()
        .unwrap();
}

#[test]
fn test_drop_same_thread() {
    use std::sync::atomic::{AtomicBool, Ordering};
    use std::sync::Arc;
    let was_called = Arc::new(AtomicBool::new(false));
    struct X(Arc<AtomicBool>);
    impl Drop for X {
        fn drop(&mut self) {
            self.0.store(true, Ordering::SeqCst);
        }
    }
    let val = Sticky::new(X(was_called.clone()));
    mem::drop(val);
    assert_eq!(was_called.load(Ordering::SeqCst), true);
}

#[test]
fn test_noop_drop_elsewhere() {
    use std::sync::atomic::{AtomicBool, Ordering};
    use std::sync::Arc;
    use std::thread;

    let was_called = Arc::new(AtomicBool::new(false));

    {
        let was_called = was_called.clone();
        thread::spawn(move || {
            struct X(Arc<AtomicBool>);
            impl Drop for X {
                fn drop(&mut self) {
                    self.0.store(true, Ordering::SeqCst);
                }
            }

            let val = Sticky::new(X(was_called.clone()));
            assert!(
                thread::spawn(move || {
                    // moves it here but do not deallocate
                    val.try_get().ok();
                }).join()
                    .is_ok()
            );

            assert_eq!(was_called.load(Ordering::SeqCst), false);
        }).join()
            .unwrap();
    }

    assert_eq!(was_called.load(Ordering::SeqCst), true);
}

#[test]
fn test_rc_sending() {
    use std::rc::Rc;
    use std::thread;
    let val = Sticky::new(Rc::new(true));
    thread::spawn(move || {
        assert!(val.try_get().is_err());
    }).join().unwrap();
}
<|endoftext|>


<commit_before>use super::TokenStreamExt;

use std::borrow::Cow;

use proc_macro2::{Group, Literal, Punct, Span, Ident, TokenStream, TokenTree};

/// Types that can be interpolated inside a [`quote!`] invocation.
///
/// [`quote!`]: macro.quote.html
pub trait ToTokens {
    /// Write `self` to the given `Tokens`.
    ///
    /// Example implementation for a struct representing Rust paths like
    /// `std::cmp::PartialEq`:
    ///
    /// ```
    /// extern crate quote;
    /// use quote::{TokenStreamExt, ToTokens};
    ///
    /// extern crate proc_macro2;
    /// use proc_macro2::{TokenTree, Spacing, Span, Punct, TokenStream};
    ///
    /// pub struct Path {
    ///     pub global: bool,
    ///     pub segments: Vec<PathSegment>,
    /// }
    ///
    /// impl ToTokens for Path {
    ///     fn to_tokens(&self, tokens: &mut TokenStream) {
    ///         for (i, segment) in self.segments.iter().enumerate() {
    ///             if i > 0 || self.global {
    ///                 // Double colon `::`
    ///                 tokens.append(Punct::new(':', Spacing::Joint));
    ///                 tokens.append(Punct::new(':', Spacing::Alone));
    ///             }
    ///             segment.to_tokens(tokens);
    ///         }
    ///     }
    /// }
    /// #
    /// # pub struct PathSegment;
    /// #
    /// # impl ToTokens for PathSegment {
    /// #     fn to_tokens(&self, tokens: &mut TokenStream) {
    /// #         unimplemented!()
    /// #     }
    /// # }
    /// #
    /// # fn main() {}
    /// ```
    fn to_tokens(&self, tokens: &mut TokenStream);

    /// Convert `self` directly into a `Tokens` object.
    ///
    /// This method is implicitly implemented using `to_tokens`, and acts as a
    /// convenience method for consumers of the `ToTokens` trait.
    fn into_token_stream(self) -> TokenStream
    where
        Self: Sized,
    {
        let mut tokens = TokenStream::empty();
        self.to_tokens(&mut tokens);
        tokens
    }
}

impl<'a, T: ?Sized + ToTokens> ToTokens for &'a T {
    fn to_tokens(&self, tokens: &mut TokenStream) {
        (**self).to_tokens(tokens);
    }
}

impl<'a, T: ?Sized + ToOwned + ToTokens> ToTokens for Cow<'a, T> {
    fn to_tokens(&self, tokens: &mut TokenStream) {
        (**self).to_tokens(tokens);
    }
}

impl<T: ?Sized + ToTokens> ToTokens for Box<T> {
    fn to_tokens(&self, tokens: &mut TokenStream) {
        (**self).to_tokens(tokens);
    }
}

impl<T: ToTokens> ToTokens for Option<T> {
    fn to_tokens(&self, tokens: &mut TokenStream) {
        if let Some(ref t) = *self {
            t.to_tokens(tokens);
        }
    }
}

impl ToTokens for str {
    fn to_tokens(&self, tokens: &mut TokenStream) {
        tokens.append(Literal::string(self));
    }
}

impl ToTokens for String {
    fn to_tokens(&self, tokens: &mut TokenStream) {
        self.as_str().to_tokens(tokens);
    }
}

macro_rules! primitive {
    ($($t:ident => $name:ident)*) => ($(
        impl ToTokens for $t {
            fn to_tokens(&self, tokens: &mut TokenStream) {
                tokens.append(Literal::$name(*self));
            }
        }
    )*)
}

primitive! {
    i8 => i8_suffixed
    i16 => i16_suffixed
    i32 => i32_suffixed
    i64 => i64_suffixed
    isize => isize_suffixed

    u8 => u8_suffixed
    u16 => u16_suffixed
    u32 => u32_suffixed
    u64 => u64_suffixed
    usize => usize_suffixed

    f32 => f32_suffixed
    f64 => f64_suffixed
}

impl ToTokens for char {
    fn to_tokens(&self, tokens: &mut TokenStream) {
        tokens.append(Literal::character(*self));
    }
}

impl ToTokens for bool {
    fn to_tokens(&self, tokens: &mut TokenStream) {
        let word = if *self { "true" } else { "false" };
        tokens.append(Ident::new(word, Span::call_site()));
    }
}

impl ToTokens for Group {
    fn to_tokens(&self, tokens: &mut TokenStream) {
        tokens.append(self.clone());
    }
}

impl ToTokens for Ident {
    fn to_tokens(&self, tokens: &mut TokenStream) {
        tokens.append(self.clone());
    }
}

impl ToTokens for Punct {
    fn to_tokens(&self, tokens: &mut TokenStream) {
        tokens.append(self.clone());
    }
}

impl ToTokens for Literal {
    fn to_tokens(&self, tokens: &mut TokenStream) {
        tokens.append(self.clone());
    }
}

impl ToTokens for TokenTree {
    fn to_tokens(&self, dst: &mut TokenStream) {
        dst.append(self.clone());
    }
}

impl ToTokens for TokenStream {
    fn to_tokens(&self, dst: &mut TokenStream) {
        dst.append_all(self.clone().into_iter());
    }
}
<commit_msg>Optimize into_token_stream for TokenStream<commit_after>use super::TokenStreamExt;

use std::borrow::Cow;

use proc_macro2::{Group, Literal, Punct, Span, Ident, TokenStream, TokenTree};

/// Types that can be interpolated inside a [`quote!`] invocation.
///
/// [`quote!`]: macro.quote.html
pub trait ToTokens {
    /// Write `self` to the given `Tokens`.
    ///
    /// Example implementation for a struct representing Rust paths like
    /// `std::cmp::PartialEq`:
    ///
    /// ```
    /// extern crate quote;
    /// use quote::{TokenStreamExt, ToTokens};
    ///
    /// extern crate proc_macro2;
    /// use proc_macro2::{TokenTree, Spacing, Span, Punct, TokenStream};
    ///
    /// pub struct Path {
    ///     pub global: bool,
    ///     pub segments: Vec<PathSegment>,
    /// }
    ///
    /// impl ToTokens for Path {
    ///     fn to_tokens(&self, tokens: &mut TokenStream) {
    ///         for (i, segment) in self.segments.iter().enumerate() {
    ///             if i > 0 || self.global {
    ///                 // Double colon `::`
    ///                 tokens.append(Punct::new(':', Spacing::Joint));
    ///                 tokens.append(Punct::new(':', Spacing::Alone));
    ///             }
    ///             segment.to_tokens(tokens);
    ///         }
    ///     }
    /// }
    /// #
    /// # pub struct PathSegment;
    /// #
    /// # impl ToTokens for PathSegment {
    /// #     fn to_tokens(&self, tokens: &mut TokenStream) {
    /// #         unimplemented!()
    /// #     }
    /// # }
    /// #
    /// # fn main() {}
    /// ```
    fn to_tokens(&self, tokens: &mut TokenStream);

    /// Convert `self` directly into a `Tokens` object.
    ///
    /// This method is implicitly implemented using `to_tokens`, and acts as a
    /// convenience method for consumers of the `ToTokens` trait.
    fn into_token_stream(self) -> TokenStream
    where
        Self: Sized,
    {
        let mut tokens = TokenStream::empty();
        self.to_tokens(&mut tokens);
        tokens
    }
}

impl<'a, T: ?Sized + ToTokens> ToTokens for &'a T {
    fn to_tokens(&self, tokens: &mut TokenStream) {
        (**self).to_tokens(tokens);
    }
}

impl<'a, T: ?Sized + ToOwned + ToTokens> ToTokens for Cow<'a, T> {
    fn to_tokens(&self, tokens: &mut TokenStream) {
        (**self).to_tokens(tokens);
    }
}

impl<T: ?Sized + ToTokens> ToTokens for Box<T> {
    fn to_tokens(&self, tokens: &mut TokenStream) {
        (**self).to_tokens(tokens);
    }
}

impl<T: ToTokens> ToTokens for Option<T> {
    fn to_tokens(&self, tokens: &mut TokenStream) {
        if let Some(ref t) = *self {
            t.to_tokens(tokens);
        }
    }
}

impl ToTokens for str {
    fn to_tokens(&self, tokens: &mut TokenStream) {
        tokens.append(Literal::string(self));
    }
}

impl ToTokens for String {
    fn to_tokens(&self, tokens: &mut TokenStream) {
        self.as_str().to_tokens(tokens);
    }
}

macro_rules! primitive {
    ($($t:ident => $name:ident)*) => ($(
        impl ToTokens for $t {
            fn to_tokens(&self, tokens: &mut TokenStream) {
                tokens.append(Literal::$name(*self));
            }
        }
    )*)
}

primitive! {
    i8 => i8_suffixed
    i16 => i16_suffixed
    i32 => i32_suffixed
    i64 => i64_suffixed
    isize => isize_suffixed

    u8 => u8_suffixed
    u16 => u16_suffixed
    u32 => u32_suffixed
    u64 => u64_suffixed
    usize => usize_suffixed

    f32 => f32_suffixed
    f64 => f64_suffixed
}

impl ToTokens for char {
    fn to_tokens(&self, tokens: &mut TokenStream) {
        tokens.append(Literal::character(*self));
    }
}

impl ToTokens for bool {
    fn to_tokens(&self, tokens: &mut TokenStream) {
        let word = if *self { "true" } else { "false" };
        tokens.append(Ident::new(word, Span::call_site()));
    }
}

impl ToTokens for Group {
    fn to_tokens(&self, tokens: &mut TokenStream) {
        tokens.append(self.clone());
    }
}

impl ToTokens for Ident {
    fn to_tokens(&self, tokens: &mut TokenStream) {
        tokens.append(self.clone());
    }
}

impl ToTokens for Punct {
    fn to_tokens(&self, tokens: &mut TokenStream) {
        tokens.append(self.clone());
    }
}

impl ToTokens for Literal {
    fn to_tokens(&self, tokens: &mut TokenStream) {
        tokens.append(self.clone());
    }
}

impl ToTokens for TokenTree {
    fn to_tokens(&self, dst: &mut TokenStream) {
        dst.append(self.clone());
    }
}

impl ToTokens for TokenStream {
    fn to_tokens(&self, dst: &mut TokenStream) {
        dst.append_all(self.clone().into_iter());
    }

    fn into_token_stream(self) -> TokenStream {
        self
    }
}
<|endoftext|>


<commit_before>pub enum Token {
    Comma,
    Number(f64),
    ParenClose,
    ParenOpen,
    Word(String),
}

pub fn tokenize(input: &str) -> Tokenizer {
    Tokenizer {text: String::from_str(input)}
}

fn is_whitespace(c: char) -> bool {
    match c {
        '\n' | '\r' | '\t' | ' ' => true,
        _                        => false,
    }
}

fn is_numberlike(c: char) -> bool {
    match c {
        c if c.is_numeric() => true,
        '.' | '-'           => true,
        _                   => false,
    }
}

struct Tokenizer {
    text: String
}

impl Iterator<Token> for Tokenizer {
    fn next(&mut self) -> Option<Token> {
        let popped_char = self.pop_char();
        if popped_char.is_none() {
            return None
        }
        let next_char = popped_char.unwrap();

        match next_char {
            '\0' => None,
            '(' => Some(Token::ParenOpen),
            ')' => Some(Token::ParenClose),
            ',' => Some(Token::Comma),
            c if is_whitespace(c) => self.next(),
            c if is_numberlike(c) => {
                let number = c.to_string() + self.read_until_whitespace().as_slice();
                let x: f64 = number.parse().unwrap();
                Some(Token::Number(x))
            }
            c => {
                let word = c.to_string() + self.read_until_whitespace().as_slice();
                Some(Token::Word(word))
            }
        }
    }
}

impl Tokenizer {
    fn pop_char(&mut self) -> Option<char> {
        if self.text.is_empty() {
            None
        } else {
            self.text.remove(0)
        }
    }

    fn read_until_whitespace(&mut self) -> String {
        let popped_char = self.pop_char();
        if popped_char.is_none() {
            return "".to_string()
        }
        let next_char = popped_char.unwrap();

        match next_char {
            '\0' | '(' | ')' | ',' => {
                self.text.insert(0, next_char);
                "".to_string()
            }
            c if is_whitespace(c) => "".to_string(),
            _ => next_char.to_string() + self.read_until_whitespace().as_slice(),
        }
    }

    /*
    fn finish_number(&mut self) -> String {
    }
    */
}

#[test]
fn test_tokenizer_1word() {
    let test_str = "hello";
    let mut tokens = tokenize(test_str);
    match tokens.next().unwrap() {
        Token::Word(n) => assert_eq!(n, "hello".to_string()),
        _ => panic!("fail")
    }
    assert!(tokens.next().is_none());
}

#[test]
fn test_tokenizer_2words() {
    let test_str = "hello world";
    let mut tokens = tokenize(test_str);
    match tokens.next().unwrap() {
        Token::Word(n) => assert_eq!(n, "hello".to_string()),
        _ => panic!("fail")
    }
    match tokens.next().unwrap() {
        Token::Word(n) => assert_eq!(n, "world".to_string()),
        _ => panic!("fail")
    }
    assert!(tokens.next().is_none());
}

#[test]
fn test_tokenizer_1number() {
    let test_str = "4.2";
    let mut tokens = tokenize(test_str);
    match tokens.next().unwrap() {
        Token::Number(n) => assert_eq!(n.to_string(), "4.2"),
        _ => panic!("fail")
    }
    assert!(tokens.next().is_none());
}

#[test]
fn test_tokenizer_2numbers() {
    let test_str = ".38 -2";
    let mut tokens = tokenize(test_str);
    match tokens.next().unwrap() {
        Token::Number(n) => assert_eq!(n.to_string(), "0.38"),
        _ => panic!("fail")
    }
    match tokens.next().unwrap() {
        Token::Number(n) => assert_eq!(n.to_string(), "-2"),
        _ => panic!("fail")
    }
    assert!(tokens.next().is_none());
}
<commit_msg>Simplify test asserts<commit_after>pub enum Token {
    Comma,
    Number(f64),
    ParenClose,
    ParenOpen,
    Word(String),
}

pub fn tokenize(input: &str) -> Tokenizer {
    Tokenizer {text: String::from_str(input)}
}

fn is_whitespace(c: char) -> bool {
    match c {
        '\n' | '\r' | '\t' | ' ' => true,
        _                        => false,
    }
}

fn is_numberlike(c: char) -> bool {
    match c {
        c if c.is_numeric() => true,
        '.' | '-'           => true,
        _                   => false,
    }
}

struct Tokenizer {
    text: String
}

impl Iterator<Token> for Tokenizer {
    fn next(&mut self) -> Option<Token> {
        let popped_char = self.pop_char();
        if popped_char.is_none() {
            return None
        }
        let next_char = popped_char.unwrap();

        match next_char {
            '\0' => None,
            '(' => Some(Token::ParenOpen),
            ')' => Some(Token::ParenClose),
            ',' => Some(Token::Comma),
            c if is_whitespace(c) => self.next(),
            c if is_numberlike(c) => {
                let number = c.to_string() + self.read_until_whitespace().as_slice();
                let x: f64 = number.parse().unwrap();
                Some(Token::Number(x))
            }
            c => {
                let word = c.to_string() + self.read_until_whitespace().as_slice();
                Some(Token::Word(word))
            }
        }
    }
}

impl Tokenizer {
    fn pop_char(&mut self) -> Option<char> {
        if self.text.is_empty() {
            None
        } else {
            self.text.remove(0)
        }
    }

    fn read_until_whitespace(&mut self) -> String {
        let popped_char = self.pop_char();
        if popped_char.is_none() {
            return "".to_string()
        }
        let next_char = popped_char.unwrap();

        match next_char {
            '\0' | '(' | ')' | ',' => {
                self.text.insert(0, next_char);
                "".to_string()
            }
            c if is_whitespace(c) => "".to_string(),
            _ => next_char.to_string() + self.read_until_whitespace().as_slice(),
        }
    }

    /*
    fn finish_number(&mut self) -> String {
    }
    */
}

#[test]
fn test_tokenizer_1word() {
    let test_str = "hello";
    let mut tokens = tokenize(test_str);
    match tokens.next().unwrap() {
        Token::Word(n) => assert_eq!(n, "hello"),
        _ => panic!("fail")
    }
    assert!(tokens.next().is_none());
}

#[test]
fn test_tokenizer_2words() {
    let test_str = "hello world";
    let mut tokens = tokenize(test_str);
    match tokens.next().unwrap() {
        Token::Word(n) => assert_eq!(n, "hello"),
        _ => panic!("fail")
    }
    match tokens.next().unwrap() {
        Token::Word(n) => assert_eq!(n, "world"),
        _ => panic!("fail")
    }
    assert!(tokens.next().is_none());
}

#[test]
fn test_tokenizer_1number() {
    let test_str = "4.2";
    let mut tokens = tokenize(test_str);
    match tokens.next().unwrap() {
        Token::Number(n) => assert_eq!(n.to_string(), "4.2"),
        _ => panic!("fail")
    }
    assert!(tokens.next().is_none());
}

#[test]
fn test_tokenizer_2numbers() {
    let test_str = ".38 -2";
    let mut tokens = tokenize(test_str);
    match tokens.next().unwrap() {
        Token::Number(n) => assert_eq!(n.to_string(), "0.38"),
        _ => panic!("fail")
    }
    match tokens.next().unwrap() {
        Token::Number(n) => assert_eq!(n.to_string(), "-2"),
        _ => panic!("fail")
    }
    assert!(tokens.next().is_none());
}
<|endoftext|>


<commit_before>/// The tokenizer for the query interpreter

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

    use std::ops::Deref;

    #[test]
    fn test_tokenize_empty_query_to_error() {
        let tokens = tokenize_with_seperator(&String::from(""), '.');
        assert!(tokens.is_err());
        let tokens = tokens.unwrap_err();

        let errkind = tokens.kind();
        assert!(is_match!(errkind, &ErrorKind::EmptyQueryError { .. }));
    }

    #[test]
    fn test_tokenize_single_token_query() {
        let tokens = tokenize_with_seperator(&String::from("example"), '.');
        assert!(tokens.is_ok());
        let tokens = tokens.unwrap();

        assert!(match tokens {
            Token::Identifier {
                ident: ident,
                next: None
            } => {
                assert_eq!(String::from("example"), ident);
                true
            },
            _ => false,
        });
    }

    #[test]
    fn test_tokenize_double_token_query() {
        let tokens = tokenize_with_seperator(&String::from("a.b"), '.');
        assert!(tokens.is_ok());
        let tokens = tokens.unwrap();

        assert!(match tokens {
            Token::Identifier { next: Some(ref next), .. } => {
                assert_eq!(1, Rc::strong_count(&next));
                assert_eq!("b", next.deref().identifier());
                match next.deref() {
                    &Token::Identifier { next: None, .. } => true,
                    _ => false
                }
            },
            _ => false,
        });
        assert_eq!("a", tokens.identifier());
    }

    #[test]
    fn test_tokenize_ident_then_array_query() {
        let tokens = tokenize_with_seperator(&String::from("a.[0]"), '.');
        assert!(tokens.is_ok());
        let tokens = tokens.unwrap();

        assert_eq!("a", tokens.identifier());
        assert!(match tokens {
            Token::Identifier { next: Some(ref next), .. } => {
                assert_eq!(1, Rc::strong_count(&next));
                match next.deref() {
                    &Token::Index { idx: 0, next: None } => true,
                    _ => false
                }
            },
            _ => false,
        });
    }

    #[test]
    fn test_tokenize_many_idents_then_array_query() {
        use std::ops::Deref;

        let tokens = tokenize_with_seperator(&String::from("a.b.c.[1000]"), '.');
        assert!(tokens.is_ok());
        let tokens = tokens.unwrap();

        assert_eq!("a", tokens.identifier());

        let expected =
            Token::Identifier {
                ident: String::from("a"),
                next: Some(Rc::new(Token::Identifier {
                    ident: String::from("b"),
                    next: Some(Rc::new(Token::Identifier {
                        ident: String::from("c"),
                        next: Some(Rc::new(Token::Index {
                            idx: 1000,
                            next: None,
                        })),
                    })),
                })),
            };

        assert_eq!(expected, tokens);
    }

    quickcheck! {
        fn test_array_index(i: i64) -> bool {
            match tokenize_with_seperator(&format!("[{}]", i), '.') {
                Ok(Token::Index {
                    idx: i,
                    next: None,
                }) => true,
                _ => false,
            }
        }
    }

}
<commit_msg>Add function interface<commit_after>/// The tokenizer for the query interpreter

use error::*;

pub fn tokenize_with_seperator(query: &String, seperator: char) -> Result<Token> {
    unimplemented!()
}

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

    use std::ops::Deref;

    #[test]
    fn test_tokenize_empty_query_to_error() {
        let tokens = tokenize_with_seperator(&String::from(""), '.');
        assert!(tokens.is_err());
        let tokens = tokens.unwrap_err();

        let errkind = tokens.kind();
        assert!(is_match!(errkind, &ErrorKind::EmptyQueryError { .. }));
    }

    #[test]
    fn test_tokenize_single_token_query() {
        let tokens = tokenize_with_seperator(&String::from("example"), '.');
        assert!(tokens.is_ok());
        let tokens = tokens.unwrap();

        assert!(match tokens {
            Token::Identifier {
                ident: ident,
                next: None
            } => {
                assert_eq!(String::from("example"), ident);
                true
            },
            _ => false,
        });
    }

    #[test]
    fn test_tokenize_double_token_query() {
        let tokens = tokenize_with_seperator(&String::from("a.b"), '.');
        assert!(tokens.is_ok());
        let tokens = tokens.unwrap();

        assert!(match tokens {
            Token::Identifier { next: Some(ref next), .. } => {
                assert_eq!(1, Rc::strong_count(&next));
                assert_eq!("b", next.deref().identifier());
                match next.deref() {
                    &Token::Identifier { next: None, .. } => true,
                    _ => false
                }
            },
            _ => false,
        });
        assert_eq!("a", tokens.identifier());
    }

    #[test]
    fn test_tokenize_ident_then_array_query() {
        let tokens = tokenize_with_seperator(&String::from("a.[0]"), '.');
        assert!(tokens.is_ok());
        let tokens = tokens.unwrap();

        assert_eq!("a", tokens.identifier());
        assert!(match tokens {
            Token::Identifier { next: Some(ref next), .. } => {
                assert_eq!(1, Rc::strong_count(&next));
                match next.deref() {
                    &Token::Index { idx: 0, next: None } => true,
                    _ => false
                }
            },
            _ => false,
        });
    }

    #[test]
    fn test_tokenize_many_idents_then_array_query() {
        use std::ops::Deref;

        let tokens = tokenize_with_seperator(&String::from("a.b.c.[1000]"), '.');
        assert!(tokens.is_ok());
        let tokens = tokens.unwrap();

        assert_eq!("a", tokens.identifier());

        let expected =
            Token::Identifier {
                ident: String::from("a"),
                next: Some(Rc::new(Token::Identifier {
                    ident: String::from("b"),
                    next: Some(Rc::new(Token::Identifier {
                        ident: String::from("c"),
                        next: Some(Rc::new(Token::Index {
                            idx: 1000,
                            next: None,
                        })),
                    })),
                })),
            };

        assert_eq!(expected, tokens);
    }

    quickcheck! {
        fn test_array_index(i: i64) -> bool {
            match tokenize_with_seperator(&format!("[{}]", i), '.') {
                Ok(Token::Index {
                    idx: i,
                    next: None,
                }) => true,
                _ => false,
            }
        }
    }

}
<|endoftext|>


<commit_before>use rutorch::*;
use std::ops::{Index, IndexMut};
use std::convert::From;
use std::cmp::max;
use std::hash::{Hash, Hasher};

use storage::*;
use rand;
use {Ixs, RcMut};

#[derive(Hash)]
pub enum TensorKind {
    FloatTensor(Tensor<f32>),
    LongTensor(Tensor<i64>),
}

pub type TensorList<T> = Vec<Tensor<T>>;
pub type TensorKindList = Vec<TensorKind>;
pub type RefTensorList<'a, T> = Vec<&'a mut Tensor<T>>;
pub type RefTensorKindList<'a> = Vec<&'a TensorKind>;
pub type TensorId = i32;

impl TensorKind {
    pub fn add_(&mut self, rhs: &TensorKind) {
        unimplemented!()
    }
    pub fn new(&self) -> Self {
        unimplemented!()
    }
    // perform deep copy
    pub fn copy(&self) -> Self {
        unimplemented!()
    }
    pub fn unsqueeze(self, dim: usize) -> Self {
        unimplemented!()
    }
    pub fn long(&self) -> Self {
        unimplemented!()
    }
    //    pub fn backend(&self) -> &
}

impl PartialEq for TensorKind {
    fn eq(&self, other: &TensorKind) -> bool {
        use self::TensorKind::{FloatTensor, LongTensor};
        match (self, other) {
            (&FloatTensor(ref t1), &FloatTensor(ref t2)) => t1.id == t2.id,
            (&LongTensor(ref t1), &LongTensor(ref t2)) => t1.id == t2.id,
            _ => false,
        }
    }
}
impl Eq for TensorKind {}
impl Clone for TensorKind {
    fn clone(&self) -> Self {
        use self::TensorKind::{FloatTensor, LongTensor};
        match *self {
            FloatTensor(ref t) => FloatTensor(t.clone()),
            LongTensor(ref t) => LongTensor(t.clone()),
        }
    }
}

impl<T> From<Tensor<T>> for TensorKind {
    #[allow(unused_variables)]
    default fn from(input: Tensor<T>) -> Self {
        unreachable!()
    }
}

impl From<Tensor<f32>> for TensorKind {
    fn from(input: Tensor<f32>) -> TensorKind {
        TensorKind::FloatTensor(input)
    }
}

impl From<Tensor<i64>> for TensorKind {
    fn from(input: Tensor<i64>) -> TensorKind {
        TensorKind::LongTensor(input)
    }
}

impl<T> From<TensorKind> for Tensor<T> {
    #[allow(unused_variables)]
    default fn from(input: TensorKind) -> Tensor<T> {
        panic!("bad cast")
    }
}

impl<'a, T> From<&'a TensorKind> for &'a Tensor<T> {
    #[allow(unused_variables)]
    default fn from(input: &'a TensorKind) -> &'a Tensor<T> {
        panic!("bad cast")
    }
}

impl<'a> From<&'a TensorKind> for &'a Tensor<f32> {
    fn from(input: &'a TensorKind) -> Self {
        match *input {
            TensorKind::FloatTensor(ref t) => t,
            _ => unreachable!(),
        }
    }
}

impl<'a> From<&'a TensorKind> for &'a Tensor<i64> {
    fn from(input: &'a TensorKind) -> Self {
        match *input {
            TensorKind::LongTensor(ref t) => t,
            _ => unreachable!(),
        }
    }
}

impl From<TensorKind> for Tensor<f32> {
    fn from(input: TensorKind) -> Self {
        match input {
            TensorKind::FloatTensor(v) => v,
            _ => unimplemented!(),
        }
    }
}

impl From<TensorKind> for Tensor<i64> {
    fn from(input: TensorKind) -> Self {
        match input {
            TensorKind::LongTensor(v) => v,
            _ => unimplemented!(),
        }
    }
}
pub struct Tensor<T> {
    pub id: i32,
    value: RcMut<TensorImpl<T, Output = T>>,
}
impl<T> Hash for Tensor<T> {
    fn hash<H: Hasher>(&self, state: &mut H) {
        self.id.hash(state)
    }
}

impl<T: Copy> Index<usize> for Tensor<T> {
    type Output = T;
    fn index(&self, idx: usize) -> &Self::Output {

        //        self.value.borrow_mut().index(idx as isize)
        unimplemented!()
    }
}

impl<T: Copy> Index<i32> for Tensor<T> {
    type Output = T;
    fn index(&self, idx: i32) -> &Self::Output {

        //        self.value.borrow_mut().index(idx as isize)
        unimplemented!()
    }
}

pub trait New<D, T> {
    fn new(args: D) -> T;
    fn new_(&self, args: D) -> T;
}

impl<T> New<usize, Tensor<T>> for Tensor<T> {
    fn new(args: usize) -> Self {
        unimplemented!()
    }
    fn new_(&self, args: usize) -> Self {
        unimplemented!()
    }
}
impl<T> New<Vec<usize>, Tensor<T>> for Tensor<T> {
    fn new(args: Vec<usize>) -> Self {
        unimplemented!()
    }
    fn new_(&self, args: Vec<usize>) -> Self {
        unimplemented!()
    }
}

impl<T> Tensor<T> {
    pub fn len(&self) -> usize {
        unimplemented!()
    }
    pub fn size(&self) -> Vec<usize> {
        unimplemented!()
    }
    pub fn zero_(&mut self) -> Self {
        unimplemented!()
    }
    pub fn add_(&mut self, rhs: &Tensor<T>) {
        unimplemented!()
    }
    pub fn cuda(&self) -> Self {
        unimplemented!()
    }
    pub fn cpu(&self) -> Self {
        unimplemented!()
    }
    pub fn reduce_max(&self, axis: usize) -> (Self, Tensor<i64>) {
        unimplemented!()
    }
    pub fn tensor_eq(&self, rhs: &Self) -> Tensor<i64> {
        unimplemented!()
    }
    pub fn sum(&self) -> u32 {
        unimplemented!()
    }
    pub fn s(&self, dim: usize) -> Self {
        unimplemented!()
    }
}

impl<T> Default for Tensor<T> {
    fn default() -> Self {
        unimplemented!()
    }
}

impl<T> Clone for Tensor<T> {
    fn clone(&self) -> Self {
        Tensor {
            id: self.id,
            value: self.value.clone(),
        }
    }
}

impl<T: Copy> Index<isize> for Tensor<T> {
    type Output = T;

    fn index(&self, idx: isize) -> &Self::Output {
        unimplemented!()
    }
}
pub trait TensorImpl<T>: Index<Ixs, Output = T> {
    //fn view<'a>(&self, dims: &[i32]) -> Tensor<'a>;
}

pub struct FloatTensor {
    t: *mut THFloatTensor,
    storage: FloatStorage,
    dims: Vec<isize>,
}

impl Default for FloatTensor {
    fn default() -> Self {
        FloatTensor::new()
    }
}

impl FloatTensor {
    pub fn new() -> Self {
        unsafe {
            FloatTensor {
                t: THFloatTensor_new(),
                storage: FloatStorage::new(),
                dims: Vec::new(),
            }
        }
    }
    pub fn with_capacity(dims: &[isize]) -> Self {
        let size = dims.iter().product();
        let storage = FloatStorage::with_capacity(size);
        let strides = vec![1; dims.len()];
        let mut t = THFloatTensor {
            size: dims.clone().as_ptr() as *mut ::std::os::raw::c_long,
            stride: strides.as_ptr() as *mut ::std::os::raw::c_long,
            nDimension: dims.len() as i32,
            storage: storage.t,
            storageOffset: 0,
            refcount: 1,
            flag: TH_TENSOR_REFCOUNTED as i8,
        };
        FloatTensor {
            t: &mut t,
            storage: storage,
            dims: Vec::from(dims),
        }
    }
    pub fn randn(dims: &[isize]) -> Self {
        /* XXX */
        let mut t = FloatTensor::with_capacity(dims);
        for x in t.storage.iter_mut() {
            *x = rand::random::<f32>()
        }
        t
    }
}

impl<'a> Index<&'a [isize]> for FloatTensor {
    type Output = f32;

    fn index(&self, idx: &'a [isize]) -> &Self::Output {
        let mut index: isize = 0;
        let lastidx = max(0, idx.len() as isize - 1) as usize;
        if idx.len() != self.dims.len() {
            panic!("bad dimlen")
        }
        for i in 0..lastidx {
            if idx[i] >= self.dims[i] {
                panic!("bad dimlen")
            }
            index += idx[i] * self.dims[i]
        }
        if idx[lastidx] >= self.dims[lastidx] {
            panic!("bad dimlen")
        }
        index += idx[lastidx];
        &self.storage[index]
    }
}

impl<'a> IndexMut<&'a [isize]> for FloatTensor {
    fn index_mut(&mut self, idx: &'a [isize]) -> &mut Self::Output {
        let mut index: isize = 0;
        let lastidx = max(0, idx.len() as isize - 1) as usize;
        if idx.len() != self.dims.len() {
            panic!("bad dimlen")
        }
        for i in 0..lastidx {
            if idx[i] >= self.dims[i] {
                panic!("bad dimlen")
            }
            index += idx[i] * self.dims[i]
        }
        if idx[lastidx] >= self.dims[lastidx] {
            panic!("bad dimlen")
        }
        index += idx[lastidx];
        &mut self.storage[index]
    }
}
<commit_msg>add native conversion stubs<commit_after>use rutorch::*;
use std::ops::{Index, IndexMut};
use std::convert::From;
use std::cmp::max;
use std::hash::{Hash, Hasher};

use storage::*;
use rand;
use {Ixs, RcMut};

#[derive(Hash)]
pub enum TensorKind {
    FloatTensor(Tensor<f32>),
    LongTensor(Tensor<i64>),
}

pub type TensorList<T> = Vec<Tensor<T>>;
pub type TensorKindList = Vec<TensorKind>;
pub type RefTensorList<'a, T> = Vec<&'a mut Tensor<T>>;
pub type RefTensorKindList<'a> = Vec<&'a TensorKind>;
pub type TensorId = i32;

impl TensorKind {
    pub fn add_(&mut self, rhs: &TensorKind) {
        unimplemented!()
    }
    pub fn new(&self) -> Self {
        unimplemented!()
    }
    // perform deep copy
    pub fn copy(&self) -> Self {
        unimplemented!()
    }
    pub fn unsqueeze(self, dim: usize) -> Self {
        unimplemented!()
    }
    pub fn long(&self) -> Self {
        unimplemented!()
    }
    pub fn in_thft(&self) -> *mut THFloatTensor {
        unimplemented!();
    }
    pub fn in_thlt(&self) -> *mut THLongTensor {
        unimplemented!();
    }
    //    pub fn backend(&self) -> &
}

impl PartialEq for TensorKind {
    fn eq(&self, other: &TensorKind) -> bool {
        use self::TensorKind::{FloatTensor, LongTensor};
        match (self, other) {
            (&FloatTensor(ref t1), &FloatTensor(ref t2)) => t1.id == t2.id,
            (&LongTensor(ref t1), &LongTensor(ref t2)) => t1.id == t2.id,
            _ => false,
        }
    }
}
impl Eq for TensorKind {}
impl Clone for TensorKind {
    fn clone(&self) -> Self {
        use self::TensorKind::{FloatTensor, LongTensor};
        match *self {
            FloatTensor(ref t) => FloatTensor(t.clone()),
            LongTensor(ref t) => LongTensor(t.clone()),
        }
    }
}

impl<T> From<Tensor<T>> for TensorKind {
    #[allow(unused_variables)]
    default fn from(input: Tensor<T>) -> Self {
        unreachable!()
    }
}

impl From<Tensor<f32>> for TensorKind {
    fn from(input: Tensor<f32>) -> TensorKind {
        TensorKind::FloatTensor(input)
    }
}

impl From<Tensor<i64>> for TensorKind {
    fn from(input: Tensor<i64>) -> TensorKind {
        TensorKind::LongTensor(input)
    }
}

impl<T> From<TensorKind> for Tensor<T> {
    #[allow(unused_variables)]
    default fn from(input: TensorKind) -> Tensor<T> {
        panic!("bad cast")
    }
}

impl<'a, T> From<&'a TensorKind> for &'a Tensor<T> {
    #[allow(unused_variables)]
    default fn from(input: &'a TensorKind) -> &'a Tensor<T> {
        panic!("bad cast")
    }
}

impl<'a> From<&'a TensorKind> for &'a Tensor<f32> {
    fn from(input: &'a TensorKind) -> Self {
        match *input {
            TensorKind::FloatTensor(ref t) => t,
            _ => unreachable!(),
        }
    }
}

impl<'a> From<&'a TensorKind> for &'a Tensor<i64> {
    fn from(input: &'a TensorKind) -> Self {
        match *input {
            TensorKind::LongTensor(ref t) => t,
            _ => unreachable!(),
        }
    }
}

impl From<TensorKind> for Tensor<f32> {
    fn from(input: TensorKind) -> Self {
        match input {
            TensorKind::FloatTensor(v) => v,
            _ => unimplemented!(),
        }
    }
}

impl From<TensorKind> for Tensor<i64> {
    fn from(input: TensorKind) -> Self {
        match input {
            TensorKind::LongTensor(v) => v,
            _ => unimplemented!(),
        }
    }
}
pub struct Tensor<T> {
    pub id: i32,
    value: RcMut<TensorImpl<T, Output = T>>,
}
impl<T> Hash for Tensor<T> {
    fn hash<H: Hasher>(&self, state: &mut H) {
        self.id.hash(state)
    }
}

impl<T: Copy> Index<usize> for Tensor<T> {
    type Output = T;
    fn index(&self, idx: usize) -> &Self::Output {

        //        self.value.borrow_mut().index(idx as isize)
        unimplemented!()
    }
}

impl<T: Copy> Index<i32> for Tensor<T> {
    type Output = T;
    fn index(&self, idx: i32) -> &Self::Output {

        //        self.value.borrow_mut().index(idx as isize)
        unimplemented!()
    }
}

pub trait New<D, T> {
    fn new(args: D) -> T;
    fn new_(&self, args: D) -> T;
}

impl<T> New<usize, Tensor<T>> for Tensor<T> {
    fn new(args: usize) -> Self {
        unimplemented!()
    }
    fn new_(&self, args: usize) -> Self {
        unimplemented!()
    }
}
impl<T> New<Vec<usize>, Tensor<T>> for Tensor<T> {
    fn new(args: Vec<usize>) -> Self {
        unimplemented!()
    }
    fn new_(&self, args: Vec<usize>) -> Self {
        unimplemented!()
    }
}

impl<T> Tensor<T> {
    pub fn len(&self) -> usize {
        unimplemented!()
    }
    pub fn size(&self) -> Vec<usize> {
        unimplemented!()
    }
    pub fn zero_(&mut self) -> Self {
        unimplemented!()
    }
    pub fn add_(&mut self, rhs: &Tensor<T>) {
        unimplemented!()
    }
    pub fn cuda(&self) -> Self {
        unimplemented!()
    }
    pub fn cpu(&self) -> Self {
        unimplemented!()
    }
    pub fn reduce_max(&self, axis: usize) -> (Self, Tensor<i64>) {
        unimplemented!()
    }
    pub fn tensor_eq(&self, rhs: &Self) -> Tensor<i64> {
        unimplemented!()
    }
    pub fn sum(&self) -> u32 {
        unimplemented!()
    }
    pub fn s(&self, dim: usize) -> Self {
        unimplemented!()
    }
}

impl<T> Default for Tensor<T> {
    fn default() -> Self {
        unimplemented!()
    }
}

impl<T> Clone for Tensor<T> {
    fn clone(&self) -> Self {
        Tensor {
            id: self.id,
            value: self.value.clone(),
        }
    }
}

impl<T: Copy> Index<isize> for Tensor<T> {
    type Output = T;

    fn index(&self, idx: isize) -> &Self::Output {
        unimplemented!()
    }
}
pub trait TensorImpl<T>: Index<Ixs, Output = T> {
    //fn view<'a>(&self, dims: &[i32]) -> Tensor<'a>;
}

pub struct FloatTensor {
    t: *mut THFloatTensor,
    storage: FloatStorage,
    dims: Vec<isize>,
}

impl Default for FloatTensor {
    fn default() -> Self {
        FloatTensor::new()
    }
}

impl FloatTensor {
    pub fn new() -> Self {
        unsafe {
            FloatTensor {
                t: THFloatTensor_new(),
                storage: FloatStorage::new(),
                dims: Vec::new(),
            }
        }
    }
    pub fn with_capacity(dims: &[isize]) -> Self {
        let size = dims.iter().product();
        let storage = FloatStorage::with_capacity(size);
        let strides = vec![1; dims.len()];
        let mut t = THFloatTensor {
            size: dims.clone().as_ptr() as *mut ::std::os::raw::c_long,
            stride: strides.as_ptr() as *mut ::std::os::raw::c_long,
            nDimension: dims.len() as i32,
            storage: storage.t,
            storageOffset: 0,
            refcount: 1,
            flag: TH_TENSOR_REFCOUNTED as i8,
        };
        FloatTensor {
            t: &mut t,
            storage: storage,
            dims: Vec::from(dims),
        }
    }
    pub fn randn(dims: &[isize]) -> Self {
        /* XXX */
        let mut t = FloatTensor::with_capacity(dims);
        for x in t.storage.iter_mut() {
            *x = rand::random::<f32>()
        }
        t
    }
}

impl<'a> Index<&'a [isize]> for FloatTensor {
    type Output = f32;

    fn index(&self, idx: &'a [isize]) -> &Self::Output {
        let mut index: isize = 0;
        let lastidx = max(0, idx.len() as isize - 1) as usize;
        if idx.len() != self.dims.len() {
            panic!("bad dimlen")
        }
        for i in 0..lastidx {
            if idx[i] >= self.dims[i] {
                panic!("bad dimlen")
            }
            index += idx[i] * self.dims[i]
        }
        if idx[lastidx] >= self.dims[lastidx] {
            panic!("bad dimlen")
        }
        index += idx[lastidx];
        &self.storage[index]
    }
}

impl<'a> IndexMut<&'a [isize]> for FloatTensor {
    fn index_mut(&mut self, idx: &'a [isize]) -> &mut Self::Output {
        let mut index: isize = 0;
        let lastidx = max(0, idx.len() as isize - 1) as usize;
        if idx.len() != self.dims.len() {
            panic!("bad dimlen")
        }
        for i in 0..lastidx {
            if idx[i] >= self.dims[i] {
                panic!("bad dimlen")
            }
            index += idx[i] * self.dims[i]
        }
        if idx[lastidx] >= self.dims[lastidx] {
            panic!("bad dimlen")
        }
        index += idx[lastidx];
        &mut self.storage[index]
    }
}
<|endoftext|>