<commit_before>// Low-level details, dealing with file descriptors etc

use mio::{self, unix};
use std::{io, mem, fmt};
use dbus::{Connection, ConnectionItems, ConnectionItem, Watch, WatchEvent, MsgHandler};
use futures::{Async, Future, task, Stream, Poll};
use tokio_core::reactor::{PollEvented, Handle as CoreHandle};
use std::rc::Rc;
use std::os::raw::c_uint;
use std::cell::RefCell;
use std::collections::VecDeque;

//#[derive(Debug)]
struct AWInner {
    conn: Rc<Connection>,
    task: RefCell<Option<task::Task>>,
    items: RefCell<VecDeque<ConnectionItem>>,
    handlers: RefCell<Vec<Box<MsgHandler>>>
}

impl fmt::Debug for AWInner {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        writeln!(f, "AWInner {{ task: {:?}, items: {:?} }}", self.task, self.items)
    }
}

impl AWInner {
    fn handle_items(&self, mut items: ConnectionItems) {
        {
            mem::swap(items.msg_handlers(), &mut *self.handlers.borrow_mut());
            let mut ci = self.items.borrow_mut();
            while let Some(item) = items.next() {
                println!("Transfer {:?}", item);
                ci.push_back(item);
            }
            mem::swap(items.msg_handlers(), &mut *self.handlers.borrow_mut());
        }
        let t = self.task.borrow_mut().take();
        println!("Unparking stream {:?}", t);
        t.map(|t| t.unpark());
    }
}

#[derive(Debug)]
pub struct AWatcher(Rc<AWInner>);

impl AWatcher {
    pub fn new(c: Rc<Connection>, h: &CoreHandle) -> io::Result<AWatcher> {
        let i = Rc::new(AWInner { conn: c, task: RefCell::new(None), items: RefCell::new(VecDeque::new()), handlers: RefCell::new(vec!()) });
        for w in i.conn.watch_fds() {
            h.spawn(AWatch2(PollEvented::new(AWatch(w), h)?, i.clone()).map_err(|e| panic!(e)));
        }
        Ok(AWatcher(i))
    }

    /// Builder method that adds a new msg handler.
    pub fn with<H: 'static + MsgHandler>(self, h: H) -> Self {
        self.append(h); self
    }

    /// Non-builder method that adds a new msg handler.
    pub fn append<H: 'static + MsgHandler>(&self, h: H) {
        self.0.handlers.borrow_mut().push(Box::new(h));
    }
}

impl Stream for AWatcher {
    type Item = ConnectionItem;
    type Error = ();
    fn poll(&mut self) -> Poll<Option<Self::Item>, Self::Error> {
        println!("Poll stream");
        let inner = &*self.0;
        match inner.items.borrow_mut().pop_front() {
            Some(item) => {
                Ok(Async::Ready(Some(item)))
            }
            None => {
                let p = task::park();
                println!("Parking stream {:?}", p);
                *inner.task.borrow_mut() = Some(p);
                Ok(Async::NotReady)
            }
        }
    }
}

#[derive(Debug)]
struct AWatch(Watch);

impl mio::Evented for AWatch {
    fn register(&self,
                poll: &mio::Poll,
                token: mio::Token,
                mut interest: mio::Ready,
                opts: mio::PollOpt) -> io::Result<()>
    {
        if !self.0.readable() { interest.remove(mio::Ready::readable()) };
        if !self.0.writable() { interest.remove(mio::Ready::writable()) };
        println!("Register: {:?} {:?}", self, interest);
        unix::EventedFd(&self.0.fd()).register(poll, token, interest, opts)
    }

    fn reregister(&self,
                  poll: &mio::Poll,
                  token: mio::Token,
                  interest: mio::Ready,
                  opts: mio::PollOpt) -> io::Result<()>
    {
        self.register(poll, token, interest, opts)
    }

    fn deregister(&self, poll: &mio::Poll) -> io::Result<()> {
        unix::EventedFd(&self.0.fd()).deregister(poll)
    }
}

#[derive(Debug)]
struct AWatch2(PollEvented<AWatch>, Rc<AWInner>);

impl Future for AWatch2 {
    type Item = ();
    type Error = io::Error;

    fn poll(&mut self) -> io::Result<Async<()>> {
        println!("Wakeup: {:?} {:?} {:?}", self, self.0.poll_read(), self.0.poll_write());

        let canread = self.0.poll_read().is_ready();
        let canwrite = self.0.poll_write().is_ready();
        let flags =
           if canread { WatchEvent::Readable as c_uint } else { 0 } +
           if canwrite { WatchEvent::Writable as c_uint } else { 0 };

        if flags == 0 { return Ok(Async::NotReady) }; // Not sure why are we woken up if we can't do anything, but seems to happen in practice

        let items = (self.1).conn.watch_handle(self.0.get_ref().0.fd(), flags);
        self.1.handle_items(items);
        if canread { self.0.need_read() };
        if canwrite { self.0.need_write() };
        Ok(Async::NotReady) // Continue forever
    }
}

#[test]
fn watch_test() {
    let conn = Rc::new(Connection::get_private(::dbus::BusType::Session).unwrap());
    let mut core = ::tokio_core::reactor::Core::new().unwrap();

    conn.register_object_path("/test").unwrap();

    let awatcher = AWatcher::new(conn.clone(), &core.handle()).unwrap();

    let m = ::dbus::Message::new_method_call(&conn.unique_name(), "/test", "com.example.dbusrs.asynctest", "AsyncTest").unwrap();
    let serial = conn.send(m).unwrap();
    println!("sent serial {}", serial);

    let (tx, rx) = ::futures::sync::oneshot::channel();
    let mut tx = Some(tx);
    let conn2 = conn.clone();
    let f = awatcher.for_each(move |i| {
        println!("Received {:?}", i);
        match i {
            ConnectionItem::MethodCall(m) => {
               assert_eq!(m.headers(), (::dbus::MessageType::MethodCall, Some("/test".to_string()),
                   Some("com.example.dbusrs.asynctest".into()), Some("AsyncTest".to_string())));
                let mr = ::dbus::Message::method_return(&m).append1("Tokio");
                println!("Sending reply {:?}", mr);
                conn2.send(mr).unwrap();
            }
            ConnectionItem::MethodReturn(m) => {
                assert_eq!(m.get_reply_serial().unwrap(), serial);
                assert_eq!(m.get1(), Some("Tokio"));
                println!("Success!");
                tx.take().unwrap().send(()).unwrap();
            }
            _ => {}
        }
        Ok(())
    });

    core.handle().spawn(f);
    core.run(rx).unwrap();
}

#[test]
fn watch2_test() {
    let conn = Rc::new(Connection::get_private(::dbus::BusType::Session).unwrap());
    let mut core = ::tokio_core::reactor::Core::new().unwrap();
    let awatcher = AWatcher::new(conn.clone(), &core.handle()).unwrap();

    let (tx, rx) = ::futures::sync::oneshot::channel();
    let mut tx = Some(tx);
    let m = ::dbus::Message::new_method_call("org.freedesktop.DBus", "/", "org.freedesktop.DBus", "ListNames").unwrap();
    awatcher.append(conn.send_with_reply(m, move |r| {
        let z: Vec<&str> = r.get1().unwrap();
        println!("got reply: {:?}", z);
        tx.take().unwrap().send(()).unwrap();
    }));

    core.handle().spawn(awatcher.for_each(|i| { println!("Received {:?}", i); Ok(()) } ));
    core.run(rx).unwrap();
}
<commit_msg>tokio: Remove debug prints<commit_after>// Low-level details, dealing with file descriptors etc

use mio::{self, unix};
use std::{io, mem, fmt};
use dbus::{Connection, ConnectionItems, ConnectionItem, Watch, WatchEvent, MsgHandler};
use futures::{Async, Future, task, Stream, Poll};
use tokio_core::reactor::{PollEvented, Handle as CoreHandle};
use std::rc::Rc;
use std::os::raw::c_uint;
use std::cell::RefCell;
use std::collections::VecDeque;

//#[derive(Debug)]
struct AWInner {
    conn: Rc<Connection>,
    task: RefCell<Option<task::Task>>,
    items: RefCell<VecDeque<ConnectionItem>>,
    handlers: RefCell<Vec<Box<MsgHandler>>>
}

impl fmt::Debug for AWInner {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        writeln!(f, "AWInner {{ task: {:?}, items: {:?} }}", self.task, self.items)
    }
}

impl AWInner {
    fn handle_items(&self, mut items: ConnectionItems) {
        {
            mem::swap(items.msg_handlers(), &mut *self.handlers.borrow_mut());
            let mut ci = self.items.borrow_mut();
            while let Some(item) = items.next() {
                ci.push_back(item);
            }
            mem::swap(items.msg_handlers(), &mut *self.handlers.borrow_mut());
        }
        let t = self.task.borrow_mut().take();
        t.map(|t| t.unpark());
    }
}

#[derive(Debug)]
pub struct AWatcher(Rc<AWInner>);

impl AWatcher {
    pub fn new(c: Rc<Connection>, h: &CoreHandle) -> io::Result<AWatcher> {
        let i = Rc::new(AWInner { conn: c, task: RefCell::new(None), items: RefCell::new(VecDeque::new()), handlers: RefCell::new(vec!()) });
        for w in i.conn.watch_fds() {
            h.spawn(AWatch2(PollEvented::new(AWatch(w), h)?, i.clone()).map_err(|e| panic!(e)));
        }
        Ok(AWatcher(i))
    }

    /// Builder method that adds a new msg handler.
    pub fn with<H: 'static + MsgHandler>(self, h: H) -> Self {
        self.append(h); self
    }

    /// Non-builder method that adds a new msg handler.
    pub fn append<H: 'static + MsgHandler>(&self, h: H) {
        self.0.handlers.borrow_mut().push(Box::new(h));
    }
}

impl Stream for AWatcher {
    type Item = ConnectionItem;
    type Error = ();
    fn poll(&mut self) -> Poll<Option<Self::Item>, Self::Error> {
        let inner = &*self.0;
        match inner.items.borrow_mut().pop_front() {
            Some(item) => {
                Ok(Async::Ready(Some(item)))
            }
            None => {
                let p = task::park();
                *inner.task.borrow_mut() = Some(p);
                Ok(Async::NotReady)
            }
        }
    }
}

#[derive(Debug)]
struct AWatch(Watch);

impl mio::Evented for AWatch {
    fn register(&self,
                poll: &mio::Poll,
                token: mio::Token,
                mut interest: mio::Ready,
                opts: mio::PollOpt) -> io::Result<()>
    {
        if !self.0.readable() { interest.remove(mio::Ready::readable()) };
        if !self.0.writable() { interest.remove(mio::Ready::writable()) };
        unix::EventedFd(&self.0.fd()).register(poll, token, interest, opts)
    }

    fn reregister(&self,
                  poll: &mio::Poll,
                  token: mio::Token,
                  interest: mio::Ready,
                  opts: mio::PollOpt) -> io::Result<()>
    {
        self.register(poll, token, interest, opts)
    }

    fn deregister(&self, poll: &mio::Poll) -> io::Result<()> {
        unix::EventedFd(&self.0.fd()).deregister(poll)
    }
}

#[derive(Debug)]
struct AWatch2(PollEvented<AWatch>, Rc<AWInner>);

impl Future for AWatch2 {
    type Item = ();
    type Error = io::Error;

    fn poll(&mut self) -> io::Result<Async<()>> {
        let canread = self.0.poll_read().is_ready();
        let canwrite = self.0.poll_write().is_ready();
        let flags =
           if canread { WatchEvent::Readable as c_uint } else { 0 } +
           if canwrite { WatchEvent::Writable as c_uint } else { 0 };

        // Not sure why are we woken up if we can't do anything, but seems to happen in practice
        if flags == 0 { return Ok(Async::NotReady) };

        let items = (self.1).conn.watch_handle(self.0.get_ref().0.fd(), flags);
        self.1.handle_items(items);
        if canread { self.0.need_read() };
        if canwrite { self.0.need_write() };
        Ok(Async::NotReady) // Continue forever
    }
}

