<commit_before>#![feature(plugin)]
#![plugin(clippy)]
#![deny(clippy)]
#![allow(unused)]

fn main() {
    let specter: i32;
    let spectre: i32;

    let apple: i32; //~ NOTE: existing binding defined here
    let bpple: i32; //~ ERROR: name is too similar
    let cpple: i32; //~ ERROR: name is too similar

    let a_bar: i32;
    let b_bar: i32;
    let c_bar: i32;

    let items = [5];
    for item in &items {
        loop {}
    }

    let foo_x: i32;
    let foo_y: i32;

    let rhs: i32;
    let lhs: i32;

    let bla_rhs: i32;
    let bla_lhs: i32;

    let blubrhs: i32; //~ NOTE: existing binding defined here
    let blublhs: i32; //~ ERROR: name is too similar

    let blubx: i32; //~ NOTE: existing binding defined here
    let bluby: i32; //~ ERROR: name is too similar
    //~| HELP: separate the discriminating character by an underscore like: `blub_y`

    let cake: i32; //~ NOTE: existing binding defined here
    let cakes: i32;
    let coke: i32; //~ ERROR: name is too similar

    match 5 {
        cheese @ 1 => {},
        rabbit => panic!(),
    }
    let cheese: i32;
    match (42, 43) {
        (cheese1, 1) => {},
        (cheese2, 2) => panic!(),
        _ => println!(""),
    }
}

#[derive(Clone, Debug)]
enum MaybeInst {
    Split,
    Split1(usize),
    Split2(usize),
}

struct InstSplit {
    uiae: usize,
}

impl MaybeInst {
    fn fill(&mut self) {
        let filled = match *self {
            MaybeInst::Split1(goto1) => panic!(1),
            MaybeInst::Split2(goto2) => panic!(2),
            _ => unimplemented!(),
        };
        unimplemented!()
    }
}

fn bla() {
    let a: i32;
    let (b, c, d): (i32, i64, i16);
    {
        {
            let cdefg: i32;
            let blar: i32;
        }
        {
            let e: i32; //~ ERROR: 5th binding whose name is just one char
        }
        {
            let e: i32; //~ ERROR: 5th binding whose name is just one char
            let f: i32; //~ ERROR: 6th binding whose name is just one char
        }
        match 5 {
            1 => println!(""),
            e => panic!(), //~ ERROR: 5th binding whose name is just one char
        }
        match 5 {
            1 => println!(""),
            _ => panic!(),
        }
    }
}
<commit_msg>update for compiletest update<commit_after>#![feature(plugin)]
#![plugin(clippy)]
#![deny(clippy)]
//~^ NOTE: lint level defined here
//~| NOTE: lint level defined here
//~| NOTE: lint level defined here
//~| NOTE: lint level defined here
//~| NOTE: lint level defined here
//~| NOTE: lint level defined here
//~| NOTE: lint level defined here
//~| NOTE: lint level defined here
//~| NOTE: lint level defined here
#![allow(unused)]

fn main() {
    let specter: i32;
    let spectre: i32;

    let apple: i32; //~ NOTE: existing binding defined here
    //~^ NOTE: existing binding defined here
    let bpple: i32; //~ ERROR: name is too similar
    //~| HELP: separate the discriminating character by an underscore like: `b_pple`
    //~| HELP: for further information visit
    let cpple: i32; //~ ERROR: name is too similar
    //~| HELP: separate the discriminating character by an underscore like: `c_pple`
    //~| HELP: for further information visit

    let a_bar: i32;
    let b_bar: i32;
    let c_bar: i32;

    let items = [5];
    for item in &items {
        loop {}
    }

    let foo_x: i32;
    let foo_y: i32;

    let rhs: i32;
    let lhs: i32;

    let bla_rhs: i32;
    let bla_lhs: i32;

    let blubrhs: i32; //~ NOTE: existing binding defined here
    let blublhs: i32; //~ ERROR: name is too similar
    //~| HELP: for further information visit

    let blubx: i32; //~ NOTE: existing binding defined here
    let bluby: i32; //~ ERROR: name is too similar
    //~| HELP: for further information visit
    //~| HELP: separate the discriminating character by an underscore like: `blub_y`

    let cake: i32; //~ NOTE: existing binding defined here
    let cakes: i32;
    let coke: i32; //~ ERROR: name is too similar
    //~| HELP: for further information visit

    match 5 {
        cheese @ 1 => {},
        rabbit => panic!(),
    }
    let cheese: i32;
    match (42, 43) {
        (cheese1, 1) => {},
        (cheese2, 2) => panic!(),
        _ => println!(""),
    }
}

#[derive(Clone, Debug)]
enum MaybeInst {
    Split,
    Split1(usize),
    Split2(usize),
}

struct InstSplit {
    uiae: usize,
}

impl MaybeInst {
    fn fill(&mut self) {
        let filled = match *self {
            MaybeInst::Split1(goto1) => panic!(1),
            MaybeInst::Split2(goto2) => panic!(2),
            _ => unimplemented!(),
        };
        unimplemented!()
    }
}

fn bla() {
    let a: i32;
    let (b, c, d): (i32, i64, i16);
    {
        {
            let cdefg: i32;
            let blar: i32;
        }
        {
            let e: i32; //~ ERROR: 5th binding whose name is just one char
            //~| HELP: for further information visit
        }
        {
            let e: i32; //~ ERROR: 5th binding whose name is just one char
            //~| HELP: for further information visit
            let f: i32; //~ ERROR: 6th binding whose name is just one char
            //~| HELP: for further information visit
        }
        match 5 {
            1 => println!(""),
            e => panic!(), //~ ERROR: 5th binding whose name is just one char
            //~| HELP: for further information visit
        }
        match 5 {
            1 => println!(""),
            _ => panic!(),
        }
    }
}
<|endoftext|>


<commit_before>#[link(name = "fuse",
uuid = "d37c5c30-fdcd-459d-bfca-ebb8da04b2a0",
url = "https://github.com/MicahChalmer/rust-fuse")];

#[comment = "FUSE bindings"];
#[license = "MIT"];
#[crate_type = "lib"];

use std::libc::{
    c_char,
    c_int,
    c_uint,
    c_ulong,
    c_void,
    mode_t,
    off_t,
    pid_t,
    size_t,
    stat,
    uid_t,
    gid_t
};

use std::ptr;
use std::str;

// A cfuncptr is used here to stand in for a C function pointer.
// For this struct, see fuse.h
type cfuncptr = *u8;
struct c_fuse_operations {
    getattr: cfuncptr,
    readlink: cfuncptr,
    getdir: cfuncptr,
    mknod: cfuncptr,
    mkdir: cfuncptr,
    unlink: cfuncptr,
    rmdir: cfuncptr,
    symlink: cfuncptr,
    rename: cfuncptr,
    link: cfuncptr,
    chmod: cfuncptr,
    chown: cfuncptr,
    truncate: cfuncptr,
    utime: cfuncptr,
    open: cfuncptr,
    read: cfuncptr,
    write: cfuncptr,
    statfs: cfuncptr,
    flush: cfuncptr,
    release: cfuncptr,
    fsync: cfuncptr,
    setxattr: cfuncptr,
    getxattr: cfuncptr,
    listxattr: cfuncptr,
    removexattr: cfuncptr,
    opendir: cfuncptr,
    readdir: cfuncptr,
    releasedir: cfuncptr,
    fsyncdir: cfuncptr,
    init: cfuncptr,
    destroy: cfuncptr,
    access: cfuncptr,
    create: cfuncptr,
    ftruncate: cfuncptr,
    fgetattr: cfuncptr,
    lock: cfuncptr,
    utimens: cfuncptr,
    bmap: cfuncptr,

    flag_nullpath_ok: uint,
    flag_nopath: uint,
    flag_utime_omit_ok: uint,
    flag_reserved: uint,

    ioctl: cfuncptr,
    poll: cfuncptr,
    write_buf: cfuncptr,
    read_buf: cfuncptr,
    flock: cfuncptr
}

// TODO: this should not be public
pub struct fuse_file_info {
    flags: c_int,
    fh_old: c_ulong, // Old file handle, don't use
    writepage: c_int,
    direct_io: c_uint,
    keep_cache: c_uint,
    flush: c_uint,
    nonseekable: c_uint,
    flock_release: c_uint,
    padding: c_uint, // Padding.  Do not use
    fh: u64,
    lock_owner: u64
}

struct c_fuse_context {
    fuse: *c_void,
    uid: uid_t,
    gid: gid_t,
    pid: pid_t,
    private_data: *rust_fuse_data,  // we use this to know what object to call
    umask: mode_t
}

struct rust_fuse_data {
    ops: ~FuseOperations
}

extern {
    fn fuse_main_real(argc:c_int, argv:**c_char,
                      op:*c_fuse_operations, op_size: size_t,
                      user_data: *c_void);

    fn fuse_get_context() -> *c_fuse_context;

    // Workaround for the fact that we can't call into c via a function ptr right
    // from rust
    fn call_filer_function(filler: cfuncptr, buf: *c_void, name: *c_char, stbuf: *stat,
                           off: off_t);
}

// Used for return values from FS operations
type errno = c_int;

type fuse_fill_dir_func<'self> = &'self fn (&'self str, Option<stat>, off_t) -> c_int;

pub struct dir_entry {
    name: ~str,
    stat: Option<stat>,
    off: off_t
}

pub trait FuseOperations {
    fn getattr(&self, path:&str, stbuf: &mut stat) -> errno;
    fn readdir(&self, path:&str, info: &fuse_file_info, filler: fuse_fill_dir_func) -> errno;
    fn open(&self, path:&str, info: &mut fuse_file_info) -> errno;  // TODO: don't allow mutation of the whole fuse_file_info
    fn read(&self, path:&str, buf:&mut [u8], size: size_t, offset: off_t, info: &fuse_file_info) -> (errno, size_t);
}

extern fn c_getattr(path: *c_char, stbuf: *mut stat) -> errno {
    unsafe {
        let ops = &((*(*fuse_get_context()).private_data).ops);
        ptr::zero_memory(stbuf, 1);
        ops.getattr(str::raw::from_c_str(path), &mut *stbuf)
    }
}

extern fn c_readdir(path: *c_char, buf: *c_void, filler: cfuncptr,
                    offset: off_t, fi: *fuse_file_info) {
    unsafe {

    }
}

pub fn fuse_main<T: FuseOperations>(args: ~[~str], ops: ~T) {

}
<commit_msg>readdir compiles<commit_after>#[link(name = "fuse",
uuid = "d37c5c30-fdcd-459d-bfca-ebb8da04b2a0",
url = "https://github.com/MicahChalmer/rust-fuse")];

#[comment = "FUSE bindings"];
#[license = "MIT"];
#[crate_type = "lib"];

use std::libc::{
    c_char,
    c_int,
    c_uint,
    c_ulong,
    c_void,
    mode_t,
    off_t,
    pid_t,
    size_t,
    stat,
    uid_t,
    gid_t
};

use std::ptr;
use std::str;

