<commit_before>// Copyright 2014-2015 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

//! C definitions used by libnative that don't belong in liblibc

#![allow(dead_code)]
#![allow(non_camel_case_types)]

pub use self::select::fd_set;
pub use self::signal::{sigaction, siginfo, sigset_t};
pub use self::signal::{SA_ONSTACK, SA_RESTART, SA_RESETHAND, SA_NOCLDSTOP};
pub use self::signal::{SA_NODEFER, SA_NOCLDWAIT, SA_SIGINFO, SIGCHLD};

use libc;

#[cfg(any(target_os = "macos",
          target_os = "ios",
          target_os = "freebsd",
          target_os = "dragonfly"))]
pub const FIONBIO: libc::c_ulong = 0x8004667e;
#[cfg(any(all(target_os = "linux",
              any(target_arch = "x86",
                  target_arch = "x86_64",
                  target_arch = "arm",
                  target_arch = "aarch64")),
          target_os = "android"))]
pub const FIONBIO: libc::c_ulong = 0x5421;
#[cfg(all(target_os = "linux",
          any(target_arch = "mips", target_arch = "mipsel")))]
pub const FIONBIO: libc::c_ulong = 0x667e;

#[cfg(any(target_os = "macos",
          target_os = "ios",
          target_os = "freebsd",
          target_os = "dragonfly"))]
pub const FIOCLEX: libc::c_ulong = 0x20006601;
#[cfg(any(all(target_os = "linux",
              any(target_arch = "x86",
                  target_arch = "x86_64",
                  target_arch = "arm",
                  target_arch = "aarch64")),
          target_os = "android"))]
pub const FIOCLEX: libc::c_ulong = 0x5451;
#[cfg(all(target_os = "linux",
          any(target_arch = "mips", target_arch = "mipsel")))]
pub const FIOCLEX: libc::c_ulong = 0x6601;

#[cfg(any(target_os = "macos",
          target_os = "ios",
          target_os = "freebsd",
          target_os = "dragonfly"))]
pub const MSG_DONTWAIT: libc::c_int = 0x80;
#[cfg(any(target_os = "linux", target_os = "android"))]
pub const MSG_DONTWAIT: libc::c_int = 0x40;

pub const WNOHANG: libc::c_int = 1;

extern {
    pub fn gettimeofday(timeval: *mut libc::timeval,
                        tzp: *mut libc::c_void) -> libc::c_int;
    pub fn select(nfds: libc::c_int,
                  readfds: *mut fd_set,
                  writefds: *mut fd_set,
                  errorfds: *mut fd_set,
                  timeout: *mut libc::timeval) -> libc::c_int;
    pub fn getsockopt(sockfd: libc::c_int,
                      level: libc::c_int,
                      optname: libc::c_int,
                      optval: *mut libc::c_void,
                      optlen: *mut libc::socklen_t) -> libc::c_int;
    pub fn ioctl(fd: libc::c_int, req: libc::c_ulong, ...) -> libc::c_int;

    pub fn waitpid(pid: libc::pid_t, status: *mut libc::c_int,
                   options: libc::c_int) -> libc::pid_t;

    pub fn sigaction(signum: libc::c_int,
                     act: *const sigaction,
                     oldact: *mut sigaction) -> libc::c_int;

    pub fn sigaddset(set: *mut sigset_t, signum: libc::c_int) -> libc::c_int;
    pub fn sigdelset(set: *mut sigset_t, signum: libc::c_int) -> libc::c_int;
    pub fn sigemptyset(set: *mut sigset_t) -> libc::c_int;
}

#[cfg(any(target_os = "macos", target_os = "ios"))]
mod select {
    pub const FD_SETSIZE: uint = 1024;

    #[repr(C)]
    pub struct fd_set {
        fds_bits: [i32; (FD_SETSIZE / 32)]
    }

    pub fn fd_set(set: &mut fd_set, fd: i32) {
        set.fds_bits[(fd / 32) as uint] |= 1 << ((fd % 32) as uint);
    }
}

#[cfg(any(target_os = "android",
          target_os = "freebsd",
          target_os = "dragonfly",
          target_os = "linux"))]
mod select {
    use uint;
    use libc;

    pub const FD_SETSIZE: uint = 1024;

    #[repr(C)]
    pub struct fd_set {
        // FIXME: shouldn't this be a c_ulong?
        fds_bits: [libc::uintptr_t; (FD_SETSIZE / uint::BITS)]
    }

    pub fn fd_set(set: &mut fd_set, fd: i32) {
        let fd = fd as uint;
        set.fds_bits[fd / uint::BITS] |= 1 << (fd % uint::BITS);
    }
}

#[cfg(any(all(target_os = "linux",
              any(target_arch = "x86",
                  target_arch = "x86_64",
                  target_arch = "arm",
                  target_arch = "aarch64")),
          target_os = "android"))]
mod signal {
    use libc;

    pub const SA_NOCLDSTOP: libc::c_ulong = 0x00000001;
    pub const SA_NOCLDWAIT: libc::c_ulong = 0x00000002;
    pub const SA_NODEFER: libc::c_ulong = 0x40000000;
    pub const SA_ONSTACK: libc::c_ulong = 0x08000000;
    pub const SA_RESETHAND: libc::c_ulong = 0x80000000;
    pub const SA_RESTART: libc::c_ulong = 0x10000000;
    pub const SA_SIGINFO: libc::c_ulong = 0x00000004;
    pub const SIGCHLD: libc::c_int = 17;

    // This definition is not as accurate as it could be, {pid, uid, status} is
    // actually a giant union. Currently we're only interested in these fields,
    // however.
    #[repr(C)]
    pub struct siginfo {
        si_signo: libc::c_int,
        si_errno: libc::c_int,
        si_code: libc::c_int,
        pub pid: libc::pid_t,
        pub uid: libc::uid_t,
        pub status: libc::c_int,
    }

    #[repr(C)]
    pub struct sigaction {
        pub sa_handler: extern fn(libc::c_int),
        pub sa_mask: sigset_t,
        pub sa_flags: libc::c_ulong,
        sa_restorer: *mut libc::c_void,
    }

    unsafe impl ::marker::Send for sigaction { }
    unsafe impl ::marker::Sync for sigaction { }

    #[repr(C)]
    #[cfg(any(all(stage0, target_word_size = "32"), all(not(stage0), target_pointer_width = "32")))]
    pub struct sigset_t {
        __val: [libc::c_ulong; 32],
    }

    #[repr(C)]
    #[cfg(any(all(stage0, target_word_size = "64"), all(not(stage0), target_pointer_width = "64")))]
    pub struct sigset_t {
        __val: [libc::c_ulong; 16],
    }
}

#[cfg(all(target_os = "linux",
          any(target_arch = "mips", target_arch = "mipsel")))]
mod signal {
    use libc;

    pub const SA_NOCLDSTOP: libc::c_ulong = 0x00000001;
    pub const SA_NOCLDWAIT: libc::c_ulong = 0x00010000;
    pub const SA_NODEFER: libc::c_ulong = 0x40000000;
    pub const SA_ONSTACK: libc::c_ulong = 0x08000000;
    pub const SA_RESETHAND: libc::c_ulong = 0x80000000;
    pub const SA_RESTART: libc::c_ulong = 0x10000000;
    pub const SA_SIGINFO: libc::c_ulong = 0x00000008;
    pub const SIGCHLD: libc::c_int = 18;

    // This definition is not as accurate as it could be, {pid, uid, status} is
    // actually a giant union. Currently we're only interested in these fields,
    // however.
    #[repr(C)]
    pub struct siginfo {
        si_signo: libc::c_int,
        si_code: libc::c_int,
        si_errno: libc::c_int,
        pub pid: libc::pid_t,
        pub uid: libc::uid_t,
        pub status: libc::c_int,
    }

    #[repr(C)]
    pub struct sigaction {
        pub sa_flags: libc::c_uint,
        pub sa_handler: extern fn(libc::c_int),
        pub sa_mask: sigset_t,
        sa_restorer: *mut libc::c_void,
        sa_resv: [libc::c_int; 1],
    }

    unsafe impl ::marker::Send for sigaction { }
    unsafe impl ::marker::Sync for sigaction { }

    #[repr(C)]
    pub struct sigset_t {
        __val: [libc::c_ulong; 32],
    }
}

#[cfg(any(target_os = "macos",
          target_os = "ios",
          target_os = "freebsd",
          target_os = "dragonfly"))]
mod signal {
    use libc;

    pub const SA_ONSTACK: libc::c_int = 0x0001;
    pub const SA_RESTART: libc::c_int = 0x0002;
    pub const SA_RESETHAND: libc::c_int = 0x0004;
    pub const SA_NOCLDSTOP: libc::c_int = 0x0008;
    pub const SA_NODEFER: libc::c_int = 0x0010;
    pub const SA_NOCLDWAIT: libc::c_int = 0x0020;
    pub const SA_SIGINFO: libc::c_int = 0x0040;
    pub const SIGCHLD: libc::c_int = 20;

    #[cfg(any(target_os = "macos", target_os = "ios"))]
    pub type sigset_t = u32;
    #[cfg(any(target_os = "freebsd", target_os = "dragonfly"))]
    #[repr(C)]
    pub struct sigset_t {
        bits: [u32; 4],
    }

    // This structure has more fields, but we're not all that interested in
    // them.
    #[repr(C)]
    pub struct siginfo {
        pub si_signo: libc::c_int,
        pub si_errno: libc::c_int,
        pub si_code: libc::c_int,
        pub pid: libc::pid_t,
        pub uid: libc::uid_t,
        pub status: libc::c_int,
    }

    #[repr(C)]
    pub struct sigaction {
        pub sa_handler: extern fn(libc::c_int),
        pub sa_flags: libc::c_int,
        pub sa_mask: sigset_t,
    }
}
<commit_msg>powerpc: add cdefs for linux<commit_after>// Copyright 2014-2015 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

//! C definitions used by libnative that don't belong in liblibc

#![allow(dead_code)]
#![allow(non_camel_case_types)]

pub use self::select::fd_set;
pub use self::signal::{sigaction, siginfo, sigset_t};
pub use self::signal::{SA_ONSTACK, SA_RESTART, SA_RESETHAND, SA_NOCLDSTOP};
pub use self::signal::{SA_NODEFER, SA_NOCLDWAIT, SA_SIGINFO, SIGCHLD};

use libc;

#[cfg(any(target_os = "macos",
          target_os = "ios",
          target_os = "freebsd",
          target_os = "dragonfly"))]
pub const FIONBIO: libc::c_ulong = 0x8004667e;
#[cfg(any(all(target_os = "linux",
              any(target_arch = "x86",
                  target_arch = "x86_64",
                  target_arch = "arm",
                  target_arch = "aarch64")),
          target_os = "android"))]
pub const FIONBIO: libc::c_ulong = 0x5421;
#[cfg(all(target_os = "linux",
          any(target_arch = "mips",
              target_arch = "mipsel",
              target_arch = "powerpc")))]
pub const FIONBIO: libc::c_ulong = 0x667e;

#[cfg(any(target_os = "macos",
          target_os = "ios",
          target_os = "freebsd",
          target_os = "dragonfly"))]
