<commit_before>//! `bless` updates the reference files in the repo with changed output files
//! from the last test run.

use std::env;
use std::ffi::OsStr;
use std::fs;
use std::lazy::SyncLazy;
use std::path::PathBuf;
use walkdir::WalkDir;

use crate::clippy_project_root;

// NOTE: this is duplicated with tests/cargo/mod.rs What to do?
pub static CARGO_TARGET_DIR: SyncLazy<PathBuf> = SyncLazy::new(|| match env::var_os("CARGO_TARGET_DIR") {
    Some(v) => v.into(),
    None => env::current_dir().unwrap().join("target"),
});

pub fn bless() {
    let test_dirs = [
        clippy_project_root().join("tests").join("ui"),
        clippy_project_root().join("tests").join("ui-toml"),
        clippy_project_root().join("tests").join("ui-cargo"),
    ];
    for test_dir in &test_dirs {
        WalkDir::new(test_dir)
            .into_iter()
            .filter_map(Result::ok)
            .filter(|f| f.path().extension() == Some(OsStr::new("rs")))
            .for_each(|f| {
                update_reference_file(f.path().with_extension("stdout"));
                update_reference_file(f.path().with_extension("stderr"));
                update_reference_file(f.path().with_extension("fixed"));
            });
    }
}

fn update_reference_file(reference_file_path: PathBuf) {
    let test_output_path = build_dir().join(PathBuf::from(reference_file_path.file_name().unwrap()));
    let relative_reference_file_path = reference_file_path.strip_prefix(clippy_project_root()).unwrap();

    // If compiletest did not write any changes during the test run,
    // we don't have to update anything
    if !test_output_path.exists() {
        return;
    }

    let test_output_file = fs::read(&test_output_path).expect("Unable to read test output file");
    let reference_file = fs::read(&reference_file_path).expect("Unable to read reference file");

    if test_output_file != reference_file {
        // If a test run caused an output file to change, update the reference file
        println!("updating {}", &relative_reference_file_path.display());
        fs::copy(test_output_path, &reference_file_path).expect("Could not update reference file");

        if reference_file.is_empty() {
            // If we copied over an empty output file, we remove the now empty reference file
            println!("removing {}", &relative_reference_file_path.display());
            fs::remove_file(reference_file_path).expect("Could not remove reference file");
        }
    }
}

fn build_dir() -> PathBuf {
    let profile = env::var("PROFILE").unwrap_or_else(|_| "debug".to_string());
    let mut path = PathBuf::new();
    path.push(CARGO_TARGET_DIR.clone());
    path.push(profile);
    path.push("test_build_base");
    path
}
<commit_msg>Fix blessing of new reference files<commit_after>//! `bless` updates the reference files in the repo with changed output files
//! from the last test run.

use std::env;
use std::ffi::OsStr;
use std::fs;
use std::lazy::SyncLazy;
use std::path::PathBuf;
use walkdir::WalkDir;

use crate::clippy_project_root;

// NOTE: this is duplicated with tests/cargo/mod.rs What to do?
pub static CARGO_TARGET_DIR: SyncLazy<PathBuf> = SyncLazy::new(|| match env::var_os("CARGO_TARGET_DIR") {
    Some(v) => v.into(),
    None => env::current_dir().unwrap().join("target"),
});

pub fn bless() {
    let test_dirs = [
        clippy_project_root().join("tests").join("ui"),
        clippy_project_root().join("tests").join("ui-toml"),
        clippy_project_root().join("tests").join("ui-cargo"),
    ];
    for test_dir in &test_dirs {
        WalkDir::new(test_dir)
            .into_iter()
            .filter_map(Result::ok)
            .filter(|f| f.path().extension() == Some(OsStr::new("rs")))
            .for_each(|f| {
                update_reference_file(f.path().with_extension("stdout"));
                update_reference_file(f.path().with_extension("stderr"));
                update_reference_file(f.path().with_extension("fixed"));
            });
    }
}

fn update_reference_file(reference_file_path: PathBuf) {
    let test_output_path = build_dir().join(PathBuf::from(reference_file_path.file_name().unwrap()));
    let relative_reference_file_path = reference_file_path.strip_prefix(clippy_project_root()).unwrap();

    // If compiletest did not write any changes during the test run,
    // we don't have to update anything
    if !test_output_path.exists() {
        return;
    }

    let test_output_file = fs::read(&test_output_path).expect("Unable to read test output file");
    let reference_file = fs::read(&reference_file_path).unwrap_or_default();

    if test_output_file != reference_file {
        // If a test run caused an output file to change, update the reference file
        println!("updating {}", &relative_reference_file_path.display());
        fs::copy(test_output_path, &reference_file_path).expect("Could not update reference file");

        // We need to re-read the file now because it was potentially updated from copying
        let reference_file = fs::read(&reference_file_path).unwrap_or_default();

        if reference_file.is_empty() {
            // If we copied over an empty output file, we remove the now empty reference file
            println!("removing {}", &relative_reference_file_path.display());
            fs::remove_file(reference_file_path).expect("Could not remove reference file");
        }
    }
}

fn build_dir() -> PathBuf {
    let profile = env::var("PROFILE").unwrap_or_else(|_| "debug".to_string());
    let mut path = PathBuf::new();
    path.push(CARGO_TARGET_DIR.clone());
    path.push(profile);
    path.push("test_build_base");
    path
}
<|endoftext|>


<commit_before>extern crate core;
extern crate system;

use std::collections::BTreeMap;
use std::fs::File;
use std::io::{Read, Write};
use std::mem::size_of;
use std::process::{Child, Command};
use std::thread;

use system::error::{Error, Result, EBADF, ENOENT};
use system::scheme::{Packet, Scheme};

pub use self::color::Color;
pub use self::display::Display;
pub use self::event::{Event, EventOption};
pub use self::image::{Image, ImageRoi};
pub use self::window::Window;

use self::bmp::BmpFile;
use self::event::{EVENT_KEY, EVENT_MOUSE};

pub mod bmp;
pub mod color;
pub mod display;
#[path="../../../kernel/common/event.rs"]
pub mod event;
pub mod image;
pub mod window;

struct OrbitalScheme {
    next_id: isize,
    cursor: Image,
    cursor_x: i32,
    cursor_y: i32,
    order: Vec<usize>,
    windows: BTreeMap<usize, Window>,
    redraw: bool,
}

impl OrbitalScheme {
    fn new() -> OrbitalScheme {
        OrbitalScheme {
            next_id: 1,
            cursor: BmpFile::from_path("/ui/cursor.bmp"),
            cursor_x: 0,
            cursor_y: 0,
            order: Vec::new(),
            windows: BTreeMap::new(),
            redraw: true,
        }
    }

    fn update(&mut self, display: &mut Display) {
        while let Some(mut event) = display.poll() {
            if event.code == EVENT_KEY {
                if let Some(id) = self.order.last() {
                    if let Some(mut window) = self.windows.get_mut(&id) {
                        window.event(event);
                    }
                }
            } else if event.code == EVENT_MOUSE {
                self.cursor_x = event.a as i32;
                self.cursor_y = event.b as i32;
                self.redraw = true;

                if let Some(id) = self.order.last() {
                    if let Some(mut window) = self.windows.get_mut(&id) {
                        event.a -= window.x as i64;
                        event.b -= window.y as i64;
                        window.event(event);
                    }
                }
            }
        }

        if self.redraw {
            self.redraw = false;
            display.as_roi().set(Color::rgb(75, 163, 253));
            for id in self.order.iter() {
                if let Some(mut window) = self.windows.get_mut(&id) {
                    window.draw(display);
                }
            }
            display.roi(self.cursor_x, self.cursor_y, self.cursor.width(), self.cursor.height()).blend(&self.cursor.as_roi());
            display.flip();
        }
    }
}

impl Scheme for OrbitalScheme {
    #[allow(unused_variables)]
    fn open(&mut self, path: &str, flags: usize, mode: usize) -> Result {
        let res = path.split(":").nth(1).unwrap_or("");
        let x = res.split("/").nth(0).unwrap_or("").parse::<i32>().unwrap_or(0);
        let y = res.split("/").nth(1).unwrap_or("").parse::<i32>().unwrap_or(0);
        let width = res.split("/").nth(2).unwrap_or("").parse::<i32>().unwrap_or(0);
        let height = res.split("/").nth(3).unwrap_or("").parse::<i32>().unwrap_or(0);

        let id = self.next_id as usize;
        self.next_id += 1;
        if self.next_id < 0 {
            self.next_id = 1;
        }

        self.order.push(id);
        self.windows.insert(id, Window::new(x, y, width, height));
        self.redraw = true;

        Ok(id)
    }

    fn read(&mut self, id: usize, buf: &mut [u8]) -> Result {
        if let Some(mut window) = self.windows.get_mut(&id) {
            window.read(buf)
        } else {
            Err(Error::new(EBADF))
        }
    }

    fn write(&mut self, id: usize, buf: &[u8]) -> Result {
        if let Some(mut window) = self.windows.get_mut(&id) {
            self.redraw = true;
            window.write(buf)
        } else {
            Err(Error::new(EBADF))
        }
    }

    fn close(&mut self, id: usize) -> Result {
        let mut i = 0;
        while i < self.order.len() {
            let mut remove = false;
            if let Some(key) = self.order.get(i) {
                if *key == id {
                    remove = true;
                }
            }

            if remove {
                self.order.remove(i);
            } else {
                i += 1;
            }
        }

        if self.windows.remove(&id).is_some() {
            self.redraw = true;
            Ok(0)
        } else {
            Err(Error::new(EBADF))
        }
    }
}

fn main() {
    let mut socket = File::create(":orbital").unwrap();
    let mut scheme = OrbitalScheme::new();
    match Display::new() {
        Ok(mut display) => {
            println!("- Orbital: Found Display {}x{}", display.width(), display.height());
            println!("    Console: Press F1");
            println!("    Desktop: Press F2");

            let _launcher: Option<Child> = match Command::new("/apps/launcher/main.bin").spawn() {
                Ok(child) => Some(child),
                Err(err) => {
                    println!("Failed to launch launcher: {}", err);
                    None
                },
            };

            loop{
                let mut packet = Packet::default();
                while socket.read(&mut packet).unwrap() == size_of::<Packet>() {
                    scheme.handle(&mut packet);
                    socket.write(&packet).unwrap();
                }

                scheme.update(&mut display);

                thread::yield_now();
            }
        },
        Err(err) => println!("- Orbital: No Display Found: {}", err)
    }
}
<commit_msg>Do not launch launcher until bugs are fixed<commit_after>extern crate core;
extern crate system;

use std::collections::BTreeMap;
use std::fs::File;
use std::io::{Read, Write};
use std::mem::size_of;
use std::process::{Child, Command};
use std::thread;

use system::error::{Error, Result, EBADF, ENOENT};
use system::scheme::{Packet, Scheme};

pub use self::color::Color;
pub use self::display::Display;
pub use self::event::{Event, EventOption};
pub use self::image::{Image, ImageRoi};
pub use self::window::Window;

use self::bmp::BmpFile;
use self::event::{EVENT_KEY, EVENT_MOUSE};

pub mod bmp;
pub mod color;
pub mod display;
#[path="../../../kernel/common/event.rs"]
pub mod event;
pub mod image;
pub mod window;

struct OrbitalScheme {
    next_id: isize,
    cursor: Image,
    cursor_x: i32,
    cursor_y: i32,
    order: Vec<usize>,
    windows: BTreeMap<usize, Window>,
    redraw: bool,
}

impl OrbitalScheme {
    fn new() -> OrbitalScheme {
        OrbitalScheme {
            next_id: 1,
            cursor: BmpFile::from_path("/ui/cursor.bmp"),
            cursor_x: 0,
            cursor_y: 0,
            order: Vec::new(),
            windows: BTreeMap::new(),
            redraw: true,
        }
    }

