<commit_before>use core::convert::TryInto;
use core::str;
use core::sync::atomic::{self, AtomicUsize};

use alloc::boxed::Box;
use alloc::collections::BTreeMap;

use spin::{Mutex, Once, RwLock};

use crate::acpi::{RXSDT_ENUM, RxsdtEnum};
use crate::event;
use crate::scheme::SchemeId;
use crate::sync::WaitCondition;

use crate::syscall::data::Stat;
use crate::syscall::error::{EACCES, EBADF, EBADFD, EINTR, EINVAL, EISDIR, ENOENT, ENOTDIR, EROFS};
use crate::syscall::flag::{
    EventFlags, EVENT_READ,
    MODE_CHR, MODE_DIR, MODE_FILE,
    O_ACCMODE, O_CREAT, O_DIRECTORY, O_EXCL, O_RDONLY, O_STAT, O_SYMLINK,
    SEEK_SET, SEEK_CUR, SEEK_END,
};
use crate::syscall::scheme::Scheme;
use crate::syscall::error::{Error, Result};

/// A scheme used to access the RSDT or XSDT, which is needed for e.g. `acpid` to function.
pub struct AcpiScheme;

struct Handle {
    offset: usize,
    kind: HandleKind,
    stat: bool,
}
#[derive(Eq, PartialEq)]
enum HandleKind {
    TopLevel,
    Rxsdt,
    ShutdownPipe,
}

static HANDLES: RwLock<BTreeMap<usize, Handle>> = RwLock::new(BTreeMap::new());
static NEXT_FD: AtomicUsize = AtomicUsize::new(0);

static DATA: Once<Box<[u8]>> = Once::new();

const TOPLEVEL_CONTENTS: &[u8] = b"rxsdt\nkstop\n";

static KSTOP_WAITCOND: WaitCondition = WaitCondition::new();
static KSTOP_FLAG: Mutex<bool> = Mutex::new(false);

static SCHEME_ID: Once<SchemeId> = Once::new();

pub fn register_kstop() -> bool {
    *KSTOP_FLAG.lock() = true;
    let mut waiters_awoken = KSTOP_WAITCOND.notify();

    if let Some(&acpi_scheme) = SCHEME_ID.r#try() {
        let handles = HANDLES.read();

        for (&fd, _) in handles.iter().filter(|(_, handle)| handle.kind == HandleKind::ShutdownPipe) {
            event::trigger(acpi_scheme, fd, EVENT_READ);
            waiters_awoken += 1;
        }
    } else {
        log::error!("Calling register_kstop before kernel ACPI scheme was initialized");
    }

    if waiters_awoken == 0 {
        log::error!("No userspace ACPI handler was notified when trying to shutdown. This is bad.");
        // Let the kernel shutdown without ACPI.
        return false;
    }

    // TODO: Context switch directly to the waiting context, to avoid annoying timeouts.
    true
}

impl AcpiScheme {
    pub fn new(id: SchemeId) -> Self {
        // NOTE: This __must__ be called from the main kernel context, while initializing all
        // schemes. If it is called by any other context, then all ACPI data will probably not even
        // be mapped.

        let mut data_init = false;
        let mut id_init = false;

        DATA.call_once(|| {
            data_init = true;

            let rsdt_or_xsdt = RXSDT_ENUM
                .r#try()
                .expect("expected RXSDT_ENUM to be initialized before AcpiScheme");

            let table = match rsdt_or_xsdt {
                RxsdtEnum::Rsdt(rsdt) => rsdt.as_slice(),
                RxsdtEnum::Xsdt(xsdt) => xsdt.as_slice(),
            };

            Box::from(table)
        });
        SCHEME_ID.call_once(|| {
            id_init = true;

            id
        });

        if !data_init || !id_init {
            log::error!("AcpiScheme::init called multiple times");
        }

        Self
    }
}

impl Scheme for AcpiScheme {
    fn open(&self, path: &str, flags: usize, opener_uid: u32, _opener_gid: u32) -> Result<usize> {
        let path = path.trim_start_matches('/');

        if opener_uid != 0 {
            return Err(Error::new(EACCES));
        }
        if flags & O_CREAT == O_CREAT {
            return Err(Error::new(EROFS));
        }
        if flags & O_EXCL == O_EXCL || flags & O_SYMLINK == O_SYMLINK {
            return Err(Error::new(EINVAL));
        }
        if flags & O_ACCMODE != O_RDONLY && flags & O_STAT != O_STAT {
            return Err(Error::new(EROFS));
        }
        let handle_kind = match path {
            "" => {
                if flags & O_DIRECTORY != O_DIRECTORY && flags & O_STAT != O_STAT {
                    return Err(Error::new(EISDIR));
                }

                HandleKind::TopLevel
            }
            "rxsdt" => {
                if flags & O_DIRECTORY == O_DIRECTORY && flags & O_STAT != O_STAT {
                    return Err(Error::new(ENOTDIR));
                }
                HandleKind::Rxsdt
            }
            "kstop" => {
                if flags & O_DIRECTORY == O_DIRECTORY && flags & O_STAT != O_STAT {
                    return Err(Error::new(ENOTDIR));
                }
                HandleKind::ShutdownPipe
            }
            _ => return Err(Error::new(ENOENT)),
        };

        let fd = NEXT_FD.fetch_add(1, atomic::Ordering::Relaxed);
        let mut handles_guard = HANDLES.write();

        let _ = handles_guard.insert(fd, Handle {
            offset: 0,
            kind: handle_kind,
            stat: flags & O_STAT == O_STAT,
        });

        Ok(fd)
    }
    fn fstat(&self, id: usize, stat: &mut Stat) -> Result<usize> {
        let handles = HANDLES.read();
        let handle = handles.get(&id).ok_or(Error::new(EBADF))?;

        match handle.kind {
            HandleKind::Rxsdt => {
                let data = DATA.r#try().ok_or(Error::new(EBADFD))?;

                stat.st_mode = MODE_FILE;
                stat.st_size = data.len().try_into().unwrap_or(u64::max_value());
            }
            HandleKind::TopLevel => {
                stat.st_mode = MODE_DIR;
                stat.st_size = TOPLEVEL_CONTENTS.len().try_into().unwrap_or(u64::max_value());
            }
            HandleKind::ShutdownPipe => {
                stat.st_mode = MODE_CHR;
                stat.st_size = 1;
            }
        }

        Ok(0)
    }
    fn seek(&self, id: usize, pos: isize, whence: usize) -> Result<isize> {
        let mut handles = HANDLES.write();
        let handle = handles.get_mut(&id).ok_or(Error::new(EBADF))?;

        if handle.stat {
            return Err(Error::new(EBADF));
        }

        let file_len = match handle.kind {
            HandleKind::Rxsdt => DATA.r#try().ok_or(Error::new(EBADFD))?.len(),
            HandleKind::ShutdownPipe => 1,
            HandleKind::TopLevel => TOPLEVEL_CONTENTS.len(),
        };

        let new_offset = match whence {
            SEEK_SET => pos as usize,
            SEEK_CUR => if pos < 0 {
                handle.offset.checked_sub((-pos) as usize).ok_or(Error::new(EINVAL))?
            } else {
                handle.offset.saturating_add(pos as usize)
            }
            SEEK_END => if pos < 0 {
                file_len.checked_sub((-pos) as usize).ok_or(Error::new(EINVAL))?
            } else {
                file_len
            }
            _ => return Err(Error::new(EINVAL)),
        };

        handle.offset = new_offset;

        Ok(new_offset as isize)
    }
    fn read(&self, id: usize, dst_buf: &mut [u8]) -> Result<usize> {
        let mut handles = HANDLES.write();
        let handle = handles.get_mut(&id).ok_or(Error::new(EBADF))?;

        if handle.stat {
            return Err(Error::new(EBADF));
        }

        let data = match handle.kind {
            HandleKind::ShutdownPipe => {
                let dst_byte = match dst_buf.first_mut() {
                    None => return Ok(0),
                    Some(dst) => if handle.offset >= 1 {
                        return Ok(0)
                    } else {
                        dst
                    },
                };

                loop {
                    let flag_guard = KSTOP_FLAG.lock();

                    if *flag_guard {
                        break;
                    } else if ! KSTOP_WAITCOND.wait(flag_guard, "waiting for kstop") {
                        return Err(Error::new(EINTR));
                    }
                }

                *dst_byte = 0x42;
                handle.offset = 1;
                return Ok(1);
            }
            HandleKind::Rxsdt => DATA.r#try().ok_or(Error::new(EBADFD))?,
            HandleKind::TopLevel => TOPLEVEL_CONTENTS,
        };

        let src_offset = core::cmp::min(handle.offset, data.len());
        let src_buf = data
            .get(src_offset..)
            .expect("expected data to be at least data.len() bytes long");

        let bytes_to_copy = core::cmp::min(dst_buf.len(), src_buf.len());

        dst_buf[..bytes_to_copy].copy_from_slice(&src_buf[..bytes_to_copy]);
        handle.offset += bytes_to_copy;

        Ok(bytes_to_copy)
    }
    fn fevent(&self, id: usize, flags: EventFlags) -> Result<EventFlags> {
        let handles = HANDLES.read();
        let handle = handles.get(&id).ok_or(Error::new(EBADF))?;

        if handle.stat {
            return Err(Error::new(EBADF));
        }

        Ok(EventFlags::empty())
    }
    fn write(&self, _id: usize, _buf: &[u8]) -> Result<usize> {
        Err(Error::new(EBADF))
    }
    fn close(&self, id: usize) -> Result<usize> {
        if HANDLES.write().remove(&id).is_none() {
            return Err(Error::new(EBADF));
        }
        Ok(0)
    }
}
<commit_msg>Fix ACPI scheme fevent warning.<commit_after>use core::convert::TryInto;
use core::str;
use core::sync::atomic::{self, AtomicUsize};

use alloc::boxed::Box;
use alloc::collections::BTreeMap;

use spin::{Mutex, Once, RwLock};

use crate::acpi::{RXSDT_ENUM, RxsdtEnum};
use crate::event;
use crate::scheme::SchemeId;
use crate::sync::WaitCondition;

use crate::syscall::data::Stat;
use crate::syscall::error::{EACCES, EBADF, EBADFD, EINTR, EINVAL, EISDIR, ENOENT, ENOTDIR, EROFS};
use crate::syscall::flag::{
    EventFlags, EVENT_READ,
    MODE_CHR, MODE_DIR, MODE_FILE,
    O_ACCMODE, O_CREAT, O_DIRECTORY, O_EXCL, O_RDONLY, O_STAT, O_SYMLINK,
    SEEK_SET, SEEK_CUR, SEEK_END,
};
use crate::syscall::scheme::Scheme;
use crate::syscall::error::{Error, Result};

/// A scheme used to access the RSDT or XSDT, which is needed for e.g. `acpid` to function.
pub struct AcpiScheme;

struct Handle {
    offset: usize,
    kind: HandleKind,
    stat: bool,
}
#[derive(Eq, PartialEq)]
enum HandleKind {
    TopLevel,
    Rxsdt,
    ShutdownPipe,
}

static HANDLES: RwLock<BTreeMap<usize, Handle>> = RwLock::new(BTreeMap::new());
static NEXT_FD: AtomicUsize = AtomicUsize::new(0);

static DATA: Once<Box<[u8]>> = Once::new();

const TOPLEVEL_CONTENTS: &[u8] = b"rxsdt\nkstop\n";

static KSTOP_WAITCOND: WaitCondition = WaitCondition::new();
static KSTOP_FLAG: Mutex<bool> = Mutex::new(false);