pub const FIOCLEX: libc::c_ulong = 0x20006601;
#[cfg(any(all(target_os = "linux",
              any(target_arch = "x86",
                  target_arch = "x86_64",
                  target_arch = "arm",
                  target_arch = "aarch64")),
          target_os = "android"))]
pub const FIOCLEX: libc::c_ulong = 0x5451;
#[cfg(all(target_os = "linux",
          any(target_arch = "mips",
              target_arch = "mipsel",
              target_arch = "powerpc")))]
pub const FIOCLEX: libc::c_ulong = 0x6601;

#[cfg(any(target_os = "macos",
          target_os = "ios",
          target_os = "freebsd",
          target_os = "dragonfly"))]
pub const MSG_DONTWAIT: libc::c_int = 0x80;
#[cfg(any(target_os = "linux", target_os = "android"))]
pub const MSG_DONTWAIT: libc::c_int = 0x40;

pub const WNOHANG: libc::c_int = 1;

extern {
    pub fn gettimeofday(timeval: *mut libc::timeval,
                        tzp: *mut libc::c_void) -> libc::c_int;
    pub fn select(nfds: libc::c_int,
                  readfds: *mut fd_set,
                  writefds: *mut fd_set,
                  errorfds: *mut fd_set,
                  timeout: *mut libc::timeval) -> libc::c_int;
    pub fn getsockopt(sockfd: libc::c_int,
                      level: libc::c_int,
                      optname: libc::c_int,
                      optval: *mut libc::c_void,
                      optlen: *mut libc::socklen_t) -> libc::c_int;
    pub fn ioctl(fd: libc::c_int, req: libc::c_ulong, ...) -> libc::c_int;

    pub fn waitpid(pid: libc::pid_t, status: *mut libc::c_int,
                   options: libc::c_int) -> libc::pid_t;

    pub fn sigaction(signum: libc::c_int,
                     act: *const sigaction,
                     oldact: *mut sigaction) -> libc::c_int;

    pub fn sigaddset(set: *mut sigset_t, signum: libc::c_int) -> libc::c_int;
    pub fn sigdelset(set: *mut sigset_t, signum: libc::c_int) -> libc::c_int;
    pub fn sigemptyset(set: *mut sigset_t) -> libc::c_int;
}

#[cfg(any(target_os = "macos", target_os = "ios"))]
mod select {
    pub const FD_SETSIZE: uint = 1024;

    #[repr(C)]
    pub struct fd_set {
        fds_bits: [i32; (FD_SETSIZE / 32)]
    }

    pub fn fd_set(set: &mut fd_set, fd: i32) {
        set.fds_bits[(fd / 32) as uint] |= 1 << ((fd % 32) as uint);
    }
}

#[cfg(any(target_os = "android",
          target_os = "freebsd",
          target_os = "dragonfly",
          target_os = "linux"))]
mod select {
    use uint;
    use libc;

    pub const FD_SETSIZE: uint = 1024;

    #[repr(C)]
    pub struct fd_set {
        // FIXME: shouldn't this be a c_ulong?
        fds_bits: [libc::uintptr_t; (FD_SETSIZE / uint::BITS)]
    }

    pub fn fd_set(set: &mut fd_set, fd: i32) {
        let fd = fd as uint;
        set.fds_bits[fd / uint::BITS] |= 1 << (fd % uint::BITS);
    }
}

#[cfg(any(all(target_os = "linux",
              any(target_arch = "x86",
                  target_arch = "x86_64",
                  target_arch = "arm",
                  target_arch = "aarch64")),
          target_os = "android"))]
mod signal {
    use libc;

    pub const SA_NOCLDSTOP: libc::c_ulong = 0x00000001;
    pub const SA_NOCLDWAIT: libc::c_ulong = 0x00000002;
    pub const SA_NODEFER: libc::c_ulong = 0x40000000;
    pub const SA_ONSTACK: libc::c_ulong = 0x08000000;
    pub const SA_RESETHAND: libc::c_ulong = 0x80000000;
    pub const SA_RESTART: libc::c_ulong = 0x10000000;
    pub const SA_SIGINFO: libc::c_ulong = 0x00000004;
    pub const SIGCHLD: libc::c_int = 17;

    // This definition is not as accurate as it could be, {pid, uid, status} is
    // actually a giant union. Currently we're only interested in these fields,
    // however.
    #[repr(C)]
    pub struct siginfo {
        si_signo: libc::c_int,
        si_errno: libc::c_int,
        si_code: libc::c_int,
        pub pid: libc::pid_t,
        pub uid: libc::uid_t,
        pub status: libc::c_int,
    }

    #[repr(C)]
    pub struct sigaction {
        pub sa_handler: extern fn(libc::c_int),
        pub sa_mask: sigset_t,
        pub sa_flags: libc::c_ulong,
        sa_restorer: *mut libc::c_void,
    }

    unsafe impl ::marker::Send for sigaction { }
    unsafe impl ::marker::Sync for sigaction { }

    #[repr(C)]
    #[cfg(any(all(stage0, target_word_size = "32"), all(not(stage0), target_pointer_width = "32")))]
    pub struct sigset_t {
        __val: [libc::c_ulong; 32],
    }

    #[repr(C)]
    #[cfg(any(all(stage0, target_word_size = "64"), all(not(stage0), target_pointer_width = "64")))]
    pub struct sigset_t {
        __val: [libc::c_ulong; 16],
    }
}

#[cfg(all(target_os = "linux",
          any(target_arch = "mips",
              target_arch = "mipsel",
              target_arch = "powerpc")))]
mod signal {
    use libc;

    pub const SA_NOCLDSTOP: libc::c_ulong = 0x00000001;
    pub const SA_NOCLDWAIT: libc::c_ulong = 0x00010000;
    pub const SA_NODEFER: libc::c_ulong = 0x40000000;
    pub const SA_ONSTACK: libc::c_ulong = 0x08000000;
    pub const SA_RESETHAND: libc::c_ulong = 0x80000000;
    pub const SA_RESTART: libc::c_ulong = 0x10000000;
    pub const SA_SIGINFO: libc::c_ulong = 0x00000008;
    pub const SIGCHLD: libc::c_int = 18;

    // This definition is not as accurate as it could be, {pid, uid, status} is
    // actually a giant union. Currently we're only interested in these fields,
    // however.
    #[repr(C)]
    pub struct siginfo {
        si_signo: libc::c_int,
        si_code: libc::c_int,
        si_errno: libc::c_int,
        pub pid: libc::pid_t,
        pub uid: libc::uid_t,
        pub status: libc::c_int,
    }

    #[repr(C)]
    pub struct sigaction {
        pub sa_flags: libc::c_uint,
        pub sa_handler: extern fn(libc::c_int),
        pub sa_mask: sigset_t,
        sa_restorer: *mut libc::c_void,
        sa_resv: [libc::c_int; 1],
    }

    unsafe impl ::marker::Send for sigaction { }
    unsafe impl ::marker::Sync for sigaction { }

    #[repr(C)]
    pub struct sigset_t {
        __val: [libc::c_ulong; 32],
    }
}

#[cfg(any(target_os = "macos",
          target_os = "ios",
          target_os = "freebsd",
          target_os = "dragonfly"))]
mod signal {
    use libc;

    pub const SA_ONSTACK: libc::c_int = 0x0001;
    pub const SA_RESTART: libc::c_int = 0x0002;
    pub const SA_RESETHAND: libc::c_int = 0x0004;
    pub const SA_NOCLDSTOP: libc::c_int = 0x0008;
    pub const SA_NODEFER: libc::c_int = 0x0010;
    pub const SA_NOCLDWAIT: libc::c_int = 0x0020;
    pub const SA_SIGINFO: libc::c_int = 0x0040;
    pub const SIGCHLD: libc::c_int = 20;

    #[cfg(any(target_os = "macos", target_os = "ios"))]
    pub type sigset_t = u32;
    #[cfg(any(target_os = "freebsd", target_os = "dragonfly"))]
    #[repr(C)]
    pub struct sigset_t {
        bits: [u32; 4],
    }

    // This structure has more fields, but we're not all that interested in
    // them.
    #[repr(C)]
    pub struct siginfo {
        pub si_signo: libc::c_int,
        pub si_errno: libc::c_int,
        pub si_code: libc::c_int,
        pub pid: libc::pid_t,
        pub uid: libc::uid_t,
        pub status: libc::c_int,
    }

    #[repr(C)]
    pub struct sigaction {
        pub sa_handler: extern fn(libc::c_int),
        pub sa_flags: libc::c_int,
        pub sa_mask: sigset_t,
    }
}
<|endoftext|>


<commit_before>// Copyright 2012 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

/*
 * The compiler code necessary to support the fmt! extension. Eventually this
 * should all get sucked into either the standard library extfmt module or the
 * compiler syntax extension plugin interface.
 */

use ast;
use codemap::span;
use ext::base::*;
use ext::base;
use ext::build;
use ext::build::*;

use core::unstable::extfmt::ct::*;

pub fn expand_syntax_ext(cx: @ext_ctxt, sp: span, tts: &[ast::token_tree])
    -> base::MacResult {
    let args = get_exprs_from_tts(cx, tts);
    if args.len() == 0 {
        cx.span_fatal(sp, "fmt! takes at least 1 argument.");
    }
    let fmt =
        expr_to_str(cx, args[0],
                    ~"first argument to fmt! must be a string literal.");
    let fmtspan = args[0].span;
    debug!("Format string: %s", fmt);
    fn parse_fmt_err_(cx: @ext_ctxt, sp: span, msg: &str) -> ! {
        cx.span_fatal(sp, msg);
    }
    let parse_fmt_err: @fn(&str) -> ! = |s| parse_fmt_err_(cx, fmtspan, s);
    let pieces = parse_fmt_string(fmt, parse_fmt_err);
    MRExpr(pieces_to_expr(cx, sp, pieces, args))
}

