<commit_before>use ::*;
use relm::{Relm, RemoteRelm, Widget};
use gtk::prelude::*;
use gtk::{Window, WindowType, DrawingArea, Button, ScrolledWindow};
use tokio_core::reactor::Interval;
use std::time::Duration;

use map::*;

#[derive(Clone)]
pub struct Model {}

use self::Msg::*;

#[derive(SimpleMsg)]
pub enum Msg {
    Tick,
    Quit,
}

#[derive(Clone)]
pub struct Win {
    hbox: gtk::Box,
    button_box: gtk::ButtonBox,
    pause_button: Button,
    next_button: Button,
    clear_button: Button,
    zoom_in_button: Button,
    zoom_out_button: Button,
    area: DrawingArea,
    scroller: ScrolledWindow,
    window: Window,
}

impl Widget for Win {
    type Root = Window;
    type Model = Model;
    type Msg = Msg;

    fn root(&self) -> &Self::Root {
        &self.window
    }

    fn model() -> Self::Model {
        Model {
        }
    }

    fn subscriptions(relm: &Relm<Msg>) {
        let stream = Interval::new(Duration::from_secs(1), relm.handle()).unwrap();
        relm.connect_exec_ignore_err(stream, Tick);
    }

    fn update(&mut self, event: Msg, _model: &mut Self::Model) {
        match event {
            Tick => {
                println!("asdf");
            }
            Quit => gtk::main_quit()
        }
    }

    fn view(relm: RemoteRelm<Msg>, model: &Self::Model) -> Self {
        let window = Window::new(WindowType::Toplevel);
        let hbox = gtk::Box::new(gtk::Orientation::Horizontal, 0);
        let button_box = gtk::ButtonBox::new(gtk::Orientation::Vertical);
        let pause_button = Button::new_with_label("Start");
        let random_button = Button::new_with_label("Randomize");
        let next_button = Button::new_with_label("Next");
        let clear_button = Button::new_with_label("Clear");
        let zoom_in_button = Button::new_with_label("Zoom in");
        let zoom_out_button = Button::new_with_label("Zoom out");
        let area = DrawingArea::new();
        let scroller = ScrolledWindow::new(None, None);
        scroller.set_size_request(600, 600);
        // disable auto-hide scrollbar
        scroller.set_overlay_scrolling(false);

        connect!(relm, window, connect_delete_event(_, _) (Some(Msg::Quit), Inhibit(false)));

        button_box.set_layout(gtk::ButtonBoxStyle::Start);
        button_box.pack_start(&pause_button, false, false, 0);
        button_box.pack_start(&next_button, false, false, 0);
        button_box.pack_start(&random_button, false, false, 0);
        button_box.pack_start(&clear_button, false, false, 0);
        button_box.pack_start(&zoom_in_button, false, false, 0);
        button_box.pack_start(&zoom_out_button, false, false, 0);
        scroller.add(&area);
        hbox.pack_start(&scroller, false, false, 0);
        hbox.pack_start(&button_box, false, false, 0);
        window.add(&hbox);
        window.set_title("Game of Life");
        window.show_all();
        Win {
            hbox: hbox,
            button_box: button_box,
            pause_button: pause_button,
            next_button: next_button,
            clear_button: clear_button,
            zoom_in_button: zoom_in_button,
            zoom_out_button: zoom_out_button,
            area: area,
            scroller: scroller,
            window: window,
        }
    }
}
<commit_msg>Strange worked behavior<commit_after>use ::*;
use relm::{Relm, RemoteRelm, Widget};
use gtk::prelude::*;
use gtk::{Window, WindowType, DrawingArea, Button, ScrolledWindow};
use tokio_core::reactor::Interval;
use std::time::Duration;

use map::*;

#[derive(Clone)]
pub struct Model {}

#[derive(SimpleMsg)]
pub enum Msg {
    Tick,
    Quit,
}

#[derive(Clone)]
pub struct Win {
    hbox: gtk::Box,
    button_box: gtk::ButtonBox,
    pause_button: Button,
    next_button: Button,
    clear_button: Button,
    zoom_in_button: Button,
    zoom_out_button: Button,
    area: DrawingArea,
    scroller: ScrolledWindow,
    window: Window,
}

impl Widget for Win {
    type Root = Window;
    type Model = Model;
    type Msg = Msg;

    fn root(&self) -> &Self::Root {
        &self.window
    }

    fn model() -> Self::Model {
        Model {
        }
    }

    fn subscriptions(relm: &Relm<Msg>) {
        let stream = Interval::new(Duration::from_secs(1), relm.handle()).unwrap();
        relm.connect_exec_ignore_err(stream, Msg::Tick);
    }

    fn update(&mut self, event: Msg, _model: &mut Self::Model) {
        match event {
            Msg::Tick => {
                println!("asdf");
            }
            Msg::Quit => gtk::main_quit()
        }
    }

    fn view(relm: RemoteRelm<Msg>, model: &Self::Model) -> Self {
        let window = Window::new(WindowType::Toplevel);
        let hbox = gtk::Box::new(gtk::Orientation::Horizontal, 0);
        let button_box = gtk::ButtonBox::new(gtk::Orientation::Vertical);
        let pause_button = Button::new_with_label("Start");
        let random_button = Button::new_with_label("Randomize");
        let next_button = Button::new_with_label("Next");
        let clear_button = Button::new_with_label("Clear");
        let zoom_in_button = Button::new_with_label("Zoom in");
        let zoom_out_button = Button::new_with_label("Zoom out");
        let area = DrawingArea::new();
        let scroller = ScrolledWindow::new(None, None);
        scroller.set_size_request(600, 600);
        // disable auto-hide scrollbar
        scroller.set_overlay_scrolling(false);

        connect!(relm, window, connect_delete_event(_, _) (Some(Msg::Quit), Inhibit(false)));

        button_box.set_layout(gtk::ButtonBoxStyle::Start);
        button_box.pack_start(&pause_button, false, false, 0);
        button_box.pack_start(&next_button, false, false, 0);
        button_box.pack_start(&random_button, false, false, 0);
        button_box.pack_start(&clear_button, false, false, 0);
        button_box.pack_start(&zoom_in_button, false, false, 0);
        button_box.pack_start(&zoom_out_button, false, false, 0);
        scroller.add(&area);
        hbox.pack_start(&scroller, false, false, 0);
        hbox.pack_start(&button_box, false, false, 0);
        window.add(&hbox);
        window.set_title("Game of Life");
        window.show_all();
        Win {
            hbox: hbox,
            button_box: button_box,
            pause_button: pause_button,
            next_button: next_button,
            clear_button: clear_button,
            zoom_in_button: zoom_in_button,
            zoom_out_button: zoom_out_button,
            area: area,
            scroller: scroller,
            window: window,
        }
    }
}
<|endoftext|>


<commit_before>// Copyright lowRISC contributors.
// Licensed under the Apache License, Version 2.0, see LICENSE for details.
// SPDX-License-Identifier: Apache-2.0

use anyhow::Result;
use regex::{Captures, Regex};
use std::fs::File;
use std::io::{Read, Write};
use std::os::unix::io::AsRawFd;
use std::time::{Duration, Instant, SystemTime};

use crate::io::uart::Uart;
use crate::util::file;

#[derive(Default)]
pub struct UartConsole {
    pub logfile: Option<File>,
    pub timeout: Option<Duration>,
    pub deadline: Option<Instant>,
    pub exit_success: Option<Regex>,
    pub exit_failure: Option<Regex>,
    pub timestamp: bool,
    pub buffer: String,
    pub newline: bool,
}

#[derive(Clone, Copy, Debug)]
pub enum ExitStatus {
    None,
    CtrlC,
    Timeout,
    ExitSuccess,
    ExitFailure,
}

// Creates a vtable for impementors of Read and AsRawFd traits.
pub trait ReadAsRawFd: Read + AsRawFd {}
impl<T: Read + AsRawFd> ReadAsRawFd for T {}

impl UartConsole {
    const CTRL_C: u8 = 3;
    const BUFFER_LEN: usize = 1024;

    // Runs an interactive console until CTRL_C is received.
    pub fn interact(
        &mut self,
        uart: &dyn Uart,
        mut stdin: Option<&mut dyn ReadAsRawFd>,
        mut stdout: Option<&mut dyn Write>,
    ) -> Result<ExitStatus> {
        if let Some(timeout) = &self.timeout {
            self.deadline = Some(Instant::now() + *timeout);
        }
        loop {
            match self.interact_once(uart, &mut stdin, &mut stdout)? {
                ExitStatus::None => {}
                status => return Ok(status),
            }
        }
    }

    // Maintain a buffer for the exit regexes to match against.
    fn append_buffer(&mut self, data: &[u8]) {
        self.buffer.push_str(&String::from_utf8_lossy(data));
        while self.buffer.len() > UartConsole::BUFFER_LEN {
            self.buffer.remove(0);
        }
    }

    // Read from the uart and process the data read.
    fn uart_read(
        &mut self,
        uart: &dyn Uart,
        timeout: Duration,
        stdout: &mut Option<&mut dyn Write>,
    ) -> Result<()> {
        let mut buf = [0u8; 256];
        let len = uart.read_timeout(&mut buf, timeout)?;
        if len == 0 {
            return Ok(());
        }
        for i in 0..len {
            if self.timestamp && self.newline {
                let t = humantime::format_rfc3339_millis(SystemTime::now());
                stdout
                    .as_mut()
                    .map_or(Ok(()), |out| out.write_fmt(format_args!("[{}]", t)))?;
                self.newline = false;
            }
            stdout
                .as_mut()
                .map_or(Ok(()), |out| out.write_all(&buf[i..i + 1]))?;
            self.newline = buf[i] == b'\n';
        }
        stdout.as_mut().map_or(Ok(()), |out| out.flush())?;

        // If we're logging, save it to the logfile.
        self.logfile
            .as_mut()
            .map_or(Ok(()), |f| f.write_all(&buf[..len]))?;
        self.append_buffer(&buf[..len]);
        Ok(())
    }

    fn process_input(
        &self,
        uart: &dyn Uart,
        stdin: &mut Option<&mut (dyn ReadAsRawFd)>,
    ) -> Result<ExitStatus> {
        if let Some(ref mut input) = stdin.as_mut() {
            if file::wait_fd_read_timeout(input.as_raw_fd(), Duration::from_millis(0)).is_ok() {
                let mut buf = [0u8; 256];
                let len = input.read(&mut buf)?;
                if len == 1 && buf[0] == UartConsole::CTRL_C {
                    return Ok(ExitStatus::CtrlC);
                }
                uart.write(&buf[..len])?;
            }
        }
        Ok(ExitStatus::None)
    }

    pub fn interact_once(
        &mut self,
        uart: &dyn Uart,
        stdin: &mut Option<&mut (dyn ReadAsRawFd)>,
        stdout: &mut Option<&mut dyn Write>,
    ) -> Result<ExitStatus> {
        if let Some(deadline) = &self.deadline {
            if Instant::now() > *deadline {
                return Ok(ExitStatus::Timeout);
            }
        }
        // This _should_ really use unix `poll` in the conventional way
        // to learn when the console or uart file descriptors become ready,
        // but some UART backends will bury their implementation in libusb
        // and make discovering the file descriptor difficult or impossible.
        //
        // As a pragmatic implementation detail, we wait for the UART
        // for a short period of time and then service the console.
        //
        // TODO: as we write more backends, re-evaluate whether there is a
        // better way to approach waiting on the UART and keyboard.

        // Check for input on the uart.
        self.uart_read(uart, Duration::from_millis(10), stdout)?;
        if self
            .exit_success
            .as_ref()
            .map(|rx| rx.is_match(&self.buffer))
            == Some(true)
        {
            return Ok(ExitStatus::ExitSuccess);
        }
        if self
            .exit_failure
            .as_ref()
            .map(|rx| rx.is_match(&self.buffer))
            == Some(true)
        {
            return Ok(ExitStatus::ExitFailure);
        }
        self.process_input(uart, stdin)
    }