// A cfuncptr is used here to stand in for a C function pointer.
// For this struct, see fuse.h
type cfuncptr = *u8;
struct c_fuse_operations {
    getattr: cfuncptr,
    readlink: cfuncptr,
    getdir: cfuncptr,
    mknod: cfuncptr,
    mkdir: cfuncptr,
    unlink: cfuncptr,
    rmdir: cfuncptr,
    symlink: cfuncptr,
    rename: cfuncptr,
    link: cfuncptr,
    chmod: cfuncptr,
    chown: cfuncptr,
    truncate: cfuncptr,
    utime: cfuncptr,
    open: cfuncptr,
    read: cfuncptr,
    write: cfuncptr,
    statfs: cfuncptr,
    flush: cfuncptr,
    release: cfuncptr,
    fsync: cfuncptr,
    setxattr: cfuncptr,
    getxattr: cfuncptr,
    listxattr: cfuncptr,
    removexattr: cfuncptr,
    opendir: cfuncptr,
    readdir: cfuncptr,
    releasedir: cfuncptr,
    fsyncdir: cfuncptr,
    init: cfuncptr,
    destroy: cfuncptr,
    access: cfuncptr,
    create: cfuncptr,
    ftruncate: cfuncptr,
    fgetattr: cfuncptr,
    lock: cfuncptr,
    utimens: cfuncptr,
    bmap: cfuncptr,

    flag_nullpath_ok: uint,
    flag_nopath: uint,
    flag_utime_omit_ok: uint,
    flag_reserved: uint,

    ioctl: cfuncptr,
    poll: cfuncptr,
    write_buf: cfuncptr,
    read_buf: cfuncptr,
    flock: cfuncptr
}

// TODO: this should not be public
pub struct fuse_file_info {
    flags: c_int,
    fh_old: c_ulong, // Old file handle, don't use
    writepage: c_int,
    direct_io: c_uint,
    keep_cache: c_uint,
    flush: c_uint,
    nonseekable: c_uint,
    flock_release: c_uint,
    padding: c_uint, // Padding.  Do not use
    fh: u64,
    lock_owner: u64
}

struct c_fuse_context {
    fuse: *c_void,
    uid: uid_t,
    gid: gid_t,
    pid: pid_t,
    private_data: *rust_fuse_data,  // we use this to know what object to call
    umask: mode_t
}

struct rust_fuse_data {
    ops: ~FuseOperations
}

extern {
    fn fuse_main_real(argc:c_int, argv:**c_char,
                      op:*c_fuse_operations, op_size: size_t,
                      user_data: *c_void);

    fn fuse_get_context() -> *c_fuse_context;

    // Workaround for the fact that we can't call into c via a function ptr right
    // from rust
    fn call_filler_function(filler: cfuncptr, buf: *c_void, name: *c_char, stbuf: *stat,
                           off: off_t) -> c_int;
}

// Used for return values from FS operations
type errno = c_int;