// FIXME (#2249): A lot of these functions for producing expressions can
// probably be factored out in common with other code that builds
// expressions.  Also: Cleanup the naming of these functions.
// Note: Moved many of the common ones to build.rs --kevina
fn pieces_to_expr(cx: @ext_ctxt, sp: span,
                  pieces: ~[Piece], args: ~[@ast::expr])
   -> @ast::expr {
    fn make_path_vec(cx: @ext_ctxt, ident: @~str) -> ~[ast::ident] {
        let intr = cx.parse_sess().interner;
        return ~[intr.intern(@~"unstable"), intr.intern(@~"extfmt"),
                 intr.intern(@~"rt"), intr.intern(ident)];
    }
    fn make_rt_path_expr(cx: @ext_ctxt, sp: span, nm: @~str) -> @ast::expr {
        let path = make_path_vec(cx, nm);
        return mk_path_global(cx, sp, path);
    }
    // Produces an AST expression that represents a RT::conv record,
    // which tells the RT::conv* functions how to perform the conversion

    fn make_rt_conv_expr(cx: @ext_ctxt, sp: span, cnv: &Conv) -> @ast::expr {
        fn make_flags(cx: @ext_ctxt, sp: span, flags: ~[Flag]) -> @ast::expr {
            let mut tmp_expr = make_rt_path_expr(cx, sp, @~"flag_none");
            for flags.each |f| {
                let fstr = match *f {
                  FlagLeftJustify => ~"flag_left_justify",
                  FlagLeftZeroPad => ~"flag_left_zero_pad",
                  FlagSpaceForSign => ~"flag_space_for_sign",
                  FlagSignAlways => ~"flag_sign_always",
                  FlagAlternate => ~"flag_alternate"
                };
                tmp_expr = mk_binary(cx, sp, ast::bitor, tmp_expr,
                                     make_rt_path_expr(cx, sp, @fstr));
            }
            return tmp_expr;
        }
        fn make_count(cx: @ext_ctxt, sp: span, cnt: Count) -> @ast::expr {
            match cnt {
              CountImplied => {
                return make_rt_path_expr(cx, sp, @~"CountImplied");
              }
              CountIs(c) => {
                let count_lit = mk_uint(cx, sp, c as uint);
                let count_is_path = make_path_vec(cx, @~"CountIs");
                let count_is_args = ~[count_lit];
                return mk_call_global(cx, sp, count_is_path, count_is_args);
              }
              _ => cx.span_unimpl(sp, ~"unimplemented fmt! conversion")
            }
        }
        fn make_ty(cx: @ext_ctxt, sp: span, t: Ty) -> @ast::expr {
            let rt_type;
            match t {
              TyHex(c) => match c {
                CaseUpper => rt_type = ~"TyHexUpper",
                CaseLower => rt_type = ~"TyHexLower"
              },
              TyBits => rt_type = ~"TyBits",
              TyOctal => rt_type = ~"TyOctal",
              _ => rt_type = ~"TyDefault"
            }
            return make_rt_path_expr(cx, sp, @rt_type);
        }
        fn make_conv_struct(cx: @ext_ctxt, sp: span, flags_expr: @ast::expr,
                         width_expr: @ast::expr, precision_expr: @ast::expr,
                         ty_expr: @ast::expr) -> @ast::expr {
            let intr = cx.parse_sess().interner;
            mk_global_struct_e(
                cx,
                sp,
                make_path_vec(cx, @~"Conv"),
                ~[
                    build::Field {
                        ident: intr.intern(@~"flags"), ex: flags_expr
                    },
                    build::Field {
                        ident: intr.intern(@~"width"), ex: width_expr
                    },
                    build::Field {
                        ident: intr.intern(@~"precision"), ex: precision_expr
                    },
                    build::Field {
                        ident: intr.intern(@~"ty"), ex: ty_expr
                    },
                ]
            )
        }
        let rt_conv_flags = make_flags(cx, sp, cnv.flags);
        let rt_conv_width = make_count(cx, sp, cnv.width);
        let rt_conv_precision = make_count(cx, sp, cnv.precision);
        let rt_conv_ty = make_ty(cx, sp, cnv.ty);
        make_conv_struct(cx, sp, rt_conv_flags, rt_conv_width,
                         rt_conv_precision, rt_conv_ty)
    }
    fn make_conv_call(cx: @ext_ctxt, sp: span, conv_type: &str, cnv: &Conv,
                      arg: @ast::expr, buf: @ast::expr) -> @ast::expr {
        let fname = ~"conv_" + conv_type;
        let path = make_path_vec(cx, @fname);
        let cnv_expr = make_rt_conv_expr(cx, sp, cnv);
        let args = ~[cnv_expr, arg, buf];
        return mk_call_global(cx, arg.span, path, args);
    }

    fn make_new_conv(cx: @ext_ctxt, sp: span, cnv: &Conv,
                     arg: @ast::expr, buf: @ast::expr) -> @ast::expr {
        fn is_signed_type(cnv: &Conv) -> bool {
            match cnv.ty {
              TyInt(s) => match s {
                Signed => return true,
                Unsigned => return false
              },
              TyFloat => return true,
              _ => return false
            }
        }
        let unsupported = ~"conversion not supported in fmt! string";
        match cnv.param {
          option::None => (),
          _ => cx.span_unimpl(sp, unsupported)
        }
        for cnv.flags.each |f| {
            match *f {
              FlagLeftJustify => (),
              FlagSignAlways => {
                if !is_signed_type(cnv) {
                    cx.span_fatal(sp,
                                  ~"+ flag only valid in " +
                                      ~"signed fmt! conversion");
                }
              }
              FlagSpaceForSign => {
                if !is_signed_type(cnv) {
                    cx.span_fatal(sp,
                                  ~"space flag only valid in " +
                                      ~"signed fmt! conversions");
                }
              }
              FlagLeftZeroPad => (),
              _ => cx.span_unimpl(sp, unsupported)
            }
        }
        match cnv.width {
          CountImplied => (),
          CountIs(_) => (),
          _ => cx.span_unimpl(sp, unsupported)
        }
        match cnv.precision {
          CountImplied => (),
          CountIs(_) => (),
          _ => cx.span_unimpl(sp, unsupported)
        }
        let (name, actual_arg) = match cnv.ty {
            TyStr => ("str", arg),
            TyInt(Signed) => ("int", arg),
            TyBool => ("bool", arg),
            TyChar => ("char", arg),
            TyBits | TyOctal | TyHex(_) | TyInt(Unsigned) => ("uint", arg),
            TyFloat => ("float", arg),
            TyPoly => ("poly", mk_addr_of(cx, sp, arg))
        };
        return make_conv_call(cx, arg.span, name, cnv, actual_arg,
                              mk_mut_addr_of(cx, arg.span, buf));
    }
    fn log_conv(c: &Conv) {
        debug!("Building conversion:");
        match c.param {
          Some(p) => { debug!("param: %s", p.to_str()); }
          _ => debug!("param: none")
        }
        for c.flags.each |f| {
            match *f {
              FlagLeftJustify => debug!("flag: left justify"),
              FlagLeftZeroPad => debug!("flag: left zero pad"),
              FlagSpaceForSign => debug!("flag: left space pad"),
              FlagSignAlways => debug!("flag: sign always"),
              FlagAlternate => debug!("flag: alternate")
            }
        }
        match c.width {
          CountIs(i) =>
              debug!("width: count is %s", i.to_str()),
          CountIsParam(i) =>
              debug!("width: count is param %s", i.to_str()),
          CountIsNextParam => debug!("width: count is next param"),
          CountImplied => debug!("width: count is implied")
        }
        match c.precision {
          CountIs(i) =>
              debug!("prec: count is %s", i.to_str()),
          CountIsParam(i) =>
              debug!("prec: count is param %s", i.to_str()),
          CountIsNextParam => debug!("prec: count is next param"),
          CountImplied => debug!("prec: count is implied")
        }
        match c.ty {
          TyBool => debug!("type: bool"),
          TyStr => debug!("type: str"),
          TyChar => debug!("type: char"),
          TyInt(s) => match s {
            Signed => debug!("type: signed"),
            Unsigned => debug!("type: unsigned")
          },
          TyBits => debug!("type: bits"),
          TyHex(cs) => match cs {
            CaseUpper => debug!("type: uhex"),
            CaseLower => debug!("type: lhex"),
          },
          TyOctal => debug!("type: octal"),
          TyFloat => debug!("type: float"),
          TyPoly => debug!("type: poly")
        }
    }

    let fmt_sp = args[0].span;
    let mut n = 0u;
    let nargs = args.len();

    /* 'ident' is the local buffer building up the result of fmt! */
    let ident = cx.parse_sess().interner.intern(@~"__fmtbuf");
    let buf = || mk_path(cx, fmt_sp, ~[ident]);
    let str_ident = cx.parse_sess().interner.intern(@~"str");
    let push_ident = cx.parse_sess().interner.intern(@~"push_str");
    let mut stms = ~[];

    /* Translate each piece (portion of the fmt expression) by invoking the
       corresponding function in core::unstable::extfmt. Each function takes a
       buffer to insert data into along with the data being formatted. */
    let npieces = pieces.len();
    do vec::consume(pieces) |i, pc| {
        match pc {
            /* Raw strings get appended via str::push_str */
            PieceString(s) => {
                let portion = mk_uniq_str(cx, fmt_sp, s);

                /* If this is the first portion, then initialize the local
                   buffer with it directly. If it's actually the only piece,
                   then there's no need for it to be mutable */
                if i == 0 {
                    stms.push(mk_local(cx, fmt_sp, npieces > 1, ident, portion));
                } else {
                    let args = ~[mk_mut_addr_of(cx, fmt_sp, buf()), portion];
                    let call = mk_call_global(cx,
                                              fmt_sp,
                                              ~[str_ident, push_ident],
                                              args);
                    stms.push(mk_stmt(cx, fmt_sp, call));
                }
            }

            /* Invoke the correct conv function in extfmt */
            PieceConv(ref conv) => {
                n += 1u;
                if n >= nargs {
                    cx.span_fatal(sp,
                                  ~"not enough arguments to fmt! " +
                                  ~"for the given format string");
                }

                log_conv(conv);
                /* If the first portion is a conversion, then the local buffer
                   must be initialized as an empty string */
                if i == 0 {
                    stms.push(mk_local(cx, fmt_sp, true, ident,
                                       mk_uniq_str(cx, fmt_sp, ~"")));
                }
                stms.push(mk_stmt(cx, fmt_sp,
                                  make_new_conv(cx, fmt_sp, conv,
                                                args[n], buf())));
            }
        }
    }

    let expected_nargs = n + 1u; // n conversions + the fmt string
    if expected_nargs < nargs {
        cx.span_fatal
            (sp, fmt!("too many arguments to fmt!. found %u, expected %u",
                           nargs, expected_nargs));
    }

    return mk_block(cx, fmt_sp, ~[], stms, Some(buf()));
}
<commit_msg>auto merge of #6219 : dotdash/rust/fmt, r=graydon<commit_after>// Copyright 2012 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

/*
 * The compiler code necessary to support the fmt! extension. Eventually this
 * should all get sucked into either the standard library extfmt module or the
 * compiler syntax extension plugin interface.
 */

use ast;
use codemap::span;
use ext::base::*;
use ext::base;
use ext::build;
use ext::build::*;

use core::unstable::extfmt::ct::*;

pub fn expand_syntax_ext(cx: @ext_ctxt, sp: span, tts: &[ast::token_tree])
    -> base::MacResult {
    let args = get_exprs_from_tts(cx, tts);
    if args.len() == 0 {
        cx.span_fatal(sp, "fmt! takes at least 1 argument.");
    }
    let fmt =
        expr_to_str(cx, args[0],
                    ~"first argument to fmt! must be a string literal.");
    let fmtspan = args[0].span;
    debug!("Format string: %s", fmt);
    fn parse_fmt_err_(cx: @ext_ctxt, sp: span, msg: &str) -> ! {
        cx.span_fatal(sp, msg);
    }
    let parse_fmt_err: @fn(&str) -> ! = |s| parse_fmt_err_(cx, fmtspan, s);
    let pieces = parse_fmt_string(fmt, parse_fmt_err);
    MRExpr(pieces_to_expr(cx, sp, pieces, args))
}