    pub fn captures(&self, status: ExitStatus) -> Option<Captures> {
        match status {
            ExitStatus::ExitSuccess => self
                .exit_success
                .as_ref()
                .map(|rx| rx.captures(&self.buffer))
                .flatten(),
            ExitStatus::ExitFailure => self
                .exit_failure
                .as_ref()
                .map(|rx| rx.captures(&self.buffer))
                .flatten(),
            _ => None,
        }
    }
}
<commit_msg>[ottool] Handle line endings in the console<commit_after>// Copyright lowRISC contributors.
// Licensed under the Apache License, Version 2.0, see LICENSE for details.
// SPDX-License-Identifier: Apache-2.0

use anyhow::Result;
use regex::{Captures, Regex};
use std::fs::File;
use std::io::{Read, Write};
use std::os::unix::io::AsRawFd;
use std::time::{Duration, Instant, SystemTime};

use crate::io::uart::Uart;
use crate::util::file;

#[derive(Default)]
pub struct UartConsole {
    pub logfile: Option<File>,
    pub timeout: Option<Duration>,
    pub deadline: Option<Instant>,
    pub exit_success: Option<Regex>,
    pub exit_failure: Option<Regex>,
    pub timestamp: bool,
    pub buffer: String,
    pub newline: bool,
}

#[derive(Clone, Copy, Debug)]
pub enum ExitStatus {
    None,
    CtrlC,
    Timeout,
    ExitSuccess,
    ExitFailure,
}

// Creates a vtable for impementors of Read and AsRawFd traits.
pub trait ReadAsRawFd: Read + AsRawFd {}
impl<T: Read + AsRawFd> ReadAsRawFd for T {}

impl UartConsole {
    const CTRL_C: u8 = 3;
    const BUFFER_LEN: usize = 1024;

    // Runs an interactive console until CTRL_C is received.
    pub fn interact(
        &mut self,
        uart: &dyn Uart,
        mut stdin: Option<&mut dyn ReadAsRawFd>,
        mut stdout: Option<&mut dyn Write>,
    ) -> Result<ExitStatus> {
        if let Some(timeout) = &self.timeout {
            self.deadline = Some(Instant::now() + *timeout);
        }
        loop {
            match self.interact_once(uart, &mut stdin, &mut stdout)? {
                ExitStatus::None => {}
                status => return Ok(status),
            }
        }
    }

    // Maintain a buffer for the exit regexes to match against.
    fn append_buffer(&mut self, data: &[u8]) {
        self.buffer.push_str(&String::from_utf8_lossy(data));
        while self.buffer.len() > UartConsole::BUFFER_LEN {
            self.buffer.remove(0);
        }
    }

    // Read from the uart and process the data read.
    fn uart_read(
        &mut self,
        uart: &dyn Uart,
        timeout: Duration,
        stdout: &mut Option<&mut dyn Write>,
    ) -> Result<()> {
        let mut buf = [0u8; 256];
        let len = uart.read_timeout(&mut buf, timeout)?;
        if len == 0 {
            return Ok(());
        }
        for i in 0..len {
            if self.timestamp && self.newline {
                let t = humantime::format_rfc3339_millis(SystemTime::now());
                stdout
                    .as_mut()
                    .map_or(Ok(()), |out| out.write_fmt(format_args!("[{}]", t)))?;
                self.newline = false;
            }
            self.newline = buf[i] == b'\n';
            stdout.as_mut().map_or(Ok(()), |out| {
                out.write_all(if self.newline {
                    b"\r\n"
                } else {
                    &buf[i..i + 1]
                })
            })?;
        }
        stdout.as_mut().map_or(Ok(()), |out| out.flush())?;

        // If we're logging, save it to the logfile.
        self.logfile
            .as_mut()
            .map_or(Ok(()), |f| f.write_all(&buf[..len]))?;
        self.append_buffer(&buf[..len]);
        Ok(())
    }

    fn process_input(
        &self,
        uart: &dyn Uart,
        stdin: &mut Option<&mut (dyn ReadAsRawFd)>,
    ) -> Result<ExitStatus> {
        if let Some(ref mut input) = stdin.as_mut() {
            if file::wait_fd_read_timeout(input.as_raw_fd(), Duration::from_millis(0)).is_ok() {
                let mut buf = [0u8; 256];
                let len = input.read(&mut buf)?;
                if len == 1 && buf[0] == UartConsole::CTRL_C {
                    return Ok(ExitStatus::CtrlC);
                }
                uart.write(&buf[..len])?;
            }
        }
        Ok(ExitStatus::None)
    }

    pub fn interact_once(
        &mut self,
        uart: &dyn Uart,
        stdin: &mut Option<&mut (dyn ReadAsRawFd)>,
        stdout: &mut Option<&mut dyn Write>,
    ) -> Result<ExitStatus> {
        if let Some(deadline) = &self.deadline {
            if Instant::now() > *deadline {
                return Ok(ExitStatus::Timeout);
            }
        }
        // This _should_ really use unix `poll` in the conventional way
        // to learn when the console or uart file descriptors become ready,
        // but some UART backends will bury their implementation in libusb
        // and make discovering the file descriptor difficult or impossible.
        //
        // As a pragmatic implementation detail, we wait for the UART
        // for a short period of time and then service the console.
        //
        // TODO: as we write more backends, re-evaluate whether there is a
        // better way to approach waiting on the UART and keyboard.

        // Check for input on the uart.
        self.uart_read(uart, Duration::from_millis(10), stdout)?;
        if self
            .exit_success
            .as_ref()
            .map(|rx| rx.is_match(&self.buffer))
            == Some(true)
        {
            return Ok(ExitStatus::ExitSuccess);
        }
        if self
            .exit_failure
            .as_ref()
            .map(|rx| rx.is_match(&self.buffer))
            == Some(true)
        {
            return Ok(ExitStatus::ExitFailure);
        }
        self.process_input(uart, stdin)
    }

    pub fn captures(&self, status: ExitStatus) -> Option<Captures> {
        match status {
            ExitStatus::ExitSuccess => self
                .exit_success
                .as_ref()
                .map(|rx| rx.captures(&self.buffer))
                .flatten(),
            ExitStatus::ExitFailure => self
                .exit_failure
                .as_ref()
                .map(|rx| rx.captures(&self.buffer))
                .flatten(),
            _ => None,
        }
    }
}
<|endoftext|>


<commit_before>use std::io::{FileAccess, FileMode, Open, Read, Truncate};
use std::io::{ReadWrite};
use std::io::{SeekEnd, SeekSet};
use std::io::fs::File;
use std::mem::size_of;

static version: u8 = 1;

// some definitions from kissdb.h

struct Kissdb {
  hash_table_size : u64,
  key_size : u64,
  value_size : u64,
  hash_tables : ~[u64],
  f : std::io::fs::File
}

enum Error {
  ErrorIO,
  ErrorMalloc,
  InvalidParameters,
  CorruptDbFile
}

enum OpenMode {
  ReadOnly,
  RW,
  RWCreate,
  RWReplace
}

fn kissdb_hash(b :&[u8], len: u64) -> u64
{
    let mut hash : u64 = 5381;
    for i in range (0, len) {
        hash = ((hash << 5) + hash) + (b[i] as u64);
    }
    return hash
}

// either
// 1. use the c95 based alloc, realloc and free
// 2. use more rustic something
// maybe trying 2. gives me more knowledge
fn kissdb_open(
    path : &Path,
    orig_mode : OpenMode,
    mut hash_table_size : u64,
    mut key_size : u64,
    mut value_size : u64
    ) -> Option<~ Kissdb>
{
    let (mode, access) : (FileMode, FileAccess) =
        match orig_mode {
            ReadOnly =>  (Open, Read), // rb
            RW => (Open, ReadWrite), // r+b
            RWCreate =>  (Open, ReadWrite), // r+b
            RWReplace => (Truncate, ReadWrite) // w+b
        };
    let mut f_ : Option<File>
        = std::io::fs::File::open_mode(path, mode, access);

    if f_.is_none() {
        match (orig_mode) {
            RWCreate =>
            f_ = std::io::fs::File::open_mode(path, Truncate, ReadWrite), // w+b
            _ => f_ = f_
        }
    };

    match f_ {
        None => return None,
        Some (mut f) =>
        {let kissdb_header_size : u64 = ((size_of::<u64>() * 3) + 4) as u64;

         f.seek(0, SeekEnd);
         if (f.tell() < kissdb_header_size) {
             if hash_table_size > 0 && key_size > 0
                 && value_size >0
             {
                 f.seek(0, SeekSet);
                 let tmp2 : [u8, ..4] = ['K' as u8, 'd' as u8, 'R' as u8, version];
                 f.write(tmp2);
                 f.write_le_u64(hash_table_size);
                 f.write_le_u64(key_size);
                 f.write_le_u64(value_size);
                 f.flush();
             }
             else {
                 fail!()
             }
         }
         else {
             f.seek(0, SeekSet);
             let mut tmp2 : [u8, ..4] = [0,0,0,0];
             if f.read(tmp2) != Some(4) { fail! (); }
             if tmp2 != ['K' as u8, 'd' as u8, 'R' as u8, version] {fail! ();}
             hash_table_size = f.read_le_u64();
             key_size = f.read_le_u64();
             value_size = f.read_le_u64();
         }

         // let hash_table_size_bytes : uint = size_of::<u64>() * (hash_table_size + 1) as uint;
         // let mut httmp = std::vec::from_elem(hash_table_size_bytes, 0 as u8);
         //         let httmp = do std::at_vec::build::<u64>(None) |push| { for i in range(0, hash_table_size + 1)
//                  { push (0); }
        //};

         let mut num_hash_tables = 0;

         // should use at_vec, actually
         // no, std::vec is OK.  It has appends
         let mut hash_tables : ~[u64] = std::vec::from_elem(0, 0 as u64);
         let mut h : Option<~[u64]>;

         // do we do realloc in rust? with append, apparently.
         while({h = f.read_one_hash_table(hash_table_size); h.is_some()})
         {
             let httmp = h.unwrap();
             hash_tables = std::vec::append(hash_tables, httmp);
             num_hash_tables = num_hash_tables + 1;
             if (httmp[hash_table_size] > 0) {
                 f.seek(httmp[hash_table_size] as i64, SeekSet)
             }
             else {
                 break;
             }
         }

         // construct h somehow
         return Some(~Kissdb {hash_table_size : hash_table_size,
                         key_size : key_size,
                         value_size : value_size,
                         hash_tables : hash_tables,
                         f : f})
        }
    }
}

trait File2 {
    fn read_one_hash_table(&mut self, u64) -> Option<~[u64]>;
}

impl File2 for File {
        fn read_one_hash_table(&mut self,
                               hash_table_size : u64) -> Option<~[u64]> {
            let bs = (hash_table_size + 1) as uint * size_of::<u64>();
            let mut buf = std::vec::from_elem(bs, 0 as u8);
            let mut result = std::vec::from_elem((hash_table_size + 1) as uint, 0 as u64);
            match self.read(buf) {
                None => None,
                Some(buf_size) if buf_size == bs => {
                    let mut br = std::io::mem::BufReader::new(buf);
                    for i in range(0, hash_table_size + 1) {
                        result[i] = br.read_le_u64();
                    }
                    Some((result))
                },
                _ => None
            }
        }
}

fn kissdb_close(~db : ~Kissdb) {
}