type fuse_fill_dir_func<'self> = &'self fn (&'self str, Option<stat>, off_t) -> c_int;

pub struct dir_entry {
    name: ~str,
    stat: Option<stat>,
    off: off_t
}

pub trait FuseOperations {
    fn getattr(&self, path:&str, stbuf: &mut stat) -> errno;
    fn readdir(&self, path:&str, filler: fuse_fill_dir_func,
               offset: off_t, info: &fuse_file_info) -> errno;
    fn open(&self, path:&str, info: &mut fuse_file_info) -> errno;  // TODO: don't allow mutation of the whole fuse_file_info
    fn read(&self, path:&str, buf:&mut [u8], size: size_t, offset: off_t, info: &fuse_file_info) -> (errno, size_t);
}

unsafe fn get_context_ops() -> &~FuseOperations {
    &((*(*fuse_get_context()).private_data).ops)
}

extern fn c_getattr(path: *c_char, stbuf: *mut stat) -> errno {
    unsafe {
        let ops = get_context_ops();
        ptr::zero_memory(stbuf, 1);
        ops.getattr(str::raw::from_c_str(path), &mut *stbuf)
    }
}

extern fn c_readdir(path: *c_char, buf: *c_void, filler: cfuncptr,
                    offset: off_t, fi: *fuse_file_info) -> c_int {
    unsafe {
        let ops = get_context_ops();
        let fill_func = |name:&str, st:Option<stat>, ofs:off_t| -> c_int {
                name.as_c_str(|c_name| {
                        call_filler_function(filler, buf, c_name, match st {
                                Some(ref s) => ptr::to_unsafe_ptr(s),
                                None => ptr::null()
                            }, ofs)
                    })
        };
        ops.readdir(str::raw::from_c_str(path), fill_func, offset, &*fi)
    }
}

pub fn fuse_main<T: FuseOperations>(_args: ~[~str], _ops: ~T) {

}
<|endoftext|>


<commit_before>//! Implements the game representation

use super::piece::Piece;
use super::color::{Color};
use super::square::{File,Square};
use super::moves::Plies;
use super::board::{mod,Board};
use super::castle::{mod,CastlingData,Side};

/// A complete representation of a chess position.
#[deriving(Clone)]
pub struct Position {
    data: Board,
    side_to_move: Color,
    castling: CastlingData,
    en_passant: Option<File>,
    ply_count: Plies,
}
impl Position {
    pub fn new() -> Position {
        Position {
            data: Board::new(),
            side_to_move: Color::White,
            castling: CastlingData::new(),
            en_passant: None,
            ply_count: Plies(0),
        }
    }
    pub fn at(&self, s: Square) -> Option<Piece> {
        self.data.at(s)
    }
    pub fn is_piece_at(&self, p: Piece, s: Square) -> bool {
        self.data.is_piece_at(p,s)
    }
    pub fn is_empty_at(&self, s: Square) -> bool {
        self.data.is_empty_at(s)
    }
    pub fn color_at(&self, s: Square) -> Option<Color> {
        self.data.color_at(s)
    }
    pub fn set_at_mut(&mut self, s: Square, val: Piece) {
        self.data.set_at_mut(s, val);
    }
    pub fn remove_at_mut(&mut self, s: Square) {
        self.data.remove_at_mut(s);
    }
    pub fn king_square(&self, c: Color) -> Square {
        self.data.king_square(c)
    }
    pub fn side_to_move(&self) -> Color {
        self.side_to_move
    }
    pub fn set_side_to_move_mut(&mut self, c: Color) {
        self.side_to_move = c;
    }
    pub fn swap_side_to_move_mut(&mut self) {
        let c = self.side_to_move.invert();
        self.set_side_to_move_mut(c);
    }
    pub fn can_castle(&self, side: Side, c: Color) -> bool {
        self.castling.get(side, c)
    }
    // Does not check for castling out of check, through check, or into check.
    pub fn can_castle_now(&self, side: Side, c: Color) -> bool {
        self.can_castle(side, c) &&
            castle::require_empty_squares(side, c).iter().all( |x| self.is_empty_at(*x) )
    }
    pub fn set_castle_mut(&mut self, side:Side, c:Color, val: bool) {
        self.castling.set_mut(side, c, val);
    }
    pub fn en_passant(&self) -> Option<File> {
        self.en_passant
    }
    pub fn has_en_passant(&self) -> bool {
        self.en_passant.is_some()
    }
    pub fn set_en_passant_mut(&mut self, val: Option<File>) {
        self.en_passant = val;
    }
    pub fn ply_count(&self) -> Plies {
        self.ply_count
    }
    pub fn set_ply_count_mut(&mut self, val: Plies) {
        self.ply_count = val;
    }

    pub fn piece_iter(&self) -> board::Iter {
        self.data.iter()
    }
}
<commit_msg>Reorder functions<commit_after>//! Implements the game representation

use super::piece::Piece;
use super::color::{Color};
use super::square::{File,Square};
use super::moves::Plies;
use super::board::{mod,Board};
use super::castle::{mod,CastlingData,Side};

/// A complete representation of a chess position.
#[deriving(Clone)]
pub struct Position {
    data: Board,
    side_to_move: Color,
    castling: CastlingData,
    en_passant: Option<File>,
    ply_count: Plies,
}
impl Position {
    pub fn new() -> Position {
        Position {
            data: Board::new(),
            side_to_move: Color::White,
            castling: CastlingData::new(),
            en_passant: None,
            ply_count: Plies(0),
        }
    }
    pub fn at(&self, s: Square) -> Option<Piece> {
        self.data.at(s)
    }
    pub fn is_piece_at(&self, p: Piece, s: Square) -> bool {
        self.data.is_piece_at(p,s)
    }
    pub fn is_empty_at(&self, s: Square) -> bool {
        self.data.is_empty_at(s)
    }
    pub fn color_at(&self, s: Square) -> Option<Color> {
        self.data.color_at(s)
    }
    pub fn set_at_mut(&mut self, s: Square, val: Piece) {
        self.data.set_at_mut(s, val);
    }
    pub fn remove_at_mut(&mut self, s: Square) {
        self.data.remove_at_mut(s);
    }
    pub fn king_square(&self, c: Color) -> Square {
        self.data.king_square(c)
    }
    pub fn piece_iter(&self) -> board::Iter {
        self.data.iter()
    }

    pub fn side_to_move(&self) -> Color {
        self.side_to_move
    }
    pub fn set_side_to_move_mut(&mut self, c: Color) {
        self.side_to_move = c;
    }
    pub fn swap_side_to_move_mut(&mut self) {
        let c = self.side_to_move.invert();
        self.set_side_to_move_mut(c);
    }
    pub fn can_castle(&self, side: Side, c: Color) -> bool {
        self.castling.get(side, c)
    }
    // Does not check for castling out of check, through check, or into check.
    pub fn can_castle_now(&self, side: Side, c: Color) -> bool {
        self.can_castle(side, c) &&
            castle::require_empty_squares(side, c).iter().all( |x| self.is_empty_at(*x) )
    }
    pub fn set_castle_mut(&mut self, side:Side, c:Color, val: bool) {
        self.castling.set_mut(side, c, val);
    }
    pub fn en_passant(&self) -> Option<File> {
        self.en_passant
    }
    pub fn has_en_passant(&self) -> bool {
        self.en_passant.is_some()
    }
    pub fn set_en_passant_mut(&mut self, val: Option<File>) {
        self.en_passant = val;
    }
    pub fn ply_count(&self) -> Plies {
        self.ply_count
    }
    pub fn set_ply_count_mut(&mut self, val: Plies) {
        self.ply_count = val;
    }
}
<|endoftext|>


<commit_before>use std::io::prelude::*;
use std::fs::File;
use std::cell::RefCell;
use std::collections::{HashSet, HashMap};

use syntax::ast::*;
use syntax::print;
use syntax::ptr::P;
use syntax::ext;
use syntax::ext::base::ExtCtxt;
use syntax::ext::build::AstBuilder;
use syntax::parse::token::{str_to_ident, Token, IdentStyle};
use syntax::codemap::{ExpnId, ExpnInfo, CompilerExpansion, NameAndSpan, DUMMY_SP};

use rustc::session::{build_session,Session};
use rustc::session::config::{build_session_options,build_configuration, Input};
use rustc_driver::{handle_options,diagnostics_registry};
use rustc_driver::driver::{phase_1_parse_input, source_name};

use super::state::State;

const CRATE_SRC : &'static str =  "//Generated by hsm-gen, modifications will be lost when regenerating
                                   use hsm;
                                   use super::shared_data::SharedData;
                                   use super::hsm_functions;";

pub struct HsmGenerator {
    sess        : Session,
    cfg         : CrateConfig,
    src_name    : String,
    krate       : RefCell<Crate>
}
impl HsmGenerator {
    pub fn new(prefix: bool) -> Self {
        let matches = match handle_options(vec!["".to_string(), "-".to_string()]) {
            Some(matches) => matches,
            None => unreachable!()
        };
        let descriptions = diagnostics_registry();
        let sopts = build_session_options(&matches);
        let sess = build_session(sopts, None, descriptions);
        let cfg = build_configuration(&sess);
        let input = Input::Str( if prefix {CRATE_SRC.to_string()} else {"".to_string()});
        let src_name = source_name(&input);
        let krate = RefCell::new(phase_1_parse_input(&sess, cfg.clone(), &input));

        HsmGenerator {
            sess    : sess,
            cfg     : cfg,
            src_name: src_name,
            krate   : krate
        }
    }

    fn ecfg(&self) -> ext::expand::ExpansionConfig {
        ext::expand::ExpansionConfig {
            crate_name      : self.src_name.clone(),
            features        : None, //Some(&self.sess.features.borrow()),
            recursion_limit : self.sess.recursion_limit.get(),
            trace_mac       : self.sess.opts.debugging_opts.trace_macros,
        }
    }
    fn extctxt(&self) -> ExtCtxt {
        let mut cx = ExtCtxt::new(&self.sess.parse_sess, self.cfg.clone(), self.ecfg());
        cx.backtrace = ExpnId::from_u32(0);
        cx.codemap().record_expansion(
            ExpnInfo {
                call_site: self.krate.borrow().span,
                callee: NameAndSpan {
                    name: "mattis".to_string(),
                    format: CompilerExpansion,
                    allow_internal_unstable: true,
                    span: None,
                },
            }
        );
        cx
    }

    pub fn print(&self, file: &str) {
        let src_nam = self.src_name.clone();
        let src = self.sess.codemap().get_filemap(&src_nam[..])
                            .src
                            .as_ref()
                            .unwrap()
                            .as_bytes()
                            .to_vec();
        let mut rdr = &src[..];
        let mut out = Vec::new();
        let ann = print::pprust::NoAnn;
        {
            let out_w: &mut Write = &mut out;
            print::pprust::print_crate( self.sess.codemap(),
                                        self.sess.diagnostic(),
                                        &self.krate.borrow(),
                                        src_nam,
                                        &mut rdr,
                                        box out_w,
                                        &ann,
                                        false).expect("Could not format crate");
        }
        // print!("{}", String::from_utf8(out).unwrap());
        let mut f = File::create(file).expect("Could not create file");
        f.write(&out).expect("Could not write to file");
    }

    pub fn create_event_enum(&self, hs: &HashSet<String>) {
        let cx = self.extctxt();
        let mut variants: Vec<P<Variant>> = Vec::new();
        for var_name in hs {
            let mut variant = cx.variant(
                DUMMY_SP,
                str_to_ident(var_name),
                Vec::new()
            );
            variant.node.vis = Visibility::Inherited;
            variants.push(P(variant));
        }
        let en = cx.item_enum(
            DUMMY_SP,
            str_to_ident("Events"),
            EnumDef{ variants: variants }
        ).map(|mut x| {
            x.vis = Visibility::Public;
            x.attrs.push(quote_attr!(&cx, #[derive(Debug, Clone)]));
            x
        });
        self.krate.borrow_mut().module.items.push(en);
    }

    pub fn create_hsm_objects(&self, states: &HashSet<String>) {
        let cx = self.extctxt();
        let events = str_to_ident("Events");
        let st_str = str_to_ident("StateStruct");
        let st     = str_to_ident("States");
        let shr_dat= str_to_ident("SharedData");
        let states: Vec<TokenTree> = states
            .iter()
            .map(|st_nam| vec![Token::Ident(str_to_ident(st_nam), IdentStyle::Plain)])
            .collect::<Vec<_>>()
            .join(&Token::Comma)
            .into_iter()
            .map(|t| TtToken(DUMMY_SP, t))
            .collect();

        let x = quote_item!(&cx,
            hsm_define_objects!($st_str, $st, $events, $shr_dat, (
                $states
            ));
        ).unwrap();
        self.krate.borrow_mut().module.items.push(x);
    }

    pub fn create_state_parent_impls(&self, hm: &HashMap<String, State>) {
        let cx = self.extctxt();
        let st = str_to_ident("States");
        let par_lst: Vec<TokenTree> = hm.values()
            .map(|state| vec![
                Token::Ident(str_to_ident(state.name.as_ref().unwrap()), IdentStyle::Plain),
                Token::RArrow,
                Token::Ident(str_to_ident(if let Some(ref x) = state.parent {x} else {"None"} ), IdentStyle::Plain)
            ])
            .collect::<Vec<_>>()
            .join(&Token::Comma)
            .into_iter()
            .map(|t| TtToken(DUMMY_SP, t))
            .collect();
        let x = quote_item!(&cx,
            hsm_state_parents!($st; $par_lst);
        ).unwrap();
        self.krate.borrow_mut().module.items.push(x);
    }

    pub fn create_state_impls(&self, hm: &HashMap<String, State>) {
        let events = str_to_ident("Events");
        let states = str_to_ident("States");
        let shr_dat= str_to_ident("SharedData");
        for state in hm.values() {
            self.create_state_impl(state, &events, &states, &shr_dat);
        }
    }

    fn create_enter_exit_arm(&self, cx: &ExtCtxt, opt_func: &Option<String>, evt_type: &str) -> Option<Arm> {
        if let &Some(ref func_nam) = opt_func {
            let func_ident = str_to_ident(func_nam);
            let evt_ident = str_to_ident(evt_type);
            Some(cx.arm(DUMMY_SP,
                   vec!(quote_pat!(&cx, hsm::Event::$evt_ident)),
                   quote_expr!(&cx, {
                        hsm_functions::$func_ident(shr_data, evt);
                        hsm::Action::Ignore
                   })
            ))
        } else { None }
    }

    fn create_state_impl(&self, state: &State, events: &Ident, states: &Ident, shr_dat: &Ident) {
        let cx = self.extctxt();
        let state_ident = str_to_ident(state.name.as_ref().unwrap());
        let mut arms: Vec<Arm> = Vec::new();
        self.create_enter_exit_arm(&cx, &state.entry, "Enter").map(|x| arms.push(x));
        self.create_enter_exit_arm(&cx, &state.exit, "Exit").map(|x| arms.push(x));
        for (trigger, target) in state.transitions.iter() {
            let target_ident = str_to_ident(target);
            let trigger_ident = str_to_ident(trigger);
            let pat = if trigger == "_" {
                quote_pat!(&cx, $trigger_ident)
            } else {
                quote_pat!(&cx, hsm::Event::User($events::$trigger_ident))
            };
            let trans = quote_expr!(&cx, $states::$target_ident);
            arms.push(cx.arm(DUMMY_SP,
                             vec!(pat),
                             quote_expr!(&cx, hsm_delayed_transition!(probe, { $trans }))
            ));
        };
        if !state.transitions.contains_key("_") {
            arms.push(cx.arm(DUMMY_SP,
                             vec!(quote_pat!(&cx, _)),
                             quote_expr!(&cx, hsm::Action::Parent)
            ));
        };
        let match_expr = cx.expr_match(DUMMY_SP, quote_expr!(&cx, evt), arms);
        let x = quote_item!(&cx,
            impl hsm::State<$events, $states, $shr_dat> for $state_ident<$events, $states, $shr_dat> {
                fn handle_event(&mut self, shr_data: &mut $shr_dat, evt: hsm::Event<$events>, probe: bool) -> hsm::Action<$states> {
                    $match_expr
                }
            }
        ).unwrap();
        self.krate.borrow_mut().module.items.push(x);
    }

    pub fn create_function_stubs(&self, hm: &HashMap<String, State>) {
        let cx = self.extctxt();
        let events = str_to_ident("Events");
        let shr_dat= str_to_ident("SharedData");
        let mut functions = HashSet::new();
        hm.values().map(|s| {
            s.entry.as_ref().map(|x|
                functions.insert(x.to_string())
            );
            s.exit.as_ref().map(|x|
                functions.insert(x.to_string())
            )
        }).count();
        for func in functions {
            let func_ident  = str_to_ident(&func);
            let it = quote_item!(&cx,
                fn $func_ident(shr_data: &mut $shr_dat, evt: hsm::Event<$events>) {
                    unimplemented!();
                }
            ).unwrap().map(|mut x| {
                x.vis = Visibility::Public;
                x
            });
            self.krate.borrow_mut().module.items.push(it);
            // println!("{}", func);
        }
    }
}
<commit_msg>states are no longer generic<commit_after>use std::io::prelude::*;
use std::fs::File;
use std::cell::RefCell;
use std::collections::{HashSet, HashMap};

use syntax::ast::*;
use syntax::print;
use syntax::ptr::P;
use syntax::ext;
use syntax::ext::base::ExtCtxt;
use syntax::ext::build::AstBuilder;
use syntax::parse::token::{str_to_ident, Token, IdentStyle};
use syntax::codemap::{ExpnId, ExpnInfo, CompilerExpansion, NameAndSpan, DUMMY_SP};

use rustc::session::{build_session,Session};
use rustc::session::config::{build_session_options,build_configuration, Input};
use rustc_driver::{handle_options,diagnostics_registry};
use rustc_driver::driver::{phase_1_parse_input, source_name};

use super::state::State;

const CRATE_SRC : &'static str  =  "//Generated by hsm-gen, modifications will be lost when regenerating
                                    use hsm;
                                    use super::hsm_shared_data::SharedData;
                                    use super::hsm_functions;";
const FN_CRATE_SRC: &'static str = "//Generated by hsm-gen, modifications will be lost when regenerating
                                    use hsm;
                                    use super::hsm_shared_data::SharedData;
                                    use super::hsm_generated::Events;";

pub struct HsmGenerator {
    sess        : Session,
    cfg         : CrateConfig,
    src_name    : String,
    krate       : RefCell<Crate>
}
impl HsmGenerator {
    pub fn new(prefix: bool) -> Self {
        let matches = match handle_options(vec!["".to_string(), "-".to_string()]) {
            Some(matches) => matches,
            None => unreachable!()
        };
        let descriptions = diagnostics_registry();
        let sopts = build_session_options(&matches);
        let sess = build_session(sopts, None, descriptions);
        let cfg = build_configuration(&sess);
        let input = Input::Str( if prefix {CRATE_SRC.to_string()} else {FN_CRATE_SRC.to_string()});
        let src_name = source_name(&input);
        let krate = RefCell::new(phase_1_parse_input(&sess, cfg.clone(), &input));

        HsmGenerator {
            sess    : sess,
            cfg     : cfg,
            src_name: src_name,
            krate   : krate
        }
    }

    fn ecfg(&self) -> ext::expand::ExpansionConfig {
        ext::expand::ExpansionConfig {
            crate_name      : self.src_name.clone(),
            features        : None, //Some(&self.sess.features.borrow()),
            recursion_limit : self.sess.recursion_limit.get(),
            trace_mac       : self.sess.opts.debugging_opts.trace_macros,
        }
    }
    fn extctxt(&self) -> ExtCtxt {
        let mut cx = ExtCtxt::new(&self.sess.parse_sess, self.cfg.clone(), self.ecfg());
        cx.backtrace = ExpnId::from_u32(0);
        cx.codemap().record_expansion(
            ExpnInfo {
                call_site: self.krate.borrow().span,
                callee: NameAndSpan {
                    name: "mattis".to_string(),
                    format: CompilerExpansion,
                    allow_internal_unstable: true,
                    span: None,
                },
            }
        );
        cx
    }

    pub fn print(&self, file: &str) {
        let src_nam = self.src_name.clone();
        let src = self.sess.codemap().get_filemap(&src_nam[..])
                            .src
                            .as_ref()
                            .unwrap()
                            .as_bytes()
                            .to_vec();
        let mut rdr = &src[..];
        let mut out = Vec::new();
        let ann = print::pprust::NoAnn;
        {
            let out_w: &mut Write = &mut out;
            print::pprust::print_crate( self.sess.codemap(),
                                        self.sess.diagnostic(),
                                        &self.krate.borrow(),
                                        src_nam,
                                        &mut rdr,
                                        box out_w,
                                        &ann,
                                        false).expect("Could not format crate");
        }
        // print!("{}", String::from_utf8(out).unwrap());
        let mut f = File::create(file).expect("Could not create file");
        f.write(&out).expect("Could not write to file");
    }

    pub fn create_event_enum(&self, hs: &HashSet<String>) {
        let cx = self.extctxt();
        let mut variants: Vec<P<Variant>> = Vec::new();
        for var_name in hs {
            let mut variant = cx.variant(
                DUMMY_SP,
                str_to_ident(var_name),
                Vec::new()
            );
            variant.node.vis = Visibility::Inherited;
            variants.push(P(variant));
        }
        let en = cx.item_enum(
            DUMMY_SP,
            str_to_ident("Events"),
            EnumDef{ variants: variants }
        ).map(|mut x| {
            x.vis = Visibility::Public;
            x.attrs.push(quote_attr!(&cx, #[derive(Debug, Clone)]));
            x
        });
        self.krate.borrow_mut().module.items.push(en);
    }

    pub fn create_hsm_objects(&self, states: &HashSet<String>) {
        let cx = self.extctxt();
        let events = str_to_ident("Events");
        let st_str = str_to_ident("StateStruct");
        let st     = str_to_ident("States");
        let shr_dat= str_to_ident("SharedData");
        let states: Vec<TokenTree> = states
            .iter()
            .map(|st_nam| vec![Token::Ident(str_to_ident(st_nam), IdentStyle::Plain)])
            .collect::<Vec<_>>()
            .join(&Token::Comma)
            .into_iter()
            .map(|t| TtToken(DUMMY_SP, t))
            .collect();

        let x = quote_item!(&cx,
            hsm_define_objects!($st_str, $st, $events, $shr_dat, (
                $states
            ));
        ).unwrap();
        self.krate.borrow_mut().module.items.push(x);
    }

    pub fn create_state_parent_impls(&self, hm: &HashMap<String, State>) {
        let cx = self.extctxt();
        let st = str_to_ident("States");
        let par_lst: Vec<TokenTree> = hm.values()
            .map(|state| vec![
                Token::Ident(str_to_ident(state.name.as_ref().unwrap()), IdentStyle::Plain),
                Token::RArrow,
                Token::Ident(str_to_ident(if let Some(ref x) = state.parent {x} else {"None"} ), IdentStyle::Plain)
            ])
            .collect::<Vec<_>>()
            .join(&Token::Comma)
            .into_iter()
            .map(|t| TtToken(DUMMY_SP, t))
            .collect();
        let x = quote_item!(&cx,
            hsm_state_parents!($st; $par_lst);
        ).unwrap();
        self.krate.borrow_mut().module.items.push(x);
    }

    pub fn create_state_impls(&self, hm: &HashMap<String, State>) {
        let events = str_to_ident("Events");
        let states = str_to_ident("States");
        let shr_dat= str_to_ident("SharedData");
        for state in hm.values() {
            self.create_state_impl(state, &events, &states, &shr_dat);
        }
    }

    fn create_enter_exit_arm(&self, cx: &ExtCtxt, opt_func: &Option<String>, evt_type: &str) -> Option<Arm> {
        if let &Some(ref func_nam) = opt_func {
            let func_ident = str_to_ident(func_nam);
            let evt_ident = str_to_ident(evt_type);
            Some(cx.arm(DUMMY_SP,
                   vec!(quote_pat!(&cx, hsm::Event::$evt_ident)),
                   quote_expr!(&cx, {
                        hsm_functions::$func_ident(shr_data, evt);
                        hsm::Action::Ignore
                   })
            ))
        } else { None }
    }

    fn create_state_impl(&self, state: &State, events: &Ident, states: &Ident, shr_dat: &Ident) {
        let cx = self.extctxt();
        let state_ident = str_to_ident(state.name.as_ref().unwrap());
        let mut arms: Vec<Arm> = Vec::new();
        self.create_enter_exit_arm(&cx, &state.entry, "Enter").map(|x| arms.push(x));
        self.create_enter_exit_arm(&cx, &state.exit, "Exit").map(|x| arms.push(x));
        for (trigger, target) in state.transitions.iter() {
            let target_ident = str_to_ident(target);
            let trigger_ident = str_to_ident(trigger);
            let pat = if trigger == "_" {
                quote_pat!(&cx, $trigger_ident)
            } else {
                quote_pat!(&cx, hsm::Event::User($events::$trigger_ident))
            };
            let trans = quote_expr!(&cx, $states::$target_ident);
            arms.push(cx.arm(DUMMY_SP,
                             vec!(pat),
                             quote_expr!(&cx, hsm_delayed_transition!(probe, { $trans }))
            ));
        };
        if !state.transitions.contains_key("_") {
            arms.push(cx.arm(DUMMY_SP,
                             vec!(quote_pat!(&cx, _)),
                             quote_expr!(&cx, hsm::Action::Parent)
            ));
        };
        let match_expr = cx.expr_match(DUMMY_SP, quote_expr!(&cx, evt), arms);
        let x = quote_item!(&cx,
            impl hsm::State<$events, $states, $shr_dat> for $state_ident {
                fn handle_event(&mut self, shr_data: &mut $shr_dat, evt: hsm::Event<$events>, probe: bool) -> hsm::Action<$states> {
                    $match_expr
                }
            }
        ).unwrap();
        self.krate.borrow_mut().module.items.push(x);
    }

    pub fn create_function_stubs(&self, hm: &HashMap<String, State>) {
        let cx = self.extctxt();
        let events = str_to_ident("Events");
        let shr_dat= str_to_ident("SharedData");
        let mut functions = HashSet::new();
        hm.values().map(|s| {
            s.entry.as_ref().map(|x|
                functions.insert(x.to_string())
            );
            s.exit.as_ref().map(|x|
                functions.insert(x.to_string())
            )
        }).count();
        for func in functions {
            let func_ident  = str_to_ident(&func);
            let it = quote_item!(&cx,
                fn $func_ident(shr_data: &mut $shr_dat, evt: hsm::Event<$events>) {
                    unimplemented!();
                }
            ).unwrap().map(|mut x| {
                x.vis = Visibility::Public;
                x
            });
            self.krate.borrow_mut().module.items.push(it);
            // println!("{}", func);
        }
    }
}
<|endoftext|>


<commit_before>//! main structures and traits used to build serializers
use crate::lib::std::{fmt, io::{self, Seek as _, SeekFrom, Write}};

/// Holds the result of serializing functions
///
/// The `Ok` case returns the `Write` used for writing, in the `Err` case an instance of
/// `cookie_factory::GenError` is returned.
pub type GenResult<W> = Result<WriteContext<W>, GenError>;

/// Base type for generator errors
#[derive(Debug)]
pub enum GenError {
    /// Input buffer is too small. Argument is the maximum index that is required
    BufferTooSmall(usize),
    /// We expected to fill the whole buffer but there is some space left
    BufferTooBig(usize),
    /// Operation asked for accessing an invalid index
    InvalidOffset,
    /// IoError returned by Write
    IoError(io::Error),

    /// Allocated for custom errors
    CustomError(u32),
    /// Generator or function not yet implemented
    NotYetImplemented,
}

impl fmt::Display for GenError {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        write!(f, "{:?}", self)
    }
}

#[cfg(feature = "std")]
impl std::error::Error for GenError {}

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

/// Trait for serializing functions
///
/// Serializing functions take one input `W` that is the target of writing and return an instance
/// of `cookie_factory::GenResult`.
///
/// This trait is implemented for all `Fn(W) -> GenResult<W>`.
pub trait SerializeFn<W>: Fn(WriteContext<W>) -> GenResult<W> {}

impl<W, F: Fn(WriteContext<W>) -> GenResult<W>> SerializeFn<W> for F {}

/// Context around a `Write` impl that is passed through serializing functions
///
/// Currently this only keeps track of the current write position since the start of serialization.
pub struct WriteContext<W> {
    pub write: W,
    pub position: u64,
}

impl<W: Write> From<W> for WriteContext<W> {
    fn from(write: W) -> Self {
        Self { write, position: 0 }
    }
}

impl<W: Write> WriteContext<W> {
    /// Returns the contained `Write` and the current position
    pub fn into_inner(self) -> (W, u64) {
        (self.write, self.position)
    }
}

impl<W: Write> Write for WriteContext<W> {
    fn write(&mut self, data: &[u8]) -> crate::lib::std::io::Result<usize> {
        let amt = self.write.write(data)?;
        self.position += amt as u64;
        Ok(amt)
    }

    #[cfg(feature = "std")]
    fn flush(&mut self) -> io::Result<()> {
        self.write.flush()
    }
}

impl<W: Seek> io::Seek for WriteContext<W> {
    fn seek(&mut self, pos: SeekFrom) -> io::Result<u64> {
        let old_pos = self.write.seek(SeekFrom::Current(0))?;
        let new_pos = self.write.seek(pos)?;
        if new_pos >= old_pos {
            self.position += new_pos - old_pos;
        } else {
            self.position -= old_pos - new_pos;
        }
        Ok(new_pos)
    }
}

/// Runs the given serializer `f` with the `Write` impl `w` and returns the result
///
/// This internally wraps `w` in a `WriteContext`, starting at position 0.
///
/// ```rust
/// use cookie_factory::{gen, combinator::slice};
///
/// let mut buf = [0u8; 100];
///
/// {
///   let (buf, pos) = gen(slice(&b"abcd"[..]), &mut buf[..]).unwrap();
///   assert_eq!(buf.len(), 100 - 4);
///   assert_eq!(pos, 4);
/// }
///
/// assert_eq!(&buf[..4], &b"abcd"[..]);
/// ```
pub fn gen<W: Write, F: SerializeFn<W>>(f: F, w: W) -> Result<(W, u64), GenError> {
    f(WriteContext::from(w)).map(|ctx| ctx.into_inner())
}

/// Runs the given serializer `f` with the `Write` impl `w` and returns the updated `w`
///
/// This internally wraps `w` in a `WriteContext`, starting at position 0.
///
/// ```rust
/// use cookie_factory::{gen_simple, combinator::slice};
///
/// let mut buf = [0u8; 100];
///
/// {
///   let buf = gen_simple(slice(&b"abcd"[..]), &mut buf[..]).unwrap();
///   assert_eq!(buf.len(), 100 - 4);
/// }
///
/// assert_eq!(&buf[..4], &b"abcd"[..]);
/// ```
pub fn gen_simple<W: Write, F: SerializeFn<W>>(f: F, w: W) -> Result<W, GenError> {
    f(WriteContext::from(w)).map(|ctx| ctx.into_inner().0)
}

/// Trait for `Write` types that allow skipping over the data
pub trait Skip: Write {
    fn skip(s: WriteContext<Self>, s: usize) -> GenResult<Self>
    where
        Self: Sized;
}

/// Trait for `Write` types that allow skipping and reserving a slice, then writing some data,
/// then write something in the slice we reserved using the return for our data write.
pub trait BackToTheBuffer: Write {
    fn reserve_write_use<
        Tmp,
        Gen: Fn(WriteContext<Self>) -> Result<(WriteContext<Self>, Tmp), GenError>,
        Before: Fn(WriteContext<Self>, Tmp) -> GenResult<Self>,
    >(
        s: WriteContext<Self>,
        reserved: usize,
        gen: &Gen,
        before: &Before,
    ) -> Result<WriteContext<Self>, GenError>
    where
        Self: Sized;
}

/// Trait for `Seek` types that want to automatically implement `BackToTheBuffer`
pub trait Seek: Write + io::Seek {}
impl Seek for io::Cursor<&mut [u8]> {}

impl<W: Seek> BackToTheBuffer for W {
    fn reserve_write_use<
        Tmp,
        Gen: Fn(WriteContext<Self>) -> Result<(WriteContext<Self>, Tmp), GenError>,
        Before: Fn(WriteContext<Self>, Tmp) -> GenResult<Self>,
    >(
        mut s: WriteContext<Self>,
        reserved: usize,
        gen: &Gen,
        before: &Before,
    ) -> Result<WriteContext<Self>, GenError> {
        let start = s.seek(SeekFrom::Current(0))?;
        let begin = s.seek(SeekFrom::Current(reserved as i64))?;
        let (mut buf, tmp) = gen(s)?;
        let end = buf.seek(SeekFrom::Current(0))?;
        buf.seek(SeekFrom::Start(start))?;
        let mut buf = before(buf, tmp)?;
        let pos = buf.seek(SeekFrom::Current(0))?;
        if pos != begin {
            return Err(GenError::BufferTooBig((begin - pos) as usize));
        }
        buf.seek(SeekFrom::Start(end))?;
        Ok(buf)
    }
}

impl Skip for &mut [u8] {
    fn skip(s: WriteContext<Self>, len: usize) -> Result<WriteContext<Self>, GenError> {
        if s.write.len() < len {
            Err(GenError::BufferTooSmall(len - s.write.len()))
        } else {
            Ok(WriteContext {
                write: &mut s.write[len..],
                position: s.position + len as u64,
            })
        }
    }
}

impl Skip for io::Cursor<&mut [u8]> {
    fn skip(mut s: WriteContext<Self>, len: usize) -> GenResult<Self> {
        let remaining = s
            .write
            .get_ref()
            .len()
            .saturating_sub(s.write.position() as usize);
        if remaining < len {
            Err(GenError::BufferTooSmall(len - remaining))
        } else {
            let cursor_position = s.write.position();
            s.write.set_position(cursor_position + len as u64);
            s.position += len as u64;
            Ok(s)
        }
    }
}

impl BackToTheBuffer for &mut [u8] {
    fn reserve_write_use<
        Tmp,
        Gen: Fn(WriteContext<Self>) -> Result<(WriteContext<Self>, Tmp), GenError>,
        Before: Fn(WriteContext<Self>, Tmp) -> GenResult<Self>,
    >(
        s: WriteContext<Self>,
        reserved: usize,
        gen: &Gen,
        before: &Before,
    ) -> Result<WriteContext<Self>, GenError> {
        let WriteContext {
            write: slice,
            position: original_position,
        } = s;

        let (res, buf) = slice.split_at_mut(reserved);
        let (new_context, tmp) = gen(WriteContext {
            write: buf,
            position: original_position + reserved as u64,
        })?;

        let res = before(
            WriteContext {
                write: res,
                position: original_position,
            },
            tmp,
        )?;

        if !res.write.is_empty() {
            return Err(GenError::BufferTooBig(res.write.len()));
        }

        Ok(new_context)
    }
}

#[cfg(feature = "std")]
impl BackToTheBuffer for Vec<u8> {
    fn reserve_write_use<
        Tmp,
        Gen: Fn(WriteContext<Self>) -> Result<(WriteContext<Self>, Tmp), GenError>,
        Before: Fn(WriteContext<Self>, Tmp) -> GenResult<Self>,
    >(
        s: WriteContext<Self>,
        reserved: usize,
        gen: &Gen,
        before: &Before,
    ) -> Result<WriteContext<Self>, GenError> {
        let WriteContext {
            write: mut vec,
            position: original_position,
        } = s;

        let start_len = vec.len();
        vec.extend(std::iter::repeat(0).take(reserved));

        let (mut new_context, tmp) = gen(WriteContext {
            write: vec,
            position: original_position + reserved as u64,
        })?;

        let tmp_context = before(
            WriteContext {
                write: Vec::new(),
                position: original_position,
            },
            tmp,
        )?;

        let tmp_written = tmp_context.write.len();
        if tmp_written != reserved {
            return Err(GenError::BufferTooBig(reserved - tmp_written));
        }

        // FIXME?: find a way to do that without copying
        // Vec::from_raw_parts + core::mem::forget makes it work, but
        // if `before` writes more than `reserved`, realloc will cause troubles
        new_context.write[start_len..(start_len + reserved)]
            .copy_from_slice(&tmp_context.write[..]);

        Ok(new_context)
    }
}
<commit_msg>Fix tests with nightly (s used as parameter more than once)<commit_after>//! main structures and traits used to build serializers
use crate::lib::std::{fmt, io::{self, Seek as _, SeekFrom, Write}};

/// Holds the result of serializing functions
///
/// The `Ok` case returns the `Write` used for writing, in the `Err` case an instance of
/// `cookie_factory::GenError` is returned.
pub type GenResult<W> = Result<WriteContext<W>, GenError>;

/// Base type for generator errors
#[derive(Debug)]
pub enum GenError {
    /// Input buffer is too small. Argument is the maximum index that is required
    BufferTooSmall(usize),
    /// We expected to fill the whole buffer but there is some space left
    BufferTooBig(usize),
    /// Operation asked for accessing an invalid index
    InvalidOffset,
    /// IoError returned by Write
    IoError(io::Error),

    /// Allocated for custom errors
    CustomError(u32),
    /// Generator or function not yet implemented
    NotYetImplemented,
}

impl fmt::Display for GenError {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        write!(f, "{:?}", self)
    }
}

#[cfg(feature = "std")]
impl std::error::Error for GenError {}

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

/// Trait for serializing functions
///
/// Serializing functions take one input `W` that is the target of writing and return an instance
/// of `cookie_factory::GenResult`.
///
/// This trait is implemented for all `Fn(W) -> GenResult<W>`.
pub trait SerializeFn<W>: Fn(WriteContext<W>) -> GenResult<W> {}

impl<W, F: Fn(WriteContext<W>) -> GenResult<W>> SerializeFn<W> for F {}

/// Context around a `Write` impl that is passed through serializing functions
///
/// Currently this only keeps track of the current write position since the start of serialization.
pub struct WriteContext<W> {
    pub write: W,
    pub position: u64,
}

impl<W: Write> From<W> for WriteContext<W> {
    fn from(write: W) -> Self {
        Self { write, position: 0 }
    }
}

impl<W: Write> WriteContext<W> {
    /// Returns the contained `Write` and the current position
    pub fn into_inner(self) -> (W, u64) {
        (self.write, self.position)
    }
}

impl<W: Write> Write for WriteContext<W> {
    fn write(&mut self, data: &[u8]) -> crate::lib::std::io::Result<usize> {
        let amt = self.write.write(data)?;
        self.position += amt as u64;
        Ok(amt)
    }

    #[cfg(feature = "std")]
    fn flush(&mut self) -> io::Result<()> {
        self.write.flush()
    }
}

impl<W: Seek> io::Seek for WriteContext<W> {
    fn seek(&mut self, pos: SeekFrom) -> io::Result<u64> {
        let old_pos = self.write.seek(SeekFrom::Current(0))?;
        let new_pos = self.write.seek(pos)?;
        if new_pos >= old_pos {
            self.position += new_pos - old_pos;
        } else {
            self.position -= old_pos - new_pos;
        }
        Ok(new_pos)
    }
}

/// Runs the given serializer `f` with the `Write` impl `w` and returns the result
///
/// This internally wraps `w` in a `WriteContext`, starting at position 0.
///
/// ```rust
/// use cookie_factory::{gen, combinator::slice};
///
/// let mut buf = [0u8; 100];
///
/// {
///   let (buf, pos) = gen(slice(&b"abcd"[..]), &mut buf[..]).unwrap();
///   assert_eq!(buf.len(), 100 - 4);
///   assert_eq!(pos, 4);
/// }
///
/// assert_eq!(&buf[..4], &b"abcd"[..]);
/// ```
pub fn gen<W: Write, F: SerializeFn<W>>(f: F, w: W) -> Result<(W, u64), GenError> {
    f(WriteContext::from(w)).map(|ctx| ctx.into_inner())
}

/// Runs the given serializer `f` with the `Write` impl `w` and returns the updated `w`
///
/// This internally wraps `w` in a `WriteContext`, starting at position 0.
///
/// ```rust
/// use cookie_factory::{gen_simple, combinator::slice};
///
/// let mut buf = [0u8; 100];
///
/// {
///   let buf = gen_simple(slice(&b"abcd"[..]), &mut buf[..]).unwrap();
///   assert_eq!(buf.len(), 100 - 4);
/// }
///
/// assert_eq!(&buf[..4], &b"abcd"[..]);
/// ```
pub fn gen_simple<W: Write, F: SerializeFn<W>>(f: F, w: W) -> Result<W, GenError> {
    f(WriteContext::from(w)).map(|ctx| ctx.into_inner().0)
}

/// Trait for `Write` types that allow skipping over the data
pub trait Skip: Write {
    fn skip(s: WriteContext<Self>, sz: usize) -> GenResult<Self>
    where
        Self: Sized;
}

/// Trait for `Write` types that allow skipping and reserving a slice, then writing some data,
/// then write something in the slice we reserved using the return for our data write.
pub trait BackToTheBuffer: Write {
    fn reserve_write_use<
        Tmp,
        Gen: Fn(WriteContext<Self>) -> Result<(WriteContext<Self>, Tmp), GenError>,
        Before: Fn(WriteContext<Self>, Tmp) -> GenResult<Self>,
    >(
        s: WriteContext<Self>,
        reserved: usize,
        gen: &Gen,
        before: &Before,
    ) -> Result<WriteContext<Self>, GenError>
    where
        Self: Sized;
}

/// Trait for `Seek` types that want to automatically implement `BackToTheBuffer`
pub trait Seek: Write + io::Seek {}
impl Seek for io::Cursor<&mut [u8]> {}

impl<W: Seek> BackToTheBuffer for W {
    fn reserve_write_use<
        Tmp,
        Gen: Fn(WriteContext<Self>) -> Result<(WriteContext<Self>, Tmp), GenError>,
        Before: Fn(WriteContext<Self>, Tmp) -> GenResult<Self>,
    >(
        mut s: WriteContext<Self>,
        reserved: usize,
        gen: &Gen,
        before: &Before,
    ) -> Result<WriteContext<Self>, GenError> {
        let start = s.seek(SeekFrom::Current(0))?;
        let begin = s.seek(SeekFrom::Current(reserved as i64))?;
        let (mut buf, tmp) = gen(s)?;
        let end = buf.seek(SeekFrom::Current(0))?;
        buf.seek(SeekFrom::Start(start))?;
        let mut buf = before(buf, tmp)?;
        let pos = buf.seek(SeekFrom::Current(0))?;
        if pos != begin {
            return Err(GenError::BufferTooBig((begin - pos) as usize));
        }
        buf.seek(SeekFrom::Start(end))?;
        Ok(buf)
    }
}

impl Skip for &mut [u8] {
    fn skip(s: WriteContext<Self>, len: usize) -> Result<WriteContext<Self>, GenError> {
        if s.write.len() < len {
            Err(GenError::BufferTooSmall(len - s.write.len()))
        } else {
            Ok(WriteContext {
                write: &mut s.write[len..],
                position: s.position + len as u64,
            })
        }
    }
}

impl Skip for io::Cursor<&mut [u8]> {
    fn skip(mut s: WriteContext<Self>, len: usize) -> GenResult<Self> {
        let remaining = s
            .write
            .get_ref()
            .len()
            .saturating_sub(s.write.position() as usize);
        if remaining < len {
            Err(GenError::BufferTooSmall(len - remaining))
        } else {
            let cursor_position = s.write.position();
            s.write.set_position(cursor_position + len as u64);
            s.position += len as u64;
            Ok(s)
        }
    }
}

impl BackToTheBuffer for &mut [u8] {
    fn reserve_write_use<
        Tmp,
        Gen: Fn(WriteContext<Self>) -> Result<(WriteContext<Self>, Tmp), GenError>,
        Before: Fn(WriteContext<Self>, Tmp) -> GenResult<Self>,
    >(
        s: WriteContext<Self>,
        reserved: usize,
        gen: &Gen,
        before: &Before,
    ) -> Result<WriteContext<Self>, GenError> {
        let WriteContext {
            write: slice,
            position: original_position,
        } = s;

        let (res, buf) = slice.split_at_mut(reserved);
        let (new_context, tmp) = gen(WriteContext {
            write: buf,
            position: original_position + reserved as u64,
        })?;

        let res = before(
            WriteContext {
                write: res,
                position: original_position,
            },
            tmp,
        )?;

        if !res.write.is_empty() {
            return Err(GenError::BufferTooBig(res.write.len()));
        }

        Ok(new_context)
    }
}

#[cfg(feature = "std")]
impl BackToTheBuffer for Vec<u8> {
    fn reserve_write_use<
        Tmp,
        Gen: Fn(WriteContext<Self>) -> Result<(WriteContext<Self>, Tmp), GenError>,
        Before: Fn(WriteContext<Self>, Tmp) -> GenResult<Self>,
    >(
        s: WriteContext<Self>,
        reserved: usize,
        gen: &Gen,
        before: &Before,
    ) -> Result<WriteContext<Self>, GenError> {
        let WriteContext {
            write: mut vec,
            position: original_position,
        } = s;

        let start_len = vec.len();
        vec.extend(std::iter::repeat(0).take(reserved));

        let (mut new_context, tmp) = gen(WriteContext {
            write: vec,
            position: original_position + reserved as u64,
        })?;

        let tmp_context = before(
            WriteContext {
                write: Vec::new(),
                position: original_position,
            },
            tmp,
        )?;

        let tmp_written = tmp_context.write.len();
        if tmp_written != reserved {
            return Err(GenError::BufferTooBig(reserved - tmp_written));
        }

        // FIXME?: find a way to do that without copying
        // Vec::from_raw_parts + core::mem::forget makes it work, but
        // if `before` writes more than `reserved`, realloc will cause troubles
        new_context.write[start_len..(start_len + reserved)]
            .copy_from_slice(&tmp_context.write[..]);

        Ok(new_context)
    }
}
<|endoftext|>


<commit_before>//! Basic types to build the parsers

use self::IResult::*;
use util::ErrorKind;

#[cfg(feature = "core")]
use std::prelude::v1::*;
use std::boxed::Box;

/// Contains the error that a parser can return
///
/// It can represent a linked list of errors, indicating the path taken in the parsing tree, with corresponding position in the input data.
/// It depends on P, the input position (for a &[u8] parser, it would be a &[u8]), and E, the custom error type (by default, u32)
#[derive(Debug,PartialEq,Eq,Clone)]
pub enum Err<P,E=u32>{
  /// An error code, represented by an ErrorKind, which can contain a custom error code represented by E
  Code(ErrorKind<E>),
  /// An error code, and the next error
  Node(ErrorKind<E>, Box<Err<P,E>>),
  /// An error code, and the input position
  Position(ErrorKind<E>, P),
  /// An error code, the input position and the next error
  NodePosition(ErrorKind<E>, P, Box<Err<P,E>>)
}

/// Contains information on needed data if a parser returned `Incomplete`
#[derive(Debug,PartialEq,Eq,Clone,Copy)]
pub enum Needed {
  /// needs more data, but we do not know how much
  Unknown,
  /// contains the required data size
  Size(usize)
}

/// Holds the result of parsing functions
///
/// It depends on I, the input type, O, the output type, and E, the error type (by default u32)
///
#[derive(Debug,PartialEq,Eq,Clone)]
pub enum IResult<I,O,E=u32> {
   /// indicates a correct parsing, the first field containing the rest of the unparsed data, the second field contains the parsed data
  Done(I,O),
  /// contains a Err, an enum that can indicate an error code, a position in the input, and a pointer to another error, making a list of errors in the parsing tree
  Error(Err<I,E>),
  /// Incomplete contains a Needed, an enum than can represent a known quantity of input data, or unknown
  Incomplete(Needed)
}

impl<I,O,E> IResult<I,O,E> {
  pub fn is_done(&self) -> bool {
    match *self {
      Done(_,_) => true,
      _         => false
    }
  }

  pub fn is_err(&self) -> bool {
    match *self {
      Error(_) => true,
      _        => false
    }
  }

  pub fn is_incomplete(&self) -> bool {
    match *self {
      Incomplete(_) => true,
      _             => false
    }
  }

  /// Maps a `IResult<I, O, E>` to `IResult<I, N, E>` by appling a function
  /// to a contained `Done` value, leaving `Error` and `Incomplete` value
  /// untouched.
  #[inline]
  pub fn map<N, F: FnOnce(O) -> N>(self, f: F) -> IResult<I, N, E> {
    match self {
      Done(i, o)    => Done(i, f(o)),
      Error(e)      => Error(e),
      Incomplete(n) => Incomplete(n),
    }
  }

  #[inline]
  pub fn map_err<N, F>(self, f: F) -> IResult<I, O, N>
   where F: FnOnce(Err<I, E>) -> Err<I, N> {
    match self {
      Error(e)      => Error(f(e)),
      Incomplete(n) => Incomplete(n),
      Done(i, o)    => Done(i, o),
    }
  }
}

pub trait GetInput<I> {
  fn remaining_input(&self) -> Option<I>;
}

pub trait GetOutput<O> {
  fn output(&self) -> Option<O>;
}

impl<'a,I,O,E> GetInput<&'a[I]> for IResult<&'a[I],O,E> {
  fn remaining_input(&self) -> Option<&'a[I]> {
    match *self {
      Done(ref i,_) => Some(*i),
      _             => None
    }
  }
}

impl<O,E> GetInput<()> for IResult<(),O,E> {
  fn remaining_input(&self) -> Option<()> {
    match *self {
      Done((),_) => Some(()),
      _          => None
    }
  }
}

impl<'a,O,E> GetInput<&'a str> for IResult<&'a str,O,E> {
  fn remaining_input(&self) -> Option<&'a str> {
    match *self {
      Done(ref i,_) => Some(*i),
      _          => None
    }
  }
}