static SCHEME_ID: Once<SchemeId> = Once::new();

pub fn register_kstop() -> bool {
    *KSTOP_FLAG.lock() = true;
    let mut waiters_awoken = KSTOP_WAITCOND.notify();

    if let Some(&acpi_scheme) = SCHEME_ID.r#try() {
        let handles = HANDLES.read();

        for (&fd, _) in handles.iter().filter(|(_, handle)| handle.kind == HandleKind::ShutdownPipe) {
            event::trigger(acpi_scheme, fd, EVENT_READ);
            waiters_awoken += 1;
        }
    } else {
        log::error!("Calling register_kstop before kernel ACPI scheme was initialized");
    }

    if waiters_awoken == 0 {
        log::error!("No userspace ACPI handler was notified when trying to shutdown. This is bad.");
        // Let the kernel shutdown without ACPI.
        return false;
    }

    // TODO: Context switch directly to the waiting context, to avoid annoying timeouts.
    true
}

impl AcpiScheme {
    pub fn new(id: SchemeId) -> Self {
        // NOTE: This __must__ be called from the main kernel context, while initializing all
        // schemes. If it is called by any other context, then all ACPI data will probably not even
        // be mapped.

        let mut data_init = false;
        let mut id_init = false;

        DATA.call_once(|| {
            data_init = true;

            let rsdt_or_xsdt = RXSDT_ENUM
                .r#try()
                .expect("expected RXSDT_ENUM to be initialized before AcpiScheme");

            let table = match rsdt_or_xsdt {
                RxsdtEnum::Rsdt(rsdt) => rsdt.as_slice(),
                RxsdtEnum::Xsdt(xsdt) => xsdt.as_slice(),
            };

            Box::from(table)
        });
        SCHEME_ID.call_once(|| {
            id_init = true;

            id
        });

        if !data_init || !id_init {
            log::error!("AcpiScheme::init called multiple times");
        }

        Self
    }
}

impl Scheme for AcpiScheme {
    fn open(&self, path: &str, flags: usize, opener_uid: u32, _opener_gid: u32) -> Result<usize> {
        let path = path.trim_start_matches('/');

        if opener_uid != 0 {
            return Err(Error::new(EACCES));
        }
        if flags & O_CREAT == O_CREAT {
            return Err(Error::new(EROFS));
        }
        if flags & O_EXCL == O_EXCL || flags & O_SYMLINK == O_SYMLINK {
            return Err(Error::new(EINVAL));
        }
        if flags & O_ACCMODE != O_RDONLY && flags & O_STAT != O_STAT {
            return Err(Error::new(EROFS));
        }
        let handle_kind = match path {
            "" => {
                if flags & O_DIRECTORY != O_DIRECTORY && flags & O_STAT != O_STAT {
                    return Err(Error::new(EISDIR));
                }

                HandleKind::TopLevel
            }
            "rxsdt" => {
                if flags & O_DIRECTORY == O_DIRECTORY && flags & O_STAT != O_STAT {
                    return Err(Error::new(ENOTDIR));
                }
                HandleKind::Rxsdt
            }
            "kstop" => {
                if flags & O_DIRECTORY == O_DIRECTORY && flags & O_STAT != O_STAT {
                    return Err(Error::new(ENOTDIR));
                }
                HandleKind::ShutdownPipe
            }
            _ => return Err(Error::new(ENOENT)),
        };

        let fd = NEXT_FD.fetch_add(1, atomic::Ordering::Relaxed);
        let mut handles_guard = HANDLES.write();

        let _ = handles_guard.insert(fd, Handle {
            offset: 0,
            kind: handle_kind,
            stat: flags & O_STAT == O_STAT,
        });

        Ok(fd)
    }
    fn fstat(&self, id: usize, stat: &mut Stat) -> Result<usize> {
        let handles = HANDLES.read();
        let handle = handles.get(&id).ok_or(Error::new(EBADF))?;

        match handle.kind {
            HandleKind::Rxsdt => {
                let data = DATA.r#try().ok_or(Error::new(EBADFD))?;

                stat.st_mode = MODE_FILE;
                stat.st_size = data.len().try_into().unwrap_or(u64::max_value());
            }
            HandleKind::TopLevel => {
                stat.st_mode = MODE_DIR;
                stat.st_size = TOPLEVEL_CONTENTS.len().try_into().unwrap_or(u64::max_value());
            }
            HandleKind::ShutdownPipe => {
                stat.st_mode = MODE_CHR;
                stat.st_size = 1;
            }
        }

        Ok(0)
    }
    fn seek(&self, id: usize, pos: isize, whence: usize) -> Result<isize> {
        let mut handles = HANDLES.write();
        let handle = handles.get_mut(&id).ok_or(Error::new(EBADF))?;

        if handle.stat {
            return Err(Error::new(EBADF));
        }

        let file_len = match handle.kind {
            HandleKind::Rxsdt => DATA.r#try().ok_or(Error::new(EBADFD))?.len(),
            HandleKind::ShutdownPipe => 1,
            HandleKind::TopLevel => TOPLEVEL_CONTENTS.len(),
        };

        let new_offset = match whence {
            SEEK_SET => pos as usize,
            SEEK_CUR => if pos < 0 {
                handle.offset.checked_sub((-pos) as usize).ok_or(Error::new(EINVAL))?
            } else {
                handle.offset.saturating_add(pos as usize)
            }
            SEEK_END => if pos < 0 {
                file_len.checked_sub((-pos) as usize).ok_or(Error::new(EINVAL))?
            } else {
                file_len
            }
            _ => return Err(Error::new(EINVAL)),
        };

        handle.offset = new_offset;

        Ok(new_offset as isize)
    }
    fn read(&self, id: usize, dst_buf: &mut [u8]) -> Result<usize> {
        let mut handles = HANDLES.write();
        let handle = handles.get_mut(&id).ok_or(Error::new(EBADF))?;

        if handle.stat {
            return Err(Error::new(EBADF));
        }

        let data = match handle.kind {
            HandleKind::ShutdownPipe => {
                let dst_byte = match dst_buf.first_mut() {
                    None => return Ok(0),
                    Some(dst) => if handle.offset >= 1 {
                        return Ok(0)
                    } else {
                        dst
                    },
                };

                loop {
                    let flag_guard = KSTOP_FLAG.lock();

                    if *flag_guard {
                        break;
                    } else if ! KSTOP_WAITCOND.wait(flag_guard, "waiting for kstop") {
                        return Err(Error::new(EINTR));
                    }
                }

                *dst_byte = 0x42;
                handle.offset = 1;
                return Ok(1);
            }
            HandleKind::Rxsdt => DATA.r#try().ok_or(Error::new(EBADFD))?,
            HandleKind::TopLevel => TOPLEVEL_CONTENTS,
        };

        let src_offset = core::cmp::min(handle.offset, data.len());
        let src_buf = data
            .get(src_offset..)
            .expect("expected data to be at least data.len() bytes long");

        let bytes_to_copy = core::cmp::min(dst_buf.len(), src_buf.len());

        dst_buf[..bytes_to_copy].copy_from_slice(&src_buf[..bytes_to_copy]);
        handle.offset += bytes_to_copy;

        Ok(bytes_to_copy)
    }
    // TODO
    fn fevent(&self, id: usize, _flags: EventFlags) -> Result<EventFlags> {
        let handles = HANDLES.read();
        let handle = handles.get(&id).ok_or(Error::new(EBADF))?;

        if handle.stat {
            return Err(Error::new(EBADF));
        }

        Ok(EventFlags::empty())
    }
    fn write(&self, _id: usize, _buf: &[u8]) -> Result<usize> {
        Err(Error::new(EBADF))
    }
    fn close(&self, id: usize) -> Result<usize> {
        if HANDLES.write().remove(&id).is_none() {
            return Err(Error::new(EBADF));
        }
        Ok(0)
    }
}
<|endoftext|>


<commit_before>extern crate rand;

use rand::Rng;
use std::io;

enum Card {
    ClubsAce,
    ClubsTen,
    ClubsKing,
    ClubsQueen,
    ClubsJack,
    ClubsNine,
    ClubsEight,
    ClubsSeven,
    SpadesAce,
    SpadesTen,
    SpadesKing,
    SpadesQueen,
    SpadesJack,
    SpadesNine,
    SpadesEight,
    SpadesSeven,
    HeartsAce,
    HeartsTen,
    HeartsKing,
    HeartsQueen,
    HeartsJack,
    HeartsNine,
    HeartsEight,
    HeartsSeven,
    DiamondsAce,
    DiamondsTen,
    DiamondsKing,
    DiamondsQueen,
    DiamondsJack,
    DiamondsNine,
    DiamondsEight,
    DiamondsSeven,
}

enum Game {
    Suit,
    Grand,
    Null,
}

enum Player {
    A,
    B,
    C,
}

fn bid(dealer: u8) -> (u8, u8) {
    let winner: u8 = dealer;
    let highest: u8 = 18;
    // TODO
    (winner, highest)
}

fn deal(dealer: u8) {
    // TODO
}

fn announce(player: u8) -> Game {
    Game::Suit
}

fn main() {
    // just for fun
    let chars = vec![74, 226, 153, 163];
    let clubs_jack: String = String::from_utf8(chars).unwrap();
    // (see http://www.termsys.demon.co.uk/vtansi.htm#colors)
    let esc_char = vec![27];
    let esc = String::from_utf8(esc_char).unwrap();
    let bright: u8 = 1;
    let black: u8 = 30;
    let red: u8 = 31;
    println!("{}[{};{}m{}{}[0m", esc, bright, black, clubs_jack, esc);
    println!("{}[{};{}m{}{}[0m", esc, bright, red, clubs_jack, esc);
    // randomly select player
    let player_number: u8 = rand::thread_rng().gen_range(0, 3);
    match player_number {
        0 => println!("player A:"),
        1 => println!("player B:"),
        2 => println!("player C:"),
        _ => panic!("Uknown player {}", player_number),
    }
    loop {
        // player player_number is dealing
        deal(player_number);
        // bid
        let (player, bid) = bid(player_number);
        // announce
        let game = announce(player);
        // play 10 tricks in a row
        for trick in 0..10 {
            println!("trick #{}:", trick);
            // ask for input
            let mut input = String::new();
            io::stdin().read_line(&mut input)
                .ok()
                .expect("failed to read line");
            let input: u8 = match input.trim().parse() {
                Ok(num) => num,
                Err(_) => break,
            };
            // is input valid?
        };
        println!("New game?");
        let mut input = String::new();
        io::stdin().read_line(&mut input)
            .ok()
            .expect("failed to read line");
        let input: u8 = match input.trim().parse() {
            Ok(num) => num,
            Err(_) => break,
        };
        println!("your input: {}", input);
        if input != 1 {
            break;
        }
    }
}
<commit_msg>Use clubs for black and hearts for red symbol.<commit_after>extern crate rand;

use rand::Rng;
use std::io;

enum Card {
    ClubsAce,
    ClubsTen,
    ClubsKing,
    ClubsQueen,
    ClubsJack,
    ClubsNine,
    ClubsEight,
    ClubsSeven,
    SpadesAce,
    SpadesTen,
    SpadesKing,
    SpadesQueen,
    SpadesJack,
    SpadesNine,
    SpadesEight,
    SpadesSeven,
    HeartsAce,
    HeartsTen,
    HeartsKing,
    HeartsQueen,
    HeartsJack,
    HeartsNine,
    HeartsEight,
    HeartsSeven,
    DiamondsAce,
    DiamondsTen,
    DiamondsKing,
    DiamondsQueen,
    DiamondsJack,
    DiamondsNine,
    DiamondsEight,
    DiamondsSeven,
}