fn main()
{
    let db = kissdb_open(&Path::new("test.db"), RWReplace, 1024, 8, size_of::<u64>() as u64);
    kissdb_close(db.unwrap());
}
<commit_msg>somehow kissdb_open is working<commit_after>use std::io::{FileAccess, FileMode, Open, Read, Truncate};
use std::io::{ReadWrite};
use std::io::{SeekEnd, SeekSet};
use std::io::fs::File;
use std::mem::size_of;

static version: u8 = 1;

// some definitions from kissdb.h

struct Kissdb {
  hash_table_size : u64,
  key_size : u64,
  value_size : u64,
  hash_tables : ~[u64],
  f : std::io::fs::File
}

enum Error {
  ErrorIO,
  ErrorMalloc,
  InvalidParameters,
  CorruptDbFile
}

enum OpenMode {
  ReadOnly,
  RW,
  RWCreate,
  RWReplace
}

fn kissdb_hash(b :&[u8], len: u64) -> u64
{
    let mut hash : u64 = 5381;
    for i in range (0, len) {
        hash = ((hash << 5) + hash) + (b[i] as u64);
    }
    return hash
}

// either
// 1. use the c95 based alloc, realloc and free
// 2. use more rustic something
// maybe trying 2. gives me more knowledge
fn kissdb_open(
    path : &Path,
    orig_mode : OpenMode,
    mut hash_table_size : u64,
    mut key_size : u64,
    mut value_size : u64
    ) -> Option<~ Kissdb>
{
    let (mode, access) : (FileMode, FileAccess) =
        match orig_mode {
            ReadOnly =>  (Open, Read), // rb
            RW => (Open, ReadWrite), // r+b
            RWCreate =>  (Open, ReadWrite), // r+b
            RWReplace => (Truncate, ReadWrite) // w+b
        };
    let mut f_ : Option<File>
        = std::io::fs::File::open_mode(path, mode, access);

    if f_.is_none() {
        match (orig_mode) {
            RWCreate =>
            f_ = std::io::fs::File::open_mode(path, Truncate, ReadWrite), // w+b
            _ => f_ = f_
        }
    };

    match f_ {
        None => return None,
        Some (mut f) =>
        {let kissdb_header_size : u64 = ((size_of::<u64>() * 3) + 4) as u64;

         f.seek(0, SeekEnd);
         if (f.tell() < kissdb_header_size) {
             if hash_table_size > 0 && key_size > 0
                 && value_size >0
             {
                 f.seek(0, SeekSet);
                 let tmp2 : [u8, ..4] = ['K' as u8, 'd' as u8, 'R' as u8, version];
                 f.write(tmp2);
                 f.write_le_u64(hash_table_size);
                 f.write_le_u64(key_size);
                 f.write_le_u64(value_size);
                 f.flush();
             }
             else {
                 fail!()
             }
         }
         else {
             f.seek(0, SeekSet);
             let mut tmp2 : [u8, ..4] = [0,0,0,0];
             if f.read(tmp2) != Some(4) { fail! (); }
             if tmp2 != ['K' as u8, 'd' as u8, 'R' as u8, version] {fail! ();}
             hash_table_size = f.read_le_u64();
             key_size = f.read_le_u64();
             value_size = f.read_le_u64();
         }

         // let hash_table_size_bytes : uint = size_of::<u64>() * (hash_table_size + 1) as uint;
         // let mut httmp = std::vec::from_elem(hash_table_size_bytes, 0 as u8);
         //         let httmp = do std::at_vec::build::<u64>(None) |push| { for i in range(0, hash_table_size + 1)
//                  { push (0); }
        //};

         let mut num_hash_tables = 0;

         // should use at_vec, actually
         // no, std::vec is OK.  It has appends
         let mut hash_tables : ~[u64] = std::vec::from_elem(0, 0 as u64);
         let mut h : Option<~[u64]>;

         // do we do realloc in rust? with append, apparently.
         while({h = f.read_one_hash_table(hash_table_size); h.is_some()})
         {
             let httmp = h.unwrap();
             hash_tables = std::vec::append(hash_tables, httmp);
             num_hash_tables = num_hash_tables + 1;
             if (httmp[hash_table_size] > 0) {
                 f.seek(httmp[hash_table_size] as i64, SeekSet)
             }
             else {
                 break;
             }
         }

         // construct h somehow
         return Some(~Kissdb {hash_table_size : hash_table_size,
                         key_size : key_size,
                         value_size : value_size,
                         hash_tables : hash_tables,
                         f : f})
        }
    }
}

trait File2 {
    fn read_one_hash_table(&mut self, u64) -> Option<~[u64]>;
}

impl File2 for File {
        fn read_one_hash_table(&mut self,
                               hash_table_size : u64) -> Option<~[u64]> {
            let bs = (hash_table_size + 1) as uint * size_of::<u64>();
            let mut buf = std::vec::from_elem(bs, 0 as u8);
            let mut result = std::vec::from_elem((hash_table_size + 1) as uint, 0 as u64);
            match self.read(buf) {
                None => None,
                Some(buf_size) if buf_size == bs => {
                    let mut br = std::io::mem::BufReader::new(buf);
                    for i in range(0, hash_table_size + 1) {
                        result[i] = br.read_le_u64();
                    }
                    Some((result))
                },
                _ => None
            }
        }
}

fn kissdb_close(~db : ~Kissdb) {
}

fn main()
{
    let db = kissdb_open(&Path::new("test.db"), RWReplace, 1024, 8, size_of::<u64>() as u64);
    kissdb_close(db.unwrap());
    let db_r = kissdb_open(&Path::new("test.db"), ReadOnly, 4, 8, size_of::<u64>() as u64);
    let db_r = db_r.unwrap();
    println(db_r.hash_table_size.to_str());
}
<|endoftext|>


<commit_before>#[macro_use]
extern crate wlroots;

use wlroots::{Compositor, CompositorBuilder, InputManagerHandler, Keyboard, KeyboardHandler,
              Output, OutputBuilder, OutputBuilderResult, OutputHandler, OutputManagerHandler,
              Texture, TextureFormat, Touch, TouchHandler};
use wlroots::key_events::KeyEvent;
use wlroots::touch_events::{DownEvent, MotionEvent, UpEvent};
use wlroots::utils::{init_logging, L_DEBUG};
use wlroots::xkbcommon::xkb::keysyms::KEY_Escape;

const CAT_STRIDE: i32 = 128;
const CAT_WIDTH: i32 = 128;
const CAT_HEIGHT: i32 = 128;
const CAT_DATA: &'static [u8] = include_bytes!("cat.data");

#[derive(Debug, Clone)]
struct TouchPoint {
    touch_id: i32,
    x: f64,
    y: f64
}

struct State {
    cat_texture: Option<Texture>,
    touch_points: Vec<TouchPoint>
}

impl State {
    fn new() -> Self {
        State { cat_texture: None,
                touch_points: Vec::new() }
    }
}

compositor_data!(State);

struct TouchHandlerEx;

struct OutputManager;

struct ExOutput;

struct InputManager;

struct ExKeyboardHandler;

impl OutputManagerHandler for OutputManager {
    fn output_added<'output>(&mut self,
                             _compositor: &mut Compositor,
                             builder: OutputBuilder<'output>)
                             -> Option<OutputBuilderResult<'output>> {
        Some(builder.build_best_mode(ExOutput))
    }
}

impl KeyboardHandler for ExKeyboardHandler {
    fn on_key(&mut self, compositor: &mut Compositor, _: &mut Keyboard, key_event: &mut KeyEvent) {
        for key in key_event.pressed_keys() {
            if key == KEY_Escape {
                compositor.terminate()
            }
        }
    }
}

impl OutputHandler for ExOutput {
    fn on_frame(&mut self, compositor: &mut Compositor, output: &mut Output) {
        let renderer = compositor.renderer.as_mut().unwrap();
        let state: &mut State = (&mut compositor.data).downcast_mut().unwrap();
        // NOTE gl functions will probably always be unsafe.
        let (width, height) = output.effective_resolution();
        let transform_matrix = output.transform_matrix();
        let mut renderer = renderer.render(output);
        renderer.clear([0.25, 0.25, 0.25, 1.0]);
        let cat_texture = state.cat_texture.as_mut().unwrap();
        let (cat_width, cat_height) = cat_texture.size();
        for touch_point in &mut state.touch_points {
            let matrix =
                cat_texture.get_matrix(&transform_matrix,
                                       (touch_point.x * width as f64) as i32 - (cat_width / 2),
                                       (touch_point.y * height as f64) as i32 - (cat_height / 2));
            renderer.render_with_matrix(cat_texture, &matrix);
        }
    }
}

impl TouchHandler for TouchHandlerEx {
    fn on_down(&mut self, compositor: &mut Compositor, _touch: &mut Touch, event: &DownEvent) {
        let state: &mut State = compositor.into();
        let (width, height) = event.size();
        let (x, y) = event.location();
        let point = TouchPoint { touch_id: event.touch_id(),
                                 x: x / width,
                                 y: y / height };
        wlr_log!(L_ERROR, "New touch point at {:?}", point);
        state.touch_points.push(point)
    }

    fn on_up(&mut self, compositor: &mut Compositor, _touch: &mut Touch, event: &UpEvent) {
        let state: &mut State = compositor.into();
        wlr_log!(L_ERROR,
                 "Removing {:?} from {:#?}",
                 event.touch_id(),
                 state.touch_points);
        if let Some(index) = state.touch_points
                                  .iter()
                                  .position(|touch_point| touch_point.touch_id == event.touch_id())
        {
            state.touch_points.remove(index);
        }
    }

    fn on_motion(&mut self, compositor: &mut Compositor, _touch: &mut Touch, event: &MotionEvent) {
        let state: &mut State = compositor.into();
        let (width, height) = event.size();
        let (x, y) = event.location();
        wlr_log!(L_ERROR, "New location: {:?}", (x, y));
        for touch_point in &mut state.touch_points {
            if touch_point.touch_id == event.touch_id() {
                touch_point.x = x / width;
                touch_point.y = y / height;
            }
        }
    }
}

impl InputManagerHandler for InputManager {
    fn touch_added(&mut self, _: &mut Compositor, _: &mut Touch) -> Option<Box<TouchHandler>> {
        Some(Box::new(TouchHandlerEx))
    }
    fn keyboard_added(&mut self,
                      _: &mut Compositor,
                      _: &mut Keyboard)
                      -> Option<Box<KeyboardHandler>> {
        Some(Box::new(ExKeyboardHandler))
    }
}

fn main() {
    init_logging(L_DEBUG, None);
    let mut compositor = CompositorBuilder::new().gles2(true)
                                                 .input_manager(Box::new(InputManager))
                                                 .output_manager(Box::new(OutputManager))
                                                 .build_auto(State::new());
    {
        let gles2 = &mut compositor.renderer.as_mut().unwrap();
        let compositor_data: &mut State = (&mut compositor.data).downcast_mut().unwrap();
        compositor_data.cat_texture = gles2.create_texture().map(|mut cat_texture| {
            cat_texture.upload_pixels(TextureFormat::ABGR8888,
                                      CAT_STRIDE,
                                      CAT_WIDTH,
                                      CAT_HEIGHT,
                                      CAT_DATA);
            cat_texture
        });
    }
    compositor.run();
}
<commit_msg>Fixed touch example<commit_after>#[macro_use]
extern crate wlroots;

use wlroots::{Compositor, CompositorBuilder, InputManagerHandler, Keyboard, KeyboardHandler,
              Output, OutputBuilder, OutputBuilderResult, OutputHandler, OutputManagerHandler,
              Texture, TextureFormat, Touch, TouchHandler};
use wlroots::key_events::KeyEvent;
use wlroots::touch_events::{DownEvent, MotionEvent, UpEvent};
use wlroots::utils::{init_logging, L_DEBUG};
use wlroots::xkbcommon::xkb::keysyms::KEY_Escape;

