<commit_before>use Addr;
use std::mem::transmute;
use system::memory::{read, write};
use prelude::*;

pub fn random() -> f64 {
    let random = unsafe { transmute::<Addr, extern "C" fn() -> f64>(0x80243b40) };
    random()
}

pub fn cdyl_init_async() {
    let cdyl_init_async = unsafe { transmute::<Addr, extern "C" fn()>(0x80022A88) };
    cdyl_init_async();
}

pub fn dmeter_rupy_init(addr: Addr) {
    let dmeter_rupy_init = unsafe { transmute::<Addr, extern "C" fn(Addr)>(0x801F7868) };
    dmeter_rupy_init(addr);
}

pub fn get_frame_count() -> u32 {
    read(0x80396218)
}

pub fn is_pause_menu_up() -> bool {
    read(0x803EA537) // alternative: 0x80396228
}

pub fn set_wind(direction: u8) {
    write(0x803D894A, direction << 5);
}

pub fn get_layer_by_id(id: i32) -> Addr {
    let fpcly_layer = unsafe { transmute::<Addr, extern "C" fn(i32) -> Addr>(0x8003b92c) };
    fpcly_layer(id)
}

pub fn set_current_layer(addr: Addr) {
    let fpcly_set_current_layer = unsafe { transmute::<Addr, extern "C" fn(Addr)>(0x8003b8cc) };
    fpcly_set_current_layer(addr)
}

pub fn get_current_layer() -> Addr {
    let fpcly_current_layer = unsafe { transmute::<Addr, extern "C" fn() -> Addr>(0x8003b8d4) };
    fpcly_current_layer()
}

pub fn get_root_layer() -> Addr {
    read(0x80365B7C)
}

use game::actor::{ActorTemplate, ActorMemory};

pub fn dstage_actor_create(template: *const ActorTemplate, memory: *mut ActorMemory) {
    let dstage_actor_create = unsafe {
        transmute::<Addr, extern "C" fn(*const ActorTemplate, *mut ActorMemory)>(0x8003f484)
    };
    dstage_actor_create(template, memory);
}

pub fn fopacm_create_append() -> &'static mut ActorMemory {
    let fopacm_create_append = unsafe {
        transmute::<Addr, extern "C" fn() -> *mut ActorMemory>(0x80023f3c)
    };
    let actor_memory = fopacm_create_append();
    unsafe { &mut *actor_memory }
}

pub fn layer_loader(dzr: Addr, layer: Addr, room_id: u8) {
    let layer_loader = unsafe { transmute::<Addr, extern "C" fn(Addr, Addr, u8)>(0x80040f3c) };
    layer_loader(dzr, layer, room_id);
}

pub fn report(text: &str) {
    let os_report = unsafe { transmute::<Addr, extern "C" fn(*const u8)>(0x800068ec) };

    let mut buffer = Vec::with_capacity(text.len());
    for &c in text.as_bytes() {
        buffer.push(c);
        if c == b'%' {
            buffer.push(b'%');
        }
    }
    buffer.push(0);

    os_report(buffer.as_ptr());
}
<commit_msg>Fix unnecessary Reallocations when Logging<commit_after>use Addr;
use std::mem::transmute;
use system::memory::{read, write};
use prelude::*;

pub fn random() -> f64 {
    let random = unsafe { transmute::<Addr, extern "C" fn() -> f64>(0x80243b40) };
    random()
}

pub fn cdyl_init_async() {
    let cdyl_init_async = unsafe { transmute::<Addr, extern "C" fn()>(0x80022A88) };
    cdyl_init_async();
}

pub fn dmeter_rupy_init(addr: Addr) {
    let dmeter_rupy_init = unsafe { transmute::<Addr, extern "C" fn(Addr)>(0x801F7868) };
    dmeter_rupy_init(addr);
}

pub fn get_frame_count() -> u32 {
    read(0x80396218)
}

pub fn is_pause_menu_up() -> bool {
    read(0x803EA537) // alternative: 0x80396228
}

pub fn set_wind(direction: u8) {
    write(0x803D894A, direction << 5);
}

pub fn get_layer_by_id(id: i32) -> Addr {
    let fpcly_layer = unsafe { transmute::<Addr, extern "C" fn(i32) -> Addr>(0x8003b92c) };
    fpcly_layer(id)
}

pub fn set_current_layer(addr: Addr) {
    let fpcly_set_current_layer = unsafe { transmute::<Addr, extern "C" fn(Addr)>(0x8003b8cc) };
    fpcly_set_current_layer(addr)
}

pub fn get_current_layer() -> Addr {
    let fpcly_current_layer = unsafe { transmute::<Addr, extern "C" fn() -> Addr>(0x8003b8d4) };
    fpcly_current_layer()
}

pub fn get_root_layer() -> Addr {
    read(0x80365B7C)
}

use game::actor::{ActorTemplate, ActorMemory};

pub fn dstage_actor_create(template: *const ActorTemplate, memory: *mut ActorMemory) {
    let dstage_actor_create = unsafe {
        transmute::<Addr, extern "C" fn(*const ActorTemplate, *mut ActorMemory)>(0x8003f484)
    };
    dstage_actor_create(template, memory);
}

pub fn fopacm_create_append() -> &'static mut ActorMemory {
    let fopacm_create_append = unsafe {
        transmute::<Addr, extern "C" fn() -> *mut ActorMemory>(0x80023f3c)
    };
    let actor_memory = fopacm_create_append();
    unsafe { &mut *actor_memory }
}

pub fn layer_loader(dzr: Addr, layer: Addr, room_id: u8) {
    let layer_loader = unsafe { transmute::<Addr, extern "C" fn(Addr, Addr, u8)>(0x80040f3c) };
    layer_loader(dzr, layer, room_id);
}

pub fn report(text: &str) {
    let os_report = unsafe { transmute::<Addr, extern "C" fn(*const u8)>(0x800068ec) };

    let mut buffer = Vec::with_capacity(text.len() + 1);
    for &c in text.as_bytes() {
        buffer.push(c);
        if c == b'%' {
            buffer.push(b'%');
        }
    }
    buffer.push(0);

    os_report(buffer.as_ptr());
}
<|endoftext|>


<commit_before>// Copyright (c) 2016 Chef Software Inc. and/or applicable contributors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

//! Contains types and functions for sending and receiving messages to and from a message broker
//! connected to one or more `RouteSrv`. All messages are routed through a `RouteSrv` and forwarded
//! to the appropriate receiver of a message.

use std::net;
use std::result;
use std::sync::mpsc;
use std::thread::{self, JoinHandle};

use fnv::FnvHasher;
use protobuf::{self, parse_from_bytes, Message};
use protocol::{self, Routable, RouteKey};
use protocol::net::{ErrCode, NetError};
use zmq;

use config::ToAddrString;
use error::Result;
use server::ZMQ_CONTEXT;

pub type RouteResult<T> = result::Result<T, NetError>;

/// Time to wait before timing out a message receive for a `BrokerConn`.
pub const RECV_TIMEOUT_MS: i32 = 5_000;
/// Time to wait before timing out a message send for a `Broker` to a router.
pub const SEND_TIMEOUT_MS: i32 = 5_000;
// ZeroMQ address for the application's Broker's queue.
const ROUTE_INPROC_ADDR: &'static str = "inproc://route-broker";

/// Client connection for sending and receiving messages to and from the service cluster through
/// a running `Broker`.
pub struct BrokerConn {
    sock: zmq::Socket,
    hasher: FnvHasher,
}

impl BrokerConn {
    /// Create a new `BrokerConn`
    ///
    /// # Errors
    ///
    /// * Socket could not be created
    /// * Socket could not be configured
    pub fn new() -> Result<Self> {
        let socket = try!((**ZMQ_CONTEXT).as_mut().socket(zmq::REQ));
        try!(socket.set_rcvtimeo(RECV_TIMEOUT_MS));
        try!(socket.set_sndtimeo(SEND_TIMEOUT_MS));
        try!(socket.set_immediate(true));
        Ok(BrokerConn {
            sock: socket,
            hasher: FnvHasher::default(),
        })
    }

    /// Connect to a running `Broker` with the given ZeroMQ address.
    ///
    /// # Errors
    ///
    /// * A connection cannot be established to a socket at the given address
    pub fn connect(&mut self, addr: &str) -> Result<()> {
        try!(self.sock.connect(addr));
        Ok(())
    }

    /// Routes a message to the connected broker, through a router, and to appropriate service,
    /// waits for a response, and then parses and returns the value of the response.
    ///
    /// # Errors
    ///
    /// * One or more message frames cannot be sent to the Broker's queue
    ///
    /// # Panics
    ///
    /// * Could not serialize message
    pub fn route<M: Routable, R: protobuf::MessageStatic>(&mut self, msg: &M) -> RouteResult<R> {
        if self.route_async(msg).is_err() {
            return Err(protocol::net::err(ErrCode::ZMQ, "net:route:1"));
        }
        match self.recv() {
            Ok(rep) => {
                if rep.get_message_id() == "NetError" {
                    let err = parse_from_bytes(rep.get_body()).unwrap();
                    return Err(err);
                }
                match parse_from_bytes::<R>(rep.get_body()) {
                    Ok(entity) => Ok(entity),
                    Err(_) => {
                        unreachable!("unexpected response, message_id={}", rep.get_message_id())
                    }
                }
            }
            Err(e) => {
                debug!("recv err, {}", e);
                Err(protocol::net::err(ErrCode::ZMQ, "net:route:3"))
            }
        }
    }

    /// Asynchronously routes a message to the connected broker, through a router, and to
    /// appropriate service.
    ///
    /// # Errors
    ///
    /// * One or more message frames cannot be sent to the Broker's queue
    ///
    /// # Panics
    ///
    /// * Could not serialize message
    pub fn route_async<M: Routable>(&mut self, msg: &M) -> Result<()> {
        let route_hash = msg.route_key().map(|key| key.hash(&mut self.hasher));
        let req = protocol::Message::new(msg).routing(route_hash).build();
        let bytes = req.write_to_bytes().unwrap();
        try!(self.sock.send_str("RQ", zmq::SNDMORE));
        try!(self.sock.send(&bytes, 0));
        Ok(())
    }

    /// Receives a message from the connected broker. This function will block the calling thread
    /// until a message is received or a timeout occurs.
    ///
    /// # Errors
    ///
    /// * `Broker` Queue became unavailable
    /// * Message was not received within the timeout
    /// * Received an unparsable message
    pub fn recv(&mut self) -> Result<protocol::net::Msg> {
        let envelope = try!(self.sock.recv_msg(0));
        let msg: protocol::net::Msg = try!(parse_from_bytes(&envelope));
        Ok(msg)
    }
}

/// A messaging Broker for proxying messages from clients to one or more `RouteSrv` and vice versa.
pub struct Broker {
    client_sock: zmq::Socket,
    router_sock: zmq::Socket,
}