#[test]
fn watch_test() {
    let conn = Rc::new(Connection::get_private(::dbus::BusType::Session).unwrap());
    let mut core = ::tokio_core::reactor::Core::new().unwrap();

    conn.register_object_path("/test").unwrap();

    let awatcher = AWatcher::new(conn.clone(), &core.handle()).unwrap();

    let m = ::dbus::Message::new_method_call(&conn.unique_name(), "/test", "com.example.dbusrs.asynctest", "AsyncTest").unwrap();
    let serial = conn.send(m).unwrap();
    println!("sent serial {}", serial);

    let (tx, rx) = ::futures::sync::oneshot::channel();
    let mut tx = Some(tx);
    let conn2 = conn.clone();
    let f = awatcher.for_each(move |i| {
        println!("Received {:?}", i);
        match i {
            ConnectionItem::MethodCall(m) => {
               assert_eq!(m.headers(), (::dbus::MessageType::MethodCall, Some("/test".to_string()),
                   Some("com.example.dbusrs.asynctest".into()), Some("AsyncTest".to_string())));
                let mr = ::dbus::Message::method_return(&m).append1("Tokio");
                println!("Sending reply {:?}", mr);
                conn2.send(mr).unwrap();
            }
            ConnectionItem::MethodReturn(m) => {
                assert_eq!(m.get_reply_serial().unwrap(), serial);
                assert_eq!(m.get1(), Some("Tokio"));
                println!("Success!");
                tx.take().unwrap().send(()).unwrap();
            }
            _ => {}
        }
        Ok(())
    });

    core.handle().spawn(f);
    core.run(rx).unwrap();
}

#[test]
fn watch2_test() {
    let conn = Rc::new(Connection::get_private(::dbus::BusType::Session).unwrap());
    let mut core = ::tokio_core::reactor::Core::new().unwrap();
    let awatcher = AWatcher::new(conn.clone(), &core.handle()).unwrap();

    let (tx, rx) = ::futures::sync::oneshot::channel();
    let mut tx = Some(tx);
    let m = ::dbus::Message::new_method_call("org.freedesktop.DBus", "/", "org.freedesktop.DBus", "ListNames").unwrap();
    awatcher.append(conn.send_with_reply(m, move |r| {
        let z: Vec<&str> = r.get1().unwrap();
        println!("got reply: {:?}", z);
        tx.take().unwrap().send(()).unwrap();
    }));

    core.handle().spawn(awatcher.for_each(|i| { println!("Received {:?}", i); Ok(()) } ));
    core.run(rx).unwrap();
}
<|endoftext|>


<commit_before>#![allow(unused_imports)] // FIXME for macOS

extern crate rand;

use rand::{SeedableRng, FromEntropy, Rng, rngs::SmallRng};

#[test]
fn simple() {
    assert_eq!(4, 4);
}

// Having more than 1 test does seem to make a difference
// (i.e., this calls ptr::swap which having just one test does not).
#[test]
fn fixed_rng() {
    let mut rng = rand::rngs::StdRng::seed_from_u64(0xdeadcafe);
    let x: u32 = rng.gen();
    let y: u32 = rng.gen();
    assert_ne!(x, y);
}

#[test]
fn entropy_rng() {
    // Use this opportunity to test querying the RNG (needs an external crate, hence tested here and not in the compiletest suite)
    let mut rng = SmallRng::from_entropy();
    let _val = rng.gen::<i32>();

    // Also try per-thread RNG.
    let mut rng = rand::thread_rng();
    let _val = rng.gen::<i32>();
}

// A test that won't work on miri
#[cfg(not(miri))]
#[test]
fn does_not_work_on_miri() {
    let x = 0u8;
    assert!(&x as *const _ as usize % 4 < 4);
}
<commit_msg>no need to allow any more<commit_after>use rand::{SeedableRng, FromEntropy, Rng, rngs::SmallRng};

#[test]
fn simple() {
    assert_eq!(4, 4);
}

// Having more than 1 test does seem to make a difference
// (i.e., this calls ptr::swap which having just one test does not).
#[test]
fn fixed_rng() {
    let mut rng = rand::rngs::StdRng::seed_from_u64(0xdeadcafe);
    let x: u32 = rng.gen();
    let y: u32 = rng.gen();
    assert_ne!(x, y);
}

#[test]
fn entropy_rng() {
    // Use this opportunity to test querying the RNG (needs an external crate, hence tested here and not in the compiletest suite)
    let mut rng = SmallRng::from_entropy();
    let _val = rng.gen::<i32>();

    // Also try per-thread RNG.
    let mut rng = rand::thread_rng();
    let _val = rng.gen::<i32>();
}

// A test that won't work on miri
#[cfg(not(miri))]
#[test]
fn does_not_work_on_miri() {
    let x = 0u8;
    assert!(&x as *const _ as usize % 4 < 4);
}
<|endoftext|>


<commit_before>extern crate postgres;
extern crate chrono;

#[cfg(test)]
mod tests;

use postgres::{Connection, SslMode, types};
use std::io::{self, Read};

#[derive(PartialEq, Debug)]
pub enum Align {
    Left,
    Right,
    Center,
}

#[allow(dead_code)]
#[derive(PartialEq, Debug)]
pub enum Color {
    White,
    BoldWhite,
    BoldRed,
    BoldGreen,
    BoldBlue,
}

pub fn color_text(text: &str, color: Color) -> String {
    let clrstr = match color {
        Color::White       => { format!("{}{}\x1B[33m\x1B[0m", "\x1B[33m\x1B[37m", text)        },
        Color::BoldWhite   => { format!("{}{}\x1B[33m\x1B[0m", "\x1B[33m\x1B[1m\x1B[33m\x1B[37m", text) },
        Color::BoldRed     => { format!("{}{}\x1B[33m\x1B[0m", "\x1B[33m\x1B[1m\x1B[33m\x1B[31m", text) },
        Color::BoldGreen   => { format!("{}{}\x1B[33m\x1B[0m", "\x1B[33m\x1B[1m\x1B[33m\x1B[32m", text) },
        Color::BoldBlue    => { format!("{}{}\x1B[33m\x1B[0m", "\x1B[33m\x1B[1m\x1B[33m\x1B[34m", text) },
    };

    clrstr
}

fn parse_result(column: &postgres::rows::Row, coltype: &Vec<types::Type>, colpos: usize) -> String {
    let val: String = match coltype[colpos] {
        types::Type::Text | types::Type::Varchar => column.get(colpos),
        types::Type::Bool => {
            let tmpbool: bool = column.get(colpos);
            match tmpbool {
                true  => String::from("true"),
                false => String::from("false"),
            }
        },
        types::Type::Int2 | types::Type::Int4 => {
            let tmpint: i32 = column.get(colpos);
            tmpint.to_string()
        },
        types::Type::Int8 => {
            let tmpint: i64 = column.get(colpos);
            tmpint.to_string()
        },
        types::Type::Float4 => {
            let tmpflt: f32 = column.get(colpos);
            tmpflt.to_string()
        },
        types::Type::Float8 => {
            let tmpflt: f64 = column.get(colpos);
            tmpflt.to_string()
        },
        types::Type::Timestamp => {
            let tmpdate: chrono::NaiveDateTime = column.get(colpos);
            tmpdate.format("%Y-%m-%d %H:%M:%s").to_string()
        },
        types::Type::TimestampTZ => {
            let tmpdate: chrono::DateTime<chrono::UTC> = column.get(colpos);
            tmpdate.format("%Y-%m-%d %H:%M:%s").to_string()
        },
        types::Type::Date => {
            let tmpdate: chrono::NaiveDate = column.get(colpos);
            tmpdate.format("%Y-%m-%d").to_string()
        },
        _ => String::from(""),
    };

    val
}

pub fn get_alignment(coltype: &types::Type) -> Align {
    match coltype {
        &types::Type::Int2          => Align::Right,
        &types::Type::Int4          => Align::Right,
        &types::Type::Int8          => Align::Right,
        &types::Type::Float4        => Align::Right,
        &types::Type::Float8        => Align::Right,
        &types::Type::Date          => Align::Right,
        &types::Type::Timestamp     => Align::Right,
        &types::Type::TimestampTZ   => Align::Right,
        _                           => Align::Left,
    }
}

pub fn pad_gen(len: usize, pad: &str) -> String {
    let mut padstr = String::from("");

    for _ in 0..len {
        padstr = padstr + pad;
    }

    padstr
}

pub fn format_field(column: &str, width: usize, align: Align) -> String {
    let padlen: usize = width - column.len();
    let extra: usize = padlen % 2;

    let ret: String = match align {
        Align::Center   => { format!("{}{}{}", pad_gen(padlen/2, " "), column, pad_gen((padlen/2)+extra, " ")) },
        Align::Right    => { format!("{}{}", pad_gen(padlen, " "), column) },
        Align::Left     => { format!("{}{}", column, pad_gen(padlen, " ")) },
    };

    ret
}

fn print_row(coltypes: &Vec<types::Type>, colwidths: &Vec<usize>, rowdata: &Vec<String>) {
    for (i, col) in rowdata.iter().enumerate() {
        if i > 0 {
            print!("{}", color_text("|", Color::BoldWhite));
        }

        print!(" {} ", format_field(&col, colwidths[i], get_alignment(&coltypes[i])));
    }

    println!("");
}

fn print_header(colwidths: &Vec<usize>, colnames: &Vec<String>) {
    for (i, name) in colnames.iter().enumerate() {
        if i > 0 {
            print!("{}", color_text("|", Color::BoldWhite));
        }

        print!(" {} ", color_text(&format_field(&name, colwidths[i], Align::Center), Color::BoldWhite));
    }

    println!("");
    for (i, col) in colwidths.iter().enumerate() {
        if i > 0 {
            print!("{}", color_text("|", Color::BoldWhite));
        }

        print!("{}", color_text(&pad_gen(col+2, "-"), Color::BoldWhite));
    }

    println!("");
}

fn main() {
    let mut buf = String::new();
    let mut colnames: Vec<String> = Vec::new();
    let mut coldata: Vec<Vec<String>> = Vec::new();
    let mut colwidths: Vec<usize> = Vec::new();
    let mut coltypes: Vec<types::Type> = Vec::new();
    let mut args = std::env::args();

    if args.len() == 1 {
        println!("{} {}", color_text("error:", Color::BoldRed), color_text("a DBURI is required!", Color::BoldWhite));
        println!("{} cat file.sql | first [DBURI]", color_text("usage:", Color::BoldBlue));
        std::process::exit(1);
    }

    let connstr: String = args.nth(1).unwrap();
    io::stdin().read_to_string(&mut buf);

    let conn = Connection::connect(&connstr as &str, SslMode::None).unwrap();
    let res = &conn.query(&mut buf, &[]).unwrap();
    let numcols = res.columns().len();

    for col in res.columns() {
        let colname = String::from(col.name());
        colwidths.push(colname.len());
        colnames.push(colname);
        coltypes.push(col.type_().clone());
    }

    for row in res.iter() {
        let mut colvals: Vec<String> = Vec::new();

        for i in 0..numcols {
            let ret = row.get_bytes(i);
            let col = if ret.is_some() { parse_result(&row, &coltypes, i) } else { String::from("") };

            if colwidths[i] < col.len() {
                colwidths[i] = col.len();
            }

            colvals.push(col);
        }

        coldata.push(colvals);
    }

    print_header(&colwidths, &colnames);
    for rowdata in coldata {
        print_row(&coltypes, &colwidths, &rowdata);
    }
}
<commit_msg>use more pattern matching, roll two functions into one<commit_after>extern crate postgres;
extern crate chrono;

#[cfg(test)]
mod tests;

use postgres::{Connection, SslMode, types};
use std::io::{self, Read};

#[derive(PartialEq, Debug)]
pub enum Align {
    Left,
    Right,
    Center,
}

#[allow(dead_code)]
#[derive(PartialEq, Debug)]
pub enum Color {
    White,
    BoldWhite,
    BoldRed,
    BoldGreen,
    BoldBlue,
}

pub fn color_text(text: &str, color: Color) -> String {
    let clrstr = match color {
        Color::White       => { format!("{}{}\x1B[33m\x1B[0m", "\x1B[33m\x1B[37m", text)        },
        Color::BoldWhite   => { format!("{}{}\x1B[33m\x1B[0m", "\x1B[33m\x1B[1m\x1B[33m\x1B[37m", text) },
        Color::BoldRed     => { format!("{}{}\x1B[33m\x1B[0m", "\x1B[33m\x1B[1m\x1B[33m\x1B[31m", text) },
        Color::BoldGreen   => { format!("{}{}\x1B[33m\x1B[0m", "\x1B[33m\x1B[1m\x1B[33m\x1B[32m", text) },
        Color::BoldBlue    => { format!("{}{}\x1B[33m\x1B[0m", "\x1B[33m\x1B[1m\x1B[33m\x1B[34m", text) },
    };

    clrstr
}