impl<'a,I,O,E> GetOutput<&'a[O]> for IResult<I,&'a[O],E> {
  fn output(&self) -> Option<&'a[O]> {
    match *self {
      Done(_, ref o) => Some(*o),
      _              => None
    }
  }
}

impl<I,E> GetOutput<()> for IResult<I,(),E> {
  fn output(&self) -> Option<()> {
    match *self {
      Done(_,()) => Some(()),
      _          => None
    }
  }
}

impl<'a,I,E> GetOutput<&'a str> for IResult<I,&'a str,E> {
  fn output(&self) -> Option<&'a str> {
    match *self {
      Done(_,ref o) => Some(*o),
      _          => None
    }
  }
}

#[cfg(test)]
mod tests {
  use super::*;
  use util::ErrorKind;

  #[test]
  fn iresult_map() {
    let done: IResult<&[u8], u32> = IResult::Done(&b""[..], 5);
    let error: IResult<&[u8], u32> = IResult::Error(Err::Code(ErrorKind::Tag));
    let incomplete: IResult<&[u8], u32> = IResult::Incomplete(Needed::Unknown);

    assert_eq!(done.map(|x| x * 2), IResult::Done(&b""[..], 10));
    assert_eq!(error.map(|x| x * 2), IResult::Error(Err::Code(ErrorKind::Tag)));
    assert_eq!(incomplete.map(|x| x * 2), IResult::Incomplete(Needed::Unknown));
  }