    fn update(&mut self, display: &mut Display) {
        while let Some(mut event) = display.poll() {
            if event.code == EVENT_KEY {
                if let Some(id) = self.order.last() {
                    if let Some(mut window) = self.windows.get_mut(&id) {
                        window.event(event);
                    }
                }
            } else if event.code == EVENT_MOUSE {
                self.cursor_x = event.a as i32;
                self.cursor_y = event.b as i32;
                self.redraw = true;

                if let Some(id) = self.order.last() {
                    if let Some(mut window) = self.windows.get_mut(&id) {
                        event.a -= window.x as i64;
                        event.b -= window.y as i64;
                        window.event(event);
                    }
                }
            }
        }

        if self.redraw {
            self.redraw = false;
            display.as_roi().set(Color::rgb(75, 163, 253));
            for id in self.order.iter() {
                if let Some(mut window) = self.windows.get_mut(&id) {
                    window.draw(display);
                }
            }
            display.roi(self.cursor_x, self.cursor_y, self.cursor.width(), self.cursor.height()).blend(&self.cursor.as_roi());
            display.flip();
        }
    }
}

impl Scheme for OrbitalScheme {
    #[allow(unused_variables)]
    fn open(&mut self, path: &str, flags: usize, mode: usize) -> Result {
        let res = path.split(":").nth(1).unwrap_or("");
        let x = res.split("/").nth(0).unwrap_or("").parse::<i32>().unwrap_or(0);
        let y = res.split("/").nth(1).unwrap_or("").parse::<i32>().unwrap_or(0);
        let width = res.split("/").nth(2).unwrap_or("").parse::<i32>().unwrap_or(0);
        let height = res.split("/").nth(3).unwrap_or("").parse::<i32>().unwrap_or(0);

        let id = self.next_id as usize;
        self.next_id += 1;
        if self.next_id < 0 {
            self.next_id = 1;
        }

        self.order.push(id);
        self.windows.insert(id, Window::new(x, y, width, height));
        self.redraw = true;

        Ok(id)
    }

    fn read(&mut self, id: usize, buf: &mut [u8]) -> Result {
        if let Some(mut window) = self.windows.get_mut(&id) {
            window.read(buf)
        } else {
            Err(Error::new(EBADF))
        }
    }

    fn write(&mut self, id: usize, buf: &[u8]) -> Result {
        if let Some(mut window) = self.windows.get_mut(&id) {
            self.redraw = true;
            window.write(buf)
        } else {
            Err(Error::new(EBADF))
        }
    }

    fn close(&mut self, id: usize) -> Result {
        let mut i = 0;
        while i < self.order.len() {
            let mut remove = false;
            if let Some(key) = self.order.get(i) {
                if *key == id {
                    remove = true;
                }
            }

            if remove {
                self.order.remove(i);
            } else {
                i += 1;
            }
        }

        if self.windows.remove(&id).is_some() {
            self.redraw = true;
            Ok(0)
        } else {
            Err(Error::new(EBADF))
        }
    }
}

fn main() {
    let mut socket = File::create(":orbital").unwrap();
    let mut scheme = OrbitalScheme::new();
    match Display::new() {
        Ok(mut display) => {
            println!("- Orbital: Found Display {}x{}", display.width(), display.height());
            println!("    Console: Press F1");
            println!("    Desktop: Press F2");

            /*
            let _launcher: Option<Child> = match Command::new("/apps/launcher/main.bin").spawn() {
                Ok(child) => Some(child),
                Err(err) => {
                    println!("Failed to launch launcher: {}", err);
                    None
                },
            };
            */

            loop{
                let mut packet = Packet::default();
                while socket.read(&mut packet).unwrap() == size_of::<Packet>() {
                    scheme.handle(&mut packet);
                    socket.write(&packet).unwrap();
                }

                scheme.update(&mut display);

                thread::yield_now();
            }
        },
        Err(err) => println!("- Orbital: No Display Found: {}", err)
    }
}
<|endoftext|>


<commit_before>use super::*;
use redox::*;

#[derive(Copy, Clone)]
/// An instruction
pub struct Inst(pub Repeat, pub Key);

/// Repeatation
#[derive(Copy, Clone)]
pub enum Repeat {
    /// An integer
    Int(usize),
    /// Not given
    Null,
}
impl Repeat {
    /// Either unwrap the Int(n) or fallback to a given value
    #[inline]
    pub fn or(self, fallback: usize) -> usize {
        if let Repeat::Int(n) = self {
            n
        } else {
            fallback
        }
    }
    /// Fallback to one (default)
    #[inline]
    pub fn d(self) -> usize {
        self.or(1)
    }
}

/// Get the next instruction
impl Editor {
    pub fn next_inst(&mut self) -> Inst {
        let mut n = 0;
        let mut shifted = false;

        // TODO: Make the switch to normal mode shift more well-coded.
        loop {
            if let EventOption::Key(k) = self.window.poll().unwrap_or(Event::new()).to_option() {
                let c = k.character;
                match c {
                    '\0' => {
                        return Inst(Repeat::Null, match k.scancode {
                            K_ALT => Key::Alt(k.pressed),
                            K_CTRL => Key::Ctrl(k.pressed),
                            K_LEFT_SHIFT | K_RIGHT_SHIFT => Key::Shift(k.pressed),
                            s if k.pressed => match s {
                                K_BKSP => Key::Backspace,
                                K_LEFT => Key::Left,
                                K_RIGHT => Key::Right,
                                K_UP => Key::Up,
                                K_DOWN => Key::Down,
                                K_TAB => Key::Tab,
                                K_ESC => Key::Escape,
                                _ => Key::Unknown(s),
                            },
                            s => Key::Unknown(s),
                        })
                    }
                    _ => if k.pressed {
                        match self.cursor().mode {
                            Mode::Primitive(_) => {
                                return Inst(Repeat::Null, Key::Char(c));
                            },
                            Mode::Command(_) => {
                                n = match c {
                                    '0' if n != 0 => n * 10,
                                    '1'           => n * 10 + 1,
                                    '2'           => n * 10 + 2,
                                    '3'           => n * 10 + 3,
                                    '4'           => n * 10 + 4,
                                    '5'           => n * 10 + 5,
                                    '6'           => n * 10 + 6,
                                    '7'           => n * 10 + 7,
                                    '8'           => n * 10 + 8,
                                    '9'           => n * 10 + 9,
                                    _             => {

                                        return Inst(if n == 0 { Repeat::Null } else { Repeat::Int(n) }, Key::Char(c));
                                    }
                                }
                            }
                        }

                    },
                }
            }
        }

        unreachable!()
    }
}
<commit_msg>Fix doc msg<commit_after>use super::*;
use redox::*;

#[derive(Copy, Clone)]
/// An instruction
pub struct Inst(pub Repeat, pub Key);

/// Repeatation
#[derive(Copy, Clone)]
pub enum Repeat {
    /// An integer
    Int(usize),
    /// Not given
    Null,
}
impl Repeat {
    /// Either unwrap the Int(n) or fallback to a given value
    #[inline]
    pub fn or(self, fallback: usize) -> usize {
        if let Repeat::Int(n) = self {
            n
        } else {
            fallback
        }
    }
    /// Fallback to one (default)
    #[inline]
    pub fn d(self) -> usize {
        self.or(1)
    }
}

impl Editor {
    /// Get the next instruction
    pub fn next_inst(&mut self) -> Inst {
        let mut n = 0;
        let mut shifted = false;

        // TODO: Make the switch to normal mode shift more well-coded.
        loop {
            if let EventOption::Key(k) = self.window.poll().unwrap_or(Event::new()).to_option() {
                let c = k.character;
                match c {
                    '\0' => {
                        return Inst(Repeat::Null, match k.scancode {
                            K_ALT => Key::Alt(k.pressed),
                            K_CTRL => Key::Ctrl(k.pressed),
                            K_LEFT_SHIFT | K_RIGHT_SHIFT => Key::Shift(k.pressed),
                            s if k.pressed => match s {
                                K_BKSP => Key::Backspace,
                                K_LEFT => Key::Left,
                                K_RIGHT => Key::Right,
                                K_UP => Key::Up,
                                K_DOWN => Key::Down,
                                K_TAB => Key::Tab,
                                K_ESC => Key::Escape,
                                _ => Key::Unknown(s),
                            },
                            s => Key::Unknown(s),
                        })
                    }
                    _ => if k.pressed {
                        match self.cursor().mode {
                            Mode::Primitive(_) => {
                                return Inst(Repeat::Null, Key::Char(c));
                            },
                            Mode::Command(_) => {
                                n = match c {
                                    '0' if n != 0 => n * 10,
                                    '1'           => n * 10 + 1,
                                    '2'           => n * 10 + 2,
                                    '3'           => n * 10 + 3,
                                    '4'           => n * 10 + 4,
                                    '5'           => n * 10 + 5,
                                    '6'           => n * 10 + 6,
                                    '7'           => n * 10 + 7,
                                    '8'           => n * 10 + 8,
                                    '9'           => n * 10 + 9,
                                    _             => {

                                        return Inst(if n == 0 { Repeat::Null } else { Repeat::Int(n) }, Key::Char(c));
                                    }
                                }
                            }
                        }

                    },
                }
            }
        }

        unreachable!()
    }
}
<|endoftext|>


<commit_before>use std::io::{TcpListener, TcpStream};
use std::io::{Acceptor, Listener};
use std::io::net::udp::UdpSocket;
use std::io::net::ip::{Ipv4Addr, SocketAddr};

struct UtpPacketHeader {
    ver_type: u8, // ver: u4, type: u4
    extension: u8,
    connection_id: u16,
    timestamp_microseconds: u32,
    timestamp_difference_microseconds: u32,
    wnd_size: u32,
    seq_nr: u16,
    ack_nr: u16,
}

impl UtpPacketHeader {
    fn bytes(&self) -> &[u8] {
        unsafe {
            let buf: &[u8, ..20] = std::mem::transmute(self);
            return buf.as_slice();
        }
    }
}

fn connection_handler(stream: TcpStream) {
    let mut sock = stream;
    println!("New client {}", sock.peer_name().unwrap());

    // Read request
    let mut buf = [0, ..512];
    let mut count: uint = 0;

    match sock.read(buf) {
        Err(e) => { println!("Error detected! {}", e) }
        Ok(c) => {
            count = c;
            println!("Received {} bytes:", c);
            println!("{}", std::str::from_utf8(buf).unwrap());
        }
    }

    // Answer request
    match sock.write(buf.slice(0, count)) {
        _ => {}
    }

    println!("Gone!");
    drop(sock);

}

fn main() {
    let header = UtpPacketHeader {
        ver_type: 0 | 0 << 4,
        extension: 0,
        connection_id: 0,
        timestamp_microseconds: 0,
        timestamp_difference_microseconds: 0,
        wnd_size: 0,
        seq_nr: 0,
        ack_nr: 0,
    };

    let mut buf = [0, ..512];
    let mut sock = UdpSocket::bind(SocketAddr { ip: Ipv4Addr(127,0,0,1), port: 8080 }).unwrap();
    match sock.recvfrom(buf) {
        Ok((_, src)) => {
            let _ = sock.sendto(header.bytes(), src);
        }
        Err(_) => {}
    }
    drop(sock);
    return;
    // Create socket
    let socket = TcpListener::bind("127.0.0.1", 8080);

    // Listen for new connections
    let mut acceptor = socket.listen();

    // Spawn a new process for handling each incoming connection
    for stream in acceptor.incoming() {
        match stream {
            Err(e) => { println!("{}", e) }
            Ok(stream) => spawn(proc() { connection_handler(stream) })
        }
    }

    drop(acceptor);
}
<commit_msg>Shut up warnings.<commit_after>use std::io::{TcpListener, TcpStream};
use std::io::{Acceptor, Listener};
use std::io::net::udp::UdpSocket;
use std::io::net::ip::{Ipv4Addr, SocketAddr};