fn parse_result(column: &postgres::rows::Row, colpos: usize, coltype: &types::Type) -> String {
    let val: String = match *coltype {
        types::Type::Text | types::Type::Varchar => column.get(colpos),
        types::Type::Bool => {
            let tmpbool: bool = column.get(colpos);
            match tmpbool {
                true  => String::from("true"),
                false => String::from("false"),
            }
        },
        types::Type::Int2 | types::Type::Int4 => {
            let tmpint: i32 = column.get(colpos);
            tmpint.to_string()
        },
        types::Type::Int8 => {
            let tmpint: i64 = column.get(colpos);
            tmpint.to_string()
        },
        types::Type::Float4 => {
            let tmpflt: f32 = column.get(colpos);
            tmpflt.to_string()
        },
        types::Type::Float8 => {
            let tmpflt: f64 = column.get(colpos);
            tmpflt.to_string()
        },
        types::Type::Timestamp => {
            let tmpdate: chrono::NaiveDateTime = column.get(colpos);
            tmpdate.format("%Y-%m-%d %H:%M:%s").to_string()
        },
        types::Type::TimestampTZ => {
            let tmpdate: chrono::DateTime<chrono::UTC> = column.get(colpos);
            tmpdate.format("%Y-%m-%d %H:%M:%s").to_string()
        },
        types::Type::Date => {
            let tmpdate: chrono::NaiveDate = column.get(colpos);
            tmpdate.format("%Y-%m-%d").to_string()
        },
        _ => String::from(""),
    };

    val
}

pub fn get_alignment(coltype: &types::Type) -> Align {
    match coltype {
        &types::Type::Int2          => Align::Right,
        &types::Type::Int4          => Align::Right,
        &types::Type::Int8          => Align::Right,
        &types::Type::Float4        => Align::Right,
        &types::Type::Float8        => Align::Right,
        &types::Type::Date          => Align::Right,
        &types::Type::Timestamp     => Align::Right,
        &types::Type::TimestampTZ   => Align::Right,
        _                           => Align::Left,
    }
}

pub fn pad_gen(len: usize, pad: &str) -> String {
    let mut padstr = String::from("");

    for _ in 0..len {
        padstr = padstr + pad;
    }

    padstr
}

pub fn format_field(column: &str, width: usize, align: Align) -> String {
    let padlen: usize = width - column.len();
    let extra: usize = padlen % 2;

    let ret: String = match align {
        Align::Center   => { format!("{}{}{}", pad_gen(padlen/2, " "), column, pad_gen((padlen/2)+extra, " ")) },
        Align::Right    => { format!("{}{}", pad_gen(padlen, " "), column) },
        Align::Left     => { format!("{}{}", column, pad_gen(padlen, " ")) },
    };

    ret
}

fn print_row(coltypes: &Vec<types::Type>, colwidths: &Vec<usize>, rowdata: &Vec<String>, is_header: bool) {
    for (i, col) in rowdata.iter().enumerate() {
        if i > 0 {
            print!("{}", color_text("|", Color::BoldWhite));
        }

        match is_header {
            false   => print!(" {} ", format_field(&col, colwidths[i], get_alignment(&coltypes[i]))),
            true    => print!(" {} ", color_text(&format_field(&col, colwidths[i], Align::Center), Color::BoldWhite)),
        };
    }

    println!("");

    match is_header {
        false   => {},
        true    => {
            for (i, col) in colwidths.iter().enumerate() {
                if i > 0 {
                    print!("{}", color_text("|", Color::BoldWhite));
                }

                print!("{}", color_text(&pad_gen(col+2, "-"), Color::BoldWhite));
            }

            println!("");
        },
    };

}

fn main() {
    let mut buf = String::new();
    let mut colnames: Vec<String> = Vec::new();
    let mut coldata: Vec<Vec<String>> = Vec::new();
    let mut colwidths: Vec<usize> = Vec::new();
    let mut coltypes: Vec<types::Type> = Vec::new();
    let mut args = std::env::args();

    if args.len() == 1 {
        println!("{} {}", color_text("error:", Color::BoldRed), color_text("a DBURI is required!", Color::BoldWhite));
        println!("{} cat file.sql | first [DBURI]", color_text("usage:", Color::BoldBlue));
        std::process::exit(1);
    }

    let connstr: String = args.nth(1).unwrap();
    io::stdin().read_to_string(&mut buf);

    let conn = Connection::connect(&connstr as &str, SslMode::None).unwrap();
    let res = &conn.query(&mut buf, &[]).unwrap();
    let numcols = res.columns().len();

    for col in res.columns() {
        let colname = String::from(col.name());
        colwidths.push(colname.len());
        colnames.push(colname);
        coltypes.push(col.type_().clone());
    }

    for row in res.iter() {
        let mut colvals: Vec<String> = Vec::new();

        for i in 0..numcols {
            let ret = row.get_bytes(i);
            let col = match ret.is_some() {
                true    => parse_result(&row, i, &coltypes[i]),
                false   => String::from(""),
            };

            colwidths[i] = match col.len() > colwidths[i] {
                true    => col.len(),
                false   => colwidths[i]
            };

            colvals.push(col);
        }

        coldata.push(colvals);
    }

    print_row(&Vec::new(), &colwidths, &colnames, true);
    for rowdata in coldata {
        print_row(&coltypes, &colwidths, &rowdata, false);
    }
}
<|endoftext|>


<commit_before>extern crate postgres;
extern crate chrono;

use postgres::{Connection, SslMode, types};
use std::io::{self, Read};

enum Align {
    Left,
    Right,
    Center,
}

#[allow(dead_code)]
enum Color {
    White,
    BoldWhite,
    BoldRed,
    BoldGreen,
    BoldBlue,
}

fn color_text(text: &str, color: Color) -> String {
    let clrstr = match color {
        Color::White       => { format!("{}{}\x1B[33m\x1B[0m", "\x1B[33m\x1B[37m", text)        },
        Color::BoldWhite   => { format!("{}{}\x1B[33m\x1B[0m", "\x1B[33m\x1B[1m\x1B[33m\x1B[37m", text) },
        Color::BoldRed     => { format!("{}{}\x1B[33m\x1B[0m", "\x1B[33m\x1B[1m\x1B[33m\x1B[31m", text) },
        Color::BoldGreen   => { format!("{}{}\x1B[33m\x1B[0m", "\x1B[33m\x1B[1m\x1B[33m\x1B[32m", text) },
        Color::BoldBlue    => { format!("{}{}\x1B[33m\x1B[0m", "\x1B[33m\x1B[1m\x1B[33m\x1B[34m", text) },
    };

    clrstr
}

fn parse_result(column: &postgres::rows::Row, coltype: &Vec<types::Type>, colpos: usize) -> String {
    let val: String = match coltype[colpos] {
        types::Type::Text | types::Type::Varchar => column.get(colpos),
        types::Type::Bool => {
            let tmpbool: bool = column.get(colpos);
            match tmpbool {
                true  => String::from("true"),
                false => String::from("false"),
            }
        },
        types::Type::Int2 | types::Type::Int4 => {
            let tmpint: i32 = column.get(colpos);
            tmpint.to_string()
        },
        types::Type::Int8 => {
            let tmpint: i64 = column.get(colpos);
            tmpint.to_string()
        },
        types::Type::Float4 => {
            let tmpflt: f32 = column.get(colpos);
            tmpflt.to_string()
        },
        types::Type::Float8 => {
            let tmpflt: f64 = column.get(colpos);
            tmpflt.to_string()
        },
        types::Type::Timestamp => {
            let tmpdate: chrono::NaiveDateTime = column.get(colpos);
            tmpdate.format("%Y-%m-%d %H:%M:%s").to_string()
        },
        types::Type::TimestampTZ => {
            let tmpdate: chrono::DateTime<chrono::UTC> = column.get(colpos);
            tmpdate.format("%Y-%m-%d %H:%M:%s").to_string()
        },
        types::Type::Date => {
            let tmpdate: chrono::NaiveDate = column.get(colpos);
            tmpdate.format("%Y-%m-%d").to_string()
        },
        _ => String::from(""),
    };

    val
}

fn get_alignment(coltype: &Vec<types::Type>, colpos: usize) -> Align {
    match coltype[colpos] {
        types::Type::Int2   => Align::Right,
        types::Type::Int4   => Align::Right,
        types::Type::Int8   => Align::Right,
        types::Type::Float4 => Align::Right,
        types::Type::Float8 => Align::Right,
        _                   => Align::Left,
    }
}

fn format_field(column: &str, width: usize, align: Align) -> String {
    let mut padstr = String::from("");
    let padlen: usize = width - column.len();

    for _ in 0..padlen {
        padstr = padstr + " ";
    }

    let ret: String = match align {
        Align::Right => format!("{}{}", padstr, column),
        Align::Left  => format!("{}{}", column, padstr),
    };

    ret
}

fn print_row(coltypes: &Vec<types::Type>, colwidths: &Vec<usize>, rowdata: &Vec<String>) {
    for (i, col) in rowdata.iter().enumerate() {
        let align = get_alignment(&coltypes, i);

        if i > 0 {
            print!("|");
        }

        print!(" {} ", format_field(&col, colwidths[i], align));
    }

    println!("");
}

fn print_header(colwidths: &Vec<usize>) {
    for (i, col) in colwidths.iter().enumerate() {
        if i > 0 {
            print!("+");
        }

        print!("-{data:-<width$}-", data="-", width=col);
    }

    println!("");
}

fn main() {
    let mut buf = String::new();
    let mut colnames: Vec<String> = Vec::new();
    let mut coldata: Vec<Vec<String>> = Vec::new();
    let mut colwidths: Vec<usize> = Vec::new();
    let mut coltypes: Vec<types::Type> = Vec::new();

    io::stdin().read_to_string(&mut buf);

    let conn = Connection::connect("postgres://jeff@localhost", SslMode::None).unwrap();
    let res = &conn.query(&mut buf, &[]).unwrap();
    let numcols = res.columns().len();

    for col in res.columns() {
        let colname = String::from(col.name());
        colwidths.push(colname.len());
        colnames.push(colname);
        coltypes.push(col.type_().clone());
    }

    for row in res.iter() {
        let mut colvals: Vec<String> = Vec::new();

        for i in 0..numcols {
            let ret = row.get_bytes(i);
            let col = if ret.is_some() { parse_result(&row, &coltypes, i) } else { String::from("") };

            if colwidths[i] < col.len() {
                colwidths[i] = col.len();
            }

            colvals.push(col);
        }

        coldata.push(colvals);
    }

    print_row(&coltypes, &colwidths, &colnames);
    print_header(&colwidths);
    for rowdata in coldata {
        print_row(&coltypes, &colwidths, &rowdata);
    }
}
<commit_msg>simplify and update the printing of the table<commit_after>extern crate postgres;
extern crate chrono;

use postgres::{Connection, SslMode, types};
use std::io::{self, Read};

enum Align {
    Left,
    Right,
    Center,
}

#[allow(dead_code)]
enum Color {
    White,
    BoldWhite,
    BoldRed,
    BoldGreen,
    BoldBlue,
}

fn color_text(text: &str, color: Color) -> String {
    let clrstr = match color {
        Color::White       => { format!("{}{}\x1B[33m\x1B[0m", "\x1B[33m\x1B[37m", text)        },
        Color::BoldWhite   => { format!("{}{}\x1B[33m\x1B[0m", "\x1B[33m\x1B[1m\x1B[33m\x1B[37m", text) },
        Color::BoldRed     => { format!("{}{}\x1B[33m\x1B[0m", "\x1B[33m\x1B[1m\x1B[33m\x1B[31m", text) },
        Color::BoldGreen   => { format!("{}{}\x1B[33m\x1B[0m", "\x1B[33m\x1B[1m\x1B[33m\x1B[32m", text) },
        Color::BoldBlue    => { format!("{}{}\x1B[33m\x1B[0m", "\x1B[33m\x1B[1m\x1B[33m\x1B[34m", text) },
    };

    clrstr
}