enum Game {
    Suit,
    Grand,
    Null,
}

enum Player {
    A,
    B,
    C,
}

fn bid(dealer: u8) -> (u8, u8) {
    let winner: u8 = dealer;
    let highest: u8 = 18;
    // TODO
    (winner, highest)
}

fn deal(dealer: u8) {
    // TODO
}

fn announce(player: u8) -> Game {
    Game::Suit
}

fn main() {
    // just for fun
    let chars = vec![74, 226, 153, 163];
    let clubs_jack: String = String::from_utf8(chars).unwrap();
    let chars = vec![74, 226, 153, 165];
    let hearts_jack: String = String::from_utf8(chars).unwrap();
    // (see http://www.termsys.demon.co.uk/vtansi.htm#colors)
    let esc_char = vec![27];
    let esc = String::from_utf8(esc_char).unwrap();
    let bright: u8 = 1;
    let black: u8 = 30;
    let red: u8 = 31;
    println!("{}[{};{}m{}{}[0m", esc, bright, black, clubs_jack, esc);
    println!("{}[{};{}m{}{}[0m", esc, bright, red, hearts_jack, esc);
    // randomly select player
    let player_number: u8 = rand::thread_rng().gen_range(0, 3);
    match player_number {
        0 => println!("player A:"),
        1 => println!("player B:"),
        2 => println!("player C:"),
        _ => panic!("Uknown player {}", player_number),
    }
    loop {
        // player player_number is dealing
        deal(player_number);
        // bid
        let (player, bid) = bid(player_number);
        // announce
        let game = announce(player);
        // play 10 tricks in a row
        for trick in 0..10 {
            println!("trick #{}:", trick);
            // ask for input
            let mut input = String::new();
            io::stdin().read_line(&mut input)
                .ok()
                .expect("failed to read line");
            let input: u8 = match input.trim().parse() {
                Ok(num) => num,
                Err(_) => break,
            };
            // is input valid?
        };
        println!("New game?");
        let mut input = String::new();
        io::stdin().read_line(&mut input)
            .ok()
            .expect("failed to read line");
        let input: u8 = match input.trim().parse() {
            Ok(num) => num,
            Err(_) => break,
        };
        println!("your input: {}", input);
        if input != 1 {
            break;
        }
    }
}
<|endoftext|>


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

use std::rc::Rc;
use std::sync::Mutex;
use std::collections::HashMap;
use bindgen::callbacks::{ParseCallbacks, IntKind};
use proc_macro2::TokenStream as TokenStream2;
use quote::quote;

/// Keeps track of all known preprocessor invocations.
#[derive(Debug,Default)]
pub(crate) struct PreprocessorDefinitions {
    integral: HashMap<String, i64>,
}

impl PreprocessorDefinitions {
    pub fn new() -> Self {
        PreprocessorDefinitions {
            integral: HashMap::new(),
        }
    }

    fn insert_int_macro(&mut self, name: &str, val: i64) {
        self.integral.insert(name.to_string(), val);
    }

    pub fn to_tokenstream(&self) -> TokenStream2 {
        if self.integral.is_empty() {
            TokenStream2::new()
        } else {
            let defs= self.integral.iter().map(|(k, v)| quote!{
                const #k = #v;
            });
            quote!{
                mod ffi {
                    mod cpp {
                        #(#defs)*
                    }
                }
            }
        }
    }
}

/// Callbacks for bindgen.
#[derive(Debug)]
pub(crate) struct PreprocessorParseCallbacks {
    definitions: Rc<Mutex<PreprocessorDefinitions>>,
}

impl PreprocessorParseCallbacks {
    pub fn new(definitions: Rc<Mutex<PreprocessorDefinitions>>) -> Self {
        PreprocessorParseCallbacks {
            definitions
        }
    }
}

impl ParseCallbacks for PreprocessorParseCallbacks {
    fn int_macro(&self, name: &str, value: i64) -> Option<IntKind> {
        let mut mg = self.definitions.try_lock().unwrap();
        mg.insert_int_macro(name, value);
        None
    }
}
<commit_msg>Adding comment.<commit_after>// Copyright 2020 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//    https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

use std::rc::Rc;
use std::sync::Mutex;
use std::collections::HashMap;
use bindgen::callbacks::{ParseCallbacks, IntKind};
use proc_macro2::TokenStream as TokenStream2;
use quote::quote;

/// Keeps track of all known preprocessor invocations.
#[derive(Debug,Default)]
pub(crate) struct PreprocessorDefinitions {
    integral: HashMap<String, i64>,
}

impl PreprocessorDefinitions {
    pub fn new() -> Self {
        PreprocessorDefinitions {
            integral: HashMap::new(),
        }
    }

    fn insert_int_macro(&mut self, name: &str, val: i64) {
        self.integral.insert(name.to_string(), val);
    }

    pub fn to_tokenstream(&self) -> TokenStream2 {
        if self.integral.is_empty() {
            TokenStream2::new()
        } else {
            let defs= self.integral.iter().map(|(k, v)| quote!{
                const #k = #v;
            });
            quote!{
                mod ffi {
                    mod cpp {
                        #(#defs)*
                    }
                }
            }
        }
    }
}

/// Callbacks for bindgen.
#[derive(Debug)]
pub(crate) struct PreprocessorParseCallbacks {
    // We use a mutex rather than a RefCell not because we need thread
    // safety, but because we need poisoning in order to avoid problems
    // with UnwindSafe.
    definitions: Rc<Mutex<PreprocessorDefinitions>>,
}

impl PreprocessorParseCallbacks {
    pub fn new(definitions: Rc<Mutex<PreprocessorDefinitions>>) -> Self {
        PreprocessorParseCallbacks {
            definitions
        }
    }
}

impl ParseCallbacks for PreprocessorParseCallbacks {
    fn int_macro(&self, name: &str, value: i64) -> Option<IntKind> {
        let mut mg = self.definitions.try_lock().unwrap();
        mg.insert_int_macro(name, value);
        None
    }
}
<|endoftext|>


<commit_before>

fn main() {
}<commit_msg>Use SDL to display a window<commit_after>import azure::cairo;

fn on_main(f: fn~()) {
    let builder = task::builder();
    let opts = {
        sched: some({
            mode: task::osmain,
            native_stack_size: none
        })
        with task::get_opts(builder)
    };
    task::set_opts(builder, opts);
    task::run(builder, f);
}

fn main() {
    on_main {||
        sdl::init([
            sdl::init_video
        ]);
        let screen = sdl::video::set_video_mode(
            320, 200, 32,
            [sdl::video::swsurface],
            [sdl::video::doublebuf]);
        assert ptr::is_not_null(screen);
        let surface = sdl::video::create_rgb_surface(
            [sdl::video::swsurface],
            320, 200, 32,
            0x00FF0000u32,
            0x0000FF00u32,
            0x000000FFu32,
            0x00000000u32
            );
        assert ptr::is_not_null(surface);
        loop {
            sdl::video::blit_surface(surface, ptr::null(),
                                     screen, ptr::null());
            sdl::video::flip(screen);
            sdl::event::poll_event {|_event|
            }
        }
        sdl::quit();
    }
}<|endoftext|>


<commit_before>import libc::c_double;
import azure::*;
import azure::bindgen::*;
import azure::cairo;
import azure::cairo::bindgen::*;

// FIXME: Busy wait hack
fn sleep() {
    iter::repeat(100000u) {||
        task::yield();
    }
}

fn main() {
    // The platform event handler thread
    let osmain_ch = osmain::osmain();

    // The compositor
    let draw_ch = gfx::compositor::compositor(osmain_ch);

    // Not sure what this is but it decides what to draw
    let model_ch = task::spawn_listener {|po|
        let mut x1 = 100;
        let mut y1 = 100;
        let mut w1 = 200;
        let mut h1 = 200;
        let mut x2 = 200;
        let mut y2 = 200;
        let mut w2 = 300;
        let mut h2 = 300;

        while !comm::peek(po) {
            let model = {
                x1: x1, y1: y1, w1: w1, h1: h1,
                x2: x2, y2: y2, w2: w2, h2: h2
            };
            comm::send(draw_ch, gfx::compositor::draw(model));

            sleep();

            x1 += 1;
            y1 += 1;
            x2 -= 1;
            y2 -= 1;
            if x1 > 800 { x1 = 0 }
            if y1 > 600 { y1 = 0 }
            if x2 < 0 { x2 = 800 }
            if y2 < 0 { y2 = 600 }
        }
    };

    // The keyboard handler
    input::input(osmain_ch, draw_ch, model_ch);
}<commit_msg>Use a real timer<commit_after>import libc::c_double;
import azure::*;
import azure::bindgen::*;
import azure::cairo;
import azure::cairo::bindgen::*;

fn main() {
    // The platform event handler thread
    let osmain_ch = osmain::osmain();

    // The compositor
    let draw_ch = gfx::compositor::compositor(osmain_ch);

    // Not sure what this is but it decides what to draw
    let model_ch = task::spawn_listener {|po|
        let mut x1 = 100;
        let mut y1 = 100;
        let mut w1 = 200;
        let mut h1 = 200;
        let mut x2 = 200;
        let mut y2 = 200;
        let mut w2 = 300;
        let mut h2 = 300;

        while !comm::peek(po) {
            let model = {
                x1: x1, y1: y1, w1: w1, h1: h1,
                x2: x2, y2: y2, w2: w2, h2: h2
            };
            comm::send(draw_ch, gfx::compositor::draw(model));

            std::timer::sleep(100u);

            x1 += 1;
            y1 += 1;
            x2 -= 1;
            y2 -= 1;
            if x1 > 800 { x1 = 0 }
            if y1 > 600 { y1 = 0 }
            if x2 < 0 { x2 = 800 }
            if y2 < 0 { y2 = 600 }
        }
    };

    // The keyboard handler
    input::input(osmain_ch, draw_ch, model_ch);
}<|endoftext|>


<commit_before>use std::env;
use std::default::Default;
use std::collections::BTreeMap;

use time::now_utc;
use rand::{Rng, thread_rng};
use rustc_serialize::json::{ToJson, Json};
use r2d2_redis::RedisConnectionManager;
use r2d2::{Config, Pool, PooledConnection};
use redis::{pipe, RedisResult, parse_redis_url};

pub type RedisPooledConnection = PooledConnection<RedisConnectionManager>;
pub type RedisPool = Pool<RedisConnectionManager>;

pub fn create_redis_pool() -> RedisPool {
    let config = Config::builder().build();
    let redis_url = &env::var("REDIS_URL").unwrap_or("redis://127.0.0.1/".to_owned());
    let url = parse_redis_url(redis_url).unwrap();
    let manager = RedisConnectionManager::new(url).unwrap();
    Pool::new(config, manager).unwrap()
}

#[derive(RustcEncodable, RustcDecodable, Debug)]
pub struct Job {
    pub class: String,
    pub args: String,
    pub retry: i64,
    pub queue: String,
    pub jid: String,
    pub created_at: i64,
    pub enqueued_at: i64,
}

impl Default for JobOpts {
    fn default() -> JobOpts {
        let now = now_utc().to_timespec().sec;
        let jid = thread_rng().gen_ascii_chars().take(24).collect::<String>();
        JobOpts {
            retry: 25,
            queue: "default".to_string(),
            jid: jid,
            created_at: now,
            enqueued_at: now,
        }
    }
}