  #[test]
  fn iresult_map_err() {
    #[derive(Clone, Copy, Debug, PartialEq, Eq)]
    struct Error(u32);

    let error_kind = Err::Code(ErrorKind::Custom(Error(5)));

    let done: IResult<&[u8], u32> = IResult::Done(&b""[..], 5);
    let error: IResult<&[u8], u32> = IResult::Error(Err::Code(ErrorKind::Tag));
    let incomplete: IResult<&[u8], u32> = IResult::Incomplete(Needed::Unknown);

    assert_eq!(done.map_err(|_| error_kind.clone()), IResult::Done(&b""[..], 5));
    assert_eq!(error.map_err(|x| error_kind.clone()), IResult::Error(error_kind.clone()));
    assert_eq!(incomplete.map_err(|x| error_kind.clone()), IResult::Incomplete(Needed::Unknown));
  }
}
<commit_msg>Add documentation for `IResult::map_err`<commit_after>//! Basic types to build the parsers

use self::IResult::*;
use util::ErrorKind;

#[cfg(feature = "core")]
use std::prelude::v1::*;
use std::boxed::Box;

/// Contains the error that a parser can return
///
/// It can represent a linked list of errors, indicating the path taken in the parsing tree, with corresponding position in the input data.
/// It depends on P, the input position (for a &[u8] parser, it would be a &[u8]), and E, the custom error type (by default, u32)
#[derive(Debug,PartialEq,Eq,Clone)]
pub enum Err<P,E=u32>{
  /// An error code, represented by an ErrorKind, which can contain a custom error code represented by E
  Code(ErrorKind<E>),
  /// An error code, and the next error
  Node(ErrorKind<E>, Box<Err<P,E>>),
  /// An error code, and the input position
  Position(ErrorKind<E>, P),
  /// An error code, the input position and the next error
  NodePosition(ErrorKind<E>, P, Box<Err<P,E>>)
}