fn parse_result(column: &postgres::rows::Row, coltype: &Vec<types::Type>, colpos: usize) -> String {
    let val: String = match coltype[colpos] {
        types::Type::Text | types::Type::Varchar => column.get(colpos),
        types::Type::Bool => {
            let tmpbool: bool = column.get(colpos);
            match tmpbool {
                true  => String::from("true"),
                false => String::from("false"),
            }
        },
        types::Type::Int2 | types::Type::Int4 => {
            let tmpint: i32 = column.get(colpos);
            tmpint.to_string()
        },
        types::Type::Int8 => {
            let tmpint: i64 = column.get(colpos);
            tmpint.to_string()
        },
        types::Type::Float4 => {
            let tmpflt: f32 = column.get(colpos);
            tmpflt.to_string()
        },
        types::Type::Float8 => {
            let tmpflt: f64 = column.get(colpos);
            tmpflt.to_string()
        },
        types::Type::Timestamp => {
            let tmpdate: chrono::NaiveDateTime = column.get(colpos);
            tmpdate.format("%Y-%m-%d %H:%M:%s").to_string()
        },
        types::Type::TimestampTZ => {
            let tmpdate: chrono::DateTime<chrono::UTC> = column.get(colpos);
            tmpdate.format("%Y-%m-%d %H:%M:%s").to_string()
        },
        types::Type::Date => {
            let tmpdate: chrono::NaiveDate = column.get(colpos);
            tmpdate.format("%Y-%m-%d").to_string()
        },
        _ => String::from(""),
    };

    val
}

fn get_alignment(coltype: &types::Type) -> Align {
    match coltype {
        &types::Type::Int2   => Align::Right,
        &types::Type::Int4   => Align::Right,
        &types::Type::Int8   => Align::Right,
        &types::Type::Float4 => Align::Right,
        &types::Type::Float8 => Align::Right,
        _                    => Align::Left,
    }
}

fn pad_gen(len: usize, pad: &str) -> String {
    let mut padstr = String::from("");

    for _ in 0..len {
        padstr = padstr + pad;
    }

    padstr
}

fn format_field(column: &str, width: usize, align: Align) -> String {
    let padlen: usize = width - column.len();
    let extra: usize = padlen % 2;

    let ret: String = match align {
        Align::Center   => { format!("{}{}{}", pad_gen(padlen/2, " "), column, pad_gen((padlen/2)+extra, " ")) },
        Align::Right    => { format!("{}{}", pad_gen(padlen, " "), column) },
        Align::Left     => { format!("{}{}", column, pad_gen(padlen, " ")) },
    };

    ret
}

fn print_row(coltypes: &Vec<types::Type>, colwidths: &Vec<usize>, rowdata: &Vec<String>) {
    for (i, col) in rowdata.iter().enumerate() {
        if i > 0 {
            print!("{}", color_text("|", Color::BoldWhite));
        }

        print!(" {} ", format_field(&col, colwidths[i], get_alignment(&coltypes[i])));
    }

    println!("");
}

fn print_header(colwidths: &Vec<usize>, colnames: &Vec<String>) {
    for (i, name) in colnames.iter().enumerate() {
        if i > 0 {
            print!("{}", color_text("|", Color::BoldWhite));
        }

        print!(" {} ", color_text(&format_field(&name, colwidths[i], Align::Center), Color::BoldWhite));
    }

    println!("");
    for (i, col) in colwidths.iter().enumerate() {
        if i > 0 {
            print!("{}", color_text("|", Color::BoldWhite));
        }

        print!("{}", color_text(&pad_gen(col+2, "-"), Color::BoldWhite));
    }

    println!("");
}

fn main() {
    let mut buf = String::new();
    let mut colnames: Vec<String> = Vec::new();
    let mut coldata: Vec<Vec<String>> = Vec::new();
    let mut colwidths: Vec<usize> = Vec::new();
    let mut coltypes: Vec<types::Type> = Vec::new();

    io::stdin().read_to_string(&mut buf);

    let conn = Connection::connect("postgres://jeff@localhost", SslMode::None).unwrap();
    let res = &conn.query(&mut buf, &[]).unwrap();
    let numcols = res.columns().len();

    for col in res.columns() {
        let colname = String::from(col.name());
        colwidths.push(colname.len());
        colnames.push(colname);
        coltypes.push(col.type_().clone());
    }

    for row in res.iter() {
        let mut colvals: Vec<String> = Vec::new();

        for i in 0..numcols {
            let ret = row.get_bytes(i);
            let col = if ret.is_some() { parse_result(&row, &coltypes, i) } else { String::from("") };

            if colwidths[i] < col.len() {
                colwidths[i] = col.len();
            }

            colvals.push(col);
        }

        coldata.push(colvals);
    }

    print_row(&coltypes, &colwidths, &colnames);
    print_header(&colwidths);
    for rowdata in coldata {
        print_row(&coltypes, &colwidths, &rowdata);
    }
}
<|endoftext|>


<commit_before>extern crate libcratesio;

use libcratesio::{CratesIO, Crate, Error};

#[test]
fn basic_data() {
    let krate = Crate::by_name("requests").unwrap();
    println!("{:?}", krate);
    assert_eq!(krate.name, "requests");
}

#[test]
fn raw_data() {
    let krate = CratesIO::query("requests").unwrap().as_json().unwrap();
    println!("{:#?}", krate);
    assert!(true);
}

#[test]
fn versions_iter() {
    let krate = Crate::by_name("requests").unwrap();
    for ver in krate.versions.iter() {
        println!("{:?}", ver);
    }
    assert!(true);
}

#[test]
fn error() {
    let err = Crate::by_name("xxx").unwrap_err();
    println!("{:?}", err);
    assert!(true);
}
<commit_msg>Add test for error response<commit_after>extern crate libcratesio;

use libcratesio::{CratesIO, Crate, Error, ErrorKind};

#[test]
fn basic_data() {
    let krate = Crate::by_name("requests").unwrap();
    println!("{:?}", krate);
    assert_eq!(krate.name, "requests");
}

#[test]
fn raw_data() {
    let krate = CratesIO::query("requests").unwrap().as_json().unwrap();
    println!("{:#?}", krate);
    assert!(true);
}

#[test]
fn versions_iter() {
    let krate = Crate::by_name("requests").unwrap();
    for ver in krate.versions.iter() {
        println!("{:?}", ver);
    }
    assert!(true);
}

#[test]
fn error() {
    let no_such_crate = Crate::by_name("no_such_crate");
    assert!(no_such_crate.is_err());
    let err = no_such_crate.unwrap_err();
    if let Error(ErrorKind::CratesIOError(response), _) = err {
        assert_eq!(response.detail(), "Not Found");
    } else {
        assert!(false);
    }
}
<|endoftext|>


<commit_before>// TODO enumerate options.

use std::str::{FromStr, ParseBoolError};
use std::num::ParseIntError;
use std::error::FromError;

#[derive(Debug)]
pub struct ParseValueError(());

#[derive(Debug)]
pub struct ParseNameError(());

impl FromError<ParseNameError> for ParseValueError {
    fn from_error(_: ParseNameError) -> Self { ParseValueError(()) }
}
impl FromError<ParseIntError> for ParseValueError {
    fn from_error(_: ParseIntError) -> Self { ParseValueError(()) }
}
impl FromError<ParseBoolError> for ParseValueError {
    fn from_error(_: ParseBoolError) -> Self { ParseValueError(()) }
}
// Required since String implements FromStr with Error = ()
impl FromError<()> for ParseValueError {
    fn from_error(_: ()) -> Self { ParseValueError(()) }
}

macro_rules! declare_type {
    ($name:ident, Check) =>  { type $name = bool; };
    ($name:ident, Spin)  =>  { type $name = i64; };
    ($name:ident, Combo) =>  { type $name = u32; };
    ($name:ident, Button) => { type $name = (); };
    ($name:ident, String) => { type $name = String; };
}

macro_rules! info_impl {
    (Check()) => { Info::Check };
    (Spin($min:expr, $max:expr)) => { Info::Spin($min, $max) };
    (Combo($($val:expr),+)) => { Info::Combo(&[$($val,)+]) };
    (Button()) => { Info::Button };
    (String()) => { Info::String };
}

macro_rules! parse_value {
    ($name:expr, Combo, $value_string:expr) => {{
        let temp = $name as usize; // work around an ICE
        let combo_list: &[&'static str] = match INFO[temp] {
            Info::Combo(x) => &x,
            _ => unreachable!(),
        };
        combo_list.position_elem(&&*$value_string).map(|x| x as u32).ok_or(ParseValueError(()))
    }};
    ($name:expr, Button, $value_string:expr) => { Ok::<(), ParseValueError>(()) };
    ($name:expr, $kind:ident, $value_string:expr) => {
        $value_string.parse()
    };
}

macro_rules! options_impl {
    (($num_opt:expr) options
     $(
         $name:ident ($repr:expr) : $kind:ident ($($info:tt),*),
      )+) => {

        $(declare_type!($name, $kind);)+

        #[derive(PartialEq, Eq, Clone, Debug)]
        pub enum Value {
            $($name($name),)+
        }

        #[derive(PartialEq, Eq, Copy, Clone, Debug)]
        pub enum Name {
            $($name,)+
        }

        impl FromStr for Value {
            type Err = ParseValueError;
            fn from_str(s: &str) -> Result<Self, ParseValueError> {
                // consume everything up to and including "name"
                let mut words = s.split(' ').skip_while(|&s| s != "name");
                words.next();

                let mut name_vec = Vec::<&str>::new();
                let mut value_vec = Vec::<&str>::new();

                let mut found_value = false;
                for curr_word in words {
                    if found_value {
                        value_vec.push(curr_word);
                    } else {
                        if curr_word == "value" {
                            found_value = true;
                        } else {
                            name_vec.push(curr_word);
                        }
                    }
                }

                let name_string  =  name_vec.connect(" ").trim().to_string();
                let value_string = value_vec.connect(" ").trim().to_string();

                let name: Name = try!(name_string.parse());
                Ok(match name {
                    $(
                        Name::$name => Value::$name(try!(
                                parse_value!(Name::$name, $kind, value_string))),
                    )+
                })
            }
        }

        impl FromStr for Name {
            type Err = ParseNameError;
            fn from_str(s: &str) -> Result<Self, ParseNameError> {
                match s {
                    $(
                        $repr => Ok(Name::$name),
                     )+
                    _ => Err(ParseNameError(())),
                }
            }
        }

        const INFO: [Info; $num_opt] = [$(
            info_impl!($kind($($info),*)),
        )+];
    }
}

options_impl!{
    (1) options
    Hash("hash"): Spin (1, 1024),
    //TestCheck("testcheck"): Check (),
    //TestCombo("testcombo"): Combo ("foo", "bar", "baz"),
    //TestButton("testbutton"): Button (),
    //TestString("teststring"): String (),
}

#[derive(PartialEq, Eq, Copy, Clone, Debug)]
pub enum Type {
    Check,
    Spin,
    Combo,
    Button,
    String,
}

#[derive(PartialEq, Eq, Clone, Debug)]
pub enum Info {
    Check,
    Spin(i64, i64),
    Combo(&'static[&'static str]),
    Button,
    String,
}
<commit_msg>Validate Spin-type options<commit_after>// TODO enumerate options.

use std::str::{FromStr, ParseBoolError};
use std::num::ParseIntError;
use std::error::FromError;

#[derive(Debug)]
pub struct ParseValueError(());

#[derive(Debug)]
pub struct ParseNameError(());

impl FromError<ParseNameError> for ParseValueError {
    fn from_error(_: ParseNameError) -> Self { ParseValueError(()) }
}
impl FromError<ParseIntError> for ParseValueError {
    fn from_error(_: ParseIntError) -> Self { ParseValueError(()) }
}
impl FromError<ParseBoolError> for ParseValueError {
    fn from_error(_: ParseBoolError) -> Self { ParseValueError(()) }
}
// Required since String implements FromStr with Error = ()
impl FromError<()> for ParseValueError {
    fn from_error(_: ()) -> Self { ParseValueError(()) }
}

macro_rules! declare_type {
    ($name:ident, Check) =>  { type $name = bool; };
    ($name:ident, Spin)  =>  { type $name = i64; };
    ($name:ident, Combo) =>  { type $name = u32; };
    ($name:ident, Button) => { type $name = (); };
    ($name:ident, String) => { type $name = String; };
}