pub struct JobOpts {
    pub retry: i64,
    pub queue: String,
    pub jid: String,
    pub created_at: i64,
    pub enqueued_at: i64,
}

impl Job {
    pub fn new(class: String, args: String, opts: JobOpts) -> Job {
        Job {
            class: class,
            args: args,
            retry: opts.retry,
            queue: opts.queue,
            jid: opts.jid,
            created_at: opts.created_at,
            enqueued_at: opts.enqueued_at,
        }
    }
}

impl ToJson for Job {
    fn to_json(&self) -> Json {
        let mut object = BTreeMap::new();
        object.insert("class".to_string(), self.class.to_json());
        // `args` are already serialized, creating Json struct from it.
        object.insert("args".to_string(), Json::from_str(&self.args).unwrap());
        object.insert("retry".to_string(), self.retry.to_json());
        object.insert("queue".to_string(), self.queue.to_json());
        object.insert("jid".to_string(), self.jid.to_json());
        object.insert("created_at".to_string(), self.created_at.to_json());
        object.insert("enqueued_at".to_string(), self.enqueued_at.to_json());
        Json::Object(object)
    }
}

pub struct ClientOpts {
    pub namespace: Option<String>,
}

impl Default for ClientOpts {
    fn default() -> ClientOpts {
        ClientOpts { namespace: None }
    }
}

pub struct Client {
    pub connection: RedisPooledConnection,
    pub namespace: Option<String>,
}

impl Client {
    pub fn new(pool: RedisPool, opts: ClientOpts) -> Client {
        Client {
            connection: pool.get().unwrap(),
            namespace: opts.namespace,
        }
    }

    pub fn push(&self, job: Job) -> RedisResult<Job> {
        let _: () = try!(pipe()
            .atomic()
            .cmd("SADD")
            .arg("queues")
            .arg(job.queue.to_string()).ignore()
            .cmd("LPUSH")
            .arg(self.queue_name(&job.queue))
            .arg(job.to_json())
            .query(&*self.connection));
        Ok(job)
    }

    fn queue_name(&self, queue: &str) -> String {
        if let Some(ref ns) = self.namespace {
            format!("{}:queue:{}", ns, queue)
        } else {
            format!("queue:{}", queue)
        }
    }
}
<commit_msg>Rust fmt<commit_after>use std::env;
use std::default::Default;
use std::collections::BTreeMap;

use time::now_utc;
use rand::{Rng, thread_rng};
use rustc_serialize::json::{ToJson, Json};
use r2d2_redis::RedisConnectionManager;
use r2d2::{Config, Pool, PooledConnection};
use redis::{pipe, RedisResult, parse_redis_url};

pub type RedisPooledConnection = PooledConnection<RedisConnectionManager>;
pub type RedisPool = Pool<RedisConnectionManager>;

pub fn create_redis_pool() -> RedisPool {
    let config = Config::builder().build();
    let redis_url = &env::var("REDIS_URL").unwrap_or("redis://127.0.0.1/".to_owned());
    let url = parse_redis_url(redis_url).unwrap();
    let manager = RedisConnectionManager::new(url).unwrap();
    Pool::new(config, manager).unwrap()
}

#[derive(RustcEncodable, RustcDecodable, Debug)]
pub struct Job {
    pub class: String,
    pub args: String,
    pub retry: i64,
    pub queue: String,
    pub jid: String,
    pub created_at: i64,
    pub enqueued_at: i64,
}

impl Default for JobOpts {
    fn default() -> JobOpts {
        let now = now_utc().to_timespec().sec;
        let jid = thread_rng().gen_ascii_chars().take(24).collect::<String>();
        JobOpts {
            retry: 25,
            queue: "default".to_string(),
            jid: jid,
            created_at: now,
            enqueued_at: now,
        }
    }
}

pub struct JobOpts {
    pub retry: i64,
    pub queue: String,
    pub jid: String,
    pub created_at: i64,
    pub enqueued_at: i64,
}

impl Job {
    pub fn new(class: String, args: String, opts: JobOpts) -> Job {
        Job {
            class: class,
            args: args,
            retry: opts.retry,
            queue: opts.queue,
            jid: opts.jid,
            created_at: opts.created_at,
            enqueued_at: opts.enqueued_at,
        }
    }
}

impl ToJson for Job {
    fn to_json(&self) -> Json {
        let mut object = BTreeMap::new();
        object.insert("class".to_string(), self.class.to_json());
        // `args` are already serialized, creating Json struct from it.
        object.insert("args".to_string(), Json::from_str(&self.args).unwrap());
        object.insert("retry".to_string(), self.retry.to_json());
        object.insert("queue".to_string(), self.queue.to_json());
        object.insert("jid".to_string(), self.jid.to_json());
        object.insert("created_at".to_string(), self.created_at.to_json());
        object.insert("enqueued_at".to_string(), self.enqueued_at.to_json());
        Json::Object(object)
    }
}

pub struct ClientOpts {
    pub namespace: Option<String>,
}

impl Default for ClientOpts {
    fn default() -> ClientOpts {
        ClientOpts { namespace: None }
    }
}

pub struct Client {
    pub connection: RedisPooledConnection,
    pub namespace: Option<String>,
}

impl Client {
    pub fn new(pool: RedisPool, opts: ClientOpts) -> Client {
        Client {
            connection: pool.get().unwrap(),
            namespace: opts.namespace,
        }
    }

    pub fn push(&self, job: Job) -> RedisResult<Job> {
        let _: () = try!(pipe()
            .atomic()
            .cmd("SADD")
            .arg("queues")
            .arg(job.queue.to_string())
            .ignore()
            .cmd("LPUSH")
            .arg(self.queue_name(&job.queue))
            .arg(job.to_json())
            .query(&*self.connection));
        Ok(job)
    }

    fn queue_name(&self, queue: &str) -> String {
        if let Some(ref ns) = self.namespace {
            format!("{}:queue:{}", ns, queue)
        } else {
            format!("queue:{}", queue)
        }
    }
}
<|endoftext|>


<commit_before>use super::utils::types::{ Sha256Digest, Bitfield, Blake2sDigest };
use super::utils::bls::{ Signature, AggregateSignature, Keypair, PublicKey };
use super::aggregate_vote::AggregateVote;
use super::rlp::{ RlpStream, Encodable } ;

pub struct Block {
    pub parent_hash: Sha256Digest,
    pub skip_count: u64,
    pub randao_reveal: Sha256Digest,
    pub attestation_bitfield: Bitfield,
    pub attestation_aggregate_sig: AggregateSignature,
    pub shard_aggregate_votes: Vec<AggregateVote>,
    pub main_chain_ref: Sha256Digest,
    pub state_hash: Blake2sDigest,
    pub sig: Option<Signature>
}
impl Block {
    pub fn new(parent_hash: Sha256Digest,
               randao_reveal: Sha256Digest,
               main_chain_ref: Sha256Digest,
               state_hash: Blake2sDigest) -> Block {
        Block {
            parent_hash: parent_hash,
            skip_count: 0,
            randao_reveal: randao_reveal,
            attestation_bitfield: Vec::new(),
            attestation_aggregate_sig: AggregateSignature::new(),
            shard_aggregate_votes: Vec::new(),
            main_chain_ref: main_chain_ref,
            state_hash: state_hash,
            sig: None
        }
    }

    /*
     * Take a Block and covert it into an array of u8 for BLS signing
     * or verfication. The `sig` field is purposefully omitted.
     */
    pub fn encode_to_signable_message(&self) -> [u8; 9140] {
        // Using biggest avg. block size from v2 spec
        let mut message: [u8; 9140] = [0; 9140];

        // Create the RLP vector
        let mut s = RlpStream::new();
        s.append(&self.parent_hash);
        s.append(&self.skip_count);
        s.append(&self.randao_reveal);
        s.append(&self.attestation_bitfield);
        // TODO: represent attestation_aggregate_sig
        // TODO: represent shard_aggregate_votes
        s.append(&self.main_chain_ref);
        s.append(&self.state_hash);
        let rlp_vec = s.out();

        // Parse the RLP vector into an array compatible with the BLS signer
        let len = rlp_vec.len();
        message[..len].copy_from_slice(&rlp_vec[..len]);
        message
    }

    /*
     * Sign the block with the given keypair.
     */
    pub fn sig_sign(&mut self, keypair: &Keypair) {
        let message = self.encode_to_signable_message();
        self.sig = Some(keypair.sign(&message));
    }

    /*
     * Verify a block signature given some keypair.
     */
    pub fn sig_verify(&self, pub_key: &PublicKey) -> bool {
        let message = self.encode_to_signable_message();
        match &self.sig {
            None => false,
            Some(sig) => {
                pub_key.verify(&message, &sig)
            },
        }
    }
}

impl Encodable for Block {
    fn rlp_append(&self, s: &mut RlpStream) {
        s.append(&self.parent_hash);
        s.append(&self.skip_count);
        s.append(&self.randao_reveal);
        s.append(&self.attestation_bitfield);
        // TODO: represent attestation_aggregate_sig
        // TODO: represent shard_aggregate_votes
        s.append(&self.main_chain_ref);
        s.append(&self.state_hash);
        // TODO: represent sig
    }
}

#[cfg(test)]
mod tests {
    extern crate rand;

    use super::*;
    use self::rand::{ SeedableRng, XorShiftRng };

    #[test]
    fn test_new_for_parent_hash() {
        let parent_hash = Sha256Digest::random();
        let randao_reveal = Sha256Digest::random();
        let main_chain_ref = Sha256Digest::random();
        let state_hash = Sha256Digest::random();
        let b = Block::new(parent_hash,
                           randao_reveal,
                           main_chain_ref,
                           state_hash);
        assert_eq!(b.parent_hash, parent_hash);
        assert_eq!(b.randao_reveal, randao_reveal);
        assert_eq!(b.main_chain_ref, main_chain_ref);
        assert_eq!(b.state_hash, state_hash);
    }

    #[test]
    fn test_signable_message_encoding() {
        let parent_hash = Sha256Digest::from([0; 32]);
        let randao_reveal = Sha256Digest::from([1; 32]);
        let main_chain_ref = Sha256Digest::from([2; 32]);
        let state_hash = Sha256Digest::from([3; 32]);
        let mut b = Block::new(parent_hash,
                           randao_reveal,
                           main_chain_ref,
                           state_hash);
        b.skip_count = 2;
        let output = b.encode_to_signable_message();
        // TODO: test this better
        assert_eq!(output[0], 160);
        assert_eq!(output[1..21], [0; 20]);
    }

    #[test]
    fn test_sign_and_verify() {
        let mut rng = XorShiftRng::from_seed([0xbc4f6d44, 0xd62f276c, 0xb963afd0, 0x5455863d]);
        let alice_keypair = Keypair::generate(&mut rng);
        let bob_keypair = Keypair::generate(&mut rng);
        let mut b = Block::new(Sha256Digest::random(),
                           Sha256Digest::random(),
                           Sha256Digest::random(),
                           Sha256Digest::random());

        // Both signatures fail before signing
        assert_eq!(b.sig_verify(&alice_keypair.public), false);
        assert_eq!(b.sig_verify(&bob_keypair.public), false);

        // Sign as Alice
        b.sig_sign(&alice_keypair);

        // Alice signature passes, bobs fails
        assert_eq!(b.sig_verify(&alice_keypair.public), true);
        assert_eq!(b.sig_verify(&bob_keypair.public), false);
    }
}
<commit_msg>Improve RLP encoding of Block<commit_after>use super::utils::types::{ Sha256Digest, Bitfield, Blake2sDigest };
use super::utils::bls::{ Signature, AggregateSignature, Keypair, PublicKey };
use super::aggregate_vote::AggregateVote;
use super::rlp::{ RlpStream, Encodable } ;