impl Broker {
    /// Create a new `Broker`
    ///
    /// # Errors
    ///
    /// * A socket cannot be created within the given `zmq::Context`
    /// * A socket cannot be configured
    ///
    /// # Panics
    ///
    /// * Could not read `zmq::Context` due to deadlock or poisoning
    fn new(net_ident: String) -> Result<Self> {
        let fe = try!((**ZMQ_CONTEXT).as_mut().socket(zmq::ROUTER));
        let be = try!((**ZMQ_CONTEXT).as_mut().socket(zmq::DEALER));
        try!(fe.set_identity(net_ident.as_bytes()));
        try!(be.set_rcvtimeo(RECV_TIMEOUT_MS));
        try!(be.set_sndtimeo(SEND_TIMEOUT_MS));
        try!(be.set_immediate(true));
        Ok(Broker {
            client_sock: fe,
            router_sock: be,
        })
    }

    /// Helper function for creating a new `BrokerConn` and connecting to the application's `Broker`
    ///
    /// # Errors
    ///
    /// * Could not connect to `Broker`
    /// * Could not create socket
    ///
    /// # Panics
    ///
    /// * Could not read `zmq::Context` due to deadlock or poisoning
    pub fn connect() -> Result<BrokerConn> {
        let mut conn = try!(BrokerConn::new());
        try!(conn.connect(ROUTE_INPROC_ADDR));
        Ok(conn)
    }

    /// Create a new `Broker` and run it in a separate thread. This function will block the calling
    /// thread until the new broker has successfully started.
    ///
    /// # Panics
    ///
    /// * Broker crashed during startup
    pub fn run(net_ident: String, routers: &Vec<net::SocketAddrV4>) -> JoinHandle<()> {
        let (tx, rx) = mpsc::sync_channel(1);
        let addrs = routers.iter().map(|a| a.to_addr_string()).collect();
        let handle = thread::Builder::new()
            .name("router-broker".to_string())
            .spawn(move || {
                let mut broker = Self::new(net_ident).unwrap();
                broker.start(tx, addrs).unwrap();
            })
            .unwrap();
        match rx.recv() {
            Ok(()) => handle,
            Err(e) => panic!("router-broker thread startup error, err={}", e),
        }
    }

    // Main loop for `Broker`.
    //
    // Binds front-end socket to ZeroMQ inproc address and connects to all routers. Sends a message
    // back to the caller over the given rendezvous channel to signal when ready.
    fn start(&mut self, rz: mpsc::SyncSender<()>, routers: Vec<String>) -> Result<()> {
        try!(self.client_sock.bind(ROUTE_INPROC_ADDR));
        for addr in routers {
            try!(self.router_sock.connect(&addr));
        }
        rz.send(()).unwrap();
        try!(zmq::proxy(&mut self.client_sock, &mut self.router_sock));
        Ok(())
    }
}
<commit_msg>Improve logging/handling when receiving an unexpected route reply<commit_after>// Copyright (c) 2016 Chef Software Inc. and/or applicable contributors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

//! Contains types and functions for sending and receiving messages to and from a message broker
//! connected to one or more `RouteSrv`. All messages are routed through a `RouteSrv` and forwarded
//! to the appropriate receiver of a message.

use std::net;
use std::result;
use std::sync::mpsc;
use std::thread::{self, JoinHandle};

use fnv::FnvHasher;
use protobuf::{self, parse_from_bytes, Message};
use protocol::{self, Routable, RouteKey};
use protocol::net::{ErrCode, NetError};
use zmq;

use config::ToAddrString;
use error::Result;
use server::ZMQ_CONTEXT;

pub type RouteResult<T> = result::Result<T, NetError>;

/// Time to wait before timing out a message receive for a `BrokerConn`.
pub const RECV_TIMEOUT_MS: i32 = 5_000;
/// Time to wait before timing out a message send for a `Broker` to a router.
pub const SEND_TIMEOUT_MS: i32 = 5_000;
// ZeroMQ address for the application's Broker's queue.
const ROUTE_INPROC_ADDR: &'static str = "inproc://route-broker";

/// Client connection for sending and receiving messages to and from the service cluster through
/// a running `Broker`.
pub struct BrokerConn {
    sock: zmq::Socket,
    hasher: FnvHasher,
}

impl BrokerConn {
    /// Create a new `BrokerConn`
    ///
    /// # Errors
    ///
    /// * Socket could not be created
    /// * Socket could not be configured
    pub fn new() -> Result<Self> {
        let socket = try!((**ZMQ_CONTEXT).as_mut().socket(zmq::REQ));
        try!(socket.set_rcvtimeo(RECV_TIMEOUT_MS));
        try!(socket.set_sndtimeo(SEND_TIMEOUT_MS));
        try!(socket.set_immediate(true));
        Ok(BrokerConn {
            sock: socket,
            hasher: FnvHasher::default(),
        })
    }

    /// Connect to a running `Broker` with the given ZeroMQ address.
    ///
    /// # Errors
    ///
    /// * A connection cannot be established to a socket at the given address
    pub fn connect(&mut self, addr: &str) -> Result<()> {
        try!(self.sock.connect(addr));
        Ok(())
    }

    /// Routes a message to the connected broker, through a router, and to appropriate service,
    /// waits for a response, and then parses and returns the value of the response.
    ///
    /// # Errors
    ///
    /// * One or more message frames cannot be sent to the Broker's queue
    ///
    /// # Panics
    ///
    /// * Could not serialize message
    pub fn route<M: Routable, R: protobuf::MessageStatic>(&mut self, msg: &M) -> RouteResult<R> {
        if self.route_async(msg).is_err() {
            return Err(protocol::net::err(ErrCode::ZMQ, "net:route:1"));
        }
        match self.recv() {
            Ok(rep) => {
                if rep.get_message_id() == "NetError" {
                    let err = parse_from_bytes(rep.get_body()).unwrap();
                    return Err(err);
                }
                match parse_from_bytes::<R>(rep.get_body()) {
                    Ok(entity) => Ok(entity),
                    Err(err) => {
                        error!("bad route reply, err={}, reply={:?}", err, rep);
                        Err(protocol::net::err(ErrCode::BUG, "net:route:2"))
                    }
                }
            }
            Err(e) => {
                debug!("recv err, {}", e);
                Err(protocol::net::err(ErrCode::ZMQ, "net:route:3"))
            }
        }
    }

    /// Asynchronously routes a message to the connected broker, through a router, and to
    /// appropriate service.
    ///
    /// # Errors
    ///
    /// * One or more message frames cannot be sent to the Broker's queue
    ///
    /// # Panics
    ///
    /// * Could not serialize message
    pub fn route_async<M: Routable>(&mut self, msg: &M) -> Result<()> {
        let route_hash = msg.route_key().map(|key| key.hash(&mut self.hasher));
        let req = protocol::Message::new(msg).routing(route_hash).build();
        let bytes = req.write_to_bytes().unwrap();
        try!(self.sock.send_str("RQ", zmq::SNDMORE));
        try!(self.sock.send(&bytes, 0));
        Ok(())
    }

    /// Receives a message from the connected broker. This function will block the calling thread
    /// until a message is received or a timeout occurs.
    ///
    /// # Errors
    ///
    /// * `Broker` Queue became unavailable
    /// * Message was not received within the timeout
    /// * Received an unparsable message
    pub fn recv(&mut self) -> Result<protocol::net::Msg> {
        let envelope = try!(self.sock.recv_msg(0));
        let msg: protocol::net::Msg = try!(parse_from_bytes(&envelope));
        Ok(msg)
    }
}

/// A messaging Broker for proxying messages from clients to one or more `RouteSrv` and vice versa.
pub struct Broker {
    client_sock: zmq::Socket,
    router_sock: zmq::Socket,
}

impl Broker {
    /// Create a new `Broker`
    ///
    /// # Errors
    ///
    /// * A socket cannot be created within the given `zmq::Context`
    /// * A socket cannot be configured
    ///
    /// # Panics
    ///
    /// * Could not read `zmq::Context` due to deadlock or poisoning
    fn new(net_ident: String) -> Result<Self> {
        let fe = try!((**ZMQ_CONTEXT).as_mut().socket(zmq::ROUTER));
        let be = try!((**ZMQ_CONTEXT).as_mut().socket(zmq::DEALER));
        try!(fe.set_identity(net_ident.as_bytes()));
        try!(be.set_rcvtimeo(RECV_TIMEOUT_MS));
        try!(be.set_sndtimeo(SEND_TIMEOUT_MS));
        try!(be.set_immediate(true));
        Ok(Broker {
            client_sock: fe,
            router_sock: be,
        })
    }

    /// Helper function for creating a new `BrokerConn` and connecting to the application's `Broker`
    ///
    /// # Errors
    ///
    /// * Could not connect to `Broker`
    /// * Could not create socket
    ///
    /// # Panics
    ///
    /// * Could not read `zmq::Context` due to deadlock or poisoning
    pub fn connect() -> Result<BrokerConn> {
        let mut conn = try!(BrokerConn::new());
        try!(conn.connect(ROUTE_INPROC_ADDR));
        Ok(conn)
    }

    /// Create a new `Broker` and run it in a separate thread. This function will block the calling
    /// thread until the new broker has successfully started.
    ///
    /// # Panics
    ///
    /// * Broker crashed during startup
    pub fn run(net_ident: String, routers: &Vec<net::SocketAddrV4>) -> JoinHandle<()> {
        let (tx, rx) = mpsc::sync_channel(1);
        let addrs = routers.iter().map(|a| a.to_addr_string()).collect();
        let handle = thread::Builder::new()
            .name("router-broker".to_string())
            .spawn(move || {
                let mut broker = Self::new(net_ident).unwrap();
                broker.start(tx, addrs).unwrap();
            })
            .unwrap();
        match rx.recv() {
            Ok(()) => handle,
            Err(e) => panic!("router-broker thread startup error, err={}", e),
        }
    }

    // Main loop for `Broker`.
    //
    // Binds front-end socket to ZeroMQ inproc address and connects to all routers. Sends a message
    // back to the caller over the given rendezvous channel to signal when ready.
    fn start(&mut self, rz: mpsc::SyncSender<()>, routers: Vec<String>) -> Result<()> {
        try!(self.client_sock.bind(ROUTE_INPROC_ADDR));
        for addr in routers {
            try!(self.router_sock.connect(&addr));
        }
        rz.send(()).unwrap();
        try!(zmq::proxy(&mut self.client_sock, &mut self.router_sock));
        Ok(())
    }
}
<|endoftext|>


<commit_before>extern crate channel;
extern crate crossbeam;

use channel::{bounded, unbounded};

#[test]
fn smoke() {
    channel::unbounded::<i32>();
    channel::bounded::<i32>(7);
    channel::bounded::<i32>(0);
}