// FIXME (#2249): A lot of these functions for producing expressions can
// probably be factored out in common with other code that builds
// expressions.  Also: Cleanup the naming of these functions.
// Note: Moved many of the common ones to build.rs --kevina
fn pieces_to_expr(cx: @ext_ctxt, sp: span,
                  pieces: ~[Piece], args: ~[@ast::expr])
   -> @ast::expr {
    fn make_path_vec(cx: @ext_ctxt, ident: @~str) -> ~[ast::ident] {
        let intr = cx.parse_sess().interner;
        return ~[intr.intern(@~"unstable"), intr.intern(@~"extfmt"),
                 intr.intern(@~"rt"), intr.intern(ident)];
    }
    fn make_rt_path_expr(cx: @ext_ctxt, sp: span, nm: @~str) -> @ast::expr {
        let path = make_path_vec(cx, nm);
        return mk_path_global(cx, sp, path);
    }
    // Produces an AST expression that represents a RT::conv record,
    // which tells the RT::conv* functions how to perform the conversion

    fn make_rt_conv_expr(cx: @ext_ctxt, sp: span, cnv: &Conv) -> @ast::expr {
        fn make_flags(cx: @ext_ctxt, sp: span, flags: ~[Flag]) -> @ast::expr {
            let mut tmp_expr = make_rt_path_expr(cx, sp, @~"flag_none");
            for flags.each |f| {
                let fstr = match *f {
                  FlagLeftJustify => ~"flag_left_justify",
                  FlagLeftZeroPad => ~"flag_left_zero_pad",
                  FlagSpaceForSign => ~"flag_space_for_sign",
                  FlagSignAlways => ~"flag_sign_always",
                  FlagAlternate => ~"flag_alternate"
                };
                tmp_expr = mk_binary(cx, sp, ast::bitor, tmp_expr,
                                     make_rt_path_expr(cx, sp, @fstr));
            }
            return tmp_expr;
        }
        fn make_count(cx: @ext_ctxt, sp: span, cnt: Count) -> @ast::expr {
            match cnt {
              CountImplied => {
                return make_rt_path_expr(cx, sp, @~"CountImplied");
              }
              CountIs(c) => {
                let count_lit = mk_uint(cx, sp, c as uint);
                let count_is_path = make_path_vec(cx, @~"CountIs");
                let count_is_args = ~[count_lit];
                return mk_call_global(cx, sp, count_is_path, count_is_args);
              }
              _ => cx.span_unimpl(sp, ~"unimplemented fmt! conversion")
            }
        }
        fn make_ty(cx: @ext_ctxt, sp: span, t: Ty) -> @ast::expr {
            let rt_type;
            match t {
              TyHex(c) => match c {
                CaseUpper => rt_type = ~"TyHexUpper",
                CaseLower => rt_type = ~"TyHexLower"
              },
              TyBits => rt_type = ~"TyBits",
              TyOctal => rt_type = ~"TyOctal",
              _ => rt_type = ~"TyDefault"
            }
            return make_rt_path_expr(cx, sp, @rt_type);
        }
        fn make_conv_struct(cx: @ext_ctxt, sp: span, flags_expr: @ast::expr,
                         width_expr: @ast::expr, precision_expr: @ast::expr,
                         ty_expr: @ast::expr) -> @ast::expr {
            let intr = cx.parse_sess().interner;
            mk_global_struct_e(
                cx,
                sp,
                make_path_vec(cx, @~"Conv"),
                ~[
                    build::Field {
                        ident: intr.intern(@~"flags"), ex: flags_expr
                    },
                    build::Field {
                        ident: intr.intern(@~"width"), ex: width_expr
                    },
                    build::Field {
                        ident: intr.intern(@~"precision"), ex: precision_expr
                    },
                    build::Field {
                        ident: intr.intern(@~"ty"), ex: ty_expr
                    },
                ]
            )
        }
        let rt_conv_flags = make_flags(cx, sp, cnv.flags);
        let rt_conv_width = make_count(cx, sp, cnv.width);
        let rt_conv_precision = make_count(cx, sp, cnv.precision);
        let rt_conv_ty = make_ty(cx, sp, cnv.ty);
        make_conv_struct(cx, sp, rt_conv_flags, rt_conv_width,
                         rt_conv_precision, rt_conv_ty)
    }
    fn make_conv_call(cx: @ext_ctxt, sp: span, conv_type: &str, cnv: &Conv,
                      arg: @ast::expr, buf: @ast::expr) -> @ast::expr {
        let fname = ~"conv_" + conv_type;
        let path = make_path_vec(cx, @fname);
        let cnv_expr = make_rt_conv_expr(cx, sp, cnv);
        let args = ~[cnv_expr, arg, buf];
        return mk_call_global(cx, arg.span, path, args);
    }

    fn make_new_conv(cx: @ext_ctxt, sp: span, cnv: &Conv,
                     arg: @ast::expr, buf: @ast::expr) -> @ast::expr {
        fn is_signed_type(cnv: &Conv) -> bool {
            match cnv.ty {
              TyInt(s) => match s {
                Signed => return true,
                Unsigned => return false
              },
              TyFloat => return true,
              _ => return false
            }
        }
        let unsupported = ~"conversion not supported in fmt! string";
        match cnv.param {
          option::None => (),
          _ => cx.span_unimpl(sp, unsupported)
        }
        for cnv.flags.each |f| {
            match *f {
              FlagLeftJustify => (),
              FlagSignAlways => {
                if !is_signed_type(cnv) {
                    cx.span_fatal(sp,
                                  ~"+ flag only valid in " +
                                      ~"signed fmt! conversion");
                }
              }
              FlagSpaceForSign => {
                if !is_signed_type(cnv) {
                    cx.span_fatal(sp,
                                  ~"space flag only valid in " +
                                      ~"signed fmt! conversions");
                }
              }
              FlagLeftZeroPad => (),
              _ => cx.span_unimpl(sp, unsupported)
            }
        }
        match cnv.width {
          CountImplied => (),
          CountIs(_) => (),
          _ => cx.span_unimpl(sp, unsupported)
        }
        match cnv.precision {
          CountImplied => (),
          CountIs(_) => (),
          _ => cx.span_unimpl(sp, unsupported)
        }
        let (name, actual_arg) = match cnv.ty {
            TyStr => ("str", arg),
            TyInt(Signed) => ("int", arg),
            TyBool => ("bool", arg),
            TyChar => ("char", arg),
            TyBits | TyOctal | TyHex(_) | TyInt(Unsigned) => ("uint", arg),
            TyFloat => ("float", arg),
            TyPoly => ("poly", mk_addr_of(cx, sp, arg))
        };
        return make_conv_call(cx, arg.span, name, cnv, actual_arg,
                              mk_mut_addr_of(cx, arg.span, buf));
    }
    fn log_conv(c: &Conv) {
        debug!("Building conversion:");
        match c.param {
          Some(p) => { debug!("param: %s", p.to_str()); }
          _ => debug!("param: none")
        }
        for c.flags.each |f| {
            match *f {
              FlagLeftJustify => debug!("flag: left justify"),
              FlagLeftZeroPad => debug!("flag: left zero pad"),
              FlagSpaceForSign => debug!("flag: left space pad"),
              FlagSignAlways => debug!("flag: sign always"),
              FlagAlternate => debug!("flag: alternate")
            }
        }
        match c.width {
          CountIs(i) =>
              debug!("width: count is %s", i.to_str()),
          CountIsParam(i) =>
              debug!("width: count is param %s", i.to_str()),
          CountIsNextParam => debug!("width: count is next param"),
          CountImplied => debug!("width: count is implied")
        }
        match c.precision {
          CountIs(i) =>
              debug!("prec: count is %s", i.to_str()),
          CountIsParam(i) =>
              debug!("prec: count is param %s", i.to_str()),
          CountIsNextParam => debug!("prec: count is next param"),
          CountImplied => debug!("prec: count is implied")
        }
        match c.ty {
          TyBool => debug!("type: bool"),
          TyStr => debug!("type: str"),
          TyChar => debug!("type: char"),
          TyInt(s) => match s {
            Signed => debug!("type: signed"),
            Unsigned => debug!("type: unsigned")
          },
          TyBits => debug!("type: bits"),
          TyHex(cs) => match cs {
            CaseUpper => debug!("type: uhex"),
            CaseLower => debug!("type: lhex"),
          },
          TyOctal => debug!("type: octal"),
          TyFloat => debug!("type: float"),
          TyPoly => debug!("type: poly")
        }
    }

    let fmt_sp = args[0].span;
    let mut n = 0u;
    let nargs = args.len();

    /* 'ident' is the local buffer building up the result of fmt! */
    let ident = cx.parse_sess().interner.intern(@~"__fmtbuf");
    let buf = || mk_path(cx, fmt_sp, ~[ident]);
    let str_ident = cx.parse_sess().interner.intern(@~"str");
    let push_ident = cx.parse_sess().interner.intern(@~"push_str");
    let mut stms = ~[];

    /* Translate each piece (portion of the fmt expression) by invoking the
       corresponding function in core::unstable::extfmt. Each function takes a
       buffer to insert data into along with the data being formatted. */
    let npieces = pieces.len();
    do vec::consume(pieces) |i, pc| {
        match pc {
            /* Raw strings get appended via str::push_str */
            PieceString(s) => {
                /* If this is the first portion, then initialize the local
                   buffer with it directly. If it's actually the only piece,
                   then there's no need for it to be mutable */
                if i == 0 {
                    stms.push(mk_local(cx, fmt_sp, npieces > 1, ident, mk_uniq_str(cx, fmt_sp, s)));
                } else {
                    let args = ~[mk_mut_addr_of(cx, fmt_sp, buf()), mk_base_str(cx, fmt_sp, s)];
                    let call = mk_call_global(cx,
                                              fmt_sp,
                                              ~[str_ident, push_ident],
                                              args);
                    stms.push(mk_stmt(cx, fmt_sp, call));
                }
            }

            /* Invoke the correct conv function in extfmt */
            PieceConv(ref conv) => {
                n += 1u;
                if n >= nargs {
                    cx.span_fatal(sp,
                                  ~"not enough arguments to fmt! " +
                                  ~"for the given format string");
                }

                log_conv(conv);
                /* If the first portion is a conversion, then the local buffer
                   must be initialized as an empty string */
                if i == 0 {
                    stms.push(mk_local(cx, fmt_sp, true, ident,
                                       mk_uniq_str(cx, fmt_sp, ~"")));
                }
                stms.push(mk_stmt(cx, fmt_sp,
                                  make_new_conv(cx, fmt_sp, conv,
                                                args[n], buf())));
            }
        }
    }

    let expected_nargs = n + 1u; // n conversions + the fmt string
    if expected_nargs < nargs {
        cx.span_fatal
            (sp, fmt!("too many arguments to fmt!. found %u, expected %u",
                           nargs, expected_nargs));
    }

    return mk_block(cx, fmt_sp, ~[], stms, Some(buf()));
}
<|endoftext|>


<commit_before>use core::position::{Size, HasSize};
use core::cellbuffer::CellAccessor;

use ui::core::{
    Alignable,
    HorizontalAlign,
    VerticalAlign,
    Widget,
    Frame,
    Painter
};