macro_rules! info_impl {
    (Check()) => { Info::Check };
    (Spin($min:expr, $max:expr)) => { Info::Spin($min, $max) };
    (Combo($($val:expr),+)) => { Info::Combo(&[$($val,)+]) };
    (Button()) => { Info::Button };
    (String()) => { Info::String };
}

macro_rules! parse_value {
    ($name:expr, Combo, $value_string:expr) => {{
        let temp = $name as usize; // work around an ICE
        let combo_list: &[&'static str] = match INFO[temp] {
            Info::Combo(x) => &x,
            _ => unreachable!(),
        };
        combo_list.position_elem(&&*$value_string).map(|x| x as u32).ok_or(ParseValueError(()))
    }};
    ($name:expr, Button, $value_string:expr) => { Ok::<(), ParseValueError>(()) };
    ($name:expr, Spin, $value_string:expr) => {{
        let val: i64 = try!($value_string.parse());
        let temp = $name as usize; // work around an ICE
        let (min_val, max_val): (i64, i64) = match INFO[temp] {
            Info::Spin(x, y) => (x, y),
            _ => unreachable!(),
        };
        if val >= min_val && val <= max_val {
            Ok(val)
        } else {
            Err(ParseValueError(()))
        }
    }};
    ($name:expr, $kind:ident, $value_string:expr) => {
        $value_string.parse()
    };
}

macro_rules! options_impl {
    (($num_opt:expr) options
     $(
         $name:ident ($repr:expr) : $kind:ident ($($info:tt),*),
      )+) => {

        $(declare_type!($name, $kind);)+

        #[derive(PartialEq, Eq, Clone, Debug)]
        pub enum Value {
            $($name($name),)+
        }

        #[derive(PartialEq, Eq, Copy, Clone, Debug)]
        pub enum Name {
            $($name,)+
        }

        impl FromStr for Value {
            type Err = ParseValueError;
            fn from_str(s: &str) -> Result<Self, ParseValueError> {
                // consume everything up to and including "name"
                let mut words = s.split(' ').skip_while(|&s| s != "name");
                words.next();

                let mut name_vec = Vec::<&str>::new();
                let mut value_vec = Vec::<&str>::new();

                let mut found_value = false;
                for curr_word in words {
                    if found_value {
                        value_vec.push(curr_word);
                    } else {
                        if curr_word == "value" {
                            found_value = true;
                        } else {
                            name_vec.push(curr_word);
                        }
                    }
                }

                let name_string  =  name_vec.connect(" ").trim().to_string();
                let value_string = value_vec.connect(" ").trim().to_string();

                let name: Name = try!(name_string.parse());
                Ok(match name {
                    $(
                        Name::$name => Value::$name(try!(
                                parse_value!(Name::$name, $kind, value_string))),
                    )+
                })
            }
        }

        impl FromStr for Name {
            type Err = ParseNameError;
            fn from_str(s: &str) -> Result<Self, ParseNameError> {
                match s {
                    $(
                        $repr => Ok(Name::$name),
                     )+
                    _ => Err(ParseNameError(())),
                }
            }
        }

        const INFO: [Info; $num_opt] = [$(
            info_impl!($kind($($info),*)),
        )+];
    }
}

options_impl!{
    (1) options
    Hash("hash"): Spin (1, 1024),
    //TestCheck("testcheck"): Check (),
    //TestCombo("testcombo"): Combo ("foo", "bar", "baz"),
    //TestButton("testbutton"): Button (),
    //TestString("teststring"): String (),
}

#[derive(PartialEq, Eq, Copy, Clone, Debug)]
pub enum Type {
    Check,
    Spin,
    Combo,
    Button,
    String,
}

#[derive(PartialEq, Eq, Clone, Debug)]
pub enum Info {
    Check,
    Spin(i64, i64),
    Combo(&'static[&'static str]),
    Button,
    String,
}
<|endoftext|>


<commit_before>//! `log` crate adapter for slog-rs
//!
//! This crate provides two way compatibility with Rust standard `log` crate.
//!
//! ### `log` -> `slog`
//!
//! After calling `init()` `slog-stdlog` will take a role of `log` crate
//! back-end, forwarding all the `log` logging to `slog_scope::logger()`.
//! In other words, any `log` crate logging statement will behave like it was `slog`
//! logging statement executed with logger returned by `slog_scope::logger()`.
//! See documentation of `slog-scope` for more information about logging scopes.
//!
//! ### `slog` -> `log`
//!
//! `StdLog` is `slog::Drain` that will pass all `Record`s passing through it to
//! `log` crate just like they were crated with `log` crate logging macros in
//! the first place.
//!
//! ## `slog-scope`
//!
//! Since `log` does not have any form of context, and does not support `Logger`
//! `slog-stdlog` relies on "logging scopes" to establish it.
//!
//! You must set up logging context for `log` -> `slog` via `slog_scope::scope`
//! or `slog_scope::set_global_logger`. Setting a global logger upfront via
//! `slog_scope::set_global_logger` is highly recommended.
//!
//! Note: Since `slog-stdlog` v2, unlike previous releases, `slog-stdlog` uses
//! logging scopes provided by `slog-scope` crate instead of it's own.
//!
//! Refer to `slog-scope` crate documentation for more information.
//!
//! ### Warning
//!
//! Be careful when using both methods at the same time, as a loop can be easily
//! created: `log` -> `slog` -> `log` -> ...
//!
//! ## Compile-time log level filtering
//!
//! For filtering `debug!` and other `log` statements at compile-time, configure
//! the features on the `log` crate in your `Cargo.toml`:
//!
//! ```norust
//! log = { version = "*", features = ["max_level_trace", "release_max_level_warn"] }
//! ```
#![warn(missing_docs)]

#[macro_use]
extern crate slog;
extern crate slog_scope;
extern crate log;

use log::LogMetadata;
use std::{io, fmt};

use slog::Level;
use slog::KV;

struct Logger;

fn log_to_slog_level(level: log::LogLevel) -> Level {
    match level {
        log::LogLevel::Trace => Level::Trace,
        log::LogLevel::Debug => Level::Debug,
        log::LogLevel::Info => Level::Info,
        log::LogLevel::Warn => Level::Warning,
        log::LogLevel::Error => Level::Error,
    }
}

impl log::Log for Logger {
    fn enabled(&self, _: &LogMetadata) -> bool {
        true
    }

    fn log(&self, r: &log::LogRecord) {
        let level = log_to_slog_level(r.metadata().level());

        let args = r.args();
        let target = r.target();
        let module = r.location().__module_path;
        let file = r.location().__file;
        let line = r.location().line();

        let s = slog::RecordStatic {
            location: &slog::RecordLocation {
                           file: file,
                           line: line,
                           column: 0,
                           function: "",
                           module: module,
                       },
            level: level,
            tag: target,
        };
        slog_scope::with_logger(|logger| logger.log(&slog::Record::new(&s, args, b!())))

    }
}

/// Register `slog-stdlog` as `log` backend.
///
/// This will pass all logging statements crated with `log`
/// crate to current `slog-scope::logger()`.
///
/// ```
/// #[macro_use]
/// extern crate log;
/// extern crate slog_stdlog;
///
/// fn main() {
///     slog_stdlog::init().unwrap();
///     // Note: this `info!(...)` macro comes from `log` crate
///     info!("standard logging redirected to slog");
/// }
/// ```
pub fn init() -> Result<(), log::SetLoggerError> {
    log::set_logger(|max_log_level| {
                        max_log_level.set(log::LogLevelFilter::max());
                        Box::new(Logger)
                    })
}

/// Drain logging `Record`s into `log` crate
///
/// Any `Record` passing through this `Drain` will be forwarded
/// to `log` crate, just like it was created with `log` crate macros
/// in the first place. The message and key-value pairs will be formated
/// to be one string.
///
/// Caution needs to be taken to prevent circular loop where `Logger`
/// installed via `slog-stdlog::set_logger` would log things to a `StdLog`
/// drain, which would again log things to the global `Logger` and so on
/// leading to an infinite recursion.
pub struct StdLog;

struct LazyLogString<'a> {
    info: &'a slog::Record<'a>,
    logger_values: &'a slog::OwnedKVList,
}

impl<'a> LazyLogString<'a> {
    fn new(info: &'a slog::Record, logger_values: &'a slog::OwnedKVList) -> Self {

        LazyLogString {
            info: info,
            logger_values: logger_values,
        }
    }
}

impl<'a> fmt::Display for LazyLogString<'a> {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {

        try!(write!(f, "{}", self.info.msg()));

        let io = io::Cursor::new(Vec::new());
        let mut ser = KSV::new(io);

        let res = {
            || -> io::Result<()> {
                try!(self.logger_values.serialize(self.info, &mut ser));
                try!(self.info.kv().serialize(self.info, &mut ser));
                Ok(())
            }
        }()
                .map_err(|_| fmt::Error);

        try!(res);

        let values = ser.into_inner().into_inner();

        write!(f, "{}", String::from_utf8_lossy(&values))

    }
}

impl slog::Drain for StdLog {
    type Err = io::Error;
    type Ok = ();
    fn log(&self, info: &slog::Record, logger_values: &slog::OwnedKVList) -> io::Result<()> {

        let level = match info.level() {
            slog::Level::Critical | slog::Level::Error => log::LogLevel::Error,
            slog::Level::Warning => log::LogLevel::Warn,
            slog::Level::Info => log::LogLevel::Info,
            slog::Level::Debug => log::LogLevel::Debug,
            slog::Level::Trace => log::LogLevel::Trace,
        };

        let target = info.tag();

        let location = log::LogLocation {
            __module_path: info.module(),
            __file: info.file(),
            __line: info.line(),
        };

        let lazy = LazyLogString::new(info, logger_values);
        // Please don't yell at me for this! :D
        // https://github.com/rust-lang-nursery/log/issues/95
        log::__log(level, target, &location, format_args!("{}", lazy));

        Ok(())
    }
}

/// Key-Separator-Value serializer
struct KSV<W: io::Write> {
    io: W,
}

impl<W: io::Write> KSV<W> {
    fn new(io: W) -> Self {
        KSV { io: io }
    }

    fn into_inner(self) -> W {
        self.io
    }
}

impl<W: io::Write> slog::Serializer for KSV<W> {
    fn emit_arguments(&mut self, key: &str, val: &fmt::Arguments) -> slog::Result {
        try!(write!(self.io, ", {}: {}", key, val));
        Ok(())
    }
}
<commit_msg>Fix example for `init`<commit_after>//! `log` crate adapter for slog-rs
//!
//! This crate provides two way compatibility with Rust standard `log` crate.
//!
//! ### `log` -> `slog`
//!
//! After calling `init()` `slog-stdlog` will take a role of `log` crate
//! back-end, forwarding all the `log` logging to `slog_scope::logger()`.
//! In other words, any `log` crate logging statement will behave like it was `slog`
//! logging statement executed with logger returned by `slog_scope::logger()`.
//! See documentation of `slog-scope` for more information about logging scopes.
//!
//! ### `slog` -> `log`
//!
//! `StdLog` is `slog::Drain` that will pass all `Record`s passing through it to
//! `log` crate just like they were crated with `log` crate logging macros in
//! the first place.
//!
//! ## `slog-scope`
//!
//! Since `log` does not have any form of context, and does not support `Logger`
//! `slog-stdlog` relies on "logging scopes" to establish it.
//!
//! You must set up logging context for `log` -> `slog` via `slog_scope::scope`
//! or `slog_scope::set_global_logger`. Setting a global logger upfront via
//! `slog_scope::set_global_logger` is highly recommended.
//!
//! Note: Since `slog-stdlog` v2, unlike previous releases, `slog-stdlog` uses
//! logging scopes provided by `slog-scope` crate instead of it's own.
//!
//! Refer to `slog-scope` crate documentation for more information.
//!
//! ### Warning
//!
//! Be careful when using both methods at the same time, as a loop can be easily
//! created: `log` -> `slog` -> `log` -> ...
//!
//! ## Compile-time log level filtering
//!
//! For filtering `debug!` and other `log` statements at compile-time, configure
//! the features on the `log` crate in your `Cargo.toml`:
//!
//! ```norust
//! log = { version = "*", features = ["max_level_trace", "release_max_level_warn"] }
//! ```
#![warn(missing_docs)]

#[macro_use]
extern crate slog;
extern crate slog_scope;
extern crate log;

use log::LogMetadata;
use std::{io, fmt};