#[test]
fn nested_recv_iter() {
    let (tx, rx) = unbounded::<i32>();
    let (total_tx, total_rx) = unbounded::<i32>();

    crossbeam::scope(|s| {
        s.spawn(move || {
            let mut acc = 0;
            for x in rx.iter() {
                acc += x;
            }
            total_tx.send(acc).unwrap();
        });

        tx.send(3).unwrap();
        tx.send(1).unwrap();
        tx.send(2).unwrap();
        drop(tx);
        assert_eq!(total_rx.recv().unwrap(), 6);
    });
}

#[test]
fn recv_iter_break() {
    let (tx, rx) = unbounded::<i32>();
    let (count_tx, count_rx) = unbounded();

    crossbeam::scope(|s| {
        s.spawn(move || {
            let mut count = 0;
            for x in rx.iter() {
                if count >= 3 {
                    break;
                } else {
                    count += x;
                }
            }
            count_tx.send(count).unwrap();
        });

        tx.send(2).unwrap();
        tx.send(2).unwrap();
        tx.send(2).unwrap();
        let _ = tx.send(2);
        drop(tx);
        assert_eq!(count_rx.recv().unwrap(), 4);
    })
}

#[test]
fn recv_try_iter() {
    let (request_tx, request_rx) = unbounded();
    let (response_tx, response_rx) = unbounded();

    crossbeam::scope(|s| {
        // Request `x`s until we have `6`.
        s.spawn(move || {
            let mut count = 0;
            loop {
                for x in response_rx.try_iter() {
                    count += x;
                    if count == 6 {
                        assert_eq!(count, 6);
                        return;
                    }
                }
                request_tx.send(()).unwrap();
            }
        });

        for _ in request_rx.iter() {
            if response_tx.send(2).is_err() {
                break;
            }
        }
    })
}

#[test]
fn recv_into_iter_owned() {
    let mut iter = {
        let (tx, rx) = unbounded::<i32>();
        tx.send(1).unwrap();
        tx.send(2).unwrap();
        rx.into_iter()
    };

    assert_eq!(iter.next().unwrap(), 1);
    assert_eq!(iter.next().unwrap(), 2);
    assert_eq!(iter.next().is_none(), true);
}

#[test]
fn recv_into_iter_borrowed() {
    let (tx, rx) = unbounded::<i32>();
    tx.send(1).unwrap();
    tx.send(2).unwrap();
    drop(tx);

    let mut iter = (&rx).into_iter();
    assert_eq!(iter.next().unwrap(), 1);
    assert_eq!(iter.next().unwrap(), 2);
    assert_eq!(iter.next().is_none(), true);
}
<commit_msg>Fix unused import<commit_after>extern crate channel;
extern crate crossbeam;

use channel::{bounded, unbounded};

#[test]
fn smoke() {
    unbounded::<i32>();
    bounded::<i32>(7);
    bounded::<i32>(0);
}

#[test]
fn nested_recv_iter() {
    let (tx, rx) = unbounded::<i32>();
    let (total_tx, total_rx) = unbounded::<i32>();

    crossbeam::scope(|s| {
        s.spawn(move || {
            let mut acc = 0;
            for x in rx.iter() {
                acc += x;
            }
            total_tx.send(acc).unwrap();
        });

        tx.send(3).unwrap();
        tx.send(1).unwrap();
        tx.send(2).unwrap();
        drop(tx);
        assert_eq!(total_rx.recv().unwrap(), 6);
    });
}

#[test]
fn recv_iter_break() {
    let (tx, rx) = unbounded::<i32>();
    let (count_tx, count_rx) = unbounded();

    crossbeam::scope(|s| {
        s.spawn(move || {
            let mut count = 0;
            for x in rx.iter() {
                if count >= 3 {
                    break;
                } else {
                    count += x;
                }
            }
            count_tx.send(count).unwrap();
        });

        tx.send(2).unwrap();
        tx.send(2).unwrap();
        tx.send(2).unwrap();
        let _ = tx.send(2);
        drop(tx);
        assert_eq!(count_rx.recv().unwrap(), 4);
    })
}

#[test]
fn recv_try_iter() {
    let (request_tx, request_rx) = unbounded();
    let (response_tx, response_rx) = unbounded();

    crossbeam::scope(|s| {
        // Request `x`s until we have `6`.
        s.spawn(move || {
            let mut count = 0;
            loop {
                for x in response_rx.try_iter() {
                    count += x;
                    if count == 6 {
                        assert_eq!(count, 6);
                        return;
                    }
                }
                request_tx.send(()).unwrap();
            }
        });

        for _ in request_rx.iter() {
            if response_tx.send(2).is_err() {
                break;
            }
        }
    })
}

#[test]
fn recv_into_iter_owned() {
    let mut iter = {
        let (tx, rx) = unbounded::<i32>();
        tx.send(1).unwrap();
        tx.send(2).unwrap();
        rx.into_iter()
    };

    assert_eq!(iter.next().unwrap(), 1);
    assert_eq!(iter.next().unwrap(), 2);
    assert_eq!(iter.next().is_none(), true);
}

#[test]
fn recv_into_iter_borrowed() {
    let (tx, rx) = unbounded::<i32>();
    tx.send(1).unwrap();
    tx.send(2).unwrap();
    drop(tx);

    let mut iter = (&rx).into_iter();
    assert_eq!(iter.next().unwrap(), 1);
    assert_eq!(iter.next().unwrap(), 2);
    assert_eq!(iter.next().is_none(), true);
}
<|endoftext|>


<commit_before>//! This module currently provides utility methods and structs for variable
//! byte codes as described in
//! http://nlp.stanford.edu/IR-book/html/htmledition/variable-byte-codes-1.html.
//!
//! Encode unsigned integers by using the `vbyte_encode` method.
//!
//! Decode a bytestream by instatiating a `VByteDecoder` and using its iterator
//! implementation.
//!
//! #Example
//!
//! ```rust,ignore
//!
//! use perlin::utils::compression::{vbyte_encode, VByteDecoder};
//!
//! let bytes = vbyte_encode(3);
//! let three = VByteDecoder::new(bytes.into_iter()).next().unwrap();
//! assert_eq!(3, three);
//! ```

//TODO: This module is full with now deprecated or obsolete stuff
//Clean up!

use std::io;
use std::io::{Seek, SeekFrom, Read, Write, Error};

/// Stores the result of a vbyte encode operation without indirection that a `Vec<u8>` would introduce.
/// Can thus be used to `vbyte_encode` on the stack
pub struct VByteEncoded {
    // Memory layout of the result: [ payload | payload | payload | ... | used_bytes ]
    data: [u8; 11],
}

impl VByteEncoded {
    /// Performs a vbyte encode without allocating memory on the heap
    /// Can then be written to a `Write`-implementor
    pub fn new(mut number: usize) -> Self {
        let mut count = 0;
        let mut result = [0u8; 11];
        loop {
            result[9 - count] = (number % 128) as u8;
            count += 1;
            if number < 128 {
                break;
            } else {
                number /= 128;
            }
        }
        result[9] += 128;
        result[10] = count as u8;
        VByteEncoded { data: result }
    }

    /// Return how many bytes are used to encode the number. Min: 1 Max: 10
    pub fn bytes_used(&self) -> u8 {
        self.data[10]
    }

    /// Writes the given VByteEncoded number to a target.
    /// Returns the number of bytes written (equal to `bytes_used`) or an `io::Error`
    pub fn write_to<W: Write>(&self, target: &mut W) -> Result<u8, Error> {
        target.write_all(&self.data[(10 - self.bytes_used()) as usize..10]).map(|()| self.bytes_used())
    }
}

/// Iterator that decodes a bytestream to unsigned integers
pub struct VByteDecoder<R> {
    source: R,
    buf: [u8; 10],
    filled: u8,
}

impl<R: Read> VByteDecoder<R> {
    /// Create a new VByteDecoder by passing a bytestream
    pub fn new(source: R) -> Self {
        VByteDecoder {
            source: source,
            buf: [0; 10],
            filled: 0,
        }
    }

    /// Sometimes it is convenient to look at the original bytestream itself
    /// (e.g. when not only vbyte encoded integers are in the bytestream)
    /// This method provides access to the underlying bytestream in form of
    /// a mutable borrow
    pub fn underlying_mut(&mut self) -> &mut R {
        &mut self.source
    }

    /// Sometimes it is convenient to look at the original bytestream itself
    /// (e.g. when not only vbyte encoded integers are in the bytestream)
    /// This method provides access to the underlying bytestream in form of
    /// a borrow
    pub fn underlying(&self) -> &R {
        &self.source
    }
}

impl<R: Read> Read for VByteDecoder<R> {
    fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
        let mut bytes_read = 0;
        if self.filled > 0 {
            // We have some bytes stored. Give them back
            // Read some bytes from self.buf.
            bytes_read += try!((&self.buf[..self.filled as usize]).read(buf));
            // These lines "shift" self.buf to the left. Eliminating the read bytes
            let mut tmp: [u8; 10] = [0; 10];
            self.filled -= bytes_read as u8;
            tmp[..10 - bytes_read].copy_from_slice(&self.buf[bytes_read..]);
            self.buf = tmp;
            // If buf is full. Return
            if bytes_read >= buf.len() {
                return Ok(bytes_read);
            }
        }
        bytes_read += try!(self.source.read(&mut buf[bytes_read..]));
        Ok(bytes_read)
    }
}

impl<R: Seek + Read> Seek for VByteDecoder<R> {
    fn seek(&mut self, pos: SeekFrom) -> io::Result<u64> {
        self.buf = [0; 10];
        match pos {
            SeekFrom::Start(_) => {
                self.filled = 0;
                self.source.seek(pos)
            },
            SeekFrom::Current(offset) => {
                let f = self.filled as i64;
                self.filled = 0;
                self.source.seek(SeekFrom::Current(offset - f))
            },
            SeekFrom::End(_) => {
                self.filled = 0;
                self.source.seek(pos)
            }
        }
    }
}

impl<R: Read> Iterator for VByteDecoder<R> {
    type Item = usize;