/// Display text to widgets
///
/// # Examples
///
/// ```
/// use rustty::ui::core::{VerticalAlign, HorizontalAlign, Widget};
/// use rustty::ui::{Dialog, Label};
///
/// let mut maindlg = Dialog::new(60, 10);
///
/// let mut label = Label::from_str("Hi, this is an example!");
/// label.pack(&maindlg, HorizontalAlign::Middle, VerticalAlign::Middle, (0,0));
/// label.draw(maindlg.frame_mut());
///
/// maindlg.draw_box();
/// ```
///
pub struct Label {
    frame: Frame,
    text: String,
    x: usize,
    y: usize,
    t_halign: HorizontalAlign,
    t_valign: VerticalAlign,
    t_margin: (usize, usize)
}

impl Label {
    /// Construct a new Label widget `cols` wide by `rols` high. Initial text is empty
    /// and left aligned
    ///
    /// # Examples
    ///
    /// ```
    /// use rustty::ui::Label;
    ///
    /// let mut label = Label::new(60, 10);
    /// ```
    ///
    pub fn new(cols: usize, rows: usize) -> Label {
        Label {
            frame: Frame::new(cols, rows),
            text: "".to_string(),
            x: 0,
            y: 0,
            t_halign: HorizontalAlign::Left,
            t_valign: VerticalAlign::Middle,
            t_margin: (0, 0)
        }
    }

    /// Construct a new label widget from an existing string *s*. *s* can either be a
    /// `&str` or `String` , and a label will be constructed that is the size of the
    /// length of characters in *s*. Text is left aligned by default
    ///
    /// # Examples
    ///
    /// ```
    /// use rustty::ui::Label;
    ///
    /// let mut label1 = Label::from_str("This is a label");    // label is size (15x1)
    ///
    /// let s = "Here's another label".to_string();
    /// let mut label2 = Label::from_str(s);                    // label is size (20x1)
    /// ```
    ///
    pub fn from_str<S: Into<String>>(s: S) -> Label {
        let s = s.into();
        Label {
            frame: Frame::new(s.len(), 1),
            text: s.into(),
            x: 0,
            y: 0,
            t_halign: HorizontalAlign::Left,
            t_valign: VerticalAlign::Middle,
            t_margin: (1, 1)
        }
    }

    /// Specify a custom alignment for the text within the widget
    ///
    /// # Examples
    ///
    /// ```
    /// use rustty::ui::core::{HorizontalAlign, VerticalAlign};
    /// use rustty::ui::Label;
    ///
    /// let mut label = Label::new(20, 3);
    /// label.set_text("Centered");
    /// label.align_text(HorizontalAlign::Middle, VerticalAlign::Middle, (0,0));
    /// ```
    ///
    pub fn align_text(&mut self, halign: HorizontalAlign, valign: VerticalAlign,
                    margin: (usize, usize)) {
        self.t_halign = halign.clone();
        self.t_valign = valign.clone();
        self.t_margin = margin;

        self.x = self.frame.halign_line(&self.text, halign, margin.0);
        self.y = self.frame.valign_line(&self.text, valign, margin.1);
    }

    /// Set the text of the widget to the passed `&str` or `String`. If the
    /// widget does not have enough room to display the new text, the widget
    /// is resized **horizontally** to accomodate the new size
    ///
    /// # Examples
    ///
    /// ```
    /// use rustty::HasSize;
    /// use rustty::ui::core::Widget;
    /// use rustty::ui::Label;
    ///
    /// let mut label1 = Label::new(20, 3);
    /// label1.set_text("Initial text");
    ///
    /// let mut label2 = Label::from_str("too small");  // label is size (9x1)
    /// label2.set_text("This is too big");             // label is size (15x1)
    /// assert_eq!(label2.frame().size(), (15, 1));
    ///
    /// let mut label3 = Label::new(4, 2);              // label is size (4x2)
    /// label3.set_text("Too big to fit!");             // label is size (8x2)
    /// assert_eq!(label3.frame().size(), (8, 2));
    /// ```
    ///
    pub fn set_text<S: Into<String>>(&mut self, new_str: S) {
        let new_str = new_str.into();
        self.text = new_str;
        let (framex, framey) = self.frame.size();
        if self.text.len() > (framex * framey) {
            // Extend widget horizontally such that it can accomodate the new
            // text size, algorithm to determine new horizontal size is:
            //      L   : length of new text
            //      CxR : dimensions of widget
            //      ciel(L - C * R) / R + C
            let new_x = (self.text.len() - framex * framey) as f32 / framey as f32;
            let new_x = new_x.ceil() as usize + framex;
            self.frame.resize((new_x, framey));
        }
    }
}

impl Widget for Label {
    fn draw(&mut self, parent: &mut CellAccessor) {
        self.frame.printline(self.x, self.y, &self.text);
        self.frame.draw_into(parent);
    }

    fn pack(&mut self, parent: &HasSize, halign: HorizontalAlign, valign: VerticalAlign,
                margin: (usize, usize)) {
        self.frame.align(parent, halign, valign, margin);
        self.x = self.frame.halign_line(&self.text, self.t_halign.clone(), margin.0);
        self.y = self.frame.valign_line(&self.text, self.t_valign.clone(), margin.1);
    }

    fn draw_box(&mut self) {
        self.frame.draw_box();
    }

    fn resize(&mut self, new_size: Size) {
        self.frame.resize(new_size);
    }

    fn frame(&self) -> &Frame {
        &self.frame
    }

    fn frame_mut(&mut self) -> &mut Frame {
        &mut self.frame
    }
}
<commit_msg>Fix label pack overwriting text margins<commit_after>use core::position::{Size, HasSize};
use core::cellbuffer::CellAccessor;

use ui::core::{
    Alignable,
    HorizontalAlign,
    VerticalAlign,
    Widget,
    Frame,
    Painter
};

/// Display text to widgets
///
/// # Examples
///
/// ```
/// use rustty::ui::core::{VerticalAlign, HorizontalAlign, Widget};
/// use rustty::ui::{Dialog, Label};
///
/// let mut maindlg = Dialog::new(60, 10);
///
/// let mut label = Label::from_str("Hi, this is an example!");
/// label.pack(&maindlg, HorizontalAlign::Middle, VerticalAlign::Middle, (0,0));
///
/// maindlg.add_label(label);
/// maindlg.draw_box();
/// ```
///
pub struct Label {
    frame: Frame,
    text: String,
    x: usize,
    y: usize,
    t_halign: HorizontalAlign,
    t_valign: VerticalAlign,
    t_margin: (usize, usize)
}

impl Label {
    /// Construct a new Label widget `cols` wide by `rols` high. Initial text is empty
    /// and left aligned
    ///
    /// # Examples
    ///
    /// ```
    /// use rustty::ui::Label;
    ///
    /// let mut label = Label::new(60, 10);
    /// ```
    ///
    pub fn new(cols: usize, rows: usize) -> Label {
        Label {
            frame: Frame::new(cols, rows),
            text: "".to_string(),
            x: 0,
            y: 0,
            t_halign: HorizontalAlign::Left,
            t_valign: VerticalAlign::Middle,
            t_margin: (0, 0)
        }
    }

    /// Construct a new label widget from an existing string *s*. *s* can either be a
    /// `&str` or `String` , and a label will be constructed that is the size of the
    /// length of characters in *s*. Text is left aligned by default
    ///
    /// # Examples
    ///
    /// ```
    /// use rustty::ui::Label;
    ///
    /// let mut label1 = Label::from_str("This is a label");    // label is size (15x1)
    ///
    /// let s = "Here's another label".to_string();
    /// let mut label2 = Label::from_str(s);                    // label is size (20x1)
    /// ```
    ///
    pub fn from_str<S: Into<String>>(s: S) -> Label {
        let s = s.into();
        Label {
            frame: Frame::new(s.len(), 1),
            text: s.into(),
            x: 0,
            y: 0,
            t_halign: HorizontalAlign::Left,
            t_valign: VerticalAlign::Middle,
            t_margin: (1, 1)
        }
    }

    /// Specify a custom alignment for the text within the widget
    ///
    /// # Examples
    ///
    /// ```
    /// use rustty::ui::core::{HorizontalAlign, VerticalAlign};
    /// use rustty::ui::Label;
    ///
    /// let mut label = Label::new(20, 3);
    /// label.set_text("Centered");
    /// label.align_text(HorizontalAlign::Middle, VerticalAlign::Middle, (0,0));
    /// ```
    ///
    pub fn align_text(&mut self, halign: HorizontalAlign, valign: VerticalAlign,
                    margin: (usize, usize)) {
        self.t_halign = halign.clone();
        self.t_valign = valign.clone();
        self.t_margin = margin;

        self.x = self.frame.halign_line(&self.text, halign, margin.0);
        self.y = self.frame.valign_line(&self.text, valign, margin.1);
    }

    /// Set the text of the widget to the passed `&str` or `String`. If the
    /// widget does not have enough room to display the new text, the widget
    /// is resized **horizontally** to accomodate the new size
    ///
    /// # Examples
    ///
    /// ```
    /// use rustty::HasSize;
    /// use rustty::ui::core::Widget;
    /// use rustty::ui::Label;
    ///
    /// let mut label1 = Label::new(20, 3);
    /// label1.set_text("Initial text");
    ///
    /// let mut label2 = Label::from_str("too small");  // label is size (9x1)
    /// label2.set_text("This is too big");             // label is size (15x1)
    /// assert_eq!(label2.frame().size(), (15, 1));
    ///
    /// let mut label3 = Label::new(4, 2);              // label is size (4x2)
    /// label3.set_text("Too big to fit!");             // label is size (8x2)
    /// assert_eq!(label3.frame().size(), (8, 2));
    /// ```
    ///
    pub fn set_text<S: Into<String>>(&mut self, new_str: S) {
        let new_str = new_str.into();
        self.text = new_str;
        let (framex, framey) = self.frame.size();
        if self.text.len() > (framex * framey) {
            // Extend widget horizontally such that it can accomodate the new
            // text size, algorithm to determine new horizontal size is:
            //      L   : length of new text
            //      CxR : dimensions of widget
            //      ciel(L - C * R) / R + C
            let new_x = (self.text.len() - framex * framey) as f32 / framey as f32;
            let new_x = new_x.ceil() as usize + framex;
            self.frame.resize((new_x, framey));
        }
    }
}

impl Widget for Label {
    fn draw(&mut self, parent: &mut CellAccessor) {
        self.frame.printline(self.x, self.y, &self.text);
        self.frame.draw_into(parent);
    }

    fn pack(&mut self, parent: &HasSize, halign: HorizontalAlign, valign: VerticalAlign,
                margin: (usize, usize)) {
        self.frame.align(parent, halign, valign, margin);
    }

    fn draw_box(&mut self) {
        self.frame.draw_box();
    }

    fn resize(&mut self, new_size: Size) {
        self.frame.resize(new_size);
    }

    fn frame(&self) -> &Frame {
        &self.frame
    }

    fn frame_mut(&mut self) -> &mut Frame {
        &mut self.frame
    }
}
<|endoftext|>


<commit_before>#[derive(Clone, Debug)]
pub struct URIBase {
    base_uri: String,
    port: u16
}

impl Default for URIBase {
    fn default() -> URIBase {
        URIBase {
            base_uri: "localhost".to_string(),
            port: 10041
        }
    }
}

impl URIBase {
    ///
    /// Create URIBase struct
    ///
    /// Default values are:
    ///
    ///   base_uri: "localhost"
    ///
    ///   port: 10041
    ///
    pub fn new() -> URIBase {
        let default: URIBase = Default::default();
        default
    }