/// Contains information on needed data if a parser returned `Incomplete`
#[derive(Debug,PartialEq,Eq,Clone,Copy)]
pub enum Needed {
  /// needs more data, but we do not know how much
  Unknown,
  /// contains the required data size
  Size(usize)
}

/// Holds the result of parsing functions
///
/// It depends on I, the input type, O, the output type, and E, the error type (by default u32)
///
#[derive(Debug,PartialEq,Eq,Clone)]
pub enum IResult<I,O,E=u32> {
   /// indicates a correct parsing, the first field containing the rest of the unparsed data, the second field contains the parsed data
  Done(I,O),
  /// contains a Err, an enum that can indicate an error code, a position in the input, and a pointer to another error, making a list of errors in the parsing tree
  Error(Err<I,E>),
  /// Incomplete contains a Needed, an enum than can represent a known quantity of input data, or unknown
  Incomplete(Needed)
}

impl<I,O,E> IResult<I,O,E> {
  pub fn is_done(&self) -> bool {
    match *self {
      Done(_,_) => true,
      _         => false
    }
  }

  pub fn is_err(&self) -> bool {
    match *self {
      Error(_) => true,
      _        => false
    }
  }

  pub fn is_incomplete(&self) -> bool {
    match *self {
      Incomplete(_) => true,
      _             => false
    }
  }