pub struct Block {
    pub parent_hash: Sha256Digest,
    pub skip_count: u64,
    pub randao_reveal: Sha256Digest,
    pub attestation_bitfield: Bitfield,
    pub attestation_aggregate_sig: AggregateSignature,
    pub shard_aggregate_votes: Vec<AggregateVote>,
    pub main_chain_ref: Sha256Digest,
    pub state_hash: Blake2sDigest,
    pub sig: Option<Signature>
}
impl Block {
    pub fn new(parent_hash: Sha256Digest,
               randao_reveal: Sha256Digest,
               main_chain_ref: Sha256Digest,
               state_hash: Blake2sDigest) -> Block {
        Block {
            parent_hash: parent_hash,
            skip_count: 0,
            randao_reveal: randao_reveal,
            attestation_bitfield: Vec::new(),
            attestation_aggregate_sig: AggregateSignature::new(),
            shard_aggregate_votes: Vec::new(),
            main_chain_ref: main_chain_ref,
            state_hash: state_hash,
            sig: None
        }
    }

    /*
     * Take a Block and covert it into an array of u8 for BLS signing
     * or verfication. The `sig` field is purposefully omitted.
     */
    pub fn encode_to_signable_message(&self) -> [u8; 9140] {
        // Using biggest avg. block size from v2 spec
        let mut message: [u8; 9140] = [0; 9140];

        // Create the RLP vector
        let mut s = RlpStream::new();
        s.append(&self.parent_hash);
        s.append(&self.skip_count);
        s.append(&self.randao_reveal);
        s.append(&self.attestation_bitfield);
        // TODO: represent attestation_aggregate_sig
        // TODO: represent shard_aggregate_votes
        s.append(&self.main_chain_ref);
        s.append(&self.state_hash);
        let rlp_vec = s.out();

        // Parse the RLP vector into an array compatible with the BLS signer
        let len = rlp_vec.len();
        message[..len].copy_from_slice(&rlp_vec[..len]);
        message
    }

    /*
     * Sign the block with the given keypair.
     */
    pub fn sig_sign(&mut self, keypair: &Keypair) {
        let message = self.encode_to_signable_message();
        self.sig = Some(keypair.sign(&message));
    }

    /*
     * Verify a block signature given some keypair.
     */
    pub fn sig_verify(&self, pub_key: &PublicKey) -> bool {
        let message = self.encode_to_signable_message();
        match &self.sig {
            None => false,
            Some(sig) => {
                pub_key.verify(&message, &sig)
            },
        }
    }
}

impl Encodable for Block {
    fn rlp_append(&self, s: &mut RlpStream) {
        s.append(&self.parent_hash);
        s.append(&self.skip_count);
        s.append(&self.randao_reveal);
        s.append(&self.attestation_bitfield);
        // s.append(&self.attestation_aggregate_sig);   // TODO: RLP this
        s.append_list(&self.shard_aggregate_votes);
        s.append(&self.main_chain_ref);
        s.append(&self.state_hash);
        // s.append(&self.sig);    // TODO: RLP this
    }
}

#[cfg(test)]
mod tests {
    use super::super::rlp;
    extern crate rand;

    use super::*;
    use self::rand::{ SeedableRng, XorShiftRng };

    #[test]
    fn test_new_for_parent_hash() {
        let parent_hash = Sha256Digest::random();
        let randao_reveal = Sha256Digest::random();
        let main_chain_ref = Sha256Digest::random();
        let state_hash = Sha256Digest::random();
        let b = Block::new(parent_hash,
                           randao_reveal,
                           main_chain_ref,
                           state_hash);
        assert_eq!(b.parent_hash, parent_hash);
        assert_eq!(b.randao_reveal, randao_reveal);
        assert_eq!(b.main_chain_ref, main_chain_ref);
        assert_eq!(b.state_hash, state_hash);
    }

    #[test]
    fn test_signable_message_encoding() {
        let parent_hash = Sha256Digest::from([0; 32]);
        let randao_reveal = Sha256Digest::from([1; 32]);
        let main_chain_ref = Sha256Digest::from([2; 32]);
        let state_hash = Sha256Digest::from([3; 32]);
        let mut b = Block::new(parent_hash,
                           randao_reveal,
                           main_chain_ref,
                           state_hash);
        b.skip_count = 2;
        let output = b.encode_to_signable_message();
        // TODO: test this better
        assert_eq!(output[0], 160);
        assert_eq!(output[1..21], [0; 20]);
    }

    #[test]
    fn test_sign_and_verify() {
        let mut rng = XorShiftRng::from_seed([0xbc4f6d44, 0xd62f276c, 0xb963afd0, 0x5455863d]);
        let alice_keypair = Keypair::generate(&mut rng);
        let bob_keypair = Keypair::generate(&mut rng);
        let mut b = Block::new(Sha256Digest::random(),
                           Sha256Digest::random(),
                           Sha256Digest::random(),
                           Sha256Digest::random());

        // Both signatures fail before signing
        assert_eq!(b.sig_verify(&alice_keypair.public), false);
        assert_eq!(b.sig_verify(&bob_keypair.public), false);

        // Sign as Alice
        b.sig_sign(&alice_keypair);

        // Alice signature passes, bobs fails
        assert_eq!(b.sig_verify(&alice_keypair.public), true);
        assert_eq!(b.sig_verify(&bob_keypair.public), false);
    }

    #[test]
    fn test_serialization() {
        let b = Block {
            parent_hash: Sha256Digest::zero(),
            skip_count: 100,
            randao_reveal: Sha256Digest::zero(),
            attestation_bitfield: Vec::new(),
            attestation_aggregate_sig: AggregateSignature::new(),
            shard_aggregate_votes: Vec::new(),
            main_chain_ref: Sha256Digest::zero(),
            state_hash: Blake2sDigest::zero(),
            sig: None
        };
        let e = rlp::encode(&b);
        println!("{:?}", e);
        assert_eq!(e.len(), 135);
        assert_eq!(e[0], 160);
        assert_eq!(e[1..33], [0; 32]);
        assert_eq!(e[33], 100);
        assert_eq!(e[34], 160);
        assert_eq!(e[35..67], [0; 32]);
        assert_eq!(e[67], 128);
        assert_eq!(e[68], 192);
        assert_eq!(e[69], 160);
        assert_eq!(e[70..102], [0; 32]);
        assert_eq!(e[102], 160);
        assert_eq!(e[103..135], [0; 32]);
    }
}
<|endoftext|>


<commit_before>// 将闭包作为参数并调用它的函数。
fn apply<F>(f: F) where
    // 闭包没有输入值和返回值。
    F: FnOnce() {
    // ^ 试一试：将 `FnOnce` 换成 `Fn` 或 `FnMut`。

    f();
}

// 使用闭包并返回一个 `i32` 整型的函数。
fn apply_to_3<F>(f: F) -> i32 where
// 闭包处理一个 `i32` 整型并返回一个 `i32` 整型。
    F: Fn(i32) -> i32 {

    f(3)
}

fn main() {
    use std::mem;

    let greeting = "hello";
    // 不可复制的类型。
    let mut farewell = "goodbye".to_owned();

    // 捕获 2 个变量：通过引用方式的 `greeting` 和
    // 通过值方式的 `farewell`。
    let diary = || {
        // `greeting` 使用引用方式：需要 `Fn`。
        println!("I said {}.", greeting);

        // 改变迫使 `farewell` 变成了通过可变引用来捕获。
        // （原文：Mutation forces `farewell` to be
        // captured by mutable reference.）
        // 现在需要 `FnMut`。
        farewell.push_str("!!!");
        println!("Then I screamed {}.", farewell);
        println!("Now I can sleep. zzzzz");

        // 手动调用 drop 将 `farewell` 强制转成通过值来捕获。
        // （原文：Manually calling drop forces `farewell` to
        // be captured by value. Now requires `FnOnce`.）
        // 现在需要 `FnOnce`。
        mem::drop(farewell);
    };

    // 调用处理闭包的函数（原文：Call the function
    // which applies the closure）。
    apply(diary);

    let double = |x| 2 * x;

    println!("3 doubled: {}", apply_to_3(double));
}
<commit_msg>Comment about to_owned<commit_after>// 将闭包作为参数并调用它的函数。
fn apply<F>(f: F) where
    // 闭包没有输入值和返回值。
    F: FnOnce() {
    // ^ 试一试：将 `FnOnce` 换成 `Fn` 或 `FnMut`。

    f();
}

// 使用闭包并返回一个 `i32` 整型的函数。
fn apply_to_3<F>(f: F) -> i32 where
// 闭包处理一个 `i32` 整型并返回一个 `i32` 整型。
    F: Fn(i32) -> i32 {

    f(3)
}

fn main() {
    use std::mem;

    let greeting = "hello";
    // 不可复制的类型。
    // `to_owned` 从借用的数据创建属于自己的数据。
    let mut farewell = "goodbye".to_owned();

    // 捕获 2 个变量：通过引用方式的 `greeting` 和
    // 通过值方式的 `farewell`。
    let diary = || {
        // `greeting` 使用引用方式：需要 `Fn`。
        println!("I said {}.", greeting);

        // 改变迫使 `farewell` 变成了通过可变引用来捕获。
        // （原文：Mutation forces `farewell` to be
        // captured by mutable reference.）
        // 现在需要 `FnMut`。
        farewell.push_str("!!!");
        println!("Then I screamed {}.", farewell);
        println!("Now I can sleep. zzzzz");

        // 手动调用 drop 将 `farewell` 强制转成通过值来捕获。
        // （原文：Manually calling drop forces `farewell` to
        // be captured by value. Now requires `FnOnce`.）
        // 现在需要 `FnOnce`。
        mem::drop(farewell);
    };

    // 调用处理闭包的函数（原文：Call the function
    // which applies the closure）。
    apply(diary);

    let double = |x| 2 * x;

    println!("3 doubled: {}", apply_to_3(double));
}
<|endoftext|>


<commit_before>// xfail-stage0

use std;
import std::ivec;

fn test_reserve_and_on_heap() {
    let int[] v = ~[ 1, 2 ];
    assert (!ivec::on_heap(v));
    ivec::reserve(v, 8u);
    assert (ivec::on_heap(v));
}

fn test_unsafe_ptrs() {
    // Test on-stack copy-from-buf.
    auto a = ~[ 1, 2, 3 ];
    auto ptr = ivec::to_ptr(a);
    auto b = ~[];
    ivec::unsafe::copy_from_buf(b, ptr, 3u);
    assert (ivec::len(b) == 3u);
    assert (b.(0) == 1);
    assert (b.(1) == 2);
    assert (b.(2) == 3);

    // Test on-heap copy-from-buf.
    auto c = ~[ 1, 2, 3, 4, 5 ];
    ptr = ivec::to_ptr(c);
    auto d = ~[];
    ivec::unsafe::copy_from_buf(d, ptr, 5u);
    assert (ivec::len(d) == 5u);
    assert (d.(0) == 1);
    assert (d.(1) == 2);
    assert (d.(2) == 3);
    assert (d.(3) == 4);
    assert (d.(4) == 5);
}

fn main() {
    test_reserve_and_on_heap();
    test_unsafe_ptrs();
}