use slog::Level;
use slog::KV;

struct Logger;

fn log_to_slog_level(level: log::LogLevel) -> Level {
    match level {
        log::LogLevel::Trace => Level::Trace,
        log::LogLevel::Debug => Level::Debug,
        log::LogLevel::Info => Level::Info,
        log::LogLevel::Warn => Level::Warning,
        log::LogLevel::Error => Level::Error,
    }
}

impl log::Log for Logger {
    fn enabled(&self, _: &LogMetadata) -> bool {
        true
    }

    fn log(&self, r: &log::LogRecord) {
        let level = log_to_slog_level(r.metadata().level());

        let args = r.args();
        let target = r.target();
        let module = r.location().__module_path;
        let file = r.location().__file;
        let line = r.location().line();

        let s = slog::RecordStatic {
            location: &slog::RecordLocation {
                           file: file,
                           line: line,
                           column: 0,
                           function: "",
                           module: module,
                       },
            level: level,
            tag: target,
        };
        slog_scope::with_logger(|logger| logger.log(&slog::Record::new(&s, args, b!())))

    }
}

/// Register `slog-stdlog` as `log` backend.
///
/// This will pass all logging statements crated with `log`
/// crate to current `slog-scope::logger()`.
///
/// ```
/// #[macro_use]
/// extern crate log;
/// extern crate slog_stdlog;
///
/// fn main() {
///     let _guard = slog_stdlog::init().unwrap();
///     // Note: this `info!(...)` macro comes from `log` crate
///     info!("standard logging redirected to slog");
/// }
/// ```
pub fn init() -> Result<(), log::SetLoggerError> {
    log::set_logger(|max_log_level| {
                        max_log_level.set(log::LogLevelFilter::max());
                        Box::new(Logger)
                    })
}

/// Drain logging `Record`s into `log` crate
///
/// Any `Record` passing through this `Drain` will be forwarded
/// to `log` crate, just like it was created with `log` crate macros
/// in the first place. The message and key-value pairs will be formated
/// to be one string.
///
/// Caution needs to be taken to prevent circular loop where `Logger`
/// installed via `slog-stdlog::set_logger` would log things to a `StdLog`
/// drain, which would again log things to the global `Logger` and so on
/// leading to an infinite recursion.
pub struct StdLog;

struct LazyLogString<'a> {
    info: &'a slog::Record<'a>,
    logger_values: &'a slog::OwnedKVList,
}

impl<'a> LazyLogString<'a> {
    fn new(info: &'a slog::Record, logger_values: &'a slog::OwnedKVList) -> Self {

        LazyLogString {
            info: info,
            logger_values: logger_values,
        }
    }
}

impl<'a> fmt::Display for LazyLogString<'a> {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {

        try!(write!(f, "{}", self.info.msg()));

        let io = io::Cursor::new(Vec::new());
        let mut ser = KSV::new(io);

        let res = {
            || -> io::Result<()> {
                try!(self.logger_values.serialize(self.info, &mut ser));
                try!(self.info.kv().serialize(self.info, &mut ser));
                Ok(())
            }
        }()
                .map_err(|_| fmt::Error);

        try!(res);

        let values = ser.into_inner().into_inner();

        write!(f, "{}", String::from_utf8_lossy(&values))

    }
}

impl slog::Drain for StdLog {
    type Err = io::Error;
    type Ok = ();
    fn log(&self, info: &slog::Record, logger_values: &slog::OwnedKVList) -> io::Result<()> {

        let level = match info.level() {
            slog::Level::Critical | slog::Level::Error => log::LogLevel::Error,
            slog::Level::Warning => log::LogLevel::Warn,
            slog::Level::Info => log::LogLevel::Info,
            slog::Level::Debug => log::LogLevel::Debug,
            slog::Level::Trace => log::LogLevel::Trace,
        };

        let target = info.tag();

        let location = log::LogLocation {
            __module_path: info.module(),
            __file: info.file(),
            __line: info.line(),
        };

        let lazy = LazyLogString::new(info, logger_values);
        // Please don't yell at me for this! :D
        // https://github.com/rust-lang-nursery/log/issues/95
        log::__log(level, target, &location, format_args!("{}", lazy));

        Ok(())
    }
}

/// Key-Separator-Value serializer
struct KSV<W: io::Write> {
    io: W,
}

impl<W: io::Write> KSV<W> {
    fn new(io: W) -> Self {
        KSV { io: io }
    }

    fn into_inner(self) -> W {
        self.io
    }
}

impl<W: io::Write> slog::Serializer for KSV<W> {
    fn emit_arguments(&mut self, key: &str, val: &fmt::Arguments) -> slog::Result {
        try!(write!(self.io, ", {}: {}", key, val));
        Ok(())
    }
}
<|endoftext|>


<commit_before>use std::error::Error;
use std::fmt;
use std::io;
use std::str;

use crate::wire_format::WireType;

/// `Result` alias for `ProtobufError`
pub type ProtobufResult<T> = Result<T, ProtobufError>;

/// Enum values added here for diagnostic purposes.
/// Users should not depend on specific values.
#[derive(Debug, thiserror::Error)]
pub enum WireError {
    #[error("Unexpected EOF")]
    UnexpectedEof,
    #[error("Unexpected wire type")]
    UnexpectedWireType(WireType),
    #[error("Incorrect tag")]
    IncorrectTag(u32),
    // unused since https://github.com/stepancheg/rust-protobuf/issues/318
    #[error("Incomplete map")]
    IncompleteMap,
    #[error("Incorrect varint")]
    IncorrectVarint,
    #[error("Invalid UTF-8 sequence")]
    Utf8Error,
    #[error("Invalid enum value: {}", .0)]
    InvalidEnumValue(i32),
    #[error("Over recursion limit")]
    OverRecursionLimit,
    #[error("Truncated message")]
    TruncatedMessage,
    // not really possible
    #[error("Limit overflow")]
    LimitOverflow,
    #[error("New limit must not be greater than current limit")]
    LimitIncrease,
}

/// Generic protobuf error
#[derive(Debug)]
pub enum ProtobufError {
    /// I/O error when reading or writing
    IoError(io::Error),
    /// Malformed input
    WireError(WireError),
    /// Protocol contains a string which is not valid UTF-8 string
    Utf8(str::Utf8Error),
    /// Not all required fields of message set.
    MessageNotInitialized(String),
}

impl fmt::Display for ProtobufError {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match self {
            // not sure that cause should be included in message
            &ProtobufError::IoError(ref e) => write!(f, "IO error: {}", e),
            &ProtobufError::WireError(ref e) => fmt::Display::fmt(e, f),
            &ProtobufError::Utf8(ref e) => write!(f, "{}", e),
            &ProtobufError::MessageNotInitialized { .. } => write!(f, "not all message fields set"),
        }
    }
}

impl Error for ProtobufError {
    fn cause(&self) -> Option<&dyn Error> {
        match self {
            &ProtobufError::IoError(ref e) => Some(e),
            &ProtobufError::Utf8(ref e) => Some(e),
            &ProtobufError::WireError(..) => None,
            &ProtobufError::MessageNotInitialized { .. } => None,
        }
    }
}

impl From<io::Error> for ProtobufError {
    fn from(err: io::Error) -> Self {
        ProtobufError::IoError(err)
    }
}

impl From<str::Utf8Error> for ProtobufError {
    fn from(err: str::Utf8Error) -> Self {
        ProtobufError::Utf8(err)
    }
}

impl From<ProtobufError> for io::Error {
    fn from(err: ProtobufError) -> Self {
        match err {
            ProtobufError::IoError(e) => e,
            ProtobufError::WireError(e) => {
                io::Error::new(io::ErrorKind::InvalidData, ProtobufError::WireError(e))
            }
            ProtobufError::MessageNotInitialized(message) => io::Error::new(
                io::ErrorKind::InvalidInput,
                ProtobufError::MessageNotInitialized(message),
            ),
            e => io::Error::new(io::ErrorKind::Other, Box::new(e)),
        }
    }
}
<commit_msg>Use thiserror for ProtobufError<commit_after>use std::io;
use std::str;

use crate::wire_format::WireType;

/// `Result` alias for `ProtobufError`
pub type ProtobufResult<T> = Result<T, ProtobufError>;

/// Enum values added here for diagnostic purposes.
/// Users should not depend on specific values.
#[derive(Debug, thiserror::Error)]
pub enum WireError {
    #[error("Unexpected EOF")]
    UnexpectedEof,
    #[error("Unexpected wire type")]
    UnexpectedWireType(WireType),
    #[error("Incorrect tag")]
    IncorrectTag(u32),
    // unused since https://github.com/stepancheg/rust-protobuf/issues/318
    #[error("Incomplete map")]
    IncompleteMap,
    #[error("Incorrect varint")]
    IncorrectVarint,
    #[error("Invalid UTF-8 sequence")]
    Utf8Error,
    #[error("Invalid enum value: {}", .0)]
    InvalidEnumValue(i32),
    #[error("Over recursion limit")]
    OverRecursionLimit,
    #[error("Truncated message")]
    TruncatedMessage,
    // not really possible
    #[error("Limit overflow")]
    LimitOverflow,
    #[error("New limit must not be greater than current limit")]
    LimitIncrease,
}

/// Generic protobuf error
#[derive(Debug, thiserror::Error)]
pub enum ProtobufError {
    /// I/O error when reading or writing
    #[error(transparent)]
    IoError(#[from] io::Error),
    /// Malformed input
    #[error(transparent)]
    WireError(#[from] WireError),
    /// Protocol contains a string which is not valid UTF-8 string
    #[error("UTF-8 decode error")]
    Utf8(#[from] str::Utf8Error),
    /// Not all required fields of message set.
    #[error("Message `{}` is missing required fields", .0)]
    MessageNotInitialized(String),
}

impl From<ProtobufError> for io::Error {
    fn from(err: ProtobufError) -> Self {
        match err {
            ProtobufError::IoError(e) => e,
            ProtobufError::WireError(e) => {
                io::Error::new(io::ErrorKind::InvalidData, ProtobufError::WireError(e))
            }
            ProtobufError::MessageNotInitialized(message) => io::Error::new(
                io::ErrorKind::InvalidInput,
                ProtobufError::MessageNotInitialized(message),
            ),
            e => io::Error::new(io::ErrorKind::Other, Box::new(e)),
        }
    }
}
<|endoftext|>


<commit_before>// ToDO: add tests
<commit_msg>test(logname) add a test for logname<commit_after>use crate::common::util::*;
use std::env;

#[test]
fn test_normal() {
    let (_, mut ucmd) = at_and_ucmd!();

    let result = ucmd.run();
    println!("result.stdout = {}", result.stdout);
    println!("result.stderr = {}", result.stderr);
    println!("env::var(CI).is_ok() = {}", env::var("CI").is_ok());

    for (key, value) in env::vars() {
        println!("{}: {}", key, value);
    }
    if env::var("USER").is_ok()
        && env::var("USER").unwrap() == "runner"
        && result.stderr.contains("error: no login name")
    {
        // In the CI, some server are failing to return logname.
        // As seems to be a configuration issue, ignoring it
        return;
    }

    assert!(result.success);
    assert!(!result.stdout.trim().is_empty());
}
<|endoftext|>


<commit_before>#![allow(dead_code, unused_variables)]
use alloc::alloc::{Global, Alloc, Layout};
use bytes::BytesMut;

use std::sync::Arc;

use audiosample::*;
use pixel::*;
use timeinfo::*;

use byte_slice_cast::*;

#[derive(Fail, Debug)]
pub enum FrameError {
    #[fail(display = "Invalid Index")]
    InvalidIndex,
    #[fail(display = "Invalid Conversion")]
    InvalidConversion,
}

use self::FrameError::*;

// TODO: Document
// TODO: Change it to provide Droppable/Seekable information or use a separate enum?
#[derive(Clone, Debug, PartialEq)]
pub enum PictureType {
    UNKNOWN,
    I,
    P,
    B,
    S,
    SI,
    SP,
    SB,
    BI,
}

#[derive(Clone, Debug, PartialEq)]
pub struct VideoInfo {
    pub pic_type: PictureType,
    pub width: usize,
    pub height: usize,
    pub format: Arc<Formaton>,
}

impl VideoInfo {
    fn size(&self, align: usize) -> usize {
        let mut size = 0;
        for &component in self.format.into_iter() {
            if let Some(c) = component {
                size += c.get_data_size(self.width, self.height, align);
            }
        }
        size
    }
}

#[derive(Clone, Debug)]
pub struct AudioInfo {
    pub samples: usize,
    pub rate: usize,
    pub map: ChannelMap,
    pub format: Arc<Soniton>,
}

impl AudioInfo {
    fn size(&self, align: usize) -> usize {
        self.format.get_audio_size(self.samples, align) * self.map.len()
    }
}

impl PartialEq for AudioInfo {

    fn eq(&self, info2: &AudioInfo) -> bool {
        self.rate == info2.rate && self.map == info2.map && self.format == info2.format
    }
}

#[derive(Clone, Debug, PartialEq)]
pub enum MediaKind {
    Video(VideoInfo),
    Audio(AudioInfo),
}

use std::convert::From;

impl From<VideoInfo> for MediaKind {
    fn from(v: VideoInfo) -> Self {
        MediaKind::Video(v)
    }
}

impl From<AudioInfo> for MediaKind {
    fn from(a: AudioInfo) -> Self {
        MediaKind::Audio(a)
    }
}

use self::MediaKind::*;

pub trait FrameBuffer : Send + Sync {
    fn linesize(&self, idx: usize) -> Result<usize, FrameError>;
    fn count(&self) -> usize;
    fn as_slice_inner<'a>(&'a self, idx: usize) -> Result<&'a [u8], FrameError>;
    fn as_mut_slice_inner<'a>(&'a mut self, idx: usize) -> Result<&'a mut [u8], FrameError>;
}

mod private {
    use byte_slice_cast::*;