  /// Maps a `IResult<I, O, E>` to `IResult<I, N, E>` by appling a function
  /// to a contained `Done` value, leaving `Error` and `Incomplete` value
  /// untouched.
  #[inline]
  pub fn map<N, F: FnOnce(O) -> N>(self, f: F) -> IResult<I, N, E> {
    match self {
      Done(i, o)    => Done(i, f(o)),
      Error(e)      => Error(e),
      Incomplete(n) => Incomplete(n),
    }
  }

  /// Maps a `IResult<I, O, E>` to `IResult<I, O, N>` by appling a function
  /// to a contained `Error` value, leaving `Done` and `Incomplete` value
  /// untouched.
  #[inline]
  pub fn map_err<N, F>(self, f: F) -> IResult<I, O, N>
   where F: FnOnce(Err<I, E>) -> Err<I, N> {
    match self {
      Error(e)      => Error(f(e)),
      Incomplete(n) => Incomplete(n),
      Done(i, o)    => Done(i, o),
    }
  }
}

pub trait GetInput<I> {
  fn remaining_input(&self) -> Option<I>;
}

pub trait GetOutput<O> {
  fn output(&self) -> Option<O>;
}

impl<'a,I,O,E> GetInput<&'a[I]> for IResult<&'a[I],O,E> {
  fn remaining_input(&self) -> Option<&'a[I]> {
    match *self {
      Done(ref i,_) => Some(*i),
      _             => None
    }
  }
}

impl<O,E> GetInput<()> for IResult<(),O,E> {
  fn remaining_input(&self) -> Option<()> {
    match *self {
      Done((),_) => Some(()),
      _          => None
    }
  }
}

impl<'a,O,E> GetInput<&'a str> for IResult<&'a str,O,E> {
  fn remaining_input(&self) -> Option<&'a str> {
    match *self {
      Done(ref i,_) => Some(*i),
      _          => None
    }
  }
}

impl<'a,I,O,E> GetOutput<&'a[O]> for IResult<I,&'a[O],E> {
  fn output(&self) -> Option<&'a[O]> {
    match *self {
      Done(_, ref o) => Some(*o),
      _              => None
    }
  }
}

impl<I,E> GetOutput<()> for IResult<I,(),E> {
  fn output(&self) -> Option<()> {
    match *self {
      Done(_,()) => Some(()),
      _          => None
    }
  }
}

impl<'a,I,E> GetOutput<&'a str> for IResult<I,&'a str,E> {
  fn output(&self) -> Option<&'a str> {
    match *self {
      Done(_,ref o) => Some(*o),
      _          => None
    }
  }
}

#[cfg(test)]
mod tests {
  use super::*;
  use util::ErrorKind;

  #[test]
  fn iresult_map() {
    let done: IResult<&[u8], u32> = IResult::Done(&b""[..], 5);
    let error: IResult<&[u8], u32> = IResult::Error(Err::Code(ErrorKind::Tag));
    let incomplete: IResult<&[u8], u32> = IResult::Incomplete(Needed::Unknown);

    assert_eq!(done.map(|x| x * 2), IResult::Done(&b""[..], 10));
    assert_eq!(error.map(|x| x * 2), IResult::Error(Err::Code(ErrorKind::Tag)));
    assert_eq!(incomplete.map(|x| x * 2), IResult::Incomplete(Needed::Unknown));
  }

  #[test]
  fn iresult_map_err() {
    #[derive(Clone, Copy, Debug, PartialEq, Eq)]
    struct Error(u32);

    let error_kind = Err::Code(ErrorKind::Custom(Error(5)));

    let done: IResult<&[u8], u32> = IResult::Done(&b""[..], 5);
    let error: IResult<&[u8], u32> = IResult::Error(Err::Code(ErrorKind::Tag));
    let incomplete: IResult<&[u8], u32> = IResult::Incomplete(Needed::Unknown);

    assert_eq!(done.map_err(|_| error_kind.clone()), IResult::Done(&b""[..], 5));
    assert_eq!(error.map_err(|x| error_kind.clone()), IResult::Error(error_kind.clone()));
    assert_eq!(incomplete.map_err(|x| error_kind.clone()), IResult::Incomplete(Needed::Unknown));
  }
}
<|endoftext|>


<commit_before>use io::lazy::Lazy;
use io::{Read, Write, Result};

use sync::Arc;

use hal::Console;
use hal::console;

use sync::spin::{InterruptSpinLock, InterruptSpinGuard};

pub fn stdout() -> Stdout {
    static STDOUT: Lazy<InterruptSpinLock<Console<'static>>> = Lazy::new(stdout_init);

    return Stdout {
        inner: unsafe { STDOUT.get() },
    };

    fn stdout_init() -> Arc<InterruptSpinLock<Console<'static>>> {
        Arc::new(InterruptSpinLock::new(console()))
    }
}

pub struct Stdout {
    inner: Arc<InterruptSpinLock<Console<'static>>>,
}

impl Stdout {
    pub fn lock(&self) -> StdoutLock {
        StdoutLock {
            lock: self.inner.lock(),
        }
    }
}

pub struct StdoutLock<'a> {
    lock: InterruptSpinGuard<'a, Console<'static>>,
}

impl<'a> Write for StdoutLock<'a> {
    fn write(&mut self, buf: &[u8]) -> Result<usize> {
        self.lock.write(buf)
    }

    fn flush(&mut self) -> Result<()> {
        self.lock.flush()
    }
}

pub fn stdin() -> Stdin {
    static STDIN: Lazy<InterruptSpinLock<Console<'static>>> = Lazy::new(stdin_init);

    return Stdin {
        inner: unsafe { STDIN.get() },
    };

    fn stdin_init() -> Arc<InterruptSpinLock<Console<'static>>> {
        Arc::new(InterruptSpinLock::new(console()))
    }
}

pub struct Stdin {
    inner: Arc<InterruptSpinLock<Console<'static>>>,
}

impl Stdin {
    pub fn lock(&self) -> StdinLock {
        StdinLock {
            lock: self.inner.lock(),
        }
    }
}

pub struct StdinLock<'a> {
    lock: InterruptSpinGuard<'a, Console<'static>>,
}

impl<'a> Read for StdinLock<'a> {
    fn read(&mut self, buf: &mut [u8]) -> Result<usize> {
        self.lock.read(buf)
    }
}
<commit_msg>io: Fix some issues detected by clippy<commit_after>use io::lazy::Lazy;
use io::{Read, Write, Result};

use sync::Arc;

use hal::Console;
use hal::console;

use sync::spin::{InterruptSpinLock, InterruptSpinGuard};

fn stdout_init() -> Arc<InterruptSpinLock<Console<'static>>> {
    Arc::new(InterruptSpinLock::new(console()))
}

pub fn stdout() -> Stdout {
    static STDOUT: Lazy<InterruptSpinLock<Console<'static>>> = Lazy::new(stdout_init);

    Stdout {
        inner: unsafe { STDOUT.get() },
    }
}

pub struct Stdout {
    inner: Arc<InterruptSpinLock<Console<'static>>>,
}

impl Stdout {
    pub fn lock(&self) -> StdoutLock {
        StdoutLock {
            lock: self.inner.lock(),
        }
    }
}

pub struct StdoutLock<'a> {
    lock: InterruptSpinGuard<'a, Console<'static>>,
}

impl<'a> Write for StdoutLock<'a> {
    fn write(&mut self, buf: &[u8]) -> Result<usize> {
        self.lock.write(buf)
    }

    fn flush(&mut self) -> Result<()> {
        self.lock.flush()
    }
}

fn stdin_init() -> Arc<InterruptSpinLock<Console<'static>>> {
    Arc::new(InterruptSpinLock::new(console()))
}

pub fn stdin() -> Stdin {
    static STDIN: Lazy<InterruptSpinLock<Console<'static>>> = Lazy::new(stdin_init);

    Stdin {
        inner: unsafe { STDIN.get() },
    }
}

pub struct Stdin {
    inner: Arc<InterruptSpinLock<Console<'static>>>,
}

impl Stdin {
    pub fn lock(&self) -> StdinLock {
        StdinLock {
            lock: self.inner.lock(),
        }
    }
}

pub struct StdinLock<'a> {
    lock: InterruptSpinGuard<'a, Console<'static>>,
}

impl<'a> Read for StdinLock<'a> {
    fn read(&mut self, buf: &mut [u8]) -> Result<usize> {
        self.lock.read(buf)
    }
}
<|endoftext|>


<commit_before>pub fn remove_to<'s>(s: &'s str, c: char) -> &'s str {
    match s.rfind(c) {
        Some(pos) => &s[(pos + 1)..],
        None => s
    }
}

pub fn remove_suffix<'s>(s: &'s str, suffix: &str) -> &'s str {
    if !s.ends_with(suffix) {
        panic!();
    }
    &s[..(s.len() - suffix.len())]
}

pub fn remove_prefix<'s>(s: &'s str, prefix: &str) -> &'s str {
    if !s.starts_with(prefix) {
        panic!();
    }
    &s[prefix.len()..]
}

#[cfg(test)]
mod test {

    use super::remove_to;
    use super::remove_prefix;
    use super::remove_suffix;