<commit_msg>Disable lib-ivec's test_unsafe_ptrs. Not working here<commit_after>// xfail-stage0

use std;
import std::ivec;

fn test_reserve_and_on_heap() {
    let int[] v = ~[ 1, 2 ];
    assert (!ivec::on_heap(v));
    ivec::reserve(v, 8u);
    assert (ivec::on_heap(v));
}

fn test_unsafe_ptrs() {
    // Test on-stack copy-from-buf.
    auto a = ~[ 1, 2, 3 ];
    auto ptr = ivec::to_ptr(a);
    auto b = ~[];
    ivec::unsafe::copy_from_buf(b, ptr, 3u);
    assert (ivec::len(b) == 3u);
    assert (b.(0) == 1);
    assert (b.(1) == 2);
    assert (b.(2) == 3);

    // Test on-heap copy-from-buf.
    auto c = ~[ 1, 2, 3, 4, 5 ];
    ptr = ivec::to_ptr(c);
    auto d = ~[];
    ivec::unsafe::copy_from_buf(d, ptr, 5u);
    assert (ivec::len(d) == 5u);
    assert (d.(0) == 1);
    assert (d.(1) == 2);
    assert (d.(2) == 3);
    assert (d.(3) == 4);
    assert (d.(4) == 5);
}

fn main() {
    test_reserve_and_on_heap();
    //test_unsafe_ptrs();
}

<|endoftext|>


<commit_before>use byteorder::{LittleEndian, WriteBytesExt};
use std::{convert::TryFrom, io::Write};

use super::image_type::{ImageType, ALPHA_BIT_MASK, SCREEN_ORIGIN_BIT_MASK};
use crate::color::ColorType;
use crate::error::{
    ImageResult, ParameterError, ParameterErrorKind, UnsupportedError, UnsupportedErrorKind,
};
use crate::{image::ImageEncoder, ImageError, ImageFormat};

/// TGA encoder.
pub struct TgaEncoder<W: Write> {
    writer: W,
}

impl<W: Write> TgaEncoder<W> {
    /// Create a new encoder that writes its output to ```w```.
    pub fn new(w: W) -> TgaEncoder<W> {
        TgaEncoder { writer: w }
    }

    /// Encodes the image ```buf``` that has dimensions ```width```
    /// and ```height``` and ```ColorType``` ```color_type```.
    ///
    /// The dimensions of the image must be between 1 and 65535 (inclusive) or
    /// an error will be returned.
    pub fn encode(
        mut self,
        buf: &[u8],
        width: u32,
        height: u32,
        color_type: ColorType,
    ) -> ImageResult<()> {
        let (num_alpha_bits, other_channel_bits, image_type) = get_pixel_info(color_type)?;
        let (width, height) = tga_dimensions(width, height)?;

        // Write TGA header.
        self.writer.write_u8(0)?; // No ID string.
        self.writer.write_u8(0)?; // No color map.
        self.writer.write_u8(image_type as u8)?; // Image type.
        self.writer.write_u16::<LittleEndian>(0)?; // No color map.
        self.writer.write_u16::<LittleEndian>(0)?; // No color map.
        self.writer.write_u8(0)?; // No color map.
        self.writer.write_u16::<LittleEndian>(0)?; // X-origin.
        self.writer.write_u16::<LittleEndian>(0)?; // Y-origin.
        self.writer.write_u16::<LittleEndian>(width)?; // Width.
        self.writer.write_u16::<LittleEndian>(height)?; // Height.
        self.writer.write_u8(num_alpha_bits + other_channel_bits)?; // Bits per pixel.
        self.writer
            .write_u8((num_alpha_bits & ALPHA_BIT_MASK) | SCREEN_ORIGIN_BIT_MASK)?; // Upper left origin.

        // Write out Bgr(a)8 or L(a)8 image data.
        let mut image = Vec::from(buf);

        match color_type {
            ColorType::Rgb8 | ColorType::Rgba8 => {
                for chunk in image.chunks_mut(usize::from(color_type.bytes_per_pixel())) {
                    chunk.swap(0, 2);
                }
            }
            _ => {}
        }

        self.writer.write_all(&image)?;
        Ok(())
    }
}

impl<W: Write> ImageEncoder for TgaEncoder<W> {
    fn write_image(
        self,
        buf: &[u8],
        width: u32,
        height: u32,
        color_type: ColorType,
    ) -> ImageResult<()> {
        self.encode(buf, width, height, color_type)
    }
}

fn get_pixel_info(color_type: ColorType) -> ImageResult<(u8, u8, ImageType)> {
    let sizes = match color_type {
        ColorType::Rgba8 | ColorType::Bgra8 => (8, 24, ImageType::RawTrueColor),
        ColorType::Rgb8 | ColorType::Bgr8 => (0, 24, ImageType::RawTrueColor),
        ColorType::La8 => (8, 8, ImageType::RawGrayScale),
        ColorType::L8 => (0, 8, ImageType::RawGrayScale),
        _ => {
            return Err(ImageError::Unsupported(
                UnsupportedError::from_format_and_kind(
                    ImageFormat::Tga.into(),
                    UnsupportedErrorKind::Color(color_type.into()),
                ),
            ))
        }
    };

    Ok(sizes)
}

fn tga_dimensions(width: u32, height: u32) -> ImageResult<(u16, u16)> {
    fn inner_dimensions(width: u32, height: u32) -> Option<(u16, u16)> {
        let width = u16::try_from(width).ok()?;
        let height = u16::try_from(height).ok()?;
        Some((width, height))
    }

    inner_dimensions(width, height).ok_or(ImageError::Parameter(ParameterError::from_kind(
        ParameterErrorKind::DimensionMismatch,
    )))
}

#[cfg(test)]
mod tests {
    use super::super::TgaDecoder;
    use super::TgaEncoder;
    use crate::color::ColorType;
    use crate::image::ImageDecoder;
    use std::io::Cursor;

    fn round_trip_image(image: &[u8], width: u32, height: u32, c: ColorType) -> Vec<u8> {
        let mut encoded_data = Vec::new();
        {
            let encoder = TgaEncoder::new(&mut encoded_data);
            encoder
                .encode(&image, width, height, c)
                .expect("could not encode image");
        }

        let decoder = TgaDecoder::new(Cursor::new(&encoded_data)).expect("failed to decode");

        let mut buf = vec![0; decoder.total_bytes() as usize];
        decoder.read_image(&mut buf).expect("failed to decode");
        buf
    }

    // FIXME: Taking a really long time to run. Tried switching to Bgr8, but then it just panics.
    // #[test]
    // fn huge_files_return_error() {
    //     let mut encoded_data = Vec::new();
    //     let image = vec![0u8; 3 * 40_000 * 40_000]; // 40_000x40_000 pixels, 3 bytes per pixel, allocated on the heap
    //     let encoder = TgaEncoder::new(&mut encoded_data);
    //     let result = encoder.encode(&image, 40_000, 40_000, ColorType::Rgb8);
    //     assert!(result.is_err());
    // }

    #[test]
    fn round_trip_single_pixel_rgb() {
        let image = [0, 1, 2];
        let decoded = round_trip_image(&image, 1, 1, ColorType::Rgb8);
        assert_eq!(3, decoded.len());
        assert_eq!(0, decoded[0]);
        assert_eq!(1, decoded[1]);
        assert_eq!(2, decoded[2]);
    }

    #[test]
    fn round_trip_single_pixel_rgba() {
        let image = [0, 1, 2, 3];
        let decoded = round_trip_image(&image, 1, 1, ColorType::Rgba8);
        assert_eq!(4, decoded.len());
        assert_eq!(0, decoded[0]);
        assert_eq!(1, decoded[1]);
        assert_eq!(2, decoded[2]);
        assert_eq!(3, decoded[3]);
    }

    #[test]
    fn round_trip_single_pixel_bgr() {
        let image = [0, 1, 2];
        let decoded = round_trip_image(&image, 1, 1, ColorType::Bgr8);
        assert_eq!(3, decoded.len());
        assert_eq!(2, decoded[0]);
        assert_eq!(1, decoded[1]);
        assert_eq!(0, decoded[2]);
    }

    #[test]
    fn round_trip_single_pixel_bgra() {
        let image = [0, 1, 2, 3];
        let decoded = round_trip_image(&image, 1, 1, ColorType::Bgra8);
        assert_eq!(4, decoded.len());
        assert_eq!(2, decoded[0]);
        assert_eq!(1, decoded[1]);
        assert_eq!(0, decoded[2]);
        assert_eq!(3, decoded[3]);
    }

    #[test]
    fn round_trip_3px_rgb() {
        let image = [0; 3 * 3 * 3]; // 3x3 pixels, 3 bytes per pixel
        let _decoded = round_trip_image(&image, 3, 3, ColorType::Rgb8);
    }

    #[test]
    fn round_trip_gray() {
        let image = [0, 1, 2]; // 3 pixels
        let decoded = round_trip_image(&image, 3, 1, ColorType::L8);
        assert_eq!(3, decoded.len());
        assert_eq!(0, decoded[0]);
        assert_eq!(1, decoded[1]);
        assert_eq!(2, decoded[2]);
    }

    #[test]
    fn round_trip_graya() {
        let image = [0, 1, 2, 3, 4, 5]; // 3 pixels, each with an alpha channel
        let decoded = round_trip_image(&image, 1, 3, ColorType::La8);
        assert_eq!(6, decoded.len());
        assert_eq!(0, decoded[0]);
        assert_eq!(1, decoded[1]);
        assert_eq!(2, decoded[2]);
        assert_eq!(3, decoded[3]);
        assert_eq!(4, decoded[4]);
        assert_eq!(5, decoded[5]);
    }
}
<commit_msg>More code review feedback<commit_after>use byteorder::{LittleEndian, WriteBytesExt};
use std::{convert::TryFrom, io::Write};

use super::image_type::{ImageType, ALPHA_BIT_MASK, SCREEN_ORIGIN_BIT_MASK};
use crate::color::ColorType;
use crate::error::{
    ImageResult, ParameterError, ParameterErrorKind, UnsupportedError, UnsupportedErrorKind,
};
use crate::{image::ImageEncoder, ImageError, ImageFormat};

/// TGA encoder.
pub struct TgaEncoder<W: Write> {
    writer: W,
}

impl<W: Write> TgaEncoder<W> {
    /// Create a new encoder that writes its output to ```w```.
    pub fn new(w: W) -> TgaEncoder<W> {
        TgaEncoder { writer: w }
    }

    /// Encodes the image ```buf``` that has dimensions ```width```
    /// and ```height``` and ```ColorType``` ```color_type```.
    ///
    /// The dimensions of the image must be between 1 and 65535 (inclusive) or
    /// an error will be returned.
    pub fn encode(
        mut self,
        buf: &[u8],
        width: u32,
        height: u32,
        color_type: ColorType,
    ) -> ImageResult<()> {
        let (num_alpha_bits, other_channel_bits, image_type) = get_pixel_info(color_type)?;
        let (width, height) = tga_dimensions(width, height)?;

        // Write TGA header.
        self.writer.write_u8(0)?; // No ID string.
        self.writer.write_u8(0)?; // No color map.
        self.writer.write_u8(image_type as u8)?; // Image type.
        self.writer.write_u16::<LittleEndian>(0)?; // No color map.
        self.writer.write_u16::<LittleEndian>(0)?; // No color map.
        self.writer.write_u8(0)?; // No color map.
        self.writer.write_u16::<LittleEndian>(0)?; // X-origin.
        self.writer.write_u16::<LittleEndian>(0)?; // Y-origin.
        self.writer.write_u16::<LittleEndian>(width)?; // Width.
        self.writer.write_u16::<LittleEndian>(height)?; // Height.
        self.writer.write_u8(num_alpha_bits + other_channel_bits)?; // Bits per pixel.
        self.writer
            .write_u8((num_alpha_bits & ALPHA_BIT_MASK) | SCREEN_ORIGIN_BIT_MASK)?; // Upper left origin.

        // Write out Bgr(a)8 or L(a)8 image data.
        let mut image = Vec::from(buf);

        match color_type {
            ColorType::Rgb8 | ColorType::Rgba8 => {
                for chunk in image.chunks_mut(usize::from(color_type.bytes_per_pixel())) {
                    chunk.swap(0, 2);
                }
            }
            _ => {}
        }

        self.writer.write_all(&image)?;
        Ok(())
    }
}