    pub trait Supported: FromByteSlice {}
    impl Supported for u8 {}
    impl Supported for i16 {}
    impl Supported for f32 {}
}

pub trait FrameBufferConv<T: private::Supported> : FrameBuffer {
    fn as_slice<'a>(&'a self, idx: usize) -> Result<&'a [T], FrameError> {
        self.as_slice_inner(idx)?.as_slice_of::<T>().map_err(|e| InvalidConversion)
    }
    fn as_mut_slice<'a>(&'a mut self, idx: usize) -> Result<&'a mut [T], FrameError> {
        self.as_mut_slice_inner(idx)?.as_mut_slice_of::<T>().map_err(|e| InvalidConversion)
    }
}

impl FrameBufferConv<u8> for FrameBuffer {}
impl FrameBufferConv<i16> for FrameBuffer {}
impl FrameBufferConv<f32> for FrameBuffer {}

use std::fmt;

impl fmt::Debug for FrameBuffer {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "FrameBuffer")
    }
}

#[derive(Debug)]
pub struct Frame {
    pub kind: MediaKind,
    pub buf: Box<FrameBuffer>,
    pub t: TimeInfo,
}

const ALIGNMENT: usize = 32;

struct Plane {
    buf: BytesMut,
    linesize: usize,
}

struct DefaultFrameBuffer {
    buf: BytesMut,
    planes: Vec<Plane>,
}

impl FrameBuffer for DefaultFrameBuffer {
    fn linesize(&self, idx: usize) -> Result<usize, FrameError> {
        match self.planes.get(idx) {
            None => Err(InvalidIndex),
            Some(plane) => Ok(plane.linesize),
        }
    }
    fn count(&self) -> usize {
        self.planes.len()
    }

    fn as_slice_inner<'a>(&'a self, idx: usize) -> Result<&'a [u8], FrameError> {
        match self.planes.get(idx) {
            None => Err(InvalidIndex),
            Some(plane) => Ok(&plane.buf),
        }
    }
    fn as_mut_slice_inner<'a>(&'a mut self, idx: usize) -> Result<&'a mut [u8], FrameError> {
        match self.planes.get_mut(idx) {
            None => Err(InvalidIndex),
            Some(plane) => Ok(&mut plane.buf),
        }
    }
}

impl DefaultFrameBuffer {
    pub fn new<'a>(kind: &'a MediaKind) -> DefaultFrameBuffer {
        match kind {
            &Video(ref video) => {
                let size = video.size(ALIGNMENT);
                let data = unsafe {
                    Global.alloc(Layout::from_size_align(size, ALIGNMENT).unwrap())
                        .unwrap()
                };
                let data = data.as_ptr() as *mut u8;
                //let data = unsafe { Heap.alloc_zeroed(Layout::from_size_align(size, ALIGNMENT)) };
                let buf = BytesMut::from(unsafe { Vec::from_raw_parts(data, size, size) });
                let mut buffer = DefaultFrameBuffer {
                    buf: buf,
                    planes: Vec::new(),
                };
                for &component in video.format.iter() {
                    if let Some(c) = component {
                        let planesize = c.get_data_size(video.width, video.height, ALIGNMENT);
                        let linesize = c.get_linesize(video.width, ALIGNMENT);
                        buffer.planes.push(Plane {
                            buf: buffer.buf.split_to(planesize),
                            linesize: linesize,
                        });
                    }
                }
                buffer
            },
            &Audio(ref audio) => {
                let size = audio.size(ALIGNMENT);
                let data = unsafe {
                    Global.alloc(Layout::from_size_align(size, ALIGNMENT).unwrap())
                        .unwrap()
                };
                let data = data.as_ptr() as *mut u8;
                let buf = BytesMut::from(unsafe { Vec::from_raw_parts(data, size, size) });
                let mut buffer = DefaultFrameBuffer {
                    buf: buf,
                    planes: Vec::new(),
                };
                for _ in 0..audio.map.len() {
                    let size = audio.format.get_audio_size(audio.samples, ALIGNMENT);
                    buffer.planes.push(Plane {
                        buf: buffer.buf.split_to(size),
                        linesize: size,
                    });
                }
                buffer
            },
        }
    }
}

pub type ArcFrame = Arc<Frame>;

pub fn new_default_frame<T>(kind: T, t: Option<TimeInfo>) -> Frame
where T: Into<MediaKind> + Clone
{
    let k = kind.into();
    let buf = DefaultFrameBuffer::new(&k);

    Frame {
        kind: k,
        buf: box buf,
        t: t.unwrap_or_default(),
    }
}

use std::ptr::copy_nonoverlapping;

fn copy_plane(
    dst: &mut [u8],
    dst_linesize: usize,
    src: &[u8],
    src_linesize: usize,
    w: usize,
    h: usize,
) {
    let dst_chunks = dst.chunks_mut(dst_linesize);
    let src_chunks = src.chunks(src_linesize);

    for (d, s) in dst_chunks.zip(src_chunks).take(h) {
        unsafe {
            copy_nonoverlapping(s.as_ptr(), d.as_mut_ptr(), w);
        }
    }
}

fn copy_image<'a, IM, IU, I>(
    dst: IM,
    dst_linesizes: IU,
    src: I,
    src_linesizes: IU,
    w: usize,
    h: usize,
    fmt: &Formaton,
) where
    IM: Iterator<Item = &'a mut [u8]>,
    I: Iterator<Item = &'a [u8]>,
    IU: Iterator<Item = usize>,
{
    let dst_iter = dst.zip(dst_linesizes);
    let src_iter = src.zip(src_linesizes);
    let iter = dst_iter.zip(src_iter).zip(fmt.iter());

    for (((d, d_linesize), (s, s_linesize)), c) in iter {
        copy_plane(
            d,
            d_linesize,
            s,
            s_linesize,
            c.unwrap().get_width(w),
            c.unwrap().get_height(h),
        );
    }
}

// TODO: Add proper tests
fn copy_to_frame<'a, I, IU>(dst: &mut Frame, mut src: I, mut src_linesize: IU, w: usize, h: usize)
where
    I: Iterator<Item = &'a [u8]>,
    IU: Iterator<Item = usize>,
{
    if let MediaKind::Video(ref fmt) = dst.kind {
        let mut f_iter = fmt.format.iter();
        let w = fmt.width;
        let h = fmt.height;
        for i in 0..dst.buf.count() {
            let d_linesize = dst.buf.linesize(i).unwrap();
            let s_linesize = src_linesize.next().unwrap();
            let d = dst.buf.as_mut_slice(i).unwrap();
            let s = src.next().unwrap();
            let c = f_iter.next().unwrap();
            copy_plane(
                d,
                d_linesize,
                s,
                s_linesize,
                c.unwrap().get_width(w),
                c.unwrap().get_height(h),
            );
        }
    } else {
        unimplemented!();
    }
}

use std::mem;
use std::slice;

// TODO make it a separate trait
impl Frame {
    pub fn copy_from_slice<'a, I, IU>(&mut self, mut src: I, mut src_linesize: IU)
    where
        I: Iterator<Item = &'a [u8]>,
        IU: Iterator<Item = usize>,
    {
        if let MediaKind::Video(ref fmt) = self.kind {
            let mut f_iter = fmt.format.iter();
            let w = fmt.width;
            let h = fmt.height;
            for i in 0..self.buf.count() {
                let d_linesize = self.buf.linesize(i).unwrap();
                let s_linesize = src_linesize.next().unwrap();
                let d = self.buf.as_mut_slice(i).unwrap();
                let s = src.next().unwrap();
                let c = f_iter.next().unwrap();
                copy_plane(
                    d,
                    d_linesize,
                    s,
                    s_linesize,
                    c.unwrap().get_width(w),
                    c.unwrap().get_height(h),
                );
            }
        } else {
            unimplemented!();
        }
    }

    pub fn copy_from_raw_parts<'a, I, IU>(&mut self, mut src: I, mut src_linesize: IU)
    where
        I: Iterator<Item = *const u8>,
        IU: Iterator<Item = usize>,
    {
        if let MediaKind::Video(ref fmt) = self.kind {
            let mut f_iter = fmt.format.iter();
            let w = fmt.width;
            let h = fmt.height;
            for i in 0..self.buf.count() {
                let d_linesize = self.buf.linesize(i).unwrap();
                let s_linesize = src_linesize.next().unwrap();
                let d = self.buf.as_mut_slice(i).unwrap();
                let c = f_iter.next().unwrap();
                let r = src.next().unwrap();
                let hb = c.unwrap().get_height(h);
                let s = unsafe { slice::from_raw_parts(r, hb * s_linesize) };
                copy_plane(d, d_linesize, s, s_linesize, c.unwrap().get_width(w), hb);
                mem::forget(s);
            }
        } else {
            unimplemented!();
        }
    }
}

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

    #[test]
    fn test_format_cmp() {
        let mut map = ChannelMap::new();
        map.add_channel(ChannelType::C);
        let sn = Arc::new(formats::S16);
        let info1 = AudioInfo{samples: 42, rate: 48000, map: map.clone(), format: sn};
        let sn = Arc::new(formats::S16);
        let info2 = AudioInfo{samples: 4242, rate: 48000, map: map.clone(), format: sn};

        assert_eq!(info1 == info2, true);

        let mut map = ChannelMap::new();
        map.add_channel(ChannelType::C);
        let sn = Arc::new(formats::S16);
        let info1 = AudioInfo{samples: 42, rate: 48000, map: map.clone(), format: sn};
        let sn = Arc::new(formats::S32);
        let info2 = AudioInfo{samples: 42, rate: 48000, map: map.clone(), format: sn};

        assert_eq!(info1 == info2, false);
    }
}
<commit_msg>data: Compare VideoInfo without picture type<commit_after>#![allow(dead_code, unused_variables)]
use alloc::alloc::{Global, Alloc, Layout};
use bytes::BytesMut;

use std::sync::Arc;

use audiosample::*;
use pixel::*;
use timeinfo::*;

use byte_slice_cast::*;

#[derive(Fail, Debug)]
pub enum FrameError {
    #[fail(display = "Invalid Index")]
    InvalidIndex,
    #[fail(display = "Invalid Conversion")]
    InvalidConversion,
}

use self::FrameError::*;

// TODO: Document
// TODO: Change it to provide Droppable/Seekable information or use a separate enum?
#[derive(Clone, Debug, PartialEq)]
pub enum PictureType {
    UNKNOWN,
    I,
    P,
    B,
    S,
    SI,
    SP,
    SB,
    BI,
}

#[derive(Clone, Debug)]
pub struct VideoInfo {
    pub pic_type: PictureType,
    pub width: usize,
    pub height: usize,
    pub format: Arc<Formaton>,
}

impl VideoInfo {
    fn size(&self, align: usize) -> usize {
        let mut size = 0;
        for &component in self.format.into_iter() {
            if let Some(c) = component {
                size += c.get_data_size(self.width, self.height, align);
            }
        }
        size
    }
}

