<commit_before>use std::collections::HashMap;
use std::io::{self, Read, Write};
use std::marker::PhantomData;
use std::string::String;
use std::sync::{Arc, Future, Mutex};
use std::sync::atomic::{AtomicUsize, Ordering, ATOMIC_USIZE_INIT};
use std::sync::mpsc::{channel, Sender, Receiver};
use std::thread::{self, JoinGuard};

use super::{Value, ReadError, WriteError, write, write_value};

static MSGID: AtomicUsize = ATOMIC_USIZE_INIT;

pub type RpcResult = Result<Value, Value>;
type PendingData = Arc<Mutex<HashMap<u32, Sender<RpcResult>>>>;

/// `Client` represents a connection to some server that accepts
/// MessagePack RPC requests.
pub struct Client<'c, R, W> {
    input: PhantomData<R>, // the reader instance is owned by the dispatch thread
    output: W,
    pending: PendingData,
    dispatch_guard: JoinGuard<'c, ()>,
}

impl<'c, R, W> Client<'c, R, W> where R: Read + Send + 'c, W: Write + Send + 'c {
    /// Construct a new Client instance from a stream.
    ///
    /// In order for this to work properly, the stream's `.clone()` method must
    /// return a new handle to the shared underlying stream; in other words, it
    /// must be a shallow clone and not deep. `TCPStream` and `UnixStream` are known
    /// to do this, but other types should be aware of this restriction.
    pub fn new_for_stream<S>(stream: S) -> Client<'c, S, S> where S: Read + Write + Clone + Send + 'c {
        Client::new(stream.clone(), stream)
    }

    /// Construct a new Client instance from a reader/writer pair.
    pub fn new(reader: R, writer: W) -> Client<'c, R, W> {
        let pending = Arc::new(Mutex::new(HashMap::new()));
        Client{
            input: PhantomData,
            output: writer,
            pending: pending.clone(),
            dispatch_guard: Client::<R, W>::dispatch_thread(reader, pending),
        }
    }

    /// Runs a scoped thread for dispatching messages received from reader to the appropriate parties.
    fn dispatch_thread(reader: R, pending: PendingData) -> JoinGuard<'c, ()> {
        thread::scoped(move || {
            let mut reader = super::Reader::new(reader);
            loop {
                match reader.read_value() {
                    Ok(value) => assert_eq!(value.int(), 1),
                    Err(ReadError::Unrecognized(0)) => break, // kill signal
                    Err(ReadError::NoData) => break, // eof
                    Err(e) => panic!("error: {}", e),
                }

                match reader.read_value() {
                    Ok(Value::Uint32(msgid)) => {
                        let responder: Sender<RpcResult> = pending.lock().unwrap().remove(&msgid).unwrap();

                        let err = reader.read_value().unwrap();
                        let res = reader.read_value().unwrap();

                        responder.send(if err == Value::Nil { Ok(res) } else { Err(err) }).unwrap();
                    },
                    Ok(value) => panic!("received value, but it wasn't a u32: {:?}", value),
                    Err(e) => panic!("failed to receive value: {:?}", e),
                }
            }
        })
    }

    /// Helper for calling methods via RPC.
    fn do_call(&mut self, method: String, params: Vec<Value>) -> Result<Receiver<RpcResult>, WriteError> {
        try!(write_value(&mut self.output, Value::Int8(0))); // for method call

        let msgid = MSGID.fetch_add(1, Ordering::SeqCst) as u32;
        let (responder, listener) = channel();
        self.pending.lock().unwrap().insert(msgid, responder);

        try!(write(&mut self.output, msgid));
        try!(write(&mut self.output, method));
        try!(write_value(&mut self.output, Value::Array(params)));
        try!(self.output.flush());

        Ok(listener)
    }

    /// Call a method via RPC and receive the response as a Future.
    ///
    /// If an `Err` value is returned, it indicates some IO error that occurred while trying
    /// to make the call. An `Ok` value means that the call was successfully made. Calling
    /// `.get()` on its contents will block the thread until a response is received.
    pub fn call(&mut self, method: String, params: Vec<Value>) -> Result<Future<RpcResult>, WriteError> {
        Ok(Future::from_receiver(try!(self.do_call(method, params))))
    }

    /// Call a method via RPC and receive the response in a closure.
    ///
    /// If an `Err` value is returned, it indicates some IO error that occurred while trying
    /// to make the call, and as a result the provided closure will never be invoked. If an
    /// `Ok` value is returned, then a new thread will be kicked off to listen for the response
    /// and pass it to the closure when it's received.
    ///
    /// # Panics
    ///
    /// The new thread could conceivably panic if the Client instance gets cleaned up before
    /// the callback is invoked.
    pub fn call_cb<F: FnOnce(RpcResult) -> () + Send + 'static>(&mut self, method: String, params: Vec<Value>, f: F) -> Result<(), WriteError> {
        let listener = try!(self.do_call(method, params));
        thread::spawn(move || {
            f(listener.recv().unwrap());
        });
        Ok(())
    }

    /// Call a method via RPC and synchronously wait for the response.
    ///
    /// If an `Err` value is returned, it indicates some IO error that occurred while trying
    /// to make the call. An `Ok` value will contain the server's response.
    pub fn call_sync(&mut self, method: String, params: Vec<Value>) -> Result<RpcResult, WriteError> {
        Ok(try!(self.do_call(method, params)).recv().unwrap())
    }
}

#[unsafe_destructor]
impl<'c, R, W> Drop for Client<'c, R, W> where W: Write {
    fn drop(&mut self) {
        match self.output.write(&[0]) {
            Ok(_) => (),
            Err(ref e) if e.kind() == io::ErrorKind::BrokenPipe => (), // already closed, no need to kill it
            Err(e) => panic!("{}", e),
        }
    }
}

#[cfg(test)]
mod test {
    use std::sync::mpsc::channel;
    use std::thread;
    use std::time::duration::Duration;

    use super::Client;
    use super::super::{Value, ReadError, write, write_value};

    // This test just calls a method "ping" and expects the result "pong".
    #[test] fn simple_test() {
        let (cw, cr) = channel();
        let (sw, sr) = channel();

        thread::spawn(move || {
            let mut reader = ::Reader::new(::test::ChanReader(cr));
            let mut writer = ::test::ChanWriter(sw);

            assert_eq!(reader.read_value().unwrap().int(), 0);
            let msgid = reader.read_value().unwrap().uint() as u32;
            let method = reader.read_value().unwrap().string();
            let _ = reader.read_value().unwrap().array(); // params

            match method.as_slice() {
                "ping" => {
                    write(&mut writer, 1 as i8).unwrap();
                    write_value(&mut writer, Value::Uint32(msgid)).unwrap();
                    write(&mut writer, ()).unwrap(); // error
                    write(&mut writer, "pong".to_string()).unwrap(); // value
                },
                m => panic!("didn't expect you to call method '{}'", m),
            }
        });

        let mut client = Client::new(::test::ChanReader(sr), ::test::ChanWriter(cw));
        let mut value_future = client.call("ping".to_string(), vec![]).unwrap();
        let value = value_future.get().unwrap();
        assert_eq!(value, Value::String("pong".to_string()));
    }

    /// This method verifies the correctness of mismatched response times by calling
    /// two methods, one slow and one fast, and verifying that the expected value
    /// gets returned to the appropriate caller.
    #[test] fn out_of_order_test() {
        let (cw, cr) = channel();
        let (sw, sr) = channel();

        thread::spawn(move || {
            let mut reader = ::Reader::new(::test::ChanReader(cr));

            loop {
                match reader.read_value() {
                    Ok(value) => assert_eq!(value.int(), 0),
                    Err(ReadError::Unrecognized(0)) => break,
                    Err(ReadError::NoData) => break,
                    x => panic!("received unexpected value '{:?}'", x),
                }

                let msgid = reader.read_value().unwrap().uint() as u32;
                let method = reader.read_value().unwrap().string();
                let params = reader.read_value().unwrap().array();
                let sw = sw.clone();

                thread::spawn(move || {
                    let msgid = msgid;
                    let method = method;
                    let mut params = params;
                    let mut writer = ::test::ChanWriter(sw);

                    macro_rules! echo(() => ({
                        write(&mut writer, 1 as i8).unwrap();
                        write_value(&mut writer, Value::Uint32(msgid)).unwrap();
                        write(&mut writer, ()).unwrap(); // error
                        write_value(&mut writer, params.swap_remove(0)).unwrap(); // value
                    }));

                    match method.as_slice() {
                        "quick_echo" => {
                            echo!();
                        },
                        "slow_echo" => {
                            use std::old_io::timer::sleep;
                            sleep(Duration::seconds(2));
                            echo!();
                        },
                        m => panic!("didn't expect you to call method '{}'", m),
                    }
                });
            }
        });

        let mut client = Client::new(::test::ChanReader(sr), ::test::ChanWriter(cw));

        let mut hello_future = client.call("slow_echo".to_string(), vec![Value::String("hello".to_string())]).unwrap();
        let mut world_future = client.call("quick_echo".to_string(), vec![Value::String("world".to_string())]).unwrap();

        assert_eq!(hello_future.get().unwrap(), Value::String("hello".to_string()));
        assert_eq!(world_future.get().unwrap(), Value::String("world".to_string()));
    }
}
<commit_msg>Fixed a small typo and did a slight documentation update.<commit_after>use std::collections::HashMap;
use std::io::{self, Read, Write};
use std::marker::PhantomData;
use std::string::String;
use std::sync::{Arc, Future, Mutex};
use std::sync::atomic::{AtomicUsize, Ordering, ATOMIC_USIZE_INIT};
use std::sync::mpsc::{channel, Sender, Receiver};
use std::thread::{self, JoinGuard};

use super::{Value, ReadError, WriteError, write, write_value};

static MSGID: AtomicUsize = ATOMIC_USIZE_INIT;

pub type RpcResult = Result<Value, Value>;
type PendingData = Arc<Mutex<HashMap<u32, Sender<RpcResult>>>>;

/// `Client` represents a connection to some server that accepts
/// MessagePack RPC requests.
pub struct Client<'c, R, W> {
    input: PhantomData<R>, // the reader instance is owned by the dispatch thread
    output: W,
    pending: PendingData,
    dispatch_guard: JoinGuard<'c, ()>,
}

impl<'c, R, W> Client<'c, R, W> where R: Read + Send + 'c, W: Write + Send + 'c {
    /// Construct a new Client instance from a stream.
    ///
    /// In order for this to work properly, the stream's `.clone()` method must
    /// return a new handle to the shared underlying stream; in other words, it
    /// must be a shallow clone and not deep. `TcpStream` and `UnixStream` are known
    /// to do this, but other types should be aware of this restriction.
    pub fn new_for_stream<S>(stream: S) -> Client<'c, S, S> where S: Read + Write + Clone + Send + 'c {
        Client::new(stream.clone(), stream)
    }