impl<W: Write> ImageEncoder for TgaEncoder<W> {
    fn write_image(
        self,
        buf: &[u8],
        width: u32,
        height: u32,
        color_type: ColorType,
    ) -> ImageResult<()> {
        self.encode(buf, width, height, color_type)
    }
}

fn get_pixel_info(color_type: ColorType) -> ImageResult<(u8, u8, ImageType)> {
    let sizes = match color_type {
        ColorType::Rgba8 | ColorType::Bgra8 => (8, 24, ImageType::RawTrueColor),
        ColorType::Rgb8 | ColorType::Bgr8 => (0, 24, ImageType::RawTrueColor),
        ColorType::La8 => (8, 8, ImageType::RawGrayScale),
        ColorType::L8 => (0, 8, ImageType::RawGrayScale),
        _ => {
            return Err(ImageError::Unsupported(
                UnsupportedError::from_format_and_kind(
                    ImageFormat::Tga.into(),
                    UnsupportedErrorKind::Color(color_type.into()),
                ),
            ))
        }
    };

    Ok(sizes)
}

fn tga_dimensions(width: u32, height: u32) -> ImageResult<(u16, u16)> {
    fn inner_dimensions(width: u32, height: u32) -> Option<(u16, u16)> {
        let width = u16::try_from(width).ok()?;
        let height = u16::try_from(height).ok()?;
        Some((width, height))
    }

    inner_dimensions(width, height).ok_or(ImageError::Parameter(ParameterError::from_kind(
        ParameterErrorKind::DimensionMismatch,
    )))
}

#[cfg(test)]
mod tests {
    use super::super::TgaDecoder;
    use super::TgaEncoder;
    use crate::color::ColorType;
    use crate::{ImageError, image::ImageDecoder, error::ParameterErrorKind};
    use std::io::Cursor;

    fn round_trip_image(image: &[u8], width: u32, height: u32, c: ColorType) -> Vec<u8> {
        let mut encoded_data = Vec::new();
        {
            let encoder = TgaEncoder::new(&mut encoded_data);
            encoder
                .encode(&image, width, height, c)
                .expect("could not encode image");
        }

        let decoder = TgaDecoder::new(Cursor::new(&encoded_data)).expect("failed to decode");

        let mut buf = vec![0; decoder.total_bytes() as usize];
        decoder.read_image(&mut buf).expect("failed to decode");
        buf
    }

    #[test]
    fn test_image_too_large() {
        // TGA cannot encode images larger than 65,535×65,535
        // create a 65,536×1 8-bit black image buffer
        let size = usize::from(u16::MAX) + 1;
        let img = vec![0u8; size];
        // Try to encode an image that is too large
        let mut encoded = Vec::new();
        let encoder = TgaEncoder::new(&mut encoded);
        let result = encoder.encode(&img, size as u32, 1, ColorType::L8);
        match result {
            Err(ImageError::Parameter(err)) => {
                assert_eq!(err.kind(), ParameterErrorKind::DimensionMismatch)
            }
            other => {
                assert!(false, "Encoding an image that is too large should return a DimensionError \
                                it returned {:?} instead", other)
            }
        }
    }

    #[test]
    fn round_trip_single_pixel_rgb() {
        let image = [0, 1, 2];
        let decoded = round_trip_image(&image, 1, 1, ColorType::Rgb8);
        assert_eq!(decoded.len(), image.len());
        assert_eq!(decoded.as_slice(), image);
    }

    #[test]
    fn round_trip_single_pixel_rgba() {
        let image = [0, 1, 2, 3];
        let decoded = round_trip_image(&image, 1, 1, ColorType::Rgba8);
        assert_eq!(decoded.len(), image.len());
        assert_eq!(decoded.as_slice(), image);
    }

    #[test]
    fn round_trip_single_pixel_bgr() {
        let image = [0, 1, 2];
        let decoded = round_trip_image(&image, 1, 1, ColorType::Bgr8);
        assert_eq!(decoded.len(), image.len());
        assert_eq!(decoded.as_slice(), [2, 1, 0]);
    }

    #[test]
    fn round_trip_single_pixel_bgra() {
        let image = [0, 1, 2, 3];
        let decoded = round_trip_image(&image, 1, 1, ColorType::Bgra8);
        assert_eq!(decoded.len(), image.len());
        assert_eq!(decoded.as_slice(), [2, 1, 0, 3]);
    }

    #[test]
    fn round_trip_gray() {
        let image = [0, 1, 2];
        let decoded = round_trip_image(&image, 3, 1, ColorType::L8);
        assert_eq!(decoded.len(), image.len());
        assert_eq!(decoded.as_slice(), image);
    }

    #[test]
    fn round_trip_graya() {
        let image = [0, 1, 2, 3, 4, 5];
        let decoded = round_trip_image(&image, 1, 3, ColorType::La8);
        assert_eq!(decoded.len(), image.len());
        assert_eq!(decoded.as_slice(), image);
    }

    #[test]
    fn round_trip_3px_rgb() {
        let image = [0; 3 * 3 * 3]; // 3x3 pixels, 3 bytes per pixel
        let _decoded = round_trip_image(&image, 3, 3, ColorType::Rgb8);
    }
}
<|endoftext|>


<commit_before>use byteorder::{LittleEndian, WriteBytesExt};
use std::io::{self, Write};

use super::image_type::{ImageType, ALPHA_BIT_MASK, SCREEN_ORIGIN_BIT_MASK};
use crate::color::ColorType;
use crate::error::{EncodingError, ImageResult, UnsupportedError, UnsupportedErrorKind};
use crate::{image::ImageEncoder, ImageError, ImageFormat};

const MAX_IMAGE_DIMENSION: u32 = std::u16::MAX as u32;

/// TGA encoder.
pub struct TgaEncoder<W: Write> {
    writer: W,
}

impl<W: Write> TgaEncoder<W> {
    /// Create a new encoder that writes its output to ```w```.
    pub fn new(w: W) -> TgaEncoder<W> {
        TgaEncoder { writer: w }
    }

    /// Encodes the image ```buf``` that has dimensions ```width```
    /// and ```height``` and ```ColorType``` ```color_type```.
    ///
    /// The dimensions of the image must be between 1 and 65535 (inclusive) or
    /// an error will be returned.
    pub fn encode(
        self,
        buf: &[u8],
        width: u32,
        height: u32,
        color_type: ColorType,
    ) -> ImageResult<()> {
        match color_type {
            ColorType::Rgba8
            | ColorType::Bgra8
            | ColorType::Rgb8
            | ColorType::Bgr8
            | ColorType::La8
            | ColorType::L8 => self
                .encode_impl(buf, width, height, color_type)
                .map_err(|err| {
                    ImageError::Encoding(EncodingError::new(ImageFormat::Tga.into(), err))
                }),
            _ => Err(ImageError::Unsupported(
                UnsupportedError::from_format_and_kind(
                    ImageFormat::Tga.into(),
                    UnsupportedErrorKind::Color(color_type.into()),
                ),
            )),
        }
    }

    fn encode_impl(
        mut self,
        buf: &[u8],
        width: u32,
        height: u32,
        color_type: ColorType,
    ) -> io::Result<()> {
        // Get pixel encoding data.
        let (num_alpha_bits, other_channel_bits, image_type) = match color_type {
            ColorType::Rgba8 | ColorType::Bgra8 => (8, 24, ImageType::RawTrueColor),
            ColorType::Rgb8 | ColorType::Bgr8 => (0, 24, ImageType::RawTrueColor),
            ColorType::La8 => (8, 8, ImageType::RawGrayScale),
            ColorType::L8 => (0, 8, ImageType::RawGrayScale),
            _ => unreachable!(),
        };

        // Write TGA header.
        self.writer.write_u8(0)?; // No ID string.
        self.writer.write_u8(0)?; // No color map.
        self.writer.write_u8(image_type as u8)?; // Image type.
        self.writer.write_u16::<LittleEndian>(0)?; // No color map.
        self.writer.write_u16::<LittleEndian>(0)?; // No color map.
        self.writer.write_u8(0)?; // No color map.
        self.writer.write_u16::<LittleEndian>(0)?; // X-origin.
        self.writer.write_u16::<LittleEndian>(0)?; // Y-origin.
        self.write_dimension(width)?; // Width.
        self.write_dimension(height)?; // Height.
        self.writer.write_u8(num_alpha_bits + other_channel_bits)?; // Bits per pixel.
        self.writer
            .write_u8((num_alpha_bits & ALPHA_BIT_MASK) | SCREEN_ORIGIN_BIT_MASK)?; // Upper left origin.

        // Write out Bgr(a)8 or L(a)8 image data.
        let mut image = Vec::from(buf);

        match color_type {
            ColorType::Rgb8 | ColorType::Rgba8 => {
                for chunk in image.chunks_mut(color_type.bytes_per_pixel() as usize) {
                    chunk.swap(0, 2);
                }
            }
            _ => {}
        }

        self.writer.write_all(&image)?;
        Ok(())
    }

    fn write_dimension(&mut self, value: u32) -> io::Result<()> {
        if value < 1 || value > MAX_IMAGE_DIMENSION {
            return Err(io::Error::new(
                io::ErrorKind::InvalidData,
                format!(
                    "Invalid TGA dimensions (width and height must be between 1 and {})",
                    MAX_IMAGE_DIMENSION
                ),
            ));
        }
        self.writer.write_u16::<LittleEndian>(value as u16)
    }
}

impl<W: Write> ImageEncoder for TgaEncoder<W> {
    fn write_image(
        self,
        buf: &[u8],
        width: u32,
        height: u32,
        color_type: ColorType,
    ) -> ImageResult<()> {
        self.encode(buf, width, height, color_type)
    }
}
<commit_msg>Fixes based on code review<commit_after>use byteorder::{LittleEndian, WriteBytesExt};
use std::{convert::TryFrom, io::Write};

use super::image_type::{ImageType, ALPHA_BIT_MASK, SCREEN_ORIGIN_BIT_MASK};
use crate::color::ColorType;
use crate::error::{
    ImageResult, ParameterError, ParameterErrorKind, UnsupportedError, UnsupportedErrorKind,
};
use crate::{image::ImageEncoder, ImageError, ImageFormat};

/// TGA encoder.
pub struct TgaEncoder<W: Write> {
    writer: W,
}

impl<W: Write> TgaEncoder<W> {
    /// Create a new encoder that writes its output to ```w```.
    pub fn new(w: W) -> TgaEncoder<W> {
        TgaEncoder { writer: w }
    }