    /// Returns the next unsigned integer which is encoded in the underlying
    /// bytestream
    /// May iterate the underlying bytestream an arbitrary number of times
    /// Returns None when the underlying bytream returns None or delivers corrupt data
    fn next(&mut self) -> Option<Self::Item> {
        let mut result: usize = 0;
        // Read bytes into buffer
        let read = self.source.read(&mut self.buf[self.filled as usize..]).unwrap();
        let mut ptr = 0;
        // Find the last byte of this number (The first that has the 128bit set)
        while ptr < self.buf.len() && self.buf[ptr] < 128 {
            ptr += 1;
        }
        // If we are not filled and we didnt read anything (Source is empty)
        // Or if we have corrupted data (No 128bit flag set)
        // Return none
        if (self.filled == 0 && read == 0) || ptr == 10 {
            return None;
        }
        //Specialcase where 10 bytes are read
        //In this case the first byte can be maximally 1
        //Else its corrupt data
        if self.buf[0] > 1 && ptr == 9 {
            return None;
        }
        let mut tmp: [u8; 10] = [0; 10];
        {
            // Split buffer so that the lhs is the number we want to decode
            let (a, buf) = self.buf.split_at(ptr + 1);
            // Copy the rest into a temporary
            tmp[..buf.len()].copy_from_slice(buf);
            self.filled = buf.len() as u8;
            // Now decode
            for byte in a {
                result *= 128;
                result += (*byte & 127) as usize;
            }
        }
        // Set self.buff and subtract the 128 from the 128 bit flag
        self.buf = tmp;
        Some(result)
    }
}

#[cfg(test)]
mod tests {

    use super::*;
    use std;
    use std::io::{Cursor, Seek, SeekFrom};

    #[test]
    fn test_heapless_vbyte_encode() {
        assert_eq!(VByteEncoded::new(0).data[9], 0x80);
        assert_eq!(VByteEncoded::new(0).bytes_used(), 1);
        assert_eq!(VByteEncoded::new(128).data[8..10], [0x01, 0x80]);
        assert_eq!(VByteEncoded::new(128).bytes_used(), 0x02);

        assert_eq!(VByteEncoded::new(0xFFFF).data[7..10], [0x03, 0x7F, 0xFF]);
        assert_eq!(VByteEncoded::new(0xFFFF).bytes_used(), 3);
        assert_eq!(VByteEncoded::new(std::u64::MAX as usize).data,
                   [1, 127, 127, 127, 127, 127, 127, 127, 127, 255, 10]);
    }

    #[test]
    fn test_vbyte_encode() {
        assert_eq!(vbyte_encode(0), vec![0x80]);
        assert_eq!(vbyte_encode(5), vec![0x85]);
        assert_eq!(vbyte_encode(127), vec![0xFF]);
        assert_eq!(vbyte_encode(128), vec![0x01, 0x80]);
        assert_eq!(vbyte_encode(130), vec![0x01, 0x82]);
        assert_eq!(vbyte_encode(255), vec![0x01, 0xFF]);
        assert_eq!(vbyte_encode(20_000), vec![0x01, 0x1C, 0xA0]);
        assert_eq!(vbyte_encode(0xFFFF), vec![0x03, 0x7F, 0xFF]);
    }

    #[test]
    fn test_vbyte_decode() {
        assert_eq!(VByteDecoder::new(vec![0x80].as_slice()).collect::<Vec<_>>(),
                   vec![0]);
        assert_eq!(VByteDecoder::new(vec![0x85].as_slice()).collect::<Vec<_>>(),
                   vec![5]);
        assert_eq!(VByteDecoder::new(vec![0xFF].as_slice()).collect::<Vec<_>>(),
                   vec![127]);
        assert_eq!(VByteDecoder::new(vec![0x80, 0x81].as_slice()).collect::<Vec<_>>(),
                   vec![0, 1]);
        assert_eq!(VByteDecoder::new(vec![0x03, 0x7F, 0xFF, 0x01, 0x82, 0x85].as_slice()).collect::<Vec<_>>(),
                   vec![0xFFFF, 130, 5]);
        assert_eq!(VByteDecoder::new(vec![0x80].as_slice()).collect::<Vec<_>>(),
                   vec![0]);
    }

    #[test]
    fn overflowing() {
        assert_eq!(VByteDecoder::new(vec![0x81; 255].as_slice()).collect::<Vec<_>>(),
                   vec![1; 255]);
    }

    #[test]
    fn more_data() {
        let data = vec![0x80, 0x01, 0x82, 0x85, 0x03, 0x7F, 0xFF, 0x80, 0x86, 0x82, 0x85, 0x84, 0x01, 0x83];
        let decoder = VByteDecoder::new(data.as_slice());
        assert_eq!(decoder.collect::<Vec<_>>(), vec![0, 130, 5, 65535, 0, 6, 2, 5, 4, 131]);
    }

    #[test]
    fn seek_basic() {
        let data = vec![0x80];
        let mut decoder = VByteDecoder::new(Cursor::new(&data));
        assert_eq!(decoder.next().unwrap(), 0);
        assert_eq!(decoder.next(), None);
        decoder.seek(SeekFrom::Start(0)).unwrap();
        assert_eq!(decoder.next().unwrap(), 0);
    }

    #[test]
    fn seek_extended() {
        let data = vec![0x80, 0x01, 0x82, 0x85, 0x03, 0x7F, 0xFF, 0x80, 0x86, 0x82, 0x85, 0x84, 0x01, 0x83];
        let mut decoder = VByteDecoder::new(Cursor::new(&data));
        assert_eq!(decoder.next().unwrap(), 0);
        assert_eq!(decoder.seek(SeekFrom::Start(0)).unwrap(), 0);
        assert_eq!(decoder.next().unwrap(), 0);
        assert_eq!(decoder.seek(SeekFrom::Current(2)).unwrap(), 3);
        assert_eq!(decoder.next().unwrap(), 5);
        assert_eq!(decoder.seek(SeekFrom::End(-2)).unwrap(), 12);
        assert_eq!(decoder.next().unwrap(), 131);
        assert_eq!(decoder.next(), None);
    }

    #[test]
    fn seek_edge_case() {
        let data = vec![0x80, 0x01, 0x82, 0x85, 0x03, 0x7F, 0xFF, 0x80, 0x86, 0x82, 0x85, 0x84, 0x01, 0x83];
        let mut decoder = VByteDecoder::new(Cursor::new(&data));
        assert_eq!(decoder.next(), Some(0));
        decoder.seek(SeekFrom::Start(50)).unwrap();
        assert_eq!(decoder.next(), None);
    }

    #[test]
    fn edge_cases() {
        // 0
        assert_eq!(VByteDecoder::new(vbyte_encode(0).as_slice()).collect::<Vec<_>>(),
                   vec![0]);

        // MAX
        assert_eq!(VByteDecoder::new(vbyte_encode(usize::max_value()).as_slice()).collect::<Vec<_>>(),
                   vec![usize::max_value()]);

        // too many bytes = corrupted data
        assert_eq!(VByteDecoder::new(vec![127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 255].as_slice()).collect::<Vec<_>>(), vec![]);
        // MAX + n = corrupted data
        assert_eq!(VByteDecoder::new(vec![2, 127, 127, 127, 127, 127, 127, 127, 127, 255].as_slice()).collect::<Vec<_>>(), vec![]);
        // zero-bytes
        assert_eq!(VByteDecoder::new(vec![0; 100].as_slice()).collect::<Vec<_>>(), vec![]);
    }

}
<commit_msg>clean up storage::compression<commit_after>//! This module currently provides utility methods and structs for variable
//! byte codes as described in
//! http://nlp.stanford.edu/IR-book/html/htmledition/variable-byte-codes-1.html.
//!
//! Encode unsigned integers by using the `vbyte_encode` method.
//!
//! Decode a bytestream by instatiating a `VByteDecoder` and using its iterator
//! implementation.
//!
//! #Example
//!
//! ```rust,ignore
//!
//! use perlin::utils::compression::{vbyte_encode, VByteDecoder};
//!
//! let bytes = vbyte_encode(3);
//! let three = VByteDecoder::new(bytes.into_iter()).next().unwrap();
//! assert_eq!(3, three);
//! ```

use std::io;
use std::io::{Seek, SeekFrom, Read, Write, Error};

/// Stores the result of a vbyte encode operation without indirection that a `Vec<u8>` would introduce.
/// Can thus be used to `vbyte_encode` on the stack
pub struct VByteEncoded {
    // Memory layout of the result: [ payload | payload | payload | ... | used_bytes ]
    data: [u8; 11],
}

impl VByteEncoded {
    /// Performs a vbyte encode without allocating memory on the heap
    /// Can then be written to a `Write`-implementor
    pub fn new(mut number: usize) -> Self {
        let mut count = 0;
        let mut result = [0u8; 11];
        loop {
            result[9 - count] = (number % 128) as u8;
            count += 1;
            if number < 128 {
                break;
            } else {
                number /= 128;
            }
        }
        result[9] += 128;
        result[10] = count as u8;
        VByteEncoded { data: result }
    }

    /// Return how many bytes are used to encode the number. Min: 1 Max: 10
    pub fn bytes_used(&self) -> u8 {
        self.data[10]
    }

    /// Access to the written data as slice
    /// Currently only used in tests
    pub fn data_buf(&self) -> &[u8] {
        &self.data[(10 - self.bytes_used()) as usize..10]
    }

    /// Writes the given VByteEncoded number to a target.
    /// Returns the number of bytes written (equal to `bytes_used`) or an `io::Error`
    pub fn write_to<W: Write>(&self, target: &mut W) -> Result<u8, Error> {
        target.write_all(&self.data[(10 - self.bytes_used()) as usize..10]).map(|()| self.bytes_used())
    }
}

/// Iterator that decodes a bytestream to unsigned integers
pub struct VByteDecoder<R> {
    source: R,
    buf: [u8; 10],
    filled: u8,
}

impl<R: Read> VByteDecoder<R> {
    /// Create a new VByteDecoder by passing a bytestream
    pub fn new(source: R) -> Self {
        VByteDecoder {
            source: source,
            buf: [0; 10],
            filled: 0,
        }
    }

    /// Sometimes it is convenient to look at the original bytestream itself
    /// (e.g. when not only vbyte encoded integers are in the bytestream)
    /// This method provides access to the underlying bytestream in form of
    /// a mutable borrow
    pub fn underlying_mut(&mut self) -> &mut R {
        &mut self.source
    }

    /// Sometimes it is convenient to look at the original bytestream itself
    /// (e.g. when not only vbyte encoded integers are in the bytestream)
    /// This method provides access to the underlying bytestream in form of
    /// a borrow
    pub fn underlying(&self) -> &R {
        &self.source
    }
}

impl<R: Read> Read for VByteDecoder<R> {
    fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
        let mut bytes_read = 0;
        if self.filled > 0 {
            // We have some bytes stored. Give them back
            // Read some bytes from self.buf.
            bytes_read += try!((&self.buf[..self.filled as usize]).read(buf));
            // These lines "shift" self.buf to the left. Eliminating the read bytes
            let mut tmp: [u8; 10] = [0; 10];
            self.filled -= bytes_read as u8;
            tmp[..10 - bytes_read].copy_from_slice(&self.buf[bytes_read..]);
            self.buf = tmp;
            // If buf is full. Return
            if bytes_read >= buf.len() {
                return Ok(bytes_read);
            }
        }
        bytes_read += try!(self.source.read(&mut buf[bytes_read..]));
        Ok(bytes_read)
    }
}