    /// Construct a new Client instance.
    ///
    /// This will spawn a scoped dispatch thread which will take ownership of the `Read`
    /// instance, and which will exit when it detects EOF, or when it receives a 0 in lieu
    /// of a MessagePack data type identifier.
    pub fn new(reader: R, writer: W) -> Client<'c, R, W> {
        let pending = Arc::new(Mutex::new(HashMap::new()));
        Client{
            input: PhantomData,
            output: writer,
            pending: pending.clone(),
            dispatch_guard: Client::<R, W>::dispatch_thread(reader, pending),
        }
    }

    /// Runs a scoped thread for dispatching messages received from reader to the appropriate parties.
    fn dispatch_thread(reader: R, pending: PendingData) -> JoinGuard<'c, ()> {
        thread::scoped(move || {
            let mut reader = super::Reader::new(reader);
            loop {
                match reader.read_value() {
                    Ok(value) => assert_eq!(value.int(), 1),
                    Err(ReadError::Unrecognized(0)) => break, // kill signal
                    Err(ReadError::NoData) => break, // eof
                    Err(e) => panic!("error: {}", e),
                }

                match reader.read_value() {
                    Ok(Value::Uint32(msgid)) => {
                        let responder: Sender<RpcResult> = pending.lock().unwrap().remove(&msgid).unwrap();

                        let err = reader.read_value().unwrap();
                        let res = reader.read_value().unwrap();

                        responder.send(if err == Value::Nil { Ok(res) } else { Err(err) }).unwrap();
                    },
                    Ok(value) => panic!("received value, but it wasn't a u32: {:?}", value),
                    Err(e) => panic!("failed to receive value: {:?}", e),
                }
            }
        })
    }

    /// Helper for calling methods via RPC.
    fn do_call(&mut self, method: String, params: Vec<Value>) -> Result<Receiver<RpcResult>, WriteError> {
        try!(write_value(&mut self.output, Value::Int8(0))); // for method call

        let msgid = MSGID.fetch_add(1, Ordering::SeqCst) as u32;
        let (responder, listener) = channel();
        self.pending.lock().unwrap().insert(msgid, responder);

        try!(write(&mut self.output, msgid));
        try!(write(&mut self.output, method));
        try!(write_value(&mut self.output, Value::Array(params)));
        try!(self.output.flush());

        Ok(listener)
    }

    /// Call a method via RPC and receive the response as a Future.
    ///
    /// If an `Err` value is returned, it indicates some IO error that occurred while trying
    /// to make the call. An `Ok` value means that the call was successfully made. Calling
    /// `.get()` on its contents will block the thread until a response is received.
    pub fn call(&mut self, method: String, params: Vec<Value>) -> Result<Future<RpcResult>, WriteError> {
        Ok(Future::from_receiver(try!(self.do_call(method, params))))
    }

    /// Call a method via RPC and receive the response in a closure.
    ///
    /// If an `Err` value is returned, it indicates some IO error that occurred while trying
    /// to make the call, and as a result the provided closure will never be invoked. If an
    /// `Ok` value is returned, then a new thread will be kicked off to listen for the response
    /// and pass it to the closure when it's received.
    ///
    /// # Panics
    ///
    /// The new thread could conceivably panic if the Client instance gets cleaned up before
    /// the callback is invoked.
    pub fn call_cb<F: FnOnce(RpcResult) -> () + Send + 'static>(&mut self, method: String, params: Vec<Value>, f: F) -> Result<(), WriteError> {
        let listener = try!(self.do_call(method, params));
        thread::spawn(move || {
            f(listener.recv().unwrap());
        });
        Ok(())
    }

    /// Call a method via RPC and synchronously wait for the response.
    ///
    /// If an `Err` value is returned, it indicates some IO error that occurred while trying
    /// to make the call. An `Ok` value will contain the server's response.
    pub fn call_sync(&mut self, method: String, params: Vec<Value>) -> Result<RpcResult, WriteError> {
        Ok(try!(self.do_call(method, params)).recv().unwrap())
    }
}

#[unsafe_destructor]
impl<'c, R, W> Drop for Client<'c, R, W> where W: Write {
    fn drop(&mut self) {
        match self.output.write(&[0]) {
            Ok(_) => (),
            Err(ref e) if e.kind() == io::ErrorKind::BrokenPipe => (), // already closed, no need to kill it
            Err(e) => panic!("{}", e),
        }
    }
}

#[cfg(test)]
mod test {
    use std::sync::mpsc::channel;
    use std::thread;
    use std::time::duration::Duration;

    use super::Client;
    use super::super::{Value, ReadError, write, write_value};

    // This test just calls a method "ping" and expects the result "pong".
    #[test] fn simple_test() {
        let (cw, cr) = channel();
        let (sw, sr) = channel();

        thread::spawn(move || {
            let mut reader = ::Reader::new(::test::ChanReader(cr));
            let mut writer = ::test::ChanWriter(sw);

            assert_eq!(reader.read_value().unwrap().int(), 0);
            let msgid = reader.read_value().unwrap().uint() as u32;
            let method = reader.read_value().unwrap().string();
            let _ = reader.read_value().unwrap().array(); // params

            match method.as_slice() {
                "ping" => {
                    write(&mut writer, 1 as i8).unwrap();
                    write_value(&mut writer, Value::Uint32(msgid)).unwrap();
                    write(&mut writer, ()).unwrap(); // error
                    write(&mut writer, "pong".to_string()).unwrap(); // value
                },
                m => panic!("didn't expect you to call method '{}'", m),
            }
        });

        let mut client = Client::new(::test::ChanReader(sr), ::test::ChanWriter(cw));
        let mut value_future = client.call("ping".to_string(), vec![]).unwrap();
        let value = value_future.get().unwrap();
        assert_eq!(value, Value::String("pong".to_string()));
    }

    /// This method verifies the correctness of mismatched response times by calling
    /// two methods, one slow and one fast, and verifying that the expected value
    /// gets returned to the appropriate caller.
    #[test] fn out_of_order_test() {
        let (cw, cr) = channel();
        let (sw, sr) = channel();

        thread::spawn(move || {
            let mut reader = ::Reader::new(::test::ChanReader(cr));

            loop {
                match reader.read_value() {
                    Ok(value) => assert_eq!(value.int(), 0),
                    Err(ReadError::Unrecognized(0)) => break,
                    Err(ReadError::NoData) => break,
                    x => panic!("received unexpected value '{:?}'", x),
                }

                let msgid = reader.read_value().unwrap().uint() as u32;
                let method = reader.read_value().unwrap().string();
                let params = reader.read_value().unwrap().array();
                let sw = sw.clone();

                thread::spawn(move || {
                    let msgid = msgid;
                    let method = method;
                    let mut params = params;
                    let mut writer = ::test::ChanWriter(sw);

                    macro_rules! echo(() => ({
                        write(&mut writer, 1 as i8).unwrap();
                        write_value(&mut writer, Value::Uint32(msgid)).unwrap();
                        write(&mut writer, ()).unwrap(); // error
                        write_value(&mut writer, params.swap_remove(0)).unwrap(); // value
                    }));

                    match method.as_slice() {
                        "quick_echo" => {
                            echo!();
                        },
                        "slow_echo" => {
                            use std::old_io::timer::sleep;
                            sleep(Duration::seconds(2));
                            echo!();
                        },
                        m => panic!("didn't expect you to call method '{}'", m),
                    }
                });
            }
        });

        let mut client = Client::new(::test::ChanReader(sr), ::test::ChanWriter(cw));

        let mut hello_future = client.call("slow_echo".to_string(), vec![Value::String("hello".to_string())]).unwrap();
        let mut world_future = client.call("quick_echo".to_string(), vec![Value::String("world".to_string())]).unwrap();

        assert_eq!(hello_future.get().unwrap(), Value::String("hello".to_string()));
        assert_eq!(world_future.get().unwrap(), Value::String("world".to_string()));
    }
}
<|endoftext|>


<commit_before>#[link(name = "sdl_ttf",
       vers = "0.1",
       uuid = "1d776704-431f-4d5b-9361-b27958535321",
       url = "http://github.com/sfackler/rust-sdl_ttf")];

#[comment="SDL_ttf bindings"];
#[license="MIT"];
#[crate_type="lib"];

extern mod sdl;

use std::libc::{c_int, c_long};
use std::ptr;

use sdl::video::{Color, Surface};

#[cfg(target_os="win32")]
#[cfg(target_os="linux")]
#[cfg(target_os="freebsd")]
mod others {
    #[link_args="-lSDL_ttf"]
    extern {}
}

mod ffi {
    use std::libc::{c_int, c_char, c_void, c_long};
    use sdl::video::ll::{SDL_Color, SDL_Surface};

    pub type TTF_Font = c_void;

    pub type TTF_StyleFlag = c_int;
    pub static TTF_STYLE_NORMAL: TTF_StyleFlag = 0x00;
    pub static TTF_STYLE_BOLD: TTF_StyleFlag = 0x01;
    pub static TTF_STYLE_ITALIC: TTF_StyleFlag = 0x02;
    pub static TTF_STYLE_UNDERLINE: c_int = 0x04;
    pub static TTF_STYLE_STRIKETHROUGH: c_int = 0x08;

    extern {
        fn TTF_Init() -> c_int;
        fn TTF_WasInit() -> c_int;
        fn TTF_Quit();
        fn TTF_OpenFont(file: *c_char, ptsize: c_int) -> *TTF_Font;
        fn TTF_OpenFontIndex(file: *c_char, ptsize: c_int, index: c_long)
            -> *TTF_Font;
        fn TTF_CloseFont(font: *TTF_Font);

        fn TTF_GetFontStyle(font: *TTF_Font) -> c_int;
        fn TTF_SetFontStyle(font: *TTF_Font, style: c_int);
        fn TTF_GetFontOutline(font: *TTF_Font) -> c_int;
        fn TTF_SetFontOutline(font: *TTF_Font, outline: c_int);

        fn TTF_RenderText_Solid(font: *TTF_Font, text: *c_char,
            color: SDL_Color) -> *SDL_Surface;
    }
}

pub enum FontStyle {
    Normal = ffi::TTF_STYLE_NORMAL as int,
    Bold = ffi::TTF_STYLE_BOLD as int,
    Italic = ffi::TTF_STYLE_ITALIC as int,
    Underline = ffi::TTF_STYLE_UNDERLINE as int,
    Strikethrough = ffi::TTF_STYLE_STRIKETHROUGH as int
}

pub struct Font {
    priv raw: *ffi::TTF_Font
}

impl Drop for Font {
    fn drop(&self) {
        unsafe {
            ffi::TTF_CloseFont(self.raw);
        }
    }
}

impl Font {
    pub fn get_style(&self) -> ~[FontStyle] {
        let bitflags = unsafe { ffi::TTF_GetFontStyle(self.raw) };

        let flags = [
            Normal,
            Bold,
            Italic,
            Underline,
            Strikethrough
        ];

        do flags.iter().filter_map |&flag| {
            if bitflags & (flag as ffi::TTF_StyleFlag) != 0 { Some(flag) }
            else {None}
        }.collect()
    }

    pub fn set_style(&self, flags: &[FontStyle]) {
        let bitflags = do flags.iter().fold(0) |bitflags, &flag| {
            bitflags | flag as ffi::TTF_StyleFlag
        };

        unsafe {
            ffi::TTF_SetFontStyle(self.raw, bitflags);
        }
    }

    pub fn get_outline(&self) -> int {
        unsafe {
            ffi::TTF_GetFontOutline(self.raw) as int
        }
    }

    pub fn set_outline(&self, outline: int) {
        unsafe {
            ffi::TTF_SetFontOutline(self.raw, outline as c_int);
        }
    }
}

pub fn init() -> bool {
    unsafe {
        ffi::TTF_Init() == 0
    }
}

pub fn was_init() -> bool {
    unsafe {
        ffi::TTF_WasInit() == 1
    }
}

pub fn quit() {
    unsafe {
        ffi::TTF_Quit();
    }
}

pub fn open_font(file: &str, ptsize: int) -> Result<~Font, ~str> {
    do file.as_c_str |c_str| {
        unsafe {
            let ptr = ffi::TTF_OpenFont(c_str, ptsize as c_int);
            if ptr == ptr::null() {
                Err(sdl::get_error())
            } else {
                Ok(~Font {raw: ptr})
            }
        }
    }
}