const CAT_STRIDE: i32 = 128;
const CAT_WIDTH: i32 = 128;
const CAT_HEIGHT: i32 = 128;
const CAT_DATA: &'static [u8] = include_bytes!("cat.data");

#[derive(Debug, Clone)]
struct TouchPoint {
    touch_id: i32,
    x: f64,
    y: f64
}

struct State {
    cat_texture: Option<Texture>,
    touch_points: Vec<TouchPoint>
}

impl State {
    fn new() -> Self {
        State { cat_texture: None,
                touch_points: Vec::new() }
    }
}

compositor_data!(State);

struct TouchHandlerEx;

struct OutputManager;

struct ExOutput;

struct InputManager;

struct ExKeyboardHandler;

impl OutputManagerHandler for OutputManager {
    fn output_added<'output>(&mut self,
                             _compositor: &mut Compositor,
                             builder: OutputBuilder<'output>)
                             -> Option<OutputBuilderResult<'output>> {
        Some(builder.build_best_mode(ExOutput))
    }
}

impl KeyboardHandler for ExKeyboardHandler {
    fn on_key(&mut self, compositor: &mut Compositor, _: &mut Keyboard, key_event: &mut KeyEvent) {
        for key in key_event.pressed_keys() {
            if key == KEY_Escape {
                compositor.terminate()
            }
        }
    }
}

impl OutputHandler for ExOutput {
    fn on_frame(&mut self, compositor: &mut Compositor, output: &mut Output) {
        let renderer = compositor.renderer.as_mut().unwrap();
        let state: &mut State = (&mut compositor.data).downcast_mut().unwrap();
        // NOTE gl functions will probably always be unsafe.
        let (width, height) = output.effective_resolution();
        let transform_matrix = output.transform_matrix();
        let mut renderer = renderer.render(output);
        renderer.clear([0.25, 0.25, 0.25, 1.0]);
        let cat_texture = state.cat_texture.as_mut().unwrap();
        let (cat_width, cat_height) = cat_texture.size();
        for touch_point in &mut state.touch_points {
            let x = (touch_point.x * width as f64) as i32 - (cat_width / 2);
            let y = (touch_point.y * height as f64) as i32 - (cat_height / 2);
            renderer.render_texture(cat_texture, transform_matrix, x, y, 1.0);
        }
    }
}

impl TouchHandler for TouchHandlerEx {
    fn on_down(&mut self, compositor: &mut Compositor, _touch: &mut Touch, event: &DownEvent) {
        let state: &mut State = compositor.into();
        let (width, height) = event.size();
        let (x, y) = event.location();
        let point = TouchPoint { touch_id: event.touch_id(),
                                 x: x / width,
                                 y: y / height };
        wlr_log!(L_ERROR, "New touch point at {:?}", point);
        state.touch_points.push(point)
    }

    fn on_up(&mut self, compositor: &mut Compositor, _touch: &mut Touch, event: &UpEvent) {
        let state: &mut State = compositor.into();
        wlr_log!(L_ERROR,
                 "Removing {:?} from {:#?}",
                 event.touch_id(),
                 state.touch_points);
        if let Some(index) = state.touch_points
                                  .iter()
                                  .position(|touch_point| touch_point.touch_id == event.touch_id())
        {
            state.touch_points.remove(index);
        }
    }

    fn on_motion(&mut self, compositor: &mut Compositor, _touch: &mut Touch, event: &MotionEvent) {
        let state: &mut State = compositor.into();
        let (width, height) = event.size();
        let (x, y) = event.location();
        wlr_log!(L_ERROR, "New location: {:?}", (x, y));
        for touch_point in &mut state.touch_points {
            if touch_point.touch_id == event.touch_id() {
                touch_point.x = x / width;
                touch_point.y = y / height;
            }
        }
    }
}

impl InputManagerHandler for InputManager {
    fn touch_added(&mut self, _: &mut Compositor, _: &mut Touch) -> Option<Box<TouchHandler>> {
        Some(Box::new(TouchHandlerEx))
    }
    fn keyboard_added(&mut self,
                      _: &mut Compositor,
                      _: &mut Keyboard)
                      -> Option<Box<KeyboardHandler>> {
        Some(Box::new(ExKeyboardHandler))
    }
}

fn main() {
    init_logging(L_DEBUG, None);
    let mut compositor = CompositorBuilder::new().gles2(true)
                                                 .input_manager(Box::new(InputManager))
                                                 .output_manager(Box::new(OutputManager))
                                                 .build_auto(State::new());
    {
        let gles2 = &mut compositor.renderer.as_mut().unwrap();
        let compositor_data: &mut State = (&mut compositor.data).downcast_mut().unwrap();
        compositor_data.cat_texture = gles2.create_texture().map(|mut cat_texture| {
            cat_texture.upload_pixels(TextureFormat::ABGR8888,
                                      CAT_STRIDE,
                                      CAT_WIDTH,
                                      CAT_HEIGHT,
                                      CAT_DATA);
            cat_texture
        });
    }
    compositor.run();
}
<|endoftext|>


<commit_before>// Rust Bitcoin Library
// Written in 2014 by
//   Andrew Poelstra <apoelstra@wpsoftware.net>
//
// To the extent possible under law, the author(s) have dedicated all
// copyright and related and neighboring rights to this software to
// the public domain worldwide. This software is distributed without
// any warranty.
//
// You should have received a copy of the CC0 Public Domain Dedication
// along with this software.
// If not, see <http://creativecommons.org/publicdomain/zero/1.0/>.
//

//! # Network Serialization
//!
//! This module defines the `Serializable` trait which is used for
//! (de)serializing Bitcoin objects for transmission on the network.
//! It also defines (de)serialization routines for many primitives.
//!

use collections::Vec;
use std::io::{IoError, IoResult, OtherIoError, MemReader, MemWriter};

use network::encodable::{ConsensusDecodable, ConsensusEncodable};
use util::hash::Sha256dHash;

/// Objects which are referred to by hash
pub trait BitcoinHash {
  /// Produces a Sha256dHash which can be used to refer to the object
  fn bitcoin_hash(&self) -> Sha256dHash;
}

impl BitcoinHash for Vec<u8> {
  fn bitcoin_hash(&self) -> Sha256dHash {
    Sha256dHash::from_data(self.as_slice())
  }
}

/// Encode an object into a vector
pub fn serialize<T: ConsensusEncodable<RawEncoder<MemWriter>, IoError>>(obj: &T) -> IoResult<Vec<u8>> {
  let mut encoder = RawEncoder::new(MemWriter::new());
  try!(obj.consensus_encode(&mut encoder));
  Ok(encoder.unwrap().unwrap())
}

/// Deserialize an object from a vector
pub fn deserialize<T: ConsensusDecodable<RawDecoder<MemReader>, IoError>>(data: Vec<u8>) -> IoResult<T> {
  let mut decoder = RawDecoder::new(MemReader::new(data));
  ConsensusDecodable::consensus_decode(&mut decoder)
}

/// An encoder for raw binary data
pub struct RawEncoder<W> {
  writer: W
}

/// An decoder for raw binary data
pub struct RawDecoder<R> {
  reader: R
}

impl<W:Writer> RawEncoder<W> {
  /// Constructor
  pub fn new(writer: W) -> RawEncoder<W> {
    RawEncoder { writer: writer }
  }

  /// Returns the underlying Writer
  pub fn unwrap(self) -> W {
    self.writer
  }
}

impl<R:Reader> RawDecoder<R> {
  /// Constructor
  pub fn new(reader: R) -> RawDecoder<R> {
    RawDecoder { reader: reader }
  }

  /// Returns the underlying Reader
  pub fn unwrap(self) -> R {
    self.reader
  }
}

/// A simple Encoder trait
pub trait SimpleEncoder<E> {
  fn emit_u64(&mut self, v: u64) -> Result<(), E>;
  fn emit_u32(&mut self, v: u32) -> Result<(), E>;
  fn emit_u16(&mut self, v: u16) -> Result<(), E>;
  fn emit_u8(&mut self, v: u8) -> Result<(), E>;

  fn emit_i64(&mut self, v: i64) -> Result<(), E>;
  fn emit_i32(&mut self, v: i32) -> Result<(), E>;
  fn emit_i16(&mut self, v: i16) -> Result<(), E>;
  fn emit_i8(&mut self, v: i8) -> Result<(), E>;

  fn emit_bool(&mut self, v: bool) -> Result<(), E>;
}

/// A simple Decoder trait
pub trait SimpleDecoder<E> {
  fn read_u64(&mut self) -> Result<u64, E>;
  fn read_u32(&mut self) -> Result<u32, E>;
  fn read_u16(&mut self) -> Result<u16, E>;
  fn read_u8(&mut self) -> Result<u8, E>;

  fn read_i64(&mut self) -> Result<i64, E>;
  fn read_i32(&mut self) -> Result<i32, E>;
  fn read_i16(&mut self) -> Result<i16, E>;
  fn read_i8(&mut self) -> Result<i8, E>;

  fn read_bool(&mut self) -> Result<bool, E>;

  fn error(&mut self, err: &str) -> E;
}

// TODO: trait reform: impl SimpleEncoder for every Encoder, ditto for Decoder

impl<W:Writer> SimpleEncoder<IoError> for RawEncoder<W> {
  #[inline]
  fn emit_u64(&mut self, v: u64) -> IoResult<()> { self.writer.write_le_u64(v) }
  #[inline]
  fn emit_u32(&mut self, v: u32) -> IoResult<()> { self.writer.write_le_u32(v) }
  #[inline]
  fn emit_u16(&mut self, v: u16) -> IoResult<()> { self.writer.write_le_u16(v) }
  #[inline]
  fn emit_u8(&mut self, v: u8) -> IoResult<()> { self.writer.write_u8(v) }

  #[inline]
  fn emit_i64(&mut self, v: i64) -> IoResult<()> { self.writer.write_le_i64(v) }
  #[inline]
  fn emit_i32(&mut self, v: i32) -> IoResult<()> { self.writer.write_le_i32(v) }
  #[inline]
  fn emit_i16(&mut self, v: i16) -> IoResult<()> { self.writer.write_le_i16(v) }
  #[inline]
  fn emit_i8(&mut self, v: i8) -> IoResult<()> { self.writer.write_i8(v) }

  #[inline]
  fn emit_bool(&mut self, v: bool) -> IoResult<()> { self.writer.write_i8(if v {1} else {0}) }
}

impl<R:Reader> SimpleDecoder<IoError> for RawDecoder<R> {
  #[inline]
  fn read_u64(&mut self) -> IoResult<u64> { self.reader.read_le_u64() }
  #[inline]
  fn read_u32(&mut self) -> IoResult<u32> { self.reader.read_le_u32() }
  #[inline]
  fn read_u16(&mut self) -> IoResult<u16> { self.reader.read_le_u16() }
  #[inline]
  fn read_u8(&mut self) -> IoResult<u8> { self.reader.read_u8() }

  #[inline]
  fn read_i64(&mut self) -> IoResult<i64> { self.reader.read_le_i64() }
  #[inline]
  fn read_i32(&mut self) -> IoResult<i32> { self.reader.read_le_i32() }
  #[inline]
  fn read_i16(&mut self) -> IoResult<i16> { self.reader.read_le_i16() }
  #[inline]
  fn read_i8(&mut self) -> IoResult<i8> { self.reader.read_i8() }

  #[inline]
  fn read_bool(&mut self) -> IoResult<bool> { self.reader.read_u8().map(|res| res != 0) }

  #[inline]
  fn error(&mut self, err: &str) -> IoError {
    IoError {
      kind: OtherIoError,
      desc: "parse error",
      detail: Some(err.to_string())
    }
  }
}

// Aren't really any tests here.. the main functions are serialize and
// deserialize, which get the crap tested out of them it every other
// module.