impl<R: Seek + Read> Seek for VByteDecoder<R> {
    fn seek(&mut self, pos: SeekFrom) -> io::Result<u64> {
        self.buf = [0; 10];
        match pos {
            SeekFrom::Start(_) => {
                self.filled = 0;
                self.source.seek(pos)
            }
            SeekFrom::Current(offset) => {
                let f = self.filled as i64;
                self.filled = 0;
                self.source.seek(SeekFrom::Current(offset - f))
            }
            SeekFrom::End(_) => {
                self.filled = 0;
                self.source.seek(pos)
            }
        }
    }
}

impl<R: Read> Iterator for VByteDecoder<R> {
    type Item = usize;

    /// Returns the next unsigned integer which is encoded in the underlying
    /// bytestream
    /// May iterate the underlying bytestream an arbitrary number of times
    /// Returns None when the underlying bytream returns None or delivers corrupt data
    fn next(&mut self) -> Option<Self::Item> {
        let mut result: usize = 0;
        // Read bytes into buffer
        let read = self.source.read(&mut self.buf[self.filled as usize..]).unwrap();
        let mut ptr = 0;
        // Find the last byte of this number (The first that has the 128bit set)
        while ptr < self.buf.len() && self.buf[ptr] < 128 {
            ptr += 1;
        }
        // If we are not filled and we didnt read anything (Source is empty)
        // Or if we have corrupted data (No 128bit flag set)
        // Return none
        if (self.filled == 0 && read == 0) || ptr == 10 {
            return None;
        }
        // Specialcase where 10 bytes are read
        // In this case the first byte can be maximally 1
        // Else its corrupt data
        if self.buf[0] > 1 && ptr == 9 {
            return None;
        }
        let mut tmp: [u8; 10] = [0; 10];
        {
            // Split buffer so that the lhs is the number we want to decode
            let (a, buf) = self.buf.split_at(ptr + 1);
            // Copy the rest into a temporary
            tmp[..buf.len()].copy_from_slice(buf);
            self.filled = buf.len() as u8;
            // Now decode
            for byte in a {
                result *= 128;
                result += (*byte & 127) as usize;
            }
        }
        // Set self.buff and subtract the 128 from the 128 bit flag
        self.buf = tmp;
        Some(result)
    }
}

#[cfg(test)]
mod tests {

    use super::*;
    use std;
    use std::io::{Cursor, Seek, SeekFrom};

    #[test]
    fn test_heapless_vbyte_encode() {
        assert_eq!(VByteEncoded::new(0).data[9], 0x80);
        assert_eq!(VByteEncoded::new(0).bytes_used(), 1);
        assert_eq!(VByteEncoded::new(128).data[8..10], [0x01, 0x80]);
        assert_eq!(VByteEncoded::new(128).bytes_used(), 0x02);

        assert_eq!(VByteEncoded::new(0xFFFF).data[7..10], [0x03, 0x7F, 0xFF]);
        assert_eq!(VByteEncoded::new(0xFFFF).bytes_used(), 3);
        assert_eq!(VByteEncoded::new(std::u64::MAX as usize).data,
                   [1, 127, 127, 127, 127, 127, 127, 127, 127, 255, 10]);
    }

    #[test]
    fn test_vbyte_decode() {
        assert_eq!(VByteDecoder::new(vec![0x80].as_slice()).collect::<Vec<_>>(),
                   vec![0]);
        assert_eq!(VByteDecoder::new(vec![0x85].as_slice()).collect::<Vec<_>>(),
                   vec![5]);
        assert_eq!(VByteDecoder::new(vec![0xFF].as_slice()).collect::<Vec<_>>(),
                   vec![127]);
        assert_eq!(VByteDecoder::new(vec![0x80, 0x81].as_slice()).collect::<Vec<_>>(),
                   vec![0, 1]);
        assert_eq!(VByteDecoder::new(vec![0x03, 0x7F, 0xFF, 0x01, 0x82, 0x85].as_slice()).collect::<Vec<_>>(),
                   vec![0xFFFF, 130, 5]);
        assert_eq!(VByteDecoder::new(vec![0x80].as_slice()).collect::<Vec<_>>(),
                   vec![0]);
    }

    #[test]
    fn overflowing() {
        assert_eq!(VByteDecoder::new(vec![0x81; 255].as_slice()).collect::<Vec<_>>(),
                   vec![1; 255]);
    }

    #[test]
    fn more_data() {
        let data = vec![0x80, 0x01, 0x82, 0x85, 0x03, 0x7F, 0xFF, 0x80, 0x86, 0x82, 0x85, 0x84, 0x01, 0x83];
        let decoder = VByteDecoder::new(data.as_slice());
        assert_eq!(decoder.collect::<Vec<_>>(),
                   vec![0, 130, 5, 65535, 0, 6, 2, 5, 4, 131]);
    }

    #[test]
    fn seek_basic() {
        let data = vec![0x80];
        let mut decoder = VByteDecoder::new(Cursor::new(&data));
        assert_eq!(decoder.next().unwrap(), 0);
        assert_eq!(decoder.next(), None);
        decoder.seek(SeekFrom::Start(0)).unwrap();
        assert_eq!(decoder.next().unwrap(), 0);
    }

    #[test]
    fn seek_extended() {
        let data = vec![0x80, 0x01, 0x82, 0x85, 0x03, 0x7F, 0xFF, 0x80, 0x86, 0x82, 0x85, 0x84, 0x01, 0x83];
        let mut decoder = VByteDecoder::new(Cursor::new(&data));
        assert_eq!(decoder.next().unwrap(), 0);
        assert_eq!(decoder.seek(SeekFrom::Start(0)).unwrap(), 0);
        assert_eq!(decoder.next().unwrap(), 0);
        assert_eq!(decoder.seek(SeekFrom::Current(2)).unwrap(), 3);
        assert_eq!(decoder.next().unwrap(), 5);
        assert_eq!(decoder.seek(SeekFrom::End(-2)).unwrap(), 12);
        assert_eq!(decoder.next().unwrap(), 131);
        assert_eq!(decoder.next(), None);
    }

    #[test]
    fn seek_edge_case() {
        let data = vec![0x80, 0x01, 0x82, 0x85, 0x03, 0x7F, 0xFF, 0x80, 0x86, 0x82, 0x85, 0x84, 0x01, 0x83];
        let mut decoder = VByteDecoder::new(Cursor::new(&data));
        assert_eq!(decoder.next(), Some(0));
        decoder.seek(SeekFrom::Start(50)).unwrap();
        assert_eq!(decoder.next(), None);
    }

    #[test]
    fn edge_cases() {
        // 0
        assert_eq!(VByteDecoder::new(VByteEncoded::new(0).data_buf()).collect::<Vec<_>>(),
                   vec![0]);

        // MAX
        assert_eq!(VByteDecoder::new(VByteEncoded::new(usize::max_value()).data_buf()).collect::<Vec<_>>(),
                   vec![usize::max_value()]);

        // too many bytes = corrupted data
        assert_eq!(VByteDecoder::new(vec![127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 255].as_slice())
                       .collect::<Vec<_>>(),
                   vec![]);
        // MAX + n = corrupted data
        assert_eq!(VByteDecoder::new(vec![2, 127, 127, 127, 127, 127, 127, 127, 127, 255].as_slice())
                       .collect::<Vec<_>>(),
                   vec![]);
        // zero-bytes
        assert_eq!(VByteDecoder::new(vec![0; 100].as_slice()).collect::<Vec<_>>(),
                   vec![]);
    }

}
<|endoftext|>


<commit_before>/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

//! Common handling for the specified value CSS url() values.

use cssparser::Parser;
use gecko_bindings::bindings;
use gecko_bindings::structs::{ServoBundledURI, URLExtraData};
use gecko_bindings::structs::mozilla::css::URLValueData;
use gecko_bindings::structs::root::{RustString, nsStyleImageRequest};
use gecko_bindings::structs::root::mozilla::css::{ImageValue, URLValue};
use gecko_bindings::sugar::refptr::RefPtr;
use malloc_size_of::{MallocSizeOf, MallocSizeOfOps};
use parser::{Parse, ParserContext};
use servo_arc::{Arc, RawOffsetArc};
use std::mem;
use style_traits::ParseError;

/// A CSS url() value for gecko.
#[css(function = "url")]
#[derive(Clone, Debug, PartialEq, ToCss)]
pub struct CssUrl {
    /// The URL in unresolved string form.
    ///
    /// Refcounted since cloning this should be cheap and data: uris can be
    /// really large.
    serialization: Arc<String>,

    /// The URL extra data.
    #[css(skip)]
    pub extra_data: RefPtr<URLExtraData>,
}

impl CssUrl {
    /// Try to parse a URL from a string value that is a valid CSS token for a
    /// URL.
    ///
    /// Returns `Err` in the case that extra_data is incomplete.
    pub fn parse_from_string<'a>(
        url: String,
        context: &ParserContext,
    ) -> Result<Self, ParseError<'a>> {
        Ok(CssUrl {
            serialization: Arc::new(url),
            extra_data: context.url_data.clone(),
        })
    }

    /// Returns true if the URL is definitely invalid. We don't eagerly resolve
    /// URLs in gecko, so we just return false here.
    /// use its |resolved| status.
    pub fn is_invalid(&self) -> bool {
        false
    }

    /// Convert from URLValueData to SpecifiedUrl.
    unsafe fn from_url_value_data(url: &URLValueData) -> Result<Self, ()> {
        Ok(CssUrl {
            serialization: if url.mUsingRustString {
                let arc_type =
                    url.mStrings.mRustString.as_ref() as *const _ as *const RawOffsetArc<String>;
                Arc::from_raw_offset((*arc_type).clone())
            } else {
                Arc::new(url.mStrings.mString.as_ref().to_string())
            },
            extra_data: url.mExtraData.to_safe(),
        })
    }

    /// Returns true if this URL looks like a fragment.
    /// See https://drafts.csswg.org/css-values/#local-urls
    pub fn is_fragment(&self) -> bool {
        self.as_str().chars().next().map_or(false, |c| c == '#')
    }

    /// Return the resolved url as string, or the empty string if it's invalid.
    ///
    /// FIXME(bholley): This returns the unresolved URL while the servo version
    /// returns the resolved URL.
    pub fn as_str(&self) -> &str {
        &*self.serialization
    }

    /// Little helper for Gecko's ffi.
    pub fn as_slice_components(&self) -> (*const u8, usize) {
        (
            self.serialization.as_str().as_ptr(),
            self.serialization.as_str().len(),
        )
    }

    /// Create a bundled URI suitable for sending to Gecko
    /// to be constructed into a css::URLValue
    pub fn for_ffi(&self) -> ServoBundledURI {
        let arc_offset = Arc::into_raw_offset(self.serialization.clone());
        ServoBundledURI {
            mURLString: unsafe { mem::transmute::<_, RawOffsetArc<RustString>>(arc_offset) },
            mExtraData: self.extra_data.get(),
        }
    }
}