    /// Set base to replace default value with specified value
    pub fn base_uri(mut self, base_uri: String) -> URIBase {
        self.base_uri = base_uri;
        self
    }

    /// Set port number to replace default value with specified value
    pub fn port(mut self, port: u16) -> URIBase {
        self.port = port;
        self
    }

    /// make base uri
    /// Default value is: "localhost:10041"
    pub fn build(self) -> String {
        format!("http://{}:{}", self.base_uri, self.port)
    }
}

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

    #[test]
    fn construct_uri_default() {
        let uri_base = URIBase::new().build();
        assert_eq!("http://localhost:10041", uri_base)
    }

    #[test]
    fn buikld_only_uri_base() {
        let uri_base = URIBase::new()
            .base_uri("127.0.0.1".to_string()).build();
        assert_eq!("http://127.0.0.1:10041", uri_base);
    }

    #[test]
    fn build_only_port() {
        let uri_base = URIBase::new().port(10042).build();
        assert_eq!("http://localhost:10042", uri_base);
    }

    #[test]
    fn uri_with_builder() {
        let uri_base = URIBase::new()
            .base_uri("127.0.1.1".to_string())
            .port(10043)
            .build();
        assert_eq!("http://127.0.1.1:10043", uri_base)
    }

}
<commit_msg>Update rustdoc<commit_after>#[derive(Clone, Debug)]
pub struct URIBase {
    base_uri: String,
    port: u16
}

impl Default for URIBase {
    fn default() -> URIBase {
        URIBase {
            base_uri: "localhost".to_string(),
            port: 10041
        }
    }
}

impl URIBase {
    ///
    /// Create URIBase struct.
    ///
    /// Default values are:
    ///
    ///   base_uri: "localhost"
    ///
    ///   port: 10041
    ///
    pub fn new() -> URIBase {
        let default: URIBase = Default::default();
        default
    }

    /// Set base to replace default value with specified value.
    pub fn base_uri(mut self, base_uri: String) -> URIBase {
        self.base_uri = base_uri;
        self
    }

    /// Set port number to replace default value with specified value.
    pub fn port(mut self, port: u16) -> URIBase {
        self.port = port;
        self
    }

    /// Build and get base uri.
    pub fn build(self) -> String {
        format!("http://{}:{}", self.base_uri, self.port)
    }
}

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

    #[test]
    fn construct_uri_default() {
        let uri_base = URIBase::new().build();
        assert_eq!("http://localhost:10041", uri_base)
    }

    #[test]
    fn buikld_only_uri_base() {
        let uri_base = URIBase::new()
            .base_uri("127.0.0.1".to_string()).build();
        assert_eq!("http://127.0.0.1:10041", uri_base);
    }

    #[test]
    fn build_only_port() {
        let uri_base = URIBase::new().port(10042).build();
        assert_eq!("http://localhost:10042", uri_base);
    }

    #[test]
    fn uri_with_builder() {
        let uri_base = URIBase::new()
            .base_uri("127.0.1.1".to_string())
            .port(10043)
            .build();
        assert_eq!("http://127.0.1.1:10043", uri_base)
    }

}
<|endoftext|>


<commit_before>//! Details of the `request` section of the procedural macro.

use proc_macro2::TokenStream;
use quote::{quote, quote_spanned, ToTokens};
use syn::{spanned::Spanned, Field, Ident};

use crate::api::{
    attribute::{Meta, MetaNameValue},
    strip_serde_attrs,
};

/// The result of processing the `request` section of the macro.
pub struct Request {
    /// The fields of the request.
    fields: Vec<RequestField>,
}

impl Request {
    /// Produces code to add necessary HTTP headers to an `http::Request`.
    pub fn add_headers_to_request(&self) -> TokenStream {
        let append_stmts = self.header_fields().map(|request_field| {
            let (field, header_name) = match request_field {
                RequestField::Header(field, header_name) => (field, header_name),
                _ => panic!("expected request field to be header variant"),
            };

            let field_name = &field.ident;

            quote! {
                headers.append(
                    ruma_api::exports::http::header::#header_name,
                    ruma_api::exports::http::header::HeaderValue::from_str(request.#field_name.as_ref())
                        .expect("failed to convert value into HeaderValue"),
                );
            }
        });

        quote! {
            #(#append_stmts)*
        }
    }

    /// Whether or not this request has any data in the HTTP body.
    pub fn has_body_fields(&self) -> bool {
        self.fields.iter().any(|field| field.is_body())
    }

    /// Whether or not this request has any data in HTTP headers.
    pub fn has_header_fields(&self) -> bool {
        self.fields.iter().any(|field| field.is_header())
    }

    /// Whether or not this request has any data in the URL path.
    pub fn has_path_fields(&self) -> bool {
        self.fields.iter().any(|field| field.is_path())
    }

    /// Whether or not this request has any data in the query string.
    pub fn has_query_fields(&self) -> bool {
        self.fields.iter().any(|field| field.is_query())
    }

    /// Produces an iterator over all the header fields.
    pub fn header_fields(&self) -> impl Iterator<Item = &RequestField> {
        self.fields.iter().filter(|field| field.is_header())
    }

    /// Gets the number of path fields.
    pub fn path_field_count(&self) -> usize {
        self.fields.iter().filter(|field| field.is_path()).count()
    }

    /// Returns the body field.
    pub fn newtype_body_field(&self) -> Option<&Field> {
        for request_field in self.fields.iter() {
            match *request_field {
                RequestField::NewtypeBody(ref field) => {
                    return Some(field);
                }
                _ => continue,
            }
        }

        None
    }

    /// Produces code for a struct initializer for body fields on a variable named `request`.
    pub fn request_body_init_fields(&self) -> TokenStream {
        self.struct_init_fields(RequestFieldKind::Body, quote!(request))
    }

    /// Produces code for a struct initializer for path fields on a variable named `request`.
    pub fn request_path_init_fields(&self) -> TokenStream {
        self.struct_init_fields(RequestFieldKind::Path, quote!(request))
    }

    /// Produces code for a struct initializer for query string fields on a variable named `request`.
    pub fn request_query_init_fields(&self) -> TokenStream {
        self.struct_init_fields(RequestFieldKind::Query, quote!(request))
    }

    /// Produces code for a struct initializer for the given field kind to be accessed through the
    /// given variable name.
    fn struct_init_fields(
        &self,
        request_field_kind: RequestFieldKind,
        src: TokenStream,
    ) -> TokenStream {
        let fields = self.fields.iter().filter_map(|f| {
            f.field_of_kind(request_field_kind).map(|field| {
                let field_name = field
                    .ident
                    .as_ref()
                    .expect("expected field to have an identifier");
                let span = field.span();

                quote_spanned! {span=>
                    #field_name: #src.#field_name
                }
            })
        });

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

impl From<Vec<Field>> for Request {
    fn from(fields: Vec<Field>) -> Self {
        let fields: Vec<_> = fields.into_iter().map(|mut field| {
            let mut field_kind = None;
            let mut header = None;

            field.attrs.retain(|attr| {
                let meta = match Meta::from_attribute(attr) {
                    Some(m) => m,
                    None => return true,
                };

                match meta {
                    Meta::Word(ident) => {
                        assert!(
                            field_kind.is_none(),
                            "ruma_api! field kind can only be set once per field"
                        );

                        field_kind = Some(match &ident.to_string()[..] {
                            "body" => RequestFieldKind::NewtypeBody,
                            "path" => RequestFieldKind::Path,
                            "query" => RequestFieldKind::Query,
                            _ => panic!("ruma_api! single-word attribute on requests must be: body, path, or query"),
                        });
                    }
                    Meta::NameValue(MetaNameValue { name, value }) => {
                        assert!(
                            name == "header",
                            "ruma_api! name/value pair attribute on requests must be: header"
                        );
                        assert!(
                            field_kind.is_none(),
                            "ruma_api! field kind can only be set once per field"
                        );

                        header = Some(value);
                        field_kind = Some(RequestFieldKind::Header);
                    }
                }

                false
            });

            RequestField::new(field_kind.unwrap_or(RequestFieldKind::Body), field, header)
        }).collect();

        let num_body_fields = fields.iter().filter(|f| f.is_body()).count();
        let num_newtype_body_fields = fields.iter().filter(|f| f.is_newtype_body()).count();
        assert!(
            num_newtype_body_fields <= 1,
            "ruma_api! request can only have one newtype body field"
        );
        if num_newtype_body_fields == 1 {
            assert!(
                num_body_fields == 0,
                "ruma_api! request can't have both regular body fields and a newtype body field"
            );
        }

        Self { fields }
    }
}

impl ToTokens for Request {
    fn to_tokens(&self, tokens: &mut TokenStream) {
        let request_struct_header = quote! {
            #[derive(Debug, Clone)]
            pub struct Request
        };

        let request_struct_body = if self.fields.is_empty() {
            quote!(;)
        } else {
            let fields = self
                .fields
                .iter()
                .map(|request_field| strip_serde_attrs(request_field.field()));

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

        let request_body_struct = if let Some(newtype_body_field) = self.newtype_body_field() {
            let field = newtype_body_field.clone();
            let ty = &field.ty;
            let span = field.span();

            quote_spanned! {span=>
                /// Data in the request body.
                #[derive(Debug, ruma_api::exports::serde::Serialize)]
                struct RequestBody(#ty);
            }
        } else if self.has_body_fields() {
            let fields = self.fields.iter().filter_map(RequestField::as_body_field);

            quote! {
                /// Data in the request body.
                #[derive(Debug, ruma_api::exports::serde::Serialize)]
                struct RequestBody {
                    #(#fields),*
                }
            }
        } else {
            TokenStream::new()
        };

        let request_path_struct = if self.has_path_fields() {
            let fields = self.fields.iter().filter_map(RequestField::as_path_field);

            quote! {
                /// Data in the request path.
                #[derive(
                    Debug,
                    ruma_api::exports::serde::Deserialize,
                    ruma_api::exports::serde::Serialize,
                )]
                struct RequestPath {
                    #(#fields),*
                }
            }
        } else {
            TokenStream::new()
        };

        let request_query_struct = if self.has_query_fields() {
            let fields = self.fields.iter().filter_map(RequestField::as_query_field);

            quote! {
                /// Data in the request's query string.
                #[derive(
                    Debug,
                    ruma_api::exports::serde::Deserialize,
                    ruma_api::exports::serde::Serialize,
                )]
                struct RequestQuery {
                    #(#fields),*
                }
            }
        } else {
            TokenStream::new()
        };

        let request = quote! {
            #request_struct_header
            #request_struct_body
            #request_body_struct
            #request_path_struct
            #request_query_struct
        };

        request.to_tokens(tokens);
    }
}

/// The types of fields that a request can have.
pub enum RequestField {
    /// JSON data in the body of the request.
    Body(Field),
    /// Data in an HTTP header.
    Header(Field, Ident),
    /// A specific data type in the body of the request.
    NewtypeBody(Field),
    /// Data that appears in the URL path.
    Path(Field),
    /// Data that appears in the query string.
    Query(Field),
}

impl RequestField {
    /// Creates a new `RequestField`.
    fn new(kind: RequestFieldKind, field: Field, header: Option<Ident>) -> Self {
        match kind {
            RequestFieldKind::Body => RequestField::Body(field),
            RequestFieldKind::Header => {
                RequestField::Header(field, header.expect("missing header name"))
            }
            RequestFieldKind::NewtypeBody => RequestField::NewtypeBody(field),
            RequestFieldKind::Path => RequestField::Path(field),
            RequestFieldKind::Query => RequestField::Query(field),
        }
    }