#[allow(dead_code)]
struct UtpPacketHeader {
    ver_type: u8, // ver: u4, type: u4
    extension: u8,
    connection_id: u16,
    timestamp_microseconds: u32,
    timestamp_difference_microseconds: u32,
    wnd_size: u32,
    seq_nr: u16,
    ack_nr: u16,
}

impl UtpPacketHeader {
    fn bytes(&self) -> &[u8] {
        unsafe {
            let buf: &[u8, ..20] = std::mem::transmute(self);
            return buf.as_slice();
        }
    }
}

fn connection_handler(stream: TcpStream) {
    let mut sock = stream;
    println!("New client {}", sock.peer_name().unwrap());

    // Read request
    let mut buf = [0, ..512];
    let mut count: uint = 0;

    match sock.read(buf) {
        Err(e) => { println!("Error detected! {}", e) }
        Ok(c) => {
            count = c;
            println!("Received {} bytes:", c);
            println!("{}", std::str::from_utf8(buf).unwrap());
        }
    }

    // Answer request
    match sock.write(buf.slice(0, count)) {
        _ => {}
    }

    println!("Gone!");
    drop(sock);

}

fn main() {
    let header = UtpPacketHeader {
        ver_type: 0 | 0 << 4,
        extension: 0,
        connection_id: 0,
        timestamp_microseconds: 0,
        timestamp_difference_microseconds: 0,
        wnd_size: 0,
        seq_nr: 0,
        ack_nr: 0,
    };

    let mut buf = [0, ..512];
    let mut sock = UdpSocket::bind(SocketAddr { ip: Ipv4Addr(127,0,0,1), port: 8080 }).unwrap();
    match sock.recvfrom(buf) {
        Ok((_, src)) => {
            let _ = sock.sendto(header.bytes(), src);
        }
        Err(_) => {}
    }
    drop(sock);
    return;
    // Create socket
    let socket = TcpListener::bind("127.0.0.1", 8080);

    // Listen for new connections
    let mut acceptor = socket.listen();

    // Spawn a new process for handling each incoming connection
    for stream in acceptor.incoming() {
        match stream {
            Err(e) => { println!("{}", e) }
            Ok(stream) => spawn(proc() { connection_handler(stream) })
        }
    }

    drop(acceptor);
}
<|endoftext|>


<commit_before>/**********************************************************\
|                                                          |
|                          hprose                          |
|                                                          |
| Official WebSite: http://www.hprose.com/                 |
|                   http://www.hprose.org/                 |
|                                                          |
\**********************************************************/
/**********************************************************\
 *                                                        *
 * io/encoder.rs                                          *
 *                                                        *
 * hprose encoder for Rust.                               *
 *                                                        *
 * LastModified: Sep 20, 2016                             *
 * Author: Chen Fei <cf@hprose.com>                       *
 *                                                        *
\**********************************************************/

use super::Hprose;

use std::hash::{Hash, BuildHasher};
use std::collections::HashMap;

pub trait Encoder {
    // Primitive types:
    fn write_nil(&mut self);
    fn write_bool(&mut self, v: bool);
    fn write_i64(&mut self, v: i64);
    fn write_u64(&mut self, v: u64);
    fn write_f32(&mut self, v: f32);
    fn write_f64(&mut self, v: f64);
    fn write_char(&mut self, v: char);
    fn write_str(&mut self, v: &str);
    fn write_bytes(&mut self, v: &[u8]);

    // Compound types:

    // Specialized types:
    fn write_option<F>(&mut self, f: F) where F: FnOnce(&mut Self);
    fn write_seq<F>(&mut self, len: usize, f: F) where F: FnOnce(&mut Self);
    fn write_map<F>(&mut self, len: usize, f: F) where F: FnOnce(&mut Self);

    // Reference:
    fn write_ref<T>(&mut self, p: *const T) -> bool;
    fn set_ref<T>(&mut self, p: *const T);
}

pub trait Encodable {
    fn encode<W: Encoder>(&self, w: &mut W);
}

impl Encodable for bool {
    fn encode<W: Encoder>(&self, w: &mut W) {
        w.write_bool(*self);
    }
}

impl Encodable for i8 {
    fn encode<W: Encoder>(&self, w: &mut W) {
        w.write_i64(*self as i64);
    }
}

impl Encodable for i16 {
    fn encode<W: Encoder>(&self, w: &mut W) {
        w.write_i64(*self as i64);
    }
}

impl Encodable for i32 {
    fn encode<W: Encoder>(&self, w: &mut W) {
        w.write_i64(*self as i64);
    }
}

impl Encodable for i64 {
    fn encode<W: Encoder>(&self, w: &mut W) {
        w.write_i64(*self);
    }
}

impl Encodable for isize {
    fn encode<W: Encoder>(&self, w: &mut W) {
        w.write_i64(*self as i64);
    }
}

impl Encodable for u8 {
    fn encode<W: Encoder>(&self, w: &mut W) {
        w.write_u64(*self as u64);
    }
}

impl Encodable for u16 {
    fn encode<W: Encoder>(&self, w: &mut W) {
        w.write_u64(*self as u64);
    }
}

impl Encodable for u32 {
    fn encode<W: Encoder>(&self, w: &mut W) {
        w.write_u64(*self as u64);
    }
}

impl Encodable for u64 {
    fn encode<W: Encoder>(&self, w: &mut W) {
        w.write_u64(*self);
    }
}

impl Encodable for usize {
    fn encode<W: Encoder>(&self, w: &mut W) {
        w.write_u64(*self as u64);
    }
}

impl Encodable for f32 {
    fn encode<W: Encoder>(&self, w: &mut W) {
        w.write_f32(*self);
    }
}

impl Encodable for f64 {
    fn encode<W: Encoder>(&self, w: &mut W) {
        w.write_f64(*self);
    }
}

impl Encodable for char {
    fn encode<W: Encoder>(&self, w: &mut W) {
        w.write_char(*self);
    }
}

impl Encodable for str {
    fn encode<W: Encoder>(&self, w: &mut W) {
        w.write_str(self);
    }
}

impl<'a> Encodable for &'a str {
    fn encode<W: Encoder>(&self, w: &mut W) {
        w.write_str(*self);
    }
}

impl Encodable for String {
    fn encode<W: Encoder>(&self, w: &mut W) {
        w.write_str(self);
    }
}

use std::{mem, ptr};

impl<T: Encodable> Encodable for [T] {
    fn encode<W: Encoder>(&self, w: &mut W) {
        w.set_ref(ptr::null::<&[T]>());
        // todo: check i8
        if mem::size_of::<T>() == 1 {
            w.write_bytes(unsafe {
                mem::transmute::<&[T], &[u8]>(self)
            });
        } else {
            w.write_seq(self.len(), |w| {
                for e in self {
                    e.encode(w);
                }
            });
        }
    }
}

impl<T: Encodable> Encodable for Vec<T> {
    fn encode<W: Encoder>(&self, w: &mut W) {
        if w.write_ref(self) {
            return
        }
        w.set_ref(self);
        w.write_seq(self.len(), |w| {
            for e in self {
                e.encode(w);
            }
        });
    }
}

impl<K, V, S> Encodable for HashMap<K, V, S>
where K: Encodable + Hash + Eq,
      V: Encodable,
      S: BuildHasher
{
    fn encode<W: Encoder>(&self, w: &mut W) {
        w.write_map(self.len(), |e| {
            for (key, val) in self {
                key.encode(e);
                val.encode(e);
            }
        })
    }
}

impl<T: Encodable> Encodable for Option<T> {
    fn encode<W: Encoder>(&self, w: &mut W) {
        w.write_option(|w| {
            match *self {
                None => w.write_nil(),
                Some(ref v) => v.encode(w)
            }
        })
    }
}

impl Encodable for Hprose {
    fn encode<W: Encoder>(&self, w: &mut W) {
        match *self {
            Hprose::Nil => w.write_nil(),
            Hprose::String(ref s) => s.encode(w),
            _ => ()
        }
    }
}
<commit_msg>Added () Box array encoders.<commit_after>/**********************************************************\
|                                                          |
|                          hprose                          |
|                                                          |
| Official WebSite: http://www.hprose.com/                 |
|                   http://www.hprose.org/                 |
|                                                          |
\**********************************************************/
/**********************************************************\
 *                                                        *
 * io/encoder.rs                                          *
 *                                                        *
 * hprose encoder for Rust.                               *
 *                                                        *
 * LastModified: Sep 21, 2016                             *
 * Author: Chen Fei <cf@hprose.com>                       *
 *                                                        *
\**********************************************************/

use super::Hprose;

use std::hash::{Hash, BuildHasher};
use std::collections::HashMap;

pub trait Encoder {
    // Primitive types:
    fn write_nil(&mut self);
    fn write_bool(&mut self, v: bool);
    fn write_i64(&mut self, v: i64);
    fn write_u64(&mut self, v: u64);
    fn write_f32(&mut self, v: f32);
    fn write_f64(&mut self, v: f64);
    fn write_char(&mut self, v: char);
    fn write_str(&mut self, v: &str);
    fn write_bytes(&mut self, v: &[u8]);

    // Compound types:

    // Specialized types:
    fn write_option<F>(&mut self, f: F) where F: FnOnce(&mut Self);
    fn write_seq<F>(&mut self, len: usize, f: F) where F: FnOnce(&mut Self);
    fn write_map<F>(&mut self, len: usize, f: F) where F: FnOnce(&mut Self);

    // Reference:
    fn write_ref<T>(&mut self, p: *const T) -> bool;
    fn set_ref<T>(&mut self, p: *const T);
}

pub trait Encodable {
    fn encode<W: Encoder>(&self, w: &mut W);
}

impl Encodable for () {
    fn encode<W: Encoder>(&self, w: &mut W) {
        w.write_nil()
    }
}

impl Encodable for bool {
    fn encode<W: Encoder>(&self, w: &mut W) {
        w.write_bool(*self);
    }
}

impl Encodable for i8 {
    fn encode<W: Encoder>(&self, w: &mut W) {
        w.write_i64(*self as i64);
    }
}

impl Encodable for i16 {
    fn encode<W: Encoder>(&self, w: &mut W) {
        w.write_i64(*self as i64);
    }
}

impl Encodable for i32 {
    fn encode<W: Encoder>(&self, w: &mut W) {
        w.write_i64(*self as i64);
    }
}

impl Encodable for i64 {
    fn encode<W: Encoder>(&self, w: &mut W) {
        w.write_i64(*self);
    }
}

impl Encodable for isize {
    fn encode<W: Encoder>(&self, w: &mut W) {
        w.write_i64(*self as i64);
    }
}

impl Encodable for u8 {
    fn encode<W: Encoder>(&self, w: &mut W) {
        w.write_u64(*self as u64);
    }
}

impl Encodable for u16 {
    fn encode<W: Encoder>(&self, w: &mut W) {
        w.write_u64(*self as u64);
    }
}

impl Encodable for u32 {
    fn encode<W: Encoder>(&self, w: &mut W) {
        w.write_u64(*self as u64);
    }
}

impl Encodable for u64 {
    fn encode<W: Encoder>(&self, w: &mut W) {
        w.write_u64(*self);
    }
}

impl Encodable for usize {
    fn encode<W: Encoder>(&self, w: &mut W) {
        w.write_u64(*self as u64);
    }
}