    #[test]
    fn test_remove_to() {
        assert_eq!("aaa", remove_to("aaa", '.'));
        assert_eq!("bbb", remove_to("aaa.bbb", '.'));
        assert_eq!("ccc", remove_to("aaa.bbb.ccc", '.'));
    }

    #[test]
    fn test_remove_prefix() {
        assert_eq!("aaa", remove_prefix("bbbaaa", "bbb"));
    }

    #[test]
    #[should_panic]
    fn test_remove_prefix_fail() {
        remove_prefix("aaa", "bbb");
    }

    #[test]
    fn test_remove_suffix() {
        assert_eq!("bbb", remove_suffix("bbbaaa", "aaa"));
    }

    #[test]
    #[should_panic]
    fn test_remove_suffix_fail() {
        remove_suffix("aaa", "bbb");
    }
}
<commit_msg>remove unused code<commit_after>pub fn remove_to<'s>(s: &'s str, c: char) -> &'s str {
    match s.rfind(c) {
        Some(pos) => &s[(pos + 1)..],
        None => s
    }
}

pub fn remove_suffix<'s>(s: &'s str, suffix: &str) -> &'s str {
    if !s.ends_with(suffix) {
        panic!();
    }
    &s[..(s.len() - suffix.len())]
}

#[cfg(test)]
mod test {

    use super::remove_to;
    use super::remove_suffix;

    #[test]
    fn test_remove_to() {
        assert_eq!("aaa", remove_to("aaa", '.'));
        assert_eq!("bbb", remove_to("aaa.bbb", '.'));
        assert_eq!("ccc", remove_to("aaa.bbb.ccc", '.'));
    }

    #[test]
    #[should_panic]
    fn test_remove_prefix_fail() {
        remove_prefix("aaa", "bbb");
    }

    #[test]
    fn test_remove_suffix() {
        assert_eq!("bbb", remove_suffix("bbbaaa", "aaa"));
    }

    #[test]
    #[should_panic]
    fn test_remove_suffix_fail() {
        remove_suffix("aaa", "bbb");
    }
}
<|endoftext|>


<commit_before>// The MIT License (MIT)
// Copyright (c) font-loader Developers
//
// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and
// associated documentation files (the "Software"), to deal in the Software without restriction,
// including without limitation the rights to use, copy, modify, merge, publish, distribute,
// sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all copies or
// substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT
// NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

/// Font loading utilities for installed system fonts
pub mod system_fonts {
    use core_text::font_descriptor::*;
    use core_text::font_descriptor;
    use core_text;
    use std::fs::File;
    use std::mem;
    use std::ptr;
    use core_foundation::string::CFString;
    use core_foundation::number::CFNumber;
    use core_foundation::array::CFArray;
    use core_foundation::dictionary::CFDictionary;
    use core_foundation::base::{CFType, TCFType};
    use core_foundation::url::{CFURL, CFURLCopyFileSystemPath, kCFURLPOSIXPathStyle};
    use libc::c_int;
    use std::io::Read;
    /// The platform specific font properties
    pub type FontProperty = CTFontDescriptor;

    /// Builder for FontProperty
    pub struct FontPropertyBuilder {
        symbolic_traits: CTFontSymbolicTraits,
        family: String
    }

    impl FontPropertyBuilder {
        pub fn new() -> FontPropertyBuilder {
            FontPropertyBuilder{ symbolic_traits: 0, family: String::new()}
        }

        pub fn italic(mut self) -> FontPropertyBuilder {
            self.symbolic_traits |= kCTFontItalicTrait;
            self
        }

        pub fn oblique(self) -> FontPropertyBuilder {
            self.italic()
        }

        pub fn monospace(mut self) -> FontPropertyBuilder {
            self.symbolic_traits |= kCTFontMonoSpaceTrait;
            self
        }

        pub fn bold(mut self) -> FontPropertyBuilder {
            self.symbolic_traits |= kCTFontBoldTrait;
            self
        }

        pub fn family(mut self, name: &str) -> FontPropertyBuilder {
            self.family = name.to_string();
            self
        }

        pub fn build(self) -> FontProperty {
            let family_attr: CFString = unsafe { TCFType::wrap_under_get_rule(kCTFontFamilyNameAttribute) };
            let family_name: CFString = self.family.parse().unwrap();
            let traits_attr: CFString = unsafe { TCFType::wrap_under_get_rule(kCTFontTraitsAttribute) };
            let symbolic_traits_attr: CFString = unsafe { TCFType::wrap_under_get_rule(kCTFontSymbolicTrait) };
            let traits = CFDictionary::from_CFType_pairs(&[(symbolic_traits_attr.as_CFType(), CFNumber::from(self.symbolic_traits as i32).as_CFType())]);
            let mut attributes = Vec::new();
            attributes.push((traits_attr.as_CFType(), traits.as_CFType()));
            if self.family.len() != 0 {
                attributes.push((family_attr.as_CFType(), family_name.as_CFType()));
            }
            let attributes = CFDictionary::from_CFType_pairs(&attributes);
            font_descriptor::new_from_attributes(&attributes)
        }
    }

    /// Get the binary data and index of a specific font
    pub fn get(config: &FontProperty) -> Option<(Vec<u8>, c_int)> {
        let mut buffer = Vec::new();
        let path;
        unsafe {
            let value =
                CTFontDescriptorCopyAttribute(config.as_concrete_TypeRef(), kCTFontURLAttribute);
            assert!(!value.is_null());

            let value: CFType = TCFType::wrap_under_get_rule(value);
            assert!(value.instance_of::<CFURL>());
            let url: CFURL = TCFType::wrap_under_get_rule(mem::transmute(value.as_CFTypeRef()));
            path = CFString::wrap_under_create_rule(CFURLCopyFileSystemPath(
                url.as_concrete_TypeRef(),
                kCFURLPOSIXPathStyle,
            ));
        }
        match File::open(path.to_string()).and_then(|mut f| f.read_to_end(&mut buffer)) {
            Ok(_) => Some((buffer, 0)),
            Err(_) => None,
        }
    }

    /// Query the names of all fonts installed in the system
    pub fn query_all() -> Vec<String> {
        core_text::font_collection::get_family_names()
            .iter()
            .map(|family_name| family_name.to_string())
            .collect()
    }

    /// Query the names of specifc fonts installed in the system
    pub fn query_specific(property: &mut FontProperty) -> Vec<String> {
        let descs: CFArray<CTFontDescriptor> = unsafe {
            let descs = CTFontDescriptorCreateMatchingFontDescriptors(
                property.as_concrete_TypeRef(),
                ptr::null(),
            );
            TCFType::wrap_under_create_rule(descs)
        };
        descs
            .iter()
            .map(|desc| desc.family_name())
            .collect::<Vec<_>>()
    }
}
<commit_msg>Convert the url directly to a path instead of going through a string<commit_after>// The MIT License (MIT)
// Copyright (c) font-loader Developers
//
// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and
// associated documentation files (the "Software"), to deal in the Software without restriction,
// including without limitation the rights to use, copy, modify, merge, publish, distribute,
// sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all copies or
// substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT
// NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

/// Font loading utilities for installed system fonts
pub mod system_fonts {
    use core_text::font_descriptor::*;
    use core_text::font_descriptor;
    use core_text;
    use std::fs::File;
    use std::mem;
    use std::ptr;
    use core_foundation::string::CFString;
    use core_foundation::number::CFNumber;
    use core_foundation::array::CFArray;
    use core_foundation::dictionary::CFDictionary;
    use core_foundation::base::{CFType, TCFType};
    use core_foundation::url::CFURL;
    use libc::c_int;
    use std::io::Read;
    /// The platform specific font properties
    pub type FontProperty = CTFontDescriptor;

    /// Builder for FontProperty
    pub struct FontPropertyBuilder {
        symbolic_traits: CTFontSymbolicTraits,
        family: String
    }

    impl FontPropertyBuilder {
        pub fn new() -> FontPropertyBuilder {
            FontPropertyBuilder{ symbolic_traits: 0, family: String::new()}
        }

        pub fn italic(mut self) -> FontPropertyBuilder {
            self.symbolic_traits |= kCTFontItalicTrait;
            self
        }

        pub fn oblique(self) -> FontPropertyBuilder {
            self.italic()
        }

        pub fn monospace(mut self) -> FontPropertyBuilder {
            self.symbolic_traits |= kCTFontMonoSpaceTrait;
            self
        }

        pub fn bold(mut self) -> FontPropertyBuilder {
            self.symbolic_traits |= kCTFontBoldTrait;
            self
        }

        pub fn family(mut self, name: &str) -> FontPropertyBuilder {
            self.family = name.to_string();
            self
        }

        pub fn build(self) -> FontProperty {
            let family_attr: CFString = unsafe { TCFType::wrap_under_get_rule(kCTFontFamilyNameAttribute) };
            let family_name: CFString = self.family.parse().unwrap();
            let traits_attr: CFString = unsafe { TCFType::wrap_under_get_rule(kCTFontTraitsAttribute) };
            let symbolic_traits_attr: CFString = unsafe { TCFType::wrap_under_get_rule(kCTFontSymbolicTrait) };
            let traits = CFDictionary::from_CFType_pairs(&[(symbolic_traits_attr.as_CFType(), CFNumber::from(self.symbolic_traits as i32).as_CFType())]);
            let mut attributes = Vec::new();
            attributes.push((traits_attr.as_CFType(), traits.as_CFType()));
            if self.family.len() != 0 {
                attributes.push((family_attr.as_CFType(), family_name.as_CFType()));
            }
            let attributes = CFDictionary::from_CFType_pairs(&attributes);
            font_descriptor::new_from_attributes(&attributes)
        }
    }

    /// Get the binary data and index of a specific font
    pub fn get(config: &FontProperty) -> Option<(Vec<u8>, c_int)> {
        let mut buffer = Vec::new();
        let url: CFURL;
        unsafe {
            let value =
                CTFontDescriptorCopyAttribute(config.as_concrete_TypeRef(), kCTFontURLAttribute);
            assert!(!value.is_null());

            let value: CFType = TCFType::wrap_under_get_rule(value);
            assert!(value.instance_of::<CFURL>());
            url = TCFType::wrap_under_get_rule(mem::transmute(value.as_CFTypeRef()));
        }
        let path = url.to_path().unwrap();
        match File::open(path).and_then(|mut f| f.read_to_end(&mut buffer)) {
            Ok(_) => Some((buffer, 0)),
            Err(_) => None,
        }
    }

    /// Query the names of all fonts installed in the system
    pub fn query_all() -> Vec<String> {
        core_text::font_collection::get_family_names()
            .iter()
            .map(|family_name| family_name.to_string())
            .collect()
    }

    /// Query the names of specifc fonts installed in the system
    pub fn query_specific(property: &mut FontProperty) -> Vec<String> {
        let descs: CFArray<CTFontDescriptor> = unsafe {
            let descs = CTFontDescriptorCreateMatchingFontDescriptors(
                property.as_concrete_TypeRef(),
                ptr::null(),
            );
            TCFType::wrap_under_create_rule(descs)
        };
        descs
            .iter()
            .map(|desc| desc.family_name())
            .collect::<Vec<_>>()
    }
}
<|endoftext|>