<commit_msg>Add docs for SimpleDecoder and SimpleEncoder traits<commit_after>// Rust Bitcoin Library
// Written in 2014 by
//   Andrew Poelstra <apoelstra@wpsoftware.net>
//
// To the extent possible under law, the author(s) have dedicated all
// copyright and related and neighboring rights to this software to
// the public domain worldwide. This software is distributed without
// any warranty.
//
// You should have received a copy of the CC0 Public Domain Dedication
// along with this software.
// If not, see <http://creativecommons.org/publicdomain/zero/1.0/>.
//

//! # Network Serialization
//!
//! This module defines the `Serializable` trait which is used for
//! (de)serializing Bitcoin objects for transmission on the network.
//! It also defines (de)serialization routines for many primitives.
//!

use collections::Vec;
use std::io::{IoError, IoResult, OtherIoError, MemReader, MemWriter};

use network::encodable::{ConsensusDecodable, ConsensusEncodable};
use util::hash::Sha256dHash;

/// Objects which are referred to by hash
pub trait BitcoinHash {
  /// Produces a Sha256dHash which can be used to refer to the object
  fn bitcoin_hash(&self) -> Sha256dHash;
}

impl BitcoinHash for Vec<u8> {
  fn bitcoin_hash(&self) -> Sha256dHash {
    Sha256dHash::from_data(self.as_slice())
  }
}

/// Encode an object into a vector
pub fn serialize<T: ConsensusEncodable<RawEncoder<MemWriter>, IoError>>(obj: &T) -> IoResult<Vec<u8>> {
  let mut encoder = RawEncoder::new(MemWriter::new());
  try!(obj.consensus_encode(&mut encoder));
  Ok(encoder.unwrap().unwrap())
}

/// Deserialize an object from a vector
pub fn deserialize<T: ConsensusDecodable<RawDecoder<MemReader>, IoError>>(data: Vec<u8>) -> IoResult<T> {
  let mut decoder = RawDecoder::new(MemReader::new(data));
  ConsensusDecodable::consensus_decode(&mut decoder)
}

/// An encoder for raw binary data
pub struct RawEncoder<W> {
  writer: W
}

/// An decoder for raw binary data
pub struct RawDecoder<R> {
  reader: R
}

impl<W:Writer> RawEncoder<W> {
  /// Constructor
  pub fn new(writer: W) -> RawEncoder<W> {
    RawEncoder { writer: writer }
  }

  /// Returns the underlying Writer
  pub fn unwrap(self) -> W {
    self.writer
  }
}

impl<R:Reader> RawDecoder<R> {
  /// Constructor
  pub fn new(reader: R) -> RawDecoder<R> {
    RawDecoder { reader: reader }
  }

  /// Returns the underlying Reader
  pub fn unwrap(self) -> R {
    self.reader
  }
}

/// A simple Encoder trait
pub trait SimpleEncoder<E> {
  /// Output a 64-bit uint
  fn emit_u64(&mut self, v: u64) -> Result<(), E>;
  /// Output a 32-bit uint
  fn emit_u32(&mut self, v: u32) -> Result<(), E>;
  /// Output a 16-bit uint
  fn emit_u16(&mut self, v: u16) -> Result<(), E>;
  /// Output a 8-bit uint
  fn emit_u8(&mut self, v: u8) -> Result<(), E>;

  /// Output a 64-bit int
  fn emit_i64(&mut self, v: i64) -> Result<(), E>;
  /// Output a 32-bit int
  fn emit_i32(&mut self, v: i32) -> Result<(), E>;
  /// Output a 16-bit int
  fn emit_i16(&mut self, v: i16) -> Result<(), E>;
  /// Output a 8-bit int
  fn emit_i8(&mut self, v: i8) -> Result<(), E>;

  /// Output a boolean
  fn emit_bool(&mut self, v: bool) -> Result<(), E>;
}

/// A simple Decoder trait
pub trait SimpleDecoder<E> {
  /// Read a 64-bit uint
  fn read_u64(&mut self) -> Result<u64, E>;
  /// Read a 32-bit uint
  fn read_u32(&mut self) -> Result<u32, E>;
  /// Read a 16-bit uint
  fn read_u16(&mut self) -> Result<u16, E>;
  /// Read a 8-bit uint
  fn read_u8(&mut self) -> Result<u8, E>;

  /// Read a 64-bit int
  fn read_i64(&mut self) -> Result<i64, E>;
  /// Read a 32-bit int
  fn read_i32(&mut self) -> Result<i32, E>;
  /// Read a 16-bit int
  fn read_i16(&mut self) -> Result<i16, E>;
  /// Read a 8-bit int
  fn read_i8(&mut self) -> Result<i8, E>;

  /// Read a boolean
  fn read_bool(&mut self) -> Result<bool, E>;

  /// Signal a decoding error
  fn error(&mut self, err: &str) -> E;
}

// TODO: trait reform: impl SimpleEncoder for every Encoder, ditto for Decoder

impl<W:Writer> SimpleEncoder<IoError> for RawEncoder<W> {
  #[inline]
  fn emit_u64(&mut self, v: u64) -> IoResult<()> { self.writer.write_le_u64(v) }
  #[inline]
  fn emit_u32(&mut self, v: u32) -> IoResult<()> { self.writer.write_le_u32(v) }
  #[inline]
  fn emit_u16(&mut self, v: u16) -> IoResult<()> { self.writer.write_le_u16(v) }
  #[inline]
  fn emit_u8(&mut self, v: u8) -> IoResult<()> { self.writer.write_u8(v) }

  #[inline]
  fn emit_i64(&mut self, v: i64) -> IoResult<()> { self.writer.write_le_i64(v) }
  #[inline]
  fn emit_i32(&mut self, v: i32) -> IoResult<()> { self.writer.write_le_i32(v) }
  #[inline]
  fn emit_i16(&mut self, v: i16) -> IoResult<()> { self.writer.write_le_i16(v) }
  #[inline]
  fn emit_i8(&mut self, v: i8) -> IoResult<()> { self.writer.write_i8(v) }

  #[inline]
  fn emit_bool(&mut self, v: bool) -> IoResult<()> { self.writer.write_i8(if v {1} else {0}) }
}

impl<R:Reader> SimpleDecoder<IoError> for RawDecoder<R> {
  #[inline]
  fn read_u64(&mut self) -> IoResult<u64> { self.reader.read_le_u64() }
  #[inline]
  fn read_u32(&mut self) -> IoResult<u32> { self.reader.read_le_u32() }
  #[inline]
  fn read_u16(&mut self) -> IoResult<u16> { self.reader.read_le_u16() }
  #[inline]
  fn read_u8(&mut self) -> IoResult<u8> { self.reader.read_u8() }

  #[inline]
  fn read_i64(&mut self) -> IoResult<i64> { self.reader.read_le_i64() }
  #[inline]
  fn read_i32(&mut self) -> IoResult<i32> { self.reader.read_le_i32() }
  #[inline]
  fn read_i16(&mut self) -> IoResult<i16> { self.reader.read_le_i16() }
  #[inline]
  fn read_i8(&mut self) -> IoResult<i8> { self.reader.read_i8() }

  #[inline]
  fn read_bool(&mut self) -> IoResult<bool> { self.reader.read_u8().map(|res| res != 0) }

  #[inline]
  fn error(&mut self, err: &str) -> IoError {
    IoError {
      kind: OtherIoError,
      desc: "parse error",
      detail: Some(err.to_string())
    }
  }
}

// Aren't really any tests here.. the main functions are serialize and
// deserialize, which get the crap tested out of them it every other
// module.

<|endoftext|>


<commit_before>// Copyright 2018 Guillaume Pinot (@TeXitoi) <texitoi@texitoi.eu>
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

//! This crate is custom derive for StructOpt. It should not be used
//! directly. See [structopt documentation](https://docs.rs/structopt)
//! for the usage of `#[derive(StructOpt)]`.

extern crate proc_macro;
extern crate syn;
#[macro_use]
extern crate quote;
extern crate proc_macro2;

mod attrs;

use attrs::{Attrs, Kind, Parser, Ty};
use proc_macro2::{Span, TokenStream};
use syn::punctuated::Punctuated;
use syn::token::Comma;
use syn::*;

/// Generates the `StructOpt` impl.
#[proc_macro_derive(StructOpt, attributes(structopt))]
pub fn structopt(input: proc_macro::TokenStream) -> proc_macro::TokenStream {
    let input: DeriveInput = syn::parse(input).unwrap();
    let gen = impl_structopt(&input);
    gen.into()
}

fn sub_type(t: &syn::Type) -> Option<&syn::Type> {
    let segs = match *t {
        syn::Type::Path(TypePath {
            path: syn::Path { ref segments, .. },
            ..
        }) => segments,
        _ => return None,
    };
    match *segs.iter().last().unwrap() {
        PathSegment {
            arguments:
                PathArguments::AngleBracketed(AngleBracketedGenericArguments { ref args, .. }),
            ..
        } if args.len() == 1 =>
        {
            if let GenericArgument::Type(ref ty) = args[0] {
                Some(ty)
            } else {
                None
            }
        }
        _ => None,
    }
}