impl Encodable for f32 {
    fn encode<W: Encoder>(&self, w: &mut W) {
        w.write_f32(*self);
    }
}

impl Encodable for f64 {
    fn encode<W: Encoder>(&self, w: &mut W) {
        w.write_f64(*self);
    }
}

impl Encodable for char {
    fn encode<W: Encoder>(&self, w: &mut W) {
        w.write_char(*self);
    }
}

impl Encodable for str {
    fn encode<W: Encoder>(&self, w: &mut W) {
        w.write_str(self);
    }
}

impl Encodable for String {
    fn encode<W: Encoder>(&self, w: &mut W) {
        w.write_str(self);
    }
}

impl<'a, T: ?Sized + Encodable> Encodable for &'a T {
    fn encode<W: Encoder>(&self, w: &mut W) {
        (**self).encode(w)
    }
}

impl<T: ?Sized + Encodable> Encodable for Box<T> {
    fn encode<W: Encoder>(&self, w: &mut W) {
        (**self).encode(w)
    }
}

macro_rules! array {
    () => ();
    ($($size:expr), +) => (
        $(impl<T: Encodable> Encodable for [T;($size)] {
            fn encode<W: Encoder>(&self, w: &mut W) {
                w.set_ref(ptr::null::<&[T]>());
                w.write_seq(self.len(), |w| {
                    for e in self {
                        e.encode(w);
                    }
                });
            }
        })+
    )
}

array! { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32 }

use std::{mem, ptr};

impl<T: Encodable> Encodable for [T] {
    fn encode<W: Encoder>(&self, w: &mut W) {
        w.set_ref(ptr::null::<&[T]>());
        // todo: check i8
        if mem::size_of::<T>() == 1 {
            w.write_bytes(unsafe {
                mem::transmute::<&[T], &[u8]>(self)
            });
        } else {
            w.write_seq(self.len(), |w| {
                for e in self {
                    e.encode(w);
                }
            });
        }
    }
}

impl<T: Encodable> Encodable for Vec<T> {
    fn encode<W: Encoder>(&self, w: &mut W) {
        if w.write_ref(self) {
            return
        }
        w.set_ref(self);
        w.write_seq(self.len(), |w| {
            for e in self {
                e.encode(w);
            }
        });
    }
}

impl<K, V, S> Encodable for HashMap<K, V, S>
where K: Encodable + Hash + Eq,
      V: Encodable,
      S: BuildHasher
{
    fn encode<W: Encoder>(&self, w: &mut W) {
        w.write_map(self.len(), |e| {
            for (key, val) in self {
                key.encode(e);
                val.encode(e);
            }
        })
    }
}

impl<T: Encodable> Encodable for Option<T> {
    fn encode<W: Encoder>(&self, w: &mut W) {
        w.write_option(|w| {
            match *self {
                None => w.write_nil(),
                Some(ref v) => v.encode(w)
            }
        })
    }
}

impl Encodable for Hprose {
    fn encode<W: Encoder>(&self, w: &mut W) {
        match *self {
            Hprose::Nil => w.write_nil(),
            Hprose::String(ref s) => s.encode(w),
            _ => ()
        }
    }
}
<|endoftext|>


<commit_before>#![feature(plugin, custom_derive, custom_attribute)]
#![plugin(rocket_codegen)]
extern crate rocket;
extern crate serde;
extern crate itertools;

#[macro_use]
extern crate serde_derive;
extern crate rocket_contrib;

#[cfg(test)]
extern crate serde_json;

use rocket_contrib::Json;

use std::io;
use std::path::{Path, PathBuf};

use rocket::response::NamedFile;

mod automata;
use automata::{Dfa, Nfa, Unsanitary};

#[get("/")]
fn index() -> io::Result<NamedFile> {
    NamedFile::open("../frontend/build/index.html")
}

#[get("/<file..>")]
fn files(file: PathBuf) -> Option<NamedFile> {
    NamedFile::open(Path::new("../frontend/build/").join(file)).ok()
}

#[post("/submit", format = "application/json", data = "<data>")]
fn submit_nfa(data: Json<Nfa<Unsanitary>>) -> Json<Dfa> {
    Json(
        data.into_inner()
            .check()
            .unwrap()
            .make_deterministic()
            .minimise(),
    )
}

fn rocket() -> rocket::Rocket {
    rocket::ignite().mount("/", routes![index, submit_nfa, files])
}

fn main() {
    rocket().launch();
}

#[cfg(test)]
mod test {
    use super::rocket;
    use rocket::local::Client;
    use rocket::http::Status;
    use rocket::http::ContentType;

    use serde_json;
    use automata::*;

    /// Test home page ("/" or "/index.html")
    #[test]
    fn test_index() {
        let rocket = rocket();
        let client = Client::new(rocket).expect("valid rocket instance");
        let mut response = client.get("/").dispatch();

        assert_eq!(response.status(), Status::Ok);
        assert_eq!(response.content_type(), Some(ContentType::HTML));
        assert!(
            response
                .body_string()
                .unwrap()
                .contains("You need to enable JavaScript to run this app.")
        );
        //assert!(response.headers().get_one("X-Special").is_some());

        let response = client.get("/index.html").dispatch();
        assert_eq!(response.status(), Status::Ok);
        assert_eq!(response.content_type(), Some(ContentType::HTML));
    }

    #[test]
    fn test_not_found() {
        let rocket = rocket();
        let client = Client::new(rocket).expect("valid rocket instance");
        let response = client.get("/asdfasdfasdf").dispatch();
        assert_eq!(response.status(), Status::NotFound);
    }

    /// Test POSTing of NFA in JSON
    #[test]
    fn test_submit_nfa() {
        let rocket = rocket();
        let client = Client::new(rocket).expect("valid rocket instance");

        //Test good JSON
        let input = r#"{
            "start": "1",
            "alphabet": ["a", "b"],
            "nodes": {
                "1": {
                    "a": ["1", "2"],
                    "b": ["1"]
                },
                "2": {
                    "a": ["3"],
                    "b": ["3"]
                },
                "3": {
                    "a": ["1"],
                    "b": ["2"]
                }
            },
            "final_states": ["3"]
        }"#;

        let mut response = client
            .post("/submit")
            .body(input)
            .header(ContentType::JSON)
            .dispatch();

        assert_eq!(response.status(), Status::Ok);

        //Convert JSON to DFA
        let body_string: &str = &(response.body_string()).unwrap();
        let dfa_thing: Dfa = serde_json::from_str(body_string).unwrap();
    }

    #[test]
    fn test_empty_nfa() {
        let rocket = rocket();
        let client = Client::new(rocket).expect("valid rocket instance");
        let response = client
            .post("/submit")
            .body("{}")
            .header(ContentType::JSON)
            .dispatch();

        assert_eq!(response.status(), Status::BadRequest);
    }

}
<commit_msg>test for re-submitting - fix later<commit_after>#![feature(plugin, custom_derive, custom_attribute)]
#![plugin(rocket_codegen)]
extern crate rocket;
extern crate serde;
extern crate itertools;

#[macro_use]
extern crate serde_derive;
extern crate rocket_contrib;

#[cfg(test)]
extern crate serde_json;

use rocket_contrib::Json;

use std::io;
use std::path::{Path, PathBuf};

use rocket::response::NamedFile;

mod automata;
use automata::{Dfa, Nfa, Unsanitary};

#[get("/")]
fn index() -> io::Result<NamedFile> {
    NamedFile::open("../frontend/build/index.html")
}

#[get("/<file..>")]
fn files(file: PathBuf) -> Option<NamedFile> {
    NamedFile::open(Path::new("../frontend/build/").join(file)).ok()
}

#[post("/submit", format = "application/json", data = "<data>")]
fn submit_nfa(data: Json<Nfa<Unsanitary>>) -> Json<Dfa> {
    Json(
        data.into_inner()
            .check()
            .unwrap()
            .make_deterministic()
            .minimise(),
    )
}

fn rocket() -> rocket::Rocket {
    rocket::ignite().mount("/", routes![index, submit_nfa, files])
}

fn main() {
    rocket().launch();
}

#[cfg(test)]
mod test {
    use super::rocket;
    use rocket::local::Client;
    use rocket::http::Status;
    use rocket::http::ContentType;

    use serde_json;
    use automata::*;

    /// Test home page ("/" or "/index.html")
    #[test]
    fn test_index() {
        let rocket = rocket();
        let client = Client::new(rocket).expect("valid rocket instance");
        let mut response = client.get("/").dispatch();

        assert_eq!(response.status(), Status::Ok);
        assert_eq!(response.content_type(), Some(ContentType::HTML));
        assert!(
            response
                .body_string()
                .unwrap()
                .contains("You need to enable JavaScript to run this app.")
        );
        //assert!(response.headers().get_one("X-Special").is_some());

        let response = client.get("/index.html").dispatch();
        assert_eq!(response.status(), Status::Ok);
        assert_eq!(response.content_type(), Some(ContentType::HTML));
    }

    #[test]
    fn test_not_found() {
        let rocket = rocket();
        let client = Client::new(rocket).expect("valid rocket instance");
        let response = client.get("/asdfasdfasdf").dispatch();
        assert_eq!(response.status(), Status::NotFound);
    }

    /// Test POSTing of NFA in JSON
    #[test]
    fn test_submit_nfa() {
        let rocket = rocket();
        let client = Client::new(rocket).expect("valid rocket instance");

        //Test good JSON
        let input = r#"{
            "start": "1",
            "alphabet": ["a", "b"],
            "nodes": {
                "1": {
                    "a": ["1", "2"],
                    "b": ["1"]
                },
                "2": {
                    "a": ["3"],
                    "b": ["3"]
                },
                "3": {
                    "a": ["1"],
                    "b": ["2"]
                }
            },
            "final_states": ["3"]
        }"#;

        let mut response = client
            .post("/submit")
            .body(input)
            .header(ContentType::JSON)
            .dispatch();

        assert_eq!(response.status(), Status::Ok);

        //Convert JSON to DFA
        let body_string: &str = &(response.body_string()).unwrap();
        let dfa_thing: Dfa = serde_json::from_str(body_string).unwrap();
    }

    #[test]
    fn test_empty_nfa() {
        let rocket = rocket();
        let client = Client::new(rocket).expect("valid rocket instance");
        let response = client
            .post("/submit")
            .body("{}")
            .header(ContentType::JSON)
            .dispatch();

        assert_eq!(response.status(), Status::BadRequest);
    }

    #[test]
    fn test_double_submit_nfa_dfa() {
        let rocket = rocket();
        let client = Client::new(rocket).expect("valid rocket instance");

        //NFA
        let input = r#"{
            "start": "1",
            "alphabet": ["a", "b"],
            "nodes": {
                "1": {
                    "a": ["1", "2"],
                    "b": ["1"]
                },
                "2": {
                    "a": ["3"],
                    "b": ["3"]
                },
                "3": {
                    "a": ["1"],
                    "b": ["2"]
                }
            },
            "final_states": ["3"]
        }"#;

        let mut response = client
            .post("/submit")
            .body(input)
            .header(ContentType::JSON)
            .dispatch();

        assert_eq!(response.status(), Status::Ok);

        //Convert JSON to DFA
        let dfa_json: &str = &(response.body_string()).unwrap();

        //Re-submit the DFA JSON we received
        let response = client
            .post("/submit")
            .body(dfa_json)
            .header(ContentType::JSON)
            .dispatch();

        assert_eq!(response.status(), Status::Ok);
    }

}
<|endoftext|>


<commit_before>// Copyright 2018 Guillaume Pinot (@TeXitoi) <texitoi@texitoi.eu>,
// Kevin Knapp (@kbknapp) <kbknapp@gmail.com>, and
// Ana Hobden (@hoverbear) <operator@hoverbear.org>
//
// 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 work was derived from Structopt (https://github.com/TeXitoi/structopt)
// commit#ea76fa1b1b273e65e3b0b1046643715b49bec51f which is licensed under the
// MIT/Apache 2.0 license.