pub fn open_font_index(file: &str, ptsize: int, index: int)
        -> Result<~Font, ~str> {
    do file.as_c_str |c_str| {
        let ptr = unsafe {
            ffi::TTF_OpenFontIndex(c_str, ptsize as c_int, index as c_long)
        };

        if ptr == ptr::null() {
            Err(sdl::get_error())
        } else {
            Ok(~Font {raw: ptr})
        }
    }
}

pub fn render_text_solid(font: &Font, text: &str, color: Color)
        -> Result<~Surface, ~str> {
    do text.as_c_str |c_text| {
        let ptr = unsafe {
            ffi::TTF_RenderText_Solid(font.raw, c_text, color.to_struct())
        };

        if ptr == ptr::null() {
            Err(sdl::get_error())
        } else {
            Ok(~Surface {raw: ptr, owned: true})
        }
    }
}
<commit_msg>Finished up functionality<commit_after>#[link(name = "sdl_ttf",
       vers = "0.1",
       uuid = "1d776704-431f-4d5b-9361-b27958535321",
       url = "http://github.com/sfackler/rust-sdl_ttf")];

#[comment="SDL_ttf bindings"];
#[license="MIT"];
#[crate_type="lib"];

extern mod sdl;

use std::libc::{c_int, c_long};
use std::cast;
use std::str;

use sdl::video::{Color, Surface};

#[cfg(target_os="win32")]
#[cfg(target_os="linux")]
#[cfg(target_os="freebsd")]
mod others {
    #[link_args="-lSDL_ttf"]
    extern {}
}

mod ffi {
    use std::libc::{c_int, c_char, c_void, c_long};
    use sdl::video::ll::{SDL_Color, SDL_Surface};

    pub type TTF_Font = c_void;

    pub type TTF_StyleFlag = c_int;
    pub static TTF_STYLE_NORMAL: TTF_StyleFlag = 0x00;
    pub static TTF_STYLE_BOLD: TTF_StyleFlag = 0x01;
    pub static TTF_STYLE_ITALIC: TTF_StyleFlag = 0x02;
    pub static TTF_STYLE_UNDERLINE: c_int = 0x04;
    pub static TTF_STYLE_STRIKETHROUGH: c_int = 0x08;

    pub type TTF_Hinting = c_int;
    pub static TTF_HINTING_NORMAL: TTF_Hinting = 0;
    pub static TTF_HINTING_LIGHT: TTF_Hinting = 1;
    pub static TTF_HINTING_MONO: TTF_Hinting = 2;
    pub static TTF_HINTING_NONE: TTF_Hinting = 3;

    extern {
        fn TTF_Init() -> c_int;
        fn TTF_WasInit() -> c_int;
        fn TTF_Quit();
        fn TTF_OpenFont(file: *c_char, ptsize: c_int) -> *TTF_Font;
        fn TTF_OpenFontIndex(file: *c_char, ptsize: c_int, index: c_long)
            -> *TTF_Font;
        fn TTF_CloseFont(font: *TTF_Font);

        fn TTF_GetFontStyle(font: *TTF_Font) -> TTF_StyleFlag;
        fn TTF_SetFontStyle(font: *TTF_Font, style: TTF_StyleFlag);
        fn TTF_GetFontOutline(font: *TTF_Font) -> c_int;
        fn TTF_SetFontOutline(font: *TTF_Font, outline: c_int);
        fn TTF_GetFontHinting(font: *TTF_Font) -> TTF_Hinting;
        fn TTF_SetFontHinting(font: *TTF_Font, hinting: TTF_Hinting);
        fn TTF_GetFontKerning(font: *TTF_Font) -> c_int;
        fn TTF_SetFontKerning(font: *TTF_Font, kerning: c_int);
        fn TTF_FontHeight(font: *TTF_Font) -> c_int;
        fn TTF_FontAscent(font: *TTF_Font) -> c_int;
        fn TTF_FontDescent(font: *TTF_Font) -> c_int;
        fn TTF_FontLineSkip(font: *TTF_Font) -> c_int;
        fn TTF_FontFaces(font: *TTF_Font) -> c_long;
        fn TTF_FontFaceIsFixedWidth(font: *TTF_Font) -> c_int;
        fn TTF_FontFaceFamilyName(font: *TTF_Font) -> *c_char;
        fn TTF_FontGlyphIsProvided(font: *TTF_Font, glyph: u16) -> c_int;
        fn TTF_GlyphMetrics(font: *TTF_Font, glyph: u16, minx: *mut c_int,
            maxx: *mut c_int, miny: *mut c_int, maxy: *mut c_int,
            advance: *mut c_int) -> c_int;
        fn TTF_SizeUTF8(font: *TTF_Font, text: *c_char, w: *mut c_int,
            h: *mut c_int) -> c_int;

        fn TTF_RenderUTF8_Solid(font: *TTF_Font, text: *c_char,
            fg: SDL_Color) -> *SDL_Surface;
        fn TTF_RenderUTF8_Shaded(font: *TTF_Font, text: *c_char,
            fg: SDL_Color, bg: SDL_Color) -> *SDL_Surface;
        fn TTF_RenderUTF8_Blended(font: *TTF_Font, text: *c_char,
            fg: SDL_Color) -> *SDL_Surface;
    }
}

pub enum FontStyle {
    NormalStyle = ffi::TTF_STYLE_NORMAL as int,
    BoldStyle = ffi::TTF_STYLE_BOLD as int,
    ItalicStyle = ffi::TTF_STYLE_ITALIC as int,
    UnderlineStyle = ffi::TTF_STYLE_UNDERLINE as int,
    StrikethroughStyle = ffi::TTF_STYLE_STRIKETHROUGH as int
}

pub enum FontHinting {
    NormalHinting = ffi::TTF_HINTING_NORMAL as int,
    LightHinting = ffi::TTF_HINTING_LIGHT as int,
    MonoHinting = ffi::TTF_HINTING_MONO as int,
    NoneHinting = ffi::TTF_HINTING_NONE as int
}

pub struct GlyphMetrics {
    minx: int,
    maxx: int,
    miny: int,
    maxy: int,
    advance: int
}

pub struct Font {
    priv raw: *ffi::TTF_Font
}

impl Drop for Font {
    fn drop(&self) {
        unsafe {
            ffi::TTF_CloseFont(self.raw);
        }
    }
}

impl Font {
    pub fn get_style(&self) -> ~[FontStyle] {
        let bitflags = unsafe { ffi::TTF_GetFontStyle(self.raw) };

        let flags = [
            NormalStyle,
            BoldStyle,
            ItalicStyle,
            UnderlineStyle,
            StrikethroughStyle
        ];

        do flags.iter().filter_map |&flag| {
            if bitflags & (flag as ffi::TTF_StyleFlag) != 0 { Some(flag) }
            else {None}
        }.collect()
    }

    pub fn set_style(&mut self, flags: &[FontStyle]) {
        let bitflags = do flags.iter().fold(0) |bitflags, &flag| {
            bitflags | flag as ffi::TTF_StyleFlag
        };

        unsafe {
            ffi::TTF_SetFontStyle(self.raw, bitflags);
        }
    }

    pub fn get_outline(&self) -> int {
        unsafe {
            ffi::TTF_GetFontOutline(self.raw) as int
        }
    }

    pub fn set_outline(&mut self, outline: int) {
        unsafe {
            ffi::TTF_SetFontOutline(self.raw, outline as c_int);
        }
    }

    pub fn get_hinting(&self) -> FontHinting {
        unsafe {
            cast::transmute(ffi::TTF_GetFontHinting(self.raw) as int)
        }
    }

    pub fn set_hinting(&mut self, hinting: FontHinting) {
        unsafe {
            ffi::TTF_SetFontHinting(self.raw, hinting as ffi::TTF_Hinting);
        }
    }

    pub fn get_kerning(&self) -> int {
        unsafe {
            ffi::TTF_GetFontKerning(self.raw) as int
        }
    }

    pub fn set_kerning(&mut self, kerning: int) {
        unsafe {
            ffi::TTF_SetFontKerning(self.raw, kerning as c_int);
        }
    }

    pub fn height(&self) -> int {
        unsafe {
            ffi::TTF_FontHeight(self.raw) as int
        }
    }

    pub fn ascent(&self) -> int {
        unsafe {
            ffi::TTF_FontAscent(self.raw) as int
        }
    }

    pub fn descent(&self) -> int {
        unsafe {
            ffi::TTF_FontDescent(self.raw) as int
        }
    }

    pub fn line_skip(&self) -> int {
        unsafe {
            ffi::TTF_FontLineSkip(self.raw) as int
        }
    }

    pub fn faces(&self) -> int {
        unsafe {
            ffi::TTF_FontFaces(self.raw) as int
        }
    }

    pub fn face_is_fixed_width(&self) -> bool {
        unsafe {
            ffi::TTF_FontFaceIsFixedWidth(self.raw) > 0
        }
    }

    pub fn face_family_name(&self) -> Option<~str> {
        unsafe {
            let ptr = ffi::TTF_FontFaceFamilyName(self.raw);

            if ptr.is_null() {
                None
            } else {
                Some(str::raw::from_c_str(ptr))
            }
        }
    }

    pub fn glyph_is_provided(&self, glyph: char) -> Option<int> {
        let ch = match char_to_utf16(glyph) {
            Some(ch) => ch,
            None => return None
        };

        unsafe {
            match ffi::TTF_FontGlyphIsProvided(self.raw, ch) {
                0 => None,
                ch => Some(ch as int)
            }
        }
    }

    pub fn glyph_metrics(&self, glyph: char) -> Result<~GlyphMetrics, ~str> {
        let ch = match char_to_utf16(glyph) {
            Some(ch) => ch,
            None => return Err(~"Glyph is not a UTF-16 character")
        };

        let mut minx: c_int = 0;
        let mut maxx: c_int = 0;
        let mut miny: c_int = 0;
        let mut maxy: c_int = 0;
        let mut advance: c_int = 0;

        unsafe {
            match ffi::TTF_GlyphMetrics(self.raw, ch, &mut minx, &mut maxx,
                    &mut miny, &mut maxy, &mut advance) {
                0 => Ok(~GlyphMetrics {minx: minx as int, maxx: maxx as int,
                    miny: miny as int, maxy: maxy as int,
                    advance: advance as int}),
                _ => Err(sdl::get_error())
            }
        }
    }

    pub fn text_size(&self, text: &str) -> Result<(int, int), ~str> {
        let mut w: c_int = 0;
        let mut h: c_int = 0;

        do text.as_c_str |c_text| {
            unsafe {
                match ffi::TTF_SizeUTF8(self.raw, c_text, &mut w, &mut h) {
                    0 => Ok((w as int, h as int)),
                    _ => Err(sdl::get_error())
                }
            }
        }
    }
}

fn char_to_utf16(glyph: char) -> Option<u16> {
    // TODO bounds checking
    if !str::is_utf16([glyph as u16]) {
        return None;
    }

    Some(str::from_char(glyph).to_utf16()[0])
}

pub fn init() -> bool {
    unsafe {
        ffi::TTF_Init() == 0
    }
}

pub fn was_init() -> bool {
    unsafe {
        ffi::TTF_WasInit() == 1
    }
}

pub fn quit() {
    unsafe {
        ffi::TTF_Quit();
    }
}