    /// Encodes the image ```buf``` that has dimensions ```width```
    /// and ```height``` and ```ColorType``` ```color_type```.
    ///
    /// The dimensions of the image must be between 1 and 65535 (inclusive) or
    /// an error will be returned.
    pub fn encode(
        mut self,
        buf: &[u8],
        width: u32,
        height: u32,
        color_type: ColorType,
    ) -> ImageResult<()> {
        let (num_alpha_bits, other_channel_bits, image_type) = get_pixel_info(color_type)?;
        let (width, height) = tga_dimensions(width, height)?;

        // Write TGA header.
        self.writer.write_u8(0)?; // No ID string.
        self.writer.write_u8(0)?; // No color map.
        self.writer.write_u8(image_type as u8)?; // Image type.
        self.writer.write_u16::<LittleEndian>(0)?; // No color map.
        self.writer.write_u16::<LittleEndian>(0)?; // No color map.
        self.writer.write_u8(0)?; // No color map.
        self.writer.write_u16::<LittleEndian>(0)?; // X-origin.
        self.writer.write_u16::<LittleEndian>(0)?; // Y-origin.
        self.writer.write_u16::<LittleEndian>(width)?; // Width.
        self.writer.write_u16::<LittleEndian>(height)?; // Height.
        self.writer.write_u8(num_alpha_bits + other_channel_bits)?; // Bits per pixel.
        self.writer
            .write_u8((num_alpha_bits & ALPHA_BIT_MASK) | SCREEN_ORIGIN_BIT_MASK)?; // Upper left origin.

        // Write out Bgr(a)8 or L(a)8 image data.
        let mut image = Vec::from(buf);

        match color_type {
            ColorType::Rgb8 | ColorType::Rgba8 => {
                for chunk in image.chunks_mut(usize::from(color_type.bytes_per_pixel())) {
                    chunk.swap(0, 2);
                }
            }
            _ => {}
        }

        self.writer.write_all(&image)?;
        Ok(())
    }
}

impl<W: Write> ImageEncoder for TgaEncoder<W> {
    fn write_image(
        self,
        buf: &[u8],
        width: u32,
        height: u32,
        color_type: ColorType,
    ) -> ImageResult<()> {
        self.encode(buf, width, height, color_type)
    }
}

fn get_pixel_info(color_type: ColorType) -> ImageResult<(u8, u8, ImageType)> {
    let sizes = match color_type {
        ColorType::Rgba8 | ColorType::Bgra8 => (8, 24, ImageType::RawTrueColor),
        ColorType::Rgb8 | ColorType::Bgr8 => (0, 24, ImageType::RawTrueColor),
        ColorType::La8 => (8, 8, ImageType::RawGrayScale),
        ColorType::L8 => (0, 8, ImageType::RawGrayScale),
        _ => {
            return Err(ImageError::Unsupported(
                UnsupportedError::from_format_and_kind(
                    ImageFormat::Tga.into(),
                    UnsupportedErrorKind::Color(color_type.into()),
                ),
            ))
        }
    };

    Ok(sizes)
}

fn tga_dimensions(width: u32, height: u32) -> ImageResult<(u16, u16)> {
    fn inner_dimensions(width: u32, height: u32) -> Option<(u16, u16)> {
        let width = u16::try_from(width).ok()?;
        let height = u16::try_from(height).ok()?;
        Some((width, height))
    }

    inner_dimensions(width, height).ok_or(ImageError::Parameter(ParameterError::from_kind(
        ParameterErrorKind::DimensionMismatch,
    )))
}

#[cfg(test)]
mod tests {
    use super::super::TgaDecoder;
    use super::TgaEncoder;
    use crate::color::ColorType;
    use crate::image::ImageDecoder;
    use std::io::Cursor;

    fn round_trip_image(image: &[u8], width: u32, height: u32, c: ColorType) -> Vec<u8> {
        let mut encoded_data = Vec::new();
        {
            let encoder = TgaEncoder::new(&mut encoded_data);
            encoder
                .encode(&image, width, height, c)
                .expect("could not encode image");
        }

        let decoder = TgaDecoder::new(Cursor::new(&encoded_data)).expect("failed to decode");

        let mut buf = vec![0; decoder.total_bytes() as usize];
        decoder.read_image(&mut buf).expect("failed to decode");
        buf
    }

    // FIXME: Taking a really long time to run. Tried switching to Bgr8, but then it just panics.
    // #[test]
    // fn huge_files_return_error() {
    //     let mut encoded_data = Vec::new();
    //     let image = vec![0u8; 3 * 40_000 * 40_000]; // 40_000x40_000 pixels, 3 bytes per pixel, allocated on the heap
    //     let encoder = TgaEncoder::new(&mut encoded_data);
    //     let result = encoder.encode(&image, 40_000, 40_000, ColorType::Rgb8);
    //     assert!(result.is_err());
    // }

    #[test]
    fn round_trip_single_pixel_rgb() {
        let image = [0, 1, 2];
        let decoded = round_trip_image(&image, 1, 1, ColorType::Rgb8);
        assert_eq!(3, decoded.len());
        assert_eq!(0, decoded[0]);
        assert_eq!(1, decoded[1]);
        assert_eq!(2, decoded[2]);
    }

    #[test]
    fn round_trip_single_pixel_rgba() {
        let image = [0, 1, 2, 3];
        let decoded = round_trip_image(&image, 1, 1, ColorType::Rgba8);
        assert_eq!(4, decoded.len());
        assert_eq!(0, decoded[0]);
        assert_eq!(1, decoded[1]);
        assert_eq!(2, decoded[2]);
        assert_eq!(3, decoded[3]);
    }

    #[test]
    fn round_trip_single_pixel_bgr() {
        let image = [0, 1, 2];
        let decoded = round_trip_image(&image, 1, 1, ColorType::Bgr8);
        assert_eq!(3, decoded.len());
        assert_eq!(2, decoded[0]);
        assert_eq!(1, decoded[1]);
        assert_eq!(0, decoded[2]);
    }

    #[test]
    fn round_trip_single_pixel_bgra() {
        let image = [0, 1, 2, 3];
        let decoded = round_trip_image(&image, 1, 1, ColorType::Bgra8);
        assert_eq!(4, decoded.len());
        assert_eq!(2, decoded[0]);
        assert_eq!(1, decoded[1]);
        assert_eq!(0, decoded[2]);
        assert_eq!(3, decoded[3]);
    }

    #[test]
    fn round_trip_3px_rgb() {
        let image = [0; 3 * 3 * 3]; // 3x3 pixels, 3 bytes per pixel
        let _decoded = round_trip_image(&image, 3, 3, ColorType::Rgb8);
    }

    #[test]
    fn round_trip_gray() {
        let image = [0, 1, 2]; // 3 pixels
        let decoded = round_trip_image(&image, 3, 1, ColorType::L8);
        assert_eq!(3, decoded.len());
        assert_eq!(0, decoded[0]);
        assert_eq!(1, decoded[1]);
        assert_eq!(2, decoded[2]);
    }

    #[test]
    fn round_trip_graya() {
        let image = [0, 1, 2, 3, 4, 5]; // 3 pixels, each with an alpha channel
        let decoded = round_trip_image(&image, 1, 3, ColorType::La8);
        assert_eq!(6, decoded.len());
        assert_eq!(0, decoded[0]);
        assert_eq!(1, decoded[1]);
        assert_eq!(2, decoded[2]);
        assert_eq!(3, decoded[3]);
        assert_eq!(4, decoded[4]);
        assert_eq!(5, decoded[5]);
    }
}
<|endoftext|>


<commit_before>///
/// Represents the possible values of an attribute on a tree node
///
pub enum TreeValue {
    Nothing,
    Int(i32),
    Real(f64),
    String(String),
    Data(Vec<u8>)
}

///
/// Traits implemented by types that can be treated as tree values
///
pub trait ToTreeValue {
    fn to_tree_value(&self) -> TreeValue;
}

impl TreeValue {
    pub fn is_nothing(&self) -> bool {
        match *self {
            TreeValue::Nothing => true,
            _ => false
        }
    }
}

impl ToTreeValue for TreeValue {
    fn to_tree_value(&self) -> TreeValue {
        self.clone()
    }
}

impl<'a> ToTreeValue for &'a TreeValue {
    fn to_tree_value(&self) -> TreeValue {
        (*self).clone()
    }
}

impl ToTreeValue for () {
    fn to_tree_value(&self) -> TreeValue { TreeValue::Nothing }
}

impl ToTreeValue for i32 {
    fn to_tree_value(&self) -> TreeValue { TreeValue::Int(*self) }
}

impl ToTreeValue for f64 {
    fn to_tree_value(&self) -> TreeValue { TreeValue::Real(*self) }
}

impl ToTreeValue for str {
    fn to_tree_value(&self) -> TreeValue { TreeValue::String(self.to_owned()) }
}

impl ToTreeValue for String {
    fn to_tree_value(&self) -> TreeValue { TreeValue::String(self.to_owned()) }
}

impl ToTreeValue for Vec<u8> {
    fn to_tree_value(&self) -> TreeValue { TreeValue::Data(self.to_owned()) }
}

impl Clone for TreeValue {
    fn clone(&self) -> TreeValue {
        match *self {
            TreeValue::Nothing          => TreeValue::Nothing,
            TreeValue::Int(v)           => TreeValue::Int(v),
            TreeValue::Real(f)          => TreeValue::Real(f),
            TreeValue::String(ref s)    => TreeValue::String(s.to_string()),
            TreeValue::Data(ref d)      => TreeValue::Data(d.to_vec())
        }
    }
}<commit_msg>Fix ToTreeValue for &str<commit_after>///
/// Represents the possible values of an attribute on a tree node
///
pub enum TreeValue {
    Nothing,
    Int(i32),
    Real(f64),
    String(String),
    Data(Vec<u8>)
}

///
/// Traits implemented by types that can be treated as tree values
///
pub trait ToTreeValue {
    fn to_tree_value(&self) -> TreeValue;
}

impl TreeValue {
    pub fn is_nothing(&self) -> bool {
        match *self {
            TreeValue::Nothing => true,
            _ => false
        }
    }
}

impl ToTreeValue for TreeValue {
    fn to_tree_value(&self) -> TreeValue {
        self.clone()
    }
}

impl<'a> ToTreeValue for &'a TreeValue {
    fn to_tree_value(&self) -> TreeValue {
        (*self).clone()
    }
}

impl ToTreeValue for () {
    fn to_tree_value(&self) -> TreeValue { TreeValue::Nothing }
}

impl ToTreeValue for i32 {
    fn to_tree_value(&self) -> TreeValue { TreeValue::Int(*self) }
}

impl ToTreeValue for f64 {
    fn to_tree_value(&self) -> TreeValue { TreeValue::Real(*self) }
}

impl<'a> ToTreeValue for &'a str {
    fn to_tree_value(&self) -> TreeValue { TreeValue::String(self.to_string()) }
}

impl ToTreeValue for String {
    fn to_tree_value(&self) -> TreeValue { TreeValue::String(self.to_owned()) }
}

impl ToTreeValue for Vec<u8> {
    fn to_tree_value(&self) -> TreeValue { TreeValue::Data(self.to_owned()) }
}

impl Clone for TreeValue {
    fn clone(&self) -> TreeValue {
        match *self {
            TreeValue::Nothing          => TreeValue::Nothing,
            TreeValue::Int(v)           => TreeValue::Int(v),
            TreeValue::Real(f)          => TreeValue::Real(f),
            TreeValue::String(ref s)    => TreeValue::String(s.to_string()),
            TreeValue::Data(ref d)      => TreeValue::Data(d.to_vec())
        }
    }
}<|endoftext|>