use crate::utils;

use clap::{CommandFactory, Parser, Subcommand, ValueEnum};

#[test]
fn doc_comments() {
    /// Lorem ipsum
    #[derive(Parser, PartialEq, Debug)]
    struct LoremIpsum {
        /// Fooify a bar
        /// and a baz
        #[arg(short, long)]
        foo: bool,
    }

    let help = utils::get_long_help::<LoremIpsum>();
    assert!(help.contains("Lorem ipsum"));
    assert!(help.contains("Fooify a bar and a baz"));
}

#[test]
fn help_is_better_than_comments() {
    /// Lorem ipsum
    #[derive(Parser, PartialEq, Debug)]
    #[command(name = "lorem-ipsum", about = "Dolor sit amet")]
    struct LoremIpsum {
        /// Fooify a bar
        #[arg(short, long, help = "DO NOT PASS A BAR UNDER ANY CIRCUMSTANCES")]
        foo: bool,
    }

    let help = utils::get_long_help::<LoremIpsum>();
    assert!(help.contains("Dolor sit amet"));
    assert!(!help.contains("Lorem ipsum"));
    assert!(help.contains("DO NOT PASS A BAR"));
}

#[test]
fn empty_line_in_doc_comment_is_double_linefeed() {
    /// Foo.
    ///
    /// Bar
    #[derive(Parser, PartialEq, Debug)]
    #[command(name = "lorem-ipsum")]
    struct LoremIpsum {}

    let help = utils::get_long_help::<LoremIpsum>();
    assert!(help.starts_with(
        "\
Foo.

Bar

Usage:"
    ));
}

#[test]
fn field_long_doc_comment_both_help_long_help() {
    /// Lorem ipsumclap
    #[derive(Parser, PartialEq, Debug)]
    #[command(name = "lorem-ipsum", about = "Dolor sit amet")]
    struct LoremIpsum {
        /// Dot is removed from multiline comments.
        ///
        /// Long help
        #[arg(long)]
        foo: bool,

        /// Dot is removed from one short comment.
        #[arg(long)]
        bar: bool,
    }

    let short_help = utils::get_help::<LoremIpsum>();
    let long_help = utils::get_long_help::<LoremIpsum>();

    assert!(short_help.contains("Dot is removed from one short comment"));
    assert!(!short_help.contains("Dot is removed from one short comment."));
    assert!(short_help.contains("Dot is removed from multiline comments"));
    assert!(!short_help.contains("Dot is removed from multiline comments."));
    assert!(long_help.contains("Long help"));
    assert!(!short_help.contains("Long help"));
}

#[test]
fn top_long_doc_comment_both_help_long_help() {
    /// Lorem ipsumclap
    #[derive(Parser, Debug)]
    #[command(name = "lorem-ipsum", about = "Dolor sit amet")]
    struct LoremIpsum {
        #[command(subcommand)]
        foo: SubCommand,
    }

    #[derive(Parser, Debug)]
    pub enum SubCommand {
        /// DO NOT PASS A BAR UNDER ANY CIRCUMSTANCES
        ///
        /// Or something else
        Foo {
            #[arg(help = "foo")]
            bars: String,
        },
    }

    let short_help = utils::get_help::<LoremIpsum>();
    let long_help = utils::get_subcommand_long_help::<LoremIpsum>("foo");

    assert!(!short_help.contains("Or something else"));
    assert!(long_help.contains("DO NOT PASS A BAR UNDER ANY CIRCUMSTANCES"));
    assert!(long_help.contains("Or something else"));
}

#[test]
fn verbatim_doc_comment() {
    /// DANCE!
    ///
    ///                    ()
    ///                    |
    ///               (   ()   )
    ///     ) ________    //  )
    ///  ()  |\       \  //
    /// ( \\__ \ ______\//
    ///    \__) |       |
    ///      |  |       |
    ///       \ |       |
    ///        \|_______|
    ///        //    \\
    ///       ((     ||
    ///        \\    ||
    ///      ( ()    ||
    ///       (      () ) )
    #[derive(Parser, Debug)]
    #[command(verbatim_doc_comment)]
    struct SeeFigure1 {
        #[arg(long)]
        foo: bool,
    }

    let help = utils::get_long_help::<SeeFigure1>();
    let sample = r#"
                   ()
                   |
              (   ()   )
    ) ________    //  )
 ()  |\       \  //