pub fn open_font(file: &str, ptsize: int) -> Result<~Font, ~str> {
    do file.as_c_str |c_str| {
        unsafe {
            let ptr = ffi::TTF_OpenFont(c_str, ptsize as c_int);
            if ptr.is_null() {
                Err(sdl::get_error())
            } else {
                Ok(~Font {raw: ptr})
            }
        }
    }
}

pub fn open_font_index(file: &str, ptsize: int, index: int)
        -> Result<~Font, ~str> {
    do file.as_c_str |c_str| {
        let ptr = unsafe {
            ffi::TTF_OpenFontIndex(c_str, ptsize as c_int, index as c_long)
        };

        if ptr.is_null() {
            Err(sdl::get_error())
        } else {
            Ok(~Font {raw: ptr})
        }
    }
}

pub fn render_solid(font: &Font, text: &str, fg: Color)
        -> Result<~Surface, ~str> {
    do text.as_c_str |c_text| {
        let ptr = unsafe {
            ffi::TTF_RenderUTF8_Solid(font.raw, c_text, fg.to_struct())
        };

        if ptr.is_null() {
            Err(sdl::get_error())
        } else {
            Ok(~Surface {raw: ptr, owned: true})
        }
    }
}

pub fn render_shaded(font: &Font, text: &str, fg: Color, bg: Color)
        -> Result<~Surface, ~str> {
    do text.as_c_str |c_text| {
        let ptr = unsafe {
            ffi::TTF_RenderUTF8_Shaded(font.raw, c_text, fg.to_struct(),
                bg.to_struct())
        };

        if ptr.is_null() {
            Err(sdl::get_error())
        } else {
            Ok(~Surface {raw: ptr, owned: true})
        }
    }
}

pub fn render_blended(font: &Font, text: &str, fg: Color)
        -> Result<~Surface, ~str> {
    do text.as_c_str |c_text| {
        let ptr = unsafe {
            ffi::TTF_RenderUTF8_Blended(font.raw, c_text, fg.to_struct())
        };

        if ptr.is_null() {
            Err(sdl::get_error())
        } else {
            Ok(~Surface {raw: ptr, owned: true})
        }
    }
}
<|endoftext|>


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

use capnp::{any_pointer};
use capnp::Error;
use capnp::capability::Promise;
use capnp::private::capability::{ClientHook, ParamsHook, PipelineHook, PipelineOp,
                                 ResultsHook, ResultsDoneHook};

use futures::Future;

use std::cell::RefCell;
use std::rc::{Rc};

use {broken, local, ForkedPromise};
use sender_queue::SenderQueue;

struct PipelineInner {
    promise: ForkedPromise<Promise<Box<PipelineHook>, Error>>,

    // Once the promise resolves, this will become non-null and point to the underlying object.
    redirect: Option<Box<PipelineHook>>,

    // Represents the operation which will set `redirect` when possible.
    self_resolution_op: Promise<(), Error>,
}

pub struct Pipeline {
    inner: Rc<RefCell<PipelineInner>>,
}

impl Pipeline {
    pub fn new(promise_param: Promise<Box<PipelineHook>, Error>) -> Pipeline {
        let promise = ForkedPromise::new_queued(promise_param);
        let branch = promise.add_branch();
        let inner = Rc::new(RefCell::new(PipelineInner {
            promise: promise,
            redirect: None,
            self_resolution_op: Promise::ok(()),
        }));
        let this = Rc::downgrade(&inner);
        let self_res = ::eagerly_evaluate(branch.then(move |result| {

            let this = match this.upgrade(){
                Some(v) => v,
                None => return Err(Error::failed("dangling self reference in queued::Pipeline".into())),
            };

            match result {
                Ok(pipeline_hook) => {
                    this.borrow_mut().redirect = Some(pipeline_hook);
                }
                Err(e) => {
                    this.borrow_mut().redirect = Some(Box::new(broken::Pipeline::new(e)));
                }
            }
            Ok(())
        }));
        inner.borrow_mut().self_resolution_op = self_res;
        Pipeline { inner: inner }
    }
}

impl Clone for Pipeline {
    fn clone(&self) -> Pipeline {
        Pipeline { inner: self.inner.clone() }
    }
}

impl PipelineHook for Pipeline {
    fn add_ref(&self) -> Box<PipelineHook> {
        Box::new(self.clone())
    }
    fn get_pipelined_cap(&self, ops: &[PipelineOp]) -> Box<ClientHook> {
        self.get_pipelined_cap_move(ops.into())
    }

    fn get_pipelined_cap_move(&self, ops: Vec<PipelineOp>) -> Box<ClientHook> {
        match &self.inner.borrow().redirect {
            &Some(ref p) => {
                return p.get_pipelined_cap_move(ops)
            }
            &None => (),
        }
        let client_promise = self.inner.borrow_mut().promise.clone().map(move |pipeline| {
            pipeline.get_pipelined_cap_move(ops)
        });

        Box::new(Client::new(Promise::from_future(client_promise)))
    }
}

type ClientHookPromiseFork = ForkedPromise<Promise<Box<ClientHook>, Error>>;

pub struct ClientInner {
    // Once the promise resolves, this will become non-null and point to the underlying object.
    redirect: Option<Box<ClientHook>>,

    // Promise that resolves when we have a new ClientHook to forward to.
    //
    // This fork shall only have three branches:  `selfResolutionOp`, `promiseForCallForwarding`, and
    // `promiseForClientResolution`, in that order.
    _promise: ClientHookPromiseFork,

    // Represents the operation which will set `redirect` when possible.
    self_resolution_op: Promise<(), Error>,

    // When this promise resolves, each queued call will be forwarded to the real client.  This needs
    // to occur *before* any 'whenMoreResolved()' promises resolve, because we want to make sure
    // previously-queued calls are delivered before any new calls made in response to the resolution.
    promise_for_call_forwarding: ClientHookPromiseFork,
    call_forwarding_queue: SenderQueue<(u64, u16, Box<ParamsHook>, Box<ResultsHook>,
                                        Promise<Box<ResultsDoneHook>, Error>),
                                       (Promise<(), Error>, Box<PipelineHook>)>,

    // whenMoreResolved() returns forks of this promise.  These must resolve *after* queued calls
    // have been initiated (so that any calls made in the whenMoreResolved() handler are correctly
    // delivered after calls made earlier), but *before* any queued calls return (because it might
    // confuse the application if a queued call returns before the capability on which it was made
    // resolves).  Luckily, we know that queued calls will involve, at the very least, an
    // eventLoop.evalLater.
    client_resolution_queue: SenderQueue<(), Box<ClientHook>>,
}

impl ClientInner {
    pub fn resolve(state: &Rc<RefCell<ClientInner>>, result: Result<Box<ClientHook>, Error>) {
        let client = match result {
            Ok(clienthook) => clienthook,
            Err(e) => broken::new_cap(e),
        };
        state.borrow_mut().redirect = Some(client.add_ref());

        for ((), waiter) in state.borrow_mut().client_resolution_queue.drain() {
            waiter.complete(client.add_ref());
        }
    }
}

pub struct Client {
    inner: Rc<RefCell<ClientInner>>,
}

impl Client {
    pub fn new(promise_param: Promise<Box<ClientHook>, Error>)
           -> Client
    {
        let promise = ForkedPromise::new_queued(promise_param);
        let branch1 = promise.add_branch();
        let branch2 = promise.add_branch();
        let branch3 = promise.add_branch();
        let inner = Rc::new(RefCell::new(ClientInner {
            redirect: None,
            _promise: promise,
            self_resolution_op: Promise::from_future(::futures::future::empty()),
            promise_for_call_forwarding: branch2,
            call_forwarding_queue: SenderQueue::new(),
            client_resolution_queue: SenderQueue::new(),
        }));
        let this = Rc::downgrade(&inner);
        let self_resolution_op = ::eagerly_evaluate(branch1.then(move |result| {
            let state = match this.upgrade() {
                Some(s) => s,
                None => return Err(Error::failed("dangling reference to QueuedClient".into())),
            };

            ClientInner::resolve(&state, result);
            Ok(())
        }));
        inner.borrow_mut().self_resolution_op = self_resolution_op;
        Client {
            inner: inner
        }
    }
}

impl ClientHook for Client {
    fn add_ref(&self) -> Box<ClientHook> {
        Box::new(Client {inner: self.inner.clone()})
    }
    fn new_call(&self, interface_id: u64, method_id: u16,
                size_hint: Option<::capnp::MessageSize>)
                -> ::capnp::capability::Request<any_pointer::Owned, any_pointer::Owned>
    {
        ::capnp::capability::Request::new(
            Box::new(local::Request::new(interface_id, method_id, size_hint, self.add_ref())))
    }

    fn call(&self, interface_id: u64, method_id: u16, params: Box<ParamsHook>, results: Box<ResultsHook>,
            results_done: Promise<Box<ResultsDoneHook>, Error>)
        -> (Promise<(), Error>, Box<PipelineHook>)
    {

        let promise_for_pair = self.inner.borrow_mut().promise_for_call_forwarding.clone().map(move |client| {
            client.call(interface_id, method_id, params, results, results_done)
        });

        let (promise_promise, pipeline_promise) = ::split::split(promise_for_pair);
        let pipeline = Pipeline::new(Promise::from_future(pipeline_promise));
        (Promise::from_future(promise_promise.flatten()), Box::new(pipeline))
    }

    fn get_ptr(&self) -> usize {
        (&*self.inner.borrow()) as * const _ as usize
    }

    fn get_brand(&self) -> usize {
        0
    }

    fn get_resolved(&self) -> Option<Box<ClientHook>> {
        match self.inner.borrow().redirect {
            Some(ref inner) => Some(inner.clone()),
            None => None,
        }
    }

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

use capnp::{any_pointer};
use capnp::Error;
use capnp::capability::Promise;
use capnp::private::capability::{ClientHook, ParamsHook, PipelineHook, PipelineOp,
                                 ResultsHook, ResultsDoneHook};

use futures::Future;

use std::cell::RefCell;
use std::rc::{Rc};

use {broken, local, ForkedPromise};
use sender_queue::SenderQueue;

struct PipelineInner {
    promise: ForkedPromise<Promise<Box<PipelineHook>, Error>>,

    // Once the promise resolves, this will become non-null and point to the underlying object.
    redirect: Option<Box<PipelineHook>>,

    // Represents the operation which will set `redirect` when possible.
    self_resolution_op: Promise<(), Error>,
}

pub struct Pipeline {
    inner: Rc<RefCell<PipelineInner>>,
}

impl Pipeline {
    pub fn new(promise_param: Promise<Box<PipelineHook>, Error>) -> Pipeline {
        let promise = ForkedPromise::new_queued(promise_param);
        let branch = promise.add_branch();
        let inner = Rc::new(RefCell::new(PipelineInner {
            promise: promise,
            redirect: None,
            self_resolution_op: Promise::ok(()),
        }));
        let this = Rc::downgrade(&inner);
        let self_res = ::eagerly_evaluate(branch.then(move |result| {

            let this = match this.upgrade(){
                Some(v) => v,
                None => return Err(Error::failed("dangling self reference in queued::Pipeline".into())),
            };

            match result {
                Ok(pipeline_hook) => {
                    this.borrow_mut().redirect = Some(pipeline_hook);
                }
                Err(e) => {
                    this.borrow_mut().redirect = Some(Box::new(broken::Pipeline::new(e)));
                }
            }
            Ok(())
        }));
        inner.borrow_mut().self_resolution_op = self_res;
        Pipeline { inner: inner }
    }
}

impl Clone for Pipeline {
    fn clone(&self) -> Pipeline {
        Pipeline { inner: self.inner.clone() }
    }
}

impl PipelineHook for Pipeline {
    fn add_ref(&self) -> Box<PipelineHook> {
        Box::new(self.clone())
    }
    fn get_pipelined_cap(&self, ops: &[PipelineOp]) -> Box<ClientHook> {
        self.get_pipelined_cap_move(ops.into())
    }