/// Generate a block of code to add arguments/subcommands corresponding to
/// the `fields` to an app.
fn gen_augmentation(fields: &Punctuated<Field, Comma>, app_var: &Ident) -> TokenStream {
    let subcmds: Vec<_> = fields
        .iter()
        .filter_map(|field| {
            let attrs = Attrs::from_field(&field);
            if let Kind::Subcommand(ty) = attrs.kind() {
                let subcmd_type = match (ty, sub_type(&field.ty)) {
                    (Ty::Option, Some(sub_type)) => sub_type,
                    _ => &field.ty,
                };
                let required = if ty == Ty::Option {
                    quote!()
                } else {
                    quote! {
                        let #app_var = #app_var.setting(
                            ::structopt::clap::AppSettings::SubcommandRequiredElseHelp
                        );
                    }
                };

                Some(quote!{
                    let #app_var = <#subcmd_type>::augment_clap( #app_var );
                    #required
                })
            } else {
                None
            }
        })
        .collect();

    assert!(
        subcmds.len() <= 1,
        "cannot have more than one nested subcommand"
    );

    let args = fields.iter().filter_map(|field| {
        let attrs = Attrs::from_field(field);
        match attrs.kind() {
            Kind::Subcommand(_) => None,
            Kind::FlattenStruct => {
                let ty = &field.ty;
                Some(quote! {
                    let #app_var = <#ty>::augment_clap(#app_var);
                    let #app_var = if <#ty>::is_subcommand() {
                        #app_var.setting(::structopt::clap::AppSettings::SubcommandRequiredElseHelp)
                    } else {
                        #app_var
                    };
                })
            }
            Kind::Arg(ty) => {
                let convert_type = match ty {
                    Ty::Vec | Ty::Option => sub_type(&field.ty).unwrap_or(&field.ty),
                    _ => &field.ty,
                };

                let occurences = attrs.parser().0 == Parser::FromOccurrences;

                let validator = match *attrs.parser() {
                    (Parser::TryFromStr, ref f) => quote! {
                        .validator(|s| {
                            #f(&s)
                            .map(|_: #convert_type| ())
                            .map_err(|e| e.to_string())
                        })
                    },
                    (Parser::TryFromOsStr, ref f) => quote! {
                        .validator_os(|s| #f(&s).map(|_: #convert_type| ()))
                    },
                    _ => quote!(),
                };

                let modifier = match ty {
                    Ty::Bool => quote!( .takes_value(false).multiple(false) ),
                    Ty::Option => quote!( .takes_value(true).multiple(false) #validator ),
                    Ty::Vec => quote!( .takes_value(true).multiple(true) #validator ),
                    Ty::Other if occurences => quote!( .takes_value(false).multiple(true) ),
                    Ty::Other => {
                        let required = !attrs.has_method("default_value");
                        quote!( .takes_value(true).multiple(false).required(#required) #validator )
                    }
                };
                let methods = attrs.methods();
                let name = attrs.name();
                Some(quote!{
                    let #app_var = #app_var.arg(
                        ::structopt::clap::Arg::with_name(#name)
                            #modifier
                            #methods
                    );
                })
            }
        }
    });

    quote! {{
        #( #args )*
        #( #subcmds )*
        #app_var
    }}
}

fn gen_constructor(fields: &Punctuated<Field, Comma>) -> TokenStream {
    let fields = fields.iter().map(|field| {
        let attrs = Attrs::from_field(field);
        let field_name = field.ident.as_ref().unwrap();
        match attrs.kind() {
            Kind::Subcommand(ty) => {
                let subcmd_type = match (ty, sub_type(&field.ty)) {
                    (Ty::Option, Some(sub_type)) => sub_type,
                    _ => &field.ty,
                };
                let unwrapper = match ty {
                    Ty::Option => quote!(),
                    _ => quote!( .unwrap() ),
                };
                quote!(#field_name: <#subcmd_type>::from_subcommand(matches.subcommand())#unwrapper)
            }
            Kind::FlattenStruct => quote!(#field_name: StructOpt::from_clap(matches)),
            Kind::Arg(ty) => {
                use Parser::*;
                let (value_of, values_of, parse) = match *attrs.parser() {
                    (FromStr, ref f) => (quote!(value_of), quote!(values_of), f.clone()),
                    (TryFromStr, ref f) => (
                        quote!(value_of),
                        quote!(values_of),
                        quote!(|s| #f(s).unwrap()),
                    ),
                    (FromOsStr, ref f) => (quote!(value_of_os), quote!(values_of_os), f.clone()),
                    (TryFromOsStr, ref f) => (
                        quote!(value_of_os),
                        quote!(values_of_os),
                        quote!(|s| #f(s).unwrap()),
                    ),
                    (FromOccurrences, ref f) => (quote!(occurrences_of), quote!(), f.clone()),
                };

                let occurences = attrs.parser().0 == Parser::FromOccurrences;
                let name = attrs.name();
                let field_value = match ty {
                    Ty::Bool => quote!(matches.is_present(#name)),
                    Ty::Option => quote! {
                        matches.#value_of(#name)
                            .as_ref()
                            .map(#parse)
                    },
                    Ty::Vec => quote! {
                        matches.#values_of(#name)
                            .map(|v| v.map(#parse).collect())
                            .unwrap_or_else(Vec::new)
                    },
                    Ty::Other if occurences => quote! {
                        #parse(matches.#value_of(#name))
                    },
                    Ty::Other => quote! {
                        matches.#value_of(#name)
                            .map(#parse)
                            .unwrap()
                    },
                };

                quote!( #field_name: #field_value )
            }
        }
    });

    quote! {{
        #( #fields ),*
    }}
}

fn gen_from_clap(struct_name: &Ident, fields: &Punctuated<Field, Comma>) -> TokenStream {
    let field_block = gen_constructor(fields);

    quote! {
        fn from_clap(matches: &::structopt::clap::ArgMatches) -> Self {
            #struct_name #field_block
        }
    }
}

fn gen_clap(attrs: &[Attribute]) -> TokenStream {
    let name = std::env::var("CARGO_PKG_NAME")
        .ok()
        .unwrap_or_else(String::default);
    let attrs = Attrs::from_struct(attrs, name);
    let name = attrs.name();
    let methods = attrs.methods();
    quote!(::structopt::clap::App::new(#name)#methods)
}

fn gen_clap_struct(struct_attrs: &[Attribute]) -> TokenStream {
    let gen = gen_clap(struct_attrs);
    quote! {
        fn clap<'a, 'b>() -> ::structopt::clap::App<'a, 'b> {
            let app = #gen;
            Self::augment_clap(app)
        }
    }
}

fn gen_augment_clap(fields: &Punctuated<Field, Comma>) -> TokenStream {
    let app_var = Ident::new("app", Span::call_site());
    let augmentation = gen_augmentation(fields, &app_var);
    quote! {
        pub fn augment_clap<'a, 'b>(
            #app_var: ::structopt::clap::App<'a, 'b>
        ) -> ::structopt::clap::App<'a, 'b> {
            #augmentation
        }
    }
}

fn gen_clap_enum(enum_attrs: &[Attribute]) -> TokenStream {
    let gen = gen_clap(enum_attrs);
    quote! {
        fn clap<'a, 'b>() -> ::structopt::clap::App<'a, 'b> {
            let app = #gen
                .setting(::structopt::clap::AppSettings::SubcommandRequiredElseHelp);
            Self::augment_clap(app)
        }
    }
}

fn gen_augment_clap_enum(variants: &Punctuated<Variant, Comma>) -> TokenStream {
    use syn::Fields::*;

    let subcommands = variants.iter().map(|variant| {
        let name = variant.ident.to_string();
        let attrs = Attrs::from_struct(&variant.attrs, name);
        let app_var = Ident::new("subcommand", Span::call_site());
        let arg_block = match variant.fields {
            Named(ref fields) => gen_augmentation(&fields.named, &app_var),
            Unit => quote!( #app_var ),
            Unnamed(FieldsUnnamed { ref unnamed, .. }) if unnamed.len() == 1 => {
                let ty = &unnamed[0];
                quote! {
                    {
                        let #app_var = <#ty>::augment_clap(#app_var);
                        if <#ty>::is_subcommand() {
                            #app_var.setting(
                                ::structopt::clap::AppSettings::SubcommandRequiredElseHelp
                            )
                        } else {
                            #app_var
                        }
                    }
                }
            }
            Unnamed(..) => panic!("{}: tuple enum are not supported", variant.ident),
        };

        let name = attrs.name();
        let from_attrs = attrs.methods();
        quote! {
            .subcommand({
                let #app_var = ::structopt::clap::SubCommand::with_name(#name);
                let #app_var = #arg_block;
                #app_var#from_attrs
            })
        }
    });

    quote! {
        pub fn augment_clap<'a, 'b>(
            app: ::structopt::clap::App<'a, 'b>
        ) -> ::structopt::clap::App<'a, 'b> {
            app #( #subcommands )*
        }
    }
}

fn gen_from_clap_enum(name: &Ident) -> TokenStream {
    quote! {
        fn from_clap(matches: &::structopt::clap::ArgMatches) -> Self {
            <#name>::from_subcommand(matches.subcommand())
                .unwrap()
        }
    }
}

fn gen_from_subcommand(name: &Ident, variants: &Punctuated<Variant, Comma>) -> TokenStream {
    use syn::Fields::*;

    let match_arms = variants.iter().map(|variant| {
        let attrs = Attrs::from_struct(&variant.attrs, variant.ident.to_string());
        let sub_name = attrs.name();
        let variant_name = &variant.ident;
        let constructor_block = match variant.fields {
            Named(ref fields) => gen_constructor(&fields.named),
            Unit => quote!(),
            Unnamed(ref fields) if fields.unnamed.len() == 1 => {
                let ty = &fields.unnamed[0];
                quote!( ( <#ty as ::structopt::StructOpt>::from_clap(matches) ) )
            }
            Unnamed(..) => panic!("{}: tuple enum are not supported", variant.ident),
        };

        quote! {
            (#sub_name, Some(matches)) =>
                Some(#name :: #variant_name #constructor_block)
        }
    });

    quote! {
        pub fn from_subcommand<'a, 'b>(
            sub: (&'b str, Option<&'b ::structopt::clap::ArgMatches<'a>>)
        ) -> Option<Self> {
            match sub {
                #( #match_arms ),*,
                _ => None
            }
        }
    }
}

fn impl_structopt_for_struct(
    name: &Ident,
    fields: &Punctuated<Field, Comma>,
    attrs: &[Attribute],
) -> TokenStream {
    let clap = gen_clap_struct(attrs);
    let augment_clap = gen_augment_clap(fields);
    let from_clap = gen_from_clap(name, fields);

    quote! {
        #[allow(unused_variables)]
        impl ::structopt::StructOpt for #name {
            #clap
            #from_clap
        }

        #[allow(dead_code, unreachable_code)]
        #[doc(hidden)]
        impl #name {
            #augment_clap
            pub fn is_subcommand() -> bool { false }
        }
    }
}

fn impl_structopt_for_enum(
    name: &Ident,
    variants: &Punctuated<Variant, Comma>,
    attrs: &[Attribute],
) -> TokenStream {
    let clap = gen_clap_enum(attrs);
    let augment_clap = gen_augment_clap_enum(variants);
    let from_clap = gen_from_clap_enum(name);
    let from_subcommand = gen_from_subcommand(name, variants);

    quote! {
        impl ::structopt::StructOpt for #name {
            #clap
            #from_clap
        }

        #[allow(unused_variables, dead_code, unreachable_code)]
        #[doc(hidden)]
        impl #name {
            #augment_clap
            #from_subcommand
            pub fn is_subcommand() -> bool { true }
        }
    }
}

fn impl_structopt(input: &DeriveInput) -> TokenStream {
    use syn::Data::*;

    let struct_name = &input.ident;
    let inner_impl = match input.data {
        Struct(DataStruct {
            fields: syn::Fields::Named(ref fields),
            ..
        }) => impl_structopt_for_struct(struct_name, &fields.named, &input.attrs),
        Enum(ref e) => impl_structopt_for_enum(struct_name, &e.variants, &input.attrs),
        _ => panic!("structopt only supports non-tuple structs and enums"),
    };

    quote!(#inner_impl)
}
<commit_msg>fully qualify StructOpt when flattening (#112)<commit_after>// Copyright 2018 Guillaume Pinot (@TeXitoi) <texitoi@texitoi.eu>
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

//! This crate is custom derive for StructOpt. It should not be used
//! directly. See [structopt documentation](https://docs.rs/structopt)
//! for the usage of `#[derive(StructOpt)]`.

extern crate proc_macro;
extern crate syn;
#[macro_use]
extern crate quote;
extern crate proc_macro2;

mod attrs;

use attrs::{Attrs, Kind, Parser, Ty};
use proc_macro2::{Span, TokenStream};
use syn::punctuated::Punctuated;
use syn::token::Comma;
use syn::*;

/// Generates the `StructOpt` impl.
#[proc_macro_derive(StructOpt, attributes(structopt))]
pub fn structopt(input: proc_macro::TokenStream) -> proc_macro::TokenStream {
    let input: DeriveInput = syn::parse(input).unwrap();
    let gen = impl_structopt(&input);
    gen.into()
}

fn sub_type(t: &syn::Type) -> Option<&syn::Type> {
    let segs = match *t {
        syn::Type::Path(TypePath {
            path: syn::Path { ref segments, .. },
            ..
        }) => segments,
        _ => return None,
    };
    match *segs.iter().last().unwrap() {
        PathSegment {
            arguments:
                PathArguments::AngleBracketed(AngleBracketedGenericArguments { ref args, .. }),
            ..
        } if args.len() == 1 =>
        {
            if let GenericArgument::Type(ref ty) = args[0] {
                Some(ty)
            } else {
                None
            }
        }
        _ => None,
    }
}

/// Generate a block of code to add arguments/subcommands corresponding to
/// the `fields` to an app.
fn gen_augmentation(fields: &Punctuated<Field, Comma>, app_var: &Ident) -> TokenStream {
    let subcmds: Vec<_> = fields
        .iter()
        .filter_map(|field| {
            let attrs = Attrs::from_field(&field);
            if let Kind::Subcommand(ty) = attrs.kind() {
                let subcmd_type = match (ty, sub_type(&field.ty)) {
                    (Ty::Option, Some(sub_type)) => sub_type,
                    _ => &field.ty,
                };
                let required = if ty == Ty::Option {
                    quote!()
                } else {
                    quote! {
                        let #app_var = #app_var.setting(
                            ::structopt::clap::AppSettings::SubcommandRequiredElseHelp
                        );
                    }
                };

                Some(quote!{
                    let #app_var = <#subcmd_type>::augment_clap( #app_var );
                    #required
                })
            } else {
                None
            }
        })
        .collect();

    assert!(
        subcmds.len() <= 1,
        "cannot have more than one nested subcommand"
    );

    let args = fields.iter().filter_map(|field| {
        let attrs = Attrs::from_field(field);
        match attrs.kind() {
            Kind::Subcommand(_) => None,
            Kind::FlattenStruct => {
                let ty = &field.ty;
                Some(quote! {
                    let #app_var = <#ty>::augment_clap(#app_var);
                    let #app_var = if <#ty>::is_subcommand() {
                        #app_var.setting(::structopt::clap::AppSettings::SubcommandRequiredElseHelp)
                    } else {
                        #app_var
                    };
                })
            }
            Kind::Arg(ty) => {
                let convert_type = match ty {
                    Ty::Vec | Ty::Option => sub_type(&field.ty).unwrap_or(&field.ty),
                    _ => &field.ty,
                };

                let occurences = attrs.parser().0 == Parser::FromOccurrences;

                let validator = match *attrs.parser() {
                    (Parser::TryFromStr, ref f) => quote! {
                        .validator(|s| {
                            #f(&s)
                            .map(|_: #convert_type| ())
                            .map_err(|e| e.to_string())
                        })
                    },
                    (Parser::TryFromOsStr, ref f) => quote! {
                        .validator_os(|s| #f(&s).map(|_: #convert_type| ()))
                    },
                    _ => quote!(),
                };

                let modifier = match ty {
                    Ty::Bool => quote!( .takes_value(false).multiple(false) ),
                    Ty::Option => quote!( .takes_value(true).multiple(false) #validator ),
                    Ty::Vec => quote!( .takes_value(true).multiple(true) #validator ),
                    Ty::Other if occurences => quote!( .takes_value(false).multiple(true) ),
                    Ty::Other => {
                        let required = !attrs.has_method("default_value");
                        quote!( .takes_value(true).multiple(false).required(#required) #validator )
                    }
                };
                let methods = attrs.methods();
                let name = attrs.name();
                Some(quote!{
                    let #app_var = #app_var.arg(
                        ::structopt::clap::Arg::with_name(#name)
                            #modifier
                            #methods
                    );
                })
            }
        }
    });

    quote! {{
        #( #args )*
        #( #subcmds )*
        #app_var
    }}
}

fn gen_constructor(fields: &Punctuated<Field, Comma>) -> TokenStream {
    let fields = fields.iter().map(|field| {
        let attrs = Attrs::from_field(field);
        let field_name = field.ident.as_ref().unwrap();
        match attrs.kind() {
            Kind::Subcommand(ty) => {
                let subcmd_type = match (ty, sub_type(&field.ty)) {
                    (Ty::Option, Some(sub_type)) => sub_type,
                    _ => &field.ty,
                };
                let unwrapper = match ty {
                    Ty::Option => quote!(),
                    _ => quote!( .unwrap() ),
                };
                quote!(#field_name: <#subcmd_type>::from_subcommand(matches.subcommand())#unwrapper)
            }
            Kind::FlattenStruct => quote!(#field_name: ::structopt::StructOpt::from_clap(matches)),
            Kind::Arg(ty) => {
                use Parser::*;
                let (value_of, values_of, parse) = match *attrs.parser() {
                    (FromStr, ref f) => (quote!(value_of), quote!(values_of), f.clone()),
                    (TryFromStr, ref f) => (
                        quote!(value_of),
                        quote!(values_of),
                        quote!(|s| #f(s).unwrap()),
                    ),
                    (FromOsStr, ref f) => (quote!(value_of_os), quote!(values_of_os), f.clone()),
                    (TryFromOsStr, ref f) => (
                        quote!(value_of_os),
                        quote!(values_of_os),
                        quote!(|s| #f(s).unwrap()),
                    ),
                    (FromOccurrences, ref f) => (quote!(occurrences_of), quote!(), f.clone()),
                };

                let occurences = attrs.parser().0 == Parser::FromOccurrences;
                let name = attrs.name();
                let field_value = match ty {
                    Ty::Bool => quote!(matches.is_present(#name)),
                    Ty::Option => quote! {
                        matches.#value_of(#name)
                            .as_ref()
                            .map(#parse)
                    },
                    Ty::Vec => quote! {
                        matches.#values_of(#name)
                            .map(|v| v.map(#parse).collect())
                            .unwrap_or_else(Vec::new)
                    },
                    Ty::Other if occurences => quote! {
                        #parse(matches.#value_of(#name))
                    },
                    Ty::Other => quote! {
                        matches.#value_of(#name)
                            .map(#parse)
                            .unwrap()
                    },
                };

                quote!( #field_name: #field_value )
            }
        }
    });

    quote! {{
        #( #fields ),*
    }}
}

fn gen_from_clap(struct_name: &Ident, fields: &Punctuated<Field, Comma>) -> TokenStream {
    let field_block = gen_constructor(fields);

    quote! {
        fn from_clap(matches: &::structopt::clap::ArgMatches) -> Self {
            #struct_name #field_block
        }
    }
}

fn gen_clap(attrs: &[Attribute]) -> TokenStream {
    let name = std::env::var("CARGO_PKG_NAME")
        .ok()
        .unwrap_or_else(String::default);
    let attrs = Attrs::from_struct(attrs, name);
    let name = attrs.name();
    let methods = attrs.methods();
    quote!(::structopt::clap::App::new(#name)#methods)
}

fn gen_clap_struct(struct_attrs: &[Attribute]) -> TokenStream {
    let gen = gen_clap(struct_attrs);
    quote! {
        fn clap<'a, 'b>() -> ::structopt::clap::App<'a, 'b> {
            let app = #gen;
            Self::augment_clap(app)
        }
    }
}

fn gen_augment_clap(fields: &Punctuated<Field, Comma>) -> TokenStream {
    let app_var = Ident::new("app", Span::call_site());
    let augmentation = gen_augmentation(fields, &app_var);
    quote! {
        pub fn augment_clap<'a, 'b>(
            #app_var: ::structopt::clap::App<'a, 'b>
        ) -> ::structopt::clap::App<'a, 'b> {
            #augmentation
        }
    }
}

fn gen_clap_enum(enum_attrs: &[Attribute]) -> TokenStream {
    let gen = gen_clap(enum_attrs);
    quote! {
        fn clap<'a, 'b>() -> ::structopt::clap::App<'a, 'b> {
            let app = #gen
                .setting(::structopt::clap::AppSettings::SubcommandRequiredElseHelp);
            Self::augment_clap(app)
        }
    }
}

fn gen_augment_clap_enum(variants: &Punctuated<Variant, Comma>) -> TokenStream {
    use syn::Fields::*;

    let subcommands = variants.iter().map(|variant| {
        let name = variant.ident.to_string();
        let attrs = Attrs::from_struct(&variant.attrs, name);
        let app_var = Ident::new("subcommand", Span::call_site());
        let arg_block = match variant.fields {
            Named(ref fields) => gen_augmentation(&fields.named, &app_var),
            Unit => quote!( #app_var ),
            Unnamed(FieldsUnnamed { ref unnamed, .. }) if unnamed.len() == 1 => {
                let ty = &unnamed[0];
                quote! {
                    {
                        let #app_var = <#ty>::augment_clap(#app_var);
                        if <#ty>::is_subcommand() {
                            #app_var.setting(
                                ::structopt::clap::AppSettings::SubcommandRequiredElseHelp
                            )
                        } else {
                            #app_var
                        }
                    }
                }
            }
            Unnamed(..) => panic!("{}: tuple enum are not supported", variant.ident),
        };

        let name = attrs.name();
        let from_attrs = attrs.methods();
        quote! {
            .subcommand({
                let #app_var = ::structopt::clap::SubCommand::with_name(#name);
                let #app_var = #arg_block;
                #app_var#from_attrs
            })
        }
    });

    quote! {
        pub fn augment_clap<'a, 'b>(
            app: ::structopt::clap::App<'a, 'b>
        ) -> ::structopt::clap::App<'a, 'b> {
            app #( #subcommands )*
        }
    }
}

fn gen_from_clap_enum(name: &Ident) -> TokenStream {
    quote! {
        fn from_clap(matches: &::structopt::clap::ArgMatches) -> Self {
            <#name>::from_subcommand(matches.subcommand())
                .unwrap()
        }
    }
}

fn gen_from_subcommand(name: &Ident, variants: &Punctuated<Variant, Comma>) -> TokenStream {
    use syn::Fields::*;

    let match_arms = variants.iter().map(|variant| {
        let attrs = Attrs::from_struct(&variant.attrs, variant.ident.to_string());
        let sub_name = attrs.name();
        let variant_name = &variant.ident;
        let constructor_block = match variant.fields {
            Named(ref fields) => gen_constructor(&fields.named),
            Unit => quote!(),
            Unnamed(ref fields) if fields.unnamed.len() == 1 => {
                let ty = &fields.unnamed[0];
                quote!( ( <#ty as ::structopt::StructOpt>::from_clap(matches) ) )
            }
            Unnamed(..) => panic!("{}: tuple enum are not supported", variant.ident),
        };

        quote! {
            (#sub_name, Some(matches)) =>
                Some(#name :: #variant_name #constructor_block)
        }
    });

    quote! {
        pub fn from_subcommand<'a, 'b>(
            sub: (&'b str, Option<&'b ::structopt::clap::ArgMatches<'a>>)
        ) -> Option<Self> {
            match sub {
                #( #match_arms ),*,
                _ => None
            }
        }
    }
}

fn impl_structopt_for_struct(
    name: &Ident,
    fields: &Punctuated<Field, Comma>,
    attrs: &[Attribute],
) -> TokenStream {
    let clap = gen_clap_struct(attrs);
    let augment_clap = gen_augment_clap(fields);
    let from_clap = gen_from_clap(name, fields);

    quote! {
        #[allow(unused_variables)]
        impl ::structopt::StructOpt for #name {
            #clap
            #from_clap
        }

        #[allow(dead_code, unreachable_code)]
        #[doc(hidden)]
        impl #name {
            #augment_clap
            pub fn is_subcommand() -> bool { false }
        }
    }
}

fn impl_structopt_for_enum(
    name: &Ident,
    variants: &Punctuated<Variant, Comma>,
    attrs: &[Attribute],
) -> TokenStream {
    let clap = gen_clap_enum(attrs);
    let augment_clap = gen_augment_clap_enum(variants);
    let from_clap = gen_from_clap_enum(name);
    let from_subcommand = gen_from_subcommand(name, variants);

    quote! {
        impl ::structopt::StructOpt for #name {
            #clap
            #from_clap
        }

        #[allow(unused_variables, dead_code, unreachable_code)]
        #[doc(hidden)]
        impl #name {
            #augment_clap
            #from_subcommand
            pub fn is_subcommand() -> bool { true }
        }
    }
}

fn impl_structopt(input: &DeriveInput) -> TokenStream {
    use syn::Data::*;

    let struct_name = &input.ident;
    let inner_impl = match input.data {
        Struct(DataStruct {
            fields: syn::Fields::Named(ref fields),
            ..
        }) => impl_structopt_for_struct(struct_name, &fields.named, &input.attrs),
        Enum(ref e) => impl_structopt_for_enum(struct_name, &e.variants, &input.attrs),
        _ => panic!("structopt only supports non-tuple structs and enums"),
    };

    quote!(#inner_impl)
}
<|endoftext|>


<commit_before>//! Information about Intel's performance events.
pub mod events;
// The types need to be in a spearate file so we don't get circular
// dependencies with build.rs include:
mod description;
pub use self::description::{Counter, EventDescription, MSRIndex, PebsType, Tuple};

use crate::cpuid;
use core::fmt::{Error, Result, Write};
use core::str;
use phf;

const MODEL_LEN: usize = 30;

#[derive(Default)]
struct ModelWriter {
    buffer: [u8; MODEL_LEN],
    index: usize,
}

impl ModelWriter {
    fn as_str(&self) -> &str {
        str::from_utf8(&self.buffer[..self.index]).unwrap()
    }
}

impl Write for ModelWriter {
    fn write_str(&mut self, s: &str) -> Result {
        // TODO: There exists probably a more efficient way of doing this:
        for c in s.chars() {
            if self.index >= self.buffer.len() {
                return Err(Error);
            }
            self.buffer[self.index] = c as u8;
            self.index += 1;
        }
        Ok(())
    }
}

// Format must be a string literal
macro_rules! get_events {
    ($format:expr) => {{
        let cpuid = cpuid::CpuId::new();

        cpuid.get_vendor_info().map_or(None, |vf| {
            cpuid.get_feature_info().map_or(None, |fi| {
                let vendor = vf.as_str();
                let (family, extended_model, model) =
                    (fi.family_id(), fi.extended_model_id(), fi.model_id());

                let mut writer: ModelWriter = Default::default();
                // Should work as long as it fits in MODEL_LEN bytes:
                write!(writer, $format, vendor, family, extended_model, model).unwrap();
                let key = writer.as_str();

                events::COUNTER_MAP.get(key)
            })
        })
    }};
}

/// Return all core performance events for the running micro-architecture.
pub fn events() -> Option<&'static phf::Map<&'static str, EventDescription<'static>>> {
    // Should be something like: GenuineIntel-6-2C
    get_events!("{}-{}-{:X}{:X}")
}

#[test]
fn events_test() {
    // Note: This will silently fail in case the counter is not available.
    events().map(|cc| {
        cc.get("INST_RETIRED.ANY").map(|p| {
            assert!(p.event_name == "INST_RETIRED.ANY");
        });
    });
}
<commit_msg>perfcnt: Use `base_xxx_id` apis for looking up `COUNTER_MAP`<commit_after>//! Information about Intel's performance events.
pub mod events;
// The types need to be in a spearate file so we don't get circular
// dependencies with build.rs include:
mod description;
pub use self::description::{Counter, EventDescription, MSRIndex, PebsType, Tuple};

use crate::cpuid;
use core::fmt::{Error, Result, Write};
use core::str;
use phf;

const MODEL_LEN: usize = 30;

#[derive(Default)]
struct ModelWriter {
    buffer: [u8; MODEL_LEN],
    index: usize,
}

impl ModelWriter {
    fn as_str(&self) -> &str {
        str::from_utf8(&self.buffer[..self.index]).unwrap()
    }
}

impl Write for ModelWriter {
    fn write_str(&mut self, s: &str) -> Result {
        // TODO: There exists probably a more efficient way of doing this:
        for c in s.chars() {
            if self.index >= self.buffer.len() {
                return Err(Error);
            }
            self.buffer[self.index] = c as u8;
            self.index += 1;
        }
        Ok(())
    }
}

// Format must be a string literal
macro_rules! get_events {
    ($format:expr) => {{
        let cpuid = cpuid::CpuId::new();

        cpuid.get_vendor_info().map_or(None, |vf| {
            cpuid.get_feature_info().map_or(None, |fi| {
                let vendor = vf.as_str();
                let (family, extended_model, model) =
                    (fi.base_family_id(), fi.extended_model_id(), fi.base_model_id());

                let mut writer: ModelWriter = Default::default();
                // Should work as long as it fits in MODEL_LEN bytes:
                write!(writer, $format, vendor, family, extended_model, model).unwrap();
                let key = writer.as_str();

                events::COUNTER_MAP.get(key)
            })
        })
    }};
}

/// Return all core performance events for the running micro-architecture.
pub fn events() -> Option<&'static phf::Map<&'static str, EventDescription<'static>>> {
    // Should be something like: GenuineIntel-6-2C
    get_events!("{}-{}-{:X}{:X}")
}

#[test]
fn events_test() {
    // Note: This will silently fail in case the counter is not available.
    events().map(|cc| {
        cc.get("INST_RETIRED.ANY").map(|p| {
            assert!(p.event_name == "INST_RETIRED.ANY");
        });
    });
}
<|endoftext|>


<commit_before>// src: https://rustbyexample.com/custom_types/structs.html
// ^ I keep forgetting these, but it's obvious where the code is from!

// A unit struct
struct Nil;

// A tuple struct
struct Pair(i32, f32);

// Structs can be reused as fields of another struct
// and order doesn't matter!(aka forward declaration not needed)
#[allow(dead_code)]
struct Rectangle {
    p1: Point,
    p2: Point,
}

// A struct with two fields
struct Point {
    x: f32,
    y: f32,
}

fn main() {
    // Instantiate a `Point`
    let point: Point = Point { x: 0.3, y: 0.4 };

    // Access the fields of the point
    println!("point coordinates: ({}, {})", point.x, point.y);

    // Destructure the point using a `let` binding
    let Point { x: my_x, y: my_y } = point;

    let _rectangle = Rectangle {
        // struct instantiation is an expression too
        p1: Point { x: my_y, y: my_x },
        p2: point,
    };

    // Instantiate a unit struct
    let _nil = Nil;

    // Instantiate a tuple struct
    let pair = Pair(1, 0.1);

    // Destructure a tuple struct
    let Pair(integer, decimal) = pair;

    println!("pair contains {:?} and {:?}", integer, decimal);
    println!("area={}", rect_area(&_rectangle));
    let r=Rectangle{
        p1: Point{x:15_f32,y:10_f32},
        p2: Point{x:50_f32,y:27.0}};
    println!("area={}", rect_area(&r));
    assert_eq!(rect_area(&r), 595.0);

    let r1=Rectangle{
        p1: Point{x:48_f32,y:9_f32},
        p2: Point{x:14_f32,y:27.0}};
    println!("area={}", rect_area(&r1));
    assert_eq!(rect_area(&r1), 612.0);
    let r1_2=Rectangle{
        p1: Point{x:14_f32,y:9_f32},
        p2: Point{x:48_f32,y:27.0}};
    assert_eq!(rect_area(&r1_2), rect_area(&r1));
}

fn rect_area(r: &Rectangle) -> f32
{
  let Rectangle{p1: Point{x,y}, p2: Point{x:x2,y:y2}} = *r;

  //src: http://www.mathopenref.com/coordrectareaperim.html
  let (width, height)= ( (y-y2).abs(), (x-x2).abs());

  width*height
}
<commit_msg>add square for Activity<commit_after>// src: https://rustbyexample.com/custom_types/structs.html
// ^ I keep forgetting these, but it's obvious where the code is from!

// A unit struct
struct Nil;

// A tuple struct
struct Pair(i32, f32);

// Structs can be reused as fields of another struct
// and order doesn't matter!(aka forward declaration not needed)
#[allow(dead_code)]
struct Rectangle {
    p1: Point,
    p2: Point,
}

// A struct with two fields
#[derive(Clone,Copy)]
struct Point {
    x: f32,
    y: f32,
}

fn main() {
    // Instantiate a `Point`
    let point: Point = Point { x: 0.3, y: 0.4 };

    // Access the fields of the point
    println!("point coordinates: ({}, {})", point.x, point.y);

    // Destructure the point using a `let` binding
    let Point { x: my_x, y: my_y } = point;

    let _rectangle = Rectangle {
        // struct instantiation is an expression too
        p1: Point { x: my_y, y: my_x },
        p2: point,
    };

    // Instantiate a unit struct
    let _nil = Nil;

    // Instantiate a tuple struct
    let pair = Pair(1, 0.1);

    // Destructure a tuple struct
    let Pair(integer, decimal) = pair;

    println!("pair contains {:?} and {:?}", integer, decimal);
    println!("area={}", rect_area(&_rectangle));
    let r=Rectangle{
        p1: Point{x:15_f32,y:10_f32},
        p2: Point{x:50_f32,y:27.0}};
    println!("area={}", rect_area(&r));
    assert_eq!(rect_area(&r), 595.0);

    let r1=Rectangle{
        p1: Point{x:48_f32,y:9_f32},
        p2: Point{x:14_f32,y:27.0}};
    println!("area={}", rect_area(&r1));
    assert_eq!(rect_area(&r1), 612.0);
    let r1_2=Rectangle{
        p1: Point{x:14_f32,y:9_f32},
        p2: Point{x:48_f32,y:27.0}};
    assert_eq!(rect_area(&r1_2), rect_area(&r1));

    let r2=square(Point{x:14.0,y:9.0}, 20.0);
    assert_eq!(rect_area(&r2), 400.0);

    let r3=square(Point{x:-1.0,y:10.0}, 20.0);
    assert_eq!(rect_area(&r3), 400.0);
}

fn rect_area(r: &Rectangle) -> f32
{
  let Rectangle{p1: Point{x,y}, p2: Point{x:x2,y:y2}} = *r;

  //src: http://www.mathopenref.com/coordrectareaperim.html
  let (width, height)= ( (y-y2).abs(), (x-x2).abs());

  width*height
}

fn square(p: Point, f: f32) -> Rectangle
{
    Rectangle{p1: p, p2: Point{x:p.x+f, y:p.y+f}}
}

<|endoftext|>


<commit_before>use engine::{Tile, Map};
use util::FromChar;
use util::units::Size;

pub trait IntoMap {
    fn as_map(self) -> MapBuildResult;
}

impl IntoMap for Vec<Vec<Tile>> {
    fn as_map(self) -> MapBuildResult {
        // TODO: check dimensions are the same
        let size = Size::new(self.len() as i32, self[0].len() as i32);

        Ok(Map {
            tiles: self,
            size: size,
        })
    }
}

fn build_line(l: &&str) -> Vec<Tile> {
    l.chars().map(|c| Tile::from_char(c)).collect()
}

impl IntoMap for String {
    fn as_map(self) -> MapBuildResult {
        let lines: Vec<&str> = self.split('\n').filter(|l| !l.is_empty()).collect();

        if !lines.iter().all(|x| x.len() == lines[0].len()) { return Err("Different length lines") };

        let tiles: Vec<Vec<Tile>> = lines.iter().map(build_line).collect();

        Ok(Map::new(tiles))
    }
}

pub type MapBuildResult = Result<Map, &'static str>;
<commit_msg>Clean up IntoMap implementations<commit_after>use engine::{Tile, Map};
use util::{FirstLast, FromChar};
use util::units::Size;

pub trait IntoMap {
    fn as_map(self) -> MapBuildResult;
}

impl IntoMap for Vec<Vec<Tile>> {
    fn as_map(self) -> MapBuildResult {
        // TODO: check dimensions are the same
        let size = Size::new(self.len() as i32, self[0].len() as i32);

        Ok(Map {
            tiles: self,
            size: size,
        })
    }
}

impl IntoMap for String {
    fn as_map(self) -> MapBuildResult {
        let lines: Vec<&str> = self.split('\n')
                                   .filter(|l| !l.is_empty())
                                   .collect();

        let expected_line_length = lines.first().len();

        if !lines.iter().all(|x| x.len() == expected_line_length) {
            return Err("Different length lines")
        }

        let tiles: Vec<Vec<Tile>> = lines.iter()
                                         .map(|l| l.chars()
                                                   .map(|c| Tile::from_char(c))
                                                   .collect())
                                         .collect();

        Ok(Map::new(tiles))
    }
}

pub type MapBuildResult = Result<Map, &'static str>;
<|endoftext|>