( \\__ \ ______\//
   \__) |       |
     |  |       |
      \ |       |
       \|_______|
       //    \\
      ((     ||
       \\    ||
     ( ()    ||
      (      () ) )"#;

    assert!(help.contains(sample))
}

#[test]
fn verbatim_doc_comment_field() {
    #[derive(Parser, Debug)]
    struct Command {
        /// This help ends in a period.
        #[arg(long, verbatim_doc_comment)]
        foo: bool,
        /// This help does not end in a period.
        #[arg(long)]
        bar: bool,
    }

    let help = utils::get_long_help::<Command>();

    assert!(help.contains("This help ends in a period."));
    assert!(help.contains("This help does not end in a period"));
}

#[test]
fn multiline_separates_default() {
    #[derive(Parser, Debug)]
    struct Command {
        /// Multiline
        ///
        /// Doc comment
        #[arg(long, default_value = "x")]
        x: String,
    }

    let help = utils::get_long_help::<Command>();
    assert!(!help.contains("Doc comment [default"));
    assert!(help.lines().any(|s| s.trim().starts_with("[default")));

    // The short help should still have the default on the same line
    let help = utils::get_help::<Command>();
    assert!(help.contains("Multiline [default"));
}

#[test]
fn value_enum_multiline_doc_comment() {
    #[derive(Parser, Debug)]
    struct Command {
        x: LoremIpsum,
    }

    #[derive(ValueEnum, Clone, PartialEq, Debug)]
    enum LoremIpsum {
        /// Doc comment summary
        ///
        /// The doc comment body is ignored
        Bar,
    }

    let help = utils::get_long_help::<Command>();

    assert!(help.contains("Doc comment summary"));

    // There is no long help text for possible values. The long help only contains the summary.
    assert!(!help.contains("The doc comment body is ignored"));
}

#[test]
fn doc_comment_about_handles_both_abouts() {
    /// Opts doc comment summary
    #[derive(Parser, Debug)]
    pub struct Opts {
        #[command(subcommand)]
        pub cmd: Sub,
    }

    /// Sub doc comment summary
    ///
    /// Sub doc comment body
    #[derive(Parser, PartialEq, Eq, Debug)]
    pub enum Sub {
        Compress { output: String },
    }

    let cmd = Opts::command();
    assert_eq!(
        cmd.get_about().map(|s| s.to_string()),
        Some("Opts doc comment summary".to_owned())
    );
    // clap will fallback to `about` on `None`.  The main care about is not providing a `Sub` doc
    // comment.
    assert_eq!(cmd.get_long_about(), None);
}

#[test]
fn respect_subcommand_doc_comment() {
    #[derive(Parser, Debug)]
    pub enum Cmd {
        /// For child
        #[command(subcommand)]
        Child(Child),
    }

    #[derive(Subcommand, Debug)]
    pub enum Child {
        One,
        Twp,
    }

    const OUTPUT: &str = "\
Usage: cmd <COMMAND>

Commands:
  child  For child
  help   Print this message or the help of the given subcommand(s)

Options:
  -h, --help  Print help information
";
    utils::assert_output::<Cmd>("cmd --help", OUTPUT, false);
}
<commit_msg>test(derive): Verify long_help behavior<commit_after>// Copyright 2018 Guillaume Pinot (@TeXitoi) <texitoi@texitoi.eu>,
// Kevin Knapp (@kbknapp) <kbknapp@gmail.com>, and
// Ana Hobden (@hoverbear) <operator@hoverbear.org>
//
// 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 work was derived from Structopt (https://github.com/TeXitoi/structopt)
// commit#ea76fa1b1b273e65e3b0b1046643715b49bec51f which is licensed under the
// MIT/Apache 2.0 license.

use crate::utils;

use clap::{CommandFactory, Parser, Subcommand, ValueEnum};

#[test]
fn doc_comments() {
    /// Lorem ipsum
    #[derive(Parser, PartialEq, Debug)]
    struct LoremIpsum {
        /// Fooify a bar
        /// and a baz
        #[arg(short, long)]
        foo: bool,
    }

    let help = utils::get_long_help::<LoremIpsum>();
    assert!(help.contains("Lorem ipsum"));
    assert!(help.contains("Fooify a bar and a baz"));
}

#[test]
fn help_is_better_than_comments() {
    /// Lorem ipsum
    #[derive(Parser, PartialEq, Debug)]
    #[command(name = "lorem-ipsum", about = "Dolor sit amet")]
    struct LoremIpsum {
        /// Fooify a bar
        #[arg(short, long, help = "DO NOT PASS A BAR UNDER ANY CIRCUMSTANCES")]
        foo: bool,
    }

    let help = utils::get_long_help::<LoremIpsum>();
    assert!(help.contains("Dolor sit amet"));
    assert!(!help.contains("Lorem ipsum"));
    assert!(help.contains("DO NOT PASS A BAR"));
}

#[test]
fn empty_line_in_doc_comment_is_double_linefeed() {
    /// Foo.
    ///
    /// Bar
    #[derive(Parser, PartialEq, Debug)]
    #[command(name = "lorem-ipsum")]
    struct LoremIpsum {}

    let help = utils::get_long_help::<LoremIpsum>();
    assert!(help.starts_with(
        "\
Foo.

Bar

Usage:"
    ));
}

#[test]
fn field_long_doc_comment_both_help_long_help() {
    /// Lorem ipsumclap
    #[derive(Parser, PartialEq, Debug)]
    #[command(name = "lorem-ipsum", about = "Dolor sit amet")]
    struct LoremIpsum {
        /// Dot is removed from multiline comments.
        ///
        /// Long help
        #[arg(long)]
        foo: bool,

        /// Dot is removed from one short comment.
        #[arg(long)]
        bar: bool,
    }

    let short_help = utils::get_help::<LoremIpsum>();
    let long_help = utils::get_long_help::<LoremIpsum>();

    assert!(short_help.contains("Dot is removed from one short comment"));
    assert!(!short_help.contains("Dot is removed from one short comment."));
    assert!(short_help.contains("Dot is removed from multiline comments"));
    assert!(!short_help.contains("Dot is removed from multiline comments."));
    assert!(long_help.contains("Long help"));
    assert!(!short_help.contains("Long help"));
}

#[test]
fn top_long_doc_comment_both_help_long_help() {
    /// Lorem ipsumclap
    #[derive(Parser, Debug)]
    #[command(name = "lorem-ipsum", about = "Dolor sit amet")]
    struct LoremIpsum {
        #[command(subcommand)]
        foo: SubCommand,
    }

    #[derive(Parser, Debug)]
    pub enum SubCommand {
        /// DO NOT PASS A BAR UNDER ANY CIRCUMSTANCES
        ///
        /// Or something else
        Foo {
            #[arg(help = "foo")]
            bars: String,
        },
    }

    let short_help = utils::get_help::<LoremIpsum>();
    let long_help = utils::get_subcommand_long_help::<LoremIpsum>("foo");

    assert!(!short_help.contains("Or something else"));
    assert!(long_help.contains("DO NOT PASS A BAR UNDER ANY CIRCUMSTANCES"));
    assert!(long_help.contains("Or something else"));
}

#[test]
fn verbatim_doc_comment() {
    /// DANCE!
    ///
    ///                    ()
    ///                    |
    ///               (   ()   )
    ///     ) ________    //  )
    ///  ()  |\       \  //
    /// ( \\__ \ ______\//
    ///    \__) |       |
    ///      |  |       |
    ///       \ |       |
    ///        \|_______|
    ///        //    \\
    ///       ((     ||
    ///        \\    ||
    ///      ( ()    ||
    ///       (      () ) )
    #[derive(Parser, Debug)]
    #[command(verbatim_doc_comment)]
    struct SeeFigure1 {
        #[arg(long)]
        foo: bool,
    }

    let help = utils::get_long_help::<SeeFigure1>();
    let sample = r#"
                   ()
                   |
              (   ()   )
    ) ________    //  )
 ()  |\       \  //
( \\__ \ ______\//
   \__) |       |
     |  |       |
      \ |       |
       \|_______|
       //    \\
      ((     ||
       \\    ||
     ( ()    ||
      (      () ) )"#;

    assert!(help.contains(sample))
}

#[test]
fn verbatim_doc_comment_field() {
    #[derive(Parser, Debug)]
    struct Command {
        /// This help ends in a period.
        #[arg(long, verbatim_doc_comment)]
        foo: bool,
        /// This help does not end in a period.
        #[arg(long)]
        bar: bool,
    }

    let help = utils::get_long_help::<Command>();

    assert!(help.contains("This help ends in a period."));
    assert!(help.contains("This help does not end in a period"));
}

#[test]
fn multiline_separates_default() {
    #[derive(Parser, Debug)]
    struct Command {
        /// Multiline
        ///
        /// Doc comment
        #[arg(long, default_value = "x")]
        x: String,
    }

    let help = utils::get_long_help::<Command>();
    assert!(!help.contains("Doc comment [default"));
    assert!(help.lines().any(|s| s.trim().starts_with("[default")));

    // The short help should still have the default on the same line
    let help = utils::get_help::<Command>();
    assert!(help.contains("Multiline [default"));
}

#[test]
fn value_enum_multiline_doc_comment() {
    #[derive(Parser, Debug)]
    struct Command {
        x: LoremIpsum,
    }

    #[derive(ValueEnum, Clone, PartialEq, Debug)]
    enum LoremIpsum {
        /// Doc comment summary
        ///
        /// The doc comment body is ignored
        Bar,
    }

    let help = utils::get_long_help::<Command>();

    assert!(help.contains("Doc comment summary"));

    // There is no long help text for possible values. The long help only contains the summary.
    assert!(!help.contains("The doc comment body is ignored"));
}

#[test]
fn doc_comment_about_handles_both_abouts() {
    /// Opts doc comment summary
    #[derive(Parser, Debug)]
    pub struct Opts {
        #[command(subcommand)]
        pub cmd: Sub,
    }

    /// Sub doc comment summary
    ///
    /// Sub doc comment body
    #[derive(Parser, PartialEq, Eq, Debug)]
    pub enum Sub {
        Compress { output: String },
    }

    let cmd = Opts::command();
    assert_eq!(
        cmd.get_about().map(|s| s.to_string()),
        Some("Opts doc comment summary".to_owned())
    );
    // clap will fallback to `about` on `None`.  The main care about is not providing a `Sub` doc
    // comment.
    assert_eq!(cmd.get_long_about(), None);
}

#[test]
fn respect_subcommand_doc_comment() {
    #[derive(Parser, Debug)]
    pub enum Cmd {
        /// For child
        #[command(subcommand)]
        Child(Child),
    }

    #[derive(Subcommand, Debug)]
    pub enum Child {
        One,
        Twp,
    }

    const OUTPUT: &str = "\
Usage: cmd <COMMAND>

Commands:
  child  For child
  help   Print this message or the help of the given subcommand(s)

Options:
  -h, --help  Print help information
";
    utils::assert_output::<Cmd>("cmd --help", OUTPUT, false);
}

#[test]
fn force_long_help() {
    /// Lorem ipsum
    #[derive(Parser, PartialEq, Debug)]
    struct LoremIpsum {
        /// Fooify a bar
        /// and a baz.
        #[arg(short, long)]
        foo: bool,
    }

    let help = utils::get_long_help::<LoremIpsum>();
    assert!(help.contains("Fooify a bar and a baz"));
}
<|endoftext|>


<commit_before>// Copyright © 2015, Peter Atashian
// Licensed under the MIT License <LICENSE.md>
//! FFI bindings to dsound.
#![cfg(windows)]
extern crate winapi;
use winapi::*;
extern "system" {
    pub fn DirectSoundCaptureCreate(
        pcGuidDevice: LPCGUID, ppDSC: *mut LPDIRECTSOUNDCAPTURE, pUnkOuter: LPUNKNOWN,
    ) -> HRESULT;
    pub fn DirectSoundCaptureCreate8(
        pcGuidDevice: LPCGUID, ppDSC8: *mut LPDIRECTSOUNDCAPTURE8, pUnkOuter: LPUNKNOWN,
    ) -> HRESULT;
    pub fn DirectSoundCaptureEnumerateA(
        pDSEnumCallback: LPDSENUMCALLBACKA, pContext: LPVOID,
    ) -> HRESULT;
    pub fn DirectSoundCaptureEnumerateW(
        pDSEnumCallback: LPDSENUMCALLBACKW, pContext: LPVOID,
    ) -> HRESULT;
    pub fn DirectSoundCreate(
        pcGuidDevice: LPCGUID, ppDS: *mut LPDIRECTSOUND, pUnkOuter: LPUNKNOWN,
    ) -> HRESULT;
    pub fn DirectSoundCreate8(
        pcGuidDevice: LPCGUID, ppDS8: *mut LPDIRECTSOUND8, pUnkOuter: LPUNKNOWN,
    ) -> HRESULT;
    pub fn DirectSoundEnumerateA(
        pDSEnumCallback: LPDSENUMCALLBACKA, pContext: LPVOID,
    ) -> HRESULT;
    pub fn DirectSoundEnumerateA(
        pDSEnumCallback: LPDSENUMCALLBACKW, pContext: LPVOID,
    ) -> HRESULT;
    pub fn DirectSoundFullDuplexCreate(
        pcGuidCaptureDevice: LPCGUID, pcGuidRenderDevice: LPCGUID,
        pcDSCBufferDesc: LPCDSCBUFFERDESC, pcDSBufferDesc: LPCDSBUFFERDESC, hWnd: HWND,
        dwLevel: DWORD, ppDSFD: *mut LPDIRECTSOUNDFULLDUPLEX,
        ppDSCBuffer8: *mut LPDIRECTSOUNDCAPTUREBUFFER8, ppDSBuffer8: *mut LPDIRECTSOUNDBUFFER8,
        pUnkOuter: LPUNKNOWN,
    ) -> HRESULT;
    pub fn GetDeviceID(pGuidSrc: LPCGUID, pGuidDest: LPGUID) -> HRESULT;
}
<commit_msg>Comment out functions that depend on types that don't exist yet<commit_after>// Copyright © 2015, Peter Atashian
// Licensed under the MIT License <LICENSE.md>
//! FFI bindings to dsound.
#![cfg(windows)]
extern crate winapi;
use winapi::*;
extern "system" {
    // pub fn DirectSoundCaptureCreate(
    //     pcGuidDevice: LPCGUID, ppDSC: *mut LPDIRECTSOUNDCAPTURE, pUnkOuter: LPUNKNOWN,
    // ) -> HRESULT;
    // pub fn DirectSoundCaptureCreate8(
    //     pcGuidDevice: LPCGUID, ppDSC8: *mut LPDIRECTSOUNDCAPTURE8, pUnkOuter: LPUNKNOWN,
    // ) -> HRESULT;
    // pub fn DirectSoundCaptureEnumerateA(
    //     pDSEnumCallback: LPDSENUMCALLBACKA, pContext: LPVOID,
    // ) -> HRESULT;
    // pub fn DirectSoundCaptureEnumerateW(
    //     pDSEnumCallback: LPDSENUMCALLBACKW, pContext: LPVOID,
    // ) -> HRESULT;
    pub fn DirectSoundCreate(
        pcGuidDevice: LPCGUID, ppDS: *mut LPDIRECTSOUND, pUnkOuter: LPUNKNOWN,
    ) -> HRESULT;
    // pub fn DirectSoundCreate8(
    //     pcGuidDevice: LPCGUID, ppDS8: *mut LPDIRECTSOUND8, pUnkOuter: LPUNKNOWN,
    // ) -> HRESULT;
    // pub fn DirectSoundEnumerateA(
    //     pDSEnumCallback: LPDSENUMCALLBACKA, pContext: LPVOID,
    // ) -> HRESULT;
    // pub fn DirectSoundEnumerateW(
    //     pDSEnumCallback: LPDSENUMCALLBACKW, pContext: LPVOID,
    // ) -> HRESULT;
    // pub fn DirectSoundFullDuplexCreate(
    //     pcGuidCaptureDevice: LPCGUID, pcGuidRenderDevice: LPCGUID,
    //     pcDSCBufferDesc: LPCDSCBUFFERDESC, pcDSBufferDesc: LPCDSBUFFERDESC, hWnd: HWND,
    //     dwLevel: DWORD, ppDSFD: *mut LPDIRECTSOUNDFULLDUPLEX,
    //     ppDSCBuffer8: *mut LPDIRECTSOUNDCAPTUREBUFFER8, ppDSBuffer8: *mut LPDIRECTSOUNDBUFFER8,
    //     pUnkOuter: LPUNKNOWN,
    // ) -> HRESULT;
    pub fn GetDeviceID(pGuidSrc: LPCGUID, pGuidDest: LPGUID) -> HRESULT;
}
<|endoftext|>


<commit_before>use std::io::Error as IoError;
use std::io::Read;

pub use parse::ParseError;

mod enums;
mod parse;

pub fn reflect<R>(name: &str, mut spirv: R) -> Result<String, Error>
    where R: Read
{
    let mut data = Vec::new();
    try!(spirv.read_to_end(&mut data));

    // now parsing the document
    let doc = try!(parse::parse_spirv(&data));

    let mut output = String::new();

    {
        // contains the data that was passed as input to this function
        let spirv_data = data.iter().map(|&byte| byte.to_string())
                             .collect::<Vec<String>>()
                             .join(", ");

        // writing the header
        output.push_str(&format!(r#"
pub struct {name} {{
    shader: ::std::sync::Arc<::vulkano::ShaderModule>,
}}

impl {name} {{
    /// Loads the shader in Vulkan as a `ShaderModule`.
    #[inline]
    pub fn load(device: &::std::sync::Arc<::vulkano::Device>) -> {name} {{

        "#, name = name));

        // checking whether each required capability is supported by the vulkan implementation
        for i in doc.instructions.iter() {
            if let &parse::Instruction::Capability(ref cap) = i {
                output.push_str(&format!(r#"
                    if !device.is_capability_supported("{cap}") {{
                        return Err(CapabilityNotSupported);
                    }}"#, cap = capability_name(cap)));
            }
        }

        // follow-up of the header
        output.push_str(&format!(r#"
        unsafe {{
            let data = [{spirv_data}];

            {name} {{
                shader: ::vulkano::ShaderModule::new(device, &data)
            }}
        }}
    }}

    /// Returns the module that was created.
    #[inline]
    pub fn module(&self) -> &::std::sync::Arc<::vulkano::ShaderModule> {{
        &self.shader
    }}
        "#, name = name, spirv_data = spirv_data));

        // writing one method for each entry point of this module
        for instruction in doc.instructions.iter() {
            if let &parse::Instruction::EntryPoint { .. } = instruction {
                output.push_str(&write_entry_point(&doc, instruction));
            }
        }

        // footer
        output.push_str(&format!(r#"
}}
        "#));
    }

    // TODO: remove
    println!("{:#?}", doc);

    Ok(output)
}

#[derive(Debug)]
pub enum Error {
    IoError(IoError),
    ParseError(ParseError),
}

impl From<IoError> for Error {
    #[inline]
    fn from(err: IoError) -> Error {
        Error::IoError(err)
    }
}

impl From<ParseError> for Error {
    #[inline]
    fn from(err: ParseError) -> Error {
        Error::ParseError(err)
    }
}

fn write_entry_point(doc: &parse::Spirv, instruction: &parse::Instruction) -> String {
    let (execution, ep_name, interface) = match instruction {
        &parse::Instruction::EntryPoint { ref execution, id, ref name, ref interface } => {
            (execution, name, interface)
        },
        _ => unreachable!()
    };

    let ty = match *execution {
        enums::ExecutionModel::ExecutionModelVertex => {
            format!("VertexShaderEntryPoint")
        },

        enums::ExecutionModel::ExecutionModelTessellationControl => {
            format!("TessControlShaderEntryPoint")
        },

        enums::ExecutionModel::ExecutionModelTessellationEvaluation => {
            format!("TessEvaluationShaderEntryPoint")
        },

        enums::ExecutionModel::ExecutionModelGeometry => {
            format!("GeometryShaderEntryPoint")
        },

        enums::ExecutionModel::ExecutionModelFragment => {
            let mut output_types = Vec::new();

            for interface in interface.iter() {
                for i in doc.instructions.iter() {
                    match i {
                        &parse::Instruction::Variable { result_type_id, result_id,
                                    storage_class: enums::StorageClass::StorageClassOutput, .. }
                                    if &result_id == interface =>
                        {
                            output_types.push(type_from_id(doc, result_type_id));
                        },
                        _ => ()
                    }
                }
            }

            format!("FragmentShaderEntryPoint<({output})>",
                    output = output_types.join(", ") + ",")
        },

        enums::ExecutionModel::ExecutionModelGLCompute => {
            format!("ComputeShaderEntryPoint")
        },

        enums::ExecutionModel::ExecutionModelKernel => panic!("Kernels are not supported"),
    };

    format!(r#"
    /// Returns a logical struct describing the entry point named `{ep_name}`.
    #[inline]
    pub fn {ep_name}_entry_point(&self) -> {ty} {{
        self.shader.entry_point("{ep_name}")
    }}
            "#, ep_name = ep_name, ty = ty)
}

fn type_from_id(doc: &parse::Spirv, searched: u32) -> String {
    for instruction in doc.instructions.iter() {
        match instruction {
            &parse::Instruction::TypeVoid { result_id } if result_id == searched => {
                return "()".to_owned()
            },
            &parse::Instruction::TypeBool { result_id } if result_id == searched => {
                return "bool".to_owned()
            },
            &parse::Instruction::TypeInt { result_id, width, signedness } if result_id == searched => {
                return "i32".to_owned()
            },
            &parse::Instruction::TypeFloat { result_id, width } if result_id == searched => {
                return "f32".to_owned()
            },
            &parse::Instruction::TypeVector { result_id, component_id, count } if result_id == searched => {
                let t = type_from_id(doc, component_id);
                return format!("[{}; {}]", t, count);
            },
            &parse::Instruction::TypeImage { result_id, sampled_type_id, ref dim, depth, arrayed, ms, sampled, ref format, ref access } if result_id == searched => {
                return format!("{}{}Texture{:?}{}{:?}",
                    if ms { "Multisample" } else { "" },
                    if depth == Some(true) { "Depth" } else { "" },
                    dim,
                    if arrayed { "Array" } else { "" },
                    format);
            },
            &parse::Instruction::TypeSampledImage { result_id, image_type_id } if result_id == searched => {
                return type_from_id(doc, image_type_id);
            },
            &parse::Instruction::TypeArray { result_id, type_id, length_id } if result_id == searched => {
                let t = type_from_id(doc, type_id);
                let len = doc.instructions.iter().filter_map(|e| {
                    match e { &parse::Instruction::Constant { result_id, ref data, .. } if result_id == length_id => Some(data.clone()), _ => None }
                }).next().expect("failed to find array length");
                let len = len.iter().rev().fold(0u64, |a, &b| (a << 32) | b as u64);
                return format!("[{}; {}]", t, len);       // FIXME:
            },
            &parse::Instruction::TypeRuntimeArray { result_id, type_id } if result_id == searched => {
                let t = type_from_id(doc, type_id);
                return format!("[{}]", t);
            },
            &parse::Instruction::TypeStruct { result_id, ref member_types } if result_id == searched => {
                let name = name_from_id(doc, result_id);
                let members = member_types.iter().enumerate().map(|(offset, &member)| {
                    let ty = type_from_id(doc, member);
                    let name = member_name_from_id(doc, result_id, offset as u32);
                    format!("\t{}: {}", name, ty)
                }).collect::<Vec<_>>();
                return format!("struct {} {{\n{}\n}}", name, members.join(",\n"));
            },
            &parse::Instruction::TypeOpaque { result_id, ref name } if result_id == searched => {
                return "<opaque>".to_owned();
            },
            &parse::Instruction::TypePointer { result_id, type_id, .. } if result_id == searched => {
                return type_from_id(doc, type_id);
            },
            _ => ()
        }
    }

    panic!("Type #{} not found", searched)
}

fn name_from_id(doc: &parse::Spirv, searched: u32) -> String {
    doc.instructions.iter().filter_map(|i| {
        if let &parse::Instruction::Name { target_id, ref name } = i {
            if target_id == searched {
                Some(name.clone())
            } else {
                None
            }
        } else {
            None
        }
    }).next().and_then(|n| if !n.is_empty() { Some(n) } else { None })
      .unwrap_or("__unnamed".to_owned())
}

fn member_name_from_id(doc: &parse::Spirv, searched: u32, searched_member: u32) -> String {
    doc.instructions.iter().filter_map(|i| {
        if let &parse::Instruction::MemberName { target_id, member, ref name } = i {
            if target_id == searched && member == searched_member {
                Some(name.clone())
            } else {
                None
            }
        } else {
            None
        }
    }).next().and_then(|n| if !n.is_empty() { Some(n) } else { None })
      .unwrap_or("__unnamed".to_owned())
}

// TODO: this function is a draft, as the actual names may not be the same
fn capability_name(cap: &enums::Capability) -> &'static str {
    match *cap {
        enums::Capability::CapabilityMatrix => "Matrix",
        enums::Capability::CapabilityShader => "Shader",
        enums::Capability::CapabilityGeometry => "Geometry",
        enums::Capability::CapabilityTessellation => "Tessellation",
        enums::Capability::CapabilityAddresses => "Addresses",
        enums::Capability::CapabilityLinkage => "Linkage",
        enums::Capability::CapabilityKernel => "Kernel",
        enums::Capability::CapabilityVector16 => "Vector16",
        enums::Capability::CapabilityFloat16Buffer => "Float16Buffer",
        enums::Capability::CapabilityFloat16 => "Float16",
        enums::Capability::CapabilityFloat64 => "Float64",
        enums::Capability::CapabilityInt64 => "Int64",
        enums::Capability::CapabilityInt64Atomics => "Int64Atomics",
        enums::Capability::CapabilityImageBasic => "ImageBasic",
        enums::Capability::CapabilityImageReadWrite => "ImageReadWrite",
        enums::Capability::CapabilityImageMipmap => "ImageMipmap",
        enums::Capability::CapabilityPipes => "Pipes",
        enums::Capability::CapabilityGroups => "Groups",
        enums::Capability::CapabilityDeviceEnqueue => "DeviceEnqueue",
        enums::Capability::CapabilityLiteralSampler => "LiteralSampler",
        enums::Capability::CapabilityAtomicStorage => "AtomicStorage",
        enums::Capability::CapabilityInt16 => "Int16",
        enums::Capability::CapabilityTessellationPointSize => "TessellationPointSize",
        enums::Capability::CapabilityGeometryPointSize => "GeometryPointSize",
        enums::Capability::CapabilityImageGatherExtended => "ImageGatherExtended",
        enums::Capability::CapabilityStorageImageMultisample => "StorageImageMultisample",
        enums::Capability::CapabilityUniformBufferArrayDynamicIndexing => "UniformBufferArrayDynamicIndexing",
        enums::Capability::CapabilitySampledImageArrayDynamicIndexing => "SampledImageArrayDynamicIndexing",
        enums::Capability::CapabilityStorageBufferArrayDynamicIndexing => "StorageBufferArrayDynamicIndexing",
        enums::Capability::CapabilityStorageImageArrayDynamicIndexing => "StorageImageArrayDynamicIndexing",
        enums::Capability::CapabilityClipDistance => "ClipDistance",
        enums::Capability::CapabilityCullDistance => "CullDistance",
        enums::Capability::CapabilityImageCubeArray => "ImageCubeArray",
        enums::Capability::CapabilitySampleRateShading => "SampleRateShading",
        enums::Capability::CapabilityImageRect => "ImageRect",
        enums::Capability::CapabilitySampledRect => "SampledRect",
        enums::Capability::CapabilityGenericPointer => "GenericPointer",
        enums::Capability::CapabilityInt8 => "Int8",
        enums::Capability::CapabilityInputAttachment => "InputAttachment",
        enums::Capability::CapabilitySparseResidency => "SparseResidency",
        enums::Capability::CapabilityMinLod => "MinLod",
        enums::Capability::CapabilitySampled1D => "Sampled1D",
        enums::Capability::CapabilityImage1D => "Image1D",
        enums::Capability::CapabilitySampledCubeArray => "SampledCubeArray",
        enums::Capability::CapabilitySampledBuffer => "SampledBuffer",
        enums::Capability::CapabilityImageBuffer => "ImageBuffer",
        enums::Capability::CapabilityImageMSArray => "ImageMSArray",
        enums::Capability::CapabilityStorageImageExtendedFormats => "StorageImageExtendedFormats",
        enums::Capability::CapabilityImageQuery => "ImageQuery",
        enums::Capability::CapabilityDerivativeControl => "DerivativeControl",
        enums::Capability::CapabilityInterpolationFunction => "InterpolationFunction",
        enums::Capability::CapabilityTransformFeedback => "TransformFeedback",
        enums::Capability::CapabilityGeometryStreams => "GeometryStreams",
        enums::Capability::CapabilityStorageImageReadWithoutFormat => "StorageImageReadWithoutFormat",
        enums::Capability::CapabilityStorageImageWriteWithoutFormat => "StorageImageWriteWithoutFormat",
    }
}
<commit_msg>Adjust namespaces<commit_after>use std::io::Error as IoError;
use std::io::Read;

pub use parse::ParseError;

mod enums;
mod parse;

pub fn reflect<R>(name: &str, mut spirv: R) -> Result<String, Error>
    where R: Read
{
    let mut data = Vec::new();
    try!(spirv.read_to_end(&mut data));

    // now parsing the document
    let doc = try!(parse::parse_spirv(&data));

    let mut output = String::new();

    {
        // contains the data that was passed as input to this function
        let spirv_data = data.iter().map(|&byte| byte.to_string())
                             .collect::<Vec<String>>()
                             .join(", ");

        // writing the header
        output.push_str(&format!(r#"
pub struct {name} {{
    shader: ::std::sync::Arc<::vulkano::shader::ShaderModule>,
}}

impl {name} {{
    /// Loads the shader in Vulkan as a `ShaderModule`.
    #[inline]
    pub fn load(device: &::std::sync::Arc<::vulkano::Device>) -> {name} {{

        "#, name = name));

        // checking whether each required capability is supported by the vulkan implementation
        for i in doc.instructions.iter() {
            if let &parse::Instruction::Capability(ref cap) = i {
                output.push_str(&format!(r#"
                    if !device.is_capability_supported("{cap}") {{
                        return Err(CapabilityNotSupported);
                    }}"#, cap = capability_name(cap)));
            }
        }

        // follow-up of the header
        output.push_str(&format!(r#"
        unsafe {{
            let data = [{spirv_data}];

            {name} {{
                shader: ::vulkano::shader::ShaderModule::new(device, &data)
            }}
        }}
    }}

    /// Returns the module that was created.
    #[inline]
    pub fn module(&self) -> &::std::sync::Arc<::vulkano::shader::ShaderModule> {{
        &self.shader
    }}
        "#, name = name, spirv_data = spirv_data));

        // writing one method for each entry point of this module
        for instruction in doc.instructions.iter() {
            if let &parse::Instruction::EntryPoint { .. } = instruction {
                output.push_str(&write_entry_point(&doc, instruction));
            }
        }

        // footer
        output.push_str(&format!(r#"
}}
        "#));
    }

    // TODO: remove
    println!("{:#?}", doc);

    Ok(output)
}

#[derive(Debug)]
pub enum Error {
    IoError(IoError),
    ParseError(ParseError),
}

impl From<IoError> for Error {
    #[inline]
    fn from(err: IoError) -> Error {
        Error::IoError(err)
    }
}

impl From<ParseError> for Error {
    #[inline]
    fn from(err: ParseError) -> Error {
        Error::ParseError(err)
    }
}

fn write_entry_point(doc: &parse::Spirv, instruction: &parse::Instruction) -> String {
    let (execution, ep_name, interface) = match instruction {
        &parse::Instruction::EntryPoint { ref execution, id, ref name, ref interface } => {
            (execution, name, interface)
        },
        _ => unreachable!()
    };

    let ty = match *execution {
        enums::ExecutionModel::ExecutionModelVertex => {
            format!("::vulkano::shader::VertexShaderEntryPoint")
        },

        enums::ExecutionModel::ExecutionModelTessellationControl => {
            format!("::vulkano::shader::TessControlShaderEntryPoint")
        },

        enums::ExecutionModel::ExecutionModelTessellationEvaluation => {
            format!("::vulkano::shader::TessEvaluationShaderEntryPoint")
        },

        enums::ExecutionModel::ExecutionModelGeometry => {
            format!("::vulkano::shader::GeometryShaderEntryPoint")
        },

        enums::ExecutionModel::ExecutionModelFragment => {
            let mut output_types = Vec::new();

            for interface in interface.iter() {
                for i in doc.instructions.iter() {
                    match i {
                        &parse::Instruction::Variable { result_type_id, result_id,
                                    storage_class: enums::StorageClass::StorageClassOutput, .. }
                                    if &result_id == interface =>
                        {
                            output_types.push(type_from_id(doc, result_type_id));
                        },
                        _ => ()
                    }
                }
            }

            format!("::vulkano::shader::FragmentShaderEntryPoint<({output})>",
                    output = output_types.join(", ") + ",")
        },

        enums::ExecutionModel::ExecutionModelGLCompute => {
            format!("::vulkano::shader::ComputeShaderEntryPoint")
        },

        enums::ExecutionModel::ExecutionModelKernel => panic!("Kernels are not supported"),
    };

    format!(r#"
    /// Returns a logical struct describing the entry point named `{ep_name}`.
    #[inline]
    pub fn {ep_name}_entry_point(&self) -> {ty} {{
        self.shader.entry_point("{ep_name}")
    }}
            "#, ep_name = ep_name, ty = ty)
}

fn type_from_id(doc: &parse::Spirv, searched: u32) -> String {
    for instruction in doc.instructions.iter() {
        match instruction {
            &parse::Instruction::TypeVoid { result_id } if result_id == searched => {
                return "()".to_owned()
            },
            &parse::Instruction::TypeBool { result_id } if result_id == searched => {
                return "bool".to_owned()
            },
            &parse::Instruction::TypeInt { result_id, width, signedness } if result_id == searched => {
                return "i32".to_owned()
            },
            &parse::Instruction::TypeFloat { result_id, width } if result_id == searched => {
                return "f32".to_owned()
            },
            &parse::Instruction::TypeVector { result_id, component_id, count } if result_id == searched => {
                let t = type_from_id(doc, component_id);
                return format!("[{}; {}]", t, count);
            },
            &parse::Instruction::TypeImage { result_id, sampled_type_id, ref dim, depth, arrayed, ms, sampled, ref format, ref access } if result_id == searched => {
                return format!("{}{}Texture{:?}{}{:?}",
                    if ms { "Multisample" } else { "" },
                    if depth == Some(true) { "Depth" } else { "" },
                    dim,
                    if arrayed { "Array" } else { "" },
                    format);
            },
            &parse::Instruction::TypeSampledImage { result_id, image_type_id } if result_id == searched => {
                return type_from_id(doc, image_type_id);
            },
            &parse::Instruction::TypeArray { result_id, type_id, length_id } if result_id == searched => {
                let t = type_from_id(doc, type_id);
                let len = doc.instructions.iter().filter_map(|e| {
                    match e { &parse::Instruction::Constant { result_id, ref data, .. } if result_id == length_id => Some(data.clone()), _ => None }
                }).next().expect("failed to find array length");
                let len = len.iter().rev().fold(0u64, |a, &b| (a << 32) | b as u64);
                return format!("[{}; {}]", t, len);       // FIXME:
            },
            &parse::Instruction::TypeRuntimeArray { result_id, type_id } if result_id == searched => {
                let t = type_from_id(doc, type_id);
                return format!("[{}]", t);
            },
            &parse::Instruction::TypeStruct { result_id, ref member_types } if result_id == searched => {
                let name = name_from_id(doc, result_id);
                let members = member_types.iter().enumerate().map(|(offset, &member)| {
                    let ty = type_from_id(doc, member);
                    let name = member_name_from_id(doc, result_id, offset as u32);
                    format!("\t{}: {}", name, ty)
                }).collect::<Vec<_>>();
                return format!("struct {} {{\n{}\n}}", name, members.join(",\n"));
            },
            &parse::Instruction::TypeOpaque { result_id, ref name } if result_id == searched => {
                return "<opaque>".to_owned();
            },
            &parse::Instruction::TypePointer { result_id, type_id, .. } if result_id == searched => {
                return type_from_id(doc, type_id);
            },
            _ => ()
        }
    }

    panic!("Type #{} not found", searched)
}

fn name_from_id(doc: &parse::Spirv, searched: u32) -> String {
    doc.instructions.iter().filter_map(|i| {
        if let &parse::Instruction::Name { target_id, ref name } = i {
            if target_id == searched {
                Some(name.clone())
            } else {
                None
            }
        } else {
            None
        }
    }).next().and_then(|n| if !n.is_empty() { Some(n) } else { None })
      .unwrap_or("__unnamed".to_owned())
}

fn member_name_from_id(doc: &parse::Spirv, searched: u32, searched_member: u32) -> String {
    doc.instructions.iter().filter_map(|i| {
        if let &parse::Instruction::MemberName { target_id, member, ref name } = i {
            if target_id == searched && member == searched_member {
                Some(name.clone())
            } else {
                None
            }
        } else {
            None
        }
    }).next().and_then(|n| if !n.is_empty() { Some(n) } else { None })
      .unwrap_or("__unnamed".to_owned())
}

// TODO: this function is a draft, as the actual names may not be the same
fn capability_name(cap: &enums::Capability) -> &'static str {
    match *cap {
        enums::Capability::CapabilityMatrix => "Matrix",
        enums::Capability::CapabilityShader => "Shader",
        enums::Capability::CapabilityGeometry => "Geometry",
        enums::Capability::CapabilityTessellation => "Tessellation",
        enums::Capability::CapabilityAddresses => "Addresses",
        enums::Capability::CapabilityLinkage => "Linkage",
        enums::Capability::CapabilityKernel => "Kernel",
        enums::Capability::CapabilityVector16 => "Vector16",
        enums::Capability::CapabilityFloat16Buffer => "Float16Buffer",
        enums::Capability::CapabilityFloat16 => "Float16",
        enums::Capability::CapabilityFloat64 => "Float64",
        enums::Capability::CapabilityInt64 => "Int64",
        enums::Capability::CapabilityInt64Atomics => "Int64Atomics",
        enums::Capability::CapabilityImageBasic => "ImageBasic",
        enums::Capability::CapabilityImageReadWrite => "ImageReadWrite",
        enums::Capability::CapabilityImageMipmap => "ImageMipmap",
        enums::Capability::CapabilityPipes => "Pipes",
        enums::Capability::CapabilityGroups => "Groups",
        enums::Capability::CapabilityDeviceEnqueue => "DeviceEnqueue",
        enums::Capability::CapabilityLiteralSampler => "LiteralSampler",
        enums::Capability::CapabilityAtomicStorage => "AtomicStorage",
        enums::Capability::CapabilityInt16 => "Int16",
        enums::Capability::CapabilityTessellationPointSize => "TessellationPointSize",
        enums::Capability::CapabilityGeometryPointSize => "GeometryPointSize",
        enums::Capability::CapabilityImageGatherExtended => "ImageGatherExtended",
        enums::Capability::CapabilityStorageImageMultisample => "StorageImageMultisample",
        enums::Capability::CapabilityUniformBufferArrayDynamicIndexing => "UniformBufferArrayDynamicIndexing",
        enums::Capability::CapabilitySampledImageArrayDynamicIndexing => "SampledImageArrayDynamicIndexing",
        enums::Capability::CapabilityStorageBufferArrayDynamicIndexing => "StorageBufferArrayDynamicIndexing",
        enums::Capability::CapabilityStorageImageArrayDynamicIndexing => "StorageImageArrayDynamicIndexing",
        enums::Capability::CapabilityClipDistance => "ClipDistance",
        enums::Capability::CapabilityCullDistance => "CullDistance",
        enums::Capability::CapabilityImageCubeArray => "ImageCubeArray",
        enums::Capability::CapabilitySampleRateShading => "SampleRateShading",
        enums::Capability::CapabilityImageRect => "ImageRect",
        enums::Capability::CapabilitySampledRect => "SampledRect",
        enums::Capability::CapabilityGenericPointer => "GenericPointer",
        enums::Capability::CapabilityInt8 => "Int8",
        enums::Capability::CapabilityInputAttachment => "InputAttachment",
        enums::Capability::CapabilitySparseResidency => "SparseResidency",
        enums::Capability::CapabilityMinLod => "MinLod",
        enums::Capability::CapabilitySampled1D => "Sampled1D",
        enums::Capability::CapabilityImage1D => "Image1D",
        enums::Capability::CapabilitySampledCubeArray => "SampledCubeArray",
        enums::Capability::CapabilitySampledBuffer => "SampledBuffer",
        enums::Capability::CapabilityImageBuffer => "ImageBuffer",
        enums::Capability::CapabilityImageMSArray => "ImageMSArray",
        enums::Capability::CapabilityStorageImageExtendedFormats => "StorageImageExtendedFormats",
        enums::Capability::CapabilityImageQuery => "ImageQuery",
        enums::Capability::CapabilityDerivativeControl => "DerivativeControl",
        enums::Capability::CapabilityInterpolationFunction => "InterpolationFunction",
        enums::Capability::CapabilityTransformFeedback => "TransformFeedback",
        enums::Capability::CapabilityGeometryStreams => "GeometryStreams",
        enums::Capability::CapabilityStorageImageReadWithoutFormat => "StorageImageReadWithoutFormat",
        enums::Capability::CapabilityStorageImageWriteWithoutFormat => "StorageImageWriteWithoutFormat",
    }
}
<|endoftext|>