    fn get_pipelined_cap_move(&self, ops: Vec<PipelineOp>) -> Box<ClientHook> {
        match &self.inner.borrow().redirect {
            &Some(ref p) => {
                return p.get_pipelined_cap_move(ops)
            }
            &None => (),
        }
        let client_promise = self.inner.borrow_mut().promise.clone().map(move |pipeline| {
            pipeline.get_pipelined_cap_move(ops)
        });

        Box::new(Client::new(Promise::from_future(client_promise)))
    }
}

type ClientHookPromiseFork = ForkedPromise<Promise<Box<ClientHook>, Error>>;

pub struct ClientInner {
    // Once the promise resolves, this will become non-null and point to the underlying object.
    redirect: Option<Box<ClientHook>>,

    // Promise that resolves when we have a new ClientHook to forward to.
    //
    // This fork shall only have three branches:  `selfResolutionOp`, `promiseForCallForwarding`, and
    // `promiseForClientResolution`, in that order.
    _promise: ClientHookPromiseFork,

    // Represents the operation which will set `redirect` when possible.
    self_resolution_op: Promise<(), Error>,

    // When this promise resolves, each queued call will be forwarded to the real client.  This needs
    // to occur *before* any 'whenMoreResolved()' promises resolve, because we want to make sure
    // previously-queued calls are delivered before any new calls made in response to the resolution.
    promise_for_call_forwarding: ClientHookPromiseFork,
    call_forwarding_queue: SenderQueue<(u64, u16, Box<ParamsHook>, Box<ResultsHook>,
                                        Promise<Box<ResultsDoneHook>, Error>),
                                       (Promise<(), Error>, Box<PipelineHook>)>,

    // whenMoreResolved() returns forks of this promise.  These must resolve *after* queued calls
    // have been initiated (so that any calls made in the whenMoreResolved() handler are correctly
    // delivered after calls made earlier), but *before* any queued calls return (because it might
    // confuse the application if a queued call returns before the capability on which it was made
    // resolves).  Luckily, we know that queued calls will involve, at the very least, an
    // eventLoop.evalLater.
    client_resolution_queue: SenderQueue<(), Box<ClientHook>>,
}

impl ClientInner {
    pub fn resolve(state: &Rc<RefCell<ClientInner>>, result: Result<Box<ClientHook>, Error>) {
        let client = match result {
            Ok(clienthook) => clienthook,
            Err(e) => broken::new_cap(e),
        };
        state.borrow_mut().redirect = Some(client.add_ref());

        for (args, waiter) in state.borrow_mut().call_forwarding_queue.drain() {
            let (interface_id, method_id, params, results, results_done) = args;
            let result_pair = client.call(interface_id, method_id, params, results, results_done);
            waiter.complete(result_pair);
        }

        for ((), waiter) in state.borrow_mut().client_resolution_queue.drain() {
            waiter.complete(client.add_ref());
        }
    }
}

pub struct Client {
    inner: Rc<RefCell<ClientInner>>,
}

impl Client {
    pub fn new(promise_param: Promise<Box<ClientHook>, Error>)
           -> Client
    {
        let promise = ForkedPromise::new_queued(promise_param);
        let branch1 = promise.add_branch();
        let branch2 = promise.add_branch();
        let inner = Rc::new(RefCell::new(ClientInner {
            redirect: None,
            _promise: promise,
            self_resolution_op: Promise::from_future(::futures::future::empty()),
            promise_for_call_forwarding: branch2,
            call_forwarding_queue: SenderQueue::new(),
            client_resolution_queue: SenderQueue::new(),
        }));
        let this = Rc::downgrade(&inner);
        let self_resolution_op = ::eagerly_evaluate(branch1.then(move |result| {
            let state = match this.upgrade() {
                Some(s) => s,
                None => return Err(Error::failed("dangling reference to QueuedClient".into())),
            };

            ClientInner::resolve(&state, result);
            Ok(())
        }));
        inner.borrow_mut().self_resolution_op = self_resolution_op;
        Client {
            inner: inner
        }
    }
}

impl ClientHook for Client {
    fn add_ref(&self) -> Box<ClientHook> {
        Box::new(Client {inner: self.inner.clone()})
    }
    fn new_call(&self, interface_id: u64, method_id: u16,
                size_hint: Option<::capnp::MessageSize>)
                -> ::capnp::capability::Request<any_pointer::Owned, any_pointer::Owned>
    {
        ::capnp::capability::Request::new(
            Box::new(local::Request::new(interface_id, method_id, size_hint, self.add_ref())))
    }

    fn call(&self, interface_id: u64, method_id: u16, params: Box<ParamsHook>, results: Box<ResultsHook>,
            results_done: Promise<Box<ResultsDoneHook>, Error>)
        -> (Promise<(), Error>, Box<PipelineHook>)
    {

//        if let Some(ref client) = self.inner.borrow().redirect {
//           client.call(interface_id, method_id, params, results, results_done)
//        } else {

            let promise_for_pair = self.inner.borrow_mut().promise_for_call_forwarding.clone().map(move |client| {
                client.call(interface_id, method_id, params, results, results_done)
            });

//            let promise_for_pair = self.inner.borrow_mut().call_forwarding_queue.push(
//                (interface_id, method_id, params, results, results_done));

            let (promise_promise, pipeline_promise) = ::split::split(promise_for_pair);
            let pipeline = Pipeline::new(Promise::from_future(pipeline_promise));
            (Promise::from_future(promise_promise.flatten()), Box::new(pipeline))
//        }
    }

    fn get_ptr(&self) -> usize {
        (&*self.inner.borrow()) as * const _ as usize
    }

    fn get_brand(&self) -> usize {
        0
    }

    fn get_resolved(&self) -> Option<Box<ClientHook>> {
        match self.inner.borrow().redirect {
            Some(ref inner) => Some(inner.clone()),
            None => None,
        }
    }

    fn when_more_resolved(&self) -> Option<Promise<Box<ClientHook>, Error>> {
        // XXX TODO what if already resolved?
        Some(self.inner.borrow_mut().client_resolution_queue.push(()))
    }
}
<|endoftext|>


<commit_before>use std::fmt;

#[derive(PartialEq, Debug, Clone, Copy)]
pub enum Val {
    Byte(u8),
    Int(i64),
    Float(f64),
}

impl Val {
    pub fn to_i64(&self) -> i64 {
        match *self {
            Val::Byte(val) => val as i64,
            Val::Int(val) => val,
            Val::Float(val) => val as i64,
        }
    }

    pub fn to_u8(&self) -> u8 {
        match *self {
            Val::Byte(val) => val,
            Val::Int(val) => val as u8,
            Val::Float(val) => val as u8,
        }
    }

    pub fn to_f64(&self) -> f64 {
        match *self {
            Val::Byte(val) => val as f64,
            Val::Int(val) => val as f64,
            Val::Float(val) => val,
        }
    }

    pub fn checked_add(&self, other: Val) -> Option<Val> {
        match (*self, other) {
            (Val::Float(f), v) => Some(Val::Float(f + v.to_f64())),
            (v, Val::Float(f)) => Some(Val::Float(v.to_f64() + f)),
            _ => self.to_i64().checked_add(other.to_i64()).map(|v| Val::Int(v)),
        }
    }

    pub fn checked_sub(&self, other: Val) -> Option<Val> {
        match (*self, other) {
            (Val::Float(f), v) => Some(Val::Float(f - v.to_f64())),
            (v, Val::Float(f)) => Some(Val::Float(v.to_f64() - f)),
            _ => self.to_i64().checked_sub(other.to_i64()).map(|v| Val::Int(v)),
        }
    }

    pub fn checked_mul(&self, other: Val) -> Option<Val> {
        match (*self, other) {
            (Val::Float(f), v) => Some(Val::Float(f * v.to_f64())),
            (v, Val::Float(f)) => Some(Val::Float(v.to_f64() * f)),
            _ => self.to_i64().checked_mul(other.to_i64()).map(|v| Val::Int(v)),
        }
    }
}

impl fmt::Display for Val {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match *self {
            Val::Byte(val) => write!(f, "{}", val),
            Val::Int(val) => write!(f, "{}", val),
            Val::Float(val) => write!(f, "{}", val),
        }
    }
}

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

    #[test]
    fn val_to_u8_works() {
        let val = Val::Byte(15);
        assert_eq!(val.to_u8(), 15);

        let val = Val::Int(54);
        assert_eq!(val.to_u8(), 54);
    }

    #[test]
    fn val_to_i64_works() {
        let val = Val::Byte(15);
        assert_eq!(val.to_i64(), 15);

        let val = Val::Int(54);
        assert_eq!(val.to_i64(), 54)
    }

    #[test]
    fn val_to_f64_works() {
        let val = Val::Byte(15);
        assert_eq!(val.to_f64(), 15.0);
    }
}
<commit_msg>Fix invalid default Val equality<commit_after>use std::fmt;

#[derive(Debug, Clone, Copy)]
pub enum Val {
    Byte(u8),
    Int(i64),
    Float(f64),
}

impl Val {
    pub fn to_i64(&self) -> i64 {
        match *self {
            Val::Byte(val) => val as i64,
            Val::Int(val) => val,
            Val::Float(val) => val as i64,
        }
    }

    pub fn to_u8(&self) -> u8 {
        match *self {
            Val::Byte(val) => val,
            Val::Int(val) => val as u8,
            Val::Float(val) => val as u8,
        }
    }

    pub fn to_f64(&self) -> f64 {
        match *self {
            Val::Byte(val) => val as f64,
            Val::Int(val) => val as f64,
            Val::Float(val) => val,
        }
    }

    pub fn checked_add(&self, other: Val) -> Option<Val> {
        match (*self, other) {
            (Val::Float(f), v) => Some(Val::Float(f + v.to_f64())),
            (v, Val::Float(f)) => Some(Val::Float(v.to_f64() + f)),
            _ => self.to_i64().checked_add(other.to_i64()).map(|v| Val::Int(v)),
        }
    }

    pub fn checked_sub(&self, other: Val) -> Option<Val> {
        match (*self, other) {
            (Val::Float(f), v) => Some(Val::Float(f - v.to_f64())),
            (v, Val::Float(f)) => Some(Val::Float(v.to_f64() - f)),
            _ => self.to_i64().checked_sub(other.to_i64()).map(|v| Val::Int(v)),
        }
    }

    pub fn checked_mul(&self, other: Val) -> Option<Val> {
        match (*self, other) {
            (Val::Float(f), v) => Some(Val::Float(f * v.to_f64())),
            (v, Val::Float(f)) => Some(Val::Float(v.to_f64() * f)),
            _ => self.to_i64().checked_mul(other.to_i64()).map(|v| Val::Int(v)),
        }
    }
}

impl PartialEq for Val {
    fn eq(&self, other: &Val) -> bool {
        match (*self, *other) {
            (Val::Float(a), Val::Float(b)) => a == b,
            (Val::Float(_), _) => false,
            (_, Val::Float(_)) => false,
            _ => self.to_i64() == other.to_i64(),
        }
    }
}