    /// Gets the kind of the request field.
    fn kind(&self) -> RequestFieldKind {
        match *self {
            RequestField::Body(..) => RequestFieldKind::Body,
            RequestField::Header(..) => RequestFieldKind::Header,
            RequestField::NewtypeBody(..) => RequestFieldKind::NewtypeBody,
            RequestField::Path(..) => RequestFieldKind::Path,
            RequestField::Query(..) => RequestFieldKind::Query,
        }
    }

    /// Whether or not this request field is a body kind.
    fn is_body(&self) -> bool {
        self.kind() == RequestFieldKind::Body
    }

    /// Whether or not this request field is a header kind.
    fn is_header(&self) -> bool {
        self.kind() == RequestFieldKind::Header
    }

    /// Whether or not this request field is a newtype body kind.
    fn is_newtype_body(&self) -> bool {
        self.kind() == RequestFieldKind::NewtypeBody
    }

    /// Whether or not this request field is a path kind.
    fn is_path(&self) -> bool {
        self.kind() == RequestFieldKind::Path
    }

    /// Whether or not this request field is a query string kind.
    fn is_query(&self) -> bool {
        self.kind() == RequestFieldKind::Query
    }

    /// Return the contained field if this request field is a body kind.
    fn as_body_field(&self) -> Option<&Field> {
        if let RequestField::Body(field) = self {
            Some(field)
        } else {
            None
        }
    }

    /// Return the contained field if this request field is a path kind.
    fn as_path_field(&self) -> Option<&Field> {
        if let RequestField::Path(field) = self {
            Some(field)
        } else {
            None
        }
    }

    /// Return the contained field if this request field is a query kind.
    fn as_query_field(&self) -> Option<&Field> {
        if let RequestField::Query(field) = self {
            Some(field)
        } else {
            None
        }
    }

    /// Gets the inner `Field` value.
    fn field(&self) -> &Field {
        match *self {
            RequestField::Body(ref field)
            | RequestField::Header(ref field, _)
            | RequestField::NewtypeBody(ref field)
            | RequestField::Path(ref field)
            | RequestField::Query(ref field) => field,
        }
    }

    /// Gets the inner `Field` value if it's of the provided kind.
    fn field_of_kind(&self, kind: RequestFieldKind) -> Option<&Field> {
        if self.kind() == kind {
            Some(self.field())
        } else {
            None
        }
    }
}

/// The types of fields that a request can have, without their values.
#[derive(Clone, Copy, PartialEq, Eq)]
enum RequestFieldKind {
    /// See the similarly named variant of `RequestField`.
    Body,
    /// See the similarly named variant of `RequestField`.
    Header,
    /// See the similarly named variant of `RequestField`.
    NewtypeBody,
    /// See the similarly named variant of `RequestField`.
    Path,
    /// See the similarly named variant of `RequestField`.
    Query,
}
<commit_msg>ruma_api_macros: Simplify RequestField::as_* methods<commit_after>//! Details of the `request` section of the procedural macro.

use proc_macro2::TokenStream;
use quote::{quote, quote_spanned, ToTokens};
use syn::{spanned::Spanned, Field, Ident};

use crate::api::{
    attribute::{Meta, MetaNameValue},
    strip_serde_attrs,
};

/// The result of processing the `request` section of the macro.
pub struct Request {
    /// The fields of the request.
    fields: Vec<RequestField>,
}

impl Request {
    /// Produces code to add necessary HTTP headers to an `http::Request`.
    pub fn add_headers_to_request(&self) -> TokenStream {
        let append_stmts = self.header_fields().map(|request_field| {
            let (field, header_name) = match request_field {
                RequestField::Header(field, header_name) => (field, header_name),
                _ => panic!("expected request field to be header variant"),
            };

            let field_name = &field.ident;

            quote! {
                headers.append(
                    ruma_api::exports::http::header::#header_name,
                    ruma_api::exports::http::header::HeaderValue::from_str(request.#field_name.as_ref())
                        .expect("failed to convert value into HeaderValue"),
                );
            }
        });

        quote! {
            #(#append_stmts)*
        }
    }

    /// Whether or not this request has any data in the HTTP body.
    pub fn has_body_fields(&self) -> bool {
        self.fields.iter().any(|field| field.is_body())
    }

    /// Whether or not this request has any data in HTTP headers.
    pub fn has_header_fields(&self) -> bool {
        self.fields.iter().any(|field| field.is_header())
    }

    /// Whether or not this request has any data in the URL path.
    pub fn has_path_fields(&self) -> bool {
        self.fields.iter().any(|field| field.is_path())
    }

    /// Whether or not this request has any data in the query string.
    pub fn has_query_fields(&self) -> bool {
        self.fields.iter().any(|field| field.is_query())
    }

    /// Produces an iterator over all the header fields.
    pub fn header_fields(&self) -> impl Iterator<Item = &RequestField> {
        self.fields.iter().filter(|field| field.is_header())
    }

    /// Gets the number of path fields.
    pub fn path_field_count(&self) -> usize {
        self.fields.iter().filter(|field| field.is_path()).count()
    }

    /// Returns the body field.
    pub fn newtype_body_field(&self) -> Option<&Field> {
        for request_field in self.fields.iter() {
            match *request_field {
                RequestField::NewtypeBody(ref field) => {
                    return Some(field);
                }
                _ => continue,
            }
        }

        None
    }

    /// Produces code for a struct initializer for body fields on a variable named `request`.
    pub fn request_body_init_fields(&self) -> TokenStream {
        self.struct_init_fields(RequestFieldKind::Body, quote!(request))
    }

    /// Produces code for a struct initializer for path fields on a variable named `request`.
    pub fn request_path_init_fields(&self) -> TokenStream {
        self.struct_init_fields(RequestFieldKind::Path, quote!(request))
    }

    /// Produces code for a struct initializer for query string fields on a variable named `request`.
    pub fn request_query_init_fields(&self) -> TokenStream {
        self.struct_init_fields(RequestFieldKind::Query, quote!(request))
    }

    /// Produces code for a struct initializer for the given field kind to be accessed through the
    /// given variable name.
    fn struct_init_fields(
        &self,
        request_field_kind: RequestFieldKind,
        src: TokenStream,
    ) -> TokenStream {
        let fields = self.fields.iter().filter_map(|f| {
            f.field_of_kind(request_field_kind).map(|field| {
                let field_name = field
                    .ident
                    .as_ref()
                    .expect("expected field to have an identifier");
                let span = field.span();

                quote_spanned! {span=>
                    #field_name: #src.#field_name
                }
            })
        });

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

impl From<Vec<Field>> for Request {
    fn from(fields: Vec<Field>) -> Self {
        let fields: Vec<_> = fields.into_iter().map(|mut field| {
            let mut field_kind = None;
            let mut header = None;

            field.attrs.retain(|attr| {
                let meta = match Meta::from_attribute(attr) {
                    Some(m) => m,
                    None => return true,
                };

                match meta {
                    Meta::Word(ident) => {
                        assert!(
                            field_kind.is_none(),
                            "ruma_api! field kind can only be set once per field"
                        );

                        field_kind = Some(match &ident.to_string()[..] {
                            "body" => RequestFieldKind::NewtypeBody,
                            "path" => RequestFieldKind::Path,
                            "query" => RequestFieldKind::Query,
                            _ => panic!("ruma_api! single-word attribute on requests must be: body, path, or query"),
                        });
                    }
                    Meta::NameValue(MetaNameValue { name, value }) => {
                        assert!(
                            name == "header",
                            "ruma_api! name/value pair attribute on requests must be: header"
                        );
                        assert!(
                            field_kind.is_none(),
                            "ruma_api! field kind can only be set once per field"
                        );

                        header = Some(value);
                        field_kind = Some(RequestFieldKind::Header);
                    }
                }

                false
            });

            RequestField::new(field_kind.unwrap_or(RequestFieldKind::Body), field, header)
        }).collect();

        let num_body_fields = fields.iter().filter(|f| f.is_body()).count();
        let num_newtype_body_fields = fields.iter().filter(|f| f.is_newtype_body()).count();
        assert!(
            num_newtype_body_fields <= 1,
            "ruma_api! request can only have one newtype body field"
        );
        if num_newtype_body_fields == 1 {
            assert!(
                num_body_fields == 0,
                "ruma_api! request can't have both regular body fields and a newtype body field"
            );
        }

        Self { fields }
    }
}

impl ToTokens for Request {
    fn to_tokens(&self, tokens: &mut TokenStream) {
        let request_struct_header = quote! {
            #[derive(Debug, Clone)]
            pub struct Request
        };

        let request_struct_body = if self.fields.is_empty() {
            quote!(;)
        } else {
            let fields = self
                .fields
                .iter()
                .map(|request_field| strip_serde_attrs(request_field.field()));

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

        let request_body_struct = if let Some(newtype_body_field) = self.newtype_body_field() {
            let field = newtype_body_field.clone();
            let ty = &field.ty;
            let span = field.span();

            quote_spanned! {span=>
                /// Data in the request body.
                #[derive(Debug, ruma_api::exports::serde::Serialize)]
                struct RequestBody(#ty);
            }
        } else if self.has_body_fields() {
            let fields = self.fields.iter().filter_map(RequestField::as_body_field);

            quote! {
                /// Data in the request body.
                #[derive(Debug, ruma_api::exports::serde::Serialize)]
                struct RequestBody {
                    #(#fields),*
                }
            }
        } else {
            TokenStream::new()
        };

        let request_path_struct = if self.has_path_fields() {
            let fields = self.fields.iter().filter_map(RequestField::as_path_field);

            quote! {
                /// Data in the request path.
                #[derive(
                    Debug,
                    ruma_api::exports::serde::Deserialize,
                    ruma_api::exports::serde::Serialize,
                )]
                struct RequestPath {
                    #(#fields),*
                }
            }
        } else {
            TokenStream::new()
        };

        let request_query_struct = if self.has_query_fields() {
            let fields = self.fields.iter().filter_map(RequestField::as_query_field);

            quote! {
                /// Data in the request's query string.
                #[derive(
                    Debug,
                    ruma_api::exports::serde::Deserialize,
                    ruma_api::exports::serde::Serialize,
                )]
                struct RequestQuery {
                    #(#fields),*
                }
            }
        } else {
            TokenStream::new()
        };

        let request = quote! {
            #request_struct_header
            #request_struct_body
            #request_body_struct
            #request_path_struct
            #request_query_struct
        };

        request.to_tokens(tokens);
    }
}

/// The types of fields that a request can have.
pub enum RequestField {
    /// JSON data in the body of the request.
    Body(Field),
    /// Data in an HTTP header.
    Header(Field, Ident),
    /// A specific data type in the body of the request.
    NewtypeBody(Field),
    /// Data that appears in the URL path.
    Path(Field),
    /// Data that appears in the query string.
    Query(Field),
}

impl RequestField {
    /// Creates a new `RequestField`.
    fn new(kind: RequestFieldKind, field: Field, header: Option<Ident>) -> Self {
        match kind {
            RequestFieldKind::Body => RequestField::Body(field),
            RequestFieldKind::Header => {
                RequestField::Header(field, header.expect("missing header name"))
            }
            RequestFieldKind::NewtypeBody => RequestField::NewtypeBody(field),
            RequestFieldKind::Path => RequestField::Path(field),
            RequestFieldKind::Query => RequestField::Query(field),
        }
    }