impl Parse for CssUrl {
    fn parse<'i, 't>(
        context: &ParserContext,
        input: &mut Parser<'i, 't>,
    ) -> Result<Self, ParseError<'i>> {
        let url = input.expect_url()?;
        Self::parse_from_string(url.as_ref().to_owned(), context)
    }
}

impl Eq for CssUrl {}

impl MallocSizeOf for CssUrl {
    fn size_of(&self, _ops: &mut MallocSizeOfOps) -> usize {
        // XXX: measure `serialization` once bug 1397971 lands

        // We ignore `extra_data`, because RefPtr is tricky, and there aren't
        // many of them in practise (sharing is common).

        0
    }
}

/// A specified url() value for general usage.
#[derive(Clone, Debug, ToComputedValue, ToCss)]
pub struct SpecifiedUrl {
    /// The specified url value.
    pub url: CssUrl,
    /// Gecko's URLValue so that we can reuse it while rematching a
    /// property with this specified value.
    #[css(skip)]
    pub url_value: RefPtr<URLValue>,
}

impl SpecifiedUrl {
    fn from_css_url(url: CssUrl) -> Self {
        let url_value = unsafe {
            let ptr = bindings::Gecko_NewURLValue(url.for_ffi());
            // We do not expect Gecko_NewURLValue returns null.
            debug_assert!(!ptr.is_null());
            RefPtr::from_addrefed(ptr)
        };
        SpecifiedUrl { url, url_value }
    }

    /// Convert from URLValueData to SpecifiedUrl.
    pub unsafe fn from_url_value_data(url: &URLValueData) -> Result<Self, ()> {
        CssUrl::from_url_value_data(url).map(Self::from_css_url)
    }
}

impl PartialEq for SpecifiedUrl {
    fn eq(&self, other: &Self) -> bool {
        self.url.eq(&other.url)
    }
}

impl Eq for SpecifiedUrl {}

impl Parse for SpecifiedUrl {
    fn parse<'i, 't>(
        context: &ParserContext,
        input: &mut Parser<'i, 't>,
    ) -> Result<Self, ParseError<'i>> {
        CssUrl::parse(context, input).map(Self::from_css_url)
    }
}

impl MallocSizeOf for SpecifiedUrl {
    fn size_of(&self, ops: &mut MallocSizeOfOps) -> usize {
        let mut n = self.url.size_of(ops);
        // Although this is a RefPtr, this is the primary reference because
        // SpecifiedUrl is responsible for creating the url_value. So we
        // measure unconditionally here.
        n += unsafe { bindings::Gecko_URLValue_SizeOfIncludingThis(self.url_value.get()) };
        n
    }
}

/// A specified url() value for image.
///
/// This exists so that we can construct `ImageValue` and reuse it.
#[derive(Clone, Debug, ToComputedValue, ToCss)]
pub struct SpecifiedImageUrl {
    /// The specified url value.
    pub url: CssUrl,
    /// Gecko's ImageValue so that we can reuse it while rematching a
    /// property with this specified value.
    #[css(skip)]
    pub image_value: RefPtr<ImageValue>,
}

impl SpecifiedImageUrl {
    fn from_css_url(url: CssUrl) -> Self {
        let image_value = unsafe {
            let ptr = bindings::Gecko_ImageValue_Create(url.for_ffi());
            // We do not expect Gecko_ImageValue_Create returns null.
            debug_assert!(!ptr.is_null());
            RefPtr::from_addrefed(ptr)
        };
        SpecifiedImageUrl { url, image_value }
    }

    /// Parse a URL from a string value. See SpecifiedUrl::parse_from_string.
    pub fn parse_from_string<'a>(
        url: String,
        context: &ParserContext,
    ) -> Result<Self, ParseError<'a>> {
        CssUrl::parse_from_string(url, context).map(Self::from_css_url)
    }

    /// Convert from URLValueData to SpecifiedUrl.
    pub unsafe fn from_url_value_data(url: &URLValueData) -> Result<Self, ()> {
        CssUrl::from_url_value_data(url).map(Self::from_css_url)
    }

    /// Convert from nsStyleImageRequest to SpecifiedUrl.
    pub unsafe fn from_image_request(image_request: &nsStyleImageRequest) -> Result<Self, ()> {
        if image_request.mImageValue.mRawPtr.is_null() {
            return Err(());
        }

        let image_value = image_request.mImageValue.mRawPtr.as_ref().unwrap();
        let url_value_data = &image_value._base;
        Self::from_url_value_data(url_value_data)
    }
}

impl Parse for SpecifiedImageUrl {
    fn parse<'i, 't>(
        context: &ParserContext,
        input: &mut Parser<'i, 't>,
    ) -> Result<Self, ParseError<'i>> {
        CssUrl::parse(context, input).map(Self::from_css_url)
    }
}

impl PartialEq for SpecifiedImageUrl {
    fn eq(&self, other: &Self) -> bool {
        self.url.eq(&other.url)
    }
}

impl Eq for SpecifiedImageUrl {}

impl MallocSizeOf for SpecifiedImageUrl {
    fn size_of(&self, ops: &mut MallocSizeOfOps) -> usize {
        let mut n = self.url.size_of(ops);
        // Although this is a RefPtr, this is the primary reference because
        // SpecifiedUrl is responsible for creating the image_value. So we
        // measure unconditionally here.
        n += unsafe { bindings::Gecko_ImageValue_SizeOfIncludingThis(self.image_value.get()) };
        n
    }
}

/// The computed value of a CSS `url()`.
pub type ComputedUrl = SpecifiedUrl;
/// The computed value of a CSS `url()` for image.
pub type ComputedImageUrl = SpecifiedImageUrl;
<commit_msg>style: Simplify ImageValue.<commit_after>/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

//! Common handling for the specified value CSS url() values.

use cssparser::Parser;
use gecko_bindings::bindings;
use gecko_bindings::structs::{ServoBundledURI, URLExtraData};
use gecko_bindings::structs::mozilla::css::URLValueData;
use gecko_bindings::structs::root::{RustString, nsStyleImageRequest};
use gecko_bindings::structs::root::mozilla::css::{ImageValue, URLValue};
use gecko_bindings::sugar::refptr::RefPtr;
use malloc_size_of::{MallocSizeOf, MallocSizeOfOps};
use parser::{Parse, ParserContext};
use servo_arc::{Arc, RawOffsetArc};
use std::mem;
use style_traits::ParseError;

/// A CSS url() value for gecko.
#[css(function = "url")]
#[derive(Clone, Debug, PartialEq, ToCss)]
pub struct CssUrl {
    /// The URL in unresolved string form.
    ///
    /// Refcounted since cloning this should be cheap and data: uris can be
    /// really large.
    serialization: Arc<String>,

    /// The URL extra data.
    #[css(skip)]
    pub extra_data: RefPtr<URLExtraData>,
}

impl CssUrl {
    /// Try to parse a URL from a string value that is a valid CSS token for a
    /// URL.
    ///
    /// Returns `Err` in the case that extra_data is incomplete.
    pub fn parse_from_string<'a>(
        url: String,
        context: &ParserContext,
    ) -> Result<Self, ParseError<'a>> {
        Ok(CssUrl {
            serialization: Arc::new(url),
            extra_data: context.url_data.clone(),
        })
    }

    /// Returns true if the URL is definitely invalid. We don't eagerly resolve
    /// URLs in gecko, so we just return false here.
    /// use its |resolved| status.
    pub fn is_invalid(&self) -> bool {
        false
    }

    /// Convert from URLValueData to SpecifiedUrl.
    unsafe fn from_url_value_data(url: &URLValueData) -> Result<Self, ()> {
        let arc_type =
            &url.mString as *const _ as *const RawOffsetArc<String>;
        Ok(CssUrl {
            serialization: Arc::from_raw_offset((*arc_type).clone()),
            extra_data: url.mExtraData.to_safe(),
        })
    }

    /// Returns true if this URL looks like a fragment.
    /// See https://drafts.csswg.org/css-values/#local-urls
    pub fn is_fragment(&self) -> bool {
        self.as_str().chars().next().map_or(false, |c| c == '#')
    }

    /// Return the resolved url as string, or the empty string if it's invalid.
    ///
    /// FIXME(bholley): This returns the unresolved URL while the servo version
    /// returns the resolved URL.
    pub fn as_str(&self) -> &str {
        &*self.serialization
    }

    /// Little helper for Gecko's ffi.
    pub fn as_slice_components(&self) -> (*const u8, usize) {
        (
            self.serialization.as_str().as_ptr(),
            self.serialization.as_str().len(),
        )
    }

    /// Create a bundled URI suitable for sending to Gecko
    /// to be constructed into a css::URLValue
    pub fn for_ffi(&self) -> ServoBundledURI {
        let arc_offset = Arc::into_raw_offset(self.serialization.clone());
        ServoBundledURI {
            mURLString: unsafe { mem::transmute::<_, RawOffsetArc<RustString>>(arc_offset) },
            mExtraData: self.extra_data.get(),
        }
    }
}

impl Parse for CssUrl {
    fn parse<'i, 't>(
        context: &ParserContext,
        input: &mut Parser<'i, 't>,
    ) -> Result<Self, ParseError<'i>> {
        let url = input.expect_url()?;
        Self::parse_from_string(url.as_ref().to_owned(), context)
    }
}

impl Eq for CssUrl {}

impl MallocSizeOf for CssUrl {
    fn size_of(&self, _ops: &mut MallocSizeOfOps) -> usize {
        // XXX: measure `serialization` once bug 1397971 lands

        // We ignore `extra_data`, because RefPtr is tricky, and there aren't
        // many of them in practise (sharing is common).

        0
    }
}

/// A specified url() value for general usage.
#[derive(Clone, Debug, ToComputedValue, ToCss)]
pub struct SpecifiedUrl {
    /// The specified url value.
    pub url: CssUrl,
    /// Gecko's URLValue so that we can reuse it while rematching a
    /// property with this specified value.
    #[css(skip)]
    pub url_value: RefPtr<URLValue>,
}

impl SpecifiedUrl {
    fn from_css_url(url: CssUrl) -> Self {
        let url_value = unsafe {
            let ptr = bindings::Gecko_NewURLValue(url.for_ffi());
            // We do not expect Gecko_NewURLValue returns null.
            debug_assert!(!ptr.is_null());
            RefPtr::from_addrefed(ptr)
        };
        SpecifiedUrl { url, url_value }
    }

    /// Convert from URLValueData to SpecifiedUrl.
    pub unsafe fn from_url_value_data(url: &URLValueData) -> Result<Self, ()> {
        CssUrl::from_url_value_data(url).map(Self::from_css_url)
    }
}