impl fmt::Display for Val {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match *self {
            Val::Byte(val) => write!(f, "{}", val),
            Val::Int(val) => write!(f, "{}", val),
            Val::Float(val) => write!(f, "{}", val),
        }
    }
}

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

    #[test]
    fn val_to_u8_works() {
        let val = Val::Byte(15);
        assert_eq!(val.to_u8(), 15);

        let val = Val::Int(54);
        assert_eq!(val.to_u8(), 54);
    }

    #[test]
    fn val_to_i64_works() {
        let val = Val::Byte(15);
        assert_eq!(val.to_i64(), 15);

        let val = Val::Int(54);
        assert_eq!(val.to_i64(), 54)
    }

    #[test]
    fn val_to_f64_works() {
        let val = Val::Byte(15);
        assert_eq!(val.to_f64(), 15.0);
    }

    #[test]
    fn val_eq_works() {
        assert_eq!(Val::Byte(1), Val::Byte(1));
        assert_eq!(Val::Byte(1), Val::Int(1));
        assert_eq!(Val::Int(1), Val::Int(1));
        assert_eq!(Val::Float(1.0), Val::Float(1.0));

        assert_ne!(Val::Byte(1), Val::Byte(2));
        assert_ne!(Val::Int(1), Val::Int(2));
        assert_ne!(Val::Float(1.0), Val::Float(2.0));

        assert_ne!(Val::Byte(1), Val::Float(1.0));
        assert_ne!(Val::Int(1), Val::Float(1.0));
    }
}
<|endoftext|>


<commit_before>use std;
use std::io::{Error, ErrorKind};
use std::io::Read;
use std::net::TcpStream;

/// Reads bytes from the TCP stream until CRLF is found or the given limit is
/// reached.
pub fn read_line(stream: &TcpStream, limit: usize) -> std::io::Result<String> {
  let mut res = vec!();
  for (i, value) in stream.bytes().enumerate() {
    let byte = try!(value);
    if byte == '\n' as u8 {
      // The end of the line. Make sure it actually was CRLF.
      let second_to_last = res.pop().unwrap_or(0);
      if second_to_last != '\r' as u8 {
        return Err(Error::new(ErrorKind::Other, "LF without CR."));
      }

      return match String::from_utf8(res) {
        Ok(s) => Ok(s),
        Err(_) => Err(Error::new(ErrorKind::Other, "Invalid UTF8.")),
      }
    }

    // Add the byte to this line.
    res.push(byte);

    // Check the limit.
    if i == limit {
      return Err(Error::new(ErrorKind::Other, "Line too long."));
    }
  }

  Err(Error::new(ErrorKind::Other, "Unexpected end of stream."))
}

#[cfg(test)]
mod tests {
  use super::read_line;
  use test::create_tcp_stream;

  #[test]
  fn test_readline_basic() {
    let stream = create_tcp_stream("foo\r\n".as_bytes());
    assert_eq!(read_line(&stream, 255).unwrap(), "foo");
  }

  #[test]
  fn test_readline_empty_line() {
    let stream = create_tcp_stream("\r\n".as_bytes());
    assert_eq!(read_line(&stream, 255).unwrap(), "");
  }

  #[test]
  fn test_readline_multiple_lines_reads_only_first() {
    let stream = create_tcp_stream("bar\r\nfoo\r\n".as_bytes());
    assert_eq!(read_line(&stream, 255).unwrap(), "bar");
    assert_eq!(read_line(&stream, 255).unwrap(), "foo");
  }

  #[test]
  fn test_readline_line_too_long() {
    let stream = create_tcp_stream("barbazfoo\r\n".as_bytes());
    assert!(read_line(&stream, 5).is_err());
  }

  #[test]
  fn test_readline_line_at_limit() {
    let stream = create_tcp_stream("123\r\n".as_bytes());
    assert_eq!(read_line(&stream, 5).unwrap(), "123");
  }

  #[test]
  fn test_readline_no_cr_before_lf() {
    let stream = create_tcp_stream("barbazfoo\n".as_bytes());
    assert!(read_line(&stream, 255).is_err());
  }

  #[test]
  fn test_readline_no_crlf() {
    let stream = create_tcp_stream("barbazfoo".as_bytes());
    assert!(read_line(&stream, 255).is_err());
  }

  #[test]
  fn test_readline_no_lf() {
    let stream = create_tcp_stream("barb\razfoo".as_bytes());
    assert!(read_line(&stream, 255).is_err());
  }

  #[test]
  fn test_readline_empty() {
    let stream = create_tcp_stream("".as_bytes());
    assert!(read_line(&stream, 255).is_err());
  }

  #[test]
  fn test_readline_only_lf() {
    let stream = create_tcp_stream("\n".as_bytes());
    assert!(read_line(&stream, 255).is_err());
  }
}
<commit_msg>Implement read_u32 for reading unsigned 32-bit integers from a stream.<commit_after>use std;
use std::io::{Error, ErrorKind};
use std::io::Read;
use std::net::TcpStream;

/// Reads bytes from the TCP stream until CRLF is found or the given limit is
/// reached.
pub fn read_line(stream: &TcpStream, limit: usize) -> std::io::Result<String> {
  let mut res = vec!();
  for (i, value) in stream.bytes().enumerate() {
    let byte = try!(value);
    if byte == '\n' as u8 {
      // The end of the line. Make sure it actually was CRLF.
      let second_to_last = res.pop().unwrap_or(0);
      if second_to_last != '\r' as u8 {
        return Err(Error::new(ErrorKind::Other, "LF without CR."));
      }

      return match String::from_utf8(res) {
        Ok(s) => Ok(s),
        Err(_) => Err(Error::new(ErrorKind::Other, "Invalid UTF8.")),
      }
    }

    // Add the byte to this line.
    res.push(byte);

    // Check the limit.
    if i == limit {
      return Err(Error::new(ErrorKind::Other, "Line too long."));
    }
  }

  Err(Error::new(ErrorKind::Other, "Unexpected end of stream."))
}

/// Reads four bytes from the stream and combines them together to form a 32 bit
/// unsigned integer.
pub fn read_u32(stream: &TcpStream) -> std::io::Result<u32> {
  let mut buf: Vec<u8> = vec![];
  let read = try!(stream.take(4).read_to_end(&mut buf));

  if read < 4 {
    return Err(Error::new(ErrorKind::Other, "Unexpected end of stream."));
  }

  Ok(buf.iter().enumerate().fold(0, |result, (i, value)| {
    result | ((*value as u32) << (3 - i) * 8)
  }))
}

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

  #[test]
  fn test_readline_basic() {
    let stream = create_tcp_stream("foo\r\n".as_bytes());
    assert_eq!(read_line(&stream, 255).unwrap(), "foo");
  }

  #[test]
  fn test_readline_empty_line() {
    let stream = create_tcp_stream("\r\n".as_bytes());
    assert_eq!(read_line(&stream, 255).unwrap(), "");
  }

  #[test]
  fn test_readline_multiple_lines_reads_only_first() {
    let stream = create_tcp_stream("bar\r\nfoo\r\n".as_bytes());
    assert_eq!(read_line(&stream, 255).unwrap(), "bar");
    assert_eq!(read_line(&stream, 255).unwrap(), "foo");
  }

  #[test]
  fn test_readline_line_too_long() {
    let stream = create_tcp_stream("barbazfoo\r\n".as_bytes());
    assert!(read_line(&stream, 5).is_err());
  }

  #[test]
  fn test_readline_line_at_limit() {
    let stream = create_tcp_stream("123\r\n".as_bytes());
    assert_eq!(read_line(&stream, 5).unwrap(), "123");
  }

  #[test]
  fn test_readline_no_cr_before_lf() {
    let stream = create_tcp_stream("barbazfoo\n".as_bytes());
    assert!(read_line(&stream, 255).is_err());
  }

  #[test]
  fn test_readline_no_crlf() {
    let stream = create_tcp_stream("barbazfoo".as_bytes());
    assert!(read_line(&stream, 255).is_err());
  }

  #[test]
  fn test_readline_no_lf() {
    let stream = create_tcp_stream("barb\razfoo".as_bytes());
    assert!(read_line(&stream, 255).is_err());
  }

  #[test]
  fn test_readline_empty() {
    let stream = create_tcp_stream("".as_bytes());
    assert!(read_line(&stream, 255).is_err());
  }

  #[test]
  fn test_readline_only_lf() {
    let stream = create_tcp_stream("\n".as_bytes());
    assert!(read_line(&stream, 255).is_err());
  }

  #[test]
  fn test_read_u32_basic() {
    let stream = create_tcp_stream(&[0x29, 0xb7, 0xf4, 0xaa, 0xff, 0xff]);
    assert_eq!(read_u32(&stream).unwrap(), 0x29b7f4aa);
  }

  #[test]
  fn test_read_u32_basic_zeroes() {
    let stream = create_tcp_stream(&[0x29, 0x00, 0xf4, 0xaa, 0xff, 0xff]);
    assert_eq!(read_u32(&stream).unwrap(), 0x2900f4aa);
  }

  #[test]
  fn test_read_u32_too_little_data() {
    let stream = create_tcp_stream(&[0x29, 0xb7, 0xf4]);
    assert!(read_u32(&stream).is_err());
  }
}
<|endoftext|>


<commit_before>//! Reading I/O operations

use std::io::{Read, Error, ErrorKind};

/// Extends the Read trait to provide common I/O reader operations
pub trait Reader : Read {

    /// Reads an unsigned byte from this Reader
    fn read_unsigned_byte(&mut self) -> Result<u8, Error> {

        let mut raw_buffer = vec![0u8; 1];

        match self.read(&mut raw_buffer) {

            Ok(count) => {
                if count == 1 {
                    return Ok(raw_buffer[0]);
                } else {
                    return Err(Error::new(ErrorKind::Other, "Could not read one byte"));
                }
            },
            Err(error) => {
                return Err(error);
            }

        }

    }

    /// Reads a signed byte from this Reader
    fn read_signed_byte(&mut self) -> Result<i8, Error> {

        let mut raw_buffer = vec![0u8; 1];

        match self.read(&mut raw_buffer) {

            Ok(count) => {
                if count == 1 {
                    return Ok(raw_buffer[0] as i8);
                } else {
                    return Err(Error::new(ErrorKind::Other, "Could not read one byte"));
                }
            },
            Err(error) => {
                return Err(error);
            }

        }

    }

    /// Reads an unsigned big-endian short from this Reader
    fn read_unsigned_be_short(&mut self) -> Result<u16, Error> {

        let mut raw_buffer = vec![0u8; 2];

        match self.read(&mut raw_buffer) {

            Ok(count) => {
                if count == 2 {
                    return Ok(
                        ((raw_buffer[0] as u16) << 8) |
                        raw_buffer[1] as u16
                    );
                } else {
                    return Err(Error::new(ErrorKind::Other, "Could not read two bytes"));
                }
            },
            Err(error) => {
                return Err(error);
            }

        }

    }

    /// Reads an unsigned little-endian short from this Reader
    fn read_unsigned_le_short(&mut self) -> Result<u16, Error> {

        let mut raw_buffer = vec![0u8; 2];

        match self.read(&mut raw_buffer) {

            Ok(count) => {
                if count == 2 {
                    return Ok(
                        raw_buffer[0] as u16 |
                        ((raw_buffer[1] as u16) << 8)
                    );
                } else {
                    return Err(Error::new(ErrorKind::Other, "Could not read two bytes"));
                }
            },
            Err(error) => {
                return Err(error);
            }

        }

    }