    /// Gets the kind of the request field.
    fn kind(&self) -> RequestFieldKind {
        match *self {
            RequestField::Body(..) => RequestFieldKind::Body,
            RequestField::Header(..) => RequestFieldKind::Header,
            RequestField::NewtypeBody(..) => RequestFieldKind::NewtypeBody,
            RequestField::Path(..) => RequestFieldKind::Path,
            RequestField::Query(..) => RequestFieldKind::Query,
        }
    }

    /// Whether or not this request field is a body kind.
    fn is_body(&self) -> bool {
        self.kind() == RequestFieldKind::Body
    }

    /// Whether or not this request field is a header kind.
    fn is_header(&self) -> bool {
        self.kind() == RequestFieldKind::Header
    }

    /// Whether or not this request field is a newtype body kind.
    fn is_newtype_body(&self) -> bool {
        self.kind() == RequestFieldKind::NewtypeBody
    }

    /// Whether or not this request field is a path kind.
    fn is_path(&self) -> bool {
        self.kind() == RequestFieldKind::Path
    }

    /// Whether or not this request field is a query string kind.
    fn is_query(&self) -> bool {
        self.kind() == RequestFieldKind::Query
    }

    /// Return the contained field if this request field is a body kind.
    fn as_body_field(&self) -> Option<&Field> {
        self.field_of_kind(RequestFieldKind::Body)
    }

    /// Return the contained field if this request field is a path kind.
    fn as_path_field(&self) -> Option<&Field> {
        self.field_of_kind(RequestFieldKind::Path)
    }

    /// Return the contained field if this request field is a query kind.
    fn as_query_field(&self) -> Option<&Field> {
        self.field_of_kind(RequestFieldKind::Query)
    }

    /// Gets the inner `Field` value.
    fn field(&self) -> &Field {
        match *self {
            RequestField::Body(ref field)
            | RequestField::Header(ref field, _)
            | RequestField::NewtypeBody(ref field)
            | RequestField::Path(ref field)
            | RequestField::Query(ref field) => field,
        }
    }

    /// Gets the inner `Field` value if it's of the provided kind.
    fn field_of_kind(&self, kind: RequestFieldKind) -> Option<&Field> {
        if self.kind() == kind {
            Some(self.field())
        } else {
            None
        }
    }
}

/// The types of fields that a request can have, without their values.
#[derive(Clone, Copy, PartialEq, Eq)]
enum RequestFieldKind {
    /// See the similarly named variant of `RequestField`.
    Body,
    /// See the similarly named variant of `RequestField`.
    Header,
    /// See the similarly named variant of `RequestField`.
    NewtypeBody,
    /// See the similarly named variant of `RequestField`.
    Path,
    /// See the similarly named variant of `RequestField`.
    Query,
}
<|endoftext|>


<commit_before>//! Wget module

use std;

#[inline(always)]
fn find_file_name(text: &String) -> Option<String> {
    let left: usize = text.rfind("-O \"").unwrap_or(0);
    let right: usize = text.rfind("\" -c").unwrap_or(0);

    if left == right { return None; }
    let left: usize = left + 4;
    Some(text[left..right].to_string())
}

#[inline(always)]
pub fn is_applicable(text: &String) -> Option<String> {
    if !text.starts_with("wget") { return None; }
    find_file_name(text)
}

pub fn handler(text: &String, file_name: String) {
    println!(">>>wget {}", &file_name);

    let cmd = format!("cd E:/Downloads; {}", text);
    if std::thread::Builder::new().name(file_name).spawn(move || {
        let output = std::process::Command::new("powershell").arg("-Command").arg(cmd).output().unwrap();
        if !output.status.success() {
            println!("[{}] Failed to wget:\n{}", std::thread::current().name().unwrap_or("UNKNOWN"), String::from_utf8_lossy(&output.stdout));
        }
        else {
            println!("[{}] Successfully downloaded", std::thread::current().name().unwrap_or("UNKNOWN"));
        }
    }).is_err() {
        println!("Failed to run new thread with wget");
    }
    return;
}
<commit_msg>clipboard_monitor: simplify downloader<commit_after>//! Wget module

use std;

#[inline(always)]
fn find_file_name(text: &String) -> Option<String> {
    let left: usize = text.rfind("-O \"").unwrap_or(0);
    let right: usize = text.rfind("\" -c").unwrap_or(0);

    if left == right { return None; }
    let left: usize = left + 4;
    Some(text[left..right].to_string())
}

#[inline(always)]
pub fn is_applicable(text: &String) -> Option<String> {
    if !text.starts_with("wget") { return None; }
    find_file_name(text)
}

#[inline(always)]
pub fn handler(text: &String, file_name: String) {
    println!(">>>wget {}", &file_name);

    let cmd = format!("cd E:/Downloads; {}", text);
    if std::thread::Builder::new().name(file_name).spawn(move || {
        let status = std::process::Command::new("powershell").arg("-Command").arg(cmd).stdout(std::process::Stdio::null()).stderr(std::process::Stdio::null()).status().unwrap();
        if !status.success() {
            println!("[{}] Failed to wget", std::thread::current().name().unwrap_or("UNKNOWN"));
        }
        else {
            println!("[{}] Successfully downloaded", std::thread::current().name().unwrap_or("UNKNOWN"));
        }
    }).is_err() {
        println!("Failed to run new thread with wget");
    }
    return;
}
<|endoftext|>


<commit_before>pub fn pathmatch(pattern: &str, pathstring: &str) -> bool
{
    let mut pattern_chars = pattern.chars();
    let mut path_chars = pathstring.chars();
    loop {
        match pattern_chars.next() {
            None => return path_chars.next().is_none(),
            Some(pc) => {
                match pc {
                    '?' => return path_chars.next().is_some(),
                    _ => {
                        match path_chars.next() {
                            None => return false,
                            Some(sc) => if pc != sc { return false },
                        }
                    }
                }
            }
        }
    }
}

#[test]
fn pathmatch_test_anychar()
{
    assert!(pathmatch("?", "?"));
    assert!(pathmatch("?", "a"));
    assert!(pathmatch("??", "BC"));
    assert!(pathmatch("B?", "BC"));
    assert!(pathmatch("?C", "BC"));
    assert!(!pathmatch("?", ""));
    assert!(!pathmatch("D?", "BC"));
}

#[test]
fn pathmatch_test_exact_equality()
{
    assert!(pathmatch("", ""));
    assert!(pathmatch("a", "a"));
    assert!(pathmatch("BC", "BC"));
    assert!(!pathmatch("a", ""));
    assert!(!pathmatch("", "BC"));
}

<commit_msg>a bit more laconic use of matching<commit_after>pub fn pathmatch(pattern: &str, pathstring: &str) -> bool
{
    let mut pattern_chars = pattern.chars();
    let mut path_chars = pathstring.chars();
    loop {
        match pattern_chars.next() {
            None => return path_chars.next().is_none(),
            Some('?') => return path_chars.next().is_some(),
            Some(pc) => {
                match path_chars.next() {
                    None => return false,
                    Some(sc) => if pc != sc { return false },
                }
            }
        }
    }
}

#[test]
fn pathmatch_test_anychar()
{
    assert!(pathmatch("?", "?"));
    assert!(pathmatch("?", "a"));
    assert!(pathmatch("??", "BC"));
    assert!(pathmatch("B?", "BC"));
    assert!(pathmatch("?C", "BC"));
    assert!(!pathmatch("?", ""));
    assert!(!pathmatch("D?", "BC"));
}

#[test]
fn pathmatch_test_exact_equality()
{
    assert!(pathmatch("", ""));
    assert!(pathmatch("a", "a"));
    assert!(pathmatch("BC", "BC"));
    assert!(!pathmatch("a", ""));
    assert!(!pathmatch("", "BC"));
}

<|endoftext|>


<commit_before>extern crate mpi;

use mpi::traits::*;
use mpi::topology::Rank;

fn main() {
    let universe = mpi::initialize().unwrap();
    let world = universe.world();
    let size = world.size();
    let rank = world.rank();

    let next_rank = if rank + 1 < size { rank + 1 } else { 0 };
    let previous_rank = if rank - 1 >= 0 { rank - 1 } else { size - 1 };

    let (msg, status) = world.send_receive::<_, mpi::topology::Rank>(&rank, previous_rank, next_rank);
    assert!(msg.is_some());
    let msg = msg.unwrap();
    println!("Process {} got message {}.\nStatus is: {:?}", rank, msg, status);
    world.barrier();
    assert_eq!(msg, next_rank);

    if rank > 0 {
        let msg = vec![rank, rank + 1, rank - 1];
        world.process_at_rank(0).send(&msg[..]);
    } else {
        for _ in (1..size) {
            let (msg, status) = world.receive_vec::<Rank>();
            assert!(msg.is_some());
            let msg = msg.unwrap();
            println!("Process {} got long message {:?}.\nStatus is: {:?}", rank, msg, status);

            let x = status.source_rank();
            let v = vec![x, x + 1, x - 1];
            assert_eq!(v, msg);
        }
    }

    let mut x = rank;
    world.send_receive_replace_into(&mut x, next_rank, previous_rank);
    assert_eq!(x, previous_rank);
}
<commit_msg>Fix send_receive example.<commit_after>extern crate mpi;

use mpi::traits::*;
use mpi::topology::Rank;

fn main() {
    let universe = mpi::initialize().unwrap();
    let world = universe.world();
    let size = world.size();
    let rank = world.rank();

    let next_rank = if rank + 1 < size { rank + 1 } else { 0 };
    let previous_rank = if rank - 1 >= 0 { rank - 1 } else { size - 1 };

    let (msg, status) = world.send_receive::<_, mpi::topology::Rank>(&rank, previous_rank, next_rank);
    assert!(msg.is_some());
    let msg = msg.unwrap();
    println!("Process {} got message {}.\nStatus is: {:?}", rank, msg, status);
    world.barrier();
    assert_eq!(msg, next_rank);

    if rank > 0 {
        let msg = vec![rank, rank + 1, rank - 1];
        world.process_at_rank(0).send(&msg[..]);
    } else {
        for _ in (1..size) {
            let (msg, status) = world.receive_vec::<Rank>();
            assert!(msg.is_some());
            let msg = msg.unwrap();
            println!("Process {} got long message {:?}.\nStatus is: {:?}", rank, msg, status);

            let x = status.source_rank();
            let v = vec![x, x + 1, x - 1];
            assert_eq!(v, msg);
        }
    }
    world.barrier();

    let mut x = rank;
    world.send_receive_replace_into(&mut x, next_rank, previous_rank);
    assert_eq!(x, previous_rank);
}
<|endoftext|>