impl PartialEq for SpecifiedUrl {
    fn eq(&self, other: &Self) -> bool {
        self.url.eq(&other.url)
    }
}

impl Eq for SpecifiedUrl {}

impl Parse for SpecifiedUrl {
    fn parse<'i, 't>(
        context: &ParserContext,
        input: &mut Parser<'i, 't>,
    ) -> Result<Self, ParseError<'i>> {
        CssUrl::parse(context, input).map(Self::from_css_url)
    }
}

impl MallocSizeOf for SpecifiedUrl {
    fn size_of(&self, ops: &mut MallocSizeOfOps) -> usize {
        let mut n = self.url.size_of(ops);
        // Although this is a RefPtr, this is the primary reference because
        // SpecifiedUrl is responsible for creating the url_value. So we
        // measure unconditionally here.
        n += unsafe { bindings::Gecko_URLValue_SizeOfIncludingThis(self.url_value.get()) };
        n
    }
}

/// A specified url() value for image.
///
/// This exists so that we can construct `ImageValue` and reuse it.
#[derive(Clone, Debug, ToComputedValue, ToCss)]
pub struct SpecifiedImageUrl {
    /// The specified url value.
    pub url: CssUrl,
    /// Gecko's ImageValue so that we can reuse it while rematching a
    /// property with this specified value.
    #[css(skip)]
    pub image_value: RefPtr<ImageValue>,
}

impl SpecifiedImageUrl {
    fn from_css_url(url: CssUrl) -> Self {
        let image_value = unsafe {
            let ptr = bindings::Gecko_ImageValue_Create(url.for_ffi());
            // We do not expect Gecko_ImageValue_Create returns null.
            debug_assert!(!ptr.is_null());
            RefPtr::from_addrefed(ptr)
        };
        SpecifiedImageUrl { url, image_value }
    }

    /// Parse a URL from a string value. See SpecifiedUrl::parse_from_string.
    pub fn parse_from_string<'a>(
        url: String,
        context: &ParserContext,
    ) -> Result<Self, ParseError<'a>> {
        CssUrl::parse_from_string(url, context).map(Self::from_css_url)
    }

    /// Convert from URLValueData to SpecifiedUrl.
    pub unsafe fn from_url_value_data(url: &URLValueData) -> Result<Self, ()> {
        CssUrl::from_url_value_data(url).map(Self::from_css_url)
    }

    /// Convert from nsStyleImageRequest to SpecifiedUrl.
    pub unsafe fn from_image_request(image_request: &nsStyleImageRequest) -> Result<Self, ()> {
        if image_request.mImageValue.mRawPtr.is_null() {
            return Err(());
        }

        let image_value = image_request.mImageValue.mRawPtr.as_ref().unwrap();
        let url_value_data = &image_value._base;
        Self::from_url_value_data(url_value_data)
    }
}

impl Parse for SpecifiedImageUrl {
    fn parse<'i, 't>(
        context: &ParserContext,
        input: &mut Parser<'i, 't>,
    ) -> Result<Self, ParseError<'i>> {
        CssUrl::parse(context, input).map(Self::from_css_url)
    }
}

impl PartialEq for SpecifiedImageUrl {
    fn eq(&self, other: &Self) -> bool {
        self.url.eq(&other.url)
    }
}

impl Eq for SpecifiedImageUrl {}

impl MallocSizeOf for SpecifiedImageUrl {
    fn size_of(&self, ops: &mut MallocSizeOfOps) -> usize {
        let mut n = self.url.size_of(ops);
        // Although this is a RefPtr, this is the primary reference because
        // SpecifiedUrl is responsible for creating the image_value. So we
        // measure unconditionally here.
        n += unsafe { bindings::Gecko_ImageValue_SizeOfIncludingThis(self.image_value.get()) };
        n
    }
}

/// The computed value of a CSS `url()`.
pub type ComputedUrl = SpecifiedUrl;
/// The computed value of a CSS `url()` for image.
pub type ComputedImageUrl = SpecifiedImageUrl;
<|endoftext|>


<commit_before>extern crate getopts;
use getopts::{optflag,getopts,OptGroup,usage};
use std::os;

use std::old_io;
use std::old_io::{IoResult, IoError};
use std::old_io::BufferedReader;
use std::old_io::File;
use std::old_io::stdio;

pub fn print_usage(program: &str, opts: &[OptGroup]) {
    let brief = format!("Usage: {} [options]", program);
    print!("{}", usage(brief.as_slice(), opts));
}

pub fn cat(v: &Vec<String>, options: &getopts::Matches) {
    if options.opt_present("u") {
        let writer = Box::new(stdio::stdout_raw());
        stdio::set_stdout(writer);
    }
    if v.is_empty() {
        cat_stdin(options);
    }
    else {
        // read files
        cat_files(v, options);
    }
}

fn cat_files(v: &Vec<String>, options: &getopts::Matches) {
    let mut linenum = 1u32;
    for filename in v.iter() {
        let path = Path::new(filename);
        match File::open(&path) {
            Ok(fh) => {
                let mut file = BufferedReader::new(fh);
                linenum = cat_file(file, options, linenum);
            },
            Err(f) => {
                println!("{}", f);
            }
        }
    }
}

fn cat_stdin(options: &getopts::Matches) {
    let mut linenum = 1u32;
    let mut printempty: bool = false;
    for line in old_io::stdin().lock().lines() {
        let (a, b) = handle_line(line.unwrap(), &mut printempty, linenum, options);
        printempty = a;
        linenum = b;
    }
}

fn cat_file<'a>(
    mut file: old_io::BufferedReader<std::old_io::fs::File>,
    options: &getopts::Matches,
    mut linenum: u32,
    ) -> u32 {
    let mut printempty: bool = false;
    let mut read_buf = [0, 4096];
    let mut out_buf: Vec<u8> = vec![];
    loop {
        match file.read(&mut read_buf) {
            Ok(n) => {
                for c in read_buf[..n].iter() {
                    out_buf.push(*c);
                    if is_nl(c) {
                        let (a, b) = handle_buf(&out_buf, &mut printempty, linenum, options);
                        printempty = a;
                        linenum = b;
                        out_buf.clear();
                    }
                }
            },
            Err(f) => {
                let mut o = 0u32;
                if out_buf.len() > 0 {
                    handle_buf(&out_buf, &mut printempty, linenum, options);
                }
                break
            }
        }
    }
    linenum
}

fn handle_line<'a>(
    linestr: String,
    printempty: &'a mut bool,
    mut linenum: u32,
    options: &getopts::Matches) -> (bool, u32) {
    if options.opt_present("s") {
        if !is_empty(&linestr) {
            if *printempty == true {
                println!("");
            }
            linenum = print_string(&linestr, linenum, options);
        }
        else {
            *printempty = true;
        }
    }
    else {
        linenum = print_string(&linestr, linenum, options);
    }
    (*printempty, linenum)
}

fn handle_buf<'a>(
    out_buf: &Vec<u8>,
    printempty: &'a mut bool,
    mut linenum: u32,
    options: &getopts::Matches) -> (bool, u32) {
    if options.opt_present("s") {
        if !is_empty_out_buf(out_buf) {
            if *printempty == true {
                if options.opt_present("n") {
                    println!("     {}\t", linenum);
                    linenum = linenum + 1;
                }
                else {
                    println!("");
                }
            }
            linenum = print_buf(&out_buf, linenum, options);
        }
        else {
            *printempty = true;
        }
    }
    else {
        linenum = print_buf(&out_buf, linenum, options);
    }
    (*printempty, linenum)
}

fn print_string<'a>(s: &String, mut linenum: u32, options: &getopts::Matches) -> u32 {
    if options.opt_present("b") {
        if !is_empty(s) {
            print_numbered(s, linenum, options);
            linenum = linenum + 1;
        }
        else {
            print_unnumbered(s, options);
        }
    }
    else if options.opt_present("n") {
        print_numbered(s, linenum, options);
        linenum = linenum + 1;
    }
    else {
        print_unnumbered(s, options);
    }
    linenum
}

fn print_buf<'a>(out_buf: &Vec<u8>, mut linenum: u32, options: &getopts::Matches) -> u32 {
    if options.opt_present("b") {
        if !is_empty_out_buf(out_buf) {
            print_numbered_buf(out_buf, linenum, options);
            linenum = linenum + 1;
        }
        else {
            print_unnumbered_buf(out_buf, options);
        }
    }
    else if options.opt_present("n") {
        print_numbered_buf(out_buf, linenum, options);
        linenum = linenum + 1;
    }
    else {
        print_unnumbered_buf(out_buf, options);
    }
    linenum
}

fn print_numbered<'a>(s: &String, linenum: u32, options: &getopts::Matches) {
    if options.opt_present("v") || options.opt_present("t") {
        print!("     {}\t", linenum);
        for b in s.as_bytes().iter() {
            print_byte(b, options);
        }
    }
    else {
        print!("     {}\t{}", linenum, s);
    }
}

fn print_numbered_buf<'a>(out_buf: &Vec<u8>, linenum: u32, options: &getopts::Matches) {
    // if options.opt_present("v") || options.opt_present("t") {
        print!("     {}\t", linenum);
        for b in out_buf.iter() {
            print_byte(b, options);
        }
    // }
}

fn print_unnumbered(s: &String, options: &getopts::Matches) {
    if options.opt_present("v") || options.opt_present("t") {
        for b in s.as_bytes().iter() {
            print_byte(b, options);
        }
    }
    else {
        print!("{}", s);
    }
}

fn print_unnumbered_buf(out_buf: &Vec<u8>, options: &getopts::Matches) {
    // if options.opt_present("v") || options.opt_present("t") {
        for b in out_buf.iter() {
            print_byte(b, options);
        }
    // }
    // else {
        // print!("{}", s);
    // }
}

fn is_empty(line: &String) -> bool {
    let newline_str = "\n".to_string();
    let crlf_str = "\r\n".to_string();
    if line.is_empty() {
        true
    }
    else if line.eq(&newline_str) || line.eq(&crlf_str) {
        true
    }
    else {
        false
    }
}

fn is_empty_out_buf(v: &Vec<u8>) -> bool {
    if v.len() > 1 {
        false
    }
    else if is_nl(&v[0]) {
        true
    }
    else {
        false
    }
}

fn is_nl(c: &u8) -> bool {
    *c == 10u8
}

fn print_byte(b: &u8, options: &getopts::Matches) {
    if (*b > 31 && *b < 127) || *b == 10 || *b == 9 {
        if options.opt_present("t") && *b == 9 {
            print_tab();
        }
        else {
            print!("{}", *b as char);
        }
    }
    else {
        if options.opt_present("v") || options.opt_present("t") {
            if *b < 32 {
                print!("^{}", (*b + 64) as char);
            }
            else if *b == 127 {
                // del char
                print!("^?");
            }
            else if *b > 127 {
                if *b == 255 {
                    print!("M-^?");
                }
                else {
                    let x = *b - 128;
                    if x < 32 {
                        print!("M-^{}", (x + 64) as char);
                    }
                    else {
                        print!("M-{}", (*b - 128) as char);
                    }
                }
            }
        }
    }
}