    /// Reads a signed big-endian short from this Reader
    fn read_signed_be_short(&mut self) -> Result<i16, Error> {

        let mut raw_buffer = vec![0u8; 2];

        match self.read(&mut raw_buffer) {

            Ok(count) => {
                if count == 2 {
                    return Ok(
                        ((raw_buffer[0] as i16) << 8) |
                        raw_buffer[1] as i16
                    );
                } else {
                    return Err(Error::new(ErrorKind::Other, "Could not read two bytes"));
                }
            },
            Err(error) => {
                return Err(error);
            }

        }

    }

    /// Reads a signed little-endian short from this Reader
    fn read_signed_le_short(&mut self) -> Result<i16, Error> {

        let mut raw_buffer = vec![0u8; 2];

        match self.read(&mut raw_buffer) {

            Ok(count) => {
                if count == 2 {
                    return Ok(
                        raw_buffer[0] as i16 |
                        ((raw_buffer[1] as i16) << 8)
                    );
                } else {
                    return Err(Error::new(ErrorKind::Other, "Could not read two bytes"));
                }
            },
            Err(error) => {
                return Err(error);
            }

        }

    }

    /// Reads an unsigned big-endian integer from this Reader
    fn read_unsigned_be_int(&mut self) -> Result<u32, Error> {

        let mut raw_buffer = vec![0u8; 4];

        match self.read(&mut raw_buffer) {

            Ok(count) => {
                if count == 4 {
                    return Ok(
                        ((raw_buffer[0] as u32) << 24) |
                        ((raw_buffer[1] as u32) << 16) |
                        ((raw_buffer[2] as u32) << 8) |
                        raw_buffer[3] as u32
                    );
                } else {
                    return Err(Error::new(ErrorKind::Other, "Could not read four bytes"));
                }
            },
            Err(error) => {
                return Err(error);
            }

        }

    }

    /// Reads an unsigned little-endian integer from this Reader
    fn read_unsigned_le_int(&mut self) -> Result<u32, Error> {

        let mut raw_buffer = vec![0u8; 4];

        match self.read(&mut raw_buffer) {

            Ok(count) => {
                if count == 4 {
                    return Ok(
                        raw_buffer[0] as u32 |
                        ((raw_buffer[1] as u32) << 8) |
                        ((raw_buffer[2] as u32) << 16) |
                        ((raw_buffer[3] as u32) << 24)
                    );
                } else {
                    return Err(Error::new(ErrorKind::Other, "Could not read four bytes"));
                }
            },
            Err(error) => {
                return Err(error);
            }

        }

    }

    /// Reads a signed big-endian integer from this Reader
    fn read_signed_be_int(&mut self) -> Result<i32, Error> {

        let mut raw_buffer = vec![0u8; 4];

        match self.read(&mut raw_buffer) {

            Ok(count) => {
                if count == 4 {
                    return Ok(
                        ((raw_buffer[0] as i32) << 24) |
                        ((raw_buffer[1] as i32) << 16) |
                        ((raw_buffer[2] as i32) << 8) |
                        raw_buffer[3] as i32
                    );
                } else {
                    return Err(Error::new(ErrorKind::Other, "Could not read four bytes"));
                }
            },
            Err(error) => {
                return Err(error);
            }

        }

    }

    /// Reads a signed little-endian integer from this Reader
    fn read_signed_le_int(&mut self) -> Result<i32, Error> {

        let mut raw_buffer = vec![0u8; 4];

        match self.read(&mut raw_buffer) {

            Ok(count) => {
                if count == 4 {
                    return Ok(
                        raw_buffer[0] as i32 |
                        ((raw_buffer[1] as i32) << 8) |
                        ((raw_buffer[2] as i32) << 16) |
                        ((raw_buffer[3] as i32) << 24)
                    );
                } else {
                    return Err(Error::new(ErrorKind::Other, "Could not read four bytes"));
                }
            },
            Err(error) => {
                return Err(error);
            }

        }

    }

    /// Reads an unsigned big-endian long from this Reader
    fn read_unsigned_be_long(&mut self) -> Result<u64, Error> {

        let mut raw_buffer = vec![0u8; 8];

        match self.read(&mut raw_buffer) {

            Ok(count) => {
                if count == 8 {
                    return Ok(
                        ((raw_buffer[0] as u64) << 56) |
                        ((raw_buffer[1] as u64) << 48) |
                        ((raw_buffer[2] as u64) << 40) |
                        ((raw_buffer[3] as u64) << 32) |
                        ((raw_buffer[4] as u64) << 24) |
                        ((raw_buffer[5] as u64) << 16) |
                        ((raw_buffer[6] as u64) << 8) |
                        raw_buffer[7] as u64
                    );
                } else {
                    return Err(Error::new(ErrorKind::Other, "Could not read eight bytes"));
                }
            },
            Err(error) => {
                return Err(error);
            }

        }

    }

    /// Reads a signed big-endian long from this Reader
    fn read_signed_be_long(&mut self) -> Result<i64, Error> {

        let mut raw_buffer = vec![0u8; 8];

        match self.read(&mut raw_buffer) {

            Ok(count) => {
                if count == 8 {
                    return Ok(
                        ((raw_buffer[0] as i64) << 56) |
                        ((raw_buffer[1] as i64) << 48) |
                        ((raw_buffer[2] as i64) << 40) |
                        ((raw_buffer[3] as i64) << 32) |
                        ((raw_buffer[4] as i64) << 24) |
                        ((raw_buffer[5] as i64) << 16) |
                        ((raw_buffer[6] as i64) << 8) |
                        raw_buffer[7] as i64
                    );
                } else {
                    return Err(Error::new(ErrorKind::Other, "Could not read eight bytes"));
                }
            },
            Err(error) => {
                return Err(error);
            }

        }

    }

    /// Reads an unsigned little-endian long from this Reader
    fn read_unsigned_le_long(&mut self) -> Result<u64, Error> {

        let mut raw_buffer = vec![0u8; 8];

        match self.read(&mut raw_buffer) {

            Ok(count) => {
                if count == 8 {
                    return Ok(
                        raw_buffer[0] as u64 |
                        ((raw_buffer[1] as u64) << 8) |
                        ((raw_buffer[2] as u64) << 16) |
                        ((raw_buffer[3] as u64) << 24) |
                        ((raw_buffer[4] as u64) << 32) |
                        ((raw_buffer[5] as u64) << 40) |
                        ((raw_buffer[6] as u64) << 48) |
                        ((raw_buffer[7] as u64) << 56)
                    );
                } else {
                    return Err(Error::new(ErrorKind::Other, "Could not read eight bytes"));
                }
            },
            Err(error) => {
                return Err(error);
            }

        }

    }

    /// Reads a signed little-endian long from this Reader
    fn read_signed_le_long(&mut self) -> Result<i64, Error> {

        let mut raw_buffer = vec![0u8; 8];

        match self.read(&mut raw_buffer) {

            Ok(count) => {
                if count == 8 {
                    return Ok(
                        raw_buffer[0] as i64 |
                        ((raw_buffer[1] as i64) << 8) |
                        ((raw_buffer[2] as i64) << 16) |
                        ((raw_buffer[3] as i64) << 24) |
                        ((raw_buffer[4] as i64) << 32) |
                        ((raw_buffer[5] as i64) << 40) |
                        ((raw_buffer[6] as i64) << 48) |
                        ((raw_buffer[7] as i64) << 56)
                    );
                } else {
                    return Err(Error::new(ErrorKind::Other, "Could not read eight bytes"));
                }
            },
            Err(error) => {
                return Err(error);
            }

        }

    }
}

impl Reader for ::std::io::Cursor<Vec<u8>> { }
impl Reader for ::std::net::TcpStream { }

#[cfg(test)]
mod tests {

    use super::Reader;

    use std::io::Cursor;

    #[test]
    fn test_read_empty_u8() {

        let mut vector = Cursor::new(vec![0u8; 0]);

        assert!(vector.read_unsigned_byte().is_err());

    }

    #[test]
    fn test_read_empty_i8() {

        let mut vector = Cursor::new(vec![0u8; 0]);

        assert!(vector.read_signed_byte().is_err());

    }

    #[test]
    fn test_read_empty_le_u16() {

        let mut vector = Cursor::new(vec![0u8; 0]);

        assert!(vector.read_unsigned_le_short().is_err());

    }

    #[test]
    fn test_read_empty_le_i16() {

        let mut vector = Cursor::new(vec![0u8; 0]);

        assert!(vector.read_signed_le_short().is_err());

    }

    #[test]
    fn test_read_empty_be_u16() {

        let mut vector = Cursor::new(vec![0u8; 0]);

        assert!(vector.read_unsigned_be_short().is_err());

    }

    #[test]
    fn test_read_empty_be_i16() {

        let mut vector = Cursor::new(vec![0u8; 0]);

        assert!(vector.read_signed_be_short().is_err());

    }

    #[test]
    fn test_read_empty_be_u32() {

        let mut vector = Cursor::new(vec![0u8; 0]);

        assert!(vector.read_unsigned_be_int().is_err());

    }

    #[test]
    fn test_read_empty_be_i32() {

        let mut vector = Cursor::new(vec![0u8; 0]);

        assert!(vector.read_signed_be_int().is_err());

    }

    #[test]
    fn test_read_empty_le_u32() {

        let mut vector = Cursor::new(vec![0u8; 0]);

        assert!(vector.read_unsigned_le_int().is_err());

    }

    #[test]
    fn test_read_empty_le_i32() {

        let mut vector = Cursor::new(vec![0u8; 0]);

        assert!(vector.read_signed_le_int().is_err());

    }

    #[test]
    fn test_read_empty_be_u64() {

        let mut vector = Cursor::new(vec![0u8; 0]);

        assert!(vector.read_unsigned_be_long().is_err());

    }

    #[test]
    fn test_read_empty_be_i64() {

        let mut vector = Cursor::new(vec![0u8; 0]);

        assert!(vector.read_signed_be_long().is_err());

    }

    #[test]
    fn test_read_empty_le_u64() {

        let mut vector = Cursor::new(vec![0u8; 0]);

        assert!(vector.read_unsigned_le_long().is_err());

    }

    #[test]
    fn test_read_empty_le_i64() {

        let mut vector = Cursor::new(vec![0u8; 0]);

        assert!(vector.read_signed_le_long().is_err());

    }

}
<commit_msg>Add a touch more description to errors<commit_after>//! Reading I/O operations

use std::io::{Read, Error, ErrorKind};

/// Extends the Read trait to provide common I/O reader operations
pub trait Reader : Read {

    /// Reads an unsigned byte from this Reader
    fn read_unsigned_byte(&mut self) -> Result<u8, Error> {

        let mut raw_buffer = vec![0u8; 1];

        match self.read(&mut raw_buffer) {

            Ok(count) => {
                if count == 1 {
                    return Ok(raw_buffer[0]);
                } else {
                    return Err(Error::new(ErrorKind::Other, "Could not read one byte (end of stream?)"));
                }
            },
            Err(error) => {
                return Err(error);
            }

        }

    }

    /// Reads a signed byte from this Reader
    fn read_signed_byte(&mut self) -> Result<i8, Error> {

        let mut raw_buffer = vec![0u8; 1];

        match self.read(&mut raw_buffer) {

            Ok(count) => {
                if count == 1 {
                    return Ok(raw_buffer[0] as i8);
                } else {
                    return Err(Error::new(ErrorKind::Other, "Could not read one byte (end of stream?)"));
                }
            },
            Err(error) => {
                return Err(error);
            }

        }

    }