#[derive(Clone, Debug)]
pub struct AudioInfo {
    pub samples: usize,
    pub rate: usize,
    pub map: ChannelMap,
    pub format: Arc<Soniton>,
}

impl AudioInfo {
    fn size(&self, align: usize) -> usize {
        self.format.get_audio_size(self.samples, align) * self.map.len()
    }
}

impl PartialEq for AudioInfo {

    fn eq(&self, info2: &AudioInfo) -> bool {
        self.rate == info2.rate && self.map == info2.map && self.format == info2.format
    }
}

impl PartialEq for VideoInfo {

    fn eq(&self, info2: &VideoInfo) -> bool {
        self.width == info2.width && self.height == info2.height && self.format == info2.format
    }
}

#[derive(Clone, Debug, PartialEq)]
pub enum MediaKind {
    Video(VideoInfo),
    Audio(AudioInfo),
}

use std::convert::From;

impl From<VideoInfo> for MediaKind {
    fn from(v: VideoInfo) -> Self {
        MediaKind::Video(v)
    }
}

impl From<AudioInfo> for MediaKind {
    fn from(a: AudioInfo) -> Self {
        MediaKind::Audio(a)
    }
}

use self::MediaKind::*;

pub trait FrameBuffer : Send + Sync {
    fn linesize(&self, idx: usize) -> Result<usize, FrameError>;
    fn count(&self) -> usize;
    fn as_slice_inner<'a>(&'a self, idx: usize) -> Result<&'a [u8], FrameError>;
    fn as_mut_slice_inner<'a>(&'a mut self, idx: usize) -> Result<&'a mut [u8], FrameError>;
}

mod private {
    use byte_slice_cast::*;

    pub trait Supported: FromByteSlice {}
    impl Supported for u8 {}
    impl Supported for i16 {}
    impl Supported for f32 {}
}

pub trait FrameBufferConv<T: private::Supported> : FrameBuffer {
    fn as_slice<'a>(&'a self, idx: usize) -> Result<&'a [T], FrameError> {
        self.as_slice_inner(idx)?.as_slice_of::<T>().map_err(|e| InvalidConversion)
    }
    fn as_mut_slice<'a>(&'a mut self, idx: usize) -> Result<&'a mut [T], FrameError> {
        self.as_mut_slice_inner(idx)?.as_mut_slice_of::<T>().map_err(|e| InvalidConversion)
    }
}

impl FrameBufferConv<u8> for FrameBuffer {}
impl FrameBufferConv<i16> for FrameBuffer {}
impl FrameBufferConv<f32> for FrameBuffer {}

use std::fmt;

impl fmt::Debug for FrameBuffer {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "FrameBuffer")
    }
}

#[derive(Debug)]
pub struct Frame {
    pub kind: MediaKind,
    pub buf: Box<FrameBuffer>,
    pub t: TimeInfo,
}

const ALIGNMENT: usize = 32;

struct Plane {
    buf: BytesMut,
    linesize: usize,
}

struct DefaultFrameBuffer {
    buf: BytesMut,
    planes: Vec<Plane>,
}

impl FrameBuffer for DefaultFrameBuffer {
    fn linesize(&self, idx: usize) -> Result<usize, FrameError> {
        match self.planes.get(idx) {
            None => Err(InvalidIndex),
            Some(plane) => Ok(plane.linesize),
        }
    }
    fn count(&self) -> usize {
        self.planes.len()
    }

    fn as_slice_inner<'a>(&'a self, idx: usize) -> Result<&'a [u8], FrameError> {
        match self.planes.get(idx) {
            None => Err(InvalidIndex),
            Some(plane) => Ok(&plane.buf),
        }
    }
    fn as_mut_slice_inner<'a>(&'a mut self, idx: usize) -> Result<&'a mut [u8], FrameError> {
        match self.planes.get_mut(idx) {
            None => Err(InvalidIndex),
            Some(plane) => Ok(&mut plane.buf),
        }
    }
}

impl DefaultFrameBuffer {
    pub fn new<'a>(kind: &'a MediaKind) -> DefaultFrameBuffer {
        match kind {
            &Video(ref video) => {
                let size = video.size(ALIGNMENT);
                let data = unsafe {
                    Global.alloc(Layout::from_size_align(size, ALIGNMENT).unwrap())
                        .unwrap()
                };
                let data = data.as_ptr() as *mut u8;
                //let data = unsafe { Heap.alloc_zeroed(Layout::from_size_align(size, ALIGNMENT)) };
                let buf = BytesMut::from(unsafe { Vec::from_raw_parts(data, size, size) });
                let mut buffer = DefaultFrameBuffer {
                    buf: buf,
                    planes: Vec::new(),
                };
                for &component in video.format.iter() {
                    if let Some(c) = component {
                        let planesize = c.get_data_size(video.width, video.height, ALIGNMENT);
                        let linesize = c.get_linesize(video.width, ALIGNMENT);
                        buffer.planes.push(Plane {
                            buf: buffer.buf.split_to(planesize),
                            linesize: linesize,
                        });
                    }
                }
                buffer
            },
            &Audio(ref audio) => {
                let size = audio.size(ALIGNMENT);
                let data = unsafe {
                    Global.alloc(Layout::from_size_align(size, ALIGNMENT).unwrap())
                        .unwrap()
                };
                let data = data.as_ptr() as *mut u8;
                let buf = BytesMut::from(unsafe { Vec::from_raw_parts(data, size, size) });
                let mut buffer = DefaultFrameBuffer {
                    buf: buf,
                    planes: Vec::new(),
                };
                for _ in 0..audio.map.len() {
                    let size = audio.format.get_audio_size(audio.samples, ALIGNMENT);
                    buffer.planes.push(Plane {
                        buf: buffer.buf.split_to(size),
                        linesize: size,
                    });
                }
                buffer
            },
        }
    }
}

pub type ArcFrame = Arc<Frame>;

pub fn new_default_frame<T>(kind: T, t: Option<TimeInfo>) -> Frame
where T: Into<MediaKind> + Clone
{
    let k = kind.into();
    let buf = DefaultFrameBuffer::new(&k);

    Frame {
        kind: k,
        buf: box buf,
        t: t.unwrap_or_default(),
    }
}

use std::ptr::copy_nonoverlapping;

fn copy_plane(
    dst: &mut [u8],
    dst_linesize: usize,
    src: &[u8],
    src_linesize: usize,
    w: usize,
    h: usize,
) {
    let dst_chunks = dst.chunks_mut(dst_linesize);
    let src_chunks = src.chunks(src_linesize);

    for (d, s) in dst_chunks.zip(src_chunks).take(h) {
        unsafe {
            copy_nonoverlapping(s.as_ptr(), d.as_mut_ptr(), w);
        }
    }
}

fn copy_image<'a, IM, IU, I>(
    dst: IM,
    dst_linesizes: IU,
    src: I,
    src_linesizes: IU,
    w: usize,
    h: usize,
    fmt: &Formaton,
) where
    IM: Iterator<Item = &'a mut [u8]>,
    I: Iterator<Item = &'a [u8]>,
    IU: Iterator<Item = usize>,
{
    let dst_iter = dst.zip(dst_linesizes);
    let src_iter = src.zip(src_linesizes);
    let iter = dst_iter.zip(src_iter).zip(fmt.iter());

    for (((d, d_linesize), (s, s_linesize)), c) in iter {
        copy_plane(
            d,
            d_linesize,
            s,
            s_linesize,
            c.unwrap().get_width(w),
            c.unwrap().get_height(h),
        );
    }
}

// TODO: Add proper tests
fn copy_to_frame<'a, I, IU>(dst: &mut Frame, mut src: I, mut src_linesize: IU, w: usize, h: usize)
where
    I: Iterator<Item = &'a [u8]>,
    IU: Iterator<Item = usize>,
{
    if let MediaKind::Video(ref fmt) = dst.kind {
        let mut f_iter = fmt.format.iter();
        let w = fmt.width;
        let h = fmt.height;
        for i in 0..dst.buf.count() {
            let d_linesize = dst.buf.linesize(i).unwrap();
            let s_linesize = src_linesize.next().unwrap();
            let d = dst.buf.as_mut_slice(i).unwrap();
            let s = src.next().unwrap();
            let c = f_iter.next().unwrap();
            copy_plane(
                d,
                d_linesize,
                s,
                s_linesize,
                c.unwrap().get_width(w),
                c.unwrap().get_height(h),
            );
        }
    } else {
        unimplemented!();
    }
}

use std::mem;
use std::slice;

// TODO make it a separate trait
impl Frame {
    pub fn copy_from_slice<'a, I, IU>(&mut self, mut src: I, mut src_linesize: IU)
    where
        I: Iterator<Item = &'a [u8]>,
        IU: Iterator<Item = usize>,
    {
        if let MediaKind::Video(ref fmt) = self.kind {
            let mut f_iter = fmt.format.iter();
            let w = fmt.width;
            let h = fmt.height;
            for i in 0..self.buf.count() {
                let d_linesize = self.buf.linesize(i).unwrap();
                let s_linesize = src_linesize.next().unwrap();
                let d = self.buf.as_mut_slice(i).unwrap();
                let s = src.next().unwrap();
                let c = f_iter.next().unwrap();
                copy_plane(
                    d,
                    d_linesize,
                    s,
                    s_linesize,
                    c.unwrap().get_width(w),
                    c.unwrap().get_height(h),
                );
            }
        } else {
            unimplemented!();
        }
    }

    pub fn copy_from_raw_parts<'a, I, IU>(&mut self, mut src: I, mut src_linesize: IU)
    where
        I: Iterator<Item = *const u8>,
        IU: Iterator<Item = usize>,
    {
        if let MediaKind::Video(ref fmt) = self.kind {
            let mut f_iter = fmt.format.iter();
            let w = fmt.width;
            let h = fmt.height;
            for i in 0..self.buf.count() {
                let d_linesize = self.buf.linesize(i).unwrap();
                let s_linesize = src_linesize.next().unwrap();
                let d = self.buf.as_mut_slice(i).unwrap();
                let c = f_iter.next().unwrap();
                let r = src.next().unwrap();
                let hb = c.unwrap().get_height(h);
                let s = unsafe { slice::from_raw_parts(r, hb * s_linesize) };
                copy_plane(d, d_linesize, s, s_linesize, c.unwrap().get_width(w), hb);
                mem::forget(s);
            }
        } else {
            unimplemented!();
        }
    }
}

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

    #[test]
    fn test_format_cmp() {
        let mut map = ChannelMap::new();
        map.add_channel(ChannelType::C);
        let sn = Arc::new(formats::S16);
        let info1 = AudioInfo{samples: 42, rate: 48000, map: map.clone(), format: sn};
        let sn = Arc::new(formats::S16);
        let info2 = AudioInfo{samples: 4242, rate: 48000, map: map.clone(), format: sn};

        assert_eq!(info1 == info2, true);

        let mut map = ChannelMap::new();
        map.add_channel(ChannelType::C);
        let sn = Arc::new(formats::S16);
        let info1 = AudioInfo{samples: 42, rate: 48000, map: map.clone(), format: sn};
        let sn = Arc::new(formats::S32);
        let info2 = AudioInfo{samples: 42, rate: 48000, map: map.clone(), format: sn};

        assert_eq!(info1 == info2, false);
    }

    use pixel::formats::{RGB565, YUV420};

    #[test]
    fn test_video_format_cmp() {
        let yuv420: Formaton = *YUV420;
        let fm = Arc::new(yuv420);
        let info1 = VideoInfo{pic_type: PictureType::I, width: 42, height: 42, format: fm};
        let yuv420: Formaton = *YUV420;
        let fm = Arc::new(yuv420);
        let info2 = VideoInfo{pic_type: PictureType::P, width: 42, height: 42, format: fm};

        assert_eq!(info1 == info2, true);

        let yuv420: Formaton = *YUV420;
        let fm = Arc::new(yuv420);
        let info1 = VideoInfo{pic_type: PictureType::I, width: 42, height: 42, format: fm};
        let rgb565: Formaton = *RGB565;
        let fm = Arc::new(rgb565);
        let info2 = VideoInfo{pic_type: PictureType::I, width: 42, height: 42, format: fm};

        assert_eq!(info1 == info2, false);
    }
}
<|endoftext|>