fn print_tab() {
    print!("^I");
}

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

    #[test]
    fn assert_is_empty() {
        let s = "".to_string();
        assert!(is_empty(&s));
    }
    #[test]
    fn assert_is_empty_newline() {
        let s = "\n".to_string();
        assert!(is_empty(&s));
    }

    #[test]
    fn assert_is_empty_crlf() {
        let s = "\r\n".to_string();
        assert!(is_empty(&s));
    }

    #[test]
    fn assert_is_empty_char() {
        let s = "d".to_string();
        assert!(!is_empty(&s));
    }

    #[test]
    fn assert_is_empty_ctrl_char() {
        let s = "".to_string();
        assert!(!is_empty(&s));
    }
}
<commit_msg>wip on converting buf to single utf8 char<commit_after>extern crate getopts;
use getopts::{optflag,getopts,OptGroup,usage};
use std::os;

use std::num::Int;
use std::char;
use std::old_io;
use std::old_io::{IoResult, IoError};
use std::old_io::BufferedReader;
use std::old_io::File;
use std::old_io::stdio;

pub fn print_usage(program: &str, opts: &[OptGroup]) {
    let brief = format!("Usage: {} [options]", program);
    print!("{}", usage(brief.as_slice(), opts));
}

pub fn cat(v: &Vec<String>, options: &getopts::Matches) {
    if options.opt_present("u") {
        let writer = Box::new(stdio::stdout_raw());
        stdio::set_stdout(writer);
    }
    if v.is_empty() {
        cat_stdin(options);
    }
    else {
        // read files
        cat_files(v, options);
    }
}

fn cat_files(v: &Vec<String>, options: &getopts::Matches) {
    let mut linenum = 1u32;
    for filename in v.iter() {
        let path = Path::new(filename);
        match File::open(&path) {
            Ok(fh) => {
                let mut file = BufferedReader::new(fh);
                linenum = cat_file(file, options, linenum);
            },
            Err(f) => {
                println!("{}", f);
            }
        }
    }
}

fn cat_stdin(options: &getopts::Matches) {
    let mut linenum = 1u32;
    let mut printempty: bool = false;
    for line in old_io::stdin().lock().lines() {
        let (a, b) = handle_line(line.unwrap(), &mut printempty, linenum, options);
        printempty = a;
        linenum = b;
    }
}

fn cat_file<'a>(
    mut file: old_io::BufferedReader<std::old_io::fs::File>,
    options: &getopts::Matches,
    mut linenum: u32,
    ) -> u32 {
    let mut printempty: bool = false;
    let mut read_buf = [0, 4096];
    let mut out_buf: Vec<u8> = vec![];
    loop {
        match file.read(&mut read_buf) {
            Ok(n) => {
                for c in read_buf[..n].iter() {
                    out_buf.push(*c);
                    if is_nl(c) {
                        let (a, b) = handle_buf(&out_buf, &mut printempty, linenum, options);
                        printempty = a;
                        linenum = b;
                        out_buf.clear();
                    }
                }
            },
            Err(f) => {
                let mut o = 0u32;
                if out_buf.len() > 0 {
                    handle_buf(&out_buf, &mut printempty, linenum, options);
                }
                break
            }
        }
    }
    linenum
}

fn handle_line<'a>(
    linestr: String,
    printempty: &'a mut bool,
    mut linenum: u32,
    options: &getopts::Matches) -> (bool, u32) {
    if options.opt_present("s") {
        if !is_empty(&linestr) {
            if *printempty == true {
                println!("");
            }
            linenum = print_string(&linestr, linenum, options);
        }
        else {
            *printempty = true;
        }
    }
    else {
        linenum = print_string(&linestr, linenum, options);
    }
    (*printempty, linenum)
}

fn handle_buf<'a>(
    out_buf: &Vec<u8>,
    printempty: &'a mut bool,
    mut linenum: u32,
    options: &getopts::Matches) -> (bool, u32) {
    if options.opt_present("s") {
        if !is_empty_out_buf(out_buf) {
            if *printempty == true {
                if options.opt_present("n") {
                    println!("     {}\t", linenum);
                    linenum = linenum + 1;
                }
                else {
                    println!("");
                }
            }
            linenum = print_buf(&out_buf, linenum, options);
        }
        else {
            *printempty = true;
        }
    }
    else {
        linenum = print_buf(&out_buf, linenum, options);
    }
    (*printempty, linenum)
}

fn print_string<'a>(s: &String, mut linenum: u32, options: &getopts::Matches) -> u32 {
    if options.opt_present("b") {
        if !is_empty(s) {
            print_numbered(s, linenum, options);
            linenum = linenum + 1;
        }
        else {
            print_unnumbered(s, options);
        }
    }
    else if options.opt_present("n") {
        print_numbered(s, linenum, options);
        linenum = linenum + 1;
    }
    else {
        print_unnumbered(s, options);
    }
    linenum
}

fn print_buf<'a>(out_buf: &Vec<u8>, mut linenum: u32, options: &getopts::Matches) -> u32 {
    if options.opt_present("b") {
        if !is_empty_out_buf(out_buf) {
            print_numbered_buf(out_buf, linenum, options);
            linenum = linenum + 1;
        }
        else {
            print_unnumbered_buf(out_buf, options);
        }
    }
    else if options.opt_present("n") {
        print_numbered_buf(out_buf, linenum, options);
        linenum = linenum + 1;
    }
    else {
        print_unnumbered_buf(out_buf, options);
    }
    linenum
}

fn print_numbered<'a>(s: &String, linenum: u32, options: &getopts::Matches) {
    if options.opt_present("v") || options.opt_present("t") {
        print!("     {}\t", linenum);
        for b in s.as_bytes().iter() {
            print_byte(b, options);
        }
    }
    else {
        print!("     {}\t{}", linenum, s);
    }
}

fn print_numbered_buf<'a>(out_buf: &Vec<u8>, linenum: u32, options: &getopts::Matches) {
    // if options.opt_present("v") || options.opt_present("t") {
        print!("     {}\t", linenum);
        let mut t = 0u32;
        for b in out_buf.iter() {
            if t > 0 {
                t = t + *b as u32;
                print!("t: {} ", t);
                print!("{}", char::from_u32(t).unwrap());
                t = 0;
            }
            else {
                if *b > 160 {
                    t = *b as u32;
                }
                else {
                    print_byte(b, options);
                }
            }
        }
    // }
}

fn print_unnumbered(s: &String, options: &getopts::Matches) {
    if options.opt_present("v") || options.opt_present("t") {
        for b in s.as_bytes().iter() {
            print_byte(b, options);
        }
    }
    else {
        print!("{}", s);
    }
}

fn print_unnumbered_buf(out_buf: &Vec<u8>, options: &getopts::Matches) {
    // if options.opt_present("v") || options.opt_present("t") {
        let mut t = 0;
        let mut buf: Vec<u8> = vec![];
        for b in out_buf.iter() {
            if t > 0 {
                buf.push(*b);
                t = t - 1;
                if t == 0 {
                    print_u8_buf(&mut buf, options);
                }
            }
            else {
                if *b >= 240 {
                    //4th byte
                    t = 3;
                    buf.push(*b);
                }
                else if *b >= 224 {
                    t = 2;
                    buf.push(*b);
                }
                else if *b >= 192 {
                    t = 1;
                    buf.push(*b);
                }
                else {
                    print_byte(b, options);
                }
            }
        }
    // }
    // else {
        // print!("{}", s);
    // }
}

fn print_u8_buf(buf: &mut Vec<u8>, options: &getopts::Matches) {

    let o = convert_buf_to_codepoint(buf);
    print!("{}", char::from_u32(o).unwrap());
    // for b in buf.iter() {
        // print_byte(b, options);
    // }
}

fn convert_buf_to_codepoint(buf: &mut Vec<u8>) -> u32 {
    let mut s = 0u32;
    for b in buf.iter() {
        if *b >= 240 {
            s = s + (*b as u32 - 240 + 2.pow(19));
        }
        else if *b >= 224 {
            s = s + (*b as u32 - 224 + 2.pow(13));
        }
        else if *b >= 192 {
            s = s + (*b as u32 - 192 + 2.pow(7));
        }
        else {
            s = s + (*b as u32 - 64);
        }
    }
    s
}

fn is_empty(line: &String) -> bool {
    let newline_str = "\n".to_string();
    let crlf_str = "\r\n".to_string();
    if line.is_empty() {
        true
    }
    else if line.eq(&newline_str) || line.eq(&crlf_str) {
        true
    }
    else {
        false
    }
}

fn is_empty_out_buf(v: &Vec<u8>) -> bool {
    if v.len() > 1 {
        false
    }
    else if is_nl(&v[0]) {
        true
    }
    else {
        false
    }
}

fn is_nl(c: &u8) -> bool {
    *c == 10u8
}

fn print_byte(b: &u8, options: &getopts::Matches) {
    if (*b > 31 && *b < 127) || *b == 10 || *b == 9 {
        if options.opt_present("t") && *b == 9 {
            print_tab();
        }
        else {
            print!("{}", *b as char);
        }
    }
    else {
        if options.opt_present("v") || options.opt_present("t") {
            if *b < 32 {
                print!("^{}", (*b + 64) as char);
            }
            else if *b == 127 {
                // del char
                print!("^?");
            }
            else if *b > 127 {
                if *b == 255 {
                    print!("M-^?");
                }
                else {
                    let x = *b - 128;
                    if x < 32 {
                        print!("M-^{}", (x + 64) as char);
                    }
                    else {
                        print!("M-{}", (*b - 128) as char);
                    }
                }
            }
        }
    }
}

fn print_tab() {
    print!("^I");
}

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

    #[test]
    fn assert_is_empty() {
        let s = "".to_string();
        assert!(is_empty(&s));
    }
    #[test]
    fn assert_is_empty_newline() {
        let s = "\n".to_string();
        assert!(is_empty(&s));
    }

    #[test]
    fn assert_is_empty_crlf() {
        let s = "\r\n".to_string();
        assert!(is_empty(&s));
    }

    #[test]
    fn assert_is_empty_char() {
        let s = "d".to_string();
        assert!(!is_empty(&s));
    }

    #[test]
    fn assert_is_empty_ctrl_char() {
        let s = "".to_string();
        assert!(!is_empty(&s));
    }

    #[test]
    fn assert_buf_to_codepoint_24() {
        let mut b = vec![24u8];
        assert_eq!(convert_buf_to_codepoint(&mut b), 24u32);
    }
}
<|endoftext|>