    /// Reads an unsigned big-endian short from this Reader
    fn read_unsigned_be_short(&mut self) -> Result<u16, Error> {

        let mut raw_buffer = vec![0u8; 2];

        match self.read(&mut raw_buffer) {

            Ok(count) => {
                if count == 2 {
                    return Ok(
                        ((raw_buffer[0] as u16) << 8) |
                        raw_buffer[1] as u16
                    );
                } else {
                    return Err(Error::new(ErrorKind::Other, "Could not read two bytes (end of stream?)"));
                }
            },
            Err(error) => {
                return Err(error);
            }

        }

    }

    /// Reads an unsigned little-endian short from this Reader
    fn read_unsigned_le_short(&mut self) -> Result<u16, Error> {

        let mut raw_buffer = vec![0u8; 2];

        match self.read(&mut raw_buffer) {

            Ok(count) => {
                if count == 2 {
                    return Ok(
                        raw_buffer[0] as u16 |
                        ((raw_buffer[1] as u16) << 8)
                    );
                } else {
                    return Err(Error::new(ErrorKind::Other, "Could not read two bytes (end of stream?)"));
                }
            },
            Err(error) => {
                return Err(error);
            }

        }

    }

    /// Reads a signed big-endian short from this Reader
    fn read_signed_be_short(&mut self) -> Result<i16, Error> {

        let mut raw_buffer = vec![0u8; 2];

        match self.read(&mut raw_buffer) {

            Ok(count) => {
                if count == 2 {
                    return Ok(
                        ((raw_buffer[0] as i16) << 8) |
                        raw_buffer[1] as i16
                    );
                } else {
                    return Err(Error::new(ErrorKind::Other, "Could not read two bytes (end of stream?)"));
                }
            },
            Err(error) => {
                return Err(error);
            }

        }

    }

    /// Reads a signed little-endian short from this Reader
    fn read_signed_le_short(&mut self) -> Result<i16, Error> {

        let mut raw_buffer = vec![0u8; 2];

        match self.read(&mut raw_buffer) {

            Ok(count) => {
                if count == 2 {
                    return Ok(
                        raw_buffer[0] as i16 |
                        ((raw_buffer[1] as i16) << 8)
                    );
                } else {
                    return Err(Error::new(ErrorKind::Other, "Could not read two bytes (end of stream?)"));
                }
            },
            Err(error) => {
                return Err(error);
            }

        }

    }

    /// Reads an unsigned big-endian integer from this Reader
    fn read_unsigned_be_int(&mut self) -> Result<u32, Error> {

        let mut raw_buffer = vec![0u8; 4];

        match self.read(&mut raw_buffer) {

            Ok(count) => {
                if count == 4 {
                    return Ok(
                        ((raw_buffer[0] as u32) << 24) |
                        ((raw_buffer[1] as u32) << 16) |
                        ((raw_buffer[2] as u32) << 8) |
                        raw_buffer[3] as u32
                    );
                } else {
                    return Err(Error::new(ErrorKind::Other, "Could not read four bytes (end of stream?)"));
                }
            },
            Err(error) => {
                return Err(error);
            }

        }

    }

    /// Reads an unsigned little-endian integer from this Reader
    fn read_unsigned_le_int(&mut self) -> Result<u32, Error> {

        let mut raw_buffer = vec![0u8; 4];

        match self.read(&mut raw_buffer) {

            Ok(count) => {
                if count == 4 {
                    return Ok(
                        raw_buffer[0] as u32 |
                        ((raw_buffer[1] as u32) << 8) |
                        ((raw_buffer[2] as u32) << 16) |
                        ((raw_buffer[3] as u32) << 24)
                    );
                } else {
                    return Err(Error::new(ErrorKind::Other, "Could not read four bytes (end of stream?)"));
                }
            },
            Err(error) => {
                return Err(error);
            }

        }

    }

    /// Reads a signed big-endian integer from this Reader
    fn read_signed_be_int(&mut self) -> Result<i32, Error> {

        let mut raw_buffer = vec![0u8; 4];

        match self.read(&mut raw_buffer) {

            Ok(count) => {
                if count == 4 {
                    return Ok(
                        ((raw_buffer[0] as i32) << 24) |
                        ((raw_buffer[1] as i32) << 16) |
                        ((raw_buffer[2] as i32) << 8) |
                        raw_buffer[3] as i32
                    );
                } else {
                    return Err(Error::new(ErrorKind::Other, "Could not read four bytes (end of stream?)"));
                }
            },
            Err(error) => {
                return Err(error);
            }

        }

    }

    /// Reads a signed little-endian integer from this Reader
    fn read_signed_le_int(&mut self) -> Result<i32, Error> {

        let mut raw_buffer = vec![0u8; 4];

        match self.read(&mut raw_buffer) {

            Ok(count) => {
                if count == 4 {
                    return Ok(
                        raw_buffer[0] as i32 |
                        ((raw_buffer[1] as i32) << 8) |
                        ((raw_buffer[2] as i32) << 16) |
                        ((raw_buffer[3] as i32) << 24)
                    );
                } else {
                    return Err(Error::new(ErrorKind::Other, "Could not read four bytes (end of stream?)"));
                }
            },
            Err(error) => {
                return Err(error);
            }

        }

    }

    /// Reads an unsigned big-endian long from this Reader
    fn read_unsigned_be_long(&mut self) -> Result<u64, Error> {

        let mut raw_buffer = vec![0u8; 8];

        match self.read(&mut raw_buffer) {

            Ok(count) => {
                if count == 8 {
                    return Ok(
                        ((raw_buffer[0] as u64) << 56) |
                        ((raw_buffer[1] as u64) << 48) |
                        ((raw_buffer[2] as u64) << 40) |
                        ((raw_buffer[3] as u64) << 32) |
                        ((raw_buffer[4] as u64) << 24) |
                        ((raw_buffer[5] as u64) << 16) |
                        ((raw_buffer[6] as u64) << 8) |
                        raw_buffer[7] as u64
                    );
                } else {
                    return Err(Error::new(ErrorKind::Other, "Could not read eight bytes (end of stream?)"));
                }
            },
            Err(error) => {
                return Err(error);
            }

        }

    }

    /// Reads a signed big-endian long from this Reader
    fn read_signed_be_long(&mut self) -> Result<i64, Error> {

        let mut raw_buffer = vec![0u8; 8];

        match self.read(&mut raw_buffer) {

            Ok(count) => {
                if count == 8 {
                    return Ok(
                        ((raw_buffer[0] as i64) << 56) |
                        ((raw_buffer[1] as i64) << 48) |
                        ((raw_buffer[2] as i64) << 40) |
                        ((raw_buffer[3] as i64) << 32) |
                        ((raw_buffer[4] as i64) << 24) |
                        ((raw_buffer[5] as i64) << 16) |
                        ((raw_buffer[6] as i64) << 8) |
                        raw_buffer[7] as i64
                    );
                } else {
                    return Err(Error::new(ErrorKind::Other, "Could not read eight bytes (end of stream?)"));
                }
            },
            Err(error) => {
                return Err(error);
            }

        }

    }

    /// Reads an unsigned little-endian long from this Reader
    fn read_unsigned_le_long(&mut self) -> Result<u64, Error> {

        let mut raw_buffer = vec![0u8; 8];

        match self.read(&mut raw_buffer) {

            Ok(count) => {
                if count == 8 {
                    return Ok(
                        raw_buffer[0] as u64 |
                        ((raw_buffer[1] as u64) << 8) |
                        ((raw_buffer[2] as u64) << 16) |
                        ((raw_buffer[3] as u64) << 24) |
                        ((raw_buffer[4] as u64) << 32) |
                        ((raw_buffer[5] as u64) << 40) |
                        ((raw_buffer[6] as u64) << 48) |
                        ((raw_buffer[7] as u64) << 56)
                    );
                } else {
                    return Err(Error::new(ErrorKind::Other, "Could not read eight bytes (end of stream?)"));
                }
            },
            Err(error) => {
                return Err(error);
            }

        }

    }

    /// Reads a signed little-endian long from this Reader
    fn read_signed_le_long(&mut self) -> Result<i64, Error> {

        let mut raw_buffer = vec![0u8; 8];

        match self.read(&mut raw_buffer) {

            Ok(count) => {
                if count == 8 {
                    return Ok(
                        raw_buffer[0] as i64 |
                        ((raw_buffer[1] as i64) << 8) |
                        ((raw_buffer[2] as i64) << 16) |
                        ((raw_buffer[3] as i64) << 24) |
                        ((raw_buffer[4] as i64) << 32) |
                        ((raw_buffer[5] as i64) << 40) |
                        ((raw_buffer[6] as i64) << 48) |
                        ((raw_buffer[7] as i64) << 56)
                    );
                } else {
                    return Err(Error::new(ErrorKind::Other, "Could not read eight bytes (end of stream?)"));
                }
            },
            Err(error) => {
                return Err(error);
            }

        }

    }
}

impl Reader for ::std::io::Cursor<Vec<u8>> { }
impl Reader for ::std::net::TcpStream { }

#[cfg(test)]
mod tests {

    use super::Reader;

    use std::io::Cursor;

    #[test]
    fn test_read_empty_u8() {

        let mut vector = Cursor::new(vec![0u8; 0]);

        assert!(vector.read_unsigned_byte().is_err());

    }

    #[test]
    fn test_read_empty_i8() {

        let mut vector = Cursor::new(vec![0u8; 0]);

        assert!(vector.read_signed_byte().is_err());

    }

    #[test]
    fn test_read_empty_le_u16() {

        let mut vector = Cursor::new(vec![0u8; 0]);

        assert!(vector.read_unsigned_le_short().is_err());

    }

    #[test]
    fn test_read_empty_le_i16() {

        let mut vector = Cursor::new(vec![0u8; 0]);

        assert!(vector.read_signed_le_short().is_err());

    }

    #[test]
    fn test_read_empty_be_u16() {

        let mut vector = Cursor::new(vec![0u8; 0]);

        assert!(vector.read_unsigned_be_short().is_err());

    }

    #[test]
    fn test_read_empty_be_i16() {

        let mut vector = Cursor::new(vec![0u8; 0]);

        assert!(vector.read_signed_be_short().is_err());

    }

    #[test]
    fn test_read_empty_be_u32() {

        let mut vector = Cursor::new(vec![0u8; 0]);

        assert!(vector.read_unsigned_be_int().is_err());

    }

    #[test]
    fn test_read_empty_be_i32() {

        let mut vector = Cursor::new(vec![0u8; 0]);

        assert!(vector.read_signed_be_int().is_err());

    }

    #[test]
    fn test_read_empty_le_u32() {

        let mut vector = Cursor::new(vec![0u8; 0]);

        assert!(vector.read_unsigned_le_int().is_err());

    }

    #[test]
    fn test_read_empty_le_i32() {

        let mut vector = Cursor::new(vec![0u8; 0]);

        assert!(vector.read_signed_le_int().is_err());

    }

    #[test]
    fn test_read_empty_be_u64() {

        let mut vector = Cursor::new(vec![0u8; 0]);

        assert!(vector.read_unsigned_be_long().is_err());

    }

    #[test]
    fn test_read_empty_be_i64() {

        let mut vector = Cursor::new(vec![0u8; 0]);

        assert!(vector.read_signed_be_long().is_err());

    }

    #[test]
    fn test_read_empty_le_u64() {

        let mut vector = Cursor::new(vec![0u8; 0]);

        assert!(vector.read_unsigned_le_long().is_err());

    }

    #[test]
    fn test_read_empty_le_i64() {

        let mut vector = Cursor::new(vec![0u8; 0]);

        assert!(vector.read_signed_le_long().is_err());

    }

}
<